Skip to content

Commit 71f3285

Browse files
author
Harlan Haskins
authored
Merge pull request swiftlang#20420 from harlanhaskins/thats-the-uhh-bodies
[Frontend] Add experimental flag to skip non-inlinable function bodies
2 parents 8a91e98 + b904133 commit 71f3285

23 files changed

+608
-87
lines changed

include/swift/AST/Decl.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5689,7 +5689,8 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
56895689
/// Note that a true return value does not imply that the body was actually
56905690
/// parsed.
56915691
bool hasBody() const {
5692-
return getBodyKind() != BodyKind::None;
5692+
return getBodyKind() != BodyKind::None &&
5693+
getBodyKind() != BodyKind::Skipped;
56935694
}
56945695

56955696
/// Returns true if the text of this function's body can be retrieved either
@@ -5716,14 +5717,22 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
57165717
/// Note that the body was skipped for this function. Function body
57175718
/// cannot be attached after this call.
57185719
void setBodySkipped(SourceRange bodyRange) {
5719-
assert(getBodyKind() == BodyKind::None);
5720+
// FIXME: Remove 'Parsed' from this once we can delay parsing function
5721+
// bodies. Right now -experimental-skip-non-inlinable-function-bodies
5722+
// requires being able to change the state from Parsed to Skipped,
5723+
// because we're still eagerly parsing function bodies.
5724+
assert(getBodyKind() == BodyKind::None ||
5725+
getBodyKind() == BodyKind::Unparsed ||
5726+
getBodyKind() == BodyKind::Parsed);
5727+
assert(bodyRange.isValid());
57205728
BodyRange = bodyRange;
57215729
setBodyKind(BodyKind::Skipped);
57225730
}
57235731

57245732
/// Note that parsing for the body was delayed.
57255733
void setBodyDelayed(SourceRange bodyRange) {
57265734
assert(getBodyKind() == BodyKind::None);
5735+
assert(bodyRange.isValid());
57275736
BodyRange = bodyRange;
57285737
setBodyKind(BodyKind::Unparsed);
57295738
}
@@ -5769,6 +5778,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
57695778
return getBodyKind() == BodyKind::TypeChecked;
57705779
}
57715780

5781+
bool isBodySkipped() const {
5782+
return getBodyKind() == BodyKind::Skipped;
5783+
}
5784+
57725785
bool isMemberwiseInitializer() const {
57735786
return getBodyKind() == BodyKind::MemberwiseInitializer;
57745787
}

include/swift/AST/DeclContext.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,15 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
409409
const_cast<DeclContext *>(this)->getInnermostDeclarationDeclContext();
410410
}
411411

412+
/// Returns the innermost context that is an AbstractFunctionDecl whose
413+
/// body has been skipped.
414+
LLVM_READONLY
415+
DeclContext *getInnermostSkippedFunctionContext();
416+
const DeclContext *getInnermostSkippedFunctionContext() const {
417+
return
418+
const_cast<DeclContext *>(this)->getInnermostSkippedFunctionContext();
419+
}
420+
412421
/// Returns the semantic parent of this context. A context has a
413422
/// parent if and only if it is not a module context.
414423
DeclContext *getParent() const {

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ ERROR(error_mode_cannot_emit_module_source_info,none,
128128
"this mode does not support emitting module source info files", ())
129129
ERROR(error_mode_cannot_emit_interface,none,
130130
"this mode does not support emitting module interface files", ())
131+
ERROR(cannot_emit_ir_skipping_function_bodies,none,
132+
"-experimental-skip-non-inlinable-function-bodies does not support "
133+
"emitting IR", ())
131134

132135
WARNING(emit_reference_dependencies_without_primary_file,none,
133136
"ignoring -emit-reference-dependencies (requires -primary-file)", ())

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ class SILOptions {
7070
/// Whether to stop the optimization pipeline after serializing SIL.
7171
bool StopOptimizationAfterSerialization = false;
7272

73+
/// Whether to skip emitting non-inlinable function bodies.
74+
bool SkipNonInlinableFunctionBodies = false;
75+
7376
/// Optimization mode being used.
7477
OptimizationMode OptMode = OptimizationMode::NotSet;
7578

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ class FrontendOptions {
180180
/// \sa swift::SharedTimer
181181
bool DebugTimeCompilation = false;
182182

183+
bool SkipNonInlinableFunctionBodies = false;
184+
183185
/// The path to which we should output statistics files.
184186
std::string StatsOutputDir;
185187

@@ -339,6 +341,7 @@ class FrontendOptions {
339341

340342
public:
341343
static bool doesActionGenerateSIL(ActionType);
344+
static bool doesActionGenerateIR(ActionType);
342345
static bool doesActionProduceOutput(ActionType);
343346
static bool doesActionProduceTextualOutput(ActionType);
344347
static bool needsProperModuleName(ActionType);

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ def stats_output_dir: Separate<["-"], "stats-output-dir">,
254254
def trace_stats_events: Flag<["-"], "trace-stats-events">,
255255
Flags<[FrontendOption, HelpHidden]>,
256256
HelpText<"Trace changes to stats in -stats-output-dir">;
257+
def experimental_skip_non_inlinable_function_bodies:
258+
Flag<["-"], "experimental-skip-non-inlinable-function-bodies">,
259+
Flags<[FrontendOption, HelpHidden]>,
260+
HelpText<"Skip type-checking and SIL generation for non-inlinable function bodies">;
257261
def profile_stats_events: Flag<["-"], "profile-stats-events">,
258262
Flags<[FrontendOption, HelpHidden]>,
259263
HelpText<"Profile changes to stats in -stats-output-dir">;

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ PASS(SimplifyUnreachableContainingBlocks, "simplify-unreachable-containing-block
311311
"Utility pass. Removes all non-term insts from blocks with unreachable terms")
312312
PASS(SerializeSILPass, "serialize-sil",
313313
"Utility pass. Serializes the current SILModule")
314+
PASS(NonInlinableFunctionSkippingChecker, "check-non-inlinable-function-skipping",
315+
"Utility pass to ensure -experimental-skip-non-inlinable-function-bodies "
316+
"skips everything it should")
314317
PASS(YieldOnceCheck, "yield-once-check",
315318
"Check correct usage of yields in yield-once coroutines")
316319
PASS(OSLogOptimization, "os-log-optimization", "Optimize os log calls")

include/swift/Subsystems.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ namespace swift {
187187
/// If set, dumps wall time taken to type check each expression to
188188
/// llvm::errs().
189189
DebugTimeExpressions = 1 << 3,
190+
191+
/// If set, the typechecker will skip typechecking non-inlinable function
192+
/// bodies. Set this if you're trying to quickly emit a module or module
193+
/// interface without a full compilation.
194+
SkipNonInlinableFunctionBodies = 1 << 4,
190195
};
191196

192197
/// Once parsing and name-binding are complete, this walks the AST to resolve

lib/AST/DeclContext.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,17 @@ Decl *DeclContext::getInnermostDeclarationDeclContext() {
231231
return nullptr;
232232
}
233233

234+
DeclContext *DeclContext::getInnermostSkippedFunctionContext() {
235+
auto dc = this;
236+
do {
237+
if (auto afd = dyn_cast<AbstractFunctionDecl>(dc))
238+
if (afd->isBodySkipped())
239+
return afd;
240+
} while ((dc = dc->getParent()));
241+
242+
return nullptr;
243+
}
244+
234245
DeclContext *DeclContext::getParentForLookup() const {
235246
if (isa<ProtocolDecl>(this) || isa<ExtensionDecl>(this)) {
236247
// If we are inside a protocol or an extension, skip directly

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,12 @@ bool ArgsToFrontendOptionsConverter::convert(
161161
if (checkUnusedSupplementaryOutputPaths())
162162
return true;
163163

164+
if (FrontendOptions::doesActionGenerateIR(Opts.RequestedAction)
165+
&& Opts.SkipNonInlinableFunctionBodies) {
166+
Diags.diagnose(SourceLoc(), diag::cannot_emit_ir_skipping_function_bodies);
167+
return true;
168+
}
169+
164170
if (const Arg *A = Args.getLastArg(OPT_module_link_name))
165171
Opts.ModuleLinkName = A->getValue();
166172

@@ -219,6 +225,8 @@ void ArgsToFrontendOptionsConverter::computeDebugTimeOptions() {
219225
Opts.DebugTimeExpressionTypeChecking |=
220226
Args.hasArg(OPT_debug_time_expression_type_checking);
221227
Opts.DebugTimeCompilation |= Args.hasArg(OPT_debug_time_compilation);
228+
Opts.SkipNonInlinableFunctionBodies |=
229+
Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies);
222230
if (const Arg *A = Args.getLastArg(OPT_stats_output_dir)) {
223231
Opts.StatsOutputDir = A->getValue();
224232
if (Args.getLastArg(OPT_trace_stats_events)) {

0 commit comments

Comments
 (0)