@@ -2861,14 +2861,18 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
2861
2861
// / relative references to the GOT entry for the variable in the object file.
2862
2862
ConstantReference
2863
2863
IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent (LinkEntity entity) {
2864
+ auto canDirectlyReferenceSILFunction = [&](SILFunction *silFn) {
2865
+ return (silFn->isDefinition () &&
2866
+ !isAvailableExternally (silFn->getLinkage ()) &&
2867
+ this == IRGen.getGenModule (silFn));
2868
+ };
2869
+
2864
2870
// Handle SILFunctions specially, because unlike other entities they aren't
2865
2871
// variables and aren't kept in the GlobalVars table.
2866
2872
if (entity.isSILFunction ()) {
2867
2873
auto *silFn = entity.getSILFunction ();
2868
2874
auto fn = getAddrOfSILFunction (silFn, NotForDefinition);
2869
- if (silFn->isDefinition () &&
2870
- !isAvailableExternally (silFn->getLinkage ()) &&
2871
- this == IRGen.getGenModule (silFn)) {
2875
+ if (canDirectlyReferenceSILFunction (silFn)) {
2872
2876
return {fn, ConstantReference::Direct};
2873
2877
}
2874
2878
@@ -2888,22 +2892,6 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity) {
2888
2892
// Ensure the variable is at least forward-declared.
2889
2893
getAddrOfLLVMVariable (entity, ConstantInit (), DebugTypeInfo ());
2890
2894
2891
- // Guess whether a global entry is a definition from this TU. This isn't
2892
- // bulletproof, but at the point we emit conformance tables, we're far enough
2893
- // along that we should have emitted any metadata objects we were going to.
2894
- auto isDefinition = [&](llvm::Constant *global) -> bool {
2895
- // We only emit aliases for definitions. (An extern alias would be an
2896
- // extern global.)
2897
- if (isa<llvm::GlobalAlias>(global))
2898
- return true ;
2899
- // Global vars are definitions if they have an initializer.
2900
- if (auto var = dyn_cast<llvm::GlobalVariable>(global))
2901
- return var->hasInitializer ();
2902
- // Assume anything else isn't a definition.
2903
- return false ;
2904
- };
2905
-
2906
- //
2907
2895
auto entry = GlobalVars[entity];
2908
2896
2909
2897
// / Returns a direct reference.
@@ -2928,36 +2916,59 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity) {
2928
2916
if (IRGen.Opts .IntegratedREPL )
2929
2917
return indirect ();
2930
2918
2931
- // Nominal type descriptors are only emitted once and can only be
2932
- // referenced directly from the same TU.
2933
- if (entity.isNominalTypeDescriptor ()) {
2934
- auto *dc = entity.getDecl ()->getDeclContext ();
2935
- if (isa<ClangModuleUnit>(dc->getModuleScopeContext ()) &&
2936
- this != IRGen.getGenModule (dc))
2937
- return indirect ();
2938
- }
2919
+ // Dynamically replaceable function keys are stored in the GlobalVars
2920
+ // table, but they don't have an associated Decl, so they require
2921
+ // special treatment here.
2922
+ if (entity.isDynamicallyReplaceableFunctionKey ()) {
2923
+ auto *silFn = entity.getSILFunction ();
2924
+ if (canDirectlyReferenceSILFunction (silFn))
2925
+ return direct ();
2939
2926
2940
- // If the variable has already been defined in this TU,
2941
- // then it definitely doesn't need a GOT entry, and we can
2942
- // relative-reference it directly.
2943
- if (!entity.isAvailableExternally (*this ) || isDefinition (entry)) {
2944
- return direct ();
2927
+ return indirect ();
2945
2928
}
2946
2929
2947
- // If the entity will be emitted as part of the current source file
2948
- // (if we know what that is), then we can reference it directly.
2949
- if (CurSourceFile
2950
- && !isa<ClangModuleUnit>(CurSourceFile)) {
2951
- if (auto *dc = entity.getDeclContextForEmission ())
2952
- if (CurSourceFile == dc->getParentSourceFile ())
2930
+ if (auto *entityDC = entity.getDeclContextForEmission ()) {
2931
+ auto *entitySF = entityDC->getModuleScopeContext ();
2932
+ bool clangImportedEntity = isa<ClangModuleUnit>(entitySF);
2933
+
2934
+ auto &mod = getSILModule ();
2935
+
2936
+ if (!mod.isWholeModule ()) {
2937
+ // In non-WMO builds, the associated context of the SILModule must
2938
+ // be a source file. Every source file is its own translation unit.
2939
+ auto *modDC = mod.getAssociatedContext ();
2940
+ auto *modSF = modDC->getModuleScopeContext ();
2941
+ assert (modSF != nullptr );
2942
+
2943
+ // Imported entities are in a different Swift module, but are emitted
2944
+ // on demand and can be referenced directly. Entities in the same
2945
+ // source file can also be referenced directly.
2946
+ if (clangImportedEntity ||
2947
+ modSF == entitySF)
2948
+ return direct ();
2949
+
2950
+ // Everything else must be referenced indirectly.
2951
+ return indirect ();
2952
+ }
2953
+
2954
+ // We're performing a WMO build.
2955
+ //
2956
+ // The associated context of the SILModule is the entire AST ModuleDecl,
2957
+ // but we might be doing a multi-threaded IRGen build, in which case
2958
+ // there is one translation unit per source file.
2959
+
2960
+ // Imported entities are in a different Swift module and are emitted
2961
+ // on demand. In multi-threaded builds, they will be emitted into one
2962
+ // translation unit only.
2963
+ if (clangImportedEntity ||
2964
+ entitySF->getParentModule () == mod.getSwiftModule ()) {
2965
+ // If we're doing a single-threaded WMO build, or if the entity is
2966
+ // scheduled to be emitted in the same translation unit, reference
2967
+ // it directly.
2968
+ if (this == IRGen.getGenModule (entitySF))
2953
2969
return direct ();
2970
+ }
2954
2971
}
2955
-
2956
- // TODO: If we know the target entry is going to be linked into the same
2957
- // binary, then we ought to be able to directly relative-reference the
2958
- // symbol. However, some platforms don't have the necessary relocations to
2959
- // represent a relative reference to an undefined symbol, so conservatively
2960
- // produce an indirect reference in this case.
2961
2972
2962
2973
// Fall back to an indirect reference if we can't establish that a direct
2963
2974
// reference is OK.
0 commit comments