Introduce -fembed-bitcode driver option
Summary:
This is the clang driver part of the change to embedded bitcode. This
includes:
1. -fembed-bitcode option which breaks down the compilation into two
stages. The first stage emits optimized bitcode and the second stage
compiles bitcode into object file.
2. -fembed-bitcode-marker option which doesn't really break down to
two stages to speedup the compilation flow.
3. pass the correct linker flag to darwin linker if tool chains supports
embedded bitcode.
Reviewers: rsmith, thakis
Subscribers: thakis, cfe-commits
Differential Revision: http://reviews.llvm.org/D17390
llvm-svn: 262282
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 6a85dab..eaf29de 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -50,7 +50,7 @@
DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<vfs::FileSystem> VFS)
: Opts(createDriverOptTable()), Diags(Diags), VFS(VFS), Mode(GCCMode),
- SaveTemps(SaveTempsNone), LTOMode(LTOK_None),
+ SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
ClangExecutable(ClangExecutable),
SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
DefaultTargetTriple(DefaultTargetTriple),
@@ -479,6 +479,19 @@
.Default(SaveTempsCwd);
}
+ // Ignore -fembed-bitcode options with LTO
+ // since the output will be bitcode anyway.
+ if (!Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) {
+ if (Args.hasArg(options::OPT_fembed_bitcode))
+ BitcodeEmbed = EmbedBitcode;
+ else if (Args.hasArg(options::OPT_fembed_bitcode_marker))
+ BitcodeEmbed = EmbedMarker;
+ } else {
+ // claim the bitcode option under LTO so no warning is issued.
+ Args.ClaimAllArgs(options::OPT_fembed_bitcode);
+ Args.ClaimAllArgs(options::OPT_fembed_bitcode_marker);
+ }
+
setLTOMode(Args);
std::unique_ptr<llvm::opt::InputArgList> UArgs =
@@ -1723,7 +1736,8 @@
// CudaHostAction, updates CollapsedCHA with the pointer to it so the
// caller can deal with extra handling such action requires.
static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
- const ToolChain *TC, const JobAction *JA,
+ bool EmbedBitcode, const ToolChain *TC,
+ const JobAction *JA,
const ActionList *&Inputs,
const CudaHostAction *&CollapsedCHA) {
const Tool *ToolForJob = nullptr;
@@ -1739,10 +1753,12 @@
!C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
isa<AssembleJobAction>(JA) && Inputs->size() == 1 &&
isa<BackendJobAction>(*Inputs->begin())) {
- // A BackendJob is always preceded by a CompileJob, and without
- // -save-temps they will always get combined together, so instead of
- // checking the backend tool, check if the tool for the CompileJob
- // has an integrated assembler.
+ // A BackendJob is always preceded by a CompileJob, and without -save-temps
+ // or -fembed-bitcode, they will always get combined together, so instead of
+ // checking the backend tool, check if the tool for the CompileJob has an
+ // integrated assembler. For -fembed-bitcode, CompileJob is still used to
+ // look up tools for BackendJob, but they need to match before we can split
+ // them.
const ActionList *BackendInputs = &(*Inputs)[0]->getInputs();
// Compile job may be wrapped in CudaHostAction, extract it if
// that's the case and update CollapsedCHA if we combine phases.
@@ -1753,6 +1769,14 @@
const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
+ // When using -fembed-bitcode, it is required to have the same tool (clang)
+ // for both CompilerJA and BackendJA. Otherwise, combine two stages.
+ if (EmbedBitcode) {
+ JobAction *InputJA = cast<JobAction>(*Inputs->begin());
+ const Tool *BackendTool = TC->SelectTool(*InputJA);
+ if (BackendTool == Compiler)
+ CompileJA = InputJA;
+ }
if (Compiler->hasIntegratedAssembler()) {
Inputs = &CompileJA->getInputs();
ToolForJob = Compiler;
@@ -1761,8 +1785,8 @@
}
// A backend job should always be combined with the preceding compile job
- // unless OPT_save_temps is enabled and the compiler is capable of emitting
- // LLVM IR as an intermediate output.
+ // unless OPT_save_temps or OPT_fembed_bitcode is enabled and the compiler is
+ // capable of emitting LLVM IR as an intermediate output.
if (isa<BackendJobAction>(JA)) {
// Check if the compiler supports emitting LLVM IR.
assert(Inputs->size() == 1);
@@ -1775,7 +1799,8 @@
const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
- if (!Compiler->canEmitIR() || !SaveTemps) {
+ if (!Compiler->canEmitIR() ||
+ (!SaveTemps && !EmbedBitcode)) {
Inputs = &CompileJA->getInputs();
ToolForJob = Compiler;
CollapsedCHA = CHA;
@@ -1889,7 +1914,8 @@
const JobAction *JA = cast<JobAction>(A);
const CudaHostAction *CollapsedCHA = nullptr;
const Tool *T =
- selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA);
+ selectToolForJob(C, isSaveTempsEnabled(), embedBitcodeEnabled(), TC, JA,
+ Inputs, CollapsedCHA);
if (!T)
return InputInfo();