]> granicus.if.org Git - llvm/commitdiff
[RISCV] Support assembling %got_pcrel_hi operator
authorAlex Bradbury <asb@lowrisc.org>
Fri, 15 Feb 2019 09:43:46 +0000 (09:43 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Fri, 15 Feb 2019 09:43:46 +0000 (09:43 +0000)
Differential Revision: https://reviews.llvm.org/D55279
Patch by James Clarke.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354110 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/relocations.s
test/MC/RISCV/rv32i-invalid.s

index 36a3e595b55d5e9e54c9ae4502a967d42f87dd87..5e89b4c8d987ddb9cfa841c5e2ef7bbcada53638 100644 (file)
@@ -504,10 +504,12 @@ public:
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
     if (!IsConstantImm) {
       IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
-      return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
+      return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
+                         VK == RISCVMCExpr::VK_RISCV_GOT_HI);
     } else {
       return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
-                                 VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
+                                 VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
+                                 VK == RISCVMCExpr::VK_RISCV_GOT_HI);
     }
   }
 
@@ -860,8 +862,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidUImm20AUIPC:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, 0, (1 << 20) - 1,
-        "operand must be a symbol with %pcrel_hi() modifier or an integer in "
-        "the range");
+        "operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier "
+        "or an integer in the range");
   case Match_InvalidSImm21Lsb0JAL:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
index 7ce058da6175006d30df98252130d67e21eebb44..c21cd7fb06abc3b84c363cc7f24fd9bcaadd0cbb 100644 (file)
@@ -33,6 +33,8 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
   switch ((unsigned)Fixup.getKind()) {
   default:
     break;
+  case RISCV::fixup_riscv_got_hi20:
+    return true;
   case RISCV::fixup_riscv_pcrel_lo12_i:
   case RISCV::fixup_riscv_pcrel_lo12_s:
     // For pcrel_lo12, force a relocation if the target of the corresponding
@@ -48,6 +50,9 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
     default:
       llvm_unreachable("Unexpected fixup kind for pcrel_lo12");
       break;
+    case RISCV::fixup_riscv_got_hi20:
+      ShouldForce = true;
+      break;
     case RISCV::fixup_riscv_pcrel_hi20:
       ShouldForce = T->getValue()->findAssociatedFragment() !=
                     Fixup.getValue()->findAssociatedFragment();
@@ -173,6 +178,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
   switch (Kind) {
   default:
     llvm_unreachable("Unknown fixup kind!");
+  case RISCV::fixup_riscv_got_hi20:
+    llvm_unreachable("Relocation should be unconditionally forced\n");
   case FK_Data_1:
   case FK_Data_2:
   case FK_Data_4:
index 6fbc02ff3c00583551131e7972c854c813cedc9c..ff3b5a5d2bd330b38b5196e46281de405ef1092d 100644 (file)
@@ -89,6 +89,7 @@ public:
       { "fixup_riscv_pcrel_hi20",   12,     20,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_pcrel_lo12_i", 20,     12,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_pcrel_lo12_s",  0,     32,  MCFixupKindInfo::FKF_IsPCRel },
+      { "fixup_riscv_got_hi20",     12,     20,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_jal",          12,     20,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_branch",        0,     32,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_rvc_jump",      2,     11,  MCFixupKindInfo::FKF_IsPCRel },
index 4cbbbcbc1b1d90f563dd25f95eb25db0a4ac3207..103ca3255e46c4f234617d0710c13168c60325ab 100644 (file)
@@ -83,6 +83,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
     return ELF::R_RISCV_PCREL_LO12_I;
   case RISCV::fixup_riscv_pcrel_lo12_s:
     return ELF::R_RISCV_PCREL_LO12_S;
+  case RISCV::fixup_riscv_got_hi20:
+    return ELF::R_RISCV_GOT_HI20;
   case RISCV::fixup_riscv_jal:
     return ELF::R_RISCV_JAL;
   case RISCV::fixup_riscv_branch:
index 3748a1fee7aea721533fc705cffcb16c413a3641..21fcb13bce80b7a8245a9f0dad10ec0ab60b9cff 100644 (file)
@@ -34,6 +34,9 @@ enum Fixups {
   // fixup_riscv_pcrel_lo12_s - 12-bit fixup corresponding to pcrel_lo(foo) for
   // the S-type store instructions
   fixup_riscv_pcrel_lo12_s,
+  // fixup_riscv_got_hi20 - 20-bit fixup corresponding to got_pcrel_hi(foo) for
+  // instructions like auipc
+  fixup_riscv_got_hi20,
   // fixup_riscv_jal - 20-bit fixup for symbol references in the jal
   // instruction
   fixup_riscv_jal,
index 4c4f9cf927af807657fbef6ab63579829cdf7ccc..fe4e2f94c01ece04d5179a5f3342a1aa7cffefdc 100644 (file)
@@ -239,6 +239,9 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
       FixupKind = RISCV::fixup_riscv_pcrel_hi20;
       RelaxCandidate = true;
       break;
+    case RISCVMCExpr::VK_RISCV_GOT_HI:
+      FixupKind = RISCV::fixup_riscv_got_hi20;
+      break;
     case RISCVMCExpr::VK_RISCV_CALL:
       FixupKind = RISCV::fixup_riscv_call;
       RelaxCandidate = true;
index 436b6fa540ab0ab92fbcc00c41d9916bc14428aa..98938d2583460d2f296008ea7effc6e67869da31 100644 (file)
@@ -62,6 +62,7 @@ const MCFixup *RISCVMCExpr::getPCRelHiFixup() const {
     switch ((unsigned)F.getKind()) {
     default:
       continue;
+    case RISCV::fixup_riscv_got_hi20:
     case RISCV::fixup_riscv_pcrel_hi20:
       return &F;
     }
@@ -136,6 +137,7 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
     case VK_RISCV_HI:
     case VK_RISCV_PCREL_LO:
     case VK_RISCV_PCREL_HI:
+    case VK_RISCV_GOT_HI:
       return false;
     }
   }
@@ -153,6 +155,7 @@ RISCVMCExpr::VariantKind RISCVMCExpr::getVariantKindForName(StringRef name) {
       .Case("hi", VK_RISCV_HI)
       .Case("pcrel_lo", VK_RISCV_PCREL_LO)
       .Case("pcrel_hi", VK_RISCV_PCREL_HI)
+      .Case("got_pcrel_hi", VK_RISCV_GOT_HI)
       .Default(VK_RISCV_Invalid);
 }
 
@@ -168,6 +171,8 @@ StringRef RISCVMCExpr::getVariantKindName(VariantKind Kind) {
     return "pcrel_lo";
   case VK_RISCV_PCREL_HI:
     return "pcrel_hi";
+  case VK_RISCV_GOT_HI:
+    return "got_pcrel_hi";
   }
 }
 
@@ -175,7 +180,7 @@ bool RISCVMCExpr::evaluateAsConstant(int64_t &Res) const {
   MCValue Value;
 
   if (Kind == VK_RISCV_PCREL_HI || Kind == VK_RISCV_PCREL_LO ||
-      Kind == VK_RISCV_CALL)
+      Kind == VK_RISCV_GOT_HI || Kind == VK_RISCV_CALL)
     return false;
 
   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
index 861acc79f27192cdff1fb9ea8cd569488bcde21d..26c9db57dd296d8b7bead00f247340c8e03ee30d 100644 (file)
@@ -28,6 +28,7 @@ public:
     VK_RISCV_HI,
     VK_RISCV_PCREL_LO,
     VK_RISCV_PCREL_HI,
+    VK_RISCV_GOT_HI,
     VK_RISCV_CALL,
     VK_RISCV_Invalid
   };
@@ -52,11 +53,11 @@ public:
 
   const MCExpr *getSubExpr() const { return Expr; }
 
-  /// Get the MCExpr of the VK_RISCV_PCREL_HI Fixup that the
-  /// VK_RISCV_PCREL_LO points to.
+  /// Get the corresponding PC-relative HI fixup that a VK_RISCV_PCREL_LO
+  /// points to.
   ///
   /// \returns nullptr if this isn't a VK_RISCV_PCREL_LO pointing to a
-  /// VK_RISCV_PCREL_HI.
+  /// known PC-relative HI fixup.
   const MCFixup *getPCRelHiFixup() const;
 
   void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
index a879c9a54adb902cc7a081e085788bf784a0b9e7..f704d27d5b7193e19e1fdc9ee637ca2b09bf76b0 100644 (file)
@@ -65,6 +65,40 @@ sb t1, %pcrel_lo(.L0)(a2)
 # INSTR: sb t1, %pcrel_lo(.L0)(a2)
 # FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L0), kind: fixup_riscv_pcrel_lo12_s
 
+.L1:
+auipc t1, %got_pcrel_hi(foo)
+# RELOC: R_RISCV_GOT_HI20 foo 0x0
+# INSTR: auipc t1, %got_pcrel_hi(foo)
+# FIXUP: fixup A - offset: 0, value: %got_pcrel_hi(foo), kind: fixup_riscv_got_hi20
+
+addi t1, t1, %pcrel_lo(.L1)
+# RELOC: R_RISCV_PCREL_LO12_I .L1 0x0
+# INSTR: addi t1, t1, %pcrel_lo(.L1)
+# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L1), kind: fixup_riscv_pcrel_lo12_i
+
+sb t1, %pcrel_lo(.L1)(a2)
+# RELOC: R_RISCV_PCREL_LO12_S .L1 0x0
+# INSTR: sb t1, %pcrel_lo(.L1)(a2)
+# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L1), kind: fixup_riscv_pcrel_lo12_s
+
+# Check that GOT relocations aren't evaluated to a constant when the symbol is
+# in the same object file.
+.L2:
+auipc t1, %got_pcrel_hi(.L1)
+# RELOC: R_RISCV_GOT_HI20 .L1 0x0
+# INSTR: auipc t1, %got_pcrel_hi(.L1)
+# FIXUP: fixup A - offset: 0, value: %got_pcrel_hi(.L1), kind: fixup_riscv_got_hi20
+
+addi t1, t1, %pcrel_lo(.L2)
+# RELOC: R_RISCV_PCREL_LO12_I .L2 0x0
+# INSTR: addi t1, t1, %pcrel_lo(.L2)
+# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_i
+
+sb t1, %pcrel_lo(.L2)(a2)
+# RELOC: R_RISCV_PCREL_LO12_S .L2 0x0
+# INSTR: sb t1, %pcrel_lo(.L2)(a2)
+# FIXUP: fixup A - offset: 0, value: %pcrel_lo(.L2), kind: fixup_riscv_pcrel_lo12_s
+
 jal zero, foo
 # RELOC: R_RISCV_JAL
 # INSTR: jal zero, foo
index f856bf1f93442369e0e85cc7425e43f9c2e7f7a9..b5fabee471ea3d0f376c0dd4196076f077c63aac 100644 (file)
@@ -40,7 +40,7 @@ bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of
 ## uimm20
 lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
 lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
-auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
 
 ## simm21_lsb0
 jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
@@ -105,7 +105,7 @@ bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a mul
 
 ## uimm20
 lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
-auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
 
 ## simm21_lsb0
 jal gp, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
@@ -125,10 +125,10 @@ lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi
 lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
 lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
 
-auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
-auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
-auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
-auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
+auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
+auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
+auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier or an integer in the range [0, 1048575]
 
 # Unrecognized operand modifier
 addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier