summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp14
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp3
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h1
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp2
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h4
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp4
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp11
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h1
-rw-r--r--llvm/test/MC/RISCV/function-call.s8
-rw-r--r--llvm/test/MC/RISCV/lla-invalid.s1
-rw-r--r--llvm/test/MC/RISCV/tail-call.s6
11 files changed, 49 insertions, 6 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b054a3d518d..6c46a401092 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index af4ee415083..d5d464ecf7d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index 246f13f7b79..ae13e5fc868 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index 103ca3255e4..4fa3cd8c573 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index 21fcb13bce8..b931acc4da5 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 883ec4d9b7c..692398ea955 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/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<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
index b6d2fa07054..d3974997070 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
+++ b/llvm/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/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
index 26c9db57dd2..2cd30875d48 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
+++ b/llvm/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/llvm/test/MC/RISCV/function-call.s b/llvm/test/MC/RISCV/function-call.s
index 44f64f5a70b..6ee77b01746 100644
--- a/llvm/test/MC/RISCV/function-call.s
+++ b/llvm/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/llvm/test/MC/RISCV/lla-invalid.s b/llvm/test/MC/RISCV/lla-invalid.s
index bd99bfd83ca..6449f9571e2 100644
--- a/llvm/test/MC/RISCV/lla-invalid.s
+++ b/llvm/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/llvm/test/MC/RISCV/tail-call.s b/llvm/test/MC/RISCV/tail-call.s
index 9662e61d866..78c73c1dd3c 100644
--- a/llvm/test/MC/RISCV/tail-call.s
+++ b/llvm/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:
OpenPOWER on IntegriCloud