diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 963501db118e7..44b1a83c5c17c 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVAsmBackend.h" +#include "RISCVFixupKinds.h" #include "RISCVMCExpr.h" #include "llvm/ADT/APInt.h" #include "llvm/MC/MCAsmInfo.h" @@ -611,6 +612,46 @@ bool RISCVAsmBackend::evaluateTargetFixup(const MCFixup &Fixup, isPCRelFixupResolved(AUIPCTarget.getAddSym(), *AUIPCDF); } +void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F, + const MCFixup &Fixup) { + StringRef VendorIdentifier; + switch (Fixup.getTargetKind()) { + default: + // No Vendor Relocation Required. + return; + case RISCV::fixup_riscv_qc_e_branch: + case RISCV::fixup_riscv_qc_abs20_u: + case RISCV::fixup_riscv_qc_e_32: + case RISCV::fixup_riscv_qc_e_jump_plt: + VendorIdentifier = "QUALCOMM"; + break; + } + + // Create a local symbol for the vendor relocation to reference. It's fine if + // the symbol has the same name as an existing symbol. + MCContext &Ctx = Asm->getContext(); + MCSymbol *VendorSymbol = Ctx.createLocalSymbol(VendorIdentifier); + auto [It, Inserted] = + VendorSymbols.try_emplace(VendorIdentifier, VendorSymbol); + + if (Inserted) { + // Setup the just-created symbol + VendorSymbol->setVariableValue(MCConstantExpr::create(0, Ctx)); + Asm->registerSymbol(*VendorSymbol); + } else { + // Fetch the existing symbol + VendorSymbol = It->getValue(); + } + + MCFixup VendorFixup = + MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_VENDOR); + // Explicitly create MCValue rather than using an MCExpr and evaluating it so + // that the absolute vendor symbol is not evaluated to constant 0. + MCValue VendorTarget = MCValue::get(VendorSymbol); + uint64_t VendorValue; + Asm->getWriter().recordRelocation(F, VendorFixup, VendorTarget, VendorValue); +} + bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup, const MCValue &Target, uint64_t &FixedValue, bool IsResolved) { @@ -660,7 +701,14 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup, if (IsResolved && (getFixupKindInfo(Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel)) IsResolved = isPCRelFixupResolved(Target.getAddSym(), F); - IsResolved = MCAsmBackend::addReloc(F, Fixup, Target, FixedValue, IsResolved); + + if (!IsResolved) { + // Some Fixups require a vendor relocation, record it (directly) before we + // add the relocation. + maybeAddVendorReloc(F, Fixup); + + Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue); + } if (Fixup.isLinkerRelaxable()) { auto FA = MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 4dffbb82e07c7..91efd44547509 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -12,6 +12,7 @@ #include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVFixupKinds.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/StringMap.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -31,6 +32,8 @@ class RISCVAsmBackend : public MCAsmBackend { bool isPCRelFixupResolved(const MCSymbol *SymA, const MCFragment &F); + StringMap VendorSymbols; + public: RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit, const MCTargetOptions &Options); @@ -50,6 +53,8 @@ class RISCVAsmBackend : public MCAsmBackend { bool addReloc(const MCFragment &, const MCFixup &, const MCValue &, uint64_t &FixedValue, bool IsResolved) override; + void maybeAddVendorReloc(const MCFragment &, const MCFixup &); + void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, MutableArrayRef Data, uint64_t Value, bool IsResolved) override; diff --git a/llvm/test/MC/RISCV/vendor-symbol.s b/llvm/test/MC/RISCV/vendor-symbol.s new file mode 100644 index 0000000000000..7df3a3efeb64e --- /dev/null +++ b/llvm/test/MC/RISCV/vendor-symbol.s @@ -0,0 +1,35 @@ +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \ +# RUN: -filetype=obj -o - \ +# RUN: | llvm-readelf -sr - \ +# RUN: | FileCheck %s + + +## This checks that the vendor identifier symbols required for vendor +## relocations do not interfere with symbols with identical names that +## are written in assembly. + + .option exact + + qc.e.bgeui s0, 20, QUALCOMM + + .global QUALCOMM +QUALCOMM: + nop + + qc.e.bgeui s0, 20, QUALCOMM + + +# CHECK-LABEL: Relocation section '.rela.text' +## Note the different values for the "Sym. Value" Field +# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0 +# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0 +# CHECK: R_RISCV_VENDOR 00000000 QUALCOMM + 0 +# CHECK: R_RISCV_CUSTOM193 00000006 QUALCOMM + 0 + + +# CHECK-LABEL: Symbol table '.symtab' +# CHECK-NOT: QUALCOMM +# CHECK: 00000000 0 NOTYPE LOCAL DEFAULT ABS QUALCOMM +# CHECK-NOT: QUALCOMM +# CHECK: 00000006 0 NOTYPE GLOBAL DEFAULT 2 QUALCOMM +# CHECK-NOT: QUALCOMM diff --git a/llvm/test/MC/RISCV/xqcibi-relocations.s b/llvm/test/MC/RISCV/xqcibi-relocations.s index 054a890a4b5e5..dff0b2b53c31b 100644 --- a/llvm/test/MC/RISCV/xqcibi-relocations.s +++ b/llvm/test/MC/RISCV/xqcibi-relocations.s @@ -1,38 +1,83 @@ -# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s -show-encoding \ -# RUN: | FileCheck -check-prefix=INSTR %s -# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi %s -o %t.o -# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \ +# RUN: | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \ +# RUN: -filetype=obj -o - \ +# RUN: | llvm-objdump -dr --mattr=+experimental-xqcibi - \ +# RUN: | FileCheck -check-prefix=OBJ %s -# Check prefixes: -# RELOC - Check the relocation in the object. -# INSTR - Check the instruction is handled properly by the ASMPrinter. +## This test checks that we emit the right relocations for Xqcibi +## relative branches. These can be resolved within the same section +## (when relaxations are disabled) but otherwise require a relocation. +## The QC.E.BI instructions also require a vendor relocation. -.text +# This is required so that the conditional branches requiring relocations +# are not converted into inverted branches with long jumps by the assembler. +.option exact -# Since foo is undefined, this will be relaxed to (qc.beqi + jal) -qc.bnei x6, 10, foo -# RELOC: R_RISCV_JAL foo 0x0 -# INSTR: qc.bnei t1, 10, foo +# ASM-LABEL: this_section: +# OBJ-LABEL: : +this_section: -# Since foo is undefined, this will be relaxed to (qc.e.bltui + jal) -qc.e.bgeui x8, 12, foo -# RELOC: R_RISCV_JAL foo 0x0 -# INSTR: qc.e.bgeui s0, 12, foo +# ASM: qc.bnei t1, 10, undef +# OBJ: qc.bnei t1, 0xa, 0x0 +# OBJ-NEXT: R_RISCV_BRANCH undef{{$}} +qc.bnei t1, 10, undef -# Check that a label in a different section is handled similar to an undefined -# symbol and gets relaxed to (qc.e.bgeui + jal) -qc.e.bltui x4, 9, .bar -# RELOC: R_RISCV_JAL .bar 0x0 -# INSTR: qc.e.bltui tp, 9, .bar +# ASM: qc.e.bgeui s0, 20, undef +# OBJ-NEXT: qc.e.bgeui s0, 0x14, 0x4 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM193 undef{{$}} +qc.e.bgeui s0, 20, undef -# Check that branches to a defined symbol are handled correctly -qc.e.beqi x7, 8, .L1 -# INSTR: qc.e.beqi t2, 8, .L1 -.L1: - ret +# ASM: qc.bnei t2, 11, same_section +# OBJ-NEXT: qc.bnei t2, 0xb, 0x28 +qc.bnei t2, 11, same_section -.section .t2 +# ASM: qc.e.bgeui s1, 21, same_section +# OBJ-NEXT: qc.e.bgeui s1, 0x15, 0x28 +qc.e.bgeui s1, 21, same_section -.bar: - ret + +# ASM: qc.bnei t2, 12, same_section_extern +# OBJ-NEXT: qc.bnei t2, 0xc, 0x14 +# OBJ-NEXT: R_RISCV_BRANCH same_section_extern{{$}} +qc.bnei t2, 12, same_section_extern + +# ASM: qc.e.bgeui s1, 22, same_section_extern +# OBJ-NEXT: qc.e.bgeui s1, 0x16, 0x18 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM193 same_section_extern{{$}} +qc.e.bgeui s1, 22, same_section_extern + + +# ASM: qc.bnei t3, 13, other_section +# OBJ-NEXT: qc.bnei t3, 0xd, 0x1e +# OBJ-NEXT: R_RISCV_BRANCH other_section{{$}} +qc.bnei t3, 13, other_section + +# ASM: qc.e.bgeui s2, 23, other_section +# OBJ-NEXT: qc.e.bgeui s2, 0x17, 0x22 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM193 other_section{{$}} +qc.e.bgeui s2, 23, other_section + + +# ASM-LABEL: same_section: +# OBJ-LABEL: : +same_section: + nop + +# ASM-LABEL: same_section_extern: +# OBJ-LABEL: : + .global same_section_extern +same_section_extern: + nop + + +.section .text.second, "ax", @progbits + +# ASM-LABEL: other_section: +# OBJ-LABEL: : +other_section: + nop diff --git a/llvm/test/MC/RISCV/xqcilb-relocations.s b/llvm/test/MC/RISCV/xqcilb-relocations.s index 0a5b788a110da..ced7f4fd99f5f 100644 --- a/llvm/test/MC/RISCV/xqcilb-relocations.s +++ b/llvm/test/MC/RISCV/xqcilb-relocations.s @@ -1,46 +1,84 @@ -# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcilb %s -show-encoding \ -# RUN: | FileCheck -check-prefix=INSTR %s -# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilb %s -o %t.o -# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcilb %s \ +# RUN: | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcilb %s \ +# RUN: -filetype=obj -o - \ +# RUN: | llvm-objdump -dr --mattr=+experimental-xqcilb - \ +# RUN: | FileCheck -check-prefix=OBJ %s -# Check prefixes: -# RELOC - Check the relocation in the object. -# INSTR - Check the instruction is handled properly by the ASMPrinter. - -.text +## This test checks that we emit the right relocations for Xqcilb +## relative jumps. These can be resolved within the same section +## (when relaxations are disabled) but otherwise require a +## vendor-specific relocation pair. +# This is required so that the conditional jumps are not compressed +# by the assembler .option exact -qc.e.j foo -# RELOC: R_RISCV_CUSTOM195 foo 0x0 -# INSTR: qc.e.j foo +# ASM-LABEL: this_section: +# OBJ-LABEL: : +this_section: + +# ASM: qc.e.j undef +# OBJ: qc.e.j 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 undef{{$}} +qc.e.j undef + +# ASM: qc.e.jal undef +# OBJ-NEXT: qc.e.jal 0x6 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 undef{{$}} +qc.e.jal undef + + +# ASM: qc.e.j same_section +# OBJ-NEXT: qc.e.j 0x30 +qc.e.j same_section + +# ASM: qc.e.jal same_section +# OBJ-NEXT: qc.e.jal 0x30 +qc.e.jal same_section + +# ASM: qc.e.j same_section_extern +# OBJ-NEXT: qc.e.j 0x18 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 same_section_extern{{$}} +qc.e.j same_section_extern -qc.e.jal foo -# RELOC: R_RISCV_CUSTOM195 foo 0x0 -# INSTR: qc.e.jal foo +# ASM: qc.e.jal same_section_extern +# OBJ-NEXT: qc.e.jal 0x1e +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 same_section_extern{{$}} +qc.e.jal same_section_extern -# Check that a label in a different section is handled similar to an undefined symbol -qc.e.j .bar -# RELOC: R_RISCV_CUSTOM195 .bar 0x0 -# INSTR: qc.e.j .bar -qc.e.jal .bar -# RELOC: R_RISCV_CUSTOM195 .bar 0x0 -# INSTR: qc.e.jal .bar +# ASM: qc.e.j other_section +# OBJ-NEXT: qc.e.j 0x24 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 other_section{{$}} +qc.e.j other_section -# Check that jumps to a defined symbol are handled correctly -qc.e.j .L1 -# INSTR:qc.e.j .L1 +# ASM: qc.e.jal other_section +# OBJ-NEXT: qc.e.jal 0x2a +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM195 other_section{{$}} +qc.e.jal other_section -qc.e.jal .L1 -# INSTR:qc.e.jal .L1 -.option noexact +# ASM-LABEL: same_section: +# OBJ-LABEL: : +same_section: + nop -.L1: - ret +# ASM-LABEL: same_section_extern: +# OBJ-LABEL: : + .global same_section_extern +same_section_extern: + nop -.section .t2 +.section .text.other, "ax", @progbits -.bar: - ret +# ASM-LABEL: other_section: +# OBJ-LABEL: : +other_section: + nop diff --git a/llvm/test/MC/RISCV/xqcili-relocations.s b/llvm/test/MC/RISCV/xqcili-relocations.s index 9c709e68334cd..ccedd42654a10 100644 --- a/llvm/test/MC/RISCV/xqcili-relocations.s +++ b/llvm/test/MC/RISCV/xqcili-relocations.s @@ -1,46 +1,78 @@ -# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcili %s -show-encoding \ -# RUN: | FileCheck -check-prefix=INSTR %s -# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcili %s -o %t.o -# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOC %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcili %s \ +# RUN: | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcili %s \ +# RUN: -filetype=obj -o - \ +# RUN: | llvm-objdump -dr --mattr=+experimental-xqcili - \ +# RUN: | FileCheck -check-prefix=OBJ %s -# Check prefixes: -# RELOC - Check the relocation in the object. -# INSTR - Check the instruction is handled properly by the ASMPrinter. - -.text +## This test checks that we emit the right relocations for Xqcili +## immediates. These always require a relocation pair, unless the +## target is absolute. +# This is required so that the conditional branches requiring relocations +# are not converted into inverted branches with long jumps by the assembler. .option exact -qc.li x4, %qc.abs20(foo) -# RELOC: R_RISCV_CUSTOM192 foo 0x0 -# INSTR: qc.li tp, %qc.abs20(foo) +.set abs_symbol, 0x0 + +# ASM-LABEL: this_section: +# OBJ-LABEL: : +this_section: + +# ASM: qc.li a0, %qc.abs20(undef) +# OBJ: qc.li a0, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM192 undef{{$}} +qc.li a0, %qc.abs20(undef) + +# ASM: qc.e.li s0, undef +# OBJ-NEXT: qc.e.li s0, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM194 undef{{$}} +qc.e.li s0, undef + + +# ASM: qc.li a1, %qc.abs20(0) +# OBJ-NEXT: qc.li a1, 0x0 +qc.li a1, %qc.abs20(abs_symbol) -qc.e.li x5, foo -# RELOC: R_RISCV_CUSTOM194 foo 0x0 -# INSTR: qc.e.li t0, foo +# ASM: qc.e.li s1, 0 +# OBJ-NEXT: qc.e.li s1, 0x0 +qc.e.li s1, abs_symbol -# Check that a label in a different section is handled similar to an undefined symbol -qc.li x9, %qc.abs20(.bar) -# RELOC: R_RISCV_CUSTOM192 .bar 0x0 -# INSTR: qc.li s1, %qc.abs20(.bar) -qc.e.li x8, .bar -# RELOC: R_RISCV_CUSTOM194 .bar 0x0 -# INSTR: qc.e.li s0, .bar +# ASM: qc.li a2, %qc.abs20(same_section) +# OBJ-NEXT: qc.li a2, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM192 same_section{{$}} +qc.li a2, %qc.abs20(same_section) -# Check that branches to a defined symbol are handled correctly -qc.li x7, %qc.abs20(.L1) -# INSTR: qc.li t2, %qc.abs20(.L1) +# ASM: qc.e.li s2, same_section +# OBJ-NEXT: qc.e.li s2, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM194 same_section{{$}} +qc.e.li s2, same_section -qc.e.li x6, .L1 -# INSTR: qc.e.li t1, .L1 +# ASM: qc.li a3, %qc.abs20(other_section) +# OBJ-NEXT: qc.li a3, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM192 other_section{{$}} +qc.li a3, %qc.abs20(other_section) -.option noexact +# ASM: qc.e.li s3, other_section +# OBJ-NEXT: qc.e.li s3, 0x0 +# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}} +# OBJ-NEXT: R_RISCV_CUSTOM194 other_section{{$}} +qc.e.li s3, other_section -.L1: - ret +# ASM-LABEL: same_section: +# OBJ-LABEL: : +same_section: + nop -.section .t2 +.section .text.other, "ax", @progbits -.bar: - ret +# ASM-LABEL: other_section: +# OBJ-LABEL: : +other_section: + nop