From 415b5e48b6309dafb28b4855007e9c63dbd0b79e Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Mon, 1 Apr 2019 14:53:17 +0000 Subject: [PATCH] [RISCV] Attach VK_RISCV_CALL to symbols upon creation This patch replaces the addition of VK_RISCV_CALL in RISCVMCCodeEmitter by creating the RISCVMCExpr when tail/call are parsed, or in the codegen case when the callee symbols are created. This required adding a new CallSymbol operand to allow only adding VK_RISCV_CALL to tail/call instructions. This patch will allow further expansion of parsing and codegen to easily include PLT symbols which must generate the R_RISCV_CALL_PLT relocation. Differential Revision: https://reviews.llvm.org/D55560 Patch by Lewis Revill. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357396 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 34 +++++++++++++++++++ .../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 6 +--- lib/Target/RISCV/RISCVISelLowering.cpp | 6 ++-- lib/Target/RISCV/RISCVInstrInfo.td | 16 +++++++-- lib/Target/RISCV/RISCVMCInstLower.cpp | 3 ++ lib/Target/RISCV/Utils/RISCVBaseInfo.h | 1 + 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index ae7b648460b..b054a3d518d 100644 --- a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -113,6 +113,7 @@ class RISCVAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); OperandMatchResultTy parseBareSymbol(OperandVector &Operands); + OperandMatchResultTy parseCallSymbol(OperandVector &Operands); OperandMatchResultTy parseJALOffset(OperandVector &Operands); bool parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -283,6 +284,16 @@ public: VK == RISCVMCExpr::VK_RISCV_None; } + bool isCallSymbol() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK; + // Must be of 'immediate' type but not a constant. + if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) + return false; + return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && + VK == RISCVMCExpr::VK_RISCV_CALL; + } + bool isCSRSystemRegister() const { return isSystemRegister(); } /// Return true if the operand is a valid for the fence instruction e.g. @@ -904,6 +915,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "operand must be a bare symbol name"); } + case Match_InvalidCallSymbol: { + SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, "operand must be a bare symbol name"); + } } llvm_unreachable("Unknown match type detected!"); @@ -1142,6 +1157,25 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { return MatchOperand_Success; } +OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) { + SMLoc S = getLoc(); + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + const MCExpr *Res; + + if (getLexer().getKind() != AsmToken::Identifier) + return MatchOperand_NoMatch; + + StringRef Identifier; + if (getParser().parseIdentifier(Identifier)) + return MatchOperand_ParseFail; + + MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); + Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext()); + Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); + return MatchOperand_Success; +} + OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) { // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo` // both being acceptable forms. When parsing `jal ra, foo` this function diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index fe4e2f94c01..883ec4d9b7c 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -101,11 +101,7 @@ void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI, raw_ostream &OS, assert(Func.isExpr() && "Expected expression"); - const MCExpr *Expr = Func.getExpr(); - - // Create function call expression CallExpr for AUIPC. - const MCExpr *CallExpr = - RISCVMCExpr::create(Expr, RISCVMCExpr::VK_RISCV_CALL, Ctx); + const MCExpr *CallExpr = Func.getExpr(); // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type. TmpInst = MCInstBuilder(RISCV::AUIPC) diff --git a/lib/Target/RISCV/RISCVISelLowering.cpp b/lib/Target/RISCV/RISCVISelLowering.cpp index 877476b711e..03baccfabec 100644 --- a/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1811,9 +1811,11 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI, // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't // split it and then direct call can be matched by PseudoCALL. if (GlobalAddressSDNode *S = dyn_cast(Callee)) { - Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); + Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, + RISCVII::MO_CALL); } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, 0); + Callee = + DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, RISCVII::MO_CALL); } // The first call operand is the chain and the second is the target address. diff --git a/lib/Target/RISCV/RISCVInstrInfo.td b/lib/Target/RISCV/RISCVInstrInfo.td index dce704cce10..b0de89229b3 100644 --- a/lib/Target/RISCV/RISCVInstrInfo.td +++ b/lib/Target/RISCV/RISCVInstrInfo.td @@ -190,6 +190,18 @@ def bare_symbol : Operand { let ParserMatchClass = BareSymbol; } +def CallSymbol : AsmOperandClass { + let Name = "CallSymbol"; + let RenderMethod = "addImmOperands"; + let DiagnosticType = "InvalidCallSymbol"; + let ParserMethod = "parseCallSymbol"; +} + +// A bare symbol used in call/tail only. +def call_symbol : Operand { + let ParserMatchClass = CallSymbol; +} + def CSRSystemRegister : AsmOperandClass { let Name = "CSRSystemRegister"; let ParserMethod = "parseCSRSystemRegister"; @@ -844,7 +856,7 @@ def : Pat<(brind (add GPR:$rs1, simm12:$imm12)), // Define AsmString to print "call" when compile with -S flag. // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in -def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func), +def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [(riscv_call tglobaladdr:$func)]> { let AsmString = "call\t$func"; } @@ -869,7 +881,7 @@ def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, // Define AsmString to print "tail" when compile with -S flag. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], isCodeGenOnly = 0 in -def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst), []> { +def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> { let AsmString = "tail\t$dst"; } diff --git a/lib/Target/RISCV/RISCVMCInstLower.cpp b/lib/Target/RISCV/RISCVMCInstLower.cpp index c2c4128f8a6..ba0cfd9edb6 100644 --- a/lib/Target/RISCV/RISCVMCInstLower.cpp +++ b/lib/Target/RISCV/RISCVMCInstLower.cpp @@ -36,6 +36,9 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, case RISCVII::MO_None: Kind = RISCVMCExpr::VK_RISCV_None; break; + case RISCVII::MO_CALL: + Kind = RISCVMCExpr::VK_RISCV_CALL; + break; case RISCVII::MO_LO: Kind = RISCVMCExpr::VK_RISCV_LO; break; diff --git a/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/lib/Target/RISCV/Utils/RISCVBaseInfo.h index c2548b781a6..990040fd0ce 100644 --- a/lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ b/lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -48,6 +48,7 @@ enum { enum { MO_None, + MO_CALL, MO_LO, MO_HI, MO_PCREL_LO, -- 2.50.1