diff options
Diffstat (limited to 'lib/Driver/ToolChains/Clang.cpp')
-rw-r--r-- | lib/Driver/ToolChains/Clang.cpp | 889 |
1 files changed, 699 insertions, 190 deletions
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 8e9c4c6aecb87..75f16898dfaf6 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -19,12 +19,14 @@ #include "AMDGPU.h" #include "CommonArgs.h" #include "Hexagon.h" +#include "MSP430.h" #include "InputInfo.h" #include "PS4CPU.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" +#include "clang/Driver/Distro.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" @@ -341,7 +343,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Args, Features); + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: @@ -363,6 +365,8 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, case llvm::Triple::amdgcn: amdgpu::getAMDGPUTargetFeatures(D, Args, Features); break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); } // Find the last of each feature. @@ -493,6 +497,8 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { if (A.getOption().matches(options::OPT_gline_tables_only) || A.getOption().matches(options::OPT_ggdb1)) return codegenoptions::DebugLineTablesOnly; + if (A.getOption().matches(options::OPT_gline_directives_only)) + return codegenoptions::DebugDirectivesOnly; return codegenoptions::LimitedDebugInfo; } @@ -524,11 +530,12 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, break; } - if (Triple.getOS() == llvm::Triple::NetBSD) { + if (Triple.isOSNetBSD()) { return !areOptimizationsEnabled(Args); } - if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) { + if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI || + Triple.isOSHurd()) { switch (Triple.getArch()) { // Don't use a frame pointer on linux if optimizing for certain targets. case llvm::Triple::mips64: @@ -800,6 +807,29 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, CmdArgs.push_back("-fcoverage-mapping"); } + if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { + auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); + if (!Args.hasArg(options::OPT_coverage)) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << "-fprofile-exclude-files=" + << "--coverage"; + + StringRef v = Arg->getValue(); + CmdArgs.push_back( + Args.MakeArgString(Twine("-fprofile-exclude-files=" + v))); + } + + if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) { + auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ); + if (!Args.hasArg(options::OPT_coverage)) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << "-fprofile-filter-files=" + << "--coverage"; + + StringRef v = Arg->getValue(); + CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v))); + } + if (C.getArgs().hasArg(options::OPT_c) || C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { @@ -889,6 +919,9 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs, unsigned DwarfVersion, llvm::DebuggerKind DebuggerTuning) { switch (DebugInfoKind) { + case codegenoptions::DebugDirectivesOnly: + CmdArgs.push_back("-debug-info-kind=line-directives-only"); + break; case codegenoptions::DebugLineTablesOnly: CmdArgs.push_back("-debug-info-kind=line-tables-only"); break; @@ -1100,10 +1133,19 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue(); if (!isa<PrecompileJobAction>(JA)) { CmdArgs.push_back("-include-pch"); - CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader))); + CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath( + C, !ThroughHeader.empty() + ? ThroughHeader + : llvm::sys::path::filename(Inputs[0].getBaseInput())))); + } + + if (ThroughHeader.empty()) { + CmdArgs.push_back(Args.MakeArgString( + Twine("-pch-through-hdrstop-") + (YcArg ? "create" : "use"))); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); } - CmdArgs.push_back( - Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); } } @@ -1114,42 +1156,26 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, bool IsFirstImplicitInclude = !RenderedImplicitInclude; RenderedImplicitInclude = true; - // Use PCH if the user requested it. - bool UsePCH = D.CCCUsePCH; - - bool FoundPTH = false; bool FoundPCH = false; SmallString<128> P(A->getValue()); // We want the files to have a name like foo.h.pch. Add a dummy extension // so that replace_extension does the right thing. P += ".dummy"; - if (UsePCH) { - llvm::sys::path::replace_extension(P, "pch"); - if (llvm::sys::fs::exists(P)) - FoundPCH = true; - } + llvm::sys::path::replace_extension(P, "pch"); + if (llvm::sys::fs::exists(P)) + FoundPCH = true; if (!FoundPCH) { - llvm::sys::path::replace_extension(P, "pth"); - if (llvm::sys::fs::exists(P)) - FoundPTH = true; - } - - if (!FoundPCH && !FoundPTH) { llvm::sys::path::replace_extension(P, "gch"); if (llvm::sys::fs::exists(P)) { - FoundPCH = UsePCH; - FoundPTH = !UsePCH; + FoundPCH = true; } } - if (FoundPCH || FoundPTH) { + if (FoundPCH) { if (IsFirstImplicitInclude) { A->claim(); - if (UsePCH) - CmdArgs.push_back("-include-pch"); - else - CmdArgs.push_back("-include-pth"); + CmdArgs.push_back("-include-pch"); CmdArgs.push_back(Args.MakeArgString(P)); continue; } else { @@ -1283,21 +1309,28 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { } } -void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, - ArgStringList &CmdArgs, bool KernelOrKext) const { +namespace { +void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs) { // Select the ABI to use. // FIXME: Support -meabi. // FIXME: Parts of this are duplicated in the backend, unify this somehow. const char *ABIName = nullptr; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); - else { + } else { std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false); ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data(); } CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); +} +} + +void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs, bool KernelOrKext) const { + RenderARMABI(Triple, Args, CmdArgs); // Determine floating point ABI from the options & target defaults. arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args); @@ -1409,19 +1442,59 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple, } } -void Clang::AddAArch64TargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); +// Parse -mbranch-protection=<protection>[+<protection>]* where +// <protection> ::= standard | none | [bti,pac-ret[+b-key,+leaf]*] +// Returns a triple of (return address signing Scope, signing key, require +// landing pads) +static std::tuple<StringRef, StringRef, bool> +ParseAArch64BranchProtection(const Driver &D, const ArgList &Args, + const Arg *A) { + StringRef Scope = "none"; + StringRef Key = "a_key"; + bool IndirectBranches = false; - if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || - Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_fapple_kext)) - CmdArgs.push_back("-disable-red-zone"); + StringRef Value = A->getValue(); + // This maps onto -mbranch-protection=<scope>+<key> + + if (Value.equals("standard")) { + Scope = "non-leaf"; + Key = "a_key"; + IndirectBranches = true; + + } else if (!Value.equals("none")) { + SmallVector<StringRef, 4> BranchProtection; + StringRef(A->getValue()).split(BranchProtection, '+'); + + auto Protection = BranchProtection.begin(); + while (Protection != BranchProtection.end()) { + if (Protection->equals("bti")) + IndirectBranches = true; + else if (Protection->equals("pac-ret")) { + Scope = "non-leaf"; + while (++Protection != BranchProtection.end()) { + // Inner loop as "leaf" and "b-key" options must only appear attached + // to pac-ret. + if (Protection->equals("leaf")) + Scope = "all"; + else if (Protection->equals("b-key")) + Key = "b_key"; + else + break; + } + Protection--; + } else + D.Diag(diag::err_invalid_branch_protection) + << *Protection << A->getAsString(Args); + Protection++; + } + } - if (!Args.hasFlag(options::OPT_mimplicit_float, - options::OPT_mno_implicit_float, true)) - CmdArgs.push_back("-no-implicit-float"); + return std::make_tuple(Scope, Key, IndirectBranches); +} +namespace { +void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs) { const char *ABIName = nullptr; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(); @@ -1432,6 +1505,23 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); +} +} + +void Clang::AddAArch64TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + + if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || + Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) + CmdArgs.push_back("-disable-red-zone"); + + if (!Args.hasFlag(options::OPT_mimplicit_float, + options::OPT_mno_implicit_float, true)) + CmdArgs.push_back("-no-implicit-float"); + + RenderAArch64ABI(Triple, Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769, options::OPT_mno_fix_cortex_a53_835769)) { @@ -1455,6 +1545,35 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, else CmdArgs.push_back("-aarch64-enable-global-merge=true"); } + + // Enable/disable return address signing and indirect branch targets. + if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ, + options::OPT_mbranch_protection_EQ)) { + + const Driver &D = getToolChain().getDriver(); + + StringRef Scope, Key; + bool IndirectBranches; + + if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { + Scope = A->getValue(); + if (!Scope.equals("none") && !Scope.equals("non-leaf") && + !Scope.equals("all")) + D.Diag(diag::err_invalid_branch_protection) + << Scope << A->getAsString(Args); + Key = "a_key"; + IndirectBranches = false; + } else + std::tie(Scope, Key, IndirectBranches) = + ParseAArch64BranchProtection(D, Args, A); + + CmdArgs.push_back( + Args.MakeArgString(Twine("-msign-return-address=") + Scope)); + CmdArgs.push_back( + Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); + if (IndirectBranches) + CmdArgs.push_back("-mbranch-target-enforce"); + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -1706,6 +1825,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args, Args.hasArg(options::OPT_fapple_kext)) CmdArgs.push_back("-disable-red-zone"); + if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs, + options::OPT_mno_tls_direct_seg_refs, true)) + CmdArgs.push_back("-mno-tls-direct-seg-refs"); + // Default to avoid implicit floating-point for kernel/kext code, but allow // that to be overridden with -mno-soft-float. bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) || @@ -2033,6 +2156,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } CmdArgs.push_back(Value.data()); TakeNextArg = true; + } else if (Value == "-fdebug-compilation-dir") { + CmdArgs.push_back("-fdebug-compilation-dir"); + TakeNextArg = true; } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -2045,6 +2171,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); } + + // forward -fembed-bitcode to assmebler + if (C.getDriver().embedBitcodeEnabled() || + C.getDriver().embedBitcodeMarkerOnly()) + Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); } static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, @@ -2066,6 +2197,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, StringRef DenormalFPMath = ""; StringRef FPContract = ""; + if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { + CmdArgs.push_back("-mlimit-float-precision"); + CmdArgs.push_back(A->getValue()); + } + for (const Arg *A : Args) { switch (A->getOption().getID()) { // If this isn't an FP option skip the claim below @@ -2228,8 +2364,6 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, // Treat blocks as analysis entry points. CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); - CmdArgs.push_back("-analyzer-eagerly-assume"); - // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); @@ -2339,6 +2473,50 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args, } } +static void RenderTrivialAutoVarInitOptions(const Driver &D, + const ToolChain &TC, + const ArgList &Args, + ArgStringList &CmdArgs) { + auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit(); + StringRef TrivialAutoVarInit = ""; + + for (const Arg *A : Args) { + switch (A->getOption().getID()) { + default: + continue; + case options::OPT_ftrivial_auto_var_init: { + A->claim(); + StringRef Val = A->getValue(); + if (Val == "uninitialized" || Val == "zero" || Val == "pattern") + TrivialAutoVarInit = Val; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + break; + } + } + } + + if (TrivialAutoVarInit.empty()) + switch (DefaultTrivialAutoVarInit) { + case LangOptions::TrivialAutoVarInitKind::Uninitialized: + break; + case LangOptions::TrivialAutoVarInitKind::Pattern: + TrivialAutoVarInit = "pattern"; + break; + case LangOptions::TrivialAutoVarInitKind::Zero: + TrivialAutoVarInit = "zero"; + break; + } + + if (!TrivialAutoVarInit.empty()) { + if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero)) + D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled); + CmdArgs.push_back( + Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit)); + } +} + static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) { const unsigned ForwardedArguments[] = { options::OPT_cl_opt_disable, @@ -2658,8 +2836,10 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, CmdArgs.push_back("-fno-signed-char"); } - if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false)) - CmdArgs.push_back("-fchar8_t"); + // The default depends on the language standard. + if (const Arg *A = + Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t)) + A->render(Args, CmdArgs); if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar, options::OPT_fno_short_wchar)) { @@ -2669,8 +2849,8 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, } else { bool IsARM = T.isARM() || T.isThumb() || T.isAArch64(); CmdArgs.push_back("-fwchar-type=int"); - if (IsARM && !(T.isOSWindows() || T.getOS() == llvm::Triple::NetBSD || - T.getOS() == llvm::Triple::OpenBSD)) + if (IsARM && !(T.isOSWindows() || T.isOSNetBSD() || + T.isOSOpenBSD())) CmdArgs.push_back("-fno-signed-wchar"); else CmdArgs.push_back("-fsigned-wchar"); @@ -2701,7 +2881,6 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D, // When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option // to do Array/Dictionary subscripting by default. if (Arch == llvm::Triple::x86 && T.isMacOSX() && - !T.isMacOSXVersionLT(10, 7) && Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily()) CmdArgs.push_back("-fobjc-subscripting-legacy-runtime"); @@ -2737,6 +2916,18 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D, Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions); } + // Allow the user to control whether messages can be converted to runtime + // functions. + if (types::isObjC(Input.getType())) { + auto *Arg = Args.getLastArg( + options::OPT_fobjc_convert_messages_to_runtime_calls, + options::OPT_fno_objc_convert_messages_to_runtime_calls); + if (Arg && + Arg->getOption().matches( + options::OPT_fno_objc_convert_messages_to_runtime_calls)) + CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls"); + } + // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. if (InferCovariantReturns) @@ -2872,12 +3063,35 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args, CmdArgs.push_back("-fno-spell-checking"); } +enum class DwarfFissionKind { None, Split, Single }; + +static DwarfFissionKind getDebugFissionKind(const Driver &D, + const ArgList &Args, Arg *&Arg) { + Arg = + Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ); + if (!Arg) + return DwarfFissionKind::None; + + if (Arg->getOption().matches(options::OPT_gsplit_dwarf)) + return DwarfFissionKind::Split; + + StringRef Value = Arg->getValue(); + if (Value == "split") + return DwarfFissionKind::Split; + if (Value == "single") + return DwarfFissionKind::Single; + + D.Diag(diag::err_drv_unsupported_option_argument) + << Arg->getOption().getName() << Arg->getValue(); + return DwarfFissionKind::None; +} + static void RenderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, const ArgList &Args, bool EmitCodeView, bool IsWindowsMSVC, ArgStringList &CmdArgs, codegenoptions::DebugInfoKind &DebugInfoKind, - const Arg *&SplitDWARFArg) { + DwarfFissionKind &DwarfFission) { if (Args.hasFlag(options::OPT_fdebug_info_for_profiling, options::OPT_fno_debug_info_for_profiling, false) && checkDebugInfoOption( @@ -2902,10 +3116,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, Args.ClaimAllArgs(options::OPT_g_Group); - SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf); + Arg* SplitDWARFArg; + DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg); - if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) { - SplitDWARFArg = nullptr; + if (DwarfFission != DwarfFissionKind::None && + !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) { + DwarfFission = DwarfFissionKind::None; SplitDWARFInlining = false; } @@ -2922,12 +3138,13 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, // composing split-dwarf and line-tables-only, so let those compose // naturally in that case. And if you just turned off debug info, // (-gsplit-dwarf -g0) - do that. - if (SplitDWARFArg) { + if (DwarfFission != DwarfFissionKind::None) { if (A->getIndex() > SplitDWARFArg->getIndex()) { if (DebugInfoKind == codegenoptions::NoDebugInfo || + DebugInfoKind == codegenoptions::DebugDirectivesOnly || (DebugInfoKind == codegenoptions::DebugLineTablesOnly && SplitDWARFInlining)) - SplitDWARFArg = nullptr; + DwarfFission = DwarfFissionKind::None; } else if (SplitDWARFInlining) DebugInfoKind = codegenoptions::NoDebugInfo; } @@ -2960,21 +3177,28 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, if (checkDebugInfoOption(A, Args, D, TC)) DWARFVersion = DwarfVersionNum(A->getSpelling()); - // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility - // argument parsing. - if (EmitCodeView) { - if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) { - EmitCodeView = checkDebugInfoOption(A, Args, D, TC); - if (EmitCodeView) { - // DWARFVersion remains at 0 if no explicit choice was made. - CmdArgs.push_back("-gcodeview"); - } - } + if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) { + if (checkDebugInfoOption(A, Args, D, TC)) + EmitCodeView = true; } + // If the user asked for debug info but did not explicitly specify -gcodeview + // or -gdwarf, ask the toolchain for the default format. if (!EmitCodeView && DWARFVersion == 0 && - DebugInfoKind != codegenoptions::NoDebugInfo) - DWARFVersion = TC.GetDefaultDwarfVersion(); + DebugInfoKind != codegenoptions::NoDebugInfo) { + switch (TC.getDefaultDebugFormat()) { + case codegenoptions::DIF_CodeView: + EmitCodeView = true; + break; + case codegenoptions::DIF_DWARF: + DWARFVersion = TC.GetDefaultDwarfVersion(); + break; + } + } + + // -gline-directives-only supported only for the DWARF debug info. + if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly) + DebugInfoKind = codegenoptions::NoDebugInfo; // We ignore flag -gstrict-dwarf for now. // And we handle flag -grecord-gcc-switches later with DWARFDebugFlags. @@ -2993,10 +3217,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-dwarf-column-info"); // FIXME: Move backend command line options to the module. - // If -gline-tables-only is the last option it wins. + // If -gline-tables-only or -gline-directives-only is the last option it wins. if (const Arg *A = Args.getLastArg(options::OPT_gmodules)) if (checkDebugInfoOption(A, Args, D, TC)) { - if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) { + if (DebugInfoKind != codegenoptions::DebugLineTablesOnly && + DebugInfoKind != codegenoptions::DebugDirectivesOnly) { DebugInfoKind = codegenoptions::LimitedDebugInfo; CmdArgs.push_back("-dwarf-ext-refs"); CmdArgs.push_back("-fmodule-format=obj"); @@ -3005,15 +3230,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, // -gsplit-dwarf should turn on -g and enable the backend dwarf // splitting and extraction. - // FIXME: Currently only works on Linux. - if (T.isOSLinux()) { + // FIXME: Currently only works on Linux and Fuchsia. + if (T.isOSLinux() || T.isOSFuchsia()) { if (!SplitDWARFInlining) CmdArgs.push_back("-fno-split-dwarf-inlining"); - if (SplitDWARFArg) { + if (DwarfFission != DwarfFissionKind::None) { if (DebugInfoKind == codegenoptions::NoDebugInfo) DebugInfoKind = codegenoptions::LimitedDebugInfo; - CmdArgs.push_back("-enable-split-dwarf"); + + if (DwarfFission == DwarfFissionKind::Single) + CmdArgs.push_back("-enable-split-dwarf=single"); + else + CmdArgs.push_back("-enable-split-dwarf"); } } @@ -3044,6 +3273,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-gembed-source"); } + if (EmitCodeView) { + CmdArgs.push_back("-gcodeview"); + + // Emit codeview type hashes if requested. + if (Args.hasFlag(options::OPT_gcodeview_ghash, + options::OPT_gno_codeview_ghash, false)) { + CmdArgs.push_back("-gcodeview-ghash"); + } + } + + // Adjust the debug info kind for the given toolchain. + TC.adjustDebugInfoKind(DebugInfoKind, Args); + RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion, DebuggerTuning); @@ -3055,11 +3297,24 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-debug-info-macro"); // -ggnu-pubnames turns on gnu style pubnames in the backend. - if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, - false)) - if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args, - D, TC)) - CmdArgs.push_back("-ggnu-pubnames"); + const auto *PubnamesArg = + Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, + options::OPT_gpubnames, options::OPT_gno_pubnames); + if (DwarfFission != DwarfFissionKind::None || + DebuggerTuning == llvm::DebuggerKind::LLDB || + (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC))) + if (!PubnamesArg || + (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) && + !PubnamesArg->getOption().matches(options::OPT_gno_pubnames))) + CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches( + options::OPT_gpubnames) + ? "-gpubnames" + : "-ggnu-pubnames"); + + if (Args.hasFlag(options::OPT_fdebug_ranges_base_address, + options::OPT_fno_debug_ranges_base_address, false)) { + CmdArgs.push_back("-fdebug-ranges-base-address"); + } // -gdwarf-aranges turns on the emission of the aranges section in the // backend. @@ -3103,32 +3358,64 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const llvm::Triple &RawTriple = getToolChain().getTriple(); - const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + const auto &TC = getToolChain(); + const llvm::Triple &RawTriple = TC.getTriple(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); const std::string &TripleStr = Triple.getTriple(); bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); - const Driver &D = getToolChain().getDriver(); + const Driver &D = TC.getDriver(); ArgStringList CmdArgs; // Check number of inputs for sanity. We need at least one input. assert(Inputs.size() >= 1 && "Must have at least one input."); - const InputInfo &Input = Inputs[0]; // CUDA/HIP compilation may have multiple inputs (source file + results of // device-side compilations). OpenMP device jobs also take the host IR as a - // second input. All other jobs are expected to have exactly one - // input. + // second input. Module precompilation accepts a list of header files to + // include as part of the module. All other jobs are expected to have exactly + // one input. bool IsCuda = JA.isOffloading(Action::OFK_Cuda); bool IsHIP = JA.isOffloading(Action::OFK_HIP); bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); - assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || - Inputs.size() == 1) && - "Unable to handle multiple inputs."); - - const llvm::Triple *AuxTriple = - IsCuda ? getToolChain().getAuxTriple() : nullptr; + bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA); + + // A header module compilation doesn't have a main input file, so invent a + // fake one as a placeholder. + const char *ModuleName = [&]{ + auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ); + return ModuleNameArg ? ModuleNameArg->getValue() : ""; + }(); + InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName); + + const InputInfo &Input = + IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0]; + + InputInfoList ModuleHeaderInputs; + const InputInfo *CudaDeviceInput = nullptr; + const InputInfo *OpenMPDeviceInput = nullptr; + for (const InputInfo &I : Inputs) { + if (&I == &Input) { + // This is the primary input. + } else if (IsHeaderModulePrecompile && + types::getPrecompiledType(I.getType()) == types::TY_PCH) { + types::ID Expected = HeaderModuleInput.getType(); + if (I.getType() != Expected) { + D.Diag(diag::err_drv_module_header_wrong_kind) + << I.getFilename() << types::getTypeName(I.getType()) + << types::getTypeName(Expected); + } + ModuleHeaderInputs.push_back(I); + } else if ((IsCuda || IsHIP) && !CudaDeviceInput) { + CudaDeviceInput = &I; + } else if (IsOpenMPDevice && !OpenMPDeviceInput) { + OpenMPDeviceInput = &I; + } else { + llvm_unreachable("unexpectedly given multiple inputs"); + } + } + const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr; bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment(); bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment(); bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment(); @@ -3204,7 +3491,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Push all default warning arguments that are specific to // the given target. These come before user provided warning options // are provided. - getToolChain().addClangWarningOptions(CmdArgs); + TC.addClangWarningOptions(CmdArgs); // Select the appropriate action. RewriteKind rewriteKind = RK_None; @@ -3231,17 +3518,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Also ignore explicit -force_cpusubtype_ALL option. (void)Args.hasArg(options::OPT_force__cpusubtype__ALL); } else if (isa<PrecompileJobAction>(JA)) { - // Use PCH if the user requested it. - bool UsePCH = D.CCCUsePCH; - if (JA.getType() == types::TY_Nothing) CmdArgs.push_back("-fsyntax-only"); else if (JA.getType() == types::TY_ModuleFile) - CmdArgs.push_back("-emit-module-interface"); - else if (UsePCH) - CmdArgs.push_back("-emit-pch"); + CmdArgs.push_back(IsHeaderModulePrecompile + ? "-emit-header-module" + : "-emit-module-interface"); else - CmdArgs.push_back("-emit-pth"); + CmdArgs.push_back("-emit-pch"); } else if (isa<VerifyPCHJobAction>(JA)) { CmdArgs.push_back("-verify-pch"); } else { @@ -3305,13 +3589,116 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); // Embed-bitcode option. + // Only white-listed flags below are allowed to be embedded. if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() && (isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) { // Add flags implied by -fembed-bitcode. Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); // Disable all llvm IR level optimizations. CmdArgs.push_back("-disable-llvm-passes"); + + // reject options that shouldn't be supported in bitcode + // also reject kernel/kext + static const constexpr unsigned kBitcodeOptionBlacklist[] = { + options::OPT_mkernel, + options::OPT_fapple_kext, + options::OPT_ffunction_sections, + options::OPT_fno_function_sections, + options::OPT_fdata_sections, + options::OPT_fno_data_sections, + options::OPT_funique_section_names, + options::OPT_fno_unique_section_names, + options::OPT_mrestrict_it, + options::OPT_mno_restrict_it, + options::OPT_mstackrealign, + options::OPT_mno_stackrealign, + options::OPT_mstack_alignment, + options::OPT_mcmodel_EQ, + options::OPT_mlong_calls, + options::OPT_mno_long_calls, + options::OPT_ggnu_pubnames, + options::OPT_gdwarf_aranges, + options::OPT_fdebug_types_section, + options::OPT_fno_debug_types_section, + options::OPT_fdwarf_directory_asm, + options::OPT_fno_dwarf_directory_asm, + options::OPT_mrelax_all, + options::OPT_mno_relax_all, + options::OPT_ftrap_function_EQ, + options::OPT_ffixed_r9, + options::OPT_mfix_cortex_a53_835769, + options::OPT_mno_fix_cortex_a53_835769, + options::OPT_ffixed_x18, + options::OPT_mglobal_merge, + options::OPT_mno_global_merge, + options::OPT_mred_zone, + options::OPT_mno_red_zone, + options::OPT_Wa_COMMA, + options::OPT_Xassembler, + options::OPT_mllvm, + }; + for (const auto &A : Args) + if (std::find(std::begin(kBitcodeOptionBlacklist), + std::end(kBitcodeOptionBlacklist), + A->getOption().getID()) != + std::end(kBitcodeOptionBlacklist)) + D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling(); + + // Render the CodeGen options that need to be passed. + if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, + options::OPT_fno_optimize_sibling_calls)) + CmdArgs.push_back("-mdisable-tail-calls"); + + RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args, + CmdArgs); + + // Render ABI arguments + switch (TC.getArch()) { + default: break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + RenderARMABI(Triple, Args, CmdArgs); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + RenderAArch64ABI(Triple, Args, CmdArgs); + break; + } + + // Optimization level for CodeGen. + if (const 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); + } + } + + // 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() && "Input output."); + } + + for (const auto &II : Inputs) { + addDashXForInput(Args, II, CmdArgs); + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + II.getInputArg().renderAsInput(Args, CmdArgs); + } + + C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(), + CmdArgs, Inputs)); + return; } + if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO()) CmdArgs.push_back("-fembed-bitcode=marker"); @@ -3346,12 +3733,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static-define"); + if (Args.hasArg(options::OPT_municode)) + CmdArgs.push_back("-DUNICODE"); + if (isa<AnalyzeJobAction>(JA)) RenderAnalyzerOptions(Args, CmdArgs, Triple, Input); + // Enable compatilibily mode to avoid analyzer-config related errors. + // Since we can't access frontend flags through hasArg, let's manually iterate + // through them. + bool FoundAnalyzerConfig = false; + for (auto Arg : Args.filtered(options::OPT_Xclang)) + if (StringRef(Arg->getValue()) == "-analyzer-config") { + FoundAnalyzerConfig = true; + break; + } + if (!FoundAnalyzerConfig) + for (auto Arg : Args.filtered(options::OPT_Xanalyzer)) + if (StringRef(Arg->getValue()) == "-analyzer-config") { + FoundAnalyzerConfig = true; + break; + } + if (FoundAnalyzerConfig) + CmdArgs.push_back("-analyzer-config-compatibility-mode=true"); + CheckCodeGenerationOptions(D, Args); - unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args); + unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args); assert(FunctionAlignment <= 31 && "function alignment will be truncated!"); if (FunctionAlignment) { CmdArgs.push_back("-function-alignment"); @@ -3361,8 +3769,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::Reloc::Model RelocationModel; unsigned PICLevel; bool IsPIE; - std::tie(RelocationModel, PICLevel, IsPIE) = - ParsePICArgs(getToolChain(), Args); + std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args); const char *RMName = RelocationModelName(RelocationModel); @@ -3390,13 +3797,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mthread-model"); if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) { - if (!getToolChain().isThreadModelSupported(A->getValue())) + if (!TC.isThreadModelSupported(A->getValue())) D.Diag(diag::err_drv_invalid_thread_model_for_target) << A->getValue() << A->getAsString(Args); CmdArgs.push_back(A->getValue()); } else - CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel())); + CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel())); Args.AddLastArg(CmdArgs, options::OPT_fveclib); @@ -3451,7 +3858,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return, options::OPT_freg_struct_return)) { - if (getToolChain().getArch() != llvm::Triple::x86) { + if (TC.getArch() != llvm::Triple::x86) { D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << RawTriple.str(); } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) { @@ -3516,18 +3923,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("-split-stacks"); - RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs); + RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. - bool IsIntegratedAssemblerDefault = - getToolChain().IsIntegratedAssemblerDefault(); + bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, IsIntegratedAssemblerDefault) || Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); - if (!getToolChain().useIntegratedAs()) + if (!TC.useIntegratedAs()) CmdArgs.push_back("-no-integrated-as"); if (Args.hasArg(options::OPT_fdebug_pass_structure)) { @@ -3580,20 +3986,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool AsynchronousUnwindTables = Args.hasFlag(options::OPT_fasynchronous_unwind_tables, options::OPT_fno_asynchronous_unwind_tables, - (getToolChain().IsUnwindTablesDefault(Args) || - getToolChain().getSanitizerArgs().needsUnwindTables()) && + (TC.IsUnwindTablesDefault(Args) || + TC.getSanitizerArgs().needsUnwindTables()) && !Freestanding); if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); - getToolChain().addClangTargetOptions(Args, CmdArgs, - JA.getOffloadingDeviceKind()); - - if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { - CmdArgs.push_back("-mlimit-float-precision"); - CmdArgs.push_back(A->getValue()); - } + TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind()); // FIXME: Handle -mtune=. (void)Args.hasArg(options::OPT_mtune_EQ); @@ -3620,22 +4020,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, types::ID InputType = Input.getType(); if (D.IsCLMode()) AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView); - else - EmitCodeView = Args.hasArg(options::OPT_gcodeview); - const Arg *SplitDWARFArg = nullptr; - RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView, - IsWindowsMSVC, CmdArgs, DebugInfoKind, SplitDWARFArg); + DwarfFissionKind DwarfFission; + RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC, + CmdArgs, DebugInfoKind, DwarfFission); // Add the split debug info name to the command lines here so we // can propagate it to the backend. - bool SplitDWARF = SplitDWARFArg && RawTriple.isOSLinux() && + bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) && + (RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) && (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)); const char *SplitDWARFOut; if (SplitDWARF) { CmdArgs.push_back("-split-dwarf-file"); - SplitDWARFOut = SplitDebugName(Args, Input); + SplitDWARFOut = SplitDebugName(Args, Output); CmdArgs.push_back(SplitDWARFOut); } @@ -3653,7 +4052,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; if (types::isCXX(InputType) && RawTriple.isOSDarwin() && - getToolChain().getArch() == llvm::Triple::x86) { + TC.getArch() == llvm::Triple::x86) { if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) || (Unsupported = Args.getLastArg(options::OPT_mkernel))) D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) @@ -3717,9 +4116,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ABICompatArg->render(Args, CmdArgs); // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled. - if (RawTriple.isPS4CPU()) { - PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs); - PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs); + if (RawTriple.isPS4CPU() && + !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + PS4cpu::addProfileRTArgs(TC, Args, CmdArgs); + PS4cpu::addSanitizerArgs(TC, CmdArgs); } // Pass options for controlling the default header search paths. @@ -3867,10 +4267,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } - if (ShouldDisableDwarfDirectory(Args, getToolChain())) + if (ShouldDisableDwarfDirectory(Args, TC)) CmdArgs.push_back("-fno-dwarf-directory-asm"); - if (ShouldDisableAutolink(Args, getToolChain())) + if (ShouldDisableAutolink(Args, TC)) CmdArgs.push_back("-fno-autolink"); // Add in -fdebug-compilation-dir if necessary. @@ -3916,6 +4316,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); + if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) { + static const char *kCFABIs[] = { + "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1", + }; + + if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs)) + D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue(); + else + A->render(Args, CmdArgs); + } + if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { CmdArgs.push_back("-fconstant-string-class"); CmdArgs.push_back(A->getValue()); @@ -3983,6 +4394,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); @@ -3993,6 +4405,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); Args.AddLastArg(CmdArgs, options::OPT_femulated_tls, options::OPT_fno_emulated_tls); + Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts); // AltiVec-like language extensions aren't relevant for assembling. if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm) @@ -4022,11 +4435,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd); Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); + Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ); + Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ); + if (Args.hasFlag(options::OPT_fopenmp_optimistic_collapse, + options::OPT_fno_openmp_optimistic_collapse, + /*Default=*/false)) + CmdArgs.push_back("-fopenmp-optimistic-collapse"); // When in OpenMP offloading mode with NVPTX target, forward // cuda-mode flag - Args.AddLastArg(CmdArgs, options::OPT_fopenmp_cuda_mode, - options::OPT_fno_openmp_cuda_mode); + if (Args.hasFlag(options::OPT_fopenmp_cuda_mode, + options::OPT_fno_openmp_cuda_mode, /*Default=*/false)) + CmdArgs.push_back("-fopenmp-cuda-mode"); + + // When in OpenMP offloading mode with NVPTX target, check if full runtime + // is required. + if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime, + options::OPT_fno_openmp_cuda_force_full_runtime, + /*Default=*/false)) + CmdArgs.push_back("-fopenmp-cuda-force-full-runtime"); break; default: // By default, if Clang doesn't know how to generate useful OpenMP code @@ -4043,16 +4470,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); } - const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); - Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + Sanitize.addArgs(TC, Args, CmdArgs, InputType); - const XRayArgs &XRay = getToolChain().getXRayArgs(); - XRay.addArgs(getToolChain(), Args, CmdArgs, InputType); + const XRayArgs &XRay = TC.getXRayArgs(); + XRay.addArgs(TC, Args, CmdArgs, InputType); - if (getToolChain().SupportsProfiling()) + if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); - if (getToolChain().SupportsProfiling()) + if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_mfentry); // -flax-vector-conversions is default. @@ -4099,7 +4526,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pthread); - RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext); + if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening, + false)) + CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening")); + + RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext); + RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs); // Translate -mstackrealign if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, @@ -4158,8 +4590,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else A->render(Args, CmdArgs); } + Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ); - RenderBuiltinOptions(getToolChain(), RawTriple, Args, CmdArgs); + RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs); if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new)) @@ -4167,19 +4600,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, - getToolChain().IsBlocksDefault()) || + TC.IsBlocksDefault()) || (Args.hasArg(options::OPT_fgnu_runtime) && Args.hasArg(options::OPT_fobjc_nonfragile_abi) && !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); - if (!Args.hasArg(options::OPT_fgnu_runtime) && - !getToolChain().hasBlocksRuntime()) + if (!Args.hasArg(options::OPT_fgnu_runtime) && !TC.hasBlocksRuntime()) CmdArgs.push_back("-fblocks-runtime-optional"); } // -fencode-extended-block-signature=1 is default. - if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) + if (TC.IsEncodeExtendedBlockSignatureDefault()) CmdArgs.push_back("-fencode-extended-block-signature"); if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts, @@ -4204,7 +4636,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_felide_constructors, false)) CmdArgs.push_back("-fno-elide-constructors"); - ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode(); + ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); if (KernelOrKext || (types::isCXX(InputType) && (RTTIMode == ToolChain::RM_Disabled))) @@ -4212,7 +4644,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, - getToolChain().getArch() == llvm::Triple::hexagon)) + TC.getArch() == llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs); @@ -4222,8 +4654,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, !RawTriple.isOSWindows() && RawTriple.getOS() != llvm::Triple::Solaris && - getToolChain().getArch() != llvm::Triple::hexagon && - getToolChain().getArch() != llvm::Triple::xcore && + TC.getArch() != llvm::Triple::xcore && ((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) || RawTriple.hasEnvironment())) || KernelOrKext) @@ -4252,7 +4683,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_ms_extensions, true)))) CmdArgs.push_back("-fms-compatibility"); - VersionTuple MSVT = getToolChain().computeMSVCVersion(&D, Args); + VersionTuple MSVT = TC.computeMSVCVersion(&D, Args); if (!MSVT.empty()) CmdArgs.push_back( Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString())); @@ -4330,8 +4761,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_experimental_new_pass_manager); ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); - RenderObjCOptions(getToolChain(), D, RawTriple, Args, Runtime, - rewriteKind != RK_None, Input, CmdArgs); + RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None, + Input, CmdArgs); if (Args.hasFlag(options::OPT_fapplication_extension, options::OPT_fno_application_extension, false)) @@ -4339,8 +4770,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Handle GCC-style exception args. if (!C.getDriver().IsCLMode()) - addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime, - CmdArgs); + addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); // Handle exception personalities Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, @@ -4355,7 +4785,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Opt.matches(options::OPT_fdwarf_exceptions)) CmdArgs.push_back("-fdwarf-exceptions"); } else { - switch (getToolChain().GetExceptionModel(Args)) { + switch (TC.GetExceptionModel(Args)) { default: break; case llvm::ExceptionHandling::DwarfCFI: @@ -4592,7 +5022,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // nice to enable this when doing a crashdump for modules as well. if (Args.hasFlag(options::OPT_frewrite_includes, options::OPT_fno_rewrite_includes, false) || - (C.isForDiagnostics() && (RewriteImports || !HaveModules))) + (C.isForDiagnostics() && !HaveModules)) CmdArgs.push_back("-frewrite-includes"); // Only allow -traditional or -traditional-cpp outside in preprocessing modes. @@ -4685,23 +5115,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addDashXForInput(Args, Input, CmdArgs); - if (Input.isFilename()) - CmdArgs.push_back(Input.getFilename()); - else - Input.getInputArg().renderAsInput(Args, CmdArgs); + ArrayRef<InputInfo> FrontendInputs = Input; + if (IsHeaderModulePrecompile) + FrontendInputs = ModuleHeaderInputs; + else if (Input.isNothing()) + FrontendInputs = {}; + + for (const InputInfo &Input : FrontendInputs) { + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); + else + Input.getInputArg().renderAsInput(Args, CmdArgs); + } Args.AddAllArgs(CmdArgs, options::OPT_undef); const char *Exec = D.getClangProgramPath(); - // Optionally embed the -cc1 level arguments into the debug info, for build - // analysis. + // Optionally embed the -cc1 level arguments into the debug info or a + // section, for build analysis. // Also record command line arguments into the debug info if // -grecord-gcc-switches options is set on. // By default, -gno-record-gcc-switches is set on and no recording. - if (getToolChain().UseDwarfDebugFlags() || - Args.hasFlag(options::OPT_grecord_gcc_switches, - options::OPT_gno_record_gcc_switches, false)) { + auto GRecordSwitches = + Args.hasFlag(options::OPT_grecord_command_line, + options::OPT_gno_record_command_line, false); + auto FRecordSwitches = + Args.hasFlag(options::OPT_frecord_command_line, + options::OPT_fno_record_command_line, false); + if (FRecordSwitches && !Triple.isOSBinFormatELF()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) + << TripleStr; + if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) { ArgStringList OriginalArgs; for (const auto &Arg : Args) Arg->render(Args, OriginalArgs); @@ -4714,21 +5160,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Flags += " "; Flags += EscapedArg; } - CmdArgs.push_back("-dwarf-debug-flags"); - CmdArgs.push_back(Args.MakeArgString(Flags)); + auto FlagsArgString = Args.MakeArgString(Flags); + if (TC.UseDwarfDebugFlags() || GRecordSwitches) { + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(FlagsArgString); + } + if (FRecordSwitches) { + CmdArgs.push_back("-record-command-line"); + CmdArgs.push_back(FlagsArgString); + } } - if (IsCuda) { - // Host-side cuda compilation receives all device-side outputs in a single - // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary. - if (Inputs.size() > 1) { - assert(Inputs.size() == 2 && "More than one GPU binary!"); + // Host-side cuda compilation receives all device-side outputs in a single + // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary. + if ((IsCuda || IsHIP) && CudaDeviceInput) { CmdArgs.push_back("-fcuda-include-gpubinary"); - CmdArgs.push_back(Inputs[1].getFilename()); - } + CmdArgs.push_back(CudaDeviceInput->getFilename()); + if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) + CmdArgs.push_back("-fgpu-rdc"); + } - if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false)) - CmdArgs.push_back("-fcuda-rdc"); + if (IsCuda) { if (Args.hasFlag(options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false)) CmdArgs.push_back("-fcuda-short-ptr"); @@ -4741,9 +5193,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // only the relevant declarations are emitted. if (IsOpenMPDevice) { CmdArgs.push_back("-fopenmp-is-device"); - if (Inputs.size() == 2) { + if (OpenMPDeviceInput) { CmdArgs.push_back("-fopenmp-host-ir-file-path"); - CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename())); + CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename())); } } @@ -4777,6 +5229,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fwhole-program-vtables"); } + bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO(); + bool SplitLTOUnit = + Args.hasFlag(options::OPT_fsplit_lto_unit, + options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit); + if (RequiresSplitLTOUnit && !SplitLTOUnit) + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fno-split-lto-unit" + << (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi"); + if (SplitLTOUnit) + CmdArgs.push_back("-fsplit-lto-unit"); + if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel, options::OPT_fno_experimental_isel)) { CmdArgs.push_back("-mllvm"); @@ -4818,6 +5281,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); + if (!Args.hasFlag(options::OPT_fcxx_static_destructors, + options::OPT_fno_cxx_static_destructors, true)) + CmdArgs.push_back("-fno-c++-static-destructors"); + if (Arg *A = Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) { if (A->getOption().matches(options::OPT_moutline)) { @@ -4838,8 +5305,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig, - getToolChain().getTriple().isOSBinFormatELF() && - getToolChain().useIntegratedAs())) + (TC.getTriple().isOSBinFormatELF() || + TC.getTriple().isOSBinFormatCOFF()) && + !TC.getTriple().isPS4() && + !TC.getTriple().isOSNetBSD() && + !Distro(D.getVFS()).IsGentoo() && + !TC.getTriple().isAndroid() && + TC.useIntegratedAs())) CmdArgs.push_back("-faddrsig"); // Finally add the compile command to the compilation. @@ -4860,16 +5332,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } + // Make the compile command echo its inputs for /showFilenames. + if (Output.getType() == types::TY_Object && + Args.hasFlag(options::OPT__SLASH_showFilenames, + options::OPT__SLASH_showFilenames_, false)) { + C.getJobs().getJobs().back()->setPrintInputFilenames(true); + } + if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (Args.hasArg(options::OPT_fomit_frame_pointer)) + if (!shouldUseFramePointer(Args, Triple)) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); // Claim some arguments which clang supports automatically. // -fpch-preprocess is used with gcc to add a special marker in the output to - // include the PCH file. Clang's PTH solution is completely transparent, so we - // do not need to deal with it at all. + // include the PCH file. Args.ClaimAllArgs(options::OPT_fpch_preprocess); // Claim some arguments which clang doesn't support, but we don't @@ -4912,7 +5390,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, } if ((runtime.getKind() == ObjCRuntime::GNUstep) && (runtime.getVersion() >= VersionTuple(2, 0))) - if (!getToolChain().getTriple().isOSBinFormatELF()) { + if (!getToolChain().getTriple().isOSBinFormatELF() && + !getToolChain().getTriple().isOSBinFormatCOFF()) { getToolChain().getDriver().Diag( diag::err_drv_gnustep_objc_runtime_incompatible_binary) << runtime.getVersion().getMajor(); @@ -5163,7 +5642,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, *DebugInfoKind = codegenoptions::LimitedDebugInfo; else *DebugInfoKind = codegenoptions::DebugLineTablesOnly; - CmdArgs.push_back("-gcodeview"); } else { *EmitCodeView = false; } @@ -5197,6 +5675,16 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, if (VolatileOptionID == options::OPT__SLASH_volatile_ms) CmdArgs.push_back("-fms-volatile"); + if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_, + options::OPT__SLASH_Zc_dllexportInlines, + false)) { + if (Args.hasArg(options::OPT__SLASH_fallback)) { + D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback); + } else { + CmdArgs.push_back("-fno-dllexport-inlines"); + } + } + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); if (MostGeneralArg && BestCaseArg) @@ -5270,9 +5758,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("msvc"); } - if (Args.hasArg(options::OPT__SLASH_Guard) && - Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf")) - CmdArgs.push_back("-cfguard"); + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + SmallVector<StringRef, 1> SplitArgs; + StringRef(A->getValue()).split(SplitArgs, ","); + bool Instrument = false; + bool NoChecks = false; + for (StringRef Arg : SplitArgs) { + if (Arg.equals_lower("cf")) + Instrument = true; + else if (Arg.equals_lower("cf-")) + Instrument = false; + else if (Arg.equals_lower("nochecks")) + NoChecks = true; + else if (Arg.equals_lower("nochecks-")) + NoChecks = false; + else + D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg; + } + // Currently there's no support emitting CFG instrumentation; the flag only + // emits the table of address-taken functions. + if (Instrument || NoChecks) + CmdArgs.push_back("-cfguard"); + } } visualstudio::Compiler *Clang::getCLFallback() const { @@ -5525,10 +6032,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - if (Args.hasArg(options::OPT_gsplit_dwarf) && - getToolChain().getTriple().isOSLinux()) { + const llvm::Triple &T = getToolChain().getTriple(); + Arg *A; + if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) && + (T.isOSLinux() || T.isOSFuchsia())) { CmdArgs.push_back("-split-dwarf-file"); - CmdArgs.push_back(SplitDebugName(Args, Input)); + CmdArgs.push_back(SplitDebugName(Args, Output)); } assert(Input.isFilename() && "Invalid input."); |