mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Factor out reading flags/version from an interface from setting up a Compiler sub-instance
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user