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; def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">, 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/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 CmdArgs; + /// \brief A list of all -fno-builtin-* function names (e.g., memset). std::vector 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: 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 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*)OS.str().data(), + OS.str().size()); + } else { + // If the input is LLVM bitcode, write the input byte stream directly. + ModuleData = ArrayRef((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 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: 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/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(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(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(JA)) CmdArgs.push_back("-disable-llvm-passes"); if (Output.getType() == types::TY_Dependencies) { 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: 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: 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 +}