Skip to content

Commit c98502f

Browse files
DougGregorjckarter
andcommitted
[IRGen] Centralize alignment/default type information in LinkEntity.
Simplify calls to getAddrOfLLVMVariableOrGOTEquivalent() and getAddrOfLLVMVariable() by moving the computation of the alignment and default type into LinkEntity. Co-authored-by: Joe Groff <[email protected]> (cherry picked from commit 602b38e)
1 parent cb1f514 commit c98502f

File tree

7 files changed

+336
-155
lines changed

7 files changed

+336
-155
lines changed

include/swift/IRGen/Linking.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Triple;
3232
namespace swift {
3333
namespace irgen {
3434
class IRGenModule;
35+
class Alignment;
3536

3637
/// Determine if the triple uses the DLL storage.
3738
bool useDllStorage(const llvm::Triple &triple);
@@ -947,6 +948,17 @@ class LinkEntity {
947948

948949
return getDecl()->isWeakImported(module);
949950
}
951+
952+
/// Return the source file whose codegen should trigger emission of this
953+
/// link entity, if one can be identified.
954+
const SourceFile *getSourceFileForEmission() const;
955+
956+
/// Get the preferred alignment for the definition of this entity.
957+
Alignment getAlignment(IRGenModule &IGM) const;
958+
959+
/// Get the default LLVM type to use for forward declarations of this
960+
/// entity.
961+
llvm::Type *getDefaultDeclarationType(IRGenModule &IGM) const;
950962
#undef LINKENTITY_GET_FIELD
951963
#undef LINKENTITY_SET_FIELD
952964
};

lib/IRGen/GenDecl.cpp

Lines changed: 73 additions & 126 deletions
Large diffs are not rendered by default.

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,19 +1554,16 @@ namespace {
15541554

15551555
// The class containing the base method.
15561556
auto *baseClass = cast<ClassDecl>(baseRef.getDecl()->getDeclContext());
1557+
IGM.IRGen.noteUseOfTypeContextDescriptor(baseClass, DontRequireMetadata);
15571558
auto baseClassEntity = LinkEntity::forNominalTypeDescriptor(baseClass);
15581559
auto baseClassDescriptor =
1559-
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
1560-
baseClassEntity, IGM.getPointerAlignment(),
1561-
IGM.Int8Ty);
1560+
IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseClassEntity);
15621561
descriptor.addRelativeAddress(baseClassDescriptor);
15631562

15641563
// The base method.
15651564
auto baseMethodEntity = LinkEntity::forMethodDescriptor(baseRef);
15661565
auto baseMethodDescriptor =
1567-
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
1568-
baseMethodEntity, Alignment(4),
1569-
IGM.MethodDescriptorStructTy);
1566+
IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseMethodEntity);
15701567
descriptor.addRelativeAddress(baseMethodDescriptor);
15711568

15721569
// The implementation of the override.
@@ -1716,9 +1713,8 @@ IRGenModule::getAddrOfSharedContextDescriptor(LinkEntity entity,
17161713
}
17171714
}
17181715

1719-
return getAddrOfLLVMVariable(entity, Alignment(4),
1716+
return getAddrOfLLVMVariable(entity,
17201717
definition,
1721-
TypeContextDescriptorTy,
17221718
DebugTypeInfo());
17231719
}
17241720

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,8 +2091,7 @@ namespace {
20912091
// Relative reference to the protocol descriptor.
20922092
auto protocol = Conformance->getProtocol();
20932093
auto descriptorRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2094-
LinkEntity::forProtocolDescriptor(protocol),
2095-
IGM.getPointerAlignment(), IGM.ProtocolDescriptorStructTy);
2094+
LinkEntity::forProtocolDescriptor(protocol));
20962095
B.addRelativeAddress(descriptorRef);
20972096
}
20982097

@@ -2185,8 +2184,7 @@ namespace {
21852184
auto assocType = entry.getAssociatedTypeWitness().Requirement;
21862185
auto assocTypeDescriptor =
21872186
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2188-
LinkEntity::forAssociatedTypeDescriptor(assocType),
2189-
Alignment(4), IGM.ProtocolRequirementStructTy);
2187+
LinkEntity::forAssociatedTypeDescriptor(assocType));
21902188
B.addRelativeAddress(assocTypeDescriptor);
21912189
} else if (entry.getKind() == SILWitnessTable::AssociatedTypeProtocol) {
21922190
// Associated conformance descriptor.
@@ -2198,16 +2196,14 @@ namespace {
21982196
witness.Protocol);
21992197
auto assocConformanceDescriptor =
22002198
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2201-
LinkEntity::forAssociatedConformanceDescriptor(requirement),
2202-
Alignment(4), IGM.ProtocolRequirementStructTy);
2199+
LinkEntity::forAssociatedConformanceDescriptor(requirement));
22032200
B.addRelativeAddress(assocConformanceDescriptor);
22042201
} else if (entry.getKind() == SILWitnessTable::Method) {
22052202
// Method descriptor.
22062203
auto declRef = entry.getMethodWitness().Requirement;
22072204
auto requirement =
22082205
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2209-
LinkEntity::forMethodDescriptor(declRef),
2210-
Alignment(4), IGM.ProtocolRequirementStructTy);
2206+
LinkEntity::forMethodDescriptor(declRef));
22112207
B.addRelativeAddress(requirement);
22122208
} else {
22132209
// Not part of the resilient witness table.

lib/IRGen/GenThunk.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ IRGenModule::getAddrOfMethodDescriptor(SILDeclRef declRef,
129129
assert(declRef.getOverriddenWitnessTableEntry() == declRef &&
130130
"Overriding protocol requirements do not have method descriptors");
131131
LinkEntity entity = LinkEntity::forMethodDescriptor(declRef);
132-
return getAddrOfLLVMVariable(entity, Alignment(4), forDefinition,
133-
MethodDescriptorStructTy, DebugTypeInfo());
132+
return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
134133
}
135134

136135
/// Fetch the method lookup function for a resilient class.

lib/IRGen/IRGenModule.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,8 @@ private: \
12981298
ForDefinition_t forDefinition);
12991299
llvm::Constant *getAddrOfWitnessTable(const NormalProtocolConformance *C,
13001300
ConstantInit definition = ConstantInit());
1301-
llvm::Constant *getAddrOfWitnessTablePattern(const NormalProtocolConformance *C,
1301+
llvm::Constant *getAddrOfWitnessTablePattern(
1302+
const NormalProtocolConformance *C,
13021303
ConstantInit definition = ConstantInit());
13031304

13041305
llvm::Constant *
@@ -1321,8 +1322,7 @@ private: \
13211322
GenericEnvironment *getGenericEnvironment();
13221323

13231324
ConstantReference
1324-
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity, Alignment alignment,
1325-
llvm::Type *defaultType,
1325+
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
13261326
ConstantReference::Directness forceIndirect = ConstantReference::Direct);
13271327

13281328
llvm::Constant *
@@ -1356,21 +1356,17 @@ private: \
13561356
llvm::function_ref<void()> emit);
13571357

13581358
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
1359-
Alignment alignment,
13601359
ConstantInit definition,
1361-
llvm::Type *defaultType,
1362-
DebugTypeInfo debugType);
1360+
DebugTypeInfo debugType,
1361+
llvm::Type *overrideDeclType = nullptr);
13631362
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
1364-
Alignment alignment,
13651363
ForDefinition_t forDefinition,
1366-
llvm::Type *defaultType,
13671364
DebugTypeInfo debugType);
13681365
ConstantReference getAddrOfLLVMVariable(LinkEntity entity,
1369-
Alignment alignment,
13701366
ConstantInit definition,
1371-
llvm::Type *defaultType,
13721367
DebugTypeInfo debugType,
1373-
SymbolReferenceKind refKind);
1368+
SymbolReferenceKind refKind,
1369+
llvm::Type *overrideDeclType = nullptr);
13741370

13751371
void emitLazyPrivateDefinitions();
13761372
void addRuntimeResolvableType(NominalTypeDecl *nominal);

lib/IRGen/Linking.cpp

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,3 +645,238 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
645645
}
646646
llvm_unreachable("bad link entity kind");
647647
}
648+
649+
llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const {
650+
switch (getKind()) {
651+
case Kind::ModuleDescriptor:
652+
case Kind::ExtensionDescriptor:
653+
case Kind::AnonymousDescriptor:
654+
case Kind::NominalTypeDescriptor:
655+
case Kind::PropertyDescriptor:
656+
return IGM.TypeContextDescriptorTy;
657+
case Kind::ProtocolDescriptor:
658+
return IGM.ProtocolDescriptorStructTy;
659+
case Kind::AssociatedTypeDescriptor:
660+
case Kind::AssociatedConformanceDescriptor:
661+
case Kind::ProtocolRequirementsBaseDescriptor:
662+
return IGM.ProtocolRequirementStructTy;
663+
case Kind::ProtocolConformanceDescriptor:
664+
return IGM.ProtocolConformanceDescriptorTy;
665+
case Kind::ObjCClassRef:
666+
return IGM.ObjCClassPtrTy;
667+
case Kind::ObjCClass:
668+
case Kind::ObjCMetaclass:
669+
case Kind::SwiftMetaclassStub:
670+
return IGM.ObjCClassStructTy;
671+
case Kind::TypeMetadataLazyCacheVariable:
672+
return IGM.TypeMetadataPtrTy;
673+
case Kind::TypeMetadataSingletonInitializationCache:
674+
// TODO: put a cache variable on IGM
675+
return llvm::StructType::get(IGM.getLLVMContext(),
676+
{IGM.TypeMetadataPtrTy, IGM.Int8PtrTy});
677+
case Kind::TypeMetadata:
678+
switch (getMetadataAddress()) {
679+
case TypeMetadataAddress::FullMetadata:
680+
if (getType().getClassOrBoundGenericClass())
681+
return IGM.FullHeapMetadataStructTy;
682+
else
683+
return IGM.FullTypeMetadataStructTy;
684+
case TypeMetadataAddress::AddressPoint:
685+
return IGM.TypeMetadataStructTy;
686+
}
687+
688+
case Kind::TypeMetadataPattern:
689+
// TODO: Use a real type?
690+
return IGM.Int8Ty;
691+
692+
case Kind::ClassMetadataBaseOffset:
693+
// TODO: put a cache variable on IGM
694+
return llvm::StructType::get(IGM.getLLVMContext(), {
695+
IGM.SizeTy, // Immediate members offset
696+
IGM.Int32Ty, // Negative size in words
697+
IGM.Int32Ty // Positive size in words
698+
});
699+
700+
case Kind::TypeMetadataInstantiationCache:
701+
// TODO: put a cache variable on IGM
702+
return llvm::ArrayType::get(IGM.Int8PtrTy,
703+
NumGenericMetadataPrivateDataWords);
704+
case Kind::ReflectionBuiltinDescriptor:
705+
case Kind::ReflectionFieldDescriptor:
706+
case Kind::ReflectionAssociatedTypeDescriptor:
707+
return IGM.FieldDescriptorTy;
708+
case Kind::ValueWitnessTable:
709+
case Kind::DirectProtocolWitnessTable:
710+
case Kind::ProtocolWitnessTablePattern:
711+
return IGM.WitnessTableTy;
712+
case Kind::FieldOffset:
713+
return IGM.SizeTy;
714+
case Kind::EnumCase:
715+
return IGM.Int32Ty;
716+
case Kind::ProtocolWitnessTableLazyCacheVariable:
717+
return IGM.WitnessTablePtrTy;
718+
case Kind::SILFunction:
719+
return IGM.FunctionPtrTy->getPointerTo();
720+
case Kind::MethodDescriptor:
721+
case Kind::MethodDescriptorInitializer:
722+
case Kind::MethodDescriptorAllocator:
723+
return IGM.MethodDescriptorStructTy;
724+
725+
default:
726+
llvm_unreachable("declaration LLVM type not specified");
727+
}
728+
}
729+
730+
Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
731+
switch (getKind()) {
732+
case Kind::ModuleDescriptor:
733+
case Kind::ExtensionDescriptor:
734+
case Kind::AnonymousDescriptor:
735+
case Kind::NominalTypeDescriptor:
736+
case Kind::ProtocolDescriptor:
737+
case Kind::AssociatedTypeDescriptor:
738+
case Kind::AssociatedConformanceDescriptor:
739+
case Kind::ProtocolConformanceDescriptor:
740+
case Kind::ProtocolRequirementsBaseDescriptor:
741+
case Kind::ReflectionBuiltinDescriptor:
742+
case Kind::ReflectionFieldDescriptor:
743+
case Kind::ReflectionAssociatedTypeDescriptor:
744+
case Kind::PropertyDescriptor:
745+
case Kind::EnumCase:
746+
case Kind::MethodDescriptor:
747+
case Kind::MethodDescriptorInitializer:
748+
case Kind::MethodDescriptorAllocator:
749+
return Alignment(4);
750+
case Kind::ObjCClassRef:
751+
case Kind::ObjCClass:
752+
case Kind::TypeMetadataLazyCacheVariable:
753+
case Kind::TypeMetadataSingletonInitializationCache:
754+
case Kind::TypeMetadata:
755+
case Kind::TypeMetadataPattern:
756+
case Kind::ClassMetadataBaseOffset:
757+
case Kind::TypeMetadataInstantiationCache:
758+
case Kind::ValueWitnessTable:
759+
case Kind::FieldOffset:
760+
case Kind::ProtocolWitnessTableLazyCacheVariable:
761+
case Kind::DirectProtocolWitnessTable:
762+
case Kind::ProtocolWitnessTablePattern:
763+
case Kind::ObjCMetaclass:
764+
case Kind::SwiftMetaclassStub:
765+
return IGM.getPointerAlignment();
766+
case Kind::SILFunction:
767+
return Alignment(1);
768+
default:
769+
llvm_unreachable("alignment not specified");
770+
}
771+
}
772+
773+
const SourceFile *LinkEntity::getSourceFileForEmission() const {
774+
const SourceFile *sf;
775+
776+
// Shared-linkage entities don't get emitted with any particular file.
777+
if (hasSharedVisibility(getLinkage(NotForDefinition)))
778+
return nullptr;
779+
780+
auto getSourceFileForDeclContext =
781+
[](const DeclContext *dc) -> const SourceFile * {
782+
if (!dc)
783+
return nullptr;
784+
return dc->getParentSourceFile();
785+
};
786+
787+
switch (getKind()) {
788+
case Kind::DispatchThunk:
789+
case Kind::DispatchThunkInitializer:
790+
case Kind::DispatchThunkAllocator:
791+
case Kind::MethodDescriptor:
792+
case Kind::MethodDescriptorInitializer:
793+
case Kind::MethodDescriptorAllocator:
794+
case Kind::MethodLookupFunction:
795+
case Kind::EnumCase:
796+
case Kind::FieldOffset:
797+
case Kind::ObjCClass:
798+
case Kind::ObjCMetaclass:
799+
case Kind::SwiftMetaclassStub:
800+
case Kind::ClassMetadataBaseOffset:
801+
case Kind::PropertyDescriptor:
802+
case Kind::NominalTypeDescriptor:
803+
case Kind::TypeMetadataPattern:
804+
case Kind::TypeMetadataInstantiationCache:
805+
case Kind::TypeMetadataInstantiationFunction:
806+
case Kind::TypeMetadataSingletonInitializationCache:
807+
case Kind::TypeMetadataCompletionFunction:
808+
case Kind::ProtocolDescriptor:
809+
case Kind::ProtocolRequirementsBaseDescriptor:
810+
case Kind::AssociatedTypeDescriptor:
811+
case Kind::AssociatedConformanceDescriptor:
812+
case Kind::DefaultAssociatedConformanceAccessor:
813+
sf = getSourceFileForDeclContext(getDecl()->getDeclContext());
814+
if (!sf)
815+
return nullptr;
816+
break;
817+
818+
case Kind::SILFunction:
819+
sf = getSourceFileForDeclContext(getSILFunction()->getDeclContext());
820+
if (!sf)
821+
return nullptr;
822+
break;
823+
824+
case Kind::SILGlobalVariable:
825+
if (auto decl = getSILGlobalVariable()->getDecl()) {
826+
sf = getSourceFileForDeclContext(decl->getDeclContext());
827+
if (!sf)
828+
return nullptr;
829+
} else {
830+
return nullptr;
831+
}
832+
break;
833+
834+
case Kind::DirectProtocolWitnessTable:
835+
case Kind::ProtocolWitnessTablePattern:
836+
case Kind::ProtocolWitnessTableAccessFunction:
837+
case Kind::GenericProtocolWitnessTableInstantiationFunction:
838+
case Kind::AssociatedTypeWitnessTableAccessFunction:
839+
case Kind::ReflectionAssociatedTypeDescriptor:
840+
case Kind::ProtocolConformanceDescriptor:
841+
case Kind::ProtocolWitnessTableLazyCacheVariable:
842+
case Kind::ProtocolWitnessTableLazyAccessFunction:
843+
sf = getSourceFileForDeclContext(
844+
getProtocolConformance()->getRootNormalConformance()->getDeclContext());
845+
if (!sf)
846+
return nullptr;
847+
break;
848+
849+
case Kind::TypeMetadata: {
850+
auto ty = getType();
851+
// Only fully concrete nominal type metadata gets emitted eagerly.
852+
auto nom = ty->getAnyNominal();
853+
if (!nom || nom->isGenericContext())
854+
return nullptr;
855+
856+
sf = getSourceFileForDeclContext(nom);
857+
if (!sf)
858+
return nullptr;
859+
break;
860+
}
861+
862+
// Always shared linkage
863+
case Kind::ModuleDescriptor:
864+
case Kind::ExtensionDescriptor:
865+
case Kind::AnonymousDescriptor:
866+
case Kind::ObjCClassRef:
867+
case Kind::TypeMetadataAccessFunction:
868+
case Kind::TypeMetadataLazyCacheVariable:
869+
case Kind::ForeignTypeMetadataCandidate:
870+
return nullptr;
871+
872+
// TODO
873+
case Kind::CoroutineContinuationPrototype:
874+
case Kind::ReflectionFieldDescriptor:
875+
case Kind::ReflectionBuiltinDescriptor:
876+
case Kind::ValueWitness:
877+
case Kind::ValueWitnessTable:
878+
return nullptr;
879+
}
880+
881+
return sf;
882+
}

0 commit comments

Comments
 (0)