21
21
#include " llvm/MC/MCExpr.h"
22
22
#include " llvm/MC/MCInst.h"
23
23
#include " llvm/MC/MCInstBuilder.h"
24
+ #include " llvm/MC/MCObjectFileInfo.h"
24
25
#include " llvm/MC/MCParser/MCAsmLexer.h"
25
26
#include " llvm/MC/MCParser/MCParsedAsmOperand.h"
26
27
#include " llvm/MC/MCParser/MCTargetAsmParser.h"
@@ -79,9 +80,18 @@ class RISCVAsmParser : public MCTargetAsmParser {
79
80
// synthesize the desired immedate value into the destination register.
80
81
void emitLoadImm (unsigned DestReg, int64_t Value, MCStreamer &Out);
81
82
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
+
82
89
// Helper to emit pseudo instruction "lla" used in PC-rel addressing.
83
90
void emitLoadLocalAddress (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
84
91
92
+ // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
93
+ void emitLoadAddress (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
94
+
85
95
// / Helper for processing MC instructions that have been successfully matched
86
96
// / by MatchAndEmitInstruction. Modifications to the emitted instructions,
87
97
// / like the expansion of pseudo instructions (e.g., "li"), can be performed
@@ -505,10 +515,12 @@ struct RISCVOperand : public MCParsedAsmOperand {
505
515
bool IsConstantImm = evaluateConstantImm (getImm (), Imm, VK);
506
516
if (!IsConstantImm) {
507
517
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);
509
520
} else {
510
521
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);
512
524
}
513
525
}
514
526
@@ -861,8 +873,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
861
873
case Match_InvalidUImm20AUIPC:
862
874
return generateImmOutOfRangeError (
863
875
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" );
866
878
case Match_InvalidSImm21Lsb0JAL:
867
879
return generateImmOutOfRangeError (
868
880
Operands, ErrorInfo, -(1 << 20 ), (1 << 20 ) - 2 ,
@@ -1408,42 +1420,82 @@ void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1408
1420
}
1409
1421
}
1410
1422
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)
1419
1431
MCContext &Ctx = getContext ();
1420
1432
1421
1433
MCSymbol *TmpLabel = Ctx.createTempSymbol (
1422
1434
" pcrel_hi" , /* AlwaysAddSuffix */ true , /* CanBeUnnamed */ false );
1423
1435
Out.EmitLabel (TmpLabel);
1424
1436
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);
1429
1438
emitToStreamer (
1430
- Out, MCInstBuilder (RISCV::AUIPC).addOperand (DestReg ).addExpr (Symbol ));
1439
+ Out, MCInstBuilder (RISCV::AUIPC).addOperand (TmpReg ).addExpr (SymbolHi ));
1431
1440
1432
1441
const MCExpr *RefToLinkTmpLabel =
1433
1442
RISCVMCExpr::create (MCSymbolRefExpr::create (TmpLabel, Ctx),
1434
1443
RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
1435
1444
1436
- emitToStreamer (Out, MCInstBuilder (RISCV::ADDI)
1437
- .addOperand (DestReg)
1445
+ emitToStreamer (Out, MCInstBuilder (SecondOpcode)
1438
1446
.addOperand (DestReg)
1447
+ .addOperand (TmpReg)
1439
1448
.addExpr (RefToLinkTmpLabel));
1440
1449
}
1441
1450
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
+
1442
1491
bool RISCVAsmParser::processInstruction (MCInst &Inst, SMLoc IDLoc,
1443
1492
MCStreamer &Out) {
1444
1493
Inst.setLoc (IDLoc);
1445
1494
1446
- if (Inst.getOpcode () == RISCV::PseudoLI) {
1495
+ switch (Inst.getOpcode ()) {
1496
+ default :
1497
+ break ;
1498
+ case RISCV::PseudoLI: {
1447
1499
unsigned Reg = Inst.getOperand (0 ).getReg ();
1448
1500
const MCOperand &Op1 = Inst.getOperand (1 );
1449
1501
if (Op1.isExpr ()) {
@@ -1463,9 +1515,13 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1463
1515
Imm = SignExtend64<32 >(Imm);
1464
1516
emitLoadImm (Reg, Imm, Out);
1465
1517
return false ;
1466
- } else if (Inst.getOpcode () == RISCV::PseudoLLA) {
1518
+ }
1519
+ case RISCV::PseudoLLA:
1467
1520
emitLoadLocalAddress (Inst, IDLoc, Out);
1468
1521
return false ;
1522
+ case RISCV::PseudoLA:
1523
+ emitLoadAddress (Inst, IDLoc, Out);
1524
+ return false ;
1469
1525
}
1470
1526
1471
1527
emitToStreamer (Out, Inst);
0 commit comments