steven_wu created this revision.
steven_wu added a subscriber: cfe-commits.
Herald added subscribers: dschuff, jfb.
Teach clang to embed bitcode inside bitcode. When -fembed-bitcode cc1
option is used, clang will embed both the input bitcode and cc1
commandline into the bitcode in special sections before compiling to
the object file. Using -fembed-bitcode-marker will only introduce a
marker in both sections.
Don't emit uselist order for -fembed-bitcode
Embedded bitcode are embedded without serialization in their normal
flow. No uselist order need to be recorded.
Apply whitelist to options used in embedded bitcode
Add a whitelist for the options that are allowed to be used with
-fembed-bitcode. That is minimize the number of the cc1 command
that needs to be embedded in the object file.
http://reviews.llvm.org/D17389
Files:
include/clang/Basic/DiagnosticDriverKinds.td
include/clang/CodeGen/BackendUtil.h
include/clang/Frontend/CodeGenOptions.def
include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/BackendUtil.cpp
lib/CodeGen/CodeGenAction.cpp
lib/Driver/Tools.cpp
lib/Driver/Tools.h
lib/Frontend/CompilerInvocation.cpp
test/Driver/embed-bitcode.c
test/Frontend/embed-bitcode.ll
Index: test/Frontend/embed-bitcode.ll
===================================================================
--- /dev/null
+++ test/Frontend/embed-bitcode.ll
@@ -0,0 +1,48 @@
+; check .ll input
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \
+; RUN: -fembed-bitcode -x ir %s -o - \
+; RUN: | FileCheck %s
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \
+; RUN: -fembed-bitcode-marker -x ir %s -o - \
+; RUN: | FileCheck %s -check-prefix=CHECK-MARKER
+; RUN: %clang_cc1 -triple aarch64-unknown-linux-gnueabi -emit-llvm \
+; RUN: -fembed-bitcode -x ir %s -o - \
+; RUN: | FileCheck %s -check-prefix=CHECK-ELF
+
+; check .bc input
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm-bc \
+; RUN: -x ir %s -o %t.bc
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \
+; RUN: -fembed-bitcode -x ir %t.bc -o - \
+; RUN: | FileCheck %s
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \
+; RUN: -fembed-bitcode-marker -x ir %t.bc -o - \
+; RUN: | FileCheck %s -check-prefix=CHECK-MARKER
+
+; run through -fembed-bitcode twice and make sure it doesn't crash
+; RUN: %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm-bc \
+; RUN: -fembed-bitcode -x ir %s -o - \
+; RUN: | %clang_cc1 -triple thumbv7-apple-ios8.0.0 -emit-llvm \
+; RUN: -fembed-bitcode -x ir - -o /dev/null
+
+; check the magic number of bitcode at the beginning of the string
+; CHECK: @llvm.embedded.module
+; CHECK: c"\DE\C0\17\0B
+; CHECK: section "__LLVM,__bitcode"
+; CHECK: @llvm.cmdline
+; CHECK: section "__LLVM,__cmdline"
+
+; CHECK-ELF: @llvm.embedded.module
+; CHECK-ELF: section ".llvmbc"
+; CHECK-ELF: @llvm.cmdline
+; CHECK-ELF: section ".llvmcmd"
+
+; CHECK-MARKER: @llvm.embedded.module
+; CHECK-MARKER: constant [0 x i8] zeroinitializer
+; CHECK-MARKER: section "__LLVM,__bitcode"
+; CHECK-MARKER: @llvm.cmdline
+; CHECK-MARKER: section "__LLVM,__cmdline"
+
+define i32 @f0() {
+ ret i32 0
+}
Index: test/Driver/embed-bitcode.c
===================================================================
--- test/Driver/embed-bitcode.c
+++ test/Driver/embed-bitcode.c
@@ -5,6 +5,7 @@
// RUN: %clang %s -fembed-bitcode 2>&1 -### | FileCheck %s -check-prefix=CHECK-CC
// CHECK-CC: -cc1
// CHECK-CC: -emit-llvm-bc
+// CHECK-CC-NOT: -emit-llvm-uselists
// CHECK-CC: -cc1
// CHECK-CC: -emit-obj
// CHECK-CC: -fembed-bitcode
@@ -24,3 +25,62 @@
// CHECK-MARKER: -fembed-bitcode-marker
// CHECK-MARKER-NOT: -cc1
+// Check clang complains about ios version min if it is used to generate link command.
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -fembed-bitcode -### 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-PLATFORM-SUPPORTED
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=5.0 %s -fembed-bitcode -### 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-PLATFORM-UNSUPPORTED
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=5.0 -c %s -fembed-bitcode -### 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-PLATFORM-SUPPORTED
+// CHECK-PLATFORM-SUPPORTED-NOT: -fembed-bitcode is not supported on versions of iOS prior to 6.0
+// CHECK-PLATFORM-UNSUPPORTED: -fembed-bitcode is not supported on versions of iOS prior to 6.0
+
+// RUN: %clang -c %s -fembed-bitcode -mkernel -fapple-kext -ffunction-sections \
+// RUN: -fno-function-sections -fdata-sections -fno-data-sections \
+// RUN: -funique-section-names -fno-unique-section-names -mrestrict-it \
+// RUN: -mno-restrict-it -mstackrealgin -mno-stackrealign -mstack-alignment=8 \
+// RUN: -mcmodel=small -mlong-calls -mno-long-calls -ggnu-pubnames \
+// RUN: -gdwarf-arange -fdebug-types-section -fno-debug-types-section \
+// RUN: -fdwarf-directory-asm -fno-dwarf-directory-asm \
+// RUN: -mrelax-all -mno-relax-all -ftrap-function=trap \
+// RUN: -ffixed-r9 -mfix-cortex-a53-835769 -mno-fix-cortex-a53-835769 \
+// RUN: -ffixed-x18 -mglobal-merge -mno-global-merge -mred-zone -mno-red-zone \
+// RUN: -Wa,-L -Xlinker,-L -mllvm -test -### 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-UNSUPPORTED-OPT
+// CHECK-UNSUPPORTED-OPT: -mkernel is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fapple-kext is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -ffunction-sections is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fno-function-sections is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fdata-sections is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fno-data-sections is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -funique-section-names is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fno-unique-section-names is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mrestrict-it is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-restrict-it is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-stackrealign is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mstack-alignment= is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mcmodel= is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mlong-calls is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-long-calls is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -ggnu-pubnames is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fdebug-types-section is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fno-debug-types-section is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fdwarf-directory-asm is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -fno-dwarf-directory-asm is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mrelax-all is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-relax-all is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -ftrap-function= is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -ffixed-r9 is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mfix-cortex-a53-835769 is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-fix-cortex-a53-835769 is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -ffixed-x18 is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mglobal-merge is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-global-merge is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mred-zone is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mno-red-zone is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -Wa, is not supported with -fembed-bitcode
+// CHECK-UNSUPPORTED-OPT: -mllvm is not supported with -fembed-bitcode
+
+// Check -mrelax-all is not passed as CC1 flag even with -O0.
+// RUN: %clang %s -fembed-bitcode -O0 2>&1 -### | FileCheck %s -check-prefix=CHECK-RELAX-ALL
+// CHECK-RELAX-ALL-NOT: -mrelax-all
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -616,6 +616,34 @@
}
}
}
+ // Handle -fembed-bitcode option.
+ Opts.EmbedBitcode = Args.hasArg(OPT_fembed_bitcode);
+ Opts.EmbedMarkerOnly = Args.hasArg(OPT_fembed_bitcode_marker);
+ // FIXME: For backend options that are not yet recorded as function
+ // attributes in the IR, keep track of them so we can embed them in a
+ // separate data section and use them when building the bitcode.
+ if (Opts.EmbedBitcode) {
+ for (ArgList::const_iterator A = Args.begin(), AE = Args.end();
+ A != AE; ++ A) {
+ // Do not encode output and input.
+ if ((*A)->getOption().getID() == options::OPT_o ||
+ (*A)->getOption().getID() == options::OPT_INPUT ||
+ (*A)->getOption().getID() == options::OPT_x ||
+ (*A)->getOption().getID() == options::OPT_fembed_bitcode ||
+ ((*A)->getOption().getGroup().isValid() &&
+ (*A)->getOption().getGroup().getID() == options::OPT_W_Group))
+ continue;
+ ArgStringList ASL;
+ (*A)->render(Args, ASL);
+ for (ArgStringList::iterator it = ASL.begin(), ie = ASL.end();
+ it != ie; ++ it) {
+ StringRef ArgStr(*it);
+ Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
+ // using \00 to seperate each commandline options.
+ Opts.CmdArgs.push_back('\0');
+ }
+ }
+ }
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -91,6 +91,10 @@
llvm::opt::ArgStringList &cmdArgs,
RewriteKind rewrite) const;
+ void RenderEmbeddedBitcodeOptions(const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
void AddClangCLArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind *DebugInfoKind,
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -2481,6 +2481,11 @@
/// \brief Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
+ // If embed bitcode, RelaxAll is not allowed.
+ if (C.getDriver().embedBitcodeEnabled() ||
+ C.getDriver().embedBitcodeMarkerOnly())
+ return false;
+
bool RelaxDefault = true;
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
@@ -3470,6 +3475,184 @@
CmdArgs.push_back("-KPIC");
}
+void Clang::RenderEmbeddedBitcodeOptions(const llvm::Triple &Triple,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ // reject options that shouldn't be supported in bitcode
+ // also reject kernel/kext.
+ for (const auto &A : Args) {
+ if (A->getOption().getID() == options::OPT_mkernel ||
+ A->getOption().getID() == options::OPT_fapple_kext ||
+ A->getOption().getID() == options::OPT_ffunction_sections ||
+ A->getOption().getID() == options::OPT_fno_function_sections ||
+ A->getOption().getID() == options::OPT_fdata_sections ||
+ A->getOption().getID() == options::OPT_fno_data_sections ||
+ A->getOption().getID() == options::OPT_funique_section_names ||
+ A->getOption().getID() == options::OPT_fno_unique_section_names ||
+ A->getOption().getID() == options::OPT_mrestrict_it ||
+ A->getOption().getID() == options::OPT_mno_restrict_it ||
+ A->getOption().getID() == options::OPT_mstackrealign ||
+ A->getOption().getID() == options::OPT_mno_stackrealign ||
+ A->getOption().getID() == options::OPT_mstack_alignment ||
+ A->getOption().getID() == options::OPT_mcmodel_EQ ||
+ A->getOption().getID() == options::OPT_mlong_calls ||
+ A->getOption().getID() == options::OPT_mno_long_calls ||
+ A->getOption().getID() == options::OPT_ggnu_pubnames ||
+ A->getOption().getID() == options::OPT_gdwarf_aranges ||
+ A->getOption().getID() == options::OPT_fdebug_types_section ||
+ A->getOption().getID() == options::OPT_fno_debug_types_section ||
+ A->getOption().getID() == options::OPT_fdwarf_directory_asm ||
+ A->getOption().getID() == options::OPT_fno_dwarf_directory_asm ||
+ A->getOption().getID() == options::OPT_mrelax_all ||
+ A->getOption().getID() == options::OPT_mno_relax_all ||
+ A->getOption().getID() == options::OPT_ftrap_function_EQ ||
+ A->getOption().getID() == options::OPT_ffixed_r9 ||
+ A->getOption().getID() == options::OPT_mfix_cortex_a53_835769 ||
+ A->getOption().getID() == options::OPT_mno_fix_cortex_a53_835769 ||
+ A->getOption().getID() == options::OPT_ffixed_x18 ||
+ A->getOption().getID() == options::OPT_mglobal_merge ||
+ A->getOption().getID() == options::OPT_mno_global_merge ||
+ A->getOption().getID() == options::OPT_mred_zone ||
+ A->getOption().getID() == options::OPT_mno_red_zone ||
+ A->getOption().getID() == options::OPT_Wa_COMMA ||
+ A->getOption().getID() == options::OPT_Xassembler ||
+ A->getOption().getID() == options::OPT_mllvm)
+ D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
+ }
+
+ // render float point related args
+ if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+ CmdArgs.push_back("-mlimit-float-precision");
+ CmdArgs.push_back(A->getValue());
+ }
+ bool OFastEnabled = isOptimizationLevelFast(Args);
+ OptSpecifier FastMathAliasOption =
+ OFastEnabled ? options::OPT_Ofast : options::OPT_ffast_math;
+ bool MathErrno = getToolChain().IsMathErrnoDefault();
+ if (Arg *A =
+ Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_fmath_errno,
+ options::OPT_fno_math_errno)) {
+ // Turning on -ffast_math (with either flag) removes the need for MathErrno.
+ // However, turning *off* -ffast_math merely restores the toolchain default
+ // (which may be false).
+ if (A->getOption().getID() == options::OPT_fno_math_errno ||
+ A->getOption().getID() == options::OPT_ffast_math ||
+ A->getOption().getID() == options::OPT_Ofast)
+ MathErrno = false;
+ else if (A->getOption().getID() == options::OPT_fmath_errno)
+ MathErrno = true;
+ }
+ if (MathErrno)
+ CmdArgs.push_back("-fmath-errno");
+ bool ReciprocalMath = false;
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_freciprocal_math, options::OPT_fno_reciprocal_math))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fno_reciprocal_math)
+ ReciprocalMath = true;
+ bool SignedZeros = true;
+ if (Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fsigned_zeros, options::OPT_fno_signed_zeros))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fsigned_zeros)
+ SignedZeros = false;
+
+ if (!SignedZeros)
+ CmdArgs.push_back("-fno-signed-zeros");
+
+ if (ReciprocalMath)
+ CmdArgs.push_back("-freciprocal-math");
+
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_ffp_contract)) {
+ if (A->getOption().getID() == options::OPT_ffp_contract) {
+ StringRef Val = A->getValue();
+ if (Val == "fast" || Val == "on" || Val == "off") {
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+ } else if (A->getOption().matches(options::OPT_ffast_math) ||
+ (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ }
+ }
+
+ // Add target specific flags.
+ switch (getToolChain().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ // Use the effective triple, which takes into account the deployment target.
+ AddARMTargetArgs(Triple, Args, CmdArgs, false);
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ AddAArch64TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ AddPPCTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ AddSparcTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::hexagon:
+ AddHexagonTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ AddWebAssemblyTargetArgs(Args, CmdArgs);
+ break;
+ }
+
+ // Optimization level for CodeGen.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
@@ -3534,11 +3717,6 @@
<< TripleStr;
}
- // Push all default warning arguments that are specific to
- // the given target. These come before user provided warning options
- // are provided.
- getToolChain().addClangWarningOptions(CmdArgs);
-
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
@@ -3606,7 +3784,9 @@
// loading the bitcode up in 'opt' or 'llc' and running passes gives the
// same result as running passes here. For LTO, we don't need to preserve
// the use-list order, since serialization to bitcode is part of the flow.
- if (JA.getType() == types::TY_LLVM_BC)
+ // For embed-bitcode, bitcode is directly embedded without serialization.
+ if (JA.getType() == types::TY_LLVM_BC &&
+ !C.getDriver().embedBitcodeEnabled())
CmdArgs.push_back("-emit-llvm-uselists");
if (D.isUsingLTO())
@@ -3627,6 +3807,30 @@
CmdArgs.push_back("-fembed-bitcode");
// Disable all llvm IR level optimizations.
CmdArgs.push_back("-disable-llvm-optzns");
+
+ RenderEmbeddedBitcodeOptions(Triple, Args, CmdArgs);
+
+ // Input/Output file.
+ if (Output.getType() == types::TY_Dependencies) {
+ // Handled with other dependency code.
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ for (const auto &II : Inputs) {
+ addDashXForInput(Args, II, CmdArgs);
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ return;
}
if (C.getDriver().embedBitcodeMarkerOnly())
CmdArgs.push_back("-fembed-bitcode-marker");
@@ -4406,6 +4610,11 @@
}
}
+ // Push all default warning arguments that are specific to
+ // the given target. These come before user provided warning options
+ // are provided.
+ getToolChain().addClangWarningOptions(CmdArgs);
+
// Warn about ignored options to clang.
for (const Arg *A :
Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
@@ -5553,7 +5762,10 @@
// With -save-temps, we want to save the unoptimized bitcode output from the
// CompileJobAction, use -disable-llvm-passes to get pristine IR generated
// by the frontend.
- if (C.getDriver().isSaveTempsEnabled() && isa<CompileJobAction>(JA))
+ // When -fembed-bitcode is enabled, optimized bitcode is emitted because it
+ // has slightly different breakdown between stages.
+ if (C.getDriver().isSaveTempsEnabled() &&
+ !C.getDriver().embedBitcodeEnabled() && isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-passes");
if (Output.getType() == types::TY_Dependencies) {
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -173,6 +173,8 @@
return;
}
+ EmbedBitcode(TheModule.get(), CodeGenOpts, llvm::MemoryBufferRef());
+
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
C.getTargetInfo().getDataLayoutString(),
getModule(), Action, AsmOutStream);
@@ -823,6 +825,9 @@
TheModule->setTargetTriple(TargetOpts.Triple);
}
+ EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(),
+ MainFile->getMemBufferRef());
+
LLVMContext &Ctx = TheModule->getContext();
Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -16,9 +16,11 @@
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/IR/DataLayout.h"
@@ -721,3 +723,86 @@
}
}
}
+
+static const char* getSectionNameForBitcode(const Triple &T) {
+ switch (T.getObjectFormat()) {
+ case Triple::MachO:
+ return "__LLVM,__bitcode";
+ case Triple::COFF:
+ case Triple::ELF:
+ case Triple::UnknownObjectFormat:
+ return ".llvmbc";
+ }
+}
+
+static const char* getSectionNameForCommandline(const Triple &T) {
+ switch (T.getObjectFormat()) {
+ case Triple::MachO:
+ return "__LLVM,__cmdline";
+ case Triple::COFF:
+ case Triple::ELF:
+ case Triple::UnknownObjectFormat:
+ return ".llvmcmd";
+ }
+}
+
+// With -fembed-bitcode, save a copy of the llvm IR as data in the
+// __LLVM,__bitcode section.
+void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
+ llvm::MemoryBufferRef Buf)
+{
+ if (!CGOpts.EmbedBitcode && !CGOpts.EmbedMarkerOnly)
+ return;
+
+ // Embed the bitcode for the llvm module.
+ std::string Data;
+ ArrayRef<uint8_t> ModuleData;
+ Triple T(M->getTargetTriple());
+ if (!CGOpts.EmbedMarkerOnly) {
+ if (!isBitcode((const unsigned char*)Buf.getBufferStart(),
+ (const unsigned char*)Buf.getBufferEnd())) {
+ // If the input is LLVM Assembly, bitcode is produced by serializing
+ // the module. Use-lists order need to be perserved in this case.
+ llvm::raw_string_ostream OS(Data);
+ llvm::WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ true);
+ ModuleData = ArrayRef<uint8_t>((uint8_t*)OS.str().data(),
+ OS.str().size());
+ } else {
+ // If the input is LLVM bitcode, write the input byte stream directly.
+ ModuleData = ArrayRef<uint8_t>((uint8_t*)Buf.getBufferStart(),
+ Buf.getBufferSize());
+ }
+ }
+ llvm::Constant *ModuleConstant =
+ llvm::ConstantDataArray::get(M->getContext(), ModuleData);
+ // Use Appending linkage so it doesn't get optimized out.
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ *M, ModuleConstant->getType(), true, llvm::GlobalValue::AppendingLinkage,
+ ModuleConstant);
+ GV->setSection(getSectionNameForBitcode(T));
+ if (llvm::GlobalVariable *Old =
+ M->getGlobalVariable("llvm.embedded.module")) {
+ assert(Old->use_empty() && "llvm.embedded.module must have no uses");
+ GV->takeName(Old);
+ Old->eraseFromParent();
+ } else {
+ GV->setName("llvm.embedded.module");
+ }
+
+ // Embed command-line options.
+ ArrayRef<uint8_t> CmdData((uint8_t*)CGOpts.CmdArgs.data(),
+ CGOpts.CmdArgs.size());
+ llvm::Constant *CmdConstant =
+ llvm::ConstantDataArray::get(M->getContext(), CmdData);
+ GV = new llvm::GlobalVariable(*M, CmdConstant->getType(), true,
+ llvm::GlobalValue::AppendingLinkage,
+ CmdConstant);
+ GV->setSection(getSectionNameForCommandline(T));
+ if (llvm::GlobalVariable *Old = M->getGlobalVariable("llvm.cmdline")) {
+ assert(Old->use_empty() && "llvm.cmdline must have no uses");
+ GV->takeName(Old);
+ Old->eraseFromParent();
+ } else {
+ GV->setName("llvm.cmdline");
+ }
+}
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -198,6 +198,9 @@
/// Set of sanitizer checks that trap rather than diagnose.
SanitizerSet SanitizeTrap;
+ /// List of backend command-line options for -fembed-bitcode.
+ std::vector<uint8_t> CmdArgs;
+
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
std::vector<std::string> NoBuiltinFuncs;
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -53,6 +53,8 @@
///< frontend.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
+CODEGENOPT(EmbedBitcode , 1, 0) ///< Embed LLVM IR bitcode as data.
+CODEGENOPT(EmbedMarkerOnly , 1, 0) ///< Only create bitcode section as marker
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
///< Decl* various IR entities came from.
///< Only useful when running CodeGen as a
Index: include/clang/CodeGen/BackendUtil.h
===================================================================
--- include/clang/CodeGen/BackendUtil.h
+++ include/clang/CodeGen/BackendUtil.h
@@ -16,6 +16,7 @@
namespace llvm {
class Module;
+ class MemoryBufferRef;
}
namespace clang {
@@ -37,6 +38,9 @@
const TargetOptions &TOpts, const LangOptions &LOpts,
StringRef TDesc, llvm::Module *M, BackendAction Action,
raw_pwrite_stream *OS);
+
+ void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
+ llvm::MemoryBufferRef Buf);
}
#endif
Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -136,6 +136,8 @@
"The target '%0' is not a supported OpenMP host target.">;
def err_drv_bitcode_unsupported_on_toolchain : Error<
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
+def err_drv_unsupported_embed_bitcode : Error<
+ "%0 is not supported with -fembed-bitcode">;
def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits