forked from OSchip/llvm-project
[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
This commit is contained in:
parent
ec12f5febe
commit
e721bc9eff
|
@ -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
|
||||
|
|
|
@ -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">>;
|
||||
|
|
|
@ -266,12 +266,26 @@ private:
|
|||
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,
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue