[llvm] [LoongArch] Support parsing the `%le_{hi20,add,lo12}_r` modifiers (PR #99485)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 18 20:30:47 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