[llvm] r364403 - [RISCV] Add pseudo instruction for calls with explicit register

Lewis Revill via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 26 03:35:59 PDT 2019


Author: lewis-revill
Date: Wed Jun 26 03:35:58 2019
New Revision: 364403

URL: http://llvm.org/viewvc/llvm-project?rev=364403&view=rev
Log:
[RISCV] Add pseudo instruction for calls with explicit register

This patch adds the PseudoCALLReg instruction which allows using an
explicit register operand as the destination for the return address.

GCC can successfully parse this form of the call instruction, which
would be used for calls to functions which do not use ra as the return
address register, such as the __riscv_save libcalls. This patch forms
the first part of an implementation of -msave-restore for RISC-V.

Differential Revision: https://reviews.llvm.org/D62685



Modified:
    llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/trunk/test/MC/RISCV/function-call-invalid.s
    llvm/trunk/test/MC/RISCV/function-call.s

Modified: llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp Wed Jun 26 03:35:58 2019
@@ -1219,6 +1219,10 @@ OperandMatchResultTy RISCVAsmParser::par
   if (getLexer().getKind() != AsmToken::Identifier)
     return MatchOperand_NoMatch;
 
+  // Avoid parsing the register in `call rd, foo` as a call symbol.
+  if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
+    return MatchOperand_NoMatch;
+
   StringRef Identifier;
   if (getParser().parseIdentifier(Identifier))
     return MatchOperand_ParseFail;

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp Wed Jun 26 03:35:58 2019
@@ -88,19 +88,29 @@ MCCodeEmitter *llvm::createRISCVMCCodeEm
   return new RISCVMCCodeEmitter(Ctx, MCII);
 }
 
-// Expand PseudoCALL and PseudoTAIL to AUIPC and JALR with relocation types.
-// We expand PseudoCALL and PseudoTAIL while encoding, meaning AUIPC and JALR
-// won't go through RISCV MC to MC compressed instruction transformation. This
-// is acceptable because AUIPC has no 16-bit form and C_JALR have no immediate
-// operand field.  We let linker relaxation deal with it. When linker
-// relaxation enabled, AUIPC and JALR have chance relax to JAL. If C extension
-// is enabled, JAL has chance relax to C_JAL.
+// Expand PseudoCALL(Reg) and PseudoTAIL to AUIPC and JALR with relocation
+// types. We expand PseudoCALL(Reg) and PseudoTAIL while encoding, meaning AUIPC
+// and JALR won't go through RISCV MC to MC compressed instruction
+// transformation. This is acceptable because AUIPC has no 16-bit form and
+// C_JALR have no immediate operand field.  We let linker relaxation deal with
+// it. When linker relaxation enabled, AUIPC and JALR have chance relax to JAL.
+// If C extension is enabled, JAL has chance relax to C_JAL.
 void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS,
                                             SmallVectorImpl<MCFixup> &Fixups,
                                             const MCSubtargetInfo &STI) const {
   MCInst TmpInst;
-  MCOperand Func = MI.getOperand(0);
-  unsigned Ra = (MI.getOpcode() == RISCV::PseudoTAIL) ? RISCV::X6 : RISCV::X1;
+  MCOperand Func;
+  unsigned Ra;
+  if (MI.getOpcode() == RISCV::PseudoTAIL) {
+    Func = MI.getOperand(0);
+    Ra = RISCV::X6;
+  } else if (MI.getOpcode() == RISCV::PseudoCALLReg) {
+    Func = MI.getOperand(1);
+    Ra = MI.getOperand(0).getReg();
+  } else {
+    Func = MI.getOperand(0);
+    Ra = RISCV::X1;
+  }
   uint32_t Binary;
 
   assert(Func.isExpr() && "Expected expression");
@@ -118,7 +128,7 @@ void RISCVMCCodeEmitter::expandFunctionC
     // Emit JALR X0, X6, 0
     TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);
   else
-    // Emit JALR X1, X1, 0
+    // Emit JALR Ra, Ra, 0
     TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);
   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
   support::endian::write(OS, Binary, support::little);
@@ -169,7 +179,8 @@ void RISCVMCCodeEmitter::encodeInstructi
   // Get byte count of instruction.
   unsigned Size = Desc.getSize();
 
-  if (MI.getOpcode() == RISCV::PseudoCALL ||
+  if (MI.getOpcode() == RISCV::PseudoCALLReg ||
+      MI.getOpcode() == RISCV::PseudoCALL ||
       MI.getOpcode() == RISCV::PseudoTAIL) {
     expandFunctionCall(MI, OS, Fixups, STI);
     MCNumEmitted += 2;

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp Wed Jun 26 03:35:58 2019
@@ -436,6 +436,7 @@ unsigned RISCVInstrInfo::getInstSizeInBy
   case TargetOpcode::KILL:
   case TargetOpcode::DBG_VALUE:
     return 0;
+  case RISCV::PseudoCALLReg:
   case RISCV::PseudoCALL:
   case RISCV::PseudoTAIL:
   case RISCV::PseudoLLA:

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Wed Jun 26 03:35:58 2019
@@ -870,6 +870,17 @@ def : Pat<(brind GPR:$rs1), (PseudoBRIND
 def : Pat<(brind (add GPR:$rs1, simm12:$imm12)),
           (PseudoBRIND GPR:$rs1, simm12:$imm12)>;
 
+// PsuedoCALLReg is a generic pseudo instruction for calls which will eventually
+// expand to auipc and jalr while encoding, with any given register used as the
+// destination.
+// Define AsmString to print "call" when compile with -S flag.
+// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
+let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0,
+    mayStore = 0, mayLoad = 0 in
+def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> {
+  let AsmString = "call\t$rd, $func";
+}
+
 // PseudoCALL is a pseudo instruction which will eventually expand to auipc
 // and jalr while encoding. This is desirable, as an auipc+jalr pair with
 // R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker

Modified: llvm/trunk/test/MC/RISCV/function-call-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/function-call-invalid.s?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/function-call-invalid.s (original)
+++ llvm/trunk/test/MC/RISCV/function-call-invalid.s Wed Jun 26 03:35:58 2019
@@ -9,3 +9,4 @@ call %hi(1234) # CHECK: :[[@LINE]]:6: er
 call %lo(1234) # CHECK: :[[@LINE]]:6: error: operand must be a bare symbol name
 call %hi(foo) # CHECK: :[[@LINE]]:6: error: operand must be a bare symbol name
 call %lo(foo) # CHECK: :[[@LINE]]:6: error: operand must be a bare symbol name
+call foo, bar # CHECK: :[[@LINE]]:6: error: operand must be a bare symbol name

Modified: llvm/trunk/test/MC/RISCV/function-call.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/function-call.s?rev=364403&r1=364402&r2=364403&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/function-call.s (original)
+++ llvm/trunk/test/MC/RISCV/function-call.s Wed Jun 26 03:35:58 2019
@@ -51,3 +51,17 @@ call foo at plt
 # INSTR: auipc ra, 0
 # INSTR: jalr  ra
 # FIXUP: fixup A - offset: 0, value: foo at plt, kind: fixup_riscv_call_plt
+
+# Ensure that an explicit register operand can be parsed.
+
+call a0, foo
+# RELOC: R_RISCV_CALL foo 0x0
+# INSTR: auipc a0, 0
+# INSTR: jalr  a0
+# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_call
+
+call a0, foo at plt
+# RELOC: R_RISCV_CALL_PLT foo 0x0
+# INSTR: auipc a0, 0
+# INSTR: jalr  a0
+# FIXUP: fixup A - offset: 0, value: foo at plt, kind: fixup_riscv_call_plt




More information about the llvm-commits mailing list