Add driver options to swift to enable MCCAS.

To enable MCCAS, the following driver options have been added

-cas-backend: Enable MCCAS backend in swift, the option
-cache-compile-job must also be used.

-cas-backend-mode=native: Set the CAS Backend mode to emit an object
file after materializing it from the CAS.

-cas-backend-mode=casid: Emit a file with the CASID for the CAS that was
created.

-cas-backend-mode=verify: Verify that the object file created is
identical to the object file materialized from the CAS.

-cas-emit-casid-file: Emit a .casid file next to the object file when
CAS Backend is enabled.
This commit is contained in:
Shubham Sandeep Rastogi
2023-05-09 09:00:23 -07:00
parent c3b97469da
commit 3c949028e8
11 changed files with 124 additions and 26 deletions

View File

@@ -491,6 +491,15 @@ public:
/// The calling convention used to perform non-swift calls.
llvm::CallingConv::ID PlatformCCallingConvention;
/// Use CAS based object format as the output.
bool UseCASBackend;
/// The output mode for the CAS Backend.
llvm::CASBackendMode CASObjMode;
/// Emit a .casid file next to the object file if CAS Backend is used.
bool EmitCASIDFile;
IRGenOptions()
: DWARFVersion(2),
OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization),
@@ -502,9 +511,9 @@ public:
DebugInfoFormat(IRGenDebugInfoFormat::None),
DisableClangModuleSkeletonCUs(false), UseJIT(false),
DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false),
Playground(false),
EmitStackPromotionChecks(false), UseSingleModuleLLVMEmission(false),
FunctionSections(false), PrintInlineTree(false), AlwaysCompile(false),
Playground(false), EmitStackPromotionChecks(false),
UseSingleModuleLLVMEmission(false), FunctionSections(false),
PrintInlineTree(false), AlwaysCompile(false),
EmbedMode(IRGenEmbedMode::None), LLVMLTOKind(IRGenLLVMLTOKind::None),
SwiftAsyncFramePointer(SwiftAsyncFramePointerKind::Auto),
HasValueNamesSetting(false), ValueNames(false),
@@ -526,13 +535,12 @@ public:
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
InternalizeAtLink(false), InternalizeSymbols(false),
EmitGenericRODatas(false), NoPreallocatedInstantiationCaches(false),
DisableReadonlyStaticObjects(false),
CollocatedMetadataFunctions(false),
ColocateTypeDescriptors(true),
UseRelativeProtocolWitnessTables(false), CmdArgs(),
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
TypeInfoFilter(TypeInfoDumpFilter::All),
PlatformCCallingConvention(llvm::CallingConv::C) {
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),
CASObjMode(llvm::CASBackendMode::Native) {
#ifndef NDEBUG
DisableRoundTripDebugTypes = false;
#else

View File

@@ -164,6 +164,10 @@ public:
return LangOpts.Target.str();
}
bool requiresCAS() const {
return FrontendOpts.EnableCaching || FrontendOpts.UseCASBackend;
}
void setClangModuleCachePath(StringRef Path) {
ClangImporterOpts.ModuleCachePath = Path.str();
}

View File

@@ -14,14 +14,15 @@
#define SWIFT_FRONTEND_FRONTENDOPTIONS_H
#include "swift/Basic/FileTypes.h"
#include "swift/Basic/Version.h"
#include "swift/Basic/PathRemapper.h"
#include "swift/Basic/Version.h"
#include "swift/Frontend/FrontendInputsAndOutputs.h"
#include "swift/Frontend/InputFile.h"
#include "clang/CAS/CASOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "clang/CAS/CASOptions.h"
#include "llvm/MC/MCTargetOptions.h"
#include <set>
#include <string>
@@ -149,6 +150,15 @@ public:
/// CacheKey for input file.
std::string InputFileKey;
/// Enable using the LLVM MCCAS backend for object file output.
bool UseCASBackend = false;
/// The output mode for the CAS Backend.
llvm::CASBackendMode CASObjMode;
/// Emit a .casid file next to the object file if CAS Backend is used.
bool EmitCASIDFile = false;
/// Number of retry opening an input file if the previous opening returns
/// bad file descriptor error.
unsigned BadFileDescriptorRetryCount = 0;

View File

@@ -1859,6 +1859,19 @@ def external_plugin_path : Separate<["-"], "external-plugin-path">, Group<plugin
HelpText<"Add directory to the plugin search path with a plugin server executable">,
MetaVarName<"<path>#<plugin-server-path>">;
def cas_backend: Flag<["-"], "cas-backend">,
Flags<[FrontendOption, NoDriverOption]>,
HelpText<"Enable using CASBackend for object file output">;
def cas_backend_mode: Joined<["-"], "cas-backend-mode=">,
Flags<[FrontendOption, NoDriverOption]>,
HelpText<"CASBackendMode for output kind">,
MetaVarName<"native|casid|verify">;
def cas_emit_casid_file: Flag<["-"], "cas-emit-casid-file">,
Flags<[FrontendOption, NoDriverOption]>,
HelpText<"Emit .casid file next to object file when CAS Backend is enabled">;
def load_plugin_library:
Separate<["-"], "load-plugin-library">, Group<plugin_search_Group>,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,

View File

@@ -263,7 +263,8 @@ namespace swift {
const IRGenOptions &opts,
UnifiedStatsReporter *stats, DiagnosticEngine &diags,
llvm::raw_pwrite_stream &out,
llvm::sys::Mutex *diagMutex = nullptr);
llvm::sys::Mutex *diagMutex = nullptr,
llvm::raw_pwrite_stream *casid = nullptr);
/// Wrap a serialized module inside a swift AST section in an object file.
void createSwiftModuleObjectFile(SILModule &SILMod, StringRef Buffer,

View File

@@ -380,6 +380,17 @@ bool ArgsToFrontendOptionsConverter::convert(
Opts.BlocklistConfigFilePaths.push_back(A);
}
if (Arg *A = Args.getLastArg(OPT_cas_backend_mode)) {
Opts.CASObjMode = llvm::StringSwitch<llvm::CASBackendMode>(A->getValue())
.Case("native", llvm::CASBackendMode::Native)
.Case("casid", llvm::CASBackendMode::CASID)
.Case("verify", llvm::CASBackendMode::Verify)
.Default(llvm::CASBackendMode::Native);
}
Opts.UseCASBackend = Args.hasArg(OPT_cas_backend);
Opts.EmitCASIDFile = Args.hasArg(OPT_cas_emit_casid_file);
return false;
}

View File

@@ -266,6 +266,10 @@ setIRGenOutputOptsFromFrontendOptions(IRGenOptions &IRGenOpts,
}
}(FrontendOpts.RequestedAction);
IRGenOpts.UseCASBackend = FrontendOpts.UseCASBackend;
IRGenOpts.CASObjMode = FrontendOpts.CASObjMode;
IRGenOpts.EmitCASIDFile = FrontendOpts.EmitCASIDFile;
// If we're in JIT mode, set the requisite flags.
if (FrontendOpts.RequestedAction == FrontendOptions::ActionType::Immediate) {
IRGenOpts.UseJIT = true;
@@ -1440,7 +1444,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
DiagnosticEngine &Diags,
StringRef workingDirectory,
const LangOptions &LangOpts,
const FrontendOptions &FrontendOpts) {
const FrontendOptions &FrontendOpts,
bool RequiresCAS) {
using namespace options;
if (const Arg *a = Args.getLastArg(OPT_tools_directory)) {
@@ -1568,7 +1573,7 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
// Forward the FrontendOptions to clang importer option so it can be
// accessed when creating clang module compilation invocation.
if (FrontendOpts.EnableCaching)
if (RequiresCAS)
Opts.CASOpts = FrontendOpts.CASOpts;
return false;
@@ -3025,7 +3030,7 @@ bool CompilerInvocation::parseArgs(
}
if (ParseClangImporterArgs(ClangImporterOpts, ParsedArgs, Diags,
workingDirectory, LangOpts, FrontendOpts)) {
workingDirectory, LangOpts, FrontendOpts, requiresCAS())) {
return true;
}

View File

@@ -407,7 +407,7 @@ void CompilerInstance::setupDependencyTrackerIfNeeded() {
bool CompilerInstance::setupCASIfNeeded(ArrayRef<const char *> Args) {
const auto &Opts = getInvocation().getFrontendOptions();
if (!Opts.EnableCaching)
if (!getInvocation().requiresCAS())
return false;
auto MaybeDB= Opts.CASOpts.getOrCreateDatabases();

View File

@@ -1672,6 +1672,7 @@ static bool generateCode(CompilerInstance &Instance, StringRef OutputFilename,
std::unique_ptr<llvm::TargetMachine> TargetMachine =
createTargetMachine(opts, Instance.getASTContext());
TargetMachine->Options.MCOptions.CAS = Instance.getSharedCASInstance();
// Free up some compiler resources now that we have an IRModule.
freeASTContextIfPossible(Instance);

View File

@@ -128,6 +128,12 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx) {
TargetOpts.DebuggerTuning = llvm::DebuggerKind::LLDB;
TargetOpts.FunctionSections = Opts.FunctionSections;
// Set option to UseCASBackend if CAS was enabled on the command line.
TargetOpts.UseCASBackend = Opts.UseCASBackend;
// Set option to select the CASBackendMode.
TargetOpts.MCOptions.CASObjMode = Opts.CASObjMode;
auto *Clang = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
// WebAssembly doesn't support atomics yet, see
@@ -605,17 +611,31 @@ bool swift::performLLVM(const IRGenOptions &Opts,
if (OutputFilename.empty())
return false;
std::unique_ptr<raw_fd_ostream> CASIDFile;
if (Opts.UseCASBackend && Opts.EmitCASIDFile &&
Opts.CASObjMode != llvm::CASBackendMode::CASID &&
Opts.OutputKind == IRGenOutputKind::ObjectFile && OutputFilename != "-") {
std::string OutputFilenameCASID = std::string(OutputFilename);
OutputFilenameCASID.append(".casid");
std::error_code EC;
CASIDFile = std::make_unique<raw_fd_ostream>(OutputFilenameCASID, EC);
if (EC) {
diagnoseSync(Diags, DiagMutex, SourceLoc(), diag::error_opening_output,
OutputFilename, std::move(EC.message()));
return true;
}
}
return compileAndWriteLLVM(Module, TargetMachine, Opts, Stats, Diags,
*OutputFile, DiagMutex);
*OutputFile, DiagMutex,
CASIDFile ? CASIDFile.get() : nullptr);
}
bool swift::compileAndWriteLLVM(llvm::Module *module,
llvm::TargetMachine *targetMachine,
const IRGenOptions &opts,
UnifiedStatsReporter *stats,
DiagnosticEngine &diags,
llvm::raw_pwrite_stream &out,
llvm::sys::Mutex *diagMutex) {
bool swift::compileAndWriteLLVM(
llvm::Module *module, llvm::TargetMachine *targetMachine,
const IRGenOptions &opts, UnifiedStatsReporter *stats,
DiagnosticEngine &diags, llvm::raw_pwrite_stream &out,
llvm::sys::Mutex *diagMutex, llvm::raw_pwrite_stream *casid) {
// Set up the final code emission pass. Bitcode/LLVM IR is emitted as part of
// the optimization pass pipeline.
@@ -639,8 +659,8 @@ bool swift::compileAndWriteLLVM(llvm::Module *module,
EmitPasses.add(createTargetTransformInfoWrapperPass(
targetMachine->getTargetIRAnalysis()));
bool fail = targetMachine->addPassesToEmitFile(EmitPasses, out, nullptr,
FileType, !opts.Verify);
bool fail = targetMachine->addPassesToEmitFile(
EmitPasses, out, nullptr, FileType, !opts.Verify, nullptr, casid);
if (fail) {
diagnoseSync(diags, diagMutex, SourceLoc(),
diag::error_codegen_init_fail);

25
test/CAS/mccas.swift Normal file
View File

@@ -0,0 +1,25 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-backend-mode=verify -cas-path %t/cas -o %t/test-verify.o
// RUN: %llvm-dwarfdump %t/test-verify.o | %FileCheck %s --check-prefix=VERIFY-FILE
// VERIFY-FILE: .debug_info
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-backend-mode=native -cas-path %t/cas -o %t/test-native.o
// RUN: %llvm-dwarfdump %t/test-native.o | %FileCheck %s --check-prefix=NATIVE-FILE
// NATIVE-FILE: .debug_info
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-backend-mode=casid -cas-path %t/cas -o %t/test-casid.id
// RUN: cat %t/test-casid.id | %FileCheck %s --check-prefix=CASID-FILE
// CASID-FILE: CASID:Jllvmcas://{{.*}}
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-emit-casid-file -cas-backend-mode=verify -cas-path %t/cas -o %t/test-verify-emit.o
// RUN: cat %t/test-verify-emit.o.casid | %FileCheck %s --check-prefix=VERIFY-EMIT
// VERIFY-EMIT: CASID:Jllvmcas://{{.*}}
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-emit-casid-file -cas-backend-mode=native -cas-path %t/cas -o %t/test-native-emit.o
// RUN: cat %t/test-native-emit.o.casid | %FileCheck %s --check-prefix=NATIVE-EMIT
// NATIVE-EMIT: CASID:Jllvmcas://{{.*}}
// RUN: %target-swift-frontend -c %s -target arm64-apple-darwin23.0.0 -g -cas-backend -cas-emit-casid-file -cas-backend-mode=casid -cas-path %t/cas -o %t/test.id
// RUN: not cat %t/test.id.casid
func testFunc() {}