diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1035,8 +1035,16 @@ parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())), arg->getSpelling()); - for (auto *arg : args.filtered(OPT_plugin_opt)) - parseClangOption(arg->getValue(), arg->getSpelling()); + for (opt::Arg *arg : args.filtered(OPT_plugin_opt_EQ_MINUS)) + parseClangOption(std::string("-") + arg->getValue(), arg->getSpelling()); + + // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or + // relative path. Just ignore. If not ended with "lto-wrapper", consider it an + // unsupported LLVMgold.so option and error. + for (opt::Arg *arg : args.filtered(OPT_plugin_opt_EQ)) + if (!StringRef(arg->getValue()).endswith("lto-wrapper")) + error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() + + "'"); // Parse -mllvm options. for (auto *arg : args.filtered(OPT_mllvm)) diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -504,7 +504,6 @@ HelpText<"Include hotness information in the optimization remarks file">; def opt_remarks_format: Separate<["--"], "opt-remarks-format">, HelpText<"The format used for serializing remarks (default: YAML)">; -defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">; def save_temps: F<"save-temps">; def lto_basicblock_sections: J<"lto-basicblock-sections=">, HelpText<"Enable basic block sections for LTO">; @@ -571,10 +570,17 @@ // --version output. defm plugin: Eq<"plugin", "Ignored for compatibility with GNU linkers">; -def plugin_opt_fresolution_eq: J<"plugin-opt=-fresolution=">; -def plugin_opt_pass_through_eq: J<"plugin-opt=-pass-through=">; -def plugin_opt_thinlto: J<"plugin-opt=thinlto">; -def plugin_opt_slash: J<"plugin-opt=/">; +def plugin_opt_EQ_MINUS: J<"plugin-opt=-">, + HelpText<"Specify an LLVM option for compatibility with LLVMgold.so">; +def: J<"plugin-opt=thinlto">; + +// Ignore GCC collect2 LTO plugin related options. Note that we don't support +// GCC LTO, but GCC collect2 passes these options even in non-LTO mode. +def: J<"plugin-opt=-fresolution=">; +def: J<"plugin-opt=-pass-through=">; +// This may be either an unhandled LLVMgold.so feature or GCC passed +// -plugin-opt=path/to/{liblto_plugin.so,lto-wrapper} +def plugin_opt_EQ : J<"plugin-opt=">; // Options listed below are silently ignored for now for compatibility. def: F<"detect-odr-violations">; diff --git a/lld/test/ELF/lto-plugin-ignore.s b/lld/test/ELF/lto-plugin-ignore.s --- a/lld/test/ELF/lto-plugin-ignore.s +++ b/lld/test/ELF/lto-plugin-ignore.s @@ -1,10 +1,28 @@ # REQUIRES: x86 +## Test we ignore some LTO related options from clang/GCC collect2. -# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t -# RUN: ld.lld %t -plugin-opt=/foo/bar -plugin-opt=-fresolution=zed \ -# RUN: -plugin-opt=-pass-through=-lgcc -plugin-opt=-function-sections \ -# RUN: -plugin-opt=-data-sections -plugin-opt=thinlto -o /dev/null +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o -# RUN: not ld.lld %t -plugin-opt=-abc -plugin-opt=-xyz 2>&1 | FileCheck %s -# CHECK: ld.lld: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-abc' -# CHECK: ld.lld: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-xyz' +## GCC collect2 passes several LTO related options to the linker even if -flto is not used. +## We need to ignore them. Note that the lto-wrapper path can be relative. +# RUN: ld.lld %t.o -o /dev/null \ +# RUN: -plugin path/to/liblto_plugin.so \ +# RUN: -plugin-opt=/path/to/lto-wrapper \ +# RUN: -plugin-opt=relative/path/to/lto-wrapper \ +# RUN: -plugin-opt=-fresolution=zed \ +# RUN: -plugin-opt=-pass-through=-lgcc \ +# RUN: -plugin-opt=-pass-through=-lgcc_eh \ +# RUN: -plugin-opt=-pass-through=-lc + +## Clang LTO passes several options to the linker, which are intended to be consumed by +## LLVMgold.so. We need to ignore them. +# RUN: ld.lld %t.o -o /dev/null -plugin /path/to/LLVMgold.so -plugin-opt=thinlto + +## Other -plugin-opt=- prefixed options are passed through to cl::ParseCommandLineOptions. +# RUN: not ld.lld %t.o -o /dev/null -plugin-opt=-abc -plugin-opt=-xyz 2>&1 | FileCheck %s +# CHECK: ld.lld: error: -plugin-opt=-: ld.lld{{.*}}: Unknown command line argument '-abc' +# CHECK: ld.lld: error: -plugin-opt=-: ld.lld{{.*}}: Unknown command line argument '-xyz' + +## Error if the option is an unhandled LLVMgold.so feature. +# RUN: not ld.lld %t.o -o /dev/null -plugin-opt=LLVMgold-feature 2>&1 | FileCheck --check-prefix=GOLD %s +# GOLD: ld.lld: error: -plugin-opt=: unknown plugin option 'LLVMgold-feature'