Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -107,6 +107,7 @@ 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); @@ -277,6 +278,16 @@ 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. @@ -898,6 +909,10 @@ 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!"); @@ -1120,6 +1135,25 @@ 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 Index: lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -102,11 +102,7 @@ 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) Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -1441,9 +1441,11 @@ // 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. Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -185,6 +185,18 @@ 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"; @@ -777,7 +789,7 @@ // 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), [(Call tglobaladdr:$func)]> { let AsmString = "call\t$func"; } @@ -801,7 +813,7 @@ // 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"; } Index: lib/Target/RISCV/RISCVMCInstLower.cpp =================================================================== --- lib/Target/RISCV/RISCVMCInstLower.cpp +++ lib/Target/RISCV/RISCVMCInstLower.cpp @@ -37,6 +37,9 @@ 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; Index: lib/Target/RISCV/Utils/RISCVBaseInfo.h =================================================================== --- lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -49,6 +49,7 @@ enum { MO_None, + MO_CALL, MO_LO, MO_HI, MO_PCREL_LO,