Skip to content

Commit b0577b0

Browse files
authored
Merge pull request #34472 from bnbarham/benb/allow-errors-69815975
[Serialization] Add an option to output modules regardless of errors
2 parents e201c73 + 241559d commit b0577b0

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
@@ -290,6 +290,12 @@ class FrontendOptions {
290290
/// any merge-modules jobs.
291291
bool EnableExperimentalCrossModuleIncrementalBuild = false;
292292

293+
/// Best effort to output a .swiftmodule regardless of any compilation
294+
/// errors. SIL generation and serialization is skipped entirely when there
295+
/// are errors. The resulting serialized AST may include errors types and
296+
/// skip nodes entirely, depending on the errors involved.
297+
bool AllowModuleWithCompilerErrors = false;
298+
293299
/// The different modes for validating TBD against the LLVM IR.
294300
enum class TBDValidationMode {
295301
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
@@ -1153,7 +1153,8 @@ static void countStatsPostSILOpt(UnifiedStatsReporter &Stats,
11531153
}
11541154

11551155
bool CompilerInstance::performSILProcessing(SILModule *silModule) {
1156-
if (performMandatorySILPasses(Invocation, silModule))
1156+
if (performMandatorySILPasses(Invocation, silModule) &&
1157+
!Invocation.getFrontendOptions().AllowModuleWithCompilerErrors)
11571158
return true;
11581159

11591160
{

lib/FrontendTool/FrontendTool.cpp

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

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

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

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

19141916
(void)migrator::updateCodeAndEmitRemapIfNeeded(&Instance);
19151917

1916-
if (Instance.getASTContext().hadError())
1918+
if (Instance.getASTContext().hadError() &&
1919+
!opts.AllowModuleWithCompilerErrors)
19171920
return true;
19181921

19191922
return cont(Instance);
@@ -2096,7 +2099,8 @@ static bool performCompile(CompilerInstance &Instance,
20962099
if (Instance.hasASTContext() &&
20972100
FrontendOptions::doesActionPerformEndOfPipelineActions(Action)) {
20982101
performEndOfPipelineActions(Instance);
2099-
hadError |= Instance.getASTContext().hadError();
2102+
if (!opts.AllowModuleWithCompilerErrors)
2103+
hadError |= Instance.getASTContext().hadError();
21002104
}
21012105
return hadError;
21022106
}
@@ -2382,7 +2386,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
23822386
if (PSPs.haveModuleOrModuleDocOutputPaths()) {
23832387
if (Action == FrontendOptions::ActionType::MergeModules ||
23842388
Action == FrontendOptions::ActionType::EmitModuleOnly) {
2385-
return Context.hadError();
2389+
return Context.hadError() && !opts.AllowModuleWithCompilerErrors;
23862390
}
23872391
}
23882392

@@ -2400,7 +2404,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
24002404

24012405
// Check if we had any errors; if we did, don't proceed to IRGen.
24022406
if (Context.hadError())
2403-
return true;
2407+
return !opts.AllowModuleWithCompilerErrors;
24042408

24052409
runSILLoweringPasses(*SM);
24062410

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:

lib/Serialization/DeclTypeRecordNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ TYPE(SIL_BLOCK_STORAGE)
109109
TYPE(SIL_BOX)
110110
TYPE(NAME_ALIAS)
111111

112+
TYPE(ERROR)
113+
112114
FIRST_DECL(TYPE_ALIAS, 60)
113115
DECL(GENERIC_TYPE_PARAM)
114116
DECL(ASSOCIATED_TYPE)

lib/Serialization/Deserialization.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,7 +2955,7 @@ class DeclDeserializer {
29552955
declOrOffset = param;
29562956

29572957
auto paramTy = MF.getType(interfaceTypeID);
2958-
if (paramTy->hasError()) {
2958+
if (paramTy->hasError() && !MF.isAllowModuleWithCompilerErrorsEnabled()) {
29592959
// FIXME: This should never happen, because we don't serialize
29602960
// error types.
29612961
DC->printContext(llvm::errs());
@@ -5670,6 +5670,23 @@ class TypeDeserializer {
56705670

56715671
return UnboundGenericType::get(genericDecl, parentTy, ctx);
56725672
}
5673+
5674+
Expected<Type> deserializeErrorType(ArrayRef<uint64_t> scratch,
5675+
StringRef blobData) {
5676+
if (!MF.isAllowModuleWithCompilerErrorsEnabled())
5677+
MF.fatal();
5678+
5679+
TypeID origID;
5680+
decls_block::ErrorTypeLayout::readRecord(scratch, origID);
5681+
5682+
auto origTy = MF.getTypeChecked(origID);
5683+
if (!origTy)
5684+
return origTy.takeError();
5685+
5686+
if (!origTy.get())
5687+
return ErrorType::get(ctx);
5688+
return ErrorType::get(origTy.get());
5689+
}
56735690
};
56745691
}
56755692

@@ -5693,7 +5710,8 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
56935710

56945711
#ifndef NDEBUG
56955712
PrettyStackTraceType trace(getContext(), "deserializing", typeOrOffset.get());
5696-
if (typeOrOffset.get()->hasError()) {
5713+
if (typeOrOffset.get()->hasError() &&
5714+
!isAllowModuleWithCompilerErrorsEnabled()) {
56975715
typeOrOffset.get()->dump(llvm::errs());
56985716
llvm_unreachable("deserialization produced an invalid type "
56995717
"(rdar://problem/30382791)");
@@ -5753,6 +5771,7 @@ Expected<Type> TypeDeserializer::getTypeCheckedImpl() {
57535771
CASE(Dictionary)
57545772
CASE(Optional)
57555773
CASE(UnboundGeneric)
5774+
CASE(Error)
57565775

57575776
#undef CASE
57585777

lib/Serialization/ModuleFile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ class ModuleFile
465465
return Core->Bits.IsImplicitDynamicEnabled;
466466
}
467467

468+
/// Whether this module is compiled while allowing errors
469+
/// ('-experimental-allow-module-with-compiler-errors').
470+
bool isAllowModuleWithCompilerErrorsEnabled() const {
471+
return Core->Bits.IsAllowModuleWithCompilerErrorsEnabled;
472+
}
473+
468474
/// \c true if this module has incremental dependency information.
469475
bool hasIncrementalInfo() const { return Core->hasIncrementalInfo(); }
470476

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor,
145145
options_block::ResilienceStrategyLayout::readRecord(scratch, Strategy);
146146
extendedInfo.setResilienceStrategy(ResilienceStrategy(Strategy));
147147
break;
148+
case options_block::IS_ALLOW_MODULE_WITH_COMPILER_ERRORS_ENABLED:
149+
extendedInfo.setAllowModuleWithCompilerErrorsEnabled(true);
150+
break;
148151
default:
149152
// Unknown options record, possibly for use by a future version of the
150153
// module format.
@@ -1150,6 +1153,8 @@ ModuleFileSharedCore::ModuleFileSharedCore(
11501153
Bits.IsTestable = extInfo.isTestable();
11511154
Bits.ResilienceStrategy = unsigned(extInfo.getResilienceStrategy());
11521155
Bits.IsImplicitDynamicEnabled = extInfo.isImplicitDynamicEnabled();
1156+
Bits.IsAllowModuleWithCompilerErrorsEnabled =
1157+
extInfo.isAllowModuleWithCompilerErrorsEnabled();
11531158
MiscVersion = info.miscVersion;
11541159

11551160
hasValidControlBlock = true;

lib/Serialization/ModuleFileSharedCore.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,11 @@ class ModuleFileSharedCore {
320320
/// Whether this module is compiled with implicit dynamic.
321321
unsigned IsImplicitDynamicEnabled: 1;
322322

323+
/// Whether this module is compiled while allowing errors.
324+
unsigned IsAllowModuleWithCompilerErrorsEnabled: 1;
325+
323326
// Explicitly pad out to the next word boundary.
324-
unsigned : 0;
327+
unsigned : 3;
325328
} Bits = {};
326329
static_assert(sizeof(ModuleBits) <= 8, "The bit set should be small");
327330

lib/Serialization/ModuleFormat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 585; // hop_to_executor instruction
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 586; // allow errors in modules
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -787,7 +787,8 @@ namespace options_block {
787787
IS_TESTABLE,
788788
RESILIENCE_STRATEGY,
789789
ARE_PRIVATE_IMPORTS_ENABLED,
790-
IS_IMPLICIT_DYNAMIC_ENABLED
790+
IS_IMPLICIT_DYNAMIC_ENABLED,
791+
IS_ALLOW_MODULE_WITH_COMPILER_ERRORS_ENABLED
791792
};
792793

793794
using SDKPathLayout = BCRecordLayout<
@@ -821,6 +822,10 @@ namespace options_block {
821822
RESILIENCE_STRATEGY,
822823
BCFixed<2>
823824
>;
825+
826+
using IsAllowModuleWithCompilerErrorsEnabledLayout = BCRecordLayout<
827+
IS_ALLOW_MODULE_WITH_COMPILER_ERRORS_ENABLED
828+
>;
824829
}
825830

826831
/// The record types within the input block.
@@ -919,6 +924,12 @@ namespace decls_block {
919924
BCArray<BCVBR<6>>
920925
>;
921926

927+
/// A placeholder for invalid types
928+
using ErrorTypeLayout = BCRecordLayout<
929+
ERROR_TYPE,
930+
TypeIDField // original type (if any)
931+
>;
932+
922933
using BuiltinAliasTypeLayout = BCRecordLayout<
923934
BUILTIN_ALIAS_TYPE,
924935
DeclIDField, // typealias decl

0 commit comments

Comments
 (0)