]> granicus.if.org Git - llvm/commitdiff
[RISCV] Support assembling @plt symbol operands
authorAlex Bradbury <asb@lowrisc.org>
Tue, 2 Apr 2019 12:47:20 +0000 (12:47 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Tue, 2 Apr 2019 12:47:20 +0000 (12:47 +0000)
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
lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h
test/MC/RISCV/function-call.s
test/MC/RISCV/lla-invalid.s
test/MC/RISCV/tail-call.s

index b054a3d518d0a91c320a0f87e8e3bb6aa01ac456..6c46a401092c2a45248835ab39174beac61c618b 100644 (file)
@@ -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;
 }
index af4ee415083856e1fcbec2316e1111befa5f77c6..d5d464ecf7dd92199b359ff716ab0d0123e723d3 100644 (file)
@@ -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.
index 246f13f7b796a21c2c157d95336d08ebc22907b1..ae13e5fc868e5ab91a298a5d92f78f9f29bc0552 100644 (file)
@@ -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 }
     };
index 103ca3255e46c4f234617d0710c13168c60325ab..4fa3cd8c573fab1b3b80eea05a4ec071f6719af6 100644 (file)
@@ -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:
index 21fcb13bce80b7a8245a9f0dad10ec0ab60b9cff..b931acc4da58d9a6b59e3d1a8463d893cdad0c05 100644 (file)
@@ -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,
index 883ec4d9b7ca0a1d2d0bfd886b9c6246981b3b7f..692398ea9551f7849b7db087a751530e530b7ab5 100644 (file)
@@ -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) {
index b6d2fa070545c2b5ea7d385bd2b3f4b876b5c76d..d3974997070f03d6ca6063304bb60e1985c6983c 100644 (file)
@@ -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))
index 26c9db57dd296d8b7bead00f247340c8e03ee30d..2cd30875d48e0dcd8d4937c91f1bcd99d6312a14 100644 (file)
@@ -30,6 +30,7 @@ public:
     VK_RISCV_PCREL_HI,
     VK_RISCV_GOT_HI,
     VK_RISCV_CALL,
+    VK_RISCV_CALL_PLT,
     VK_RISCV_Invalid
   };
 
index 44f64f5a70b4103fe4503bc51bae7f8ea1d72e9b..6ee77b017465b1cc1f6b97a2403ceece030a0776 100644 (file)
@@ -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
index bd99bfd83ca97f91d7be24c01ec4eee5d819888a..6449f9571e29748d4a8f097d0d62c78dfbea44a3 100644 (file)
@@ -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
index 9662e61d866ebd0240807a1772ecd1190e3a3d1f..78c73c1dd3c1e7bdda056bd2bcd8d1fa58cd5590 100644 (file)
@@ -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: