Skip to content

Commit 241559d

Browse files
committed
[Serialization] Add an option to output modules regardless of errors
Adds a new frontend option "-experimental-allow-module-with-compiler-errors". If any compilation errors occur while generating the .swiftmodule, this mode will skip SIL entirely and only serialize the (likey invalid) AST. This existence of this option during generation is serialized into the resulting .swiftmodule. Errors found in deserialization are only allowed if it is set. Primarily intended for IDE requests (eg. indexing and code completion) to ensure robust cross-module results, despite possible errors. Resolves rdar://69815975
1 parent b714a31 commit 241559d

21 files changed

+386
-22
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ namespace swift {
367367
/// TODO: remove this when @_implementationOnly modules are robust enough.
368368
bool AllowDeserializingImplementationOnly = false;
369369

370+
// Allow errors during module generation. See corresponding option in
371+
// FrontendOptions.
372+
bool AllowModuleWithCompilerErrors = false;
373+
370374
/// Sets the target we are building for and updates platform conditions
371375
/// to match.
372376
///

include/swift/Frontend/FrontendOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ class FrontendOptions {
289289
/// any merge-modules jobs.
290290
bool EnableExperimentalCrossModuleIncrementalBuild = false;
291291

292+
/// Best effort to output a .swiftmodule regardless of any compilation
293+
/// errors. SIL generation and serialization is skipped entirely when there
294+
/// are errors. The resulting serialized AST may include errors types and
295+
/// skip nodes entirely, depending on the errors involved.
296+
bool AllowModuleWithCompilerErrors = false;
297+
292298
/// The different modes for validating TBD against the LLVM IR.
293299
enum class TBDValidationMode {
294300
Default, ///< Do the default validation for the current platform.

include/swift/Option/FrontendOptions.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,4 +779,9 @@ def experimental_skip_all_function_bodies:
779779
Flag<["-"], "experimental-skip-all-function-bodies">,
780780
HelpText<"Skip type-checking function bodies and all SIL generation">;
781781

782+
def experimental_allow_module_with_compiler_errors:
783+
Flag<["-"], "experimental-allow-module-with-compiler-errors">,
784+
Flags<[HelpHidden]>,
785+
HelpText<"Attempt to output .swiftmodule, regardless of compilation errors">;
786+
782787
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

include/swift/Serialization/Validation.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ class ExtendedValidationInfo {
9898
unsigned IsSIB : 1;
9999
unsigned IsTestable : 1;
100100
unsigned ResilienceStrategy : 2;
101-
unsigned IsImplicitDynamicEnabled: 1;
101+
unsigned IsImplicitDynamicEnabled : 1;
102+
unsigned IsAllowModuleWithCompilerErrorsEnabled : 1;
102103
} Bits;
103104
public:
104105
ExtendedValidationInfo() : Bits() {}
@@ -138,6 +139,12 @@ class ExtendedValidationInfo {
138139
void setResilienceStrategy(ResilienceStrategy resilience) {
139140
Bits.ResilienceStrategy = unsigned(resilience);
140141
}
142+
bool isAllowModuleWithCompilerErrorsEnabled() {
143+
return Bits.IsAllowModuleWithCompilerErrorsEnabled;
144+
}
145+
void setAllowModuleWithCompilerErrorsEnabled(bool val) {
146+
Bits.IsAllowModuleWithCompilerErrorsEnabled = val;
147+
}
141148
};
142149

143150
/// Returns info about the serialized AST in the given data.

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ bool ArgsToFrontendOptionsConverter::convert(
214214
Opts.EnableIncrementalDependencyVerifier |= Args.hasArg(OPT_verify_incremental_dependencies);
215215
Opts.UseSharedResourceFolder = !Args.hasArg(OPT_use_static_resource_dir);
216216
Opts.DisableBuildingInterface = Args.hasArg(OPT_disable_building_interface);
217+
Opts.AllowModuleWithCompilerErrors = Args.hasArg(OPT_experimental_allow_module_with_compiler_errors);
217218

218219
computeImportObjCHeaderOptions();
219220
computeImplicitImportModuleNames(OPT_import_module, /*isTestable=*/false);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
683683
Opts.DisableAvailabilityChecking = true;
684684
}
685685

686+
if (FrontendOpts.AllowModuleWithCompilerErrors) {
687+
Opts.AllowModuleWithCompilerErrors = true;
688+
}
689+
686690
return HadError || UnsupportedOS || UnsupportedArch;
687691
}
688692

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,8 @@ static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
11421142
}
11431143

11441144
bool CompilerInstance::performSILProcessing(SILModule *silModule) {
1145-
if (performMandatorySILPasses(Invocation, silModule))
1145+
if (performMandatorySILPasses(Invocation, silModule) &&
1146+
!Invocation.getFrontendOptions().AllowModuleWithCompilerErrors)
11461147
return true;
11471148

11481149
{

lib/FrontendTool/FrontendTool.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,11 +1786,13 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) {
17861786
assert(ctx.getLoadedModules().begin()->second == Instance.getMainModule());
17871787
}
17881788

1789-
// Verify the AST for all the modules we've loaded.
1790-
ctx.verifyAllLoadedModules();
1789+
if (!opts.AllowModuleWithCompilerErrors) {
1790+
// Verify the AST for all the modules we've loaded.
1791+
ctx.verifyAllLoadedModules();
17911792

1792-
// Verify generic signatures if we've been asked to.
1793-
verifyGenericSignaturesIfNeeded(Invocation, ctx);
1793+
// Verify generic signatures if we've been asked to.
1794+
verifyGenericSignaturesIfNeeded(Invocation, ctx);
1795+
}
17941796

17951797
// Emit any additional outputs that we only need for a successful compilation.
17961798
// We don't want to unnecessarily delay getting any errors back to the user.
@@ -1867,7 +1869,8 @@ withSemanticAnalysis(CompilerInstance &Instance, FrontendObserver *observer,
18671869

18681870
(void)migrator::updateCodeAndEmitRemapIfNeeded(&Instance);
18691871

1870-
if (Instance.getASTContext().hadError())
1872+
if (Instance.getASTContext().hadError() &&
1873+
!opts.AllowModuleWithCompilerErrors)
18711874
return true;
18721875

18731876
return cont(Instance);
@@ -2048,7 +2051,8 @@ static bool performCompile(CompilerInstance &Instance,
20482051
if (Instance.hasASTContext() &&
20492052
FrontendOptions::doesActionPerformEndOfPipelineActions(Action)) {
20502053
performEndOfPipelineActions(Instance);
2051-
hadError |= Instance.getASTContext().hadError();
2054+
if (!opts.AllowModuleWithCompilerErrors)
2055+
hadError |= Instance.getASTContext().hadError();
20522056
}
20532057
return hadError;
20542058
}
@@ -2334,7 +2338,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
23342338
if (PSPs.haveModuleOrModuleDocOutputPaths()) {
23352339
if (Action == FrontendOptions::ActionType::MergeModules ||
23362340
Action == FrontendOptions::ActionType::EmitModuleOnly) {
2337-
return Context.hadError();
2341+
return Context.hadError() && !opts.AllowModuleWithCompilerErrors;
23382342
}
23392343
}
23402344

@@ -2352,7 +2356,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
23522356

23532357
// Check if we had any errors; if we did, don't proceed to IRGen.
23542358
if (Context.hadError())
2355-
return true;
2359+
return !opts.AllowModuleWithCompilerErrors;
23562360

23572361
runSILLoweringPasses(*SM);
23582362

lib/SILGen/SILGen.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,11 @@ ASTLoweringRequest::evaluate(Evaluator &evaluator,
19521952
if (desc.opts.SkipFunctionBodies == FunctionBodySkipping::All)
19531953
return silMod;
19541954

1955+
// Skip emitting SIL if there's been any compilation errors
1956+
if (silMod->getASTContext().hadError() &&
1957+
silMod->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
1958+
return silMod;
1959+
19551960
SILGenModuleRAII scope(*silMod);
19561961

19571962
// Emit a specific set of SILDeclRefs if needed.

lib/Sema/TypeCheckStorage.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,6 +2308,8 @@ IsAccessorTransparentRequest::evaluate(Evaluator &evaluator,
23082308
// Anything else should not have a synthesized setter.
23092309
LLVM_FALLTHROUGH;
23102310
case WriteImplKind::Immutable:
2311+
if (accessor->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
2312+
return false;
23112313
llvm_unreachable("should not be synthesizing accessor in this case");
23122314

23132315
case WriteImplKind::StoredWithObservers:

0 commit comments

Comments
 (0)