Skip to content

Commit 8538d56

Browse files
authored
Merge pull request #16 from Disasm/rv64-pic
Add support for pc-relative addressing on 64-bit RISC-V
2 parents 1bbe0b3 + 637e52c commit 8538d56

23 files changed

+561
-76
lines changed

llvm/include/llvm/CodeGen/MachineBasicBlock.h

+11
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ class MachineBasicBlock
115115
/// branch.
116116
bool AddressTaken = false;
117117

118+
/// Indicate that this basic block needs its symbol be emitted regardless of
119+
/// whether the flow just falls-through to it.
120+
bool LabelMustBeEmitted = false;
121+
118122
/// Indicate that this basic block is the entry block of an EH scope, i.e.,
119123
/// the block that used to have a catchpad or cleanuppad instruction in the
120124
/// LLVM IR.
@@ -159,6 +163,13 @@ class MachineBasicBlock
159163
/// branch.
160164
void setHasAddressTaken() { AddressTaken = true; }
161165

166+
/// Test whether this block must have its label emitted.
167+
bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; }
168+
169+
/// Set this block to reflect that, regardless how we flow to it, we need
170+
/// its label be emitted.
171+
void setLabelMustBeEmitted() { LabelMustBeEmitted = true; }
172+
162173
/// Return the MachineFunction containing this basic block.
163174
const MachineFunction *getParent() const { return xParent; }
164175
MachineFunction *getParent() { return xParent; }

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -2922,13 +2922,16 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
29222922

29232923
// Print the main label for the block.
29242924
if (MBB.pred_empty() ||
2925-
(isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
2925+
(isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() &&
2926+
!MBB.hasLabelMustBeEmitted())) {
29262927
if (isVerbose()) {
29272928
// NOTE: Want this comment at start of line, don't emit with AddComment.
29282929
OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":",
29292930
false);
29302931
}
29312932
} else {
2933+
if (isVerbose() && MBB.hasLabelMustBeEmitted())
2934+
OutStreamer->AddComment("Label of block must be emitted");
29322935
OutStreamer->EmitLabel(MBB.getSymbol());
29332936
}
29342937
}

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

+77-21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/MC/MCExpr.h"
2222
#include "llvm/MC/MCInst.h"
2323
#include "llvm/MC/MCInstBuilder.h"
24+
#include "llvm/MC/MCObjectFileInfo.h"
2425
#include "llvm/MC/MCParser/MCAsmLexer.h"
2526
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
2627
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
@@ -79,9 +80,18 @@ class RISCVAsmParser : public MCTargetAsmParser {
7980
// synthesize the desired immedate value into the destination register.
8081
void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out);
8182

83+
// Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
84+
// helpers such as emitLoadLocalAddress and emitLoadAddress.
85+
void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
86+
const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
87+
unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
88+
8289
// Helper to emit pseudo instruction "lla" used in PC-rel addressing.
8390
void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
8491

92+
// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
93+
void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
94+
8595
/// Helper for processing MC instructions that have been successfully matched
8696
/// by MatchAndEmitInstruction. Modifications to the emitted instructions,
8797
/// like the expansion of pseudo instructions (e.g., "li"), can be performed
@@ -505,10 +515,12 @@ struct RISCVOperand : public MCParsedAsmOperand {
505515
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
506516
if (!IsConstantImm) {
507517
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
508-
return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
518+
return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
519+
VK == RISCVMCExpr::VK_RISCV_GOT_HI);
509520
} else {
510521
return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
511-
VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
522+
VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
523+
VK == RISCVMCExpr::VK_RISCV_GOT_HI);
512524
}
513525
}
514526

@@ -861,8 +873,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
861873
case Match_InvalidUImm20AUIPC:
862874
return generateImmOutOfRangeError(
863875
Operands, ErrorInfo, 0, (1 << 20) - 1,
864-
"operand must be a symbol with %pcrel_hi() modifier or an integer in "
865-
"the range");
876+
"operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier "
877+
"or an integer in the range");
866878
case Match_InvalidSImm21Lsb0JAL:
867879
return generateImmOutOfRangeError(
868880
Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
@@ -1408,42 +1420,82 @@ void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
14081420
}
14091421
}
14101422

1411-
void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1412-
MCStreamer &Out) {
1413-
// The local load address pseudo-instruction "lla" is used in PC-relative
1414-
// addressing of symbols:
1415-
// lla rdest, symbol
1416-
// expands to
1417-
// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1418-
// ADDI rdest, %pcrel_lo(TmpLabel)
1423+
void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
1424+
const MCExpr *Symbol,
1425+
RISCVMCExpr::VariantKind VKHi,
1426+
unsigned SecondOpcode, SMLoc IDLoc,
1427+
MCStreamer &Out) {
1428+
// A pair of instructions for PC-relative addressing; expands to
1429+
// TmpLabel: AUIPC TmpReg, VKHi(symbol)
1430+
// OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
14191431
MCContext &Ctx = getContext();
14201432

14211433
MCSymbol *TmpLabel = Ctx.createTempSymbol(
14221434
"pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
14231435
Out.EmitLabel(TmpLabel);
14241436

1425-
MCOperand DestReg = Inst.getOperand(0);
1426-
const RISCVMCExpr *Symbol = RISCVMCExpr::create(
1427-
Inst.getOperand(1).getExpr(), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
1428-
1437+
const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
14291438
emitToStreamer(
1430-
Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol));
1439+
Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
14311440

14321441
const MCExpr *RefToLinkTmpLabel =
14331442
RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
14341443
RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
14351444

1436-
emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1437-
.addOperand(DestReg)
1445+
emitToStreamer(Out, MCInstBuilder(SecondOpcode)
14381446
.addOperand(DestReg)
1447+
.addOperand(TmpReg)
14391448
.addExpr(RefToLinkTmpLabel));
14401449
}
14411450

1451+
void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1452+
MCStreamer &Out) {
1453+
// The load local address pseudo-instruction "lla" is used in PC-relative
1454+
// addressing of local symbols:
1455+
// lla rdest, symbol
1456+
// expands to
1457+
// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1458+
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1459+
MCOperand DestReg = Inst.getOperand(0);
1460+
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1461+
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1462+
RISCV::ADDI, IDLoc, Out);
1463+
}
1464+
1465+
void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
1466+
MCStreamer &Out) {
1467+
// The load address pseudo-instruction "la" is used in PC-relative and
1468+
// GOT-indirect addressing of global symbols:
1469+
// la rdest, symbol
1470+
// expands to either (for non-PIC)
1471+
// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1472+
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1473+
// or (for PIC)
1474+
// TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
1475+
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
1476+
MCOperand DestReg = Inst.getOperand(0);
1477+
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1478+
unsigned SecondOpcode;
1479+
RISCVMCExpr::VariantKind VKHi;
1480+
// FIXME: Should check .option (no)pic when implemented
1481+
if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1482+
SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
1483+
VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
1484+
} else {
1485+
SecondOpcode = RISCV::ADDI;
1486+
VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
1487+
}
1488+
emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
1489+
}
1490+
14421491
bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
14431492
MCStreamer &Out) {
14441493
Inst.setLoc(IDLoc);
14451494

1446-
if (Inst.getOpcode() == RISCV::PseudoLI) {
1495+
switch (Inst.getOpcode()) {
1496+
default:
1497+
break;
1498+
case RISCV::PseudoLI: {
14471499
unsigned Reg = Inst.getOperand(0).getReg();
14481500
const MCOperand &Op1 = Inst.getOperand(1);
14491501
if (Op1.isExpr()) {
@@ -1463,9 +1515,13 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
14631515
Imm = SignExtend64<32>(Imm);
14641516
emitLoadImm(Reg, Imm, Out);
14651517
return false;
1466-
} else if (Inst.getOpcode() == RISCV::PseudoLLA) {
1518+
}
1519+
case RISCV::PseudoLLA:
14671520
emitLoadLocalAddress(Inst, IDLoc, Out);
14681521
return false;
1522+
case RISCV::PseudoLA:
1523+
emitLoadAddress(Inst, IDLoc, Out);
1524+
return false;
14691525
}
14701526

14711527
emitToStreamer(Out, Inst);

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

+7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
3333
switch ((unsigned)Fixup.getKind()) {
3434
default:
3535
break;
36+
case RISCV::fixup_riscv_got_hi20:
37+
return true;
3638
case RISCV::fixup_riscv_pcrel_lo12_i:
3739
case RISCV::fixup_riscv_pcrel_lo12_s:
3840
// For pcrel_lo12, force a relocation if the target of the corresponding
@@ -48,6 +50,9 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
4850
default:
4951
llvm_unreachable("Unexpected fixup kind for pcrel_lo12");
5052
break;
53+
case RISCV::fixup_riscv_got_hi20:
54+
ShouldForce = true;
55+
break;
5156
case RISCV::fixup_riscv_pcrel_hi20:
5257
ShouldForce = T->getValue()->findAssociatedFragment() !=
5358
Fixup.getValue()->findAssociatedFragment();
@@ -173,6 +178,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
173178
switch (Kind) {
174179
default:
175180
llvm_unreachable("Unknown fixup kind!");
181+
case RISCV::fixup_riscv_got_hi20:
182+
llvm_unreachable("Relocation should be unconditionally forced\n");
176183
case FK_Data_1:
177184
case FK_Data_2:
178185
case FK_Data_4:

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

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class RISCVAsmBackend : public MCAsmBackend {
8080
{ "fixup_riscv_pcrel_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
8181
{ "fixup_riscv_pcrel_lo12_i", 20, 12, MCFixupKindInfo::FKF_IsPCRel },
8282
{ "fixup_riscv_pcrel_lo12_s", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
83+
{ "fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
8384
{ "fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel },
8485
{ "fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
8586
{ "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel },

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

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
8484
return ELF::R_RISCV_PCREL_LO12_I;
8585
case RISCV::fixup_riscv_pcrel_lo12_s:
8686
return ELF::R_RISCV_PCREL_LO12_S;
87+
case RISCV::fixup_riscv_got_hi20:
88+
return ELF::R_RISCV_GOT_HI20;
8789
case RISCV::fixup_riscv_jal:
8890
return ELF::R_RISCV_JAL;
8991
case RISCV::fixup_riscv_branch:

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

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ enum Fixups {
3535
// fixup_riscv_pcrel_lo12_s - 12-bit fixup corresponding to pcrel_lo(foo) for
3636
// the S-type store instructions
3737
fixup_riscv_pcrel_lo12_s,
38+
// fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for
39+
// instructions like auipc
40+
fixup_riscv_got_hi20,
3841
// fixup_riscv_jal - 20-bit fixup for symbol references in the jal
3942
// instruction
4043
fixup_riscv_jal,

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

+3
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
235235
case RISCVMCExpr::VK_RISCV_PCREL_HI:
236236
FixupKind = RISCV::fixup_riscv_pcrel_hi20;
237237
break;
238+
case RISCVMCExpr::VK_RISCV_GOT_HI:
239+
FixupKind = RISCV::fixup_riscv_got_hi20;
240+
break;
238241
case RISCVMCExpr::VK_RISCV_CALL:
239242
FixupKind = RISCV::fixup_riscv_call;
240243
break;

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const {
6363
switch ((unsigned)F.getKind()) {
6464
default:
6565
continue;
66+
case RISCV::fixup_riscv_got_hi20:
6667
case RISCV::fixup_riscv_pcrel_hi20:
6768
return &F;
6869
}
@@ -137,6 +138,7 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
137138
case VK_RISCV_HI:
138139
case VK_RISCV_PCREL_LO:
139140
case VK_RISCV_PCREL_HI:
141+
case VK_RISCV_GOT_HI:
140142
return false;
141143
}
142144
}
@@ -154,6 +156,7 @@ RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
154156
.Case("hi", VK_RISCV_HI)
155157
.Case("pcrel_lo", VK_RISCV_PCREL_LO)
156158
.Case("pcrel_hi", VK_RISCV_PCREL_HI)
159+
.Case("got_pcrel_hi", VK_RISCV_GOT_HI)
157160
.Default(VK_RISCV_Invalid);
158161
}
159162

@@ -169,14 +172,16 @@ StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
169172
return "pcrel_lo";
170173
case VK_RISCV_PCREL_HI:
171174
return "pcrel_hi";
175+
case VK_RISCV_GOT_HI:
176+
return "got_pcrel_hi";
172177
}
173178
}
174179

175180
bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
176181
MCValue Value;
177182

178183
if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
179-
Kind == VK_RISCV_CALL)
184+
Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL)
180185
return false;
181186

182187
if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class RISCVMCExpr : public MCTargetExpr {
2929
VK_RISCV_HI,
3030
VK_RISCV_PCREL_LO,
3131
VK_RISCV_PCREL_HI,
32+
VK_RISCV_GOT_HI,
3233
VK_RISCV_CALL,
3334
VK_RISCV_Invalid
3435
};
@@ -53,11 +54,11 @@ class RISCVMCExpr : public MCTargetExpr {
5354

5455
const MCExpr *getSubExpr() const { return Expr; }
5556

56-
/// Get the MCExpr of the VK_RISCV_PCREL_HI Fixup that the
57-
/// VK_RISCV_PCREL_LO points to.
57+
/// Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO
58+
/// points to.
5859
///
5960
/// \returns nullptr if this isn't a VK_RISCV_PCREL_LO pointing to a
60-
/// VK_RISCV_PCREL_HI.
61+
/// known PC-relative HI fixup.
6162
const MCFixup *getPCRelHiFixup() const;
6263

6364
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;

0 commit comments

Comments
 (0)