Skip to content

Commit 5770d59

Browse files
authored
Merge pull request #78427 from compnerd/internals
IRGen: special case VWT emission linkage computation
2 parents 3472312 + 59e7c1b commit 5770d59

File tree

5 files changed

+69
-36
lines changed

5 files changed

+69
-36
lines changed

include/swift/IRGen/Linking.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,8 @@ class LinkEntity {
16641664
/// Determine whether entity that represents a symbol is in DATA segment.
16651665
bool isData() const { return !isText(); }
16661666

1667+
bool isTypeKind() const { return isTypeKind(getKind()); }
1668+
16671669
bool isAlwaysSharedLinkage() const;
16681670
#undef LINKENTITY_GET_FIELD
16691671
#undef LINKENTITY_SET_FIELD

lib/IRGen/GenDecl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3909,6 +3909,34 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
39093909
auto var = createVariable(*this, link, definitionType,
39103910
entity.getAlignment(*this), DbgTy);
39113911

3912+
// @escaping () -> ()
3913+
// NOTE: we explicitly desugar the `Void` type for the return as the test
3914+
// suite makes assumptions that it can emit the value witness table without a
3915+
// standard library for the target. `Context.getVoidType()` will attempt to
3916+
// lookup the `Decl` before returning the canonical type. To workaround this
3917+
// dependency, we simply desugar the `Void` return type to `()`.
3918+
static CanType kAnyFunctionType =
3919+
FunctionType::get({}, Context.TheEmptyTupleType,
3920+
ASTExtInfo{})->getCanonicalType();
3921+
3922+
// Adjust the linkage for the well-known VWTs that are strongly defined
3923+
// in the runtime.
3924+
//
3925+
// We special case the "AnyFunctionType" here as this type is referened
3926+
// inside the standard library with the definition being in the runtime
3927+
// preventing the normal detection from identifying that this is module
3928+
// local.
3929+
if (getSwiftModule()->isStdlibModule())
3930+
if (entity.isTypeKind() &&
3931+
(IsWellKnownBuiltinOrStructralType(entity.getType()) ||
3932+
entity.getType() == kAnyFunctionType))
3933+
if (auto *GV = dyn_cast<llvm::GlobalValue>(var))
3934+
if (GV->hasDLLImportStorageClass())
3935+
ApplyIRLinkage({llvm::GlobalValue::ExternalLinkage,
3936+
llvm::GlobalValue::DefaultVisibility,
3937+
llvm::GlobalValue::DefaultStorageClass})
3938+
.to(GV);
3939+
39123940
// Install the concrete definition if we have one.
39133941
if (definition && definition.hasInit()) {
39143942
definition.getInit().installInGlobal(var);

lib/IRGen/IRGenModule.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,39 @@ llvm::Module *IRGenModule::getModule() const {
13621362
return ClangCodeGen->GetModule();
13631363
}
13641364

1365+
bool IRGenModule::IsWellKnownBuiltinOrStructralType(CanType T) const {
1366+
static const CanType kStructural[] = {
1367+
Context.TheEmptyTupleType, Context.TheNativeObjectType,
1368+
Context.TheBridgeObjectType, Context.TheRawPointerType,
1369+
Context.getAnyObjectType()
1370+
};
1371+
1372+
if (std::any_of(std::begin(kStructural), std::end(kStructural),
1373+
[T](const CanType &ST) { return T == ST; }))
1374+
return true;
1375+
1376+
if (auto IntTy = dyn_cast<BuiltinIntegerType>(T)) {
1377+
auto Width = IntTy->getWidth();
1378+
if (Width.isPointerWidth())
1379+
return true;
1380+
if (!Width.isFixedWidth())
1381+
return false;
1382+
switch (Width.getFixedWidth()) {
1383+
case 8:
1384+
case 16:
1385+
case 32:
1386+
case 64:
1387+
case 128:
1388+
case 256:
1389+
return true;
1390+
default:
1391+
break;
1392+
}
1393+
}
1394+
1395+
return false;
1396+
}
1397+
13651398
GeneratedModule IRGenModule::intoGeneratedModule() && {
13661399
return GeneratedModule{
13671400
std::move(LLVMContext),

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,8 @@ class IRGenModule {
11371137

11381138
ClassMetadataStrategy getClassMetadataStrategy(const ClassDecl *theClass);
11391139

1140+
bool IsWellKnownBuiltinOrStructralType(CanType type) const;
1141+
11401142
private:
11411143
TypeConverter &Types;
11421144
friend TypeConverter;

lib/IRGen/MetadataRequest.cpp

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3688,41 +3688,6 @@ namespace {
36883688
return nullptr;
36893689
}
36903690

3691-
bool hasVisibleValueWitnessTable(CanType t) const {
3692-
// Some builtin and structural types have value witnesses exported from
3693-
// the runtime.
3694-
auto &C = IGF.IGM.Context;
3695-
if (t == C.TheEmptyTupleType
3696-
|| t == C.TheNativeObjectType
3697-
|| t == C.TheBridgeObjectType
3698-
|| t == C.TheRawPointerType
3699-
|| t == C.getAnyObjectType())
3700-
return true;
3701-
if (auto intTy = dyn_cast<BuiltinIntegerType>(t)) {
3702-
auto width = intTy->getWidth();
3703-
if (width.isPointerWidth())
3704-
return true;
3705-
if (width.isFixedWidth()) {
3706-
switch (width.getFixedWidth()) {
3707-
case 8:
3708-
case 16:
3709-
case 32:
3710-
case 64:
3711-
case 128:
3712-
case 256:
3713-
return true;
3714-
default:
3715-
return false;
3716-
}
3717-
}
3718-
return false;
3719-
}
3720-
3721-
// TODO: If a nominal type is in the same source file as we're currently
3722-
// emitting, we would be able to see its value witness table.
3723-
return false;
3724-
}
3725-
37263691
/// Fallback default implementation.
37273692
llvm::Value *visitType(CanType t, DynamicMetadataRequest request) {
37283693
auto silTy = IGF.IGM.getLoweredType(t);
@@ -3731,7 +3696,10 @@ namespace {
37313696
// If the type is in the same source file, or has a common value
37323697
// witness table exported from the runtime, we can project from the
37333698
// value witness table instead of emitting a new record.
3734-
if (hasVisibleValueWitnessTable(t))
3699+
//
3700+
// TODO: If a nominal type is in the same source file as we're currently
3701+
// emitting, we would be able to see its value witness table.
3702+
if (IGF.IGM.IsWellKnownBuiltinOrStructralType(t))
37353703
return emitFromValueWitnessTable(t);
37363704

37373705
// If the type is a singleton aggregate, the field's layout is equivalent

0 commit comments

Comments
 (0)