Skip to content

Commit b72b0c3

Browse files
authored
Merge pull request #34612 from xymus/dont-skip-nested-types
[Sema] Add flag to optimize building swiftmodule files preserving type info for LLDB
2 parents f9c2ad6 + 02c1343 commit b72b0c3

File tree

9 files changed

+157
-75
lines changed

9 files changed

+157
-75
lines changed

include/swift/AST/Decl.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ class alignas(1 << DeclAlignInBits) Decl {
391391
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
392392
StaticSpelling : 2
393393
);
394-
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1,
394+
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1+1,
395395
/// \see AbstractFunctionDecl::BodyKind
396396
BodyKind : 3,
397397

@@ -415,7 +415,11 @@ class alignas(1 << DeclAlignInBits) Decl {
415415
Synthesized : 1,
416416

417417
/// Whether this member's body consists of a single expression.
418-
HasSingleExpressionBody : 1
418+
HasSingleExpressionBody : 1,
419+
420+
/// Whether peeking into this function detected nested type declarations.
421+
/// This is set when skipping over the decl at parsing.
422+
HasNestedTypeDeclarations : 1
419423
);
420424

421425
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+1,
@@ -5544,6 +5548,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
55445548
Bits.AbstractFunctionDecl.Throws = Throws;
55455549
Bits.AbstractFunctionDecl.Synthesized = false;
55465550
Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
5551+
Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false;
55475552
}
55485553

55495554
void setBodyKind(BodyKind K) {
@@ -5690,6 +5695,16 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
56905695
setBody(S, BodyKind::Parsed);
56915696
}
56925697

5698+
/// Was there a nested type declaration detected when parsing this
5699+
/// function was skipped?
5700+
bool hasNestedTypeDeclarations() const {
5701+
return Bits.AbstractFunctionDecl.HasNestedTypeDeclarations;
5702+
}
5703+
5704+
void setHasNestedTypeDeclarations(bool value) {
5705+
Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = value;
5706+
}
5707+
56935708
/// Note that parsing for the body was delayed.
56945709
///
56955710
/// The function should return the body statement and a flag indicating

include/swift/Basic/FunctionBodySkipping.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ enum class FunctionBodySkipping : uint8_t {
2323
None,
2424
/// Only non-inlinable function bodies should be skipped.
2525
NonInlinable,
26+
/// Only non-inlinable functions bodies without type definitions should
27+
/// be skipped.
28+
NonInlinableWithoutTypes,
2629
/// All function bodies should be skipped, where not otherwise required
2730
/// for type inference.
2831
All

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ def experimental_skip_non_inlinable_function_bodies:
301301
Flag<["-"], "experimental-skip-non-inlinable-function-bodies">,
302302
Flags<[FrontendOption, HelpHidden]>,
303303
HelpText<"Skip type-checking and SIL generation for non-inlinable function bodies">;
304+
def experimental_skip_non_inlinable_function_bodies_without_types:
305+
Flag<["-"], "experimental-skip-non-inlinable-function-bodies-without-types">,
306+
Flags<[FrontendOption, HelpHidden]>,
307+
HelpText<"Skip work on non-inlinable function bodies that do not declare nested types">;
304308
def profile_stats_events: Flag<["-"], "profile-stats-events">,
305309
Flags<[FrontendOption, HelpHidden]>,
306310
HelpText<"Profile changes to stats in -stats-output-dir">;

include/swift/Parse/Parser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,10 @@ class Parser {
687687

688688
/// Skip a braced block (e.g. function body). The current token must be '{'.
689689
/// Returns \c true if the parser hit the eof before finding matched '}'.
690-
bool skipBracedBlock();
690+
///
691+
/// Set \c HasNestedTypeDeclarations to true if a token for a type
692+
/// declaration is detected in the skipped block.
693+
bool skipBracedBlock(bool &HasNestedTypeDeclarations);
691694

692695
/// Skip over SIL decls until we encounter the start of a Swift decl or eof.
693696
void skipSILUntilSwiftDecl();

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ bool ArgsToFrontendOptionsConverter::convert(
195195

196196
if (FrontendOptions::doesActionGenerateIR(Opts.RequestedAction) &&
197197
(Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) ||
198-
Args.hasArg(OPT_experimental_skip_all_function_bodies))) {
198+
Args.hasArg(OPT_experimental_skip_all_function_bodies) ||
199+
Args.hasArg(
200+
OPT_experimental_skip_non_inlinable_function_bodies_without_types))) {
199201
Diags.diagnose(SourceLoc(), diag::cannot_emit_ir_skipping_function_bodies);
200202
return true;
201203
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,12 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
729729
Opts.DebugTimeExpressions |=
730730
Args.hasArg(OPT_debug_time_expression_type_checking);
731731

732+
// Check for SkipFunctionBodies arguments in order from skipping less to
733+
// skipping more.
734+
if (Args.hasArg(
735+
OPT_experimental_skip_non_inlinable_function_bodies_without_types))
736+
Opts.SkipFunctionBodies = FunctionBodySkipping::NonInlinableWithoutTypes;
737+
732738
// If asked to perform InstallAPI, go ahead and enable non-inlinable function
733739
// body skipping.
734740
if (Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies) ||

lib/Parse/ParseDecl.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3519,10 +3519,12 @@ static void diagnoseOperatorFixityAttributes(Parser &P,
35193519
static unsigned skipUntilMatchingRBrace(Parser &P,
35203520
bool &HasPoundDirective,
35213521
bool &HasOperatorDeclarations,
3522-
bool &HasNestedClassDeclarations) {
3522+
bool &HasNestedClassDeclarations,
3523+
bool &HasNestedTypeDeclarations) {
35233524
HasPoundDirective = false;
35243525
HasOperatorDeclarations = false;
35253526
HasNestedClassDeclarations = false;
3527+
HasNestedTypeDeclarations = false;
35263528

35273529
unsigned OpenBraces = 1;
35283530

@@ -3541,6 +3543,10 @@ static unsigned skipUntilMatchingRBrace(Parser &P,
35413543

35423544
HasPoundDirective |= P.Tok.isAny(tok::pound_sourceLocation, tok::pound_line,
35433545
tok::pound_if, tok::pound_else, tok::pound_endif, tok::pound_elseif);
3546+
3547+
HasNestedTypeDeclarations |= P.Tok.isAny(tok::kw_class, tok::kw_struct,
3548+
tok::kw_enum);
3549+
35443550
if (P.consumeIf(tok::l_brace)) {
35453551
++OpenBraces;
35463552
continue;
@@ -4819,10 +4825,12 @@ bool Parser::canDelayMemberDeclParsing(bool &HasOperatorDeclarations,
48194825
// we can't lazily parse.
48204826
BacktrackingScope BackTrack(*this);
48214827
bool HasPoundDirective;
4828+
bool HasNestedTypeDeclarations;
48224829
skipUntilMatchingRBrace(*this,
48234830
HasPoundDirective,
48244831
HasOperatorDeclarations,
4825-
HasNestedClassDeclarations);
4832+
HasNestedClassDeclarations,
4833+
HasNestedTypeDeclarations);
48264834
if (!HasPoundDirective)
48274835
BackTrack.cancelBacktrack();
48284836
return !BackTrack.willBacktrack();
@@ -5510,7 +5518,7 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
55105518
return ParameterList::create(P.Context, StartLoc, param, EndLoc);
55115519
}
55125520

5513-
bool Parser::skipBracedBlock() {
5521+
bool Parser::skipBracedBlock(bool &HasNestedTypeDeclarations) {
55145522
SyntaxParsingContext disabled(SyntaxContext);
55155523
SyntaxContext->disable();
55165524
consumeToken(tok::l_brace);
@@ -5524,7 +5532,8 @@ bool Parser::skipBracedBlock() {
55245532
unsigned OpenBraces = skipUntilMatchingRBrace(*this,
55255533
HasPoundDirectives,
55265534
HasOperatorDeclarations,
5527-
HasNestedClassDeclarations);
5535+
HasNestedClassDeclarations,
5536+
HasNestedTypeDeclarations);
55285537
if (consumeIf(tok::r_brace))
55295538
--OpenBraces;
55305539
return OpenBraces != 0;
@@ -6420,11 +6429,13 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
64206429
BodyRange.Start = Tok.getLoc();
64216430

64226431
// Advance the parser to the end of the block; '{' ... '}'.
6423-
skipBracedBlock();
6432+
bool HasNestedTypeDeclarations;
6433+
skipBracedBlock(HasNestedTypeDeclarations);
64246434

64256435
BodyRange.End = PreviousLoc;
64266436

64276437
AFD->setBodyDelayed(BodyRange);
6438+
AFD->setHasNestedTypeDeclarations(HasNestedTypeDeclarations);
64286439

64296440
if (isCodeCompletionFirstPass() &&
64306441
SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23512351
FunctionBodySkipping::All)
23522352
return true;
23532353

2354+
// If we want all types (for LLDB) we can't skip functions with nested
2355+
// types. We could probably improve upon this and type-check only the
2356+
// nested types instead for better performances.
2357+
if (AFD->hasNestedTypeDeclarations() &&
2358+
getASTContext().TypeCheckerOpts.SkipFunctionBodies ==
2359+
FunctionBodySkipping::NonInlinableWithoutTypes)
2360+
return false;
2361+
23542362
// Only skip functions where their body won't be serialized
23552363
return AFD->getResilienceExpansion() != ResilienceExpansion::Minimal;
23562364
}

0 commit comments

Comments
 (0)