@@ -1688,7 +1688,7 @@ namespace {
16881688 VTable (IGM.getSILModule().lookUpVTable(getType())),
16891689 Resilient(IGM.hasResilientMetadata(Type, ResilienceExpansion::Minimal)) {
16901690
1691- if (getType ()->isForeign () || Type-> isForeignReferenceType () )
1691+ if (getType ()->isForeign ())
16921692 return ;
16931693
16941694 MetadataLayout = &IGM.getClassMetadataLayout (Type);
@@ -1719,7 +1719,6 @@ namespace {
17191719 }
17201720
17211721 void layout () {
1722- assert (!getType ()->isForeignReferenceType ());
17231722 super::layout ();
17241723 addVTable ();
17251724 addOverrideTable ();
@@ -1788,7 +1787,8 @@ namespace {
17881787 // is a foreign class.
17891788 if ((IGM.IRGen .Opts .ReflectionMetadata !=
17901789 ReflectionMetadataMode::Runtime) ||
1791- getType ()->isForeign ()) {
1790+ getType ()->isForeign () ||
1791+ getType ()->isForeignReferenceType ()) {
17921792 B.addInt32 (0 );
17931793 return ;
17941794 }
@@ -2556,15 +2556,6 @@ void irgen::emitLazyTypeContextDescriptor(IRGenModule &IGM,
25562556void irgen::emitLazyTypeMetadata (IRGenModule &IGM, NominalTypeDecl *type) {
25572557 eraseExistingTypeContextDescriptor (IGM, type);
25582558
2559- // Special case, UFOs are opaque pointers for now.
2560- if (auto cd = dyn_cast<ClassDecl>(type)) {
2561- if (cd->isForeignReferenceType ()) {
2562- auto sd = cast<StructDecl>(type->getASTContext ().getOpaquePointerDecl ());
2563- emitStructMetadata (IGM, sd);
2564- return ;
2565- }
2566- }
2567-
25682559 if (requiresForeignTypeMetadata (type)) {
25692560 emitForeignTypeMetadata (IGM, type);
25702561 } else if (auto sd = dyn_cast<StructDecl>(type)) {
@@ -3245,12 +3236,7 @@ static void createNonGenericMetadataAccessFunction(IRGenModule &IGM,
32453236// / Emit the base-offset variable for the class.
32463237static void emitClassMetadataBaseOffset (IRGenModule &IGM,
32473238 ClassDecl *classDecl) {
3248- if (classDecl->isForeignReferenceType ()) {
3249- classDecl->getASTContext ().Diags .diagnose (
3250- classDecl->getLoc (), diag::foreign_reference_types_unsupported.ID ,
3251- {});
3252- exit (1 );
3253- }
3239+ assert (!classDecl->isForeignReferenceType ());
32543240
32553241 // Otherwise, we know the offset at compile time, even if our
32563242 // clients do not, so just emit a constant.
@@ -5425,21 +5411,21 @@ namespace {
54255411 }
54265412 };
54275413
5428- class ForeignClassMetadataBuilder ;
5414+ template < class Impl >
54295415 class ForeignClassMetadataBuilderBase :
5430- public ForeignClassMetadataVisitor<ForeignClassMetadataBuilder > {
5416+ public ForeignClassMetadataVisitor<Impl > {
54315417 protected:
54325418 ConstantStructBuilder &B;
54335419
54345420 ForeignClassMetadataBuilderBase (IRGenModule &IGM, ClassDecl *target,
54355421 ConstantStructBuilder &B)
5436- : ForeignClassMetadataVisitor(IGM, target), B(B) {}
5422+ : ForeignClassMetadataVisitor<Impl> (IGM, target), B(B) {}
54375423 };
54385424
54395425 // / A builder for ForeignClassMetadata.
54405426 class ForeignClassMetadataBuilder :
54415427 public ForeignMetadataBuilderBase<ForeignClassMetadataBuilder,
5442- ForeignClassMetadataBuilderBase> {
5428+ ForeignClassMetadataBuilderBase<ForeignClassMetadataBuilder> > {
54435429 public:
54445430 ForeignClassMetadataBuilder (IRGenModule &IGM, ClassDecl *target,
54455431 ConstantStructBuilder &B)
@@ -5532,6 +5518,60 @@ namespace {
55325518 B.addNullPointer (IGM.Int8PtrTy );
55335519 }
55345520 };
5521+
5522+ // / A builder for ForeignReferenceTypeMetadata.
5523+ class ForeignReferenceTypeMetadataBuilder :
5524+ public ForeignMetadataBuilderBase<ForeignReferenceTypeMetadataBuilder,
5525+ ForeignClassMetadataBuilderBase<ForeignReferenceTypeMetadataBuilder>> {
5526+ public:
5527+ ForeignReferenceTypeMetadataBuilder (IRGenModule &IGM, ClassDecl *target,
5528+ ConstantStructBuilder &B)
5529+ : ForeignMetadataBuilderBase(IGM, target, B) {
5530+ assert (getTargetType ()->isForeignReferenceType () &&
5531+ " foreign reference type metadata build must be used on foreign reference types." );
5532+
5533+ if (IGM.getOptions ().LazyInitializeClassMetadata )
5534+ CanBeConstant = false ;
5535+ }
5536+
5537+ void emitInitializeMetadata (IRGenFunction &IGF, llvm::Value *metadata,
5538+ MetadataDependencyCollector *collector) {
5539+ llvm_unreachable (" Not implemented for foreign reference types." );
5540+ }
5541+
5542+ // Visitor methods.
5543+
5544+ void addValueWitnessTable () {
5545+ auto type = getTargetType ()->getCanonicalType ();
5546+ B.add (irgen::emitValueWitnessTable (IGM, type, false , false ).getValue ());
5547+ }
5548+
5549+ void addMetadataFlags () {
5550+ B.addInt (IGM.MetadataKindTy , (unsigned ) MetadataKind::ForeignReferenceType);
5551+ }
5552+
5553+ void addNominalTypeDescriptor () {
5554+ auto descriptor =
5555+ ClassContextDescriptorBuilder (this ->IGM , Target, RequireMetadata).emit ();
5556+ B.addSignedPointer (descriptor,
5557+ IGM.getOptions ().PointerAuth .TypeDescriptors ,
5558+ PointerAuthEntity::Special::TypeDescriptor);
5559+ }
5560+
5561+ void addSuperclass () {
5562+ // Always leave the superclass pointer unfilled. We'll have to
5563+ // unique it during initialization anyway, so we might as well spare
5564+ // ourselves the load-time work.
5565+ B.addNullPointer (IGM.TypeMetadataPtrTy );
5566+
5567+ assert (!Target->hasSuperclass () &&
5568+ " foreign reference types should not have superclasses." );
5569+ }
5570+
5571+ void addReservedWord () {
5572+ B.addNullPointer (IGM.Int8PtrTy );
5573+ }
5574+ };
55355575
55365576 // / A builder for ForeignStructMetadata.
55375577 class ForeignStructMetadataBuilder :
@@ -5598,8 +5638,9 @@ bool irgen::requiresForeignTypeMetadata(CanType type) {
55985638
55995639bool irgen::requiresForeignTypeMetadata (NominalTypeDecl *decl) {
56005640 if (auto *clazz = dyn_cast<ClassDecl>(decl)) {
5601- assert (!clazz->isForeignReferenceType ());
5602-
5641+ if (clazz->isForeignReferenceType ())
5642+ return true ;
5643+
56035644 switch (clazz->getForeignClassKind ()) {
56045645 case ClassDecl::ForeignKind::Normal:
56055646 case ClassDecl::ForeignKind::RuntimeOnly:
@@ -5623,16 +5664,25 @@ void irgen::emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl) {
56235664 init.setPacked (true );
56245665
56255666 if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
5626- assert (classDecl->getForeignClassKind () == ClassDecl::ForeignKind::CFType ||
5627- classDecl->isForeignReferenceType ());
5667+ if (classDecl->isForeignReferenceType ()) {
5668+ ForeignReferenceTypeMetadataBuilder builder (IGM, classDecl, init);
5669+ builder.layout ();
56285670
5629- ForeignClassMetadataBuilder builder (IGM, classDecl, init);
5630- builder.layout ();
5671+ IGM.defineTypeMetadata (type, /* isPattern=*/ false ,
5672+ builder.canBeConstant (),
5673+ init.finishAndCreateFuture ());
5674+ builder.createMetadataAccessFunction ();
5675+ } else {
5676+ assert (classDecl->getForeignClassKind () == ClassDecl::ForeignKind::CFType);
56315677
5632- IGM.defineTypeMetadata (type, /* isPattern=*/ false ,
5633- builder.canBeConstant (),
5634- init.finishAndCreateFuture ());
5635- builder.createMetadataAccessFunction ();
5678+ ForeignClassMetadataBuilder builder (IGM, classDecl, init);
5679+ builder.layout ();
5680+
5681+ IGM.defineTypeMetadata (type, /* isPattern=*/ false ,
5682+ builder.canBeConstant (),
5683+ init.finishAndCreateFuture ());
5684+ builder.createMetadataAccessFunction ();
5685+ }
56365686 } else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
56375687 assert (isa<ClangModuleUnit>(structDecl->getModuleScopeContext ()));
56385688
0 commit comments