Skip to content

Commit 602b38e

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]>
1 parent a858e4f commit 602b38e

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);
@@ -936,6 +937,17 @@ class LinkEntity {
936937

937938
return getDecl()->isWeakImported(module);
938939
}
940+
941+
/// Return the source file whose codegen should trigger emission of this
942+
/// link entity, if one can be identified.
943+
const SourceFile *getSourceFileForEmission() const;
944+
945+
/// Get the preferred alignment for the definition of this entity.
946+
Alignment getAlignment(IRGenModule &IGM) const;
947+
948+
/// Get the default LLVM type to use for forward declarations of this
949+
/// entity.
950+
llvm::Type *getDefaultDeclarationType(IRGenModule &IGM) const;
939951
#undef LINKENTITY_GET_FIELD
940952
#undef LINKENTITY_SET_FIELD
941953
};

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
@@ -1552,19 +1552,16 @@ namespace {
15521552

15531553
// The class containing the base method.
15541554
auto *baseClass = cast<ClassDecl>(baseRef.getDecl()->getDeclContext());
1555+
IGM.IRGen.noteUseOfTypeContextDescriptor(baseClass, DontRequireMetadata);
15551556
auto baseClassEntity = LinkEntity::forNominalTypeDescriptor(baseClass);
15561557
auto baseClassDescriptor =
1557-
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
1558-
baseClassEntity, IGM.getPointerAlignment(),
1559-
IGM.Int8Ty);
1558+
IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseClassEntity);
15601559
descriptor.addRelativeAddress(baseClassDescriptor);
15611560

15621561
// The base method.
15631562
auto baseMethodEntity = LinkEntity::forMethodDescriptor(baseRef);
15641563
auto baseMethodDescriptor =
1565-
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
1566-
baseMethodEntity, Alignment(4),
1567-
IGM.MethodDescriptorStructTy);
1564+
IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseMethodEntity);
15681565
descriptor.addRelativeAddress(baseMethodDescriptor);
15691566

15701567
// The implementation of the override.
@@ -1714,9 +1711,8 @@ IRGenModule::getAddrOfSharedContextDescriptor(LinkEntity entity,
17141711
}
17151712
}
17161713

1717-
return getAddrOfLLVMVariable(entity, Alignment(4),
1714+
return getAddrOfLLVMVariable(entity,
17181715
definition,
1719-
TypeContextDescriptorTy,
17201716
DebugTypeInfo());
17211717
}
17221718

lib/IRGen/GenProto.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,8 +2046,7 @@ namespace {
20462046
// Relative reference to the protocol descriptor.
20472047
auto protocol = Conformance->getProtocol();
20482048
auto descriptorRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2049-
LinkEntity::forProtocolDescriptor(protocol),
2050-
IGM.getPointerAlignment(), IGM.ProtocolDescriptorStructTy);
2049+
LinkEntity::forProtocolDescriptor(protocol));
20512050
B.addRelativeAddress(descriptorRef);
20522051
}
20532052

@@ -2143,8 +2142,7 @@ namespace {
21432142
auto assocType = entry.getAssociatedTypeWitness().Requirement;
21442143
auto assocTypeDescriptor =
21452144
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2146-
LinkEntity::forAssociatedTypeDescriptor(assocType),
2147-
Alignment(4), IGM.ProtocolRequirementStructTy);
2145+
LinkEntity::forAssociatedTypeDescriptor(assocType));
21482146
B.addRelativeAddress(assocTypeDescriptor);
21492147
} else if (entry.getKind() == SILWitnessTable::AssociatedTypeProtocol) {
21502148
// Associated conformance descriptor.
@@ -2156,16 +2154,14 @@ namespace {
21562154
witness.Protocol);
21572155
auto assocConformanceDescriptor =
21582156
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2159-
LinkEntity::forAssociatedConformanceDescriptor(requirement),
2160-
Alignment(4), IGM.ProtocolRequirementStructTy);
2157+
LinkEntity::forAssociatedConformanceDescriptor(requirement));
21612158
B.addRelativeAddress(assocConformanceDescriptor);
21622159
} else if (entry.getKind() == SILWitnessTable::Method) {
21632160
// Method descriptor.
21642161
auto declRef = entry.getMethodWitness().Requirement;
21652162
auto requirement =
21662163
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2167-
LinkEntity::forMethodDescriptor(declRef),
2168-
Alignment(4), IGM.ProtocolRequirementStructTy);
2164+
LinkEntity::forMethodDescriptor(declRef));
21692165
B.addRelativeAddress(requirement);
21702166
} else {
21712167
// 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
@@ -1321,7 +1321,8 @@ private: \
13211321
ForDefinition_t forDefinition);
13221322
llvm::Constant *getAddrOfWitnessTable(const NormalProtocolConformance *C,
13231323
ConstantInit definition = ConstantInit());
1324-
llvm::Constant *getAddrOfWitnessTablePattern(const NormalProtocolConformance *C,
1324+
llvm::Constant *getAddrOfWitnessTablePattern(
1325+
const NormalProtocolConformance *C,
13251326
ConstantInit definition = ConstantInit());
13261327

13271328
llvm::Function *
@@ -1341,8 +1342,7 @@ private: \
13411342
GenericEnvironment *getGenericEnvironment();
13421343

13431344
ConstantReference
1344-
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity, Alignment alignment,
1345-
llvm::Type *defaultType,
1345+
getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
13461346
ConstantReference::Directness forceIndirect = ConstantReference::Direct);
13471347

13481348
llvm::Constant *
@@ -1376,21 +1376,17 @@ private: \
13761376
llvm::function_ref<void()> emit);
13771377

13781378
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
1379-
Alignment alignment,
13801379
ConstantInit definition,
1381-
llvm::Type *defaultType,
1382-
DebugTypeInfo debugType);
1380+
DebugTypeInfo debugType,
1381+
llvm::Type *overrideDeclType = nullptr);
13831382
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
1384-
Alignment alignment,
13851383
ForDefinition_t forDefinition,
1386-
llvm::Type *defaultType,
13871384
DebugTypeInfo debugType);
13881385
ConstantReference getAddrOfLLVMVariable(LinkEntity entity,
1389-
Alignment alignment,
13901386
ConstantInit definition,
1391-
llvm::Type *defaultType,
13921387
DebugTypeInfo debugType,
1393-
SymbolReferenceKind refKind);
1388+
SymbolReferenceKind refKind,
1389+
llvm::Type *overrideDeclType = nullptr);
13941390

13951391
void emitLazyPrivateDefinitions();
13961392
void addRuntimeResolvableType(NominalTypeDecl *nominal);

lib/IRGen/Linking.cpp

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

0 commit comments

Comments
 (0)