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

View File

@@ -2433,13 +2433,7 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
} }
// Ensure the variable is at least forward-declared. // Ensure the variable is at least forward-declared.
if (entity.isForeignTypeMetadataCandidate()) { getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
auto foreignCandidate
= getAddrOfForeignTypeMetadataCandidate(entity.getType());
(void)foreignCandidate;
} else {
getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}
// Guess whether a global entry is a definition from this TU. This isn't // 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 // bulletproof, but at the point we emit conformance tables, we're far enough
@@ -2484,11 +2478,20 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
// indirect references in this mode. // indirect references in this mode.
if (IRGen.Opts.IntegratedREPL) if (IRGen.Opts.IntegratedREPL)
return indirect(); 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, // If the variable has already been defined in this TU,
// then it definitely doesn't need a GOT entry, and we can // then it definitely doesn't need a GOT entry, and we can
// relative-reference it directly. // relative-reference it directly.
if ((!entity.isAvailableExternally(*this) || isDefinition(entry))) { if (!entity.isAvailableExternally(*this) || isDefinition(entry)) {
return direct(); return direct();
} }
@@ -3133,7 +3136,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
TypeMetadataAddress addrKind; TypeMetadataAddress addrKind;
unsigned adjustmentIndex; 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; addrKind = TypeMetadataAddress::FullMetadata;
adjustmentIndex = MetadataAdjustmentIndex::Class; adjustmentIndex = MetadataAdjustmentIndex::Class;
} else { } else {
@@ -3160,9 +3169,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
addUsedGlobal(var); addUsedGlobal(var);
// Keep type metadata around for all types. // Keep type metadata around for all types.
if (auto nominal = concreteType->getAnyNominal()) if (nominal)
addRuntimeResolvableType(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. // For concrete metadata, declare the alias to its address point.
auto directEntity = LinkEntity::forTypeMetadata(concreteType, auto directEntity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint); TypeMetadataAddress::AddressPoint);
@@ -3181,21 +3194,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
return defineAlias(directEntity, addr); return defineAlias(directEntity, addr);
} }
/// Fetch the declaration of the metadata (or metadata template) for a /// Fetch the declaration of the (possibly uninitialized) metadata for a type.
/// 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.
llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType) { llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType) {
return getAddrOfTypeMetadata(concreteType, return getAddrOfTypeMetadata(concreteType,
SymbolReferenceKind::Absolute).getDirectValue(); SymbolReferenceKind::Absolute).getDirectValue();
@@ -3205,32 +3204,20 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
SymbolReferenceKind refKind) { SymbolReferenceKind refKind) {
assert(!isa<UnboundGenericType>(concreteType)); assert(!isa<UnboundGenericType>(concreteType));
auto nominal = concreteType->getAnyNominal();
llvm::Type *defaultVarTy; llvm::Type *defaultVarTy;
unsigned adjustmentIndex; unsigned adjustmentIndex;
ClassDecl *ObjCClass = nullptr;
// Objective-C classes use the ObjC class object. // Foreign classes reference the full metadata with a GEP.
if (isa<ClassType>(concreteType) && if (nominal && requiresForeignTypeMetadata(nominal)) {
!hasKnownSwiftMetadata(*this, cast<ClassType>(concreteType)->getDecl())) { defaultVarTy = FullTypeMetadataStructTy;
defaultVarTy = TypeMetadataStructTy; adjustmentIndex = MetadataAdjustmentIndex::ValueType;
adjustmentIndex = 0;
ObjCClass = cast<ClassType>(concreteType)->getDecl();
// The symbol for other nominal type metadata is generated at the address // The symbol for other nominal type metadata is generated at the address
// point. // point.
} else if (isa<ClassType>(concreteType) || } else if (nominal) {
isa<BoundGenericClassType>(concreteType)) { assert(!nominal->hasClangNode());
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;
defaultVarTy = TypeMetadataStructTy; defaultVarTy = TypeMetadataStructTy;
adjustmentIndex = 0; adjustmentIndex = 0;
} else { } else {
@@ -3248,20 +3235,24 @@ ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
IRGen.noteUseOfTypeMetadata(nominal); IRGen.noteUseOfTypeMetadata(nominal);
} }
LinkEntity entity Optional<LinkEntity> entity;
= ObjCClass ? LinkEntity::forObjCClass(ObjCClass) DebugTypeInfo DbgTy;
: LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint);
auto DbgTy = if (nominal && requiresForeignTypeMetadata(nominal)) {
ObjCClass entity = LinkEntity::forTypeMetadata(concreteType,
? DebugTypeInfo::getObjCClass(ObjCClass, ObjCClassPtrTy, TypeMetadataAddress::FullMetadata);
getPointerSize(), getPointerAlignment()) DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
: DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
defaultVarTy->getPointerTo(), Size(0), 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); defaultVarTy);
// FIXME: MC breaks when emitting alias references on some platforms // 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); eraseExistingTypeContextDescriptor(IGM, type);
if (requiresForeignTypeMetadata(type)) { if (requiresForeignTypeMetadata(type)) {
(void)IGM.getAddrOfForeignTypeMetadataCandidate( emitForeignTypeMetadata(IGM, type);
type->getDeclaredInterfaceType()->getCanonicalType());
} else if (auto sd = dyn_cast<StructDecl>(type)) { } else if (auto sd = dyn_cast<StructDecl>(type)) {
return emitStructMetadata(IGM, sd); emitStructMetadata(IGM, sd);
} else if (auto ed = dyn_cast<EnumDecl>(type)) { } else if (auto ed = dyn_cast<EnumDecl>(type)) {
emitEnumMetadata(IGM, ed); emitEnumMetadata(IGM, ed);
} else if (auto pd = dyn_cast<ProtocolDecl>(type)) { } else if (auto pd = dyn_cast<ProtocolDecl>(type)) {
@@ -1705,7 +1704,6 @@ void irgen::emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type) {
} else { } else {
llvm_unreachable("should not have enqueued a class decl here!"); llvm_unreachable("should not have enqueued a class decl here!");
} }
} }
llvm::Constant * llvm::Constant *
@@ -3804,7 +3802,7 @@ namespace {
[&](IRGenFunction &IGF, [&](IRGenFunction &IGF,
DynamicMetadataRequest request, DynamicMetadataRequest request,
llvm::Constant *cacheVariable) { llvm::Constant *cacheVariable) {
auto candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type); auto candidate = IGF.IGM.getAddrOfTypeMetadata(type);
auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(), auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
{request.get(IGF), candidate}); {request.get(IGF), candidate});
call->addAttribute(llvm::AttributeList::FunctionIndex, call->addAttribute(llvm::AttributeList::FunctionIndex,
@@ -4012,98 +4010,57 @@ bool irgen::requiresForeignTypeMetadata(NominalTypeDecl *decl) {
!isa<ProtocolDecl>(decl); !isa<ProtocolDecl>(decl);
} }
llvm::Constant * void irgen::emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl) {
IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) { auto type = decl->getDeclaredType()->getCanonicalType();
// What we save in GlobalVars is actually the offsetted value.
auto entity = LinkEntity::forForeignTypeMetadataCandidate(type);
if (auto entry = GlobalVars[entity])
return entry;
// Create a temporary base for relative references. // Create a temporary base for relative references.
ConstantInitBuilder builder(*this); ConstantInitBuilder builder(IGM);
auto init = builder.beginStruct(); auto init = builder.beginStruct();
init.setPacked(true); init.setPacked(true);
// Local function to create the global variable for the foreign type if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
// 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();
assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType); assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
ForeignClassMetadataBuilder builder(*this, classDecl, init); ForeignClassMetadataBuilder builder(IGM, classDecl, init);
builder.layout(); builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable(); IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction(); builder.createMetadataAccessFunction();
} else if (auto structType = dyn_cast<StructType>(type)) { } else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
auto structDecl = structType->getDecl();
assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext())); assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext()));
ImportedStructs.insert(structDecl); IGM.emitFieldMetadataRecord(structDecl);
ForeignStructMetadataBuilder builder(*this, structDecl, init); ForeignStructMetadataBuilder builder(IGM, structDecl, init);
builder.layout(); builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable(); IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction(); builder.createMetadataAccessFunction();
} else if (auto enumType = dyn_cast<EnumType>(type)) { } else if (auto enumDecl = dyn_cast<EnumDecl>(decl)) {
auto enumDecl = enumType->getDecl();
assert(enumDecl->hasClangNode()); assert(enumDecl->hasClangNode());
ForeignEnumMetadataBuilder builder(*this, enumDecl, init); ForeignEnumMetadataBuilder builder(IGM, enumDecl, init);
builder.layout(); builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
canBeConstant = builder.canBeConstant();
createCandidateVariable(); IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction(); builder.createMetadataAccessFunction();
} else { } else {
llvm_unreachable("foreign metadata for unexpected type?!"); 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 the enclosing type is also an imported type, force its metadata too.
if (auto enclosing = type->getNominalParent()) { if (auto enclosing = type->getNominalParent()) {
auto canonicalEnclosing = enclosing->getCanonicalType(); auto canonicalEnclosing = enclosing->getCanonicalType();
if (requiresForeignTypeMetadata(canonicalEnclosing)) { if (requiresForeignTypeMetadata(canonicalEnclosing)) {
(void)getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing); IGM.IRGen.noteUseOfTypeMetadata(canonicalEnclosing);
} }
} }
return result;
} }
// Protocols // Protocols

View File

@@ -71,6 +71,10 @@ namespace irgen {
/// generated definitions. /// generated definitions.
void emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type); 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. /// Emit the metadata associated with the given struct declaration.
void emitStructMetadata(IRGenModule &IGM, StructDecl *theStruct); void emitStructMetadata(IRGenModule &IGM, StructDecl *theStruct);

View File

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

View File

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

View File

@@ -1031,9 +1031,6 @@ public:
/// without knowledge of their contents. This includes imported structs /// without knowledge of their contents. This includes imported structs
/// and fixed-size multi-payload enums. /// and fixed-size multi-payload enums.
llvm::SetVector<const NominalTypeDecl *> OpaqueTypes; 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 *getTypeRef(CanType type, MangledTypeRefRole role);
llvm::Constant *getMangledAssociatedConformance( llvm::Constant *getMangledAssociatedConformance(
@@ -1273,7 +1270,6 @@ public:
ForDefinition_t forDefinition); ForDefinition_t forDefinition);
llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type, llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type,
ForDefinition_t forDefinition); ForDefinition_t forDefinition);
llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D, llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
ForDefinition_t forDefinition); ForDefinition_t forDefinition);

View File

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

View File

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

View File

@@ -9,7 +9,22 @@
// CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type // CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type
// CHECK: [[OBJC:%objc_object]] = 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-DIRECT-SAME: constant
// CHECK-INDIRECT-SAME: global // CHECK-INDIRECT-SAME: global
// CHECK-SAME: <{ {{.*}} }> <{ // CHECK-SAME: <{ {{.*}} }> <{
@@ -18,21 +33,6 @@
// CHECK-INDIRECT-SAME: i8** null, // CHECK-INDIRECT-SAME: i8** null,
// CHECK-SAME: [[INT]] 515, {{.*}}"$sSo17CCRefrigeratorRefaMn", [[TYPE]]* null, 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 sil_stage canonical
import CoreCooling import CoreCooling
@@ -61,9 +61,9 @@ bb0(%0 : $CCRefrigerator, %1: $CCMutableRefrigerator):
// CHECK-NEXT: call swiftcc void @generic_function([[OBJC]]* [[T0]], [[TYPE]]* [[T2]]) // CHECK-NEXT: call swiftcc void @generic_function([[OBJC]]* [[T0]], [[TYPE]]* [[T2]])
// CHECK-NEXT: ret void // CHECK-NEXT: ret void
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"( // 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: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0,
// 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-SAME: @"$sSo17CCRefrigeratorRefaMf"
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$sSo24CCMutableRefrigeratorRefaMr"(%swift.type*, i8*, i8**) // CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$sSo24CCMutableRefrigeratorRefaMr"(%swift.type*, i8*, i8**)
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"([[INT]] 255) // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$sSo17CCRefrigeratorRefaMa"([[INT]] 255)

View File

@@ -3,19 +3,19 @@
sil_stage canonical sil_stage canonical
import c_layout 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: [[AMAZING_COLOR_NAME:@.*]] = private constant [13 x i8] c"AmazingColor\00"
// CHECK-LABEL: @"$sSo12AmazingColorVMn" = linkonce_odr hidden constant // CHECK-LABEL: @"$sSo12AmazingColorVMn" = linkonce_odr hidden constant
// CHECK-SAME: [[AMAZING_COLOR_NAME]] // CHECK-SAME: [[AMAZING_COLOR_NAME]]
// CHECK-SAME: @"$sSo12AmazingColorVMa" // 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: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVWV"
// CHECK-SAME: [[INT]] 512, // CHECK-SAME: [[INT]] 512,
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn" // CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
@@ -23,8 +23,8 @@ import c_layout
// CHECK-SAME: i32 4 } // CHECK-SAME: i32 4 }
// CHECK-LABEL: @"\01l_type_metadata_table" = private constant // CHECK-LABEL: @"\01l_type_metadata_table" = private constant
// CHECK-SAME: @"$sSo14HasNestedUnionVMn"
// CHECK-SAME: @"$sSo12AmazingColorVMn" // CHECK-SAME: @"$sSo12AmazingColorVMn"
// CHECK-SAME: @"$sSo14HasNestedUnionVMn"
// CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn" // CHECK-SAME: @"$sSo14HasNestedUnionV18__Unnamed_struct_sVMn"
sil @test0 : $() -> () { sil @test0 : $() -> () {
@@ -37,7 +37,7 @@ bb0:
} }
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo14HasNestedUnionVMa"( // 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-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_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: @"\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: @"\01L_selector_data(acquiesce)"
// CHECK-NOT: @"\01L_selector_data(disharmonize)" // CHECK-NOT: @"\01L_selector_data(disharmonize)"
// CHECK: @"\01L_selector_data(eviscerate)" // CHECK: @"\01L_selector_data(eviscerate)"
// CHECK: @"$sSo4RectVMn" = linkonce_odr hidden constant
// CHECK: @"$sSo4RectVMf" = linkonce_odr hidden constant
struct id { struct id {
var data : AnyObject var data : AnyObject
} }
@@ -130,7 +130,7 @@ func test10(_ g: Gizmo, r: Rect) {
func test11_helper<T>(_ t: T) {} func test11_helper<T>(_ t: T) {}
// NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata. // NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata.
// CHECK-LABEL: define hidden swiftcc void @"$s4objc6test11yySo4RectVF" // 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) } func test11(_ r: Rect) { test11_helper(r) }
class WeakObjC { class WeakObjC {

View File

@@ -1,6 +1,9 @@
// RUN: %empty-directory(%t) // RUN: %empty-directory(%t)
// RUN: %build-irgen-test-overlays // 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: CPU=x86_64
// REQUIRES: objc_interop // REQUIRES: objc_interop
@@ -9,10 +12,11 @@ import Foundation
import gizmo import gizmo
// CHECK: @"$sSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant // 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-SAME: @"$sBi{{[0-9]+}}_WV"
// CHECK: @"$sSo16NSRuncingOptionsVSQSCMc" = linkonce_odr hidden constant // 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-LABEL: define{{( dllexport)?}}{{( protected)?}} i32 @main
// CHECK: call swiftcc %swift.metadata_response @"$sSo16NSRuncingOptionsVMa"(i64 0) // CHECK: call swiftcc %swift.metadata_response @"$sSo16NSRuncingOptionsVMa"(i64 0)
@@ -87,7 +91,9 @@ func use_metadata<T: Equatable>(_ t:T){}
use_metadata(NSRuncingOptions.mince) use_metadata(NSRuncingOptions.mince)
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sSo16NSRuncingOptionsVMa"(i64) // 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 { @objc enum ExportedToObjC: Int {
case Foo = -1, Bar, Bas case Foo = -1, Bar, Bas

View File

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