Skip to content

Commit df04e31

Browse files
lenarysvs-quic
andcommitted
[RISCV] Vendor Relocations for Xqci extension
This patch implements vendor relocation support for RISC-V, starting with the Xqci extensions. This is done by re-organising `RISCVAsmBackend::evaluateTargetFixup`, to also handle emitting the vendor relocation when the fixup is unresolved. An extra parameter `bool RecordReloc` is added to `evaluateTargetFixup`, so that the relocation is only emitted when it should be, as `evaluateTargetFixup` works the same way. This adds tests showing resolveable and unresolvable symbols for the xqci fixups (some of which are absolute and some of which are pc-relative), including tests when relaxation is enabled which forces relocations that might otherwise not be needed. Co-authored-by: Sudharsan Veeravalli <[email protected]>
1 parent 4e01a07 commit df04e31

File tree

10 files changed

+472
-137
lines changed

10 files changed

+472
-137
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ class MCAsmBackend {
111111

112112
virtual bool evaluateTargetFixup(const MCAssembler &Asm, const MCFixup &Fixup,
113113
const MCFragment *DF, const MCValue &Target,
114-
const MCSubtargetInfo *STI,
115-
uint64_t &Value) {
114+
const MCSubtargetInfo *STI, uint64_t &Value,
115+
bool RecordReloc) {
116116
llvm_unreachable("Need to implement hook if target has custom fixups");
117117
}
118118

llvm/lib/MC/MCAssembler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
158158
bool IsResolved = false;
159159
unsigned FixupFlags = getBackend().getFixupKindInfo(Fixup.getKind()).Flags;
160160
if (FixupFlags & MCFixupKindInfo::FKF_IsTarget) {
161-
IsResolved =
162-
getBackend().evaluateTargetFixup(*this, Fixup, DF, Target, STI, Value);
161+
IsResolved = getBackend().evaluateTargetFixup(*this, Fixup, DF, Target, STI,
162+
Value, RecordReloc);
163163
} else {
164164
const MCSymbol *Add = Target.getAddSym();
165165
const MCSymbol *Sub = Target.getSubSym();

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 135 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "RISCVAsmBackend.h"
10+
#include "RISCVFixupKinds.h"
1011
#include "RISCVMCExpr.h"
1112
#include "llvm/ADT/APInt.h"
1213
#include "llvm/MC/MCAsmInfo.h"
@@ -37,7 +38,7 @@ static cl::opt<bool> ULEB128Reloc(
3738
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
3839
bool Is64Bit, const MCTargetOptions &Options)
3940
: MCAsmBackend(llvm::endianness::little, ELF::R_RISCV_RELAX), STI(STI),
40-
OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
41+
OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options), VendorSymbols() {
4142
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
4243
}
4344

@@ -84,10 +85,12 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
8485
{"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
8586
{"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
8687

87-
{"fixup_riscv_qc_e_branch", 0, 48, MCFixupKindInfo::FKF_IsPCRel},
88-
{"fixup_riscv_qc_e_32", 16, 32, 0},
89-
{"fixup_riscv_qc_abs20_u", 12, 20, 0},
90-
{"fixup_riscv_qc_e_jump_plt", 0, 48, MCFixupKindInfo::FKF_IsPCRel},
88+
{"fixup_riscv_qc_e_branch", 0, 48,
89+
MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
90+
{"fixup_riscv_qc_e_32", 16, 32, MCFixupKindInfo::FKF_IsTarget},
91+
{"fixup_riscv_qc_abs20_u", 12, 20, MCFixupKindInfo::FKF_IsTarget},
92+
{"fixup_riscv_qc_e_jump_plt", 0, 48,
93+
MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
9194
};
9295
static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
9396
"Not all fixup kinds added to Infos array");
@@ -571,37 +574,10 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
571574
}
572575
}
573576

574-
bool RISCVAsmBackend::evaluateTargetFixup(
575-
const MCAssembler &Asm, const MCFixup &Fixup, const MCFragment *DF,
576-
const MCValue &Target, const MCSubtargetInfo *STI, uint64_t &Value) {
577-
const MCFixup *AUIPCFixup;
578-
const MCFragment *AUIPCDF;
579-
MCValue AUIPCTarget;
580-
switch (Fixup.getTargetKind()) {
581-
default:
582-
llvm_unreachable("Unexpected fixup kind!");
583-
case RISCV::fixup_riscv_pcrel_hi20:
584-
AUIPCFixup = &Fixup;
585-
AUIPCDF = DF;
586-
AUIPCTarget = Target;
587-
break;
588-
case RISCV::fixup_riscv_pcrel_lo12_i:
589-
case RISCV::fixup_riscv_pcrel_lo12_s: {
590-
AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);
591-
if (!AUIPCFixup) {
592-
Asm.getContext().reportError(Fixup.getLoc(),
593-
"could not find corresponding %pcrel_hi");
594-
return true;
595-
}
596-
597-
// MCAssembler::evaluateFixup will emit an error for this case when it sees
598-
// the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
599-
const MCExpr *AUIPCExpr = AUIPCFixup->getValue();
600-
if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Asm))
601-
return true;
602-
break;
603-
}
604-
}
577+
static bool evaluateAUIPCFixup(const MCAssembler &Asm,
578+
const MCFixup *AUIPCFixup,
579+
const MCFragment *AUIPCDF, MCValue AUIPCTarget,
580+
uint64_t &Value) {
605581

606582
if (!AUIPCTarget.getAddSym())
607583
return false;
@@ -622,6 +598,129 @@ bool RISCVAsmBackend::evaluateTargetFixup(
622598
return AUIPCFixup->getTargetKind() == RISCV::fixup_riscv_pcrel_hi20;
623599
}
624600

601+
StringRef
602+
RISCVAsmBackend::getVendorSymbolNameForRelocation(unsigned FixupKind) const {
603+
switch (FixupKind) {
604+
case RISCV::fixup_riscv_qc_e_branch:
605+
case RISCV::fixup_riscv_qc_abs20_u:
606+
case RISCV::fixup_riscv_qc_e_32:
607+
case RISCV::fixup_riscv_qc_e_jump_plt:
608+
return "QUALCOMM";
609+
}
610+
611+
return "";
612+
}
613+
614+
bool RISCVAsmBackend::evaluateVendorFixup(const MCAssembler &Asm,
615+
const MCFixup &Fixup,
616+
const MCFragment *DF,
617+
const MCValue &Target,
618+
const MCSubtargetInfo *STI,
619+
uint64_t &Value, bool RecordReloc) {
620+
// This is a copy of the target-independent branch of
621+
// MCAssembler::evaluateFixup
622+
bool IsResolved = false;
623+
const MCSymbol *Add = Target.getAddSym();
624+
const MCSymbol *Sub = Target.getSubSym();
625+
Value = Target.getConstant();
626+
if (Add && Add->isDefined())
627+
Value += Asm.getSymbolOffset(*Add);
628+
if (Sub && Sub->isDefined())
629+
Value -= Asm.getSymbolOffset(*Sub);
630+
631+
unsigned FixupFlags = getFixupKindInfo(Fixup.getKind()).Flags;
632+
if (FixupFlags & MCFixupKindInfo::FKF_IsPCRel) {
633+
Value -= Asm.getFragmentOffset(*DF) + Fixup.getOffset();
634+
635+
if (Add && !Sub && !Add->isUndefined() && !Add->isAbsolute()) {
636+
IsResolved = Asm.getWriter().isSymbolRefDifferenceFullyResolvedImpl(
637+
Asm, *Add, *DF, false, true);
638+
}
639+
} else {
640+
IsResolved = Target.isAbsolute();
641+
}
642+
// End copy of MCAssembler::evaluateFixup
643+
644+
// If we failed to resolve, or we need to force relocations (relaxations), then
645+
// record a vendor relocation too.
646+
if ((!IsResolved || shouldForceRelocation(Asm, Fixup, Target, STI)) &&
647+
RecordReloc) {
648+
// Here are the additions to emit a vendor relocation for fixups that need
649+
// them.
650+
MCContext &Ctx = Asm.getContext();
651+
652+
StringRef VendorIdentifier =
653+
getVendorSymbolNameForRelocation(Fixup.getTargetKind());
654+
655+
auto It = VendorSymbols.find(VendorIdentifier);
656+
if (It == VendorSymbols.end()) {
657+
auto *VendorSymbol =
658+
cast<MCSymbolELF>(Ctx.createLocalSymbol(VendorIdentifier));
659+
660+
// Vendor Symbols are Absolute, Local, NOTYPE.
661+
VendorSymbol->setType(ELF::STT_NOTYPE);
662+
VendorSymbol->setBinding(ELF::STB_LOCAL);
663+
VendorSymbol->setVariableValue(MCConstantExpr::create(0, Ctx));
664+
const_cast<MCAssembler &>(Asm).registerSymbol(*VendorSymbol);
665+
666+
It = VendorSymbols.try_emplace(VendorIdentifier, VendorSymbol).first;
667+
}
668+
669+
MCSymbolELF *VendorSymbol = It->getValue();
670+
const MCExpr *VendorExpr = MCSymbolRefExpr::create(VendorSymbol, Ctx);
671+
MCFixup VendorFixup =
672+
MCFixup::create(Fixup.getOffset(), VendorExpr,
673+
FirstLiteralRelocationKind + ELF::R_RISCV_VENDOR);
674+
// Explicitly create MCValue so that the absolute symbol is not evaluated to
675+
// a constant.
676+
MCValue VendorTarget = MCValue::get(VendorSymbol);
677+
uint64_t VendorValue;
678+
Asm.getWriter().recordRelocation(const_cast<MCAssembler &>(Asm), DF,
679+
VendorFixup, VendorTarget, VendorValue);
680+
}
681+
682+
return IsResolved;
683+
}
684+
685+
bool RISCVAsmBackend::evaluateTargetFixup(const MCAssembler &Asm,
686+
const MCFixup &Fixup,
687+
const MCFragment *DF,
688+
const MCValue &Target,
689+
const MCSubtargetInfo *STI,
690+
uint64_t &Value, bool RecordReloc) {
691+
switch (Fixup.getTargetKind()) {
692+
case RISCV::fixup_riscv_pcrel_hi20:
693+
return evaluateAUIPCFixup(Asm, &Fixup, DF, Target, Value);
694+
case RISCV::fixup_riscv_pcrel_lo12_i:
695+
case RISCV::fixup_riscv_pcrel_lo12_s: {
696+
const MCFragment *AUIPCDF;
697+
const MCFixup *AUIPCFixup =
698+
cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);
699+
if (!AUIPCFixup) {
700+
Asm.getContext().reportError(Fixup.getLoc(),
701+
"could not find corresponding %pcrel_hi");
702+
return true;
703+
}
704+
705+
// MCAssembler::evaluateFixup will emit an error for this case when it sees
706+
// the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
707+
const MCExpr *AUIPCExpr = AUIPCFixup->getValue();
708+
MCValue AUIPCTarget;
709+
if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Asm))
710+
return true;
711+
712+
return evaluateAUIPCFixup(Asm, AUIPCFixup, AUIPCDF, AUIPCTarget, Value);
713+
}
714+
case RISCV::fixup_riscv_qc_e_branch:
715+
case RISCV::fixup_riscv_qc_abs20_u:
716+
case RISCV::fixup_riscv_qc_e_32:
717+
case RISCV::fixup_riscv_qc_e_jump_plt:
718+
return evaluateVendorFixup(Asm, Fixup, DF, Target, STI, Value, RecordReloc);
719+
}
720+
721+
llvm_unreachable("Unexpected target fixup kind!");
722+
}
723+
625724
bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
626725
const MCFragment &F,
627726
const MCFixup &Fixup,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "MCTargetDesc/RISCVBaseInfo.h"
1313
#include "MCTargetDesc/RISCVFixupKinds.h"
1414
#include "MCTargetDesc/RISCVMCTargetDesc.h"
15+
#include "llvm/ADT/StringMap.h"
1516
#include "llvm/MC/MCAsmBackend.h"
1617
#include "llvm/MC/MCFixupKindInfo.h"
1718
#include "llvm/MC/MCSubtargetInfo.h"
@@ -20,6 +21,7 @@ namespace llvm {
2021
class MCAssembler;
2122
class MCObjectTargetWriter;
2223
class raw_ostream;
24+
class MCSymbolELF;
2325

2426
class RISCVAsmBackend : public MCAsmBackend {
2527
const MCSubtargetInfo &STI;
@@ -28,6 +30,8 @@ class RISCVAsmBackend : public MCAsmBackend {
2830
bool ForceRelocs = false;
2931
const MCTargetOptions &TargetOptions;
3032

33+
StringMap<MCSymbolELF *> VendorSymbols;
34+
3135
public:
3236
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
3337
const MCTargetOptions &Options);
@@ -45,8 +49,15 @@ class RISCVAsmBackend : public MCAsmBackend {
4549

4650
bool evaluateTargetFixup(const MCAssembler &Asm, const MCFixup &Fixup,
4751
const MCFragment *DF, const MCValue &Target,
48-
const MCSubtargetInfo *STI,
49-
uint64_t &Value) override;
52+
const MCSubtargetInfo *STI, uint64_t &Value,
53+
bool RecordReloc) override;
54+
55+
bool evaluateVendorFixup(const MCAssembler &Asm, const MCFixup &Fixup,
56+
const MCFragment *DF, const MCValue &Target,
57+
const MCSubtargetInfo *STI, uint64_t &Value,
58+
bool RecordReloc);
59+
60+
StringRef getVendorSymbolNameForRelocation(unsigned TargetFixupKind) const;
5061

5162
bool handleAddSubRelocations(const MCAssembler &Asm, const MCFragment &F,
5263
const MCFixup &Fixup, const MCValue &Target,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \
2+
# RUN: | FileCheck -check-prefix=ASM %s
3+
# RUN: llvm-mc -triple riscv32 -mattr=+experimental-xqcibi %s \
4+
# RUN: -filetype=obj -o - \
5+
# RUN: | llvm-objdump -dr --mattr=+experimental-xqcibi - \
6+
# RUN: | FileCheck -check-prefix=OBJ %s
7+
8+
## This test checks that we emit the right relocations for Xqcibi
9+
## relative branches, when relaxations are enabled. These require a relocation.
10+
## The QC.E.B<op>I instructions also require a vendor relocation.
11+
12+
# These are required to turn off autocompression, but to re-enable
13+
# linker relaxation.
14+
.option exact
15+
.option relax
16+
17+
# ASM-LABEL: this_section:
18+
# OBJ-LABEL: <this_section>:
19+
this_section:
20+
21+
# ASM: qc.bnei t2, 11, same_section
22+
# OBJ: qc.bnei t2, 0xb, 0x0 <this_section>
23+
# OBJ-NEXT: R_RISCV_BRANCH same_section{{$}}
24+
# OBJ-NOT: R_RISCV
25+
qc.bnei t2, 11, same_section
26+
27+
# ASM: qc.e.bgeui s1, 21, same_section
28+
# OBJ: qc.e.bgeui s1, 0x15, 0x4 <this_section+0x4>
29+
# OBJ-NEXT: R_RISCV_VENDOR QUALCOMM{{$}}
30+
# OBJ-NEXT: R_RISCV_CUSTOM193 same_section{{$}}
31+
# OBJ-NOT: R_RISCV
32+
qc.e.bgeui s1, 21, same_section
33+
34+
# ASM-LABEL: same_section:
35+
# OBJ-LABEL: <same_section>:
36+
same_section:
37+
nop
38+

0 commit comments

Comments
 (0)