Factor out reading flags/version from an interface from setting up a Compiler sub-instance

This commit is contained in:
Artem Chikin
2022-08-04 15:38:37 -07:00
parent 7fd2a29fb7
commit a90d3e2de1
4 changed files with 106 additions and 67 deletions

View File

@@ -453,7 +453,7 @@ public:
const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, const StringRef backupInterfaceDir, const StringRef prebuiltCachePath,
const StringRef ABIDescriptorPath, StringRef interfacePath, const StringRef ABIDescriptorPath, StringRef interfacePath,
StringRef outputPath, bool ShouldSerializeDeps, StringRef outputPath, bool ShouldSerializeDeps,
ArrayRef<std::string> CompiledCandidates, StringRef CompilerVersion, ArrayRef<std::string> CompiledCandidates,
DependencyTracker *tracker = nullptr); DependencyTracker *tracker = nullptr);
}; };
@@ -473,13 +473,8 @@ private:
InFlightDiagnostic diagnose(StringRef interfacePath, InFlightDiagnostic diagnose(StringRef interfacePath,
SourceLoc diagnosticLoc, SourceLoc diagnosticLoc,
Diag<ArgTypes...> ID, Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... Args) { typename detail::PassArgument<ArgTypes>::type... Args) {
SourceLoc loc = diagnosticLoc; return InterfaceSubContextDelegateImpl::diagnose(interfacePath, diagnosticLoc, SM, Diags, ID, std::move(Args)...);
if (diagnosticLoc.isInvalid()) {
// Diagnose this inside the interface file, if possible.
loc = SM.getLocFromExternalSource(interfacePath, 1, 1);
}
return Diags->diagnose(loc, ID, std::move(Args)...);
} }
void void
inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts, inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
@@ -500,6 +495,22 @@ public:
StringRef backupModuleInterfaceDir, StringRef backupModuleInterfaceDir,
bool serializeDependencyHashes, bool trackSystemDependencies, bool serializeDependencyHashes, bool trackSystemDependencies,
RequireOSSAModules_t requireOSSAModules); RequireOSSAModules_t requireOSSAModules);
template<typename ...ArgTypes>
static InFlightDiagnostic diagnose(StringRef interfacePath,
SourceLoc diagnosticLoc,
SourceManager &SM,
DiagnosticEngine *Diags,
Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... Args) {
SourceLoc loc = diagnosticLoc;
if (diagnosticLoc.isInvalid()) {
// Diagnose this inside the interface file, if possible.
loc = SM.getLocFromExternalSource(interfacePath, 1, 1);
}
return Diags->diagnose(loc, ID, std::move(Args)...);
}
std::error_code runInSubContext(StringRef moduleName, std::error_code runInSubContext(StringRef moduleName,
StringRef interfacePath, StringRef interfacePath,
StringRef outputPath, StringRef outputPath,

View File

@@ -93,6 +93,10 @@ bool ArgsToFrontendOptionsConverter::convert(
if (Args.hasArg(OPT_track_system_dependencies)) { if (Args.hasArg(OPT_track_system_dependencies)) {
Opts.IntermoduleDependencyTracking = Opts.IntermoduleDependencyTracking =
IntermoduleDepTrackingMode::IncludeSystem; IntermoduleDepTrackingMode::IncludeSystem;
} else if (Args.hasArg(OPT_explicit_interface_module_build)) {
// Always track at least the non-system dependencies for interface building.
Opts.IntermoduleDependencyTracking =
IntermoduleDepTrackingMode::ExcludeSystem;
} }
if (const Arg *A = Args.getLastArg(OPT_bad_file_descriptor_retry_count)) { if (const Arg *A = Args.getLastArg(OPT_bad_file_descriptor_retry_count)) {
@@ -624,7 +628,7 @@ bool ArgsToFrontendOptionsConverter::checkBuildFromInterfaceOnlyOptions()
if (Opts.RequestedAction != FrontendOptions::ActionType::CompileModuleFromInterface && if (Opts.RequestedAction != FrontendOptions::ActionType::CompileModuleFromInterface &&
Opts.ExplicitInterfaceBuild) { Opts.ExplicitInterfaceBuild) {
Diags.diagnose(SourceLoc(), Diags.diagnose(SourceLoc(),
diag::error_cannot_ignore_interface_options_in_mode); diag::error_cannot_explicit_interface_build_in_mode);
return true; return true;
} }
return false; return false;

View File

@@ -181,16 +181,16 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization(
} }
std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface( std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
StringRef interfacePath, StringRef outputPath, bool ShouldSerializeDeps, StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
ArrayRef<std::string> compiledCandidates, ArrayRef<std::string> CompiledCandidates,
StringRef CompilerVersion) { StringRef CompilerVersion) {
auto Invocation = Instance.getInvocation(); auto Invocation = Instance.getInvocation();
// Try building forwarding module first. If succeed, return. // Try building forwarding module first. If succeed, return.
if (Instance.getASTContext() if (Instance.getASTContext()
.getModuleInterfaceChecker() .getModuleInterfaceChecker()
->tryEmitForwardingModule(Invocation.getModuleName(), interfacePath, ->tryEmitForwardingModule(Invocation.getModuleName(), InterfacePath,
compiledCandidates, outputPath)) { CompiledCandidates, OutputPath)) {
return std::error_code(); return std::error_code();
} }
FrontendOptions &FEOpts = Invocation.getFrontendOptions(); FrontendOptions &FEOpts = Invocation.getFrontendOptions();
@@ -198,15 +198,12 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
(FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck); (FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck);
const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput();
StringRef InPath = InputInfo.getFileName(); StringRef InPath = InputInfo.getFileName();
const auto &OutputInfo =
InputInfo.getPrimarySpecificPaths().SupplementaryOutputs;
StringRef OutPath = OutputInfo.ModuleOutputPath;
// Build the .swiftmodule; this is a _very_ abridged version of the logic // Build the .swiftmodule; this is a _very_ abridged version of the logic
// in performCompile in libFrontendTool, specialized, to just the one // in performCompile in libFrontendTool, specialized, to just the one
// module-serialization task we're trying to do here. // module-serialization task we're trying to do here.
LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " << InPath LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile " << InPath
<< " to " << OutPath << "\n"); << " to " << OutputPath << "\n");
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n"); LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) { if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) {
@@ -262,7 +259,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
// Setup the callbacks for serialization, which can occur during the // Setup the callbacks for serialization, which can occur during the
// optimization pipeline. // optimization pipeline.
SerializationOptions SerializationOpts; SerializationOptions SerializationOpts;
std::string OutPathStr = OutPath.str(); std::string OutPathStr = OutputPath.str();
SerializationOpts.OutputPath = OutPathStr.c_str(); SerializationOpts.OutputPath = OutPathStr.c_str();
SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName; SerializationOpts.ModuleLinkName = FEOpts.ModuleLinkName;
SerializationOpts.AutolinkForceLoad = SerializationOpts.AutolinkForceLoad =
@@ -277,8 +274,8 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName; SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName;
SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str(); SerializationOpts.ABIDescriptorPath = ABIDescriptorPath.str();
SmallVector<FileDependency, 16> Deps; SmallVector<FileDependency, 16> Deps;
bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; bool SerializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes;
if (collectDepsForSerialization(Deps, interfacePath, serializeHashes)) { if (collectDepsForSerialization(Deps, InterfacePath, SerializeHashes)) {
return std::make_error_code(std::errc::not_supported); return std::make_error_code(std::errc::not_supported);
} }
if (ShouldSerializeDeps) if (ShouldSerializeDeps)

View File

@@ -1259,13 +1259,83 @@ bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface(
SearchPathOpts.CandidateCompiledModules); SearchPathOpts.CandidateCompiledModules);
} }
static bool readSwiftInterfaceVersionAndArgs(
SourceManager &SM, DiagnosticEngine &Diags, llvm::StringSaver &ArgSaver,
SmallVectorImpl<const char *> &SubArgs, std::string &CompilerVersion,
StringRef interfacePath, SourceLoc diagnosticLoc) {
llvm::vfs::FileSystem &fs = *SM.getFileSystem();
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
if (!FileOrError) {
// Don't use this->diagnose() because it'll just try to re-open
// interfacePath.
Diags.diagnose(diagnosticLoc, diag::error_open_input_file, interfacePath,
FileOrError.getError().message());
return true;
}
auto SB = FileOrError.get()->getBuffer();
auto VersRe = getSwiftInterfaceFormatVersionRegex();
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
SmallVector<StringRef, 1> VersMatches, CompMatches;
if (!VersRe.match(SB, &VersMatches)) {
InterfaceSubContextDelegateImpl::diagnose(
interfacePath, diagnosticLoc, SM, &Diags,
diag::error_extracting_version_from_module_interface);
return true;
}
if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) {
InterfaceSubContextDelegateImpl::diagnose(
interfacePath, diagnosticLoc, SM, &Diags,
diag::error_extracting_version_from_module_interface);
return true;
}
assert(VersMatches.size() == 2);
// FIXME We should diagnose this at a location that makes sense:
auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), &Diags);
if (CompRe.match(SB, &CompMatches)) {
assert(CompMatches.size() == 2);
CompilerVersion = ArgSaver.save(CompMatches[1]).str();
} else {
// Don't diagnose; handwritten module interfaces don't include this field.
CompilerVersion = "(unspecified, file possibly handwritten)";
}
// For now: we support anything with the same "major version" and assume
// minor versions might be interesting for debugging, or special-casing a
// compatible field variant.
if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
InterfaceSubContextDelegateImpl::diagnose(
interfacePath, diagnosticLoc, SM, &Diags,
diag::unsupported_version_of_module_interface, interfacePath, Vers);
return true;
}
return false;
}
bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface( bool ModuleInterfaceLoader::buildExplicitSwiftModuleFromSwiftInterface(
CompilerInstance &Instance, const StringRef moduleCachePath, CompilerInstance &Instance, const StringRef moduleCachePath,
const StringRef backupInterfaceDir, const StringRef prebuiltCachePath, const StringRef backupInterfaceDir, const StringRef prebuiltCachePath,
const StringRef ABIDescriptorPath, StringRef interfacePath, const StringRef ABIDescriptorPath, StringRef interfacePath,
StringRef outputPath, bool ShouldSerializeDeps, StringRef outputPath, bool ShouldSerializeDeps,
ArrayRef<std::string> CompiledCandidates, StringRef CompilerVersion, ArrayRef<std::string> CompiledCandidates,
DependencyTracker *tracker) { DependencyTracker *tracker) {
// Read out the compiler version.
llvm::BumpPtrAllocator alloc;
llvm::StringSaver ArgSaver(alloc);
std::string CompilerVersion;
SmallVector<const char *, 64> InterfaceArgs;
readSwiftInterfaceVersionAndArgs(Instance.getSourceMgr(),
Instance.getDiags(),
ArgSaver,
InterfaceArgs,
CompilerVersion,
interfacePath,
SourceLoc());
auto Builder = ExplicitModuleInterfaceBuilder( auto Builder = ExplicitModuleInterfaceBuilder(
Instance, &Instance.getDiags(), Instance.getSourceMgr(), Instance, &Instance.getDiags(), Instance.getSourceMgr(),
moduleCachePath, backupInterfaceDir, prebuiltCachePath, moduleCachePath, backupInterfaceDir, prebuiltCachePath,
@@ -1382,53 +1452,10 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
std::string &CompilerVersion, std::string &CompilerVersion,
StringRef interfacePath, StringRef interfacePath,
SourceLoc diagnosticLoc) { SourceLoc diagnosticLoc) {
llvm::vfs::FileSystem &fs = *SM.getFileSystem(); if (readSwiftInterfaceVersionAndArgs(SM, *Diags, ArgSaver, SubArgs,
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath); CompilerVersion, interfacePath,
if (!FileOrError) { diagnosticLoc))
// Don't use this->diagnose() because it'll just try to re-open
// interfacePath.
Diags->diagnose(diagnosticLoc, diag::error_open_input_file,
interfacePath, FileOrError.getError().message());
return true; return true;
}
auto SB = FileOrError.get()->getBuffer();
auto VersRe = getSwiftInterfaceFormatVersionRegex();
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
SmallVector<StringRef, 1> VersMatches, CompMatches;
if (!VersRe.match(SB, &VersMatches)) {
diagnose(interfacePath, diagnosticLoc,
diag::error_extracting_version_from_module_interface);
return true;
}
if (extractCompilerFlagsFromInterface(interfacePath, SB, ArgSaver, SubArgs)) {
diagnose(interfacePath, diagnosticLoc,
diag::error_extracting_version_from_module_interface);
return true;
}
assert(VersMatches.size() == 2);
// FIXME We should diagnose this at a location that makes sense:
auto Vers = swift::version::Version(VersMatches[1], SourceLoc(), Diags);
if (CompRe.match(SB, &CompMatches)) {
assert(CompMatches.size() == 2);
CompilerVersion = ArgSaver.save(CompMatches[1]).str();
}
else {
// Don't diagnose; handwritten module interfaces don't include this field.
CompilerVersion = "(unspecified, file possibly handwritten)";
}
// For now: we support anything with the same "major version" and assume
// minor versions might be interesting for debugging, or special-casing a
// compatible field variant.
if (Vers.asMajorVersion() != InterfaceFormatVersion.asMajorVersion()) {
diagnose(interfacePath, diagnosticLoc,
diag::unsupported_version_of_module_interface, interfacePath, Vers);
return true;
}
SmallString<32> ExpectedModuleName = subInvocation.getModuleName(); SmallString<32> ExpectedModuleName = subInvocation.getModuleName();
if (subInvocation.parseArgs(SubArgs, *Diags)) { if (subInvocation.parseArgs(SubArgs, *Diags)) {