IRGen: Emit foreign type metadata using the lazy metadata mechanism

Instead of a wholly separate lazyness mechanism for foreign metadata where
the first call to getAddrOfForeignTypeMetadataCandidate() would emit the
metadata, emit it using the lazy metadata mechanism.

This eliminates some code duplication. It also ensures that foreign
metadata is only emitted once per SIL module, and not once per LLVM
module, avoiding duplicate copies that must be ODR'd away in multi-threaded
mode.

This fixes the test case from <rdar://problem/49710077>.
This commit is contained in:
Slava Pestov
2019-04-11 00:10:45 -04:00
parent 6d2fc0c08c
commit dd80f588dd
15 changed files with 168 additions and 224 deletions

View File

@@ -346,10 +346,6 @@ class LinkEntity {
/// The pointer is a canonical TypeBase*.
TypeMetadataLazyCacheVariable,
/// A foreign type metadata candidate.
/// The pointer is a canonical TypeBase*.
ForeignTypeMetadataCandidate,
/// A reflection metadata descriptor for a builtin or imported type.
ReflectionBuiltinDescriptor,
@@ -688,12 +684,6 @@ public:
return entity;
}
static LinkEntity forForeignTypeMetadataCandidate(CanType type) {
LinkEntity entity;
entity.setForType(Kind::ForeignTypeMetadataCandidate, type);
return entity;
}
static LinkEntity forClassMetadataBaseOffset(ClassDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ClassMetadataBaseOffset, decl);
@@ -1047,15 +1037,15 @@ public:
getKind() == Kind::ObjCResilientClassStub);
return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress);
}
bool isForeignTypeMetadataCandidate() const {
return getKind() == Kind::ForeignTypeMetadataCandidate;
}
bool isObjCClassRef() const {
return getKind() == Kind::ObjCClassRef;
}
bool isSILFunction() const {
return getKind() == Kind::SILFunction;
}
bool isNominalTypeDescriptor() const {
return getKind() == Kind::NominalTypeDescriptor;
}
/// Determine whether this entity will be weak-imported.
bool isWeakImported(ModuleDecl *module,

View File

@@ -2433,13 +2433,7 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
}
// Ensure the variable is at least forward-declared.
if (entity.isForeignTypeMetadataCandidate()) {
auto foreignCandidate
= getAddrOfForeignTypeMetadataCandidate(entity.getType());
(void)foreignCandidate;
} else {
getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}
getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
// Guess whether a global entry is a definition from this TU. This isn't
// bulletproof, but at the point we emit conformance tables, we're far enough
@@ -2485,10 +2479,19 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
if (IRGen.Opts.IntegratedREPL)
return indirect();
// Nominal type descriptors are only emitted once and can only be
// referenced directly from the same TU.
if (entity.isNominalTypeDescriptor()) {
auto *dc = entity.getDecl()->getDeclContext();
if (isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
this != IRGen.getGenModule(dc))
return indirect();
}
// If the variable has already been defined in this TU,
// then it definitely doesn't need a GOT entry, and we can
// relative-reference it directly.
if ((!entity.isAvailableExternally(*this) || isDefinition(entry))) {
if (!entity.isAvailableExternally(*this) || isDefinition(entry)) {
return direct();
}
@@ -3133,7 +3136,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
TypeMetadataAddress addrKind;
unsigned adjustmentIndex;
if (concreteType->getClassOrBoundGenericClass()) {
auto nominal = concreteType->getAnyNominal();
// Native Swift class metadata has a destructor before the address point.
// Foreign class metadata candidates do not, and neither does value type
// metadata.
if (nominal && isa<ClassDecl>(nominal) &&
!requiresForeignTypeMetadata(nominal)) {
addrKind = TypeMetadataAddress::FullMetadata;
adjustmentIndex = MetadataAdjustmentIndex::Class;
} else {
@@ -3160,9 +3169,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
addUsedGlobal(var);
// Keep type metadata around for all types.
if (auto nominal = concreteType->getAnyNominal())
if (nominal)
addRuntimeResolvableType(nominal);
// Don't define the alias for foreign type metadata, since it's not ABI.
if (nominal && requiresForeignTypeMetadata(nominal))
return var;
// For concrete metadata, declare the alias to its address point.
auto directEntity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint);
@@ -3181,21 +3194,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
return defineAlias(directEntity, addr);
}
/// Fetch the declaration of the metadata (or metadata template) for a
/// type.
///
/// If the definition type is specified, the result will always be a
/// GlobalValue of the given type, which may not be at the
/// canonical address point for a type metadata.
///
/// If the definition type is not specified, then:
/// - if the metadata is indirect, then the result will not be adjusted
/// and it will have the type pointer-to-T, where T is the type
/// of a direct metadata;
/// - if the metadata is a pattern, then the result will not be
/// adjusted and it will have FullTypeMetadataPtrTy;
/// - otherwise it will be adjusted to the canonical address point
/// for a type metadata and it will have type TypeMetadataPtrTy.
/// Fetch the declaration of the (possibly uninitialized) metadata for a type.
llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType) {
return getAddrOfTypeMetadata(concreteType,
SymbolReferenceKind::Absolute).getDirectValue();
@@ -3205,31 +3204,19 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
SymbolReferenceKind refKind) {
assert(!isa<UnboundGenericType>(concreteType));
auto nominal = concreteType->getAnyNominal();
llvm::Type *defaultVarTy;
unsigned adjustmentIndex;
ClassDecl *ObjCClass = nullptr;
// Objective-C classes use the ObjC class object.
if (isa<ClassType>(concreteType) &&
!hasKnownSwiftMetadata(*this, cast<ClassType>(concreteType)->getDecl())) {
defaultVarTy = TypeMetadataStructTy;
adjustmentIndex = 0;
ObjCClass = cast<ClassType>(concreteType)->getDecl();
// Foreign classes reference the full metadata with a GEP.
if (nominal && requiresForeignTypeMetadata(nominal)) {
defaultVarTy = FullTypeMetadataStructTy;
adjustmentIndex = MetadataAdjustmentIndex::ValueType;
// The symbol for other nominal type metadata is generated at the address
// point.
} else if (isa<ClassType>(concreteType) ||
isa<BoundGenericClassType>(concreteType)) {
assert(!concreteType->getClassOrBoundGenericClass()->isForeign()
&& "metadata for foreign classes should be emitted as "
"foreign candidate");
defaultVarTy = TypeMetadataStructTy;
adjustmentIndex = 0;
} else if (auto nom = concreteType->getAnyNominal()) {
assert(!isa<ClangModuleUnit>(nom->getModuleScopeContext())
&& "metadata for foreign type should be emitted as "
"foreign candidate");
(void)nom;
} else if (nominal) {
assert(!nominal->hasClangNode());
defaultVarTy = TypeMetadataStructTy;
adjustmentIndex = 0;
@@ -3248,20 +3235,24 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
IRGen.noteUseOfTypeMetadata(nominal);
}
LinkEntity entity
= ObjCClass ? LinkEntity::forObjCClass(ObjCClass)
: LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint);
Optional<LinkEntity> entity;
DebugTypeInfo DbgTy;
auto DbgTy =
ObjCClass
? DebugTypeInfo::getObjCClass(ObjCClass, ObjCClassPtrTy,
getPointerSize(), getPointerAlignment())
: DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
if (nominal && requiresForeignTypeMetadata(nominal)) {
entity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::FullMetadata);
DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
defaultVarTy->getPointerTo(), Size(0),
Alignment(1));
Alignment(1));;
} else {
entity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint);
DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
defaultVarTy->getPointerTo(), Size(0),
Alignment(1));;
}
auto addr = getAddrOfLLVMVariable(entity, ConstantInit(), DbgTy, refKind,
auto addr = getAddrOfLLVMVariable(*entity, ConstantInit(), DbgTy, refKind,
defaultVarTy);
// FIXME: MC breaks when emitting alias references on some platforms

View File

@@ -1694,10 +1694,9 @@ void irgen::emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type) {
eraseExistingTypeContextDescriptor(IGM, type);
if (requiresForeignTypeMetadata(type)) {
(void)IGM.getAddrOfForeignTypeMetadataCandidate(
type->getDeclaredInterfaceType()->getCanonicalType());
emitForeignTypeMetadata(IGM, type);
} else if (auto sd = dyn_cast<StructDecl>(type)) {
return emitStructMetadata(IGM, sd);
emitStructMetadata(IGM, sd);
} else if (auto ed = dyn_cast<EnumDecl>(type)) {
emitEnumMetadata(IGM, ed);
} else if (auto pd = dyn_cast<ProtocolDecl>(type)) {
@@ -1705,7 +1704,6 @@ void irgen::emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type) {
} else {
llvm_unreachable("should not have enqueued a class decl here!");
}
}
llvm::Constant *
@@ -3804,7 +3802,7 @@ namespace {
[&](IRGenFunction &IGF,
DynamicMetadataRequest request,
llvm::Constant *cacheVariable) {
auto candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type);
auto candidate = IGF.IGM.getAddrOfTypeMetadata(type);
auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
{request.get(IGF), candidate});
call->addAttribute(llvm::AttributeList::FunctionIndex,
@@ -4012,98 +4010,57 @@ bool irgen::requiresForeignTypeMetadata(NominalTypeDecl *decl) {
!isa<ProtocolDecl>(decl);
}
llvm::Constant *
IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
// What we save in GlobalVars is actually the offsetted value.
auto entity = LinkEntity::forForeignTypeMetadataCandidate(type);
if (auto entry = GlobalVars[entity])
return entry;
void irgen::emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl) {
auto type = decl->getDeclaredType()->getCanonicalType();
// Create a temporary base for relative references.
ConstantInitBuilder builder(*this);
ConstantInitBuilder builder(IGM);
auto init = builder.beginStruct();
init.setPacked(true);
// Local function to create the global variable for the foreign type
// metadata candidate.
bool canBeConstant;
Size addressPoint;
llvm::Constant *result = nullptr;
auto createCandidateVariable = [&] {
auto definition = init.finishAndCreateFuture();
// Create the global variable.
LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
auto var =
createVariable(*this, link, definition.getType(),
getPointerAlignment());
definition.installInGlobal(var);
var->setConstant(canBeConstant);
// Apply the offset.
result = llvm::ConstantExpr::getBitCast(var, Int8PtrTy);
result = llvm::ConstantExpr::getInBoundsGetElementPtr(
Int8Ty, result, getSize(addressPoint));
result = llvm::ConstantExpr::getBitCast(result, TypeMetadataPtrTy);
// Only remember the offset.
GlobalVars[entity] = result;
};
// Compute the constant initializer and the offset of the type
// metadata candidate within it.
if (auto classType = dyn_cast<ClassType>(type)) {
assert(!classType.getParent());
auto classDecl = classType->getDecl();
if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
ForeignClassMetadataBuilder builder(*this, classDecl, init);
ForeignClassMetadataBuilder builder(IGM, classDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable();
IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
} else if (auto structType = dyn_cast<StructType>(type)) {
auto structDecl = structType->getDecl();
} else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext()));
ImportedStructs.insert(structDecl);
IGM.emitFieldMetadataRecord(structDecl);
ForeignStructMetadataBuilder builder(*this, structDecl, init);
ForeignStructMetadataBuilder builder(IGM, structDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable();
IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
} else if (auto enumType = dyn_cast<EnumType>(type)) {
auto enumDecl = enumType->getDecl();
} else if (auto enumDecl = dyn_cast<EnumDecl>(decl)) {
assert(enumDecl->hasClangNode());
ForeignEnumMetadataBuilder builder(*this, enumDecl, init);
ForeignEnumMetadataBuilder builder(IGM, enumDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable();
IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
} else {
llvm_unreachable("foreign metadata for unexpected type?!");
}
// Keep type metadata around for all types.
addRuntimeResolvableType(type->getAnyNominal());
// If the enclosing type is also an imported type, force its metadata too.
if (auto enclosing = type->getNominalParent()) {
auto canonicalEnclosing = enclosing->getCanonicalType();
if (requiresForeignTypeMetadata(canonicalEnclosing)) {
(void)getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing);
IGM.IRGen.noteUseOfTypeMetadata(canonicalEnclosing);
}
}
return result;
}
// Protocols

View File

@@ -71,6 +71,10 @@ namespace irgen {
/// generated definitions.
void emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type);
/// Emit metadata for a foreign struct, enum or class.
void emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl);
/// Emit the metadata associated with the given struct declaration.
void emitStructMetadata(IRGenModule &IGM, StructDecl *theStruct);

View File

@@ -2164,11 +2164,8 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
// Record this conformance descriptor.
addProtocolConformance(std::move(description));
// Trigger the lazy emission of the foreign type metadata.
CanType conformingType = conf->getType()->getCanonicalType();
if (requiresForeignTypeMetadata(conformingType)) {
(void)getAddrOfForeignTypeMetadataCandidate(conformingType);
}
IRGen.noteUseOfTypeContextDescriptor(conf->getType()->getAnyNominal(),
RequireMetadata);
}
/// True if a function's signature in LLVM carries polymorphic parameters.

View File

@@ -998,9 +998,6 @@ void IRGenModule::emitBuiltinReflectionMetadata() {
BuiltinTypes.insert(anyMetatype);
}
for (auto SD : ImportedStructs)
emitFieldMetadataRecord(SD);
for (auto builtinType : BuiltinTypes)
emitBuiltinTypeMetadataRecord(builtinType);

View File

@@ -1031,9 +1031,6 @@ public:
/// without knowledge of their contents. This includes imported structs
/// and fixed-size multi-payload enums.
llvm::SetVector<const NominalTypeDecl *> OpaqueTypes;
/// Imported structs referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<const StructDecl *> ImportedStructs;
llvm::Constant *getTypeRef(CanType type, MangledTypeRefRole role);
llvm::Constant *getMangledAssociatedConformance(
@@ -1273,7 +1270,6 @@ public:
ForDefinition_t forDefinition);
llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type,
ForDefinition_t forDefinition);
llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
ForDefinition_t forDefinition);

View File

@@ -176,9 +176,6 @@ std::string LinkEntity::mangleAsString() const {
return mangler.mangleTypeMetadataPattern(
cast<NominalTypeDecl>(getDecl()));
case Kind::ForeignTypeMetadataCandidate:
return mangler.mangleTypeMetadataFull(getType());
case Kind::SwiftMetaclassStub:
return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));
@@ -469,13 +466,18 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
return SILLinkage::Private;
}
case Kind::TypeMetadata:
case Kind::TypeMetadata: {
auto *nominal = getType().getAnyNominal();
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
// For imported types, the full metadata object is a candidate
// for uniquing.
if (getDeclLinkage(nominal) == FormalLinkage::PublicNonUnique)
return SILLinkage::Shared;
// The full metadata object is private to the containing module.
return SILLinkage::Private;
case TypeMetadataAddress::AddressPoint: {
auto *nominal = getType().getAnyNominal();
return getSILLinkage(nominal
? getDeclLinkage(nominal)
: FormalLinkage::PublicUnique,
@@ -483,6 +485,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
}
}
llvm_unreachable("bad kind");
}
// ...but we don't actually expose individual value witnesses (right now).
case Kind::ValueWitness: {
@@ -492,11 +495,6 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
return forDefinition ? SILLinkage::Private : SILLinkage::PrivateExternal;
}
// Foreign type metadata candidates are always shared; the runtime
// does the uniquing.
case Kind::ForeignTypeMetadataCandidate:
return SILLinkage::Shared;
case Kind::TypeMetadataAccessFunction:
switch (getTypeMetadataAccessStrategy(getType())) {
case MetadataAccessStrategy::PublicUniqueAccessor:
@@ -522,7 +520,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
case Kind::ObjCResilientClassStub: {
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
// The full class stub object is private to the containing module.
// The full class stub object is private to the containing module,
// excpet for foreign types.
return SILLinkage::Private;
case TypeMetadataAddress::AddressPoint: {
auto *classDecl = cast<ClassDecl>(getDecl());
@@ -706,10 +705,6 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
case Kind::TypeMetadata:
return ::isAvailableExternally(IGM, getType());
case Kind::ForeignTypeMetadataCandidate:
assert(!::isAvailableExternally(IGM, getType()));
return false;
case Kind::ObjCClass:
case Kind::ObjCMetaclass:
// FIXME: Removing this triggers a linker bug
@@ -1022,7 +1017,6 @@ bool LinkEntity::isWeakImported(ModuleDecl *module,
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::ForeignTypeMetadataCandidate:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::CoroutineContinuationPrototype:
@@ -1141,7 +1135,6 @@ const SourceFile *LinkEntity::getSourceFileForEmission() const {
case Kind::ObjCClassRef:
case Kind::TypeMetadataAccessFunction:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::ForeignTypeMetadataCandidate:
return nullptr;
// TODO

View File

@@ -1946,9 +1946,6 @@ llvm::Function *irgen::getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM,
switch (getTypeMetadataAccessStrategy(type)) {
case MetadataAccessStrategy::ForeignAccessor:
// Force the foreign candidate to exist.
(void) IGM.getAddrOfForeignTypeMetadataCandidate(type);
LLVM_FALLTHROUGH;
case MetadataAccessStrategy::PublicUniqueAccessor:
case MetadataAccessStrategy::HiddenUniqueAccessor:
case MetadataAccessStrategy::PrivateAccessor:

View File

@@ -9,7 +9,22 @@
// CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type
// CHECK: [[OBJC:%objc_object]] = type
// CHECK: @"$sSo17CCRefrigeratorRefaN" = linkonce_odr hidden
// CHECK: [[MUTABLE_REFRIGERATOR_NAME:@.*]] = private constant [52 x i8] c"CCMutableRefrigerator\00NCCMutableRefrigeratorRef\00St\00\00"
// CHECK: @"$sSo24CCMutableRefrigeratorRefaMn" = linkonce_odr hidden constant
// -- is imported, foreign init, is class, is nonunique
// CHECK-SAME: <i32 0x0006_0010>
// CHECK-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
// CHECK-SAME: @"$sSo24CCMutableRefrigeratorRefaMa"
// CHECK-SAME: @"$sSo24CCMutableRefrigeratorRefaMr"
// CHECK: @"$sSo24CCMutableRefrigeratorRefaMf" = linkonce_odr hidden global <{ {{.*}} }> <{
// -- value witness table
// CHECK-DIRECT-SAME: i8** @"$sBOWV",
// CHECK-INDIRECT-SAME: i8** null,
// CHECK-64-SAME: i64 515, {{.*}}"$sSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
// CHECK: @"$sSo17CCRefrigeratorRefaMf" = linkonce_odr hidden
// CHECK-DIRECT-SAME: constant
// CHECK-INDIRECT-SAME: global
// CHECK-SAME: <{ {{.*}} }> <{
@@ -18,21 +33,6 @@
// CHECK-INDIRECT-SAME: i8** null,
// CHECK-SAME: [[INT]] 515, {{.*}}"$sSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null }>
// CHECK: [[MUTABLE_REFRIGERATOR_NAME:@.*]] = private constant [52 x i8] c"CCMutableRefrigerator\00NCCMutableRefrigeratorRef\00St\00\00"
// CHECK-64: @"$sSo24CCMutableRefrigeratorRefaMn" = linkonce_odr hidden constant
// -- is imported, foreign init, is class, is nonunique
// CHECK-64-SAME: <i32 0x0006_0010>
// CHECK-64-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
// CHECK-64-SAME: @"$sSo24CCMutableRefrigeratorRefaMa"
// CHECK-64-SAME: @"$sSo24CCMutableRefrigeratorRefaMr"
// CHECK-64: @"$sSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
// -- value witness table
// CHECK-DIRECT-64-SAME: i8** @"$sBOWV",
// CHECK-INDIRECT-64-SAME: i8** null,
// CHECK-64-SAME: i64 515, {{.*}}"$sSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
sil_stage canonical
import CoreCooling
@@ -61,9 +61,9 @@ bb0(%0 : $CCRefrigerator, %1: $CCMutableRefrigerator):
// CHECK-NEXT: call swiftcc void @generic_function([[OBJC]]* [[T0]], [[TYPE]]* [[T2]])
// CHECK-NEXT: ret void
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"(
// CHECK-32: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$sSo17CCRefrigeratorRefaN" to i8*), [[INT]] 4) to [[TYPE]]*))
// CHECK-64: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$sSo17CCRefrigeratorRefaN" to i8*), [[INT]] 8) to [[TYPE]]*))
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"(
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0,
// CHECK-SAME: @"$sSo17CCRefrigeratorRefaMf"
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$sSo24CCMutableRefrigeratorRefaMr"(%swift.type*, i8*, i8**)
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"([[INT]] 255)

View File

@@ -3,19 +3,19 @@
sil_stage canonical
import c_layout
// CHECK: [[HAS_NESTED_UNION_NAME:@.*]] = private constant [15 x i8] c"HasNestedUnion\00"
// CHECK-LABEL: @"$sSo14HasNestedUnionVMn" = linkonce_odr hidden constant
// CHECK-SAME: [[HAS_NESTED_UNION_NAME]]
// CHECK-SAME: @"$sSo14HasNestedUnionVMa"
// CHECK: [[AMAZING_COLOR_NAME:@.*]] = private constant [13 x i8] c"AmazingColor\00"
// CHECK-LABEL: @"$sSo12AmazingColorVMn" = linkonce_odr hidden constant
// CHECK-SAME: [[AMAZING_COLOR_NAME]]
// CHECK-SAME: @"$sSo12AmazingColorVMa"
// CHECK-LABEL: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVN" = linkonce_odr hidden constant
// CHECK: [[HAS_NESTED_UNION_NAME:@.*]] = private constant [15 x i8] c"HasNestedUnion\00"
// CHECK-LABEL: @"$sSo14HasNestedUnionVMn" = linkonce_odr hidden constant
// CHECK-SAME: [[HAS_NESTED_UNION_NAME]]
// CHECK-SAME: @"$sSo14HasNestedUnionVMa"
// CHECK-LABEL: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMf" = linkonce_odr hidden constant
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVWV"
// CHECK-SAME: [[INT]] 512,
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
@@ -23,8 +23,8 @@ import c_layout
// CHECK-SAME: i32 4 }
// CHECK-LABEL: @"\01l_type_metadata_table" = private constant
// CHECK-SAME: @"$sSo14HasNestedUnionVMn"
// CHECK-SAME: @"$sSo12AmazingColorVMn"
// CHECK-SAME: @"$sSo14HasNestedUnionVMn"
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
sil @test0 : $() -> () {
@@ -37,7 +37,7 @@ bb0:
}
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo14HasNestedUnionVMa"(
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}$sSo14HasNestedUnionVN
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}@"$sSo14HasNestedUnionVMf"
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo12AmazingColorVMa"(
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}@"$sSo12AmazingColorVN"
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}@"$sSo12AmazingColorVMf"

View File

@@ -0,0 +1,12 @@
// RUN: %target-swift-frontend -parse-as-library -module-name=test -O %s -emit-ir -disable-reflection-metadata | %FileCheck %s
struct S { }
extension S: Equatable {
static func ==(lhs: S, rhs: S) -> Bool {
return false
}
}
// CHECK-LABEL: @"$s4test1SVMn" = hidden constant
// CHECK-LABEL: @"$s4test1SVSQAAMc" = hidden constant

View File

@@ -22,13 +22,13 @@ import gizmo
// CHECK: @"\01L_selector_data(bar)" = private global [4 x i8] c"bar\00", section "__TEXT,__objc_methname,cstring_literals", align 1
// CHECK: @"\01L_selector(bar)" = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
// CHECK: @"$sSo4RectVMn" = linkonce_odr hidden constant
// CHECK: @"$sSo4RectVN" = linkonce_odr hidden constant
// CHECK: @"\01L_selector_data(acquiesce)"
// CHECK-NOT: @"\01L_selector_data(disharmonize)"
// CHECK: @"\01L_selector_data(eviscerate)"
// CHECK: @"$sSo4RectVMn" = linkonce_odr hidden constant
// CHECK: @"$sSo4RectVMf" = linkonce_odr hidden constant
struct id {
var data : AnyObject
}
@@ -130,7 +130,7 @@ func test10(_ g: Gizmo, r: Rect) {
func test11_helper<T>(_ t: T) {}
// NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata.
// CHECK-LABEL: define hidden swiftcc void @"$s4objc6test11yySo4RectVF"
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata(i64 %0, {{.*}} @"$sSo4RectVN"
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata(i64 %0, {{.*}} @"$sSo4RectVMf"
func test11(_ r: Rect) { test11_helper(r) }
class WeakObjC {

View File

@@ -1,6 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir > %t/out.txt
// RUN: %FileCheck %s -DINT=i%target-ptrsize < %t/out.txt
// RUN: %FileCheck %s --check-prefix=NEGATIVE < %t/out.txt
// REQUIRES: CPU=x86_64
// REQUIRES: objc_interop
@@ -9,10 +12,11 @@ import Foundation
import gizmo
// CHECK: @"$sSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant
// CHECK: @"$sSo16NSRuncingOptionsVN" = linkonce_odr hidden constant
// CHECK: @"$sSo16NSRuncingOptionsVMf" = linkonce_odr hidden constant
// CHECK-SAME: @"$sBi{{[0-9]+}}_WV"
// CHECK: @"$sSo16NSRuncingOptionsVSQSCMc" = linkonce_odr hidden constant
// CHECK-NOT: @"$sSo28NeverActuallyMentionedByNameVSQSCWp" = linkonce_odr hidden constant
// NEGATIVE-NOT: @"$sSo28NeverActuallyMentionedByNameVSQSCWp" = linkonce_odr hidden constant
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} i32 @main
// CHECK: call swiftcc %swift.metadata_response @"$sSo16NSRuncingOptionsVMa"(i64 0)
@@ -87,7 +91,9 @@ func use_metadata<T: Equatable>(_ t:T){}
use_metadata(NSRuncingOptions.mince)
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo16NSRuncingOptionsVMa"(i64)
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}} @"$sSo16NSRuncingOptionsVN" {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0,
// CHECK-SAME: @"$sSo16NSRuncingOptionsVMf"
// CHECK-SAME: [[NOUNWIND_READNONE:#[0-9]+]]
@objc enum ExportedToObjC: Int {
case Foo = -1, Bar, Bas

View File

@@ -13,35 +13,39 @@ sil @use_metatypes : $@convention(thin) () -> () {
bb0:
%take = function_ref @take_metatype : $@convention(thin) <T> (@thick T.Type) -> ()
// CHECK: [[TagError1_NAME:@[0-9]+]] = private constant [14 x i8] c"TagError1\00Re\00\00"
// CHECK: @"$sSC9TagError1LeVMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0011>
// CHECK-SAME: @"$sSCMXM"
// CHECK-SAME: [14 x i8]* [[TagError1_NAME]]
%0 = metatype $@thick TagError1.Type
apply %take<TagError1>(%0) : $@convention(thin) <T> (@thick T.Type) -> ()
// CHECK: [[TagError2_NAME:@[0-9]+]] = private constant [17 x i8] c"Code\00NTagError2\00\00"
// CHECK: @"$sSo9TagError2VMn" = linkonce_odr hidden constant
// CHECK: [[TypedefError2Code_NAME:@[0-9]+]] = private constant [24 x i8] c"Code\00NTypedefError2\00St\00\00"
// CHECK: @"$sSo13TypedefError2aMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0012>
// CHECK-SAME: @"$sSoMXM"
// CHECK-SAME: [17 x i8]* [[TagError2_NAME]]
%1 = metatype $@thick TagError2.Code.Type
apply %take<TagError2.Code>(%1) : $@convention(thin) <T> (@thick T.Type) -> ()
// CHECK-SAME: [24 x i8]* [[TypedefError2Code_NAME]]
// CHECK: [[TypedefError1_NAME:@[0-9]+]] = private constant [18 x i8] c"TypedefError1\00RE\00\00"
// CHECK: @"$sSC13TypedefError1LEVMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0011>
// CHECK-SAME: @"$sSCMXM"
// CHECK-SAME: [18 x i8]* [[TypedefError1_NAME]]
// CHECK: [[TagError2_NAME:@[0-9]+]] = private constant [17 x i8] c"Code\00NTagError2\00\00"
// CHECK: @"$sSo9TagError2VMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0012>
// CHECK-SAME: @"$sSoMXM"
// CHECK-SAME: [17 x i8]* [[TagError2_NAME]]
// CHECK: [[TagError1_NAME:@[0-9]+]] = private constant [14 x i8] c"TagError1\00Re\00\00"
// CHECK: @"$sSC9TagError1LeVMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0011>
// CHECK-SAME: @"$sSCMXM"
// CHECK-SAME: [14 x i8]* [[TagError1_NAME]]
%0 = metatype $@thick TagError1.Type
apply %take<TagError1>(%0) : $@convention(thin) <T> (@thick T.Type) -> ()
%1 = metatype $@thick TagError2.Code.Type
apply %take<TagError2.Code>(%1) : $@convention(thin) <T> (@thick T.Type) -> ()
%2 = metatype $@thick TypedefError1.Type
apply %take<TypedefError1>(%2) : $@convention(thin) <T> (@thick T.Type) -> ()
// CHECK: [[TypedefError2Code_NAME:@[0-9]+]] = private constant [24 x i8] c"Code\00NTypedefError2\00St\00\00"
// CHECK: @"$sSo13TypedefError2aMn" = linkonce_odr hidden constant
// CHECK-SAME: <i32 0x0006_0012>
// CHECK-SAME: @"$sSoMXM"
// CHECK-SAME: [24 x i8]* [[TypedefError2Code_NAME]]
%3 = metatype $@thick TypedefError2.Code.Type
apply %take<TypedefError2.Code>(%3) : $@convention(thin) <T> (@thick T.Type) -> ()