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: 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; @@ -3629,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"); @@ -4408,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)) { Index: test/Driver/embed-bitcode.c =================================================================== --- test/Driver/embed-bitcode.c +++ test/Driver/embed-bitcode.c @@ -35,3 +35,52 @@ // 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