Skip to content

Commit e0f7f2a

Browse files
committed
Factor out reading flags/version from an interface from setting up a Compiler sub-instance
1 parent d267ff3 commit e0f7f2a

File tree

4 files changed

+108
-69
lines changed

4 files changed

+108
-69
lines changed

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
453453
const StringRef backupInterfaceDir, const StringRef prebuiltCachePath,
454454
const StringRef ABIDescriptorPath, StringRef interfacePath,
455455
StringRef outputPath, bool ShouldSerializeDeps,
456-
ArrayRef<std::string> CompiledCandidates, StringRef CompilerVersion,
456+
ArrayRef<std::string> CompiledCandidates,
457457
DependencyTracker *tracker = nullptr);
458458
};
459459

@@ -473,13 +473,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
473473
InFlightDiagnostic diagnose(StringRef interfacePath,
474474
SourceLoc diagnosticLoc,
475475
Diag<ArgTypes...> ID,
476-
typename detail::PassArgument<ArgTypes>::type... Args) {
477-
SourceLoc loc = diagnosticLoc;
478-
if (diagnosticLoc.isInvalid()) {
479-
// Diagnose this inside the interface file, if possible.
480-
loc = SM.getLocFromExternalSource(interfacePath, 1, 1);
481-
}
482-
return Diags->diagnose(loc, ID, std::move(Args)...);
476+
typename detail::PassArgument<ArgTypes>::type... Args) {
477+
return InterfaceSubContextDelegateImpl::diagnose(interfacePath, diagnosticLoc, SM, Diags, ID, std::move(Args)...);
483478
}
484479
void
485480
inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
@@ -500,6 +495,22 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
500495
StringRef backupModuleInterfaceDir,
501496
bool serializeDependencyHashes, bool trackSystemDependencies,
502497
RequireOSSAModules_t requireOSSAModules);
498+
499+
template<typename ...ArgTypes>
500+
static InFlightDiagnostic diagnose(StringRef interfacePath,
501+
SourceLoc diagnosticLoc,
502+
SourceManager &SM,
503+
DiagnosticEngine *Diags,
504+
Diag<ArgTypes...> ID,
505+
typename detail::PassArgument<ArgTypes>::type... Args) {
506+
SourceLoc loc = diagnosticLoc;
507+
if (diagnosticLoc.isInvalid()) {
508+
// Diagnose this inside the interface file, if possible.
509+
loc = SM.getLocFromExternalSource(interfacePath, 1, 1);
510+
}
511+
return Diags->diagnose(loc, ID, std::move(Args)...);
512+
}
513+
503514
std::error_code runInSubContext(StringRef moduleName,
504515
StringRef interfacePath,
505516
StringRef outputPath,

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ bool ArgsToFrontendOptionsConverter::convert(
9393
if (Args.hasArg(OPT_track_system_dependencies)) {
9494
Opts.IntermoduleDependencyTracking =
9595
IntermoduleDepTrackingMode::IncludeSystem;
96+
} else if (Args.hasArg(OPT_explicit_interface_module_build)) {
97+
// Always track at least the non-system dependencies for interface building.
98+
Opts.IntermoduleDependencyTracking =
99+
IntermoduleDepTrackingMode::ExcludeSystem;
96100
}
97101

98102
if (const Arg *A = Args.getLastArg(OPT_bad_file_descriptor_retry_count)) {
@@ -624,7 +628,7 @@ bool ArgsToFrontendOptionsConverter::checkBuildFromInterfaceOnlyOptions()
624628
if (Opts.RequestedAction != FrontendOptions::ActionType::CompileModuleFromInterface &&
625629
Opts.ExplicitInterfaceBuild) {
626630
Diags.diagnose(SourceLoc(),
627-
diag::error_cannot_ignore_interface_options_in_mode);
631+
diag::error_cannot_explicit_interface_build_in_mode);
628632
return true;
629633
}
630634
return false;

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,32 +181,29 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization(
181181
}
182182

183183
std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
184-
StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps,
184+
StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps,
185185
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
186-
ArrayRef<std::string> compiledCandidates,
186+
ArrayRef<std::string> CompiledCandidates,
187187
StringRef CompilerVersion) {
188188
auto Invocation = Instance.getInvocation();
189189
// Try building forwarding module first. If succeed, return.
190190
if (Instance.getASTContext()
191191
.getModuleInterfaceChecker()
192-
->tryEmitForwardingModule(Invocation.getModuleName(), interfacePath,
193-
compiledCandidates, outputPath)) {
192+
->tryEmitForwardingModule(Invocation.getModuleName(), InterfacePath,
193+
CompiledCandidates, OutputPath)) {
194194
return std::error_code();
195195
}
196196
FrontendOptions &FEOpts = Invocation.getFrontendOptions();
197197
bool isTypeChecking =
198198
(FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck);
199199
const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput();
200200
StringRef InPath = InputInfo.getFileName();
201-
const auto &OutputInfo =
202-
InputInfo.getPrimarySpecificPaths().SupplementaryOutputs;
203-
StringRef OutPath = OutputInfo.ModuleOutputPath;
204201

205202
// Build the .swiftmodule; this is a _very_ abridged version of the logic
206203
// in performCompile in libFrontendTool, specialized, to just the one
207204
// module-serialization task we're trying to do here.
208205
LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " << InPath
209-
<< " to " << OutPath << "\n");
206+
<< " to " << OutputPath << "\n");
210207

211208
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
212209
if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) {
@@ -224,12 +221,12 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
224221
Instance.getASTContext());
225222

226223
if (!isTypeChecking && CompilerVersion.str() != builtByCompiler) {
227-
diagnose(&Instance.getDiags(), Instance.getSourceMgr(), interfacePath,
224+
diagnose(&Instance.getDiags(), Instance.getSourceMgr(), InterfacePath,
228225
diag::module_interface_build_failed_mismatching_compiler,
229226
Invocation.getModuleName(), CompilerVersion,
230227
builtByCompiler);
231228
} else {
232-
diagnose(&Instance.getDiags(), Instance.getSourceMgr(), interfacePath,
229+
diagnose(&Instance.getDiags(), Instance.getSourceMgr(), InterfacePath,
233230
diag::module_interface_build_failed, isTypeChecking,
234231
Invocation.getModuleName(),
235232
CompilerVersion.str() == builtByCompiler, CompilerVersion.str(),
@@ -259,7 +256,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
259256
// Setup the callbacks for serialization, which can occur during the
260257
// optimization pipeline.
261258
SerializationOptions SerializationOpts;
262-
std::string OutPathStr = OutPath.str();
259+
std::string OutPathStr = OutputPath.str();
263260
SerializationOpts.OutputPath = OutPathStr.c_str();
264261
SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName;
265262
SerializationOpts.AutolinkForceLoad =
@@ -274,8 +271,8 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
274271
SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName;
275272
SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str();
276273
SmallVector<FileDependency, 16> Deps;
277-
bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes;
278-
if (collectDepsForSerialization(Deps, interfacePath, serializeHashes)) {
274+
bool SerializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes;
275+
if (collectDepsForSerialization(Deps, InterfacePath, SerializeHashes)) {
279276
return std::make_error_code(std::errc::not_supported);
280277
}
281278
if (ShouldSerializeDeps)

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 74 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,13 +1259,83 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
12591259
SearchPathOpts.CandidateCompiledModules);
12601260
}
12611261

1262+
static bool readSwiftInterfaceVersionAndArgs(
1263+
SourceManager &SM, DiagnosticEngine &Diags, llvm::StringSaver &ArgSaver,
1264+
SmallVectorImpl<const char *> &SubArgs, std::string &CompilerVersion,
1265+
StringRef interfacePath, SourceLoc diagnosticLoc) {
1266+
llvm::vfs::FileSystem &fs = *SM.getFileSystem();
1267+
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
1268+
if (!FileOrError) {
1269+
// Don't use this->diagnose() because it'll just try to re-open
1270+
// interfacePath.
1271+
Diags.diagnose(diagnosticLoc, diag::error_open_input_file, interfacePath,
1272+
FileOrError.getError().message());
1273+
return true;
1274+
}
1275+
auto SB = FileOrError.get()->getBuffer();
1276+
auto VersRe = getSwiftInterfaceFormatVersionRegex();
1277+
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
1278+
SmallVector<StringRef, 1> VersMatches, CompMatches;
1279+
1280+
if (!VersRe.match(SB, &VersMatches)) {
1281+
InterfaceSubContextDelegateImpl::diagnose(
1282+
interfacePath, diagnosticLoc, SM, &Diags,
1283+
diag::error_extracting_version_from_module_interface);
1284+
return true;
1285+
}
1286+
1287+
if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) {
1288+
InterfaceSubContextDelegateImpl::diagnose(
1289+
interfacePath, diagnosticLoc, SM, &Diags,
1290+
diag::error_extracting_version_from_module_interface);
1291+
return true;
1292+
}
1293+
1294+
assert(VersMatches.size() == 2);
1295+
// FIXME We should diagnose this at a location that makes sense:
1296+
auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), &Diags);
1297+
1298+
if (CompRe.match(SB, &CompMatches)) {
1299+
assert(CompMatches.size() == 2);
1300+
CompilerVersion = ArgSaver.save(CompMatches[1]).str();
1301+
} else {
1302+
// Don't diagnose; handwritten module interfaces don't include this field.
1303+
CompilerVersion = "(unspecified, file possibly handwritten)";
1304+
}
1305+
1306+
// For now: we support anything with the same "major version" and assume
1307+
// minor versions might be interesting for debugging, or special-casing a
1308+
// compatible field variant.
1309+
if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
1310+
InterfaceSubContextDelegateImpl::diagnose(
1311+
interfacePath, diagnosticLoc, SM, &Diags,
1312+
diag::unsupported_version_of_module_interface, interfacePath, Vers);
1313+
return true;
1314+
}
1315+
return false;
1316+
}
1317+
12621318
bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface(
12631319
CompilerInstance &Instance, const StringRef moduleCachePath,
12641320
const StringRef backupInterfaceDir, const StringRef prebuiltCachePath,
12651321
const StringRef ABIDescriptorPath, StringRef interfacePath,
12661322
StringRef outputPath, bool ShouldSerializeDeps,
1267-
ArrayRef<std::string> CompiledCandidates, StringRef CompilerVersion,
1323+
ArrayRef<std::string> CompiledCandidates,
12681324
DependencyTracker *tracker) {
1325+
1326+
// Read out the compiler version.
1327+
llvm::BumpPtrAllocator alloc;
1328+
llvm::StringSaver ArgSaver(alloc);
1329+
std::string CompilerVersion;
1330+
SmallVector<const char *, 64> InterfaceArgs;
1331+
readSwiftInterfaceVersionAndArgs(Instance.getSourceMgr(),
1332+
Instance.getDiags(),
1333+
ArgSaver,
1334+
InterfaceArgs,
1335+
CompilerVersion,
1336+
interfacePath,
1337+
SourceLoc());
1338+
12691339
auto Builder = ExplicitModuleInterfaceBuilder(
12701340
Instance, moduleCachePath, backupInterfaceDir, prebuiltCachePath,
12711341
ABIDescriptorPath);
@@ -1381,53 +1451,10 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
13811451
std::string &CompilerVersion,
13821452
StringRef interfacePath,
13831453
SourceLoc diagnosticLoc) {
1384-
llvm::vfs::FileSystem &fs = *SM.getFileSystem();
1385-
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
1386-
if (!FileOrError) {
1387-
// Don't use this->diagnose() because it'll just try to re-open
1388-
// interfacePath.
1389-
Diags->diagnose(diagnosticLoc, diag::error_open_input_file,
1390-
interfacePath, FileOrError.getError().message());
1391-
return true;
1392-
}
1393-
auto SB = FileOrError.get()->getBuffer();
1394-
auto VersRe = getSwiftInterfaceFormatVersionRegex();
1395-
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
1396-
SmallVector<StringRef, 1> VersMatches, CompMatches;
1397-
1398-
if (!VersRe.match(SB, &VersMatches)) {
1399-
diagnose(interfacePath, diagnosticLoc,
1400-
diag::error_extracting_version_from_module_interface);
1401-
return true;
1402-
}
1403-
1404-
if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) {
1405-
diagnose(interfacePath, diagnosticLoc,
1406-
diag::error_extracting_version_from_module_interface);
1454+
if (readSwiftInterfaceVersionAndArgs(SM, *Diags, ArgSaver, SubArgs,
1455+
CompilerVersion, interfacePath,
1456+
diagnosticLoc))
14071457
return true;
1408-
}
1409-
1410-
assert(VersMatches.size() == 2);
1411-
// FIXME We should diagnose this at a location that makes sense:
1412-
auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), Diags);
1413-
1414-
if (CompRe.match(SB, &CompMatches)) {
1415-
assert(CompMatches.size() == 2);
1416-
CompilerVersion = ArgSaver.save(CompMatches[1]).str();
1417-
}
1418-
else {
1419-
// Don't diagnose; handwritten module interfaces don't include this field.
1420-
CompilerVersion = "(unspecified, file possibly handwritten)";
1421-
}
1422-
1423-
// For now: we support anything with the same "major version" and assume
1424-
// minor versions might be interesting for debugging, or special-casing a
1425-
// compatible field variant.
1426-
if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
1427-
diagnose(interfacePath, diagnosticLoc,
1428-
diag::unsupported_version_of_module_interface, interfacePath, Vers);
1429-
return true;
1430-
}
14311458

14321459
SmallString<32> ExpectedModuleName = subInvocation.getModuleName();
14331460
if (subInvocation.parseArgs(SubArgs, *Diags)) {

0 commit comments

Comments
 (0)