From 9f0f36e02231e86eadaac12f74f6a86e1c5318c1 Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Wed, 25 Sep 2019 01:19:48 +0000 Subject: [PATCH] [ELF] accept thinlto options without --plugin-opt= prefix Summary: When support for ThinLTO was first added to lld, the options that control it were prefixed with --plugin-opt= for compatibility with an existing implementation as a linker plugin. This change enables shorter versions of the options to be used, as follows: New Existing -thinlto-emit-imports-files --plugin-opt=thinlto-emit-imports-files -thinlto-index-only --plugin-opt=thinlto-index-only -thinlto-index-only= --plugin-opt=thinlto-index-only= -thinlto-object-suffix-replace= --plugin-opt=thinlto-object-suffix-replace= -thinlto-prefix-replace= --plugin-opt=thinlto-prefix-replace= -lto-obj-path= --plugin-opt=obj-path= The options with the --plugin-opt= prefix have been retained as aliases for the shorter variants so that they continue to be accepted. Reviewers: tejohnson, ruiu, espindola Reviewed By: ruiu Subscribers: emaste, arichardson, MaskRay, steven_wu, dexonsmith, arphaman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67782 llvm-svn: 372798 --- lld/ELF/Driver.cpp | 24 ++++++++------- lld/ELF/Options.td | 30 +++++++++++++++---- lld/test/ELF/lto/thinlto-emit-imports.ll | 15 +++++++--- lld/test/ELF/lto/thinlto-index-file.ll | 6 +++- lld/test/ELF/lto/thinlto-obj-path.ll | 7 ++++- .../ELF/lto/thinlto-object-suffix-replace.ll | 5 ++++ lld/test/ELF/lto/thinlto-prefix-replace.ll | 5 ++++ 7 files changed, 70 insertions(+), 22 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f4a4d1d3fd18..e5f3febd0693 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -757,6 +757,12 @@ static bool getCompressDebugSections(opt::InputArgList &args) { return true; } +static StringRef getAliasSpelling(opt::Arg *arg) { + if (const opt::Arg *alias = arg->getAlias()) + return alias->getSpelling(); + return arg->getSpelling(); +} + static std::pair getOldNewOptions(opt::InputArgList &args, unsigned id) { auto *arg = args.getLastArg(id); @@ -766,7 +772,7 @@ static std::pair getOldNewOptions(opt::InputArgList &args, StringRef s = arg->getValue(); std::pair ret = s.split(';'); if (ret.second.empty()) - error(arg->getSpelling() + " expects 'old;new' format, but got " + s); + error(getAliasSpelling(arg) + " expects 'old;new' format, but got " + s); return ret; } @@ -858,7 +864,7 @@ static void readConfigs(opt::InputArgList &args) { config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager); config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes); config->ltoo = args::getInteger(args, OPT_lto_O, 2); - config->ltoObjPath = args.getLastArgValue(OPT_plugin_opt_obj_path_eq); + config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile); config->mapFile = args.getLastArgValue(OPT_Map); @@ -903,17 +909,15 @@ static void readConfigs(opt::InputArgList &args) { config->thinLTOCachePolicy = CHECK( parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - config->thinLTOEmitImportsFiles = - args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files); - config->thinLTOIndexOnly = args.hasArg(OPT_plugin_opt_thinlto_index_only) || - args.hasArg(OPT_plugin_opt_thinlto_index_only_eq); - config->thinLTOIndexOnlyArg = - args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq); + config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files); + config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) || + args.hasArg(OPT_thinlto_index_only_eq); + config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq); config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u); config->thinLTOObjectSuffixReplace = - getOldNewOptions(args, OPT_plugin_opt_thinlto_object_suffix_replace_eq); + getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq); config->thinLTOPrefixReplace = - getOldNewOptions(args, OPT_plugin_opt_thinlto_prefix_replace_eq); + getOldNewOptions(args, OPT_thinlto_prefix_replace_eq); config->trace = args.hasArg(OPT_trace); config->undefined = args::getStrings(args, OPT_undefined); config->undefinedVersion = diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 3711ca512f77..c540efb25e90 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -481,6 +481,7 @@ def lto_cs_profile_generate: F<"lto-cs-profile-generate">, HelpText<"Perform context senstive PGO instrumentation">; def lto_cs_profile_file: J<"lto-cs-profile-file=">, HelpText<"Context sensitive profile file path">; +def lto_obj_path_eq: J<"lto-obj-path=">; def lto_sample_profile: J<"lto-sample-profile=">, HelpText<"Sample profile file path">; def disable_verify: F<"disable-verify">; @@ -498,7 +499,12 @@ def save_temps: F<"save-temps">; def thinlto_cache_dir: J<"thinlto-cache-dir=">, HelpText<"Path to ThinLTO cached object file directory">; defm thinlto_cache_policy: Eq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">; +def thinlto_emit_imports_files: F<"thinlto-emit-imports-files">; +def thinlto_index_only: F<"thinlto-index-only">; +def thinlto_index_only_eq: J<"thinlto-index-only=">; def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; +def thinlto_object_suffix_replace_eq: J<"thinlto-object-suffix-replace=">; +def thinlto_prefix_replace_eq: J<"thinlto-prefix-replace=">; def: J<"plugin-opt=O">, Alias, HelpText<"Alias for -lto-O">; def: F<"plugin-opt=debug-pass-manager">, @@ -512,19 +518,31 @@ def: J<"plugin-opt=lto-partitions=">, Alias, HelpText<"Alias for def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">; def: F<"plugin-opt=new-pass-manager">, Alias, HelpText<"Alias for -lto-new-pass-manager">; -def plugin_opt_obj_path_eq: J<"plugin-opt=obj-path=">; def: F<"plugin-opt=cs-profile-generate">, Alias, HelpText<"Alias for -lto-cs-profile-generate">; def: J<"plugin-opt=cs-profile-path=">, Alias, HelpText<"Alias for -lto-cs-profile-file">; +def: J<"plugin-opt=obj-path=">, + Alias, + HelpText<"Alias for -lto-obj-path=">; def: J<"plugin-opt=sample-profile=">, Alias, HelpText<"Alias for -lto-sample-profile">; def: F<"plugin-opt=save-temps">, Alias, HelpText<"Alias for -save-temps">; -def plugin_opt_thinlto_emit_imports_files: F<"plugin-opt=thinlto-emit-imports-files">; -def plugin_opt_thinlto_index_only: F<"plugin-opt=thinlto-index-only">; -def plugin_opt_thinlto_index_only_eq: J<"plugin-opt=thinlto-index-only=">; -def plugin_opt_thinlto_object_suffix_replace_eq: J<"plugin-opt=thinlto-object-suffix-replace=">; -def plugin_opt_thinlto_prefix_replace_eq: J<"plugin-opt=thinlto-prefix-replace=">; +def: F<"plugin-opt=thinlto-emit-imports-files">, + Alias, + HelpText<"Alias for -thinlto-emit-imports-files">; +def: F<"plugin-opt=thinlto-index-only">, + Alias, + HelpText<"Alias for -thinlto-index-only">; +def: J<"plugin-opt=thinlto-index-only=">, + Alias, + HelpText<"Alias for -thinlto-index-only=">; +def: J<"plugin-opt=thinlto-object-suffix-replace=">, + Alias, + HelpText<"Alias for -thinlto-object-suffix-replace=">; +def: J<"plugin-opt=thinlto-prefix-replace=">, + Alias, + HelpText<"Alias for -thinlto-prefix-replace=">; // Ignore LTO plugin-related options. // clang -flto passes -plugin and -plugin-opt to the linker. This is required diff --git a/lld/test/ELF/lto/thinlto-emit-imports.ll b/lld/test/ELF/lto/thinlto-emit-imports.ll index f85f409a26a1..c2d047757001 100644 --- a/lld/test/ELF/lto/thinlto-emit-imports.ll +++ b/lld/test/ELF/lto/thinlto-emit-imports.ll @@ -14,15 +14,15 @@ ; The imports file for this module contains the bitcode file for ; Inputs/thinlto.ll -; RUN: cat %t1.o.imports | count 1 -; RUN: cat %t1.o.imports | FileCheck %s --check-prefix=IMPORTS1 +; RUN: count 1 < %t1.o.imports +; RUN: FileCheck %s --check-prefix=IMPORTS1 < %t1.o.imports ; IMPORTS1: thinlto-emit-imports.ll.tmp2.o ; The imports file for Input/thinlto.ll is empty as it does not import anything. -; RUN: cat %t2.o.imports | count 0 +; RUN: count 0 < %t2.o.imports ; The imports file for Input/thinlto_empty.ll is empty but should exist. -; RUN: cat %t3.o.imports | count 0 +; RUN: count 0 < %t3.o.imports ; The index file should be created even for the input with an empty summary. ; RUN: ls %t3.o.thinlto.bc @@ -43,6 +43,13 @@ ; RUN: not ls %t2.o.imports ; RUN: not ls %t3.o.imports +; Check that imports files are generated also when -thinlto-index-only +; is specified without --plugin-opt=. +; RUN: rm -f %t1.o.imports +; RUN: ld.lld -thinlto-index-only -thinlto-emit-imports-files -shared %t1.o %t2.o %t3.o -o %t4 +; RUN: count 1 < %t1.o.imports +; RUN: FileCheck %s --check-prefix=IMPORTS1 < %t1.o.imports + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lld/test/ELF/lto/thinlto-index-file.ll b/lld/test/ELF/lto/thinlto-index-file.ll index 18f4350b3a4b..5792f7b6a9bf 100644 --- a/lld/test/ELF/lto/thinlto-index-file.ll +++ b/lld/test/ELF/lto/thinlto-index-file.ll @@ -6,12 +6,16 @@ ; RUN: opt -module-summary %p/Inputs/thinlto_empty.ll -o %t3.o ; Ensure lld writes linked files to linked objects file -; RUN: ld.lld --plugin-opt=thinlto-index-only=%t.idx -shared %t1.o %t2.o %t3.o -o %t4 +; RUN: ld.lld --plugin-opt=thinlto-index-only=%t.idx -shared %t1.o %t2.o %t3.o -o /dev/null ; RUN: FileCheck %s < %t.idx ; CHECK: {{.*}}thinlto-index-file.ll.tmp1.o ; CHECK: {{.*}}thinlto-index-file.ll.tmp2.o ; CHECK: {{.*}}thinlto-index-file.ll.tmp3.o +; Check that this also works without the --plugin-opt= prefix. +; RUN: ld.lld -thinlto-index-only=%t.idx -shared %t1.o %t2.o %t3.o -o /dev/null +; RUN: FileCheck %s < %t.idx + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lld/test/ELF/lto/thinlto-obj-path.ll b/lld/test/ELF/lto/thinlto-obj-path.ll index 8878c8984d09..224b5b651861 100644 --- a/lld/test/ELF/lto/thinlto-obj-path.ll +++ b/lld/test/ELF/lto/thinlto-obj-path.ll @@ -5,11 +5,16 @@ ; Test to ensure that thinlto-index-only with obj-path creates the file. ; RUN: rm -f %t4.o -; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=obj-path=%t4.o -shared %t1.o %t2.o -o %t3 +; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=obj-path=%t4.o -shared %t1.o %t2.o -o /dev/null ; RUN: llvm-readobj -h %t4.o | FileCheck %s ; RUN: llvm-nm %t4.o 2>&1 | FileCheck %s -check-prefix=NO-SYMBOLS ; NO-SYMBOLS: no symbols +; Check that this also works without the --plugin-opt= prefix. +; RUN: rm -f %t4.o +; RUN: ld.lld -thinlto-index-only -lto-obj-path=%t4.o -shared %t1.o %t2.o -o /dev/null +; RUN: llvm-readobj -h %t4.o | FileCheck %s + ; CHECK: Format: ELF64-x86-64 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/lld/test/ELF/lto/thinlto-object-suffix-replace.ll b/lld/test/ELF/lto/thinlto-object-suffix-replace.ll index 1749f816cd15..0593e574b724 100644 --- a/lld/test/ELF/lto/thinlto-object-suffix-replace.ll +++ b/lld/test/ELF/lto/thinlto-object-suffix-replace.ll @@ -21,6 +21,11 @@ ; RUN: --plugin-opt=thinlto-object-suffix-replace=".thinlink.bc;.o" \ ; RUN: -shared %t1.thinlink.bc -o %t3 ; RUN: diff %t1.o.thinlto.bc.orig %t1.o.thinlto.bc +; Also check that this works without the --plugin-opt= prefix. +; RUN: ld.lld -thinlto-index-only \ +; RUN: -thinlto-object-suffix-replace=".thinlink.bc;.o" \ +; RUN: -shared %t1.thinlink.bc -o %t3 +; RUN: diff %t1.o.thinlto.bc.orig %t1.o.thinlto.bc ; Ensure lld generates error if object suffix replace option does not have 'old;new' format ; RUN: rm -f %t1.o.thinlto.bc diff --git a/lld/test/ELF/lto/thinlto-prefix-replace.ll b/lld/test/ELF/lto/thinlto-prefix-replace.ll index 67b11c74abf6..2aa8e105ad3b 100644 --- a/lld/test/ELF/lto/thinlto-prefix-replace.ll +++ b/lld/test/ELF/lto/thinlto-prefix-replace.ll @@ -9,6 +9,11 @@ ; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-prefix-replace="%t/oldpath/;%t/newpath/" -shared %t/oldpath/thinlto_prefix_replace.o -o %t/thinlto_prefix_replace ; RUN: ls %t/newpath/thinlto_prefix_replace.o.thinlto.bc +; Check that this also works without the --plugin-opt= prefix. +; RUN: rm -f %t/newpath/thinlto_prefix_replace.o.thinlto.bc +; RUN: ld.lld -thinlto-index-only -thinlto-prefix-replace="%t/oldpath/;%t/newpath/" -shared %t/oldpath/thinlto_prefix_replace.o -o %t/thinlto_prefix_replace +; RUN: ls %t/newpath/thinlto_prefix_replace.o.thinlto.bc + ; Ensure that lld generates error if prefix replace option does not have 'old;new' format ; RUN: rm -f %t/newpath/thinlto_prefix_replace.o.thinlto.bc ; RUN: not ld.lld --plugin-opt=thinlto-index-only --plugin-opt=thinlto-prefix-replace=abc:def -shared %t/oldpath/thinlto_prefix_replace.o -o %t/thinlto_prefix_replace 2>&1 | FileCheck %s --check-prefix=ERR