From 58692f8b4073497ca8d3dae36acdf8b2e8b2fa03 Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Tue, 2 Apr 2019 12:47:20 +0000 Subject: [PATCH] [RISCV] Support assembling @plt symbol operands This patch allows symbols appended with @plt to parse and assemble with the R_RISCV_CALL_PLT relocation. Differential Revision: https://reviews.llvm.org/D55335 Patch by Lewis Revill. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357470 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 14 ++++++++++++-- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 3 ++- lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h | 1 + .../RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp | 2 ++ lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h | 4 ++++ .../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 4 ++++ lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp | 11 ++++++++--- lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h | 1 + test/MC/RISCV/function-call.s | 8 ++++++++ test/MC/RISCV/lla-invalid.s | 1 + test/MC/RISCV/tail-call.s | 6 ++++++ 11 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index b054a3d518d..6c46a401092 100644 --- a/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -291,7 +291,8 @@ public: if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) return false; return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && - VK == RISCVMCExpr::VK_RISCV_CALL; + (VK == RISCVMCExpr::VK_RISCV_CALL || + VK == RISCVMCExpr::VK_RISCV_CALL_PLT); } bool isCSRSystemRegister() const { return isSystemRegister(); } @@ -1142,6 +1143,11 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { if (getParser().parseIdentifier(Identifier)) return MatchOperand_ParseFail; + if (Identifier.consume_back("@plt")) { + Error(getLoc(), "'@plt' operand not valid for instruction"); + return MatchOperand_ParseFail; + } + MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); if (Sym->isVariable()) { @@ -1169,9 +1175,13 @@ OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) { if (getParser().parseIdentifier(Identifier)) return MatchOperand_ParseFail; + RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL; + if (Identifier.consume_back("@plt")) + Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; + MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext()); + Res = RISCVMCExpr::create(Res, Kind, getContext()); Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); return MatchOperand_Success; } diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index af4ee415083..d5d464ecf7d 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -230,7 +230,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7); return Value; } - case RISCV::fixup_riscv_call: { + case RISCV::fixup_riscv_call: + case RISCV::fixup_riscv_call_plt: { // Jalr will add UpperImm with the sign-extended 12-bit LowerImm, // we need to add 0x800ULL before extract upper bits to reflect the // effect of the sign extension. diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 246f13f7b79..ae13e5fc868 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -110,6 +110,7 @@ public: { "fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_riscv_relax", 0, 0, 0 }, { "fixup_riscv_align", 0, 0, 0 } }; diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp index 103ca3255e4..4fa3cd8c573 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp +++ b/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp @@ -95,6 +95,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_RISCV_RVC_BRANCH; case RISCV::fixup_riscv_call: return ELF::R_RISCV_CALL; + case RISCV::fixup_riscv_call_plt: + return ELF::R_RISCV_CALL_PLT; case RISCV::fixup_riscv_relax: return ELF::R_RISCV_RELAX; case RISCV::fixup_riscv_align: diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h index 21fcb13bce8..b931acc4da5 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h +++ b/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h @@ -52,6 +52,10 @@ enum Fixups { // fixup_riscv_call - A fixup representing a call attached to the auipc // instruction in a pair composed of adjacent auipc+jalr instructions. fixup_riscv_call, + // fixup_riscv_call_plt - A fixup representing a procedure linkage table call + // attached to the auipc instruction in a pair composed of adjacent auipc+jalr + // instructions. + fixup_riscv_call_plt, // fixup_riscv_relax - Used to generate an R_RISCV_RELAX relocation type, // which indicates the linker may relax the instruction pair. fixup_riscv_relax, diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index 883ec4d9b7c..692398ea955 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -242,6 +242,10 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, FixupKind = RISCV::fixup_riscv_call; RelaxCandidate = true; break; + case RISCVMCExpr::VK_RISCV_CALL_PLT: + FixupKind = RISCV::fixup_riscv_call_plt; + RelaxCandidate = true; + break; } } else if (Kind == MCExpr::SymbolRef && cast(Expr)->getKind() == MCSymbolRefExpr::VK_None) { diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp index b6d2fa07054..d3974997070 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -33,11 +33,15 @@ const RISCVMCExpr *RISCVMCExpr::create(const MCExpr *Expr, VariantKind Kind, } void RISCVMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { - bool HasVariant = - ((getKind() != VK_RISCV_None) && (getKind() != VK_RISCV_CALL)); + VariantKind Kind = getKind(); + bool HasVariant = ((Kind != VK_RISCV_None) && (Kind != VK_RISCV_CALL) && + (Kind != VK_RISCV_CALL_PLT)); + if (HasVariant) OS << '%' << getVariantKindName(getKind()) << '('; Expr->print(OS, MAI); + if (Kind == VK_RISCV_CALL_PLT) + OS << "@plt"; if (HasVariant) OS << ')'; } @@ -200,7 +204,8 @@ bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const { MCValue Value; if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO || - Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL) + Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL || + Kind == VK_RISCV_CALL_PLT) return false; if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) diff --git a/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h b/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h index 26c9db57dd2..2cd30875d48 100644 --- a/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h +++ b/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h @@ -30,6 +30,7 @@ public: VK_RISCV_PCREL_HI, VK_RISCV_GOT_HI, VK_RISCV_CALL, + VK_RISCV_CALL_PLT, VK_RISCV_Invalid }; diff --git a/test/MC/RISCV/function-call.s b/test/MC/RISCV/function-call.s index 44f64f5a70b..6ee77b01746 100644 --- a/test/MC/RISCV/function-call.s +++ b/test/MC/RISCV/function-call.s @@ -43,3 +43,11 @@ call mstatus # INSTR: auipc ra, 0 # INSTR: jalr ra # FIXUP: fixup A - offset: 0, value: mstatus, kind: fixup_riscv_call + +# Ensure that calls to procedure linkage table symbols work. + +call foo@plt +# RELOC: R_RISCV_CALL_PLT foo 0x0 +# INSTR: auipc ra, 0 +# INSTR: jalr ra +# FIXUP: fixup A - offset: 0, value: foo@plt, kind: fixup_riscv_call_plt diff --git a/test/MC/RISCV/lla-invalid.s b/test/MC/RISCV/lla-invalid.s index bd99bfd83ca..6449f9571e2 100644 --- a/test/MC/RISCV/lla-invalid.s +++ b/test/MC/RISCV/lla-invalid.s @@ -4,3 +4,4 @@ # Non bare symbols must be rejected lla a2, %lo(a_symbol) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name lla a2, %hi(a_symbol) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name +lla a2, foo@plt # CHECK: :[[@LINE]]:17: error: '@plt' operand not valid for instruction diff --git a/test/MC/RISCV/tail-call.s b/test/MC/RISCV/tail-call.s index 9662e61d866..78c73c1dd3c 100644 --- a/test/MC/RISCV/tail-call.s +++ b/test/MC/RISCV/tail-call.s @@ -45,3 +45,9 @@ tail ra # INSTR: auipc t1, 0 # INSTR: jr t1 # FIXUP: fixup A - offset: 0, value: ra, kind: + +tail foo@plt +# RELOC: R_RISCV_CALL_PLT foo 0x0 +# INSTR: auipc t1, 0 +# INSTR: jr t1 +# FIXUP: fixup A - offset: 0, value: foo@plt, kind: -- 2.50.1