diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-07-27 07:32:11 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-07-27 07:32:11 +0000 |
commit | 015ce0f68f791b3abec4225c1b2e532ce5020174 (patch) | |
tree | 7b755798a643c838a8f3e25bbbf175715ed04018 /clang/lib/Driver/MSVCToolChain.cpp | |
parent | a96ffd5337191d0862c236e27801aafb6fbc4a9b (diff) | |
download | bcm5719-llvm-015ce0f68f791b3abec4225c1b2e532ce5020174.tar.gz bcm5719-llvm-015ce0f68f791b3abec4225c1b2e532ce5020174.zip |
[clang-cl] Handle -O correctly
We had multiple bugs here:
- We didn't support multiple optimization options in one argument.
e.g. -O2y-
- We didn't correctly expand -O[12dx] to their respective options.
- We treated -O1 as clang -O1 instead of clang -Os.
- We treated -Ox as clang -O3 instead of clang -O2. In fact, cl's -Ox
option is *less* powerful than cl's -O2 option despite -Ox described
as "Full Optimization".
This fixes PR24003.
llvm-svn: 243261
Diffstat (limited to 'clang/lib/Driver/MSVCToolChain.cpp')
-rw-r--r-- | clang/lib/Driver/MSVCToolChain.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/clang/lib/Driver/MSVCToolChain.cpp b/clang/lib/Driver/MSVCToolChain.cpp index c816b29dca2..b890375742e 100644 --- a/clang/lib/Driver/MSVCToolChain.cpp +++ b/clang/lib/Driver/MSVCToolChain.cpp @@ -528,3 +528,101 @@ SanitizerMask MSVCToolChain::getSupportedSanitizers() const { Res |= SanitizerKind::Address; return Res; } + +llvm::opt::DerivedArgList * +MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, + const char *BoundArch) const { + DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); + const OptTable &Opts = getDriver().getOpts(); + + // The -O[12xd] flag actually expands to several flags. We must desugar the + // flags so that options embedded can be negated. For example, the '-O2' flag + // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to + // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single + // aspect of '-O2'. + // + // Note that this expansion logic only applies to the *last* of '[12xd]'. + + // First step is to search for the character we'd like to expand. + const char *ExpandChar = nullptr; + for (Arg *A : Args) { + if (!A->getOption().matches(options::OPT__SLASH_O)) + continue; + StringRef OptStr = A->getValue(); + for (size_t I = 0, E = OptStr.size(); I != E; ++I) { + const char &OptChar = *(OptStr.data() + I); + if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') + ExpandChar = OptStr.data() + I; + } + } + + // The -O flag actually takes an amalgam of other options. For example, + // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. + for (Arg *A : Args) { + if (!A->getOption().matches(options::OPT__SLASH_O)) { + DAL->append(A); + continue; + } + + StringRef OptStr = A->getValue(); + for (size_t I = 0, E = OptStr.size(); I != E; ++I) { + const char &OptChar = *(OptStr.data() + I); + switch (OptChar) { + default: + break; + case '1': + case '2': + case 'x': + case 'd': + if (&OptChar == ExpandChar) { + if (OptChar == 'd') { + DAL->AddFlagArg(A, Opts.getOption(options::OPT_O0)); + } else { + if (OptChar == '1') { + DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); + } else if (OptChar == '2' || OptChar == 'x') { + DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); + DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); + } + DAL->AddFlagArg(A, + Opts.getOption(options::OPT_fomit_frame_pointer)); + if (OptChar == '1' || OptChar == '2') + DAL->AddFlagArg(A, + Opts.getOption(options::OPT_ffunction_sections)); + } + } + break; + case 'b': + if (isdigit(OptStr[I + 1])) + ++I; + break; + case 'g': + break; + case 'i': + if (OptStr[I + 1] == '-') { + ++I; + DAL->AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); + } else { + DAL->AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); + } + break; + case 's': + DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); + break; + case 't': + DAL->AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); + break; + case 'y': + if (OptStr[I + 1] == '-') { + ++I; + DAL->AddFlagArg(A, + Opts.getOption(options::OPT_fno_omit_frame_pointer)); + } else { + DAL->AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); + } + break; + } + } + } + return DAL; +} |