Skip to content

Commit ed93b46

Browse files
committed
[Embedded] Introduce DeferredCodeGen feature.
Introduce an experimental feature DeferredCodeGen, that defers the generation of LLVM IR (and therefore object code) for all entities within an Embedded Swift module unless they have explicitly requested to not be emitted into the client (e.g., with `@_neverEmitIntoClient`). This feature is meant to generalize and subsume -emit-empty-object-file, relying on lazy emission of entities rather than abruptly ending the compilation pipeline before emitting any IR. Part of rdar://158363967.
1 parent 4f010f0 commit ed93b46

File tree

16 files changed

+97
-24
lines changed

16 files changed

+97
-24
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
752752
HasAnyUnavailableDuringLoweringValues : 1
753753
);
754754

755-
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
755+
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
756756
/// If the module is compiled as static library.
757757
StaticLibrary : 1,
758758

@@ -821,7 +821,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
821821
SerializePackageEnabled : 1,
822822

823823
/// Whether this module has enabled strict memory safety checking.
824-
StrictMemorySafety : 1
824+
StrictMemorySafety : 1,
825+
826+
/// Whether this module uses deferred code generation in Embedded Swift.
827+
DeferredCodeGen : 1
825828
);
826829

827830
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,

include/swift/AST/Module.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ class ModuleDecl
818818
Bits.ModuleDecl.IsConcurrencyChecked = value;
819819
}
820820

821-
/// Whether this module has enable strict memory safety checking.
821+
/// Whether this module has enabled strict memory safety checking.
822822
bool strictMemorySafety() const {
823823
return Bits.ModuleDecl.StrictMemorySafety;
824824
}
@@ -827,6 +827,15 @@ class ModuleDecl
827827
Bits.ModuleDecl.StrictMemorySafety = value;
828828
}
829829

830+
/// Whether this module uses deferred code generation.
831+
bool deferredCodeGen() const {
832+
return Bits.ModuleDecl.DeferredCodeGen;
833+
}
834+
835+
void setDeferredCodeGen(bool value = true) {
836+
Bits.ModuleDecl.DeferredCodeGen = value;
837+
}
838+
830839
bool isObjCNameLookupCachePopulated() const {
831840
return Bits.ModuleDecl.ObjCNameLookupCachePopulated;
832841
}

include/swift/Basic/Features.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ EXPERIMENTAL_FEATURE(KeyPathWithMethodMembers, false)
324324
// Whether to enable @_used and @_section attributes
325325
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
326326

327+
// Whether to emit an Embedded Swift module with "deferred" code generation,
328+
// meaning that the only code that will be emitted into the object file is
329+
// code that was marked as "never emit into client". For everything else,
330+
// Swift still store the SIL and emit it into the client only when used.
331+
EXPERIMENTAL_FEATURE(DeferredCodeGen, true)
332+
327333
// Whether to compile scripts lazily in immediate mode
328334
EXPERIMENTAL_FEATURE(LazyImmediate, false)
329335

include/swift/Serialization/Validation.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class ExtendedValidationInfo {
147147
unsigned AllowNonResilientAccess: 1;
148148
unsigned SerializePackageEnabled: 1;
149149
unsigned StrictMemorySafety: 1;
150+
unsigned DeferredCodeGen: 1;
150151
} Bits;
151152

152153
public:
@@ -251,7 +252,14 @@ class ExtendedValidationInfo {
251252
void setStrictMemorySafety(bool val = true) {
252253
Bits.StrictMemorySafety = val;
253254
}
254-
255+
256+
bool deferredCodeGen() const {
257+
return Bits.DeferredCodeGen;
258+
}
259+
void setDeferredCodeGen(bool val = true) {
260+
Bits.DeferredCodeGen = val;
261+
}
262+
255263
bool hasCxxInteroperability() const { return Bits.HasCxxInteroperability; }
256264
void setHasCxxInteroperability(bool val) {
257265
Bits.HasCxxInteroperability = val;

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ UNINTERESTING_FEATURE(CodeItemMacros)
8484
UNINTERESTING_FEATURE(PreambleMacros)
8585
UNINTERESTING_FEATURE(TupleConformances)
8686
UNINTERESTING_FEATURE(SymbolLinkageMarkers)
87+
UNINTERESTING_FEATURE(DeferredCodeGen)
8788
UNINTERESTING_FEATURE(LazyImmediate)
8889
UNINTERESTING_FEATURE(MoveOnlyClasses)
8990
UNINTERESTING_FEATURE(NoImplicitCopy)

lib/AST/Module.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx,
784784
Bits.ModuleDecl.AllowNonResilientAccess = 0;
785785
Bits.ModuleDecl.SerializePackageEnabled = 0;
786786
Bits.ModuleDecl.StrictMemorySafety = 0;
787+
Bits.ModuleDecl.DeferredCodeGen = 0;
787788

788789
// Populate the module's files.
789790
SmallVector<FileUnit *, 2> files;

lib/Frontend/Frontend.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,9 @@ ModuleDecl *CompilerInstance::getMainModule() const {
15111511
MainModule->setSerializePackageEnabled();
15121512
if (Invocation.getLangOptions().hasFeature(Feature::StrictMemorySafety))
15131513
MainModule->setStrictMemorySafety(true);
1514+
if (Invocation.getLangOptions().hasFeature(Feature::Embedded) &&
1515+
Invocation.getLangOptions().hasFeature(Feature::DeferredCodeGen))
1516+
MainModule->setDeferredCodeGen(true);
15141517

15151518
configureAvailabilityDomains(getASTContext(),
15161519
Invocation.getFrontendOptions(), MainModule);

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,10 +1112,20 @@ bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) {
11121112
if (decl->isNeverEmittedIntoClient())
11131113
return false;
11141114

1115-
// If the declaration is not from the main module, treat its definition as
1116-
// non-unique.
1115+
/// @_alwaysEmitIntoClient means that we have a non-unique definition.
1116+
if (decl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
1117+
return true;
1118+
11171119
auto module = decl->getModuleContext();
11181120
auto &ctx = module->getASTContext();
1121+
1122+
/// With deferred code generation, declarations are emitted as late as
1123+
/// possible, so they must have non-unique definitions.
1124+
if (module->deferredCodeGen())
1125+
return true;
1126+
1127+
// If the declaration is not from the main module, treat its definition as
1128+
// non-unique.
11191129
return module != ctx.MainModule && ctx.MainModule;
11201130
}
11211131

lib/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,9 @@ class ModuleFile
710710
/// \c true if this module was built with strict memory safety.
711711
bool strictMemorySafety() const { return Core->strictMemorySafety(); }
712712

713+
/// \c true if this module uses deferred code generation.
714+
bool deferredCodeGen() const { return Core->deferredCodeGen(); }
715+
713716
/// Associates this module file with the AST node representing it.
714717
///
715718
/// Checks that the file is compatible with the AST module it's being loaded

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor,
226226
case options_block::STRICT_MEMORY_SAFETY:
227227
extendedInfo.setStrictMemorySafety(true);
228228
break;
229+
case options_block::DEFERRED_CODE_GEN:
230+
extendedInfo.setDeferredCodeGen(true);
231+
break;
229232
default:
230233
// Unknown options record, possibly for use by a future version of the
231234
// module format.
@@ -1520,6 +1523,7 @@ ModuleFileSharedCore::ModuleFileSharedCore(
15201523
Bits.AllowNonResilientAccess = extInfo.allowNonResilientAccess();
15211524
Bits.SerializePackageEnabled = extInfo.serializePackageEnabled();
15221525
Bits.StrictMemorySafety = extInfo.strictMemorySafety();
1526+
Bits.DeferredCodeGen = extInfo.deferredCodeGen();
15231527
MiscVersion = info.miscVersion;
15241528
SDKVersion = info.sdkVersion;
15251529
ModuleABIName = extInfo.getModuleABIName();

0 commit comments

Comments
 (0)