2020#include  " llvm/MC/MCExpr.h" 
2121#include  " llvm/MC/MCInst.h" 
2222#include  " llvm/MC/MCInstBuilder.h" 
23+ #include  " llvm/MC/MCObjectFileInfo.h" 
2324#include  " llvm/MC/MCParser/MCAsmLexer.h" 
2425#include  " llvm/MC/MCParser/MCParsedAsmOperand.h" 
2526#include  " llvm/MC/MCParser/MCTargetAsmParser.h" 
@@ -78,9 +79,18 @@ class RISCVAsmParser : public MCTargetAsmParser {
7879  //  synthesize the desired immedate value into the destination register.
7980  void  emitLoadImm (unsigned  DestReg, int64_t  Value, MCStreamer &Out);
8081
82+   //  Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
83+   //  helpers such as emitLoadLocalAddress and emitLoadAddress.
84+   void  emitAuipcInstPair (MCOperand DestReg, MCOperand TmpReg,
85+                          const  MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
86+                          unsigned  SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
87+ 
8188  //  Helper to emit pseudo instruction "lla" used in PC-rel addressing.
8289  void  emitLoadLocalAddress (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
8390
91+   //  Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
92+   void  emitLoadAddress (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
93+ 
8494  // / Helper for processing MC instructions that have been successfully matched
8595  // / by MatchAndEmitInstruction. Modifications to the emitted instructions,
8696  // / like the expansion of pseudo instructions (e.g., "li"), can be performed
@@ -1409,42 +1419,82 @@ void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
14091419  }
14101420}
14111421
1412- void  RISCVAsmParser::emitLoadLocalAddress  (MCInst &Inst, SMLoc IDLoc ,
1413-                                           MCStreamer &Out) { 
1414-   //  The local load address pseudo-instruction "lla" is used in PC-relative 
1415-   //  addressing of symbols: 
1416-   //    lla rdest, symbol 
1417-   //  expands to
1418-   //    TmpLabel: AUIPC rdest, %pcrel_hi (symbol)
1419-   //              ADDI rdest , %pcrel_lo(TmpLabel)
1422+ void  RISCVAsmParser::emitAuipcInstPair  (MCOperand DestReg, MCOperand TmpReg ,
1423+                                        const  MCExpr *Symbol, 
1424+                                        RISCVMCExpr::VariantKind VKHi, 
1425+                                         unsigned  SecondOpcode, SMLoc IDLoc, 
1426+                                        MCStreamer &Out) { 
1427+   //  A pair of instructions for PC-relative addressing;  expands to
1428+   //    TmpLabel: AUIPC TmpReg, VKHi (symbol)
1429+   //              OP DestReg, TmpReg , %pcrel_lo(TmpLabel)
14201430  MCContext &Ctx = getContext ();
14211431
14221432  MCSymbol *TmpLabel = Ctx.createTempSymbol (
14231433      " pcrel_hi" /*  AlwaysAddSuffix */ true , /*  CanBeUnnamed */ false );
14241434  Out.EmitLabel (TmpLabel);
14251435
1426-   MCOperand DestReg = Inst.getOperand (0 );
1427-   const  RISCVMCExpr *Symbol = RISCVMCExpr::create (
1428-       Inst.getOperand (1 ).getExpr (), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
1429- 
1436+   const  RISCVMCExpr *SymbolHi = RISCVMCExpr::create (Symbol, VKHi, Ctx);
14301437  emitToStreamer (
1431-       Out, MCInstBuilder (RISCV::AUIPC).addOperand (DestReg ).addExpr (Symbol ));
1438+       Out, MCInstBuilder (RISCV::AUIPC).addOperand (TmpReg ).addExpr (SymbolHi ));
14321439
14331440  const  MCExpr *RefToLinkTmpLabel =
14341441      RISCVMCExpr::create (MCSymbolRefExpr::create (TmpLabel, Ctx),
14351442                          RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
14361443
1437-   emitToStreamer (Out, MCInstBuilder (RISCV::ADDI)
1438-                           .addOperand (DestReg)
1444+   emitToStreamer (Out, MCInstBuilder (SecondOpcode)
14391445                          .addOperand (DestReg)
1446+                           .addOperand (TmpReg)
14401447                          .addExpr (RefToLinkTmpLabel));
14411448}
14421449
1450+ void  RISCVAsmParser::emitLoadLocalAddress (MCInst &Inst, SMLoc IDLoc,
1451+                                           MCStreamer &Out) {
1452+   //  The load local address pseudo-instruction "lla" is used in PC-relative
1453+   //  addressing of local symbols:
1454+   //    lla rdest, symbol
1455+   //  expands to
1456+   //    TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1457+   //              ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1458+   MCOperand DestReg = Inst.getOperand (0 );
1459+   const  MCExpr *Symbol = Inst.getOperand (1 ).getExpr ();
1460+   emitAuipcInstPair (DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1461+                     RISCV::ADDI, IDLoc, Out);
1462+ }
1463+ 
1464+ void  RISCVAsmParser::emitLoadAddress (MCInst &Inst, SMLoc IDLoc,
1465+                                      MCStreamer &Out) {
1466+   //  The load address pseudo-instruction "la" is used in PC-relative and
1467+   //  GOT-indirect addressing of global symbols:
1468+   //    la rdest, symbol
1469+   //  expands to either (for non-PIC)
1470+   //    TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1471+   //              ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1472+   //  or (for PIC)
1473+   //    TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
1474+   //              Lx rdest, %pcrel_lo(TmpLabel)(rdest)
1475+   MCOperand DestReg = Inst.getOperand (0 );
1476+   const  MCExpr *Symbol = Inst.getOperand (1 ).getExpr ();
1477+   unsigned  SecondOpcode;
1478+   RISCVMCExpr::VariantKind VKHi;
1479+   //  FIXME: Should check .option (no)pic when implemented
1480+   if  (getContext ().getObjectFileInfo ()->isPositionIndependent ()) {
1481+     SecondOpcode = isRV64 () ? RISCV::LD : RISCV::LW;
1482+     VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
1483+   } else  {
1484+     SecondOpcode = RISCV::ADDI;
1485+     VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
1486+   }
1487+   emitAuipcInstPair (DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
1488+ }
1489+ 
14431490bool  RISCVAsmParser::processInstruction (MCInst &Inst, SMLoc IDLoc,
14441491                                        MCStreamer &Out) {
14451492  Inst.setLoc (IDLoc);
14461493
1447-   if  (Inst.getOpcode () == RISCV::PseudoLI) {
1494+   switch  (Inst.getOpcode ()) {
1495+   default :
1496+     break ;
1497+   case  RISCV::PseudoLI: {
14481498    unsigned  Reg = Inst.getOperand (0 ).getReg ();
14491499    const  MCOperand &Op1 = Inst.getOperand (1 );
14501500    if  (Op1.isExpr ()) {
@@ -1464,9 +1514,13 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
14641514      Imm = SignExtend64<32 >(Imm);
14651515    emitLoadImm (Reg, Imm, Out);
14661516    return  false ;
1467-   } else  if  (Inst.getOpcode () == RISCV::PseudoLLA) {
1517+   }
1518+   case  RISCV::PseudoLLA:
14681519    emitLoadLocalAddress (Inst, IDLoc, Out);
14691520    return  false ;
1521+   case  RISCV::PseudoLA:
1522+     emitLoadAddress (Inst, IDLoc, Out);
1523+     return  false ;
14701524  }
14711525
14721526  emitToStreamer (Out, Inst);
0 commit comments