diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-04 19:20:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:02:26 +0000 |
commit | 81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch) | |
tree | 311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp | |
parent | 5fff09660e06a66bed6482da9c70df328e16bbb6 (diff) | |
parent | 145449b1e420787bb99721a429341fa6be3adfb6 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp | 530 |
1 files changed, 251 insertions, 279 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp index 7f1ce3da7e7e..abef4cf65496 100644 --- a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp @@ -94,6 +94,7 @@ #include <cassert> #include <cstddef> #include <cstring> +#include <fstream> #include <memory> #include <string> #include <tuple> @@ -107,6 +108,20 @@ using namespace options; using namespace llvm::opt; //===----------------------------------------------------------------------===// +// Helpers. +//===----------------------------------------------------------------------===// + +// Parse misexpect tolerance argument value. +// Valid option values are integers in the range [0, 100) +inline Expected<Optional<uint64_t>> parseToleranceOption(StringRef Arg) { + int64_t Val; + if (Arg.getAsInteger(10, Val)) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Not an integer: %s", Arg.data()); + return Val; +} + +//===----------------------------------------------------------------------===// // Initialization. //===----------------------------------------------------------------------===// @@ -503,6 +518,22 @@ static bool FixupInvocation(CompilerInvocation &Invocation, Diags.Report(diag::warn_ignored_hip_only_option) << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args); + // When these options are used, the compiler is allowed to apply + // optimizations that may affect the final result. For example + // (x+y)+z is transformed to x+(y+z) but may not give the same + // final result; it's not value safe. + // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF + // or NaN. Final result may then differ. An error is issued when the eval + // method is set with one of these options. + if (Args.hasArg(OPT_ffp_eval_method_EQ)) { + if (LangOpts.ApproxFunc) + Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0; + if (LangOpts.AllowFPReassoc) + Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1; + if (LangOpts.AllowRecip) + Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2; + } + // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0. // This option should be deprecated for CL > 1.0 because // this option was added for compatibility with OpenCL 1.0. @@ -526,11 +557,6 @@ static bool FixupInvocation(CompilerInvocation &Invocation, << A->getSpelling() << T.getTriple(); } - if (!CodeGenOpts.ProfileRemappingFile.empty() && CodeGenOpts.LegacyPassManager) - Diags.Report(diag::err_drv_argument_only_allowed_with) - << Args.getLastArg(OPT_fprofile_remapping_file_EQ)->getAsString(Args) - << "-fno-legacy-pass-manager"; - return Diags.getNumErrors() == NumErrorsBefore; } @@ -790,18 +816,6 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING - if (Opts.AnalysisStoreOpt != RegionStoreModel) { - switch (Opts.AnalysisStoreOpt) { -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ - case NAME##Model: \ - GenerateArg(Args, OPT_analyzer_store, CMDFLAG, SA); \ - break; -#include "clang/StaticAnalyzer/Core/Analyses.def" - default: - llvm_unreachable("Tried to generate unknown analysis store."); - } - } - if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) { switch (Opts.AnalysisConstraintsOpt) { #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ @@ -889,20 +903,13 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING - if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { - StringRef Name = A->getValue(); - AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name) -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ - .Case(CMDFLAG, NAME##Model) -#include "clang/StaticAnalyzer/Core/Analyses.def" - .Default(NumStores); - if (Value == NumStores) { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << Name; - } else { - Opts.AnalysisStoreOpt = Value; - } - } + if (Args.hasArg(OPT_analyzer_store)) + Diags.Report(diag::warn_analyzer_deprecated_option) << "-analyzer-store" + << "clang-16"; + if (Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks)) + Diags.Report(diag::warn_analyzer_deprecated_option) + << "-analyzer-opt-analyze-nested-blocks" + << "clang-16"; if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { StringRef Name = A->getValue(); @@ -915,6 +922,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; } else { +#ifndef LLVM_WITH_Z3 + if (Value == AnalysisConstraints::Z3ConstraintsModel) { + Diags.Report(diag::err_analyzer_not_built_with_z3); + } +#endif // LLVM_WITH_Z3 Opts.AnalysisConstraintsOpt = Value; } } @@ -1062,7 +1074,7 @@ static void initOption(AnalyzerOptions::ConfigTable &Config, else OptionField = DefaultVal; } else - OptionField = PossiblyInvalidVal.getValue(); + OptionField = *PossiblyInvalidVal; } static void initOption(AnalyzerOptions::ConfigTable &Config, @@ -1081,25 +1093,22 @@ static void initOption(AnalyzerOptions::ConfigTable &Config, static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, DiagnosticsEngine *Diags) { // TODO: There's no need to store the entire configtable, it'd be plenty - // enough tostore checker options. + // enough to store checker options. #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL); +#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...) +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" -#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ - SHALLOW_VAL, DEEP_VAL) \ - switch (AnOpts.getUserMode()) { \ - case UMK_Shallow: \ - initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, SHALLOW_VAL); \ - break; \ - case UMK_Deep: \ - initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEEP_VAL); \ - break; \ - } \ + assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep"); + const bool InShallowMode = AnOpts.UserMode == "shallow"; +#define ANALYZER_OPTION(...) +#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ + SHALLOW_VAL, DEEP_VAL) \ + initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \ + InShallowMode ? SHALLOW_VAL : DEEP_VAL); #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" -#undef ANALYZER_OPTION -#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE // At this point, AnalyzerOptions is configured. Let's validate some options. @@ -1473,6 +1482,9 @@ void CompilerInvocation::GenerateCodeGenArgs( else if (Opts.CFProtectionBranch) GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA); + if (Opts.IBTSeal) + GenerateArg(Args, OPT_mibt_seal, SA); + for (const auto &F : Opts.LinkBitcodeFiles) { bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded && F.PropagateAttrs && F.Internalize; @@ -1492,7 +1504,8 @@ void CompilerInvocation::GenerateCodeGenArgs( if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) GenerateArg(Args, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str(), SA); - if (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()) + if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) || + (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE())) GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, Opts.FP32DenormalMode.str(), SA); @@ -1530,6 +1543,9 @@ void CompilerInvocation::GenerateCodeGenArgs( : "auto", SA); + GenerateArg(Args, OPT_fdiagnostics_misexpect_tolerance_EQ, + Twine(*Opts.DiagnosticsMisExpectTolerance), SA); + for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover)) GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA); @@ -1591,23 +1607,22 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, // At O0 we want to fully disable inlining outside of cases marked with // 'alwaysinline' that are required for correctness. - Opts.setInlining((Opts.OptimizationLevel == 0) - ? CodeGenOptions::OnlyAlwaysInlining - : CodeGenOptions::NormalInlining); - // Explicit inlining flags can disable some or all inlining even at - // optimization levels above zero. - if (Arg *InlineArg = Args.getLastArg( - options::OPT_finline_functions, options::OPT_finline_hint_functions, - options::OPT_fno_inline_functions, options::OPT_fno_inline)) { - if (Opts.OptimizationLevel > 0) { - const Option &InlineOpt = InlineArg->getOption(); - if (InlineOpt.matches(options::OPT_finline_functions)) - Opts.setInlining(CodeGenOptions::NormalInlining); - else if (InlineOpt.matches(options::OPT_finline_hint_functions)) - Opts.setInlining(CodeGenOptions::OnlyHintInlining); - else - Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); - } + if (Opts.OptimizationLevel == 0) { + Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); + } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions, + options::OPT_finline_hint_functions, + options::OPT_fno_inline_functions, + options::OPT_fno_inline)) { + // Explicit inlining flags can disable some or all inlining even at + // optimization levels above zero. + if (A->getOption().matches(options::OPT_finline_functions)) + Opts.setInlining(CodeGenOptions::NormalInlining); + else if (A->getOption().matches(options::OPT_finline_hint_functions)) + Opts.setInlining(CodeGenOptions::OnlyHintInlining); + else + Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); + } else { + Opts.setInlining(CodeGenOptions::NormalInlining); } // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to @@ -1710,10 +1725,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, // -ftime-report= is only for new pass manager. if (A->getOption().getID() == OPT_ftime_report_EQ) { - if (Opts.LegacyPassManager) - Diags.Report(diag::err_drv_argument_only_allowed_with) - << A->getAsString(Args) << "-fno-legacy-pass-manager"; - StringRef Val = A->getValue(); if (Val == "per-pass") Opts.TimePassesPerRun = false; @@ -1847,6 +1858,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { StringRef Val = A->getValue(); Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val); + Opts.FP32DenormalMode = Opts.FPDenormalMode; if (!Opts.FPDenormalMode.isValid()) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } @@ -1939,7 +1951,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, << "-fdiagnostics-hotness-threshold="; } else { Opts.DiagnosticsHotnessThreshold = *ResultOrErr; - if ((!Opts.DiagnosticsHotnessThreshold.hasValue() || + if ((!Opts.DiagnosticsHotnessThreshold || Opts.DiagnosticsHotnessThreshold.getValue() > 0) && !UsingProfile) Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) @@ -1947,6 +1959,23 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } } + if (auto *arg = + Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) { + auto ResultOrErr = parseToleranceOption(arg->getValue()); + + if (!ResultOrErr) { + Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance) + << "-fdiagnostics-misexpect-tolerance="; + } else { + Opts.DiagnosticsMisExpectTolerance = *ResultOrErr; + if ((!Opts.DiagnosticsMisExpectTolerance || + Opts.DiagnosticsMisExpectTolerance.getValue() > 0) && + !UsingProfile) + Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo) + << "-fdiagnostics-misexpect-tolerance="; + } + } + // If the user requested to use a sample profile for PGO, then the // backend will need to track source location information so the profile // can be incorporated into the IR. @@ -1977,8 +2006,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, else if (Args.hasArg(options::OPT_fno_finite_loops)) Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never; - Opts.EmitIEEENaNCompliantInsts = - Args.hasFlag(options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee); + Opts.EmitIEEENaNCompliantInsts = Args.hasFlag( + options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true); if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs) Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans); @@ -2102,11 +2131,9 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; for (auto *A : Args) { const Option &O = A->getOption(); - if (O.matches(options::OPT_fcolor_diagnostics) || - O.matches(options::OPT_fdiagnostics_color)) { + if (O.matches(options::OPT_fcolor_diagnostics)) { ShowColors = Colors_On; - } else if (O.matches(options::OPT_fno_color_diagnostics) || - O.matches(options::OPT_fno_diagnostics_color)) { + } else if (O.matches(options::OPT_fno_color_diagnostics)) { ShowColors = Colors_Off; } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { StringRef Value(A->getValue()); @@ -2406,7 +2433,6 @@ static const auto &getFrontendActionTable() { {frontend::EmitLLVM, OPT_emit_llvm}, {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, {frontend::EmitCodeGenOnly, OPT_emit_codegen_only}, - {frontend::EmitCodeGenOnly, OPT_emit_codegen_only}, {frontend::EmitObj, OPT_emit_obj}, {frontend::ExtractAPI, OPT_extract_api}, @@ -2416,6 +2442,7 @@ static const auto &getFrontendActionTable() { {frontend::GenerateModule, OPT_emit_module}, {frontend::GenerateModuleInterface, OPT_emit_module_interface}, {frontend::GenerateHeaderModule, OPT_emit_header_module}, + {frontend::GenerateHeaderUnit, OPT_emit_header_unit}, {frontend::GeneratePCH, OPT_emit_pch}, {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs}, {frontend::InitOnly, OPT_init_only}, @@ -2432,7 +2459,7 @@ static const auto &getFrontendActionTable() { {frontend::MigrateSource, OPT_migrate}, {frontend::RunPreprocessorOnly, OPT_Eonly}, {frontend::PrintDependencyDirectivesSourceMinimizerOutput, - OPT_print_dependency_directives_minimized_source}, + OPT_print_dependency_directives_minimized_source}, }; return Table; @@ -2551,10 +2578,10 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, for (const auto &ModuleFile : Opts.ModuleFiles) GenerateArg(Args, OPT_fmodule_file, ModuleFile, SA); - if (Opts.AuxTargetCPU.hasValue()) + if (Opts.AuxTargetCPU) GenerateArg(Args, OPT_aux_target_cpu, *Opts.AuxTargetCPU, SA); - if (Opts.AuxTargetFeatures.hasValue()) + if (Opts.AuxTargetFeatures) for (const auto &Feature : *Opts.AuxTargetFeatures) GenerateArg(Args, OPT_aux_target_feature, Feature, SA); @@ -2562,6 +2589,20 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : ""; StringRef ModuleMap = Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : ""; + StringRef HeaderUnit = ""; + switch (Opts.DashX.getHeaderUnitKind()) { + case InputKind::HeaderUnit_None: + break; + case InputKind::HeaderUnit_User: + HeaderUnit = "-user"; + break; + case InputKind::HeaderUnit_System: + HeaderUnit = "-system"; + break; + case InputKind::HeaderUnit_Abs: + HeaderUnit = "-header-unit"; + break; + } StringRef Header = IsHeader ? "-header" : ""; StringRef Lang; @@ -2604,9 +2645,13 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, case Language::LLVM_IR: Lang = "ir"; break; + case Language::HLSL: + Lang = "hlsl"; + break; } - GenerateArg(Args, OPT_x, Lang + Header + ModuleMap + Preprocessed, SA); + GenerateArg(Args, OPT_x, + Lang + HeaderUnit + Header + ModuleMap + Preprocessed, SA); } // OPT_INPUT has a unique class, generate it directly. @@ -2751,13 +2796,32 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_x)) { StringRef XValue = A->getValue(); - // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'. + // Parse suffixes: + // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'. // FIXME: Supporting '<lang>-header-cpp-output' would be useful. bool Preprocessed = XValue.consume_back("-cpp-output"); bool ModuleMap = XValue.consume_back("-module-map"); - IsHeaderFile = !Preprocessed && !ModuleMap && - XValue != "precompiled-header" && - XValue.consume_back("-header"); + // Detect and consume the header indicator. + bool IsHeader = + XValue != "precompiled-header" && XValue.consume_back("-header"); + + // If we have c++-{user,system}-header, that indicates a header unit input + // likewise, if the user put -fmodule-header together with a header with an + // absolute path (header-unit-header). + InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None; + if (IsHeader || Preprocessed) { + if (XValue.consume_back("-header-unit")) + HUK = InputKind::HeaderUnit_Abs; + else if (XValue.consume_back("-system")) + HUK = InputKind::HeaderUnit_System; + else if (XValue.consume_back("-user")) + HUK = InputKind::HeaderUnit_User; + } + + // The value set by this processing is an un-preprocessed source which is + // not intended to be a module map or header unit. + IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap && + HUK == InputKind::HeaderUnit_None; // Principal languages. DashX = llvm::StringSwitch<InputKind>(XValue) @@ -2770,18 +2834,21 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Case("objective-c", Language::ObjC) .Case("objective-c++", Language::ObjCXX) .Case("renderscript", Language::RenderScript) + .Case("hlsl", Language::HLSL) .Default(Language::Unknown); // "objc[++]-cpp-output" is an acceptable synonym for // "objective-c[++]-cpp-output". - if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap) + if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap && + HUK == InputKind::HeaderUnit_None) DashX = llvm::StringSwitch<InputKind>(XValue) .Case("objc", Language::ObjC) .Case("objc++", Language::ObjCXX) .Default(Language::Unknown); // Some special cases cannot be combined with suffixes. - if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile) + if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap && + HUK == InputKind::HeaderUnit_None) DashX = llvm::StringSwitch<InputKind>(XValue) .Case("cpp-output", InputKind(Language::C).getPreprocessed()) .Case("assembler-with-cpp", Language::Asm) @@ -2796,6 +2863,12 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (Preprocessed) DashX = DashX.getPreprocessed(); + // A regular header is considered mutually exclusive with a header unit. + if (HUK != InputKind::HeaderUnit_None) { + DashX = DashX.withHeaderUnit(HUK); + IsHeaderFile = true; + } else if (IsHeaderFile) + DashX = DashX.getHeader(); if (ModuleMap) DashX = DashX.withFormat(InputKind::ModuleMap); } @@ -2805,6 +2878,11 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.Inputs.clear(); if (Inputs.empty()) Inputs.push_back("-"); + + if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None && + Inputs.size() > 1) + Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1]; + for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { InputKind IK = DashX; if (IK.isUnknown()) { @@ -3103,155 +3181,6 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } -void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, - const llvm::Triple &T, - std::vector<std::string> &Includes, - LangStandard::Kind LangStd) { - // Set some properties which depend solely on the input kind; it would be nice - // to move these to the language standard, and have the driver resolve the - // input kind + language standard. - // - // FIXME: Perhaps a better model would be for a single source file to have - // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) - // simultaneously active? - if (IK.getLanguage() == Language::Asm) { - Opts.AsmPreprocessor = 1; - } else if (IK.isObjectiveC()) { - Opts.ObjC = 1; - } - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK.getLanguage()) { - case Language::Unknown: - case Language::LLVM_IR: - llvm_unreachable("Invalid input kind!"); - case Language::OpenCL: - LangStd = LangStandard::lang_opencl12; - break; - case Language::OpenCLCXX: - LangStd = LangStandard::lang_openclcpp10; - break; - case Language::CUDA: - LangStd = LangStandard::lang_cuda; - break; - case Language::Asm: - case Language::C: -#if defined(CLANG_DEFAULT_STD_C) - LangStd = CLANG_DEFAULT_STD_C; -#else - // The PS4 uses C99 as the default C standard. - if (T.isPS4()) - LangStd = LangStandard::lang_gnu99; - else - LangStd = LangStandard::lang_gnu17; -#endif - break; - case Language::ObjC: -#if defined(CLANG_DEFAULT_STD_C) - LangStd = CLANG_DEFAULT_STD_C; -#else - LangStd = LangStandard::lang_gnu11; -#endif - break; - case Language::CXX: - case Language::ObjCXX: -#if defined(CLANG_DEFAULT_STD_CXX) - LangStd = CLANG_DEFAULT_STD_CXX; -#else - LangStd = LangStandard::lang_gnucxx14; -#endif - break; - case Language::RenderScript: - LangStd = LangStandard::lang_c99; - break; - case Language::HIP: - LangStd = LangStandard::lang_hip; - break; - } - } - - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Opts.LangStd = LangStd; - Opts.LineComment = Std.hasLineComments(); - Opts.C99 = Std.isC99(); - Opts.C11 = Std.isC11(); - Opts.C17 = Std.isC17(); - Opts.C2x = Std.isC2x(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus11 = Std.isCPlusPlus11(); - Opts.CPlusPlus14 = Std.isCPlusPlus14(); - Opts.CPlusPlus17 = Std.isCPlusPlus17(); - Opts.CPlusPlus20 = Std.isCPlusPlus20(); - Opts.CPlusPlus2b = Std.isCPlusPlus2b(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUCVersion = 0; - Opts.HexFloats = Std.hasHexFloats(); - Opts.ImplicitInt = Std.hasImplicitInt(); - - // Set OpenCL Version. - Opts.OpenCL = Std.isOpenCL(); - if (LangStd == LangStandard::lang_opencl10) - Opts.OpenCLVersion = 100; - else if (LangStd == LangStandard::lang_opencl11) - Opts.OpenCLVersion = 110; - else if (LangStd == LangStandard::lang_opencl12) - Opts.OpenCLVersion = 120; - else if (LangStd == LangStandard::lang_opencl20) - Opts.OpenCLVersion = 200; - else if (LangStd == LangStandard::lang_opencl30) - Opts.OpenCLVersion = 300; - else if (LangStd == LangStandard::lang_openclcpp10) - Opts.OpenCLCPlusPlusVersion = 100; - else if (LangStd == LangStandard::lang_openclcpp2021) - Opts.OpenCLCPlusPlusVersion = 202100; - - // OpenCL has some additional defaults. - if (Opts.OpenCL) { - Opts.AltiVec = 0; - Opts.ZVector = 0; - Opts.setDefaultFPContractMode(LangOptions::FPM_On); - Opts.OpenCLCPlusPlus = Opts.CPlusPlus; - Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; - Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; - - // Include default header file for OpenCL. - if (Opts.IncludeDefaultHeader) { - if (Opts.DeclareOpenCLBuiltins) { - // Only include base header file for builtin types and constants. - Includes.push_back("opencl-c-base.h"); - } else { - Includes.push_back("opencl-c.h"); - } - } - } - - Opts.HIP = IK.getLanguage() == Language::HIP; - Opts.CUDA = IK.getLanguage() == Language::CUDA || Opts.HIP; - if (Opts.HIP) { - // HIP toolchain does not support 'Fast' FPOpFusion in backends since it - // fuses multiplication/addition instructions without contract flag from - // device library functions in LLVM bitcode, which causes accuracy loss in - // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. - // For device library functions in bitcode to work, 'Strict' or 'Standard' - // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' - // FP contract option is used to allow fuse across statements in frontend - // whereas respecting contract flag in backend. - Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); - } else if (Opts.CUDA) { - // Allow fuse across statements disregarding pragmas. - Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); - } - - Opts.RenderScript = IK.getLanguage() == Language::RenderScript; - - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; - - // OpenCL has half keyword - Opts.Half = Opts.OpenCL; -} - /// Check if input file kind and language standard are compatible. static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S) { @@ -3289,6 +3218,9 @@ static bool IsInputCompatibleWithStandard(InputKind IK, // FIXME: The -std= value is not ignored; it affects the tokenization // and preprocessing rules if we're preprocessing this asm input. return true; + + case Language::HLSL: + return S.getLanguage() == Language::HLSL; } llvm_unreachable("unexpected input language"); @@ -3321,6 +3253,9 @@ static StringRef GetInputKindName(InputKind IK) { case Language::LLVM_IR: return "LLVM IR"; + case Language::HLSL: + return "HLSL"; + case Language::Unknown: break; } @@ -3456,6 +3391,8 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Args, OPT_mlong_double_128, SA); else if (Opts.LongDoubleSize == 64) GenerateArg(Args, OPT_mlong_double_64, SA); + else if (Opts.LongDoubleSize == 80) + GenerateArg(Args, OPT_mlong_double_80, SA); // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='. @@ -3484,9 +3421,6 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA); } - if (Opts.OpenMPTargetNewRuntime) - GenerateArg(Args, OPT_fopenmp_target_new_runtime, SA); - if (Opts.OpenMPThreadSubscription) GenerateArg(Args, OPT_fopenmp_assume_threads_oversubscription, SA); @@ -3560,6 +3494,8 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Args, OPT_fclang_abi_compat_EQ, "11.0", SA); else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver12) GenerateArg(Args, OPT_fclang_abi_compat_EQ, "12.0", SA); + else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver14) + GenerateArg(Args, OPT_fclang_abi_compat_EQ, "14.0", SA); if (Opts.getSignReturnAddressScope() == LangOptions::SignReturnAddressScopeKind::All) @@ -3581,8 +3517,16 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, else GenerateArg(Args, OPT_fno_experimental_relative_cxx_abi_vtables, SA); + if (Opts.UseTargetPathSeparator) + GenerateArg(Args, OPT_ffile_reproducible, SA); + else + GenerateArg(Args, OPT_fno_file_reproducible, SA); + for (const auto &MP : Opts.MacroPrefixMap) GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA); + + if (!Opts.RandstructSeed.empty()) + GenerateArg(Args, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed, SA); } bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, @@ -3680,7 +3624,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins); - CompilerInvocation::setLangDefaults(Opts, IK, T, Includes, LangStd); + LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd); // The key paths of codegen options defined in Options.td start with // "LangOpts->". Let's provide the expected variable name and type. @@ -3767,8 +3711,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, VersionTuple GNUCVer; bool Invalid = GNUCVer.tryParse(A->getValue()); unsigned Major = GNUCVer.getMajor(); - unsigned Minor = GNUCVer.getMinor().getValueOr(0); - unsigned Patch = GNUCVer.getSubminor().getValueOr(0); + unsigned Minor = GNUCVer.getMinor().value_or(0); + unsigned Patch = GNUCVer.getSubminor().value_or(0); if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); @@ -3776,28 +3720,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch; } - // In AIX OS, the -mignore-xcoff-visibility is enable by default if there is - // no -fvisibility=* option. - // This is the reason why '-fvisibility' needs to be always generated: - // its absence implies '-mignore-xcoff-visibility'. - // - // Suppose the original cc1 command line does contain '-fvisibility default': - // '-mignore-xcoff-visibility' should not be implied. - // * If '-fvisibility' is not generated (as most options with default values - // don't), its absence would imply '-mignore-xcoff-visibility'. This changes - // the command line semantics. - // * If '-fvisibility' is generated regardless of its presence and value, - // '-mignore-xcoff-visibility' won't be implied and the command line - // semantics are kept intact. - // - // When the original cc1 command line does **not** contain '-fvisibility', - // '-mignore-xcoff-visibility' is implied. The generated command line will - // contain both '-fvisibility default' and '-mignore-xcoff-visibility' and - // subsequent calls to `CreateFromArgs`/`generateCC1CommandLine` will always - // produce the same arguments. - - if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility) || - !Args.hasArg(OPT_fvisibility))) + if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility))) Opts.IgnoreXCOFFVisibility = 1; if (Args.hasArg(OPT_ftrapv)) { @@ -3816,8 +3739,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 + - VT.getMinor().getValueOr(0) * 100000 + - VT.getSubminor().getValueOr(0); + VT.getMinor().value_or(0) * 100000 + + VT.getSubminor().value_or(0); } // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs @@ -3839,11 +3762,19 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); - Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) - ? 128 - : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; + if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { + if (A->getOption().matches(options::OPT_mlong_double_64)) + Opts.LongDoubleSize = 64; + else if (A->getOption().matches(options::OPT_mlong_double_80)) + Opts.LongDoubleSize = 80; + else if (A->getOption().matches(options::OPT_mlong_double_128)) + Opts.LongDoubleSize = 128; + else + Opts.LongDoubleSize = 0; + } if (Opts.FastRelaxedMath) Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); + llvm::sort(Opts.ModuleFeatures); // -mrtd option @@ -3875,9 +3806,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder); bool IsTargetSpecified = Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ); - Opts.OpenMPTargetNewRuntime = - Opts.OpenMPIsDevice && - Args.hasArg(options::OPT_fopenmp_target_new_runtime); Opts.ConvergentFunctions = Opts.ConvergentFunctions || Opts.OpenMPIsDevice; @@ -3925,17 +3853,13 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, // Set either by a specific value or to a default if not specified. if (Opts.OpenMPIsDevice && (Args.hasArg(OPT_fopenmp_target_debug) || Args.hasArg(OPT_fopenmp_target_debug_EQ))) { - if (Opts.OpenMPTargetNewRuntime) { - Opts.OpenMPTargetDebug = getLastArgIntValue( - Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags); - if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug)) - Opts.OpenMPTargetDebug = 1; - } else { - Diags.Report(diag::err_drv_debug_no_new_runtime); - } + Opts.OpenMPTargetDebug = getLastArgIntValue( + Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags); + if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug)) + Opts.OpenMPTargetDebug = 1; } - if (Opts.OpenMPIsDevice && Opts.OpenMPTargetNewRuntime) { + if (Opts.OpenMPIsDevice) { if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription)) Opts.OpenMPTeamSubscription = true; if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription)) @@ -4062,6 +3986,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver11); else if (Major <= 12) Opts.setClangABICompat(LangOptions::ClangABI::Ver12); + else if (Major <= 14) + Opts.setClangABICompat(LangOptions::ClangABI::Ver14); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); @@ -4125,6 +4051,12 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, {std::string(Split.first), std::string(Split.second)}); } + Opts.UseTargetPathSeparator = + !Args.getLastArg(OPT_fno_file_reproducible) && + (Args.getLastArg(OPT_ffile_compilation_dir_EQ) || + Args.getLastArg(OPT_fmacro_prefix_map_EQ) || + Args.getLastArg(OPT_ffile_reproducible)); + // Error if -mvscale-min is unbounded. if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) { unsigned VScaleMin; @@ -4132,6 +4064,19 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_cc1_unbounded_vscale_min); } + if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) { + std::ifstream SeedFile(A->getValue(0)); + + if (!SeedFile.is_open()) + Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file) + << A->getValue(0); + + std::getline(SeedFile, Opts.RandstructSeed); + } + + if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ)) + Opts.RandstructSeed = A->getValue(0); + return Diags.getNumErrors() == NumErrorsBefore; } @@ -4153,6 +4098,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::GenerateModule: case frontend::GenerateModuleInterface: case frontend::GenerateHeaderModule: + case frontend::GenerateHeaderUnit: case frontend::GeneratePCH: case frontend::GenerateInterfaceStubs: case frontend::ParseSyntaxOnly: @@ -4234,6 +4180,10 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") || I == "opencl-c.h")) continue; + // Don't generate HLSL includes. They are implied by other flags that are + // generated elsewhere. + if (LangOpts.HLSL && I == "hlsl.h") + continue; GenerateArg(Args, OPT_include, I, SA); } @@ -4356,6 +4306,8 @@ static void GeneratePreprocessorOutputArgs( GenerateArg(Args, OPT_dM, SA); if (!Generate_dM && Opts.ShowMacros) GenerateArg(Args, OPT_dD, SA); + if (Opts.DirectivesOnly) + GenerateArg(Args, OPT_fdirectives_only, SA); } static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -4378,6 +4330,7 @@ static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM); Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); + Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only); return Diags.getNumErrors() == NumErrorsBefore; } @@ -4400,6 +4353,9 @@ static void GenerateTargetArgs(const TargetOptions &Opts, if (!Opts.SDKVersion.empty()) GenerateArg(Args, OPT_target_sdk_version_EQ, Opts.SDKVersion.getAsString(), SA); + if (!Opts.DarwinTargetVariantSDKVersion.empty()) + GenerateArg(Args, OPT_darwin_target_variant_sdk_version_EQ, + Opts.DarwinTargetVariantSDKVersion.getAsString(), SA); } static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, @@ -4427,6 +4383,15 @@ static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, else Opts.SDKVersion = Version; } + if (Arg *A = + Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) { + llvm::VersionTuple Version; + if (Version.tryParse(A->getValue())) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + else + Opts.DarwinTargetVariantSDKVersion = Version; + } return Diags.getNumErrors() == NumErrorsBefore; } @@ -4478,6 +4443,13 @@ bool CompilerInvocation::CreateFromArgsImpl( if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) LangOpts.ObjCExceptions = 1; + for (auto Warning : Res.getDiagnosticOpts().Warnings) { + if (Warning == "misexpect" && + !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) { + Res.getCodeGenOpts().MisExpect = true; + } + } + if (LangOpts.CUDA) { // During CUDA device-side compilation, the aux triple is the // triple used for host compilation. |