[clang] e721bc9 - [clang][cli] Generate and round-trip CodeGen options
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 9 02:43:47 PST 2021
Author: Jan Svoboda
Date: 2021-02-09T11:43:38+01:00
New Revision: e721bc9effefab8a625e913e7391bdd340693ddc
URL: https://github.com/llvm/llvm-project/commit/e721bc9effefab8a625e913e7391bdd340693ddc
DIFF: https://github.com/llvm/llvm-project/commit/e721bc9effefab8a625e913e7391bdd340693ddc.diff
LOG: [clang][cli] Generate and round-trip CodeGen options
This patch implements generation of remaining codegen options and tests it by performing parse-generate-parse round trip.
Reviewed By: dexonsmith
Differential Revision: https://reviews.llvm.org/D96056
Added:
Modified:
clang/include/clang/Basic/XRayInstr.h
clang/include/clang/Driver/Options.td
clang/include/clang/Frontend/CompilerInvocation.h
clang/lib/Basic/XRayInstr.cpp
clang/lib/Frontend/CompilerInvocation.cpp
llvm/include/llvm/Option/OptParser.td
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/XRayInstr.h b/clang/include/clang/Basic/XRayInstr.h
index 42ca7773fcceb..23ca2c75fc997 100644
--- a/clang/include/clang/Basic/XRayInstr.h
+++ b/clang/include/clang/Basic/XRayInstr.h
@@ -65,8 +65,13 @@ struct XRayInstrSet {
XRayInstrMask Mask = 0;
};
+/// Parses a command line argument into a mask.
XRayInstrMask parseXRayInstrValue(StringRef Value);
+/// Serializes a set into a list of command line arguments.
+void serializeXRayInstrValue(XRayInstrSet Set,
+ SmallVectorImpl<StringRef> &Values);
+
} // namespace clang
#endif // LLVM_CLANG_BASIC_XRAYINSTR_H
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index baea96df5829b..544f5771861ab 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4453,12 +4453,7 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
//===----------------------------------------------------------------------===//
let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
-def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">,
- Values<"line-tables-only,line-directives-only,constructor,limited,standalone,unused-types">,
- NormalizedValuesScope<"codegenoptions">,
- NormalizedValues<["DebugLineTablesOnly", "DebugDirectivesOnly", "DebugInfoConstructor",
- "LimitedDebugInfo", "FullDebugInfo", "UnusedTypeInfo"]>,
- MarshallingInfoString<CodeGenOpts<"DebugInfo">, "NoDebugInfo">, AutoNormalizeEnum;
+def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
def debug_info_macro : Flag<["-"], "debug-info-macro">,
HelpText<"Emit macro debug information">,
MarshallingInfoFlag<CodeGenOpts<"MacroDebugInfo">>;
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 0b53c867cd98d..8cd512cbfd89e 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -266,12 +266,26 @@ class CompilerInvocation : public CompilerInvocationBase {
StringAllocator SA, const llvm::Triple &T);
/// Parse command line options that map to CodeGenOptions.
- static bool ParseCodeGenArgs(CodeGenOptions &Opts, llvm::opt::ArgList &Args,
- InputKind IK, DiagnosticsEngine &Diags,
- const llvm::Triple &T,
+ static bool ParseCodeGenArgsImpl(CodeGenOptions &Opts,
+ llvm::opt::ArgList &Args, InputKind IK,
+ DiagnosticsEngine &Diags,
+ const llvm::Triple &T,
+ const std::string &OutputFile,
+ const LangOptions &LangOptsRef);
+
+ static bool ParseCodeGenArgs(CompilerInvocation &Res, CodeGenOptions &Opts,
+ llvm::opt::ArgList &Args, InputKind IK,
+ DiagnosticsEngine &Diags, const llvm::Triple &T,
const std::string &OutputFile,
const LangOptions &LangOptsRef);
+ // Generate command line options from CodeGenOptions.
+ static void GenerateCodeGenArgs(const CodeGenOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, const llvm::Triple &T,
+ const std::string &OutputFile,
+ const LangOptions *LangOpts);
+
/// Parse command line options that map to HeaderSearchOptions.
static void ParseHeaderSearchArgs(CompilerInvocation &Res,
HeaderSearchOptions &Opts,
diff --git a/clang/lib/Basic/XRayInstr.cpp b/clang/lib/Basic/XRayInstr.cpp
index 79052e05860ea..822e14bbb622d 100644
--- a/clang/lib/Basic/XRayInstr.cpp
+++ b/clang/lib/Basic/XRayInstr.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
namespace clang {
@@ -30,4 +31,30 @@ XRayInstrMask parseXRayInstrValue(StringRef Value) {
return ParsedKind;
}
+void serializeXRayInstrValue(XRayInstrSet Set,
+ SmallVectorImpl<StringRef> &Values) {
+ if (Set.Mask == XRayInstrKind::All) {
+ Values.push_back("all");
+ return;
+ }
+
+ if (Set.Mask == XRayInstrKind::None) {
+ Values.push_back("none");
+ return;
+ }
+
+ if (Set.has(XRayInstrKind::Custom))
+ Values.push_back("custom");
+
+ if (Set.has(XRayInstrKind::Typed))
+ Values.push_back("typed");
+
+ if (Set.has(XRayInstrKind::FunctionEntry) &&
+ Set.has(XRayInstrKind::FunctionExit))
+ Values.push_back("function");
+ else if (Set.has(XRayInstrKind::FunctionEntry))
+ Values.push_back("function-entry");
+ else if (Set.has(XRayInstrKind::FunctionExit))
+ Values.push_back("function-exit");
+}
} // namespace clang
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 658dad54532ea..020cbf0f176ec 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -54,6 +54,7 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -625,14 +626,17 @@ static bool RoundTrip(ParseFn Parse, GenerateFn Generate, SwapOptsFn SwapOpts,
// Run the first parse on the original arguments with dummy options and
// diagnostics.
SwapOpts(Res);
- if (!Parse(Res, OriginalArgs, DummyDiags)) {
+ if (!Parse(Res, OriginalArgs, DummyDiags) ||
+ DummyDiags.getNumWarnings() != 0) {
// If the first parse did not succeed, it must be user mistake (invalid
// command line arguments). We won't be able to generate arguments that
// would reproduce the same result. Let's fail again with the original
// options and diagnostics, so all side-effects of parsing are visible.
+ unsigned NumWarningsBefore = Diags.getNumWarnings();
SwapOpts(Res);
- if (!Parse(Res, OriginalArgs, Diags))
- return false;
+ auto Success = Parse(Res, OriginalArgs, Diags);
+ if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
+ return Success;
// Parse with original options and diagnostics succeeded even though it
// shouldn't have. Something is off.
@@ -749,16 +753,11 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
static void getAllNoBuiltinFuncValues(ArgList &Args,
std::vector<std::string> &Funcs) {
- SmallVector<const char *, 8> Values;
- for (const auto &Arg : Args) {
- const Option &O = Arg->getOption();
- if (O.matches(options::OPT_fno_builtin_)) {
- const char *FuncName = Arg->getValue();
- if (Builtin::Context::isBuiltinFunc(FuncName))
- Values.push_back(FuncName);
- }
- }
- Funcs.insert(Funcs.end(), Values.begin(), Values.end());
+ std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
+ auto BuiltinEnd = llvm::partition(Values, [](const std::string FuncName) {
+ return Builtin::Context::isBuiltinFunc(FuncName);
+ });
+ Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
}
static void GenerateAnalyzerArgs(AnalyzerOptions &Opts,
@@ -1238,6 +1237,15 @@ static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
}
}
+static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ serializeXRayInstrValue(S, BundleParts);
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
+ return OS.str();
+}
+
// Set the profile kind using fprofile-instrument-use-path.
static void setPGOUseInstrumentor(CodeGenOptions &Opts,
const Twine &ProfileName) {
@@ -1259,12 +1267,258 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
}
-bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
- InputKind IK,
- DiagnosticsEngine &Diags,
- const llvm::Triple &T,
- const std::string &OutputFile,
- const LangOptions &LangOptsRef) {
+void CompilerInvocation::GenerateCodeGenArgs(
+ const CodeGenOptions &Opts, SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, const llvm::Triple &T, const std::string &OutputFile,
+ const LangOptions *LangOpts) {
+ const CodeGenOptions &CodeGenOpts = Opts;
+
+ if (Opts.OptimizationLevel == 0)
+ GenerateArg(Args, OPT_O0, SA);
+ else
+ GenerateArg(Args, OPT_O, Twine(Opts.OptimizationLevel), SA);
+
+#define CODEGEN_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef CODEGEN_OPTION_WITH_MARSHALLING
+
+ if (Opts.OptimizationLevel > 0) {
+ if (Opts.Inlining == CodeGenOptions::NormalInlining)
+ GenerateArg(Args, OPT_finline_functions, SA);
+ else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
+ GenerateArg(Args, OPT_finline_hint_functions, SA);
+ else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
+ GenerateArg(Args, OPT_fno_inline, SA);
+ }
+
+ if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
+ GenerateArg(Args, OPT_fdirect_access_external_data, SA);
+ else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
+ GenerateArg(Args, OPT_fno_direct_access_external_data, SA);
+
+ Optional<StringRef> DebugInfoVal;
+ switch (Opts.DebugInfo) {
+ case codegenoptions::DebugLineTablesOnly:
+ DebugInfoVal = "line-tables-only";
+ break;
+ case codegenoptions::DebugDirectivesOnly:
+ DebugInfoVal = "line-directives-only";
+ break;
+ case codegenoptions::DebugInfoConstructor:
+ DebugInfoVal = "constructor";
+ break;
+ case codegenoptions::LimitedDebugInfo:
+ DebugInfoVal = "limited";
+ break;
+ case codegenoptions::FullDebugInfo:
+ DebugInfoVal = "standalone";
+ break;
+ case codegenoptions::UnusedTypeInfo:
+ DebugInfoVal = "unused-types";
+ break;
+ case codegenoptions::NoDebugInfo: // default value
+ DebugInfoVal = None;
+ break;
+ case codegenoptions::LocTrackingOnly: // implied value
+ DebugInfoVal = None;
+ break;
+ }
+ if (DebugInfoVal)
+ GenerateArg(Args, OPT_debug_info_kind_EQ, *DebugInfoVal, SA);
+
+ if (Opts.DebugInfo == codegenoptions::DebugInfoConstructor)
+ GenerateArg(Args, OPT_fuse_ctor_homing, SA);
+
+ for (const auto &Prefix : Opts.DebugPrefixMap)
+ GenerateArg(Args, OPT_fdebug_prefix_map_EQ,
+ Prefix.first + "=" + Prefix.second, SA);
+
+ for (const auto &Prefix : Opts.ProfilePrefixMap)
+ GenerateArg(Args, OPT_fprofile_prefix_map_EQ,
+ Prefix.first + "=" + Prefix.second, SA);
+
+ if (Opts.NewStructPathTBAA)
+ GenerateArg(Args, OPT_new_struct_path_tbaa, SA);
+
+ if (Opts.OptimizeSize == 1)
+ GenerateArg(Args, OPT_O, "s", SA);
+ else if (Opts.OptimizeSize == 2)
+ GenerateArg(Args, OPT_O, "z", SA);
+
+ // SimplifyLibCalls is set only in the absence of -fno-builtin and
+ // -ffreestanding. We'll consider that when generating them.
+
+ // NoBuiltinFuncs are generated by LangOptions.
+
+ if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
+ GenerateArg(Args, OPT_funroll_loops, SA);
+ else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
+ GenerateArg(Args, OPT_fno_unroll_loops, SA);
+
+ if (!Opts.BinutilsVersion.empty())
+ GenerateArg(Args, OPT_fbinutils_version_EQ, Opts.BinutilsVersion, SA);
+
+ if (Opts.DebugNameTable ==
+ static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
+ GenerateArg(Args, OPT_ggnu_pubnames, SA);
+ else if (Opts.DebugNameTable ==
+ static_cast<unsigned>(
+ llvm::DICompileUnit::DebugNameTableKind::Default))
+ GenerateArg(Args, OPT_gpubnames, SA);
+
+ // ProfileInstrumentUsePath is marshalled automatically, no need to generate
+ // it or PGOUseInstrumentor.
+
+ if (Opts.TimePasses) {
+ if (Opts.TimePassesPerRun)
+ GenerateArg(Args, OPT_ftime_report_EQ, "per-pass-run", SA);
+ else
+ GenerateArg(Args, OPT_ftime_report, SA);
+ }
+
+ if (Opts.FunctionSections &&
+ (Opts.BBSections == "none" || Opts.BBSections == "labels"))
+ GenerateArg(Args, OPT_ffunction_sections, SA);
+
+ if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
+ GenerateArg(Args, OPT_flto, SA);
+
+ if (Opts.PrepareForThinLTO)
+ GenerateArg(Args, OPT_flto_EQ, "thin", SA);
+
+ if (!Opts.ThinLTOIndexFile.empty())
+ GenerateArg(Args, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile, SA);
+
+ if (Opts.SaveTempsFilePrefix == OutputFile)
+ GenerateArg(Args, OPT_save_temps_EQ, "obj", SA);
+
+ StringRef MemProfileBasename("memprof.profraw");
+ if (!Opts.MemoryProfileOutput.empty()) {
+ if (Opts.MemoryProfileOutput == MemProfileBasename) {
+ GenerateArg(Args, OPT_fmemory_profile, SA);
+ } else {
+ size_t ArgLength =
+ Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
+ GenerateArg(Args, OPT_fmemory_profile_EQ,
+ Opts.MemoryProfileOutput.substr(0, ArgLength), SA);
+ }
+ }
+
+ if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)
+ GenerateArg(Args, OPT_coverage_version_EQ, Opts.CoverageVersion, SA);
+
+ // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
+ // '-fembed_bitcode', which does not map to any CompilerInvocation field and
+ // won't be generated.)
+
+ if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {
+ std::string InstrBundle =
+ serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);
+ if (!InstrBundle.empty())
+ GenerateArg(Args, OPT_fxray_instrumentation_bundle, InstrBundle, SA);
+ }
+
+ if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "full", SA);
+ else if (Opts.CFProtectionReturn)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "return", SA);
+ else if (Opts.CFProtectionBranch)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA);
+
+ for (const auto &F : Opts.LinkBitcodeFiles) {
+ bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
+ F.PropagateAttrs && F.Internalize;
+ GenerateArg(Args,
+ Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
+ F.Filename, SA);
+ }
+
+ // TODO: Consider removing marshalling annotations from f[no_]emulated_tls.
+ // That would make it easy to generate the option only **once** if it was
+ // explicitly set to non-default value.
+ if (Opts.ExplicitEmulatedTLS) {
+ GenerateArg(
+ Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA);
+ }
+
+ if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) {
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ Opts.FPDenormalMode.print(OS);
+ GenerateArg(Args, OPT_fdenormal_fp_math_EQ, OS.str(), SA);
+ }
+
+ if (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()) {
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ Opts.FP32DenormalMode.print(OS);
+ GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, OS.str(), SA);
+ }
+
+ if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
+ OptSpecifier Opt =
+ T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
+ GenerateArg(Args, Opt, SA);
+ } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
+ OptSpecifier Opt =
+ T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
+ GenerateArg(Args, Opt, SA);
+ }
+
+ if (Opts.IgnoreXCOFFVisibility)
+ GenerateArg(Args, OPT_mignore_xcoff_visibility, SA);
+
+ if (Opts.EnableAIXExtendedAltivecABI)
+ GenerateArg(Args, OPT_mabi_EQ_vec_extabi, SA);
+
+ if (!Opts.OptRecordPasses.empty())
+ GenerateArg(Args, OPT_opt_record_passes, Opts.OptRecordPasses, SA);
+
+ if (!Opts.OptRecordFormat.empty())
+ GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA);
+
+ if (Opts.OptimizationRemarkPattern)
+ GenerateArg(Args, OPT_Rpass_EQ, Opts.OptimizationRemarkPattern.Pattern, SA);
+
+ if (Opts.OptimizationRemarkMissedPattern)
+ GenerateArg(Args, OPT_Rpass_missed_EQ,
+ Opts.OptimizationRemarkMissedPattern.Pattern, SA);
+
+ if (Opts.OptimizationRemarkAnalysisPattern)
+ GenerateArg(Args, OPT_Rpass_analysis_EQ,
+ Opts.OptimizationRemarkAnalysisPattern.Pattern, SA);
+
+ GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ,
+ Opts.DiagnosticsHotnessThreshold
+ ? Twine(*Opts.DiagnosticsHotnessThreshold)
+ : "auto",
+ SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
+ GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
+ GenerateArg(Args, OPT_fsanitize_trap_EQ, Sanitizer, SA);
+
+ if (!Opts.EmitVersionIdentMetadata)
+ GenerateArg(Args, OPT_Qn, SA);
+}
+
+bool CompilerInvocation::ParseCodeGenArgsImpl(CodeGenOptions &Opts,
+ ArgList &Args, InputKind IK,
+ DiagnosticsEngine &Diags,
+ const llvm::Triple &T,
+ const std::string &OutputFile,
+ const LangOptions &LangOptsRef) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
bool Success = true;
unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
@@ -1324,7 +1578,24 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.DirectAccessExternalData =
Args.hasArg(OPT_fdirect_access_external_data) ||
(!Args.hasArg(OPT_fno_direct_access_external_data) &&
- getLastArgIntValue(Args, OPT_pic_level, 0, Diags) == 0);
+ LangOpts->PICLevel == 0);
+
+ if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
+ unsigned Val =
+ llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
+ .Case("line-directives-only", codegenoptions::DebugDirectivesOnly)
+ .Case("constructor", codegenoptions::DebugInfoConstructor)
+ .Case("limited", codegenoptions::LimitedDebugInfo)
+ .Case("standalone", codegenoptions::FullDebugInfo)
+ .Case("unused-types", codegenoptions::UnusedTypeInfo)
+ .Default(~0U);
+ if (Val == ~0U)
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << A->getValue();
+ else
+ Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val));
+ }
// If -fuse-ctor-homing is set and limited debug info is already on, then use
// constructor homing.
@@ -1356,10 +1627,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
Args.hasArg(OPT_new_struct_path_tbaa);
Opts.OptimizeSize = getOptimizationLevelSize(Args);
- Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
- Args.hasArg(OPT_ffreestanding));
+ Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
if (Opts.SimplifyLibCalls)
- getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
+ Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
Opts.UnrollLoops =
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
(Opts.OptimizationLevel > 1));
@@ -1434,6 +1704,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
} else if (Args.hasArg(OPT_fmemory_profile))
Opts.MemoryProfileOutput = MemProfileBasename;
+ memcpy(Opts.CoverageVersion, "408*", 4);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
if (Args.hasArg(OPT_coverage_version_EQ)) {
StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
@@ -1650,7 +1921,30 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
- return Success;
+ return Success && Diags.getNumErrors() == NumErrorsBefore;
+}
+
+bool CompilerInvocation::ParseCodeGenArgs(
+ CompilerInvocation &Res, CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+ DiagnosticsEngine &Diags, const llvm::Triple &T,
+ const std::string &OutputFile, const LangOptions &LangOptsRef) {
+ CodeGenOptions DummyOpts;
+
+ return RoundTrip(
+ [&](CompilerInvocation &Res, ArgList &Args, DiagnosticsEngine &Diags) {
+ Args.getLastArg(OPT_O0, OPT_O4, OPT_O, OPT_Ofast);
+ return ParseCodeGenArgsImpl(Res.getCodeGenOpts(), Args, IK, Diags, T,
+ OutputFile, LangOptsRef);
+ },
+ [&](CompilerInvocation &Res, SmallVectorImpl<const char *> &GeneratedArgs,
+ StringAllocator SA) {
+ GenerateCodeGenArgs(Res.getCodeGenOpts(), GeneratedArgs, SA, T,
+ OutputFile, &LangOptsRef);
+ },
+ [&DummyOpts](CompilerInvocation &Res) {
+ std::swap(Res.CodeGenOpts, DummyOpts);
+ },
+ Res, Args, Diags, "CodeGenOptions");
}
static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
@@ -2746,8 +3040,9 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
if (Opts.NoBuiltin && !Opts.Freestanding)
GenerateArg(Args, OPT_fno_builtin, SA);
- // Not generating '-fno-builtin-xxx'. It's handled for CodeGenOptions, that
- // also read OPT_fno_builtin_.
+ if (!Opts.NoBuiltin)
+ for (const auto &Func : Opts.NoBuiltinFuncs)
+ GenerateArg(Args, OPT_fno_builtin_, Func, SA);
if (Opts.LongDoubleSize == 128)
GenerateArg(Args, OPT_mlong_double_128, SA);
@@ -3719,7 +4014,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
if (LangOpts.OpenMPIsDevice)
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
- Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
+ Success &= ParseCodeGenArgs(Res, Res.getCodeGenOpts(), Args, DashX, Diags, T,
Res.getFrontendOpts().OutputFile, LangOpts);
// FIXME: Override value name discarding when asan or msan is used because the
@@ -3883,11 +4178,9 @@ void CompilerInvocation::generateCC1CommandLine(
EXTRACTOR, TABLE_INDEX)
#define DIAG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-#define CODEGEN_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
#include "clang/Driver/Options.inc"
-#undef CODEGEN_OPTION_WITH_MARSHALLING
#undef DIAG_OPTION_WITH_MARSHALLING
#undef OPTION_WITH_MARSHALLING
@@ -3896,6 +4189,8 @@ void CompilerInvocation::generateCC1CommandLine(
GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
GenerateLangArgs(*LangOpts, Args, SA, T);
+ GenerateCodeGenArgs(CodeGenOpts, Args, SA, T, FrontendOpts.OutputFile,
+ &*LangOpts);
GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts,
FrontendOpts, CodeGenOpts);
}
diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 9a179c511bd6c..c85c6c56c8ea9 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -175,7 +175,7 @@ class MarshallingInfoString<KeyPathAndMacro kpm, code defaultvalue="std::string(
class MarshallingInfoStringInt<KeyPathAndMacro kpm, code defaultvalue="0", code type="unsigned">
: MarshallingInfo<kpm, defaultvalue> {
code Normalizer = "normalizeStringIntegral<"#type#">";
- code Denormalizer = "denormalizeString";
+ code Denormalizer = "denormalizeString<"#type#">";
}
class MarshallingInfoStringVector<KeyPathAndMacro kpm>
More information about the cfe-commits
mailing list