Swift: lock built swiftmodule traps in main

This should cover `-merge-modules` mode.

Dumping of the configuration to the target files was moved to a
separate pair of header/source files, as now it is also done in
`SwiftOutputRewrite.cpp`.
This commit is contained in:
Paolo Tranquilli
2022-07-29 16:27:55 +02:00
parent 405d0fcd54
commit daf1fa3c31
8 changed files with 56 additions and 46 deletions

View File

@@ -2,14 +2,10 @@ load("//swift:rules.bzl", "swift_cc_binary")
swift_cc_binary(
name = "extractor",
srcs = [
"SwiftOutputRewrite.cpp",
"SwiftOutputRewrite.h",
"SwiftExtractor.cpp",
"SwiftExtractor.h",
"SwiftExtractorConfiguration.h",
"main.cpp",
],
srcs = glob([
"*.h",
"*.cpp",
]),
visibility = ["//swift:__pkg__"],
deps = [
"//swift/extractor/infra",

View File

@@ -14,7 +14,7 @@
#include "swift/extractor/trap/generated/TrapClasses.h"
#include "swift/extractor/trap/TrapDomain.h"
#include "swift/extractor/visitors/SwiftVisitor.h"
#include "swift/extractor/infra/TargetFile.h"
#include "swift/extractor/TargetTrapFile.h"
using namespace codeql;
using namespace std::string_literals;
@@ -80,20 +80,6 @@ static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& modul
return ret;
}
static void dumpArgs(TargetFile& out, const SwiftExtractorConfiguration& config) {
out << "/* extractor-args:\n";
for (const auto& opt : config.frontendOptions) {
out << " " << std::quoted(opt) << " \\\n";
}
out << "\n*/\n";
out << "/* swift-frontend-args:\n";
for (const auto& opt : config.patchedFrontendOptions) {
out << " " << std::quoted(opt) << " \\\n";
}
out << "\n*/\n";
}
static void extractDeclarations(const SwiftExtractorConfiguration& config,
swift::CompilerInstance& compiler,
swift::ModuleDecl& module,
@@ -103,12 +89,11 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
// The extractor can be called several times from different processes with
// the same input file(s). Using `TargetFile` the first process will win, and the following
// will just skip the work
auto trapTarget = TargetFile::create(filename + ".trap", config.trapDir, config.getTempTrapDir());
auto trapTarget = createTargetTrapFile(config, filename);
if (!trapTarget) {
// another process arrived first, nothing to do for us
return;
}
dumpArgs(*trapTarget, config);
TrapDomain trap{*trapTarget};
// TODO: remove this and recreate it with IPA when we have that
@@ -172,14 +157,6 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
auto inputFiles = collectInputFilenames(compiler);
auto modules = collectModules(compiler);
// we want to make sure any following extractor run will not try to extract things from
// the swiftmodule files we are creating in this run, as those things will already have been
// extracted from source with more information. We do this by creating empty trap files.
// TargetFile semantics will ensure any following run trying to extract that swiftmodule will just
// skip doing it
for (const auto& output : config.outputSwiftModules) {
TargetFile::create(output + ".trap", config.trapDir, config.getTempTrapDir());
}
for (auto& module : modules) {
bool isFromSourceFile = false;
for (auto file : module->getFiles()) {

View File

@@ -3,6 +3,8 @@
#include <string>
#include <vector>
#include "swift/extractor/infra/TargetFile.h"
namespace codeql {
struct SwiftExtractorConfiguration {
// The location for storing TRAP files to be imported by CodeQL engine.
@@ -32,9 +34,6 @@ struct SwiftExtractorConfiguration {
// A temporary directory that contains build artifacts generated by the extractor during the
// overall extraction process.
std::string getTempArtifactDir() const { return scratchDir + "/swift-extraction-artifacts"; }
// Output swiftmodule files. This also includes possible locations where XCode internally moves
// modules
std::vector<std::string> outputSwiftModules;
};
} // namespace codeql

View File

@@ -1,5 +1,6 @@
#include "SwiftOutputRewrite.h"
#include "swift/extractor/SwiftExtractorConfiguration.h"
#include "swift/extractor/TargetTrapFile.h"
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/FileSystem.h>
@@ -323,15 +324,18 @@ std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& conf
return overlays;
}
std::vector<std::string> getOutputSwiftModules(
const std::unordered_map<std::string, std::string>& remapping) {
std::vector<std::string> ret;
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
const std::unordered_map<std::string, std::string>& remapping) {
for (const auto& [oldPath, newPath] : remapping) {
if (llvm::StringRef(oldPath).endswith(".swiftmodule")) {
ret.push_back(oldPath);
if (auto target = createTargetTrapFile(config, oldPath)) {
*target << "// trap file deliberately empty\n"
"// this swiftmodule was created during the build, so its entities must have"
" been extracted directly from source files";
}
}
}
return ret;
}
} // namespace codeql

View File

@@ -29,7 +29,7 @@ void storeRemappingForVFS(const SwiftExtractorConfiguration& config,
// This is separate from storeRemappingForVFS as we also collect files produced by other processes.
std::vector<std::string> collectVFSFiles(const SwiftExtractorConfiguration& config);
// Returns a list of output remapped swift module files
std::vector<std::string> getOutputSwiftModules(
const std::unordered_map<std::string, std::string>& remapping);
// Creates empty trap files for output swiftmodule files
void lockOutputSwiftModuleTraps(const SwiftExtractorConfiguration& config,
const std::unordered_map<std::string, std::string>& remapping);
} // namespace codeql

View File

@@ -0,0 +1,23 @@
#include "swift/extractor/TargetTrapFile.h"
#include <iomanip>
namespace codeql {
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
std::string_view target) {
std::string trap{target};
trap += ".trap";
auto ret = TargetFile::create(trap, configuration.trapDir, configuration.getTempTrapDir());
if (ret) {
*ret << "/* extractor-args:\n";
for (const auto& opt : configuration.frontendOptions) {
*ret << " " << std::quoted(opt) << " \\\n";
}
*ret << "\n*/\n"
"/* swift-frontend-args:\n";
for (const auto& opt : configuration.patchedFrontendOptions) {
*ret << " " << std::quoted(opt) << " \\\n";
}
*ret << "\n*/\n";
}
return ret;
}
} // namespace codeql

View File

@@ -0,0 +1,11 @@
#pragma once
#include "swift/extractor/infra/TargetFile.h"
#include "swift/extractor/SwiftExtractorConfiguration.h"
namespace codeql {
std::optional<TargetFile> createTargetTrapFile(const SwiftExtractorConfiguration& configuration,
std::string_view target);
} // namespace codeql

View File

@@ -68,7 +68,7 @@ int main(int argc, char** argv) {
codeql::rewriteOutputsInPlace(configuration, configuration.patchedFrontendOptions);
codeql::ensureDirectoriesForNewPathsExist(remapping);
codeql::storeRemappingForVFS(configuration, remapping);
configuration.outputSwiftModules = codeql::getOutputSwiftModules(remapping);
codeql::lockOutputSwiftModuleTraps(configuration, remapping);
std::vector<const char*> args;
for (auto& arg : configuration.patchedFrontendOptions) {