mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Add -fbinutils-version= to gate ELF features on the specified binutils version
There are two use cases. Assembler We have accrued some code gated on MCAsmInfo::useIntegratedAssembler(). Some features are supported by latest GNU as, but we have to use MCAsmInfo::useIntegratedAs() because the newer versions have not been widely adopted (e.g. SHF_LINK_ORDER 'o' and 'unique' linkage in 2.35, --compress-debug-sections= in 2.26). Linker We want to use features supported only by LLD or very new GNU ld, or don't want to work around older GNU ld. We currently can't represent that "we don't care about old GNU ld". You can find such workarounds in a few other places, e.g. Mips/MipsAsmprinter.cpp PowerPC/PPCTOCRegDeps.cpp X86/X86MCInstrLower.cpp AArch64 TLS workaround for R_AARCH64_TLSLD_MOVW_DTPREL_* (PR ld/18276), R_AARCH64_TLSLE_LDST8_TPREL_LO12 (https://bugs.llvm.org/show_bug.cgi?id=36727 https://sourceware.org/bugzilla/show_bug.cgi?id=22969) Mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER components (supported by LLD in D84001; GNU ld feature request https://sourceware.org/bugzilla/show_bug.cgi?id=16833 may take a while before available). This feature allows to garbage collect some unused sections (e.g. fragmented .gcc_except_table). This patch adds `-fbinutils-version=` to clang and `-binutils-version` to llc. It changes one codegen place in SHF_MERGE to demonstrate its usage. `-fbinutils-version=2.35` means the produced object file does not care about GNU ld<2.35 compatibility. When `-fno-integrated-as` is specified, the produced assembly can be consumed by GNU as>=2.35, but older versions may not work. `-fbinutils-version=none` means that we can use all ELF features, regardless of GNU as/ld support. Both clang and llc need `parseBinutilsVersion`. Such command line parsing is usually implemented in `llvm/lib/CodeGen/CommandFlags.cpp` (LLVMCodeGen), however, ClangCodeGen does not depend on LLVMCodeGen. So I add `parseBinutilsVersion` to `llvm/lib/Target/TargetMachine.cpp` (LLVMTarget). Differential Revision: https://reviews.llvm.org/D85474
This commit is contained in:
parent
ef4906bd9c
commit
71834ae8ab
@ -406,6 +406,12 @@ protected:
|
||||
|
||||
//===--- Integrated Assembler Information ----------------------------===//
|
||||
|
||||
// Generated object files can use all ELF features supported by GNU ld of
|
||||
// this binutils version and later. INT_MAX means all features can be used,
|
||||
// regardless of GNU ld support. The default value is referenced by
|
||||
// clang/Driver/Options.td.
|
||||
std::pair<int, int> BinutilsVersion = {2, 26};
|
||||
|
||||
/// Should we use the integrated assembler?
|
||||
/// The integrated assembler should be enabled by default (by the
|
||||
/// constructors) when failing to parse a valid piece of assembly (inline
|
||||
@ -673,9 +679,17 @@ public:
|
||||
return InitialFrameState;
|
||||
}
|
||||
|
||||
void setBinutilsVersion(std::pair<int, int> Value) {
|
||||
BinutilsVersion = Value;
|
||||
}
|
||||
|
||||
/// Return true if assembly (inline or otherwise) should be parsed.
|
||||
bool useIntegratedAssembler() const { return UseIntegratedAssembler; }
|
||||
|
||||
bool binutilsIsAtLeast(int Major, int Minor) const {
|
||||
return BinutilsVersion >= std::make_pair(Major, Minor);
|
||||
}
|
||||
|
||||
/// Set whether assembly (inline or otherwise) should be parsed.
|
||||
virtual void setUseIntegratedAssembler(bool Value) {
|
||||
UseIntegratedAssembler = Value;
|
||||
|
@ -376,6 +376,8 @@ public:
|
||||
/// The integer bit size to use for SjLj based exception handling.
|
||||
static constexpr unsigned DefaultSjLjDataSize = 32;
|
||||
virtual unsigned getSjLjDataSize() const { return DefaultSjLjDataSize; }
|
||||
|
||||
static std::pair<int, int> parseBinutilsVersion(StringRef Version);
|
||||
};
|
||||
|
||||
/// This class describes a target machine that is implemented with the LLVM
|
||||
|
@ -146,6 +146,10 @@ namespace llvm {
|
||||
/// optimization should be disabled for the given machine function.
|
||||
bool DisableFramePointerElim(const MachineFunction &MF) const;
|
||||
|
||||
/// If greater than 0, override the default value of
|
||||
/// MCAsmInfo::BinutilsVersion.
|
||||
std::pair<int, int> BinutilsVersion{0, 0};
|
||||
|
||||
/// UnsafeFPMath - This flag is enabled when the
|
||||
/// -enable-unsafe-fp-math flag is specified on the command line. When
|
||||
/// this flag is off (the default), the code generator is not allowed to
|
||||
|
@ -61,6 +61,9 @@ void LLVMTargetMachine::initAsmInfo() {
|
||||
"Make sure you include the correct TargetSelect.h"
|
||||
"and that InitializeAllTargetMCs() is being invoked!");
|
||||
|
||||
if (Options.BinutilsVersion.first > 0)
|
||||
TmpAsmInfo->setBinutilsVersion(Options.BinutilsVersion);
|
||||
|
||||
if (Options.DisableIntegratedAS)
|
||||
TmpAsmInfo->setUseIntegratedAssembler(false);
|
||||
|
||||
|
@ -685,7 +685,8 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
|
||||
UniqueID = NextUniqueID++;
|
||||
Flags |= ELF::SHF_LINK_ORDER;
|
||||
} else {
|
||||
if (getContext().getAsmInfo()->useIntegratedAssembler()) {
|
||||
if (getContext().getAsmInfo()->useIntegratedAssembler() ||
|
||||
getContext().getAsmInfo()->binutilsIsAtLeast(2, 35)) {
|
||||
// Symbols must be placed into sections with compatible entry
|
||||
// sizes. Generate unique sections for symbols that have not
|
||||
// been assigned to compatible sections.
|
||||
@ -736,8 +737,9 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
|
||||
assert(Section->getLinkedToSymbol() == LinkedToSym &&
|
||||
"Associated symbol mismatch between sections");
|
||||
|
||||
if (!getContext().getAsmInfo()->useIntegratedAssembler()) {
|
||||
// If we are not using the integrated assembler then this symbol might have
|
||||
if (!(getContext().getAsmInfo()->useIntegratedAssembler() ||
|
||||
getContext().getAsmInfo()->binutilsIsAtLeast(2, 35))) {
|
||||
// If we are using GNU as before 2.35, then this symbol might have
|
||||
// been placed in an incompatible mergeable section. Emit an error if this
|
||||
// is the case to avoid creating broken output.
|
||||
if ((Section->getFlags() & ELF::SHF_MERGE) &&
|
||||
|
@ -233,3 +233,12 @@ TargetIRAnalysis TargetMachine::getTargetIRAnalysis() {
|
||||
return TargetIRAnalysis(
|
||||
[this](const Function &F) { return this->getTargetTransformInfo(F); });
|
||||
}
|
||||
|
||||
std::pair<int, int> TargetMachine::parseBinutilsVersion(StringRef Version) {
|
||||
if (Version == "none")
|
||||
return {INT_MAX, INT_MAX}; // Make binutilsIsAtLeast() return true.
|
||||
std::pair<int, int> Ret;
|
||||
if (!Version.consumeInteger(10, Ret.first) && Version.consume_front("."))
|
||||
Version.consumeInteger(10, Ret.second);
|
||||
return Ret;
|
||||
}
|
||||
|
@ -282,15 +282,21 @@ module asm ".section .asm_nonmergeable2,\22a\22,@progbits"
|
||||
;; --no-integrated-as avoids the use of ",unique," for compatibility with older binutils.
|
||||
|
||||
;; Error if an incompatible symbol is explicitly placed into a mergeable section.
|
||||
; RUN: not llc < %s -mtriple=x86_64 --no-integrated-as 2>&1 \
|
||||
; RUN: not llc < %s -mtriple=x86_64 --no-integrated-as -binutils-version=2.34 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=NO-I-AS-ERR
|
||||
; NO-I-AS-ERR: error: Symbol 'explicit_default_1' from module '<stdin>' required a section with entry-size=0 but was placed in section '.rodata.cst16' with entry-size=16: Explicit assignment by pragma or attribute of an incompatible symbol to this section?
|
||||
; NO-I-AS-ERR: error: Symbol 'explicit_default_4' from module '<stdin>' required a section with entry-size=0 but was placed in section '.debug_str' with entry-size=1: Explicit assignment by pragma or attribute of an incompatible symbol to this section?
|
||||
; NO-I-AS-ERR: error: Symbol 'explicit_implicit_2' from module '<stdin>' required a section with entry-size=0 but was placed in section '.rodata.str1.1' with entry-size=1: Explicit assignment by pragma or attribute of an incompatible symbol to this section?
|
||||
; NO-I-AS-ERR: error: Symbol 'explicit_implicit_4' from module '<stdin>' required a section with entry-size=0 but was placed in section '.rodata.str1.1' with entry-size=1: Explicit assignment by pragma or attribute of an incompatible symbol to this section?
|
||||
|
||||
;; For GNU as before 2.35,
|
||||
;; Don't create mergeable sections for globals with an explicit section name.
|
||||
; RUN: echo '@explicit = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit"' > %t.no_i_as.ll
|
||||
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=NO-I-AS
|
||||
; NO-I-AS: .section .explicit,"a",@progbits
|
||||
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.34 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=NO-I-AS-OLD
|
||||
; NO-I-AS-OLD: .section .explicit,"a",@progbits
|
||||
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=2.35 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=NO-I-AS-NEW
|
||||
; RUN: llc < %t.no_i_as.ll -mtriple=x86_64 --no-integrated-as -binutils-version=none 2>&1 \
|
||||
; RUN: | FileCheck %s --check-prefix=NO-I-AS-NEW
|
||||
; NO-I-AS-NEW: .section .explicit,"aM",@progbits,4,unique,1
|
||||
|
13
test/tools/llc/binutils-version.ll
Normal file
13
test/tools/llc/binutils-version.ll
Normal file
@ -0,0 +1,13 @@
|
||||
;; Test valid and invalid -binutils-version values.
|
||||
; RUN: llc %s -filetype=null -binutils-version=none
|
||||
; RUN: llc %s -filetype=null -binutils-version=2
|
||||
; RUN: llc %s -filetype=null -binutils-version=2.35
|
||||
|
||||
;; Disallow -binutils-version=0 because we use $major==0 to indicate the MC
|
||||
;; default.
|
||||
; RUN: not llc %s -filetype=null -binutils-version=0 2>&1 | FileCheck %s --check-prefix=ERR
|
||||
; RUN: not llc %s -filetype=null -binutils-version=nan 2>&1 | FileCheck %s --check-prefix=ERR
|
||||
; RUN: not llc %s -filetype=null -binutils-version=2. 2>&1 | FileCheck %s --check-prefix=ERR
|
||||
; RUN: not llc %s -filetype=null -binutils-version=3.-14 2>&1 | FileCheck %s --check-prefix=ERR
|
||||
|
||||
; ERR: error: invalid -binutils-version, accepting 'none' or major.minor
|
@ -82,6 +82,15 @@ TimeCompilations("time-compilations", cl::Hidden, cl::init(1u),
|
||||
cl::value_desc("N"),
|
||||
cl::desc("Repeat compilation N times for timing"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
BinutilsVersion("binutils-version", cl::Hidden,
|
||||
cl::desc("Produced object files can use all ELF features "
|
||||
"supported by this binutils version and newer."
|
||||
"If -no-integrated-as is specified, the generated "
|
||||
"assembly will consider GNU as support."
|
||||
"'none' means that all ELF features can be used, "
|
||||
"regardless of binutils support"));
|
||||
|
||||
static cl::opt<bool>
|
||||
NoIntegratedAssembler("no-integrated-as", cl::Hidden,
|
||||
cl::desc("Disable integrated assembler"));
|
||||
@ -427,9 +436,24 @@ static int compileModule(char **argv, LLVMContext &Context) {
|
||||
case '3': OLvl = CodeGenOpt::Aggressive; break;
|
||||
}
|
||||
|
||||
// Parse 'none' or '$major.$minor'. Disallow -binutils-version=0 because we
|
||||
// use that to indicate the MC default.
|
||||
if (!BinutilsVersion.empty() && BinutilsVersion != "none") {
|
||||
StringRef V = BinutilsVersion.getValue();
|
||||
unsigned Num;
|
||||
if (V.consumeInteger(10, Num) || Num == 0 ||
|
||||
!(V.empty() ||
|
||||
(V.consume_front(".") && !V.consumeInteger(10, Num) && V.empty()))) {
|
||||
WithColor::error(errs(), argv[0])
|
||||
<< "invalid -binutils-version, accepting 'none' or major.minor\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
TargetOptions Options;
|
||||
auto InitializeOptions = [&](const Triple &TheTriple) {
|
||||
Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
|
||||
Options.BinutilsVersion =
|
||||
TargetMachine::parseBinutilsVersion(BinutilsVersion);
|
||||
Options.DisableIntegratedAS = NoIntegratedAssembler;
|
||||
Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
|
||||
Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory;
|
||||
|
Loading…
x
Reference in New Issue
Block a user