diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -845,6 +845,24 @@ return true; } +static bool getLtoWholeProgramVisibility(opt::InputArgList &args) { + auto *Arg = args.getLastArg(OPT_lto_whole_program_visibility, + OPT_lto_whole_program_visibility_eq); + if (!Arg) + return false; + if (Arg->getOption().getID() == OPT_lto_whole_program_visibility) + return true; + StringRef s = Arg->getValue(); + if (s == "off") + return false; + else if (s == "on") + return true; + else if (s == "noexportdynamic") + return !(args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false)); + error("unknown --lto-whole-program-visibility: " + s); + return false; +} + static StringRef getAliasSpelling(opt::Arg *arg) { if (const opt::Arg *alias = arg->getAlias()) return alias->getSpelling(); @@ -974,8 +992,7 @@ config->ltoEmitAsm = args.hasArg(OPT_lto_emit_asm); config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager); config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes); - config->ltoWholeProgramVisibility = - args.hasArg(OPT_lto_whole_program_visibility); + config->ltoWholeProgramVisibility = getLtoWholeProgramVisibility(args); config->ltoo = args::getInteger(args, OPT_lto_O, 2); config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -542,8 +542,12 @@ def lto_obj_path_eq: JJ<"lto-obj-path=">; def lto_sample_profile: JJ<"lto-sample-profile=">, HelpText<"Sample profile file path">; -def lto_whole_program_visibility: FF<"lto-whole-program-visibility">, - HelpText<"Asserts that the LTO link has whole program visibility">; +def lto_whole_program_visibility: FF<"lto-whole-program-visibility">; +def lto_whole_program_visibility_eq: JJ<"lto-whole-program-visibility=">, + HelpText<"Asserts that the LTO link has whole program visibility. " + "If specified without any argument, defaults to 'on'. " + "If 'noexportdynamic' then on unless --export-dynamic also specified.">, + MetaVarName<"[off,noexportdynamic,on]">; def disable_verify: F<"disable-verify">; defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">; def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, diff --git a/lld/test/ELF/lto/devirt_vcall_vis_public.ll b/lld/test/ELF/lto/devirt_vcall_vis_public.ll --- a/lld/test/ELF/lto/devirt_vcall_vis_public.ll +++ b/lld/test/ELF/lto/devirt_vcall_vis_public.ll @@ -7,6 +7,15 @@ ; RUN: ld.lld %t2.o -o %t3 -save-temps --lto-whole-program-visibility \ ; RUN: -mllvm -pass-remarks=. --export-dynamic 2>&1 | FileCheck %s --check-prefix=REMARK ; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR +; Try again with explicit "on" +; RUN: ld.lld %t2.o -o %t3 -save-temps --lto-whole-program-visibility=on \ +; RUN: -mllvm -pass-remarks=. --export-dynamic 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR +; Try again with "noexportdynamic" and use -u instead of --export-dynamic +; RUN: ld.lld %t2.o -o %t3 -save-temps --lto-whole-program-visibility=noexportdynamic \ +; RUN: -mllvm -pass-remarks=. -u _start -u _ZTV1B -u _ZTV1C -u _ZTV1D \ +; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR ; Hybrid WPD ; Generate split module with summary for hybrid Thin/Regular LTO WPD. @@ -31,6 +40,14 @@ ; RUN: ld.lld %t2.o -o %t3 -save-temps \ ; RUN: -mllvm -pass-remarks=. --export-dynamic 2>&1 | FileCheck %s --implicit-check-not single-impl --allow-empty ; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-NODEVIRT-IR +; Try again with explicit "off" +; RUN: ld.lld %t2.o -o %t3 -save-temps --lto-whole-program-visibility=off \ +; RUN: -mllvm -pass-remarks=. --export-dynamic 2>&1 | FileCheck %s --implicit-check-not single-impl --allow-empty +; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-NODEVIRT-IR +; Try again with "noexportdynamic" +; RUN: ld.lld %t2.o -o %t3 -save-temps --lto-whole-program-visibility=noexportdynamic \ +; RUN: -mllvm -pass-remarks=. --export-dynamic 2>&1 | FileCheck %s --implicit-check-not single-impl --allow-empty +; RUN: llvm-dis %t2.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-NODEVIRT-IR ; Hybrid WPD ; RUN: ld.lld %t.o -o %t3 -save-temps \