diff options
| author | Roger Ferrer Ibanez <rofirrim@gmail.com> | 2018-08-09 07:08:20 +0000 |
|---|---|---|
| committer | Roger Ferrer Ibanez <rofirrim@gmail.com> | 2018-08-09 07:08:20 +0000 |
| commit | 577a97e2b9177fb48a01bde79e2f9af260fa4653 (patch) | |
| tree | a7ba23f8d35e677587591c9782096250a5040e87 /llvm/lib/Target/RISCV | |
| parent | 7164b7d3472611c04bc2d52b99d9ea7718fce62e (diff) | |
| download | bcm5719-llvm-577a97e2b9177fb48a01bde79e2f9af260fa4653.tar.gz bcm5719-llvm-577a97e2b9177fb48a01bde79e2f9af260fa4653.zip | |
[RISCV] Add "lla" pseudo-instruction to assembler
This pseudo-instruction is similar to la but uses PC-relative addressing
unconditionally. This is, la is only different to lla when using -fPIC. This
pseudo-instruction seems often forgotten in several specs but it is definitely
mentioned in binutils opcodes/riscv-opc.c. The semantics are defined both in
page 37 of the "RISC-V Reader" book but also in function macro found in
gas/config/tc-riscv.c.
This is a very first step towards adding PIC support for Linux in the RISC-V
backend.
The lla pseudo-instruction expands to a sequence of auipc + addi with a couple
of pc-rel relocations where the second points to the first one. This is
described in
https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#pc-relative-symbol-addresses
For now, this patch only introduces support of that pseudo instruction at the
assembler parser.
Differential Revision: https://reviews.llvm.org/D49661
llvm-svn: 339314
Diffstat (limited to 'llvm/lib/Target/RISCV')
| -rw-r--r-- | llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 67 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfo.td | 5 |
2 files changed, 69 insertions, 3 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 9a455c10548..5a56ddf0656 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -73,6 +73,9 @@ class RISCVAsmParser : public MCTargetAsmParser { // synthesize the desired immedate value into the destination register. void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out); + // Helper to emit pseudo instruction "lla" used in PC-rel addressing. + void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + /// Helper for processing MC instructions that have been successfully matched /// by MatchAndEmitInstruction. Modifications to the emitted instructions, /// like the expansion of pseudo instructions (e.g., "li"), can be performed @@ -964,6 +967,26 @@ bool RISCVAsmParser::parseOperand(OperandVector &Operands, return true; } +/// Return true if the operand at the OperandIdx for opcode Name should be +/// 'forced' to be parsed as an immediate. This is required for +/// pseudoinstructions such as tail or call, which allow bare symbols to be used +/// that could clash with register names. +static bool shouldForceImediateOperand(StringRef Name, unsigned OperandIdx) { + // FIXME: This may not scale so perhaps we want to use a data-driven approach + // instead. + switch (OperandIdx) { + case 0: + // call imm + // tail imm + return Name == "tail" || Name == "call"; + case 1: + // lla rdest, imm + return Name == "lla"; + default: + return false; + } +} + bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -975,18 +998,20 @@ bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, return false; // Parse first operand - bool ForceImmediate = (Name == "call" || Name == "tail"); - if (parseOperand(Operands, ForceImmediate)) + if (parseOperand(Operands, shouldForceImediateOperand(Name, 0))) return true; // Parse until end of statement, consuming commas between operands + unsigned OperandIdx = 1; while (getLexer().is(AsmToken::Comma)) { // Consume comma token getLexer().Lex(); // Parse next operand - if (parseOperand(Operands, false)) + if (parseOperand(Operands, shouldForceImediateOperand(Name, OperandIdx))) return true; + + ++OperandIdx; } if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -1184,6 +1209,39 @@ void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value, .addImm(Lo12)); } +void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out) { + // The local load address pseudo-instruction "lla" is used in PC-relative + // addressing of symbols: + // lla rdest, symbol + // expands to + // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) + // ADDI rdest, %pcrel_lo(TmpLabel) + MCContext &Ctx = getContext(); + + MCSymbol *TmpLabel = Ctx.createTempSymbol( + "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false); + Out.EmitLabel(TmpLabel); + + MCOperand DestReg = Inst.getOperand(0); + const RISCVMCExpr *Symbol = RISCVMCExpr::create( + Inst.getOperand(1).getExpr(), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx); + + MCInst &AUIPC = + MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol); + emitToStreamer(Out, AUIPC); + + const MCExpr *RefToLinkTmpLabel = + RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx), + RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx); + + MCInst &ADDI = MCInstBuilder(RISCV::ADDI) + .addOperand(DestReg) + .addOperand(DestReg) + .addExpr(RefToLinkTmpLabel); + emitToStreamer(Out, ADDI); +} + bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out) { Inst.setLoc(IDLoc); @@ -1198,6 +1256,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Imm = SignExtend64<32>(Imm); emitLoadImm(Reg, Imm, Out); return false; + } else if (Inst.getOpcode() == RISCV::PseudoLLA) { + emitLoadLocalAddress(Inst, IDLoc, Out); + return false; } emitToStreamer(Out, Inst); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index dd19e31d7ca..1dc60737a16 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -759,6 +759,11 @@ def : Pat<(Tail (iPTR tglobaladdr:$dst)), def : Pat<(Tail (iPTR texternalsym:$dst)), (PseudoTAIL texternalsym:$dst)>; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, + isAsmParserOnly = 1 in +def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], + "lla", "$dst, $src">; + /// Loads multiclass LdPat<PatFrag LoadOp, RVInst Inst> { |

