@@ -428,7 +428,6 @@ class PrettySourceFileEmission : public llvm::PrettyStackTraceEntry {
428
428
// / Emit all the top-level code in the source file.
429
429
void IRGenModule::emitSourceFile (SourceFile &SF) {
430
430
PrettySourceFileEmission StackEntry (SF);
431
- llvm::SaveAndRestore<SourceFile *> SetCurSourceFile (CurSourceFile, &SF);
432
431
433
432
// Emit types and other global decls.
434
433
for (auto *decl : SF.getTopLevelDecls ())
@@ -764,19 +763,9 @@ IRGenModule::getAddrOfContextDescriptorForParent(DeclContext *parent,
764
763
// descriptor, so we'll just emit an extension context.
765
764
auto clas = dyn_cast<ClassDecl>(nominal);
766
765
if (!clas || clas->isForeign () || hasKnownSwiftMetadata (*this , clas)) {
767
- // Some targets don't support relative references to undefined symbols.
768
- // If the extension is in a different file from the original type
769
- // declaration, it may not get emitted in this TU. Use an indirect
770
- // reference to work around the object format limitation.
771
- auto shouldBeIndirect =
772
- parent->getModuleScopeContext () != ofChild->getModuleScopeContext ()
773
- ? ConstantReference::Indirect
774
- : ConstantReference::Direct;
775
-
776
766
IRGen.noteUseOfTypeContextDescriptor (nominal, DontRequireMetadata);
777
767
return getAddrOfLLVMVariableOrGOTEquivalent (
778
- LinkEntity::forNominalTypeDescriptor (nominal),
779
- shouldBeIndirect);
768
+ LinkEntity::forNominalTypeDescriptor (nominal));
780
769
}
781
770
}
782
771
return {getAddrOfExtensionContextDescriptor (ext),
@@ -2695,6 +2684,9 @@ llvm::Constant *IRGenModule::getOrCreateGOTEquivalent(llvm::Constant *global,
2695
2684
return gotEntry;
2696
2685
}
2697
2686
2687
+ if (Context.Stats )
2688
+ Context.Stats ->getFrontendCounters ().NumGOTEntries ++;
2689
+
2698
2690
// Use the global as the initializer for an anonymous constant. LLVM can treat
2699
2691
// this as equivalent to the global's GOT entry.
2700
2692
auto gotEquivalent = createGOTEquivalent (*this , global, entity);
@@ -2867,16 +2859,19 @@ IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
2867
2859
// / global variable. LLVM can replace relative references to this variable with
2868
2860
// / relative references to the GOT entry for the variable in the object file.
2869
2861
ConstantReference
2870
- IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent (LinkEntity entity,
2871
- ConstantReference::Directness forceIndirectness) {
2862
+ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent (LinkEntity entity) {
2863
+ auto canDirectlyReferenceSILFunction = [&](SILFunction *silFn) {
2864
+ return (silFn->isDefinition () &&
2865
+ !isAvailableExternally (silFn->getLinkage ()) &&
2866
+ this == IRGen.getGenModule (silFn));
2867
+ };
2868
+
2872
2869
// Handle SILFunctions specially, because unlike other entities they aren't
2873
2870
// variables and aren't kept in the GlobalVars table.
2874
2871
if (entity.isSILFunction ()) {
2875
2872
auto *silFn = entity.getSILFunction ();
2876
2873
auto fn = getAddrOfSILFunction (silFn, NotForDefinition);
2877
- if (silFn->isDefinition () &&
2878
- !isAvailableExternally (silFn->getLinkage ()) &&
2879
- this == IRGen.getGenModule (silFn)) {
2874
+ if (canDirectlyReferenceSILFunction (silFn)) {
2880
2875
return {fn, ConstantReference::Direct};
2881
2876
}
2882
2877
@@ -2896,22 +2891,6 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
2896
2891
// Ensure the variable is at least forward-declared.
2897
2892
getAddrOfLLVMVariable (entity, ConstantInit (), DebugTypeInfo ());
2898
2893
2899
- // Guess whether a global entry is a definition from this TU. This isn't
2900
- // bulletproof, but at the point we emit conformance tables, we're far enough
2901
- // along that we should have emitted any metadata objects we were going to.
2902
- auto isDefinition = [&](llvm::Constant *global) -> bool {
2903
- // We only emit aliases for definitions. (An extern alias would be an
2904
- // extern global.)
2905
- if (isa<llvm::GlobalAlias>(global))
2906
- return true ;
2907
- // Global vars are definitions if they have an initializer.
2908
- if (auto var = dyn_cast<llvm::GlobalVariable>(global))
2909
- return var->hasInitializer ();
2910
- // Assume anything else isn't a definition.
2911
- return false ;
2912
- };
2913
-
2914
- //
2915
2894
auto entry = GlobalVars[entity];
2916
2895
2917
2896
// / Returns a direct reference.
@@ -2931,43 +2910,64 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
2931
2910
return {gotEquivalent, ConstantReference::Indirect};
2932
2911
};
2933
2912
2934
- // Return the GOT entry if we were asked to.
2935
- if (forceIndirectness == ConstantReference::Indirect)
2936
- return indirect ();
2937
-
2938
2913
// The integrated REPL incrementally adds new definitions, so always use
2939
2914
// indirect references in this mode.
2940
2915
if (IRGen.Opts .IntegratedREPL )
2941
2916
return indirect ();
2942
2917
2943
- // Nominal type descriptors are only emitted once and can only be
2944
- // referenced directly from the same TU.
2945
- if (entity.isNominalTypeDescriptor ()) {
2946
- auto *dc = entity.getDecl ()->getDeclContext ();
2947
- if (isa<ClangModuleUnit>(dc->getModuleScopeContext ()) &&
2948
- this != IRGen.getGenModule (dc))
2949
- return indirect ();
2950
- }
2918
+ // Dynamically replaceable function keys are stored in the GlobalVars
2919
+ // table, but they don't have an associated Decl, so they require
2920
+ // special treatment here.
2921
+ if (entity.isDynamicallyReplaceableFunctionKey ()) {
2922
+ auto *silFn = entity.getSILFunction ();
2923
+ if (canDirectlyReferenceSILFunction (silFn))
2924
+ return direct ();
2951
2925
2952
- // If the variable has already been defined in this TU,
2953
- // then it definitely doesn't need a GOT entry, and we can
2954
- // relative-reference it directly.
2955
- if (!entity.isAvailableExternally (*this ) || isDefinition (entry)) {
2956
- return direct ();
2926
+ return indirect ();
2957
2927
}
2958
2928
2959
- // If the entity will be emitted as part of the current source file
2960
- // (if we know what that is), then we can reference it directly.
2961
- if (CurSourceFile
2962
- && !isa<ClangModuleUnit>(CurSourceFile)
2963
- && CurSourceFile == entity.getSourceFileForEmission ())
2964
- return direct ();
2965
-
2966
- // TODO: If we know the target entry is going to be linked into the same
2967
- // binary, then we ought to be able to directly relative-reference the
2968
- // symbol. However, some platforms don't have the necessary relocations to
2969
- // represent a relative reference to an undefined symbol, so conservatively
2970
- // produce an indirect reference in this case.
2929
+ if (auto *entityDC = entity.getDeclContextForEmission ()) {
2930
+ auto *entitySF = entityDC->getModuleScopeContext ();
2931
+ bool clangImportedEntity = isa<ClangModuleUnit>(entitySF);
2932
+
2933
+ auto &mod = getSILModule ();
2934
+
2935
+ if (!mod.isWholeModule ()) {
2936
+ // In non-WMO builds, the associated context of the SILModule must
2937
+ // be a source file. Every source file is its own translation unit.
2938
+ auto *modDC = mod.getAssociatedContext ();
2939
+ auto *modSF = modDC->getModuleScopeContext ();
2940
+ assert (modSF != nullptr );
2941
+
2942
+ // Imported entities are in a different Swift module, but are emitted
2943
+ // on demand and can be referenced directly. Entities in the same
2944
+ // source file can also be referenced directly.
2945
+ if (clangImportedEntity ||
2946
+ modSF == entitySF)
2947
+ return direct ();
2948
+
2949
+ // Everything else must be referenced indirectly.
2950
+ return indirect ();
2951
+ }
2952
+
2953
+ // We're performing a WMO build.
2954
+ //
2955
+ // The associated context of the SILModule is the entire AST ModuleDecl,
2956
+ // but we might be doing a multi-threaded IRGen build, in which case
2957
+ // there is one translation unit per source file.
2958
+
2959
+ // Imported entities are in a different Swift module and are emitted
2960
+ // on demand. In multi-threaded builds, they will be emitted into one
2961
+ // translation unit only.
2962
+ if (clangImportedEntity ||
2963
+ entitySF->getParentModule () == mod.getSwiftModule ()) {
2964
+ // If we're doing a single-threaded WMO build, or if the entity is
2965
+ // scheduled to be emitted in the same translation unit, reference
2966
+ // it directly.
2967
+ if (this == IRGen.getGenModule (entitySF))
2968
+ return direct ();
2969
+ }
2970
+ }
2971
2971
2972
2972
// Fall back to an indirect reference if we can't establish that a direct
2973
2973
// reference is OK.
0 commit comments