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,8 @@ 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()); // 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">; @@ -524,6 +523,8 @@ def thinlto_object_suffix_replace_eq: J<"thinlto-object-suffix-replace=">; def thinlto_prefix_replace_eq: J<"thinlto-prefix-replace=">; +def plugin_opt_EQ_MINUS: J<"plugin-opt=-">, + HelpText<"Specify an LLVM option for compatibility with LLVMgold.so">; def: J<"plugin-opt=O">, Alias, HelpText<"Alias for --lto-O">; def: F<"plugin-opt=debug-pass-manager">, Alias, HelpText<"Alias for --lto-debug-pass-manager">; @@ -571,10 +572,9 @@ // --version output. defm plugin: Eq<"plugin", "Ignored for compatibility with GNU linkers">; +def plugin_opt_EQ: J<"plugin-opt=">; 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=/">; // 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,25 @@ # 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 a path can be relative. +# RUN: ld.lld %t.o -o /dev/null \ +# RUN: -plugin-opt=/abs/path/to/liblto_plugin.so \ +# RUN: -plugin-opt=relative/path/to/lto-wrapper \ +# RUN: -plugin-opt=-fresolution=zed \ +# RUN: -plugin-opt=-pass-through=-lgcc + +## 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' + +## Some LLVMgold.so options start with -plugin-opt= but not with -plugin-opt=-. +## They are silently ignored. +# RUN: ld.lld %t.o -o /dev/null -plugin-opt=LLVMgold-feature