[llvm] [LoongArch] Support parsing the `%le_{hi20,add,lo12}_r` modifiers (PR #99485)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 19 02:46:10 PDT 2024


https://github.com/wangleiat updated https://github.com/llvm/llvm-project/pull/99485

>From 49ae61a80735bddf5bf273c7bc1e9d49bf658f33 Mon Sep 17 00:00:00 2001
From: wanglei <wanglei at loongson.cn>
Date: Thu, 18 Jul 2024 20:51:17 +0800
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5-bogner
---
 .../AsmParser/LoongArchAsmParser.cpp          | 16 +++++++
 .../Target/LoongArch/LoongArchInstrInfo.td    | 28 +++++++++++
 .../MCTargetDesc/LoongArchFixupKinds.h        |  6 +++
 .../MCTargetDesc/LoongArchMCCodeEmitter.cpp   | 47 +++++++++++++++++++
 .../MCTargetDesc/LoongArchMCExpr.cpp          |  9 ++++
 .../LoongArch/MCTargetDesc/LoongArchMCExpr.h  |  3 ++
 .../MC/LoongArch/Relocations/relocations.s    | 15 ++++++
 7 files changed, 124 insertions(+)

diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 73cb80245bca4..208bd3db8f14e 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -245,6 +245,16 @@ class LoongArchOperand : public MCParsedAsmOperand {
            VK == LoongArchMCExpr::VK_LoongArch_None;
   }
 
+  bool isTPRelAddSymbol() const {
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    // Must be of 'immediate' type but not a constant.
+    if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
+      return false;
+    return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+           VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
+  }
+
   bool isUImm1() const { return isUImm<1>(); }
   bool isUImm2() const { return isUImm<2>(); }
   bool isUImm2plus1() const { return isUImm<2, 1>(); }
@@ -276,6 +286,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
                        VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
                        VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
     return IsConstantImm
@@ -391,6 +402,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||
                        VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
     return IsConstantImm
                ? isInt<20>(Imm) && IsValidKind
@@ -1686,6 +1698,10 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(ErrorLoc, "operand must be a bare symbol name");
   }
+  case Match_InvalidTPRelAddSymbol: {
+    SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
+  }
   }
   llvm_unreachable("Unknown match type detected!");
 }
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 67c3dfd3b2599..1e8fc2da63a2c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -456,6 +456,19 @@ def bare_symbol : Operand<GRLenVT> {
   let ParserMatchClass = BareSymbol;
 }
 
+def TPRelAddSymbol : AsmOperandClass {
+  let Name = "TPRelAddSymbol";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticType = "InvalidTPRelAddSymbol";
+  let ParserMethod = "parseOperandWithModifier";
+}
+
+// A bare symbol with the %le_add_r variant.
+def tprel_add_symbol : Operand<GRLenVT> {
+  let ParserMatchClass = TPRelAddSymbol;
+}
+
+
 // Standalone (codegen-only) immleaf patterns.
 
 // A 12-bit signed immediate plus one where the imm range will be [-2047, 2048].
@@ -1570,6 +1583,21 @@ def PseudoTAIL36 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [],
                           "tail36", "$tmp, $dst">,
                    Requires<[IsLA64]>;
 
+// This is a special case of the ADD_W/D instruction used to facilitate the use
+// of a fourth operand to emit a relocation on a symbol relating to this
+// instruction. The relocation does not affect any bits of the instruction itself
+// but is used as a hint to the linker.
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in {
+def PseudoAddTPRel_W : Pseudo<(outs GPR:$rd),
+                             (ins GPR:$rj, GPR:$rk, tprel_add_symbol:$sym), [],
+                             "add.w", "$rd, $rj, $rk, $sym">,
+                             Requires<[IsLA32]>;
+def PseudoAddTPRel_D :  Pseudo<(outs GPR:$rd),
+                             (ins GPR:$rj, GPR:$rk, tprel_add_symbol:$sym), [],
+                             "add.d", "$rd, $rj, $rk, $sym">,
+                             Requires<[IsLA64]>;
+}
+
 /// Load address (la*) macro instructions.
 
 // Define isCodeGenOnly = 0 to expose them to tablegened assembly parser.
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
index fb0587bf3bed7..29ed14f6e4d62 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
@@ -136,6 +136,12 @@ enum Fixups {
   fixup_loongarch_tls_desc_ld,
   // 12-bit fixup corresponding to %desc_call(foo) for instruction jirl.
   fixup_loongarch_tls_desc_call,
+  // 20-bit fixup corresponding to %le_hi20_r(foo) for instruction lu12i.w.
+  fixup_loongarch_tls_le_hi20_r,
+  // Fixup corresponding to %le_add_r(foo) for instruction PseudoAddTPRel_W/D.
+  fixup_loongarch_tls_le_add_r,
+  // 12-bit fixup corresponding to %le_lo12_r(foo) for instruction addi.w/d.
+  fixup_loongarch_tls_le_lo12_r,
 };
 } // end namespace LoongArch
 } // end namespace llvm
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
index 83812dc3c62a8..b7892ebb25e76 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -49,6 +49,10 @@ class LoongArchMCCodeEmitter : public MCCodeEmitter {
                          SmallVectorImpl<MCFixup> &Fixups,
                          const MCSubtargetInfo &STI) const;
 
+  void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
+                      SmallVectorImpl<MCFixup> &Fixups,
+                      const MCSubtargetInfo &STI) const;
+
   /// TableGen'erated function for getting the binary encoding for an
   /// instruction.
   uint64_t getBinaryCodeForInstr(const MCInst &MI,
@@ -134,6 +138,9 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
     case LoongArchMCExpr::VK_LoongArch_None:
     case LoongArchMCExpr::VK_LoongArch_Invalid:
       llvm_unreachable("Unhandled fixup kind!");
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R:
+      llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "
+                       "instruction operand");
     case LoongArchMCExpr::VK_LoongArch_B16:
       FixupKind = LoongArch::fixup_loongarch_b16;
       break;
@@ -274,6 +281,12 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
     case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL:
       FixupKind = LoongArch::fixup_loongarch_tls_desc_call;
       break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R:
+      FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R:
+      FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r;
+      break;
     }
   } else if (Kind == MCExpr::SymbolRef &&
              cast<MCSymbolRefExpr>(Expr)->getKind() ==
@@ -346,6 +359,37 @@ void LoongArchMCCodeEmitter::expandToVectorLDI(
   support::endian::write(CB, Binary, llvm::endianness::little);
 }
 
+void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
+                                            SmallVectorImpl<char> &CB,
+                                            SmallVectorImpl<MCFixup> &Fixups,
+                                            const MCSubtargetInfo &STI) const {
+  MCOperand Rd = MI.getOperand(0);
+  MCOperand Rj = MI.getOperand(1);
+  MCOperand Rk = MI.getOperand(2);
+  MCOperand Symbol = MI.getOperand(3);
+  assert(Symbol.isExpr() &&
+         "Expected expression as third input to TP-relative add");
+
+  const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());
+  assert(Expr &&
+         Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R &&
+         "Expected %le_add_r relocation on TP-relative symbol");
+
+  // Emit the correct %le_add_r relocation for the symbol.
+  Fixups.push_back(MCFixup::create(
+      0, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r),
+      MI.getLoc()));
+
+  // Emit a normal ADD instruction with the given operands.
+  unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D
+                     ? LoongArch::ADD_D
+                     : LoongArch::ADD_W;
+  MCInst TmpInst =
+      MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk);
+  uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+  support::endian::write(CB, Binary, llvm::endianness::little);
+}
+
 void LoongArchMCCodeEmitter::encodeInstruction(
     const MCInst &MI, SmallVectorImpl<char> &CB,
     SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
@@ -366,6 +410,9 @@ void LoongArchMCCodeEmitter::encodeInstruction(
   case LoongArch::PseudoXVREPLI_W:
   case LoongArch::PseudoXVREPLI_D:
     return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
+  case LoongArch::PseudoAddTPRel_W:
+  case LoongArch::PseudoAddTPRel_D:
+    return expandAddTPRel(MI, CB, Fixups, STI);
   }
 
   switch (Size) {
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
index 9b537794c7ab6..98b9b1ab6d3f4 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
@@ -160,6 +160,12 @@ StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {
     return "desc_ld";
   case VK_LoongArch_TLS_DESC_CALL:
     return "desc_call";
+  case VK_LoongArch_TLS_LE_HI20_R:
+    return "le_hi20_r";
+  case VK_LoongArch_TLS_LE_ADD_R:
+    return "le_add_r";
+  case VK_LoongArch_TLS_LE_LO12_R:
+    return "le_lo12_r";
   }
 }
 
@@ -213,6 +219,9 @@ LoongArchMCExpr::getVariantKindForName(StringRef name) {
       .Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12)
       .Case("desc_ld", VK_LoongArch_TLS_DESC_LD)
       .Case("desc_call", VK_LoongArch_TLS_DESC_CALL)
+      .Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R)
+      .Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R)
+      .Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R)
       .Default(VK_LoongArch_Invalid);
 }
 
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
index 148fea309d6fc..1546d894d56ab 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
@@ -72,6 +72,9 @@ class LoongArchMCExpr : public MCTargetExpr {
     VK_LoongArch_TLS_DESC64_HI12,
     VK_LoongArch_TLS_DESC_LD,
     VK_LoongArch_TLS_DESC_CALL,
+    VK_LoongArch_TLS_LE_HI20_R,
+    VK_LoongArch_TLS_LE_ADD_R,
+    VK_LoongArch_TLS_LE_LO12_R,
     VK_LoongArch_Invalid // Must be the last item.
   };
 
diff --git a/llvm/test/MC/LoongArch/Relocations/relocations.s b/llvm/test/MC/LoongArch/Relocations/relocations.s
index 87df59978c6ea..e83b67199e656 100644
--- a/llvm/test/MC/LoongArch/Relocations/relocations.s
+++ b/llvm/test/MC/LoongArch/Relocations/relocations.s
@@ -273,3 +273,18 @@ lu52i.d $t1, $t1, %desc64_hi12(foo)
 # RELOC: R_LARCH_TLS_DESC64_HI12 foo 0x0
 # INSTR: lu52i.d $t1, $t1, %desc64_hi12(foo)
 # FIXUP: fixup A - offset: 0, value: %desc64_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %le_hi20_r(foo)
+# RELOC: R_LARCH_TLS_LE_HI20_R foo 0x0
+# INSTR: lu12i.w $t1, %le_hi20_r(foo)
+# FIXUP: fixup A - offset: 0, value: %le_hi20_r(foo), kind: FK_NONE
+
+add.d $t1, $t2, $tp, %le_add_r(foo)
+# RELOC: R_LARCH_TLS_LE_ADD_R foo 0x0
+# INSTR: add.d $t1, $t2, $tp, %le_add_r(foo)
+# FIXUP: fixup A - offset: 0, value: %le_add_r(foo), kind: FK_NONE
+
+addi.d $t1, $a2, %le_lo12_r(foo)
+# RELOC: R_LARCH_TLS_LE_LO12_R foo 0x0
+# INSTR: addi.d $t1, $a2, %le_lo12_r(foo)
+# FIXUP: fixup A - offset: 0, value: %le_lo12_r(foo), kind: FK_NONE



More information about the llvm-commits mailing list