Skip to content

Commit

Permalink
[ELF] Add convenience TableGen classes to enforce two dashes for opti…
Browse files Browse the repository at this point in the history
…ons not supported by GNU ld

Announced on https://lists.llvm.org/pipermail/llvm-dev/2020-May/141416.html

For many options, we have to support either one or two dash to be
compatible with GNU ld. For newer and lld specific options, we can enforce strict double dashes.

Affected options:

* --thinlto-*
* --lto-*
* --shuffle-sections=

This patch does not change `-plugin-opt=*` because clang driver passes
`-plugin-opt=*` and I don't intend to cause churn.

In 2000, GNU ld tried something similar with --omagic
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=e4897a3288f37d5f69e8acd256a6e83e607fe8d8

Reviewed By: tejohnson, psmith

Differential Revision: https://reviews.llvm.org/D79371
  • Loading branch information
MaskRay committed May 8, 2020
1 parent 9782892 commit e20a215
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 38 deletions.
61 changes: 37 additions & 24 deletions lld/ELF/Options.td
@@ -1,5 +1,18 @@
include "llvm/Option/OptParser.td"

// Convenience classes for long options which only accept two dashes. For lld
// specific or newer long options, we prefer two dashes to avoid collision with
// short options. For many others, we have to accept both forms to be compatible
// with GNU ld.
class FF<string name> : Flag<["--"], name>;
class JJ<string name>: Joined<["--"], name>;

multiclass EEq<string name, string help> {
def NAME: Separate<["--"], name>;
def NAME # _eq: Joined<["--"], name # "=">, Alias<!cast<Separate>(NAME)>,
HelpText<help>;
}

// For options whose names are multiple letters, either one dash or
// two can precede the option name except those that start with 'o'.
class F<string name>: Flag<["--", "-"], name>;
Expand Down Expand Up @@ -265,7 +278,7 @@ def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
HelpText<"Specify the binary format for the output object file">;

def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">,
def omagic: FF<"omagic">, MetaVarName<"<magic>">,
HelpText<"Set the text and data sections to be readable and writable, do not page align sections, link against static libraries">;

defm orphan_handling:
Expand Down Expand Up @@ -484,57 +497,57 @@ def: JoinedOrSeparate<["-"], "u">, Alias<undefined>, HelpText<"Alias for --undef
def: Flag<["-"], "V">, Alias<version>, HelpText<"Alias for --version">;

// LTO-related options.
def lto_aa_pipeline: J<"lto-aa-pipeline=">,
def lto_aa_pipeline: JJ<"lto-aa-pipeline=">,
HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
def lto_debug_pass_manager: F<"lto-debug-pass-manager">,
def lto_debug_pass_manager: FF<"lto-debug-pass-manager">,
HelpText<"Debug new pass manager">;
def lto_emit_asm: F<"lto-emit-asm">,
def lto_emit_asm: FF<"lto-emit-asm">,
HelpText<"Emit assembly code">;
def lto_new_pass_manager: F<"lto-new-pass-manager">,
def lto_new_pass_manager: FF<"lto-new-pass-manager">,
HelpText<"Use new pass manager">;
def lto_newpm_passes: J<"lto-newpm-passes=">,
def lto_newpm_passes: JJ<"lto-newpm-passes=">,
HelpText<"Passes to run during LTO">;
def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
def lto_O: JJ<"lto-O">, MetaVarName<"<opt-level>">,
HelpText<"Optimization level for LTO">;
def lto_partitions: J<"lto-partitions=">,
def lto_partitions: JJ<"lto-partitions=">,
HelpText<"Number of LTO codegen partitions">;
def lto_cs_profile_generate: F<"lto-cs-profile-generate">,
def lto_cs_profile_generate: FF<"lto-cs-profile-generate">,
HelpText<"Perform context sensitive PGO instrumentation">;
def lto_cs_profile_file: J<"lto-cs-profile-file=">,
def lto_cs_profile_file: JJ<"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=">,
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: F<"lto-whole-program-visibility">,
def lto_whole_program_visibility: FF<"lto-whole-program-visibility">,
HelpText<"Asserts that the LTO link has whole program visibility">;
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">,
HelpText<"YAML output file for optimization remarks">;
def opt_remarks_passes: Separate<["--"], "opt-remarks-passes">,
HelpText<"Regex for the passes that need to be serialized to the output file">;
def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">,
def opt_remarks_with_hotness: FF<"opt-remarks-with-hotness">,
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)">;
def save_temps: F<"save-temps">;
def lto_basicblock_sections: J<"lto-basicblock-sections=">,
def lto_basicblock_sections: JJ<"lto-basicblock-sections=">,
HelpText<"Enable basic block sections for LTO">;
defm lto_unique_bb_section_names: B<"lto-unique-bb-section-names",
"Give unique names to every basic block section for LTO",
"Do not give unique names to every basic block section for LTO (default)">;
def shuffle_sections: J<"shuffle-sections=">, MetaVarName<"<seed>">,
def shuffle_sections: JJ<"shuffle-sections=">, MetaVarName<"<seed>">,
HelpText<"Shuffle input sections using the given seed. If 0, use a random seed">;
def thinlto_cache_dir: J<"thinlto-cache-dir=">,
def thinlto_cache_dir: JJ<"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=">,
defm thinlto_cache_policy: EEq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">;
def thinlto_emit_imports_files: FF<"thinlto-emit-imports-files">;
def thinlto_index_only: FF<"thinlto-index-only">;
def thinlto_index_only_eq: JJ<"thinlto-index-only=">;
def thinlto_jobs: JJ<"thinlto-jobs=">,
HelpText<"Number of ThinLTO jobs. Default to --threads=">;
def thinlto_object_suffix_replace_eq: J<"thinlto-object-suffix-replace=">;
def thinlto_prefix_replace_eq: J<"thinlto-prefix-replace=">;
def thinlto_object_suffix_replace_eq: JJ<"thinlto-object-suffix-replace=">;
def thinlto_prefix_replace_eq: JJ<"thinlto-prefix-replace=">;

def: J<"plugin-opt=O">, Alias<lto_O>, HelpText<"Alias for --lto-O">;
def: F<"plugin-opt=debug-pass-manager">,
Expand Down
6 changes: 6 additions & 0 deletions lld/docs/ReleaseNotes.rst
Expand Up @@ -26,6 +26,12 @@ ELF Improvements

* ...

Breaking changes
----------------

* One-dash form of some long option (``--thinlto-*``, ``--lto-*``, ``--shuffle-sections=``)
are no longer supported.

COFF Improvements
-----------------

Expand Down
12 changes: 6 additions & 6 deletions lld/test/ELF/lto/devirt_vcall_vis_public.ll
@@ -1,23 +1,23 @@
; REQUIRES: x86
; Test that -lto-whole-program-visibility enables devirtualization.
; Test that --lto-whole-program-visibility enables devirtualization.

; Index based WPD
; Generate unsplit module with summary for ThinLTO index-based WPD.
; RUN: opt -thinlto-bc -o %t2.o %s
; RUN: ld.lld %t2.o -o %t3 -save-temps -lto-whole-program-visibility \
; RUN: opt --thinlto-bc -o %t2.o %s
; 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

; Hybrid WPD
; Generate split module with summary for hybrid Thin/Regular LTO WPD.
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s
; RUN: ld.lld %t.o -o %t3 -save-temps -lto-whole-program-visibility \
; RUN: opt --thinlto-bc --thinlto-split-lto-unit -o %t.o %s
; RUN: ld.lld %t.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 %t.o.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR

; Regular LTO WPD
; RUN: opt -o %t4.o %s
; RUN: ld.lld %t4.o -o %t3 -save-temps -lto-whole-program-visibility \
; RUN: ld.lld %t4.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 %t3.0.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR

Expand Down
4 changes: 2 additions & 2 deletions lld/test/ELF/lto/thinlto-emit-imports.ll
Expand Up @@ -43,10 +43,10 @@
; RUN: not ls %t2.o.imports
; RUN: not ls %t3.o.imports

; Check that imports files are generated also when -thinlto-index-only
; 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: 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

Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/thinlto-index-file.ll
Expand Up @@ -13,7 +13,7 @@
; 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: 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"
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/thinlto-obj-path.ll
Expand Up @@ -11,7 +11,7 @@

; 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: 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

;; Ensure lld emits empty combined module if specific obj-path.
Expand Down
6 changes: 3 additions & 3 deletions lld/test/ELF/lto/thinlto-object-suffix-replace.ll
Expand Up @@ -5,7 +5,7 @@

; Generate bitcode file with summary, as well as a minimized bitcode without
; the debug metadata for the thin link.
; RUN: opt -thinlto-bc %s -thin-link-bitcode-file=%t1.thinlink.bc -o %t1.o
; RUN: opt --thinlto-bc %s -thin-link-bitcode-file=%t1.thinlink.bc -o %t1.o

; First perform the thin link on the normal bitcode file, and save the
; resulting index.
Expand All @@ -22,8 +22,8 @@
; 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: 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

Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/thinlto-prefix-replace.ll
Expand Up @@ -11,7 +11,7 @@

; 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: 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
Expand Down

0 comments on commit e20a215

Please sign in to comment.