[llvm] [LoongArch] Support parsing la.tls.desc pseudo instruction (PR #90158)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 29 18:56:19 PDT 2024
https://github.com/wangleiat updated https://github.com/llvm/llvm-project/pull/90158
>From c6a9d4327370f321d4c34f5edbd7326a88637bf3 Mon Sep 17 00:00:00 2001
From: wanglei <wanglei at loongson.cn>
Date: Fri, 26 Apr 2024 11:03:39 +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.4
---
.../AsmParser/LoongArchAsmParser.cpp | 170 +++++++++++++++++-
.../Target/LoongArch/LoongArchInstrInfo.td | 21 +++
.../MCTargetDesc/LoongArchFixupKinds.h | 22 +++
.../MCTargetDesc/LoongArchMCCodeEmitter.cpp | 30 ++++
.../MCTargetDesc/LoongArchMCExpr.cpp | 32 ++++
.../LoongArch/MCTargetDesc/LoongArchMCExpr.h | 10 ++
llvm/test/MC/LoongArch/Macros/macros-la-bad.s | 3 +
llvm/test/MC/LoongArch/Macros/macros-la.s | 45 +++++
llvm/test/MC/LoongArch/Misc/tls-symbols.s | 22 +++
.../MC/LoongArch/Relocations/relocations.s | 50 ++++++
10 files changed, 398 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 20284b18428bd8..73cb80245bca4d 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -118,6 +118,13 @@ class LoongArchAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "la.tls.gd $rd, $rj, sym".
void emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo instruction "la.tls.desc $rd, sym".
+ void emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ void emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo instruction "la.tls.desc $rd, $rj, sym".
+ void emitLoadAddressTLSDescPcrelLarge(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out);
+
// Helper to emit pseudo instruction "li.w/d $rd, $imm".
void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
@@ -132,6 +139,7 @@ class LoongArchAsmParser : public MCTargetAsmParser {
Match_RequiresOpnd2NotR0R1,
Match_RequiresAMORdDifferRkRj,
Match_RequiresLAORdDifferRj,
+ Match_RequiresLAORdR4,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "LoongArchGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -267,7 +275,9 @@ class LoongArchOperand : public MCParsedAsmOperand {
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
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_IE_PC_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
return IsConstantImm
? isInt<12>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -288,7 +298,9 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
- VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
return IsConstantImm
? isInt<12>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -311,7 +323,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
- VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12;
return IsConstantImm
? isUInt<12>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -334,7 +347,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
VK == LoongArchMCExpr::VK_LoongArch_B16 ||
- VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
+ VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
return IsConstantImm
? isShiftedInt<16, 2>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -355,7 +369,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
- VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
return IsConstantImm
? isInt<20>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -375,7 +390,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
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 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
return IsConstantImm
? isInt<20>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -396,7 +412,9 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
- VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20 ||
+ VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20;
return IsConstantImm
? isInt<20>(Imm) && IsValidKind
@@ -801,6 +819,13 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addImm(0),
getSTI());
continue;
+ } else if (VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD) {
+ Out.emitInstruction(MCInstBuilder(Opc)
+ .addReg(LoongArch::R1)
+ .addReg(DestReg)
+ .addExpr(LE),
+ getSTI());
+ continue;
}
Out.emitInstruction(
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
@@ -833,6 +858,13 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addReg(TmpReg),
getSTI());
break;
+ case LoongArch::JIRL:
+ Out.emitInstruction(MCInstBuilder(Opc)
+ .addReg(LoongArch::R1)
+ .addReg(LoongArch::R1)
+ .addExpr(LE),
+ getSTI());
+ break;
}
}
}
@@ -1116,6 +1148,109 @@ void LoongArchAsmParser::emitLoadAddressTLSGDLarge(MCInst &Inst, SMLoc IDLoc,
emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
}
+void LoongArchAsmParser::emitLoadAddressTLSDescAbs(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // `la.tls.desc $rd, sym` with `la-global-with-abs` feature
+ // for la32 expands to:
+ // lu12i.w $rd, %desc_hi20(sym)
+ // ori $rd, $rd, %desc_lo12(sym)
+ // ld.w $ra, $rd, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ //
+ // for la64 expands to:
+ // lu12i.w $rd, %desc_hi20(sym)
+ // ori $rd, $rd, %desc_lo12(sym)
+ // lu32i.d $rd, %desc64_lo20(sym)
+ // lu52i.d $rd, $rd, %desc64_hi12(sym)
+ // ld.d $ra, $rd, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ MCRegister DestReg = Inst.getOperand(0).getReg();
+ const MCExpr *Symbol = Inst.getOpcode() == LoongArch::PseudoLA_TLS_DESC_ABS
+ ? Inst.getOperand(1).getExpr()
+ : Inst.getOperand(2).getExpr();
+ unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+ InstSeq Insts;
+
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LU12I_W, LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::ORI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12));
+
+ if (is64Bit()) {
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12));
+ }
+
+ Insts.push_back(
+ LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
+
+ emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
+}
+
+void LoongArchAsmParser::emitLoadAddressTLSDescPcrel(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // la.tls.desc $rd, sym
+ // expands to:
+ // pcalau12i $rd, %desc_pc_hi20(sym)
+ // addi.w/d $rd, $rd, %desc_pc_lo12(sym)
+ // ld.w/d $ra, $rd, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ MCRegister DestReg = Inst.getOperand(0).getReg();
+ const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+ unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+ unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+ InstSeq Insts;
+
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ ADDI, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
+ Insts.push_back(
+ LoongArchAsmParser::Inst(LD, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
+
+ emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
+}
+
+void LoongArchAsmParser::emitLoadAddressTLSDescPcrelLarge(MCInst &Inst,
+ SMLoc IDLoc,
+ MCStreamer &Out) {
+ // la.tls.desc $rd, $rj, sym
+ // expands to:
+ // pcalau12i $rd, %desc_pc_hi20(sym)
+ // addi.d $rj, $r0, %desc_pc_lo12(sym)
+ // lu32i.d $rj, %desc64_pc_lo20(sym)
+ // lu52i.d $rj, $rj, %desc64_pc_hi12(sym)
+ // add.d $rd, $rd, $rj
+ // ld.w/d $ra, $rd, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ MCRegister DestReg = Inst.getOperand(0).getReg();
+ MCRegister TmpReg = Inst.getOperand(1).getReg();
+ const MCExpr *Symbol = Inst.getOperand(2).getExpr();
+ InstSeq Insts;
+
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::PCALAU12I, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::ADDI_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LU32I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LU52I_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12));
+ Insts.push_back(LoongArchAsmParser::Inst(LoongArch::ADD_D));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::LD_D, LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD));
+ Insts.push_back(LoongArchAsmParser::Inst(
+ LoongArch::JIRL, LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL));
+
+ emitLAInstSeq(DestReg, TmpReg, Symbol, Insts, IDLoc, Out);
+}
+
void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
MCRegister DestReg = Inst.getOperand(0).getReg();
@@ -1211,6 +1346,16 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLA_TLS_GD_LARGE:
emitLoadAddressTLSGDLarge(Inst, IDLoc, Out);
return false;
+ case LoongArch::PseudoLA_TLS_DESC_ABS:
+ case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
+ emitLoadAddressTLSDescAbs(Inst, IDLoc, Out);
+ return false;
+ case LoongArch::PseudoLA_TLS_DESC_PC:
+ emitLoadAddressTLSDescPcrel(Inst, IDLoc, Out);
+ return false;
+ case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:
+ emitLoadAddressTLSDescPcrelLarge(Inst, IDLoc, Out);
+ return false;
case LoongArch::PseudoLI_W:
case LoongArch::PseudoLI_D:
emitLoadImm(Inst, IDLoc, Out);
@@ -1238,6 +1383,15 @@ unsigned LoongArchAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return Match_RequiresAMORdDifferRkRj;
}
break;
+ case LoongArch::PseudoLA_TLS_DESC_ABS:
+ case LoongArch::PseudoLA_TLS_DESC_ABS_LARGE:
+ case LoongArch::PseudoLA_TLS_DESC_PC:
+ case LoongArch::PseudoLA_TLS_DESC_PC_LARGE: {
+ unsigned Rd = Inst.getOperand(0).getReg();
+ if (Rd != LoongArch::R4)
+ return Match_RequiresLAORdR4;
+ break;
+ }
case LoongArch::PseudoLA_PCREL_LARGE:
case LoongArch::PseudoLA_GOT_LARGE:
case LoongArch::PseudoLA_TLS_IE_LARGE:
@@ -1376,6 +1530,8 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
"$rd must be different from both $rk and $rj");
case Match_RequiresLAORdDifferRj:
return Error(Operands[1]->getStartLoc(), "$rd must be different from $rj");
+ case Match_RequiresLAORdR4:
+ return Error(Operands[1]->getStartLoc(), "$rd must be $r4");
case Match_InvalidUImm1:
return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
/*Upper=*/(1 << 1) - 1);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 80429bc45be14c..958803b52d4ec8 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -1607,6 +1607,27 @@ def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
} // Defs = [R20], Size = 20
}
+// TLSDESC
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
+ isAsmParserOnly = 1, Defs = [R1] in {
+def PseudoLA_TLS_DESC_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src),
+ [], "la.tls.desc", "$dst, $src">,
+ Requires<[IsLA32, HasLaGlobalWithAbs]>;
+def PseudoLA_TLS_DESC_ABS_LARGE : Pseudo<(outs GPR:$dst),
+ (ins GPR:$tmp, bare_symbol:$src), [],
+ "la.tls.desc", "$dst, $src">,
+ Requires<[IsLA64, HasLaGlobalWithAbs]>;
+def PseudoLA_TLS_DESC_PC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
+ "la.tls.desc", "$dst, $src">;
+}
+
+let isCall = 1, isBarrier = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0,
+ isCodeGenOnly = 0, isAsmParserOnly = 1, Defs = [R1, R4, R20], Size = 32 in
+def PseudoLA_TLS_DESC_PC_LARGE : Pseudo<(outs GPR:$dst),
+ (ins GPR:$tmp, bare_symbol:$src), [],
+ "la.tls.desc", "$dst, $tmp, $src">,
+ Requires<[IsLA64]>;
+
// Load address inst alias: "la", "la.global" and "la.local".
// Default:
// la = la.global = la.got
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
index 0d19d2b0fb1fe8..fb0587bf3bed7c 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
@@ -114,6 +114,28 @@ enum Fixups {
// 36-bit fixup corresponding to %call36(foo) for a pair instructions:
// pcaddu18i+jirl.
fixup_loongarch_call36 = FirstLiteralRelocationKind + ELF::R_LARCH_CALL36,
+ // 20-bit fixup corresponding to %desc_pc_hi20(foo) for instruction pcalau12i.
+ fixup_loongarch_tls_desc_pc_hi20 =
+ FirstLiteralRelocationKind + ELF::R_LARCH_TLS_DESC_PC_HI20,
+ // 12-bit fixup corresponding to %desc_pc_lo12(foo) for instructions like
+ // addi.w/d.
+ fixup_loongarch_tls_desc_pc_lo12,
+ // 20-bit fixup corresponding to %desc64_pc_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_tls_desc64_pc_lo20,
+ // 12-bit fixup corresponding to %desc64_pc_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_tls_desc64_pc_hi12,
+ // 20-bit fixup corresponding to %desc_hi20(foo) for instruction lu12i.w.
+ fixup_loongarch_tls_desc_hi20,
+ // 12-bit fixup corresponding to %desc_lo12(foo) for instruction ori.
+ fixup_loongarch_tls_desc_lo12,
+ // 20-bit fixup corresponding to %desc64_lo20(foo) for instruction lu32i.d.
+ fixup_loongarch_tls_desc64_lo20,
+ // 12-bit fixup corresponding to %desc64_hi12(foo) for instruction lu52i.d.
+ fixup_loongarch_tls_desc64_hi12,
+ // 12-bit fixup corresponding to %desc_ld(foo) for instruction ld.w/d.
+ fixup_loongarch_tls_desc_ld,
+ // 12-bit fixup corresponding to %desc_call(foo) for instruction jirl.
+ fixup_loongarch_tls_desc_call,
};
} // 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 9ac0128f251728..83812dc3c62a8b 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -244,6 +244,36 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
case LoongArchMCExpr::VK_LoongArch_CALL36:
FixupKind = LoongArch::fixup_loongarch_call36;
break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_pc_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc64_pc_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_hi20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LO12:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_lo12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_LO20:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc64_lo20;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC64_HI12:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc64_hi12;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_ld;
+ break;
+ case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL:
+ FixupKind = LoongArch::fixup_loongarch_tls_desc_call;
+ break;
}
} else if (Kind == MCExpr::SymbolRef &&
cast<MCSymbolRefExpr>(Expr)->getKind() ==
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
index d6fa3b6e50968c..34f9bc65ec77c3 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
@@ -140,6 +140,26 @@ StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {
return "gd_hi20";
case VK_LoongArch_CALL36:
return "call36";
+ case VK_LoongArch_TLS_DESC_PC_HI20:
+ return "desc_pc_hi20";
+ case VK_LoongArch_TLS_DESC_PC_LO12:
+ return "desc_pc_lo12";
+ case VK_LoongArch_TLS_DESC64_PC_LO20:
+ return "desc64_pc_lo20";
+ case VK_LoongArch_TLS_DESC64_PC_HI12:
+ return "desc64_pc_hi12";
+ case VK_LoongArch_TLS_DESC_HI20:
+ return "desc_hi20";
+ case VK_LoongArch_TLS_DESC_LO12:
+ return "desc_lo12";
+ case VK_LoongArch_TLS_DESC64_LO20:
+ return "desc64_lo20";
+ case VK_LoongArch_TLS_DESC64_HI12:
+ return "desc64_hi12";
+ case VK_LoongArch_TLS_DESC_LD:
+ return "desc_ld";
+ case VK_LoongArch_TLS_DESC_CALL:
+ return "desc_call";
}
}
@@ -183,6 +203,16 @@ LoongArchMCExpr::getVariantKindForName(StringRef name) {
.Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20)
.Case("gd_hi20", VK_LoongArch_TLS_GD_HI20)
.Case("call36", VK_LoongArch_CALL36)
+ .Case("desc_pc_hi20", VK_LoongArch_TLS_DESC_PC_HI20)
+ .Case("desc_pc_lo12", VK_LoongArch_TLS_DESC_PC_LO12)
+ .Case("desc64_pc_lo20", VK_LoongArch_TLS_DESC64_PC_LO20)
+ .Case("desc64_pc_hi12", VK_LoongArch_TLS_DESC64_PC_HI12)
+ .Case("desc_hi20", VK_LoongArch_TLS_DESC_HI20)
+ .Case("desc_lo12", VK_LoongArch_TLS_DESC_LO12)
+ .Case("desc64_lo20", VK_LoongArch_TLS_DESC64_LO20)
+ .Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12)
+ .Case("desc_ld", VK_LoongArch_TLS_DESC_LD)
+ .Case("desc_call", VK_LoongArch_TLS_DESC_CALL)
.Default(VK_LoongArch_Invalid);
}
@@ -223,6 +253,8 @@ void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
case VK_LoongArch_TLS_LD_HI20:
case VK_LoongArch_TLS_GD_PC_HI20:
case VK_LoongArch_TLS_GD_HI20:
+ case VK_LoongArch_TLS_DESC_PC_HI20:
+ case VK_LoongArch_TLS_DESC_HI20:
break;
}
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
index bd828116d7fa46..71dd5bd14e4ee1 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
@@ -62,6 +62,16 @@ class LoongArchMCExpr : public MCTargetExpr {
VK_LoongArch_TLS_GD_PC_HI20,
VK_LoongArch_TLS_GD_HI20,
VK_LoongArch_CALL36,
+ VK_LoongArch_TLS_DESC_PC_HI20,
+ VK_LoongArch_TLS_DESC_PC_LO12,
+ VK_LoongArch_TLS_DESC64_PC_LO20,
+ VK_LoongArch_TLS_DESC64_PC_HI12,
+ VK_LoongArch_TLS_DESC_HI20,
+ VK_LoongArch_TLS_DESC_LO12,
+ VK_LoongArch_TLS_DESC64_LO20,
+ VK_LoongArch_TLS_DESC64_HI12,
+ VK_LoongArch_TLS_DESC_LD,
+ VK_LoongArch_TLS_DESC_CALL,
VK_LoongArch_Invalid // Must be the last item.
};
diff --git a/llvm/test/MC/LoongArch/Macros/macros-la-bad.s b/llvm/test/MC/LoongArch/Macros/macros-la-bad.s
index 03c6355e40b092..29c9745e4ad864 100644
--- a/llvm/test/MC/LoongArch/Macros/macros-la-bad.s
+++ b/llvm/test/MC/LoongArch/Macros/macros-la-bad.s
@@ -11,3 +11,6 @@ la.abs $a0, $a1, sym
la.pcrel $a0, $a0, sym
# CHECK: :[[#@LINE-1]]:11: error: $rd must be different from $rj
+
+la.tls.desc $a1, sym
+# CHECK: :[[#@LINE-1]]:14: error: $rd must be $r4
diff --git a/llvm/test/MC/LoongArch/Macros/macros-la.s b/llvm/test/MC/LoongArch/Macros/macros-la.s
index 1a1d12d7d7dfd1..5c572c8e75a0f6 100644
--- a/llvm/test/MC/LoongArch/Macros/macros-la.s
+++ b/llvm/test/MC/LoongArch/Macros/macros-la.s
@@ -3,6 +3,8 @@
# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.relax
# RUN: llvm-readobj -r %t.relax | FileCheck %s --check-prefixes=RELOC,RELAX
+# RUN: llvm-mc --triple=loongarch64 --defsym ABS=1 --mattr=+la-global-with-abs \
+# RUN: %s | FileCheck %s --check-prefix=ABS
# RELOC: Relocations [
# RELOC-NEXT: Section ({{.*}}) .rela.text {
@@ -124,5 +126,48 @@ la.tls.gd $a0, $a1, sym_gd_large
# RELOC-NEXT: R_LARCH_GOT64_PC_LO20 sym_gd_large 0x0
# RELOC-NEXT: R_LARCH_GOT64_PC_HI12 sym_gd_large 0x0
+la.tls.desc $a0, sym_desc
+# CHECK-NEXT: pcalau12i $a0, %desc_pc_hi20(sym_desc)
+# CHECK-NEXT: addi.d $a0, $a0, %desc_pc_lo12(sym_desc)
+# CHECK-NEXT: ld.d $ra, $a0, %desc_ld(sym_desc)
+# CHECK-NEXT: jirl $ra, $ra, %desc_call(sym_desc)
+# CHECK-EMPTY:
+# RELOC-NEXT: R_LARCH_TLS_DESC_PC_HI20 sym_desc 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_PC_LO12 sym_desc 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_LD sym_desc 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_CALL sym_desc 0x0
+
+la.tls.desc $a0, $a1, sym_desc_large
+# CHECK-NEXT: pcalau12i $a0, %desc_pc_hi20(sym_desc_large)
+# CHECK-NEXT: addi.d $a1, $zero, %desc_pc_lo12(sym_desc_large)
+# CHECK-NEXT: lu32i.d $a1, %desc64_pc_lo20(sym_desc_large)
+# CHECK-NEXT: lu52i.d $a1, $a1, %desc64_pc_hi12(sym_desc_large)
+# CHECK-NEXT: add.d $a0, $a0, $a1
+# CHECK-NEXT: ld.d $ra, $a0, %desc_ld(sym_desc_large)
+# CHECK-NEXT: jirl $ra, $ra, %desc_call(sym_desc_large)
+# CHECK-EMPTY:
+# RELOC-NEXT: R_LARCH_TLS_DESC_PC_HI20 sym_desc_large 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_PC_LO12 sym_desc_large 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC64_PC_LO20 sym_desc_large 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC64_PC_HI12 sym_desc_large 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_LD sym_desc_large 0x0
+# RELOC-NEXT: R_LARCH_TLS_DESC_CALL sym_desc_large 0x0
+
+
# RELOC-NEXT: }
# RELOC-NEXT: ]
+
+#############################################################
+## with feature: +la-global-with-abs
+#############################################################
+.ifdef ABS
+
+la.tls.desc $a0, sym_desc
+# ABS: lu12i.w $a0, %desc_hi20(sym_desc)
+# ABS-NEXT: ori $a0, $a0, %desc_lo12(sym_desc)
+# ABS-NEXT: lu32i.d $a0, %desc64_lo20(sym_desc)
+# ABS-NEXT: lu52i.d $a0, $a0, %desc64_hi12(sym_desc)
+# ABS-NEXT: ld.d $ra, $a0, %desc_ld(sym_desc)
+# ABS-NEXT: jirl $ra, $ra, %desc_call(sym_desc)
+
+.endif
diff --git a/llvm/test/MC/LoongArch/Misc/tls-symbols.s b/llvm/test/MC/LoongArch/Misc/tls-symbols.s
index 2f91cbe004d27d..340fea29ed94a3 100644
--- a/llvm/test/MC/LoongArch/Misc/tls-symbols.s
+++ b/llvm/test/MC/LoongArch/Misc/tls-symbols.s
@@ -77,3 +77,25 @@ lu12i.w $a1, %le_hi20(le)
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined
# CHECK-NEXT: }
+
+pcalau12i $a1, %desc_pc_hi20(desc_pc)
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: desc_pc
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: TLS
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+
+lu12i.w $a1, %desc_hi20(desc_abs)
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: desc_abs
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: TLS
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
diff --git a/llvm/test/MC/LoongArch/Relocations/relocations.s b/llvm/test/MC/LoongArch/Relocations/relocations.s
index bec71e10389333..87df59978c6ea3 100644
--- a/llvm/test/MC/LoongArch/Relocations/relocations.s
+++ b/llvm/test/MC/LoongArch/Relocations/relocations.s
@@ -223,3 +223,53 @@ pcaddu18i $t1, %call36(foo)
# RELOC: R_LARCH_CALL36 foo 0x0
# INSTR: pcaddu18i $t1, %call36(foo)
# FIXUP: fixup A - offset: 0, value: %call36(foo), kind: FK_NONE
+
+pcalau12i $t1, %desc_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_DESC_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %desc_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_pc_hi20(foo), kind: FK_NONE
+
+addi.d $t1, $t1, %desc_pc_lo12(foo)
+# RELOC: R_LARCH_TLS_DESC_PC_LO12 foo 0x0
+# INSTR: addi.d $t1, $t1, %desc_pc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_pc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %desc64_pc_lo20(foo)
+# RELOC: R_LARCH_TLS_DESC64_PC_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %desc64_pc_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %desc64_pc_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %desc64_pc_hi12(foo)
+# RELOC: R_LARCH_TLS_DESC64_PC_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %desc64_pc_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %desc64_pc_hi12(foo), kind: FK_NONE
+
+ld.d $ra, $t1, %desc_ld(foo)
+# RELOC: R_LARCH_TLS_DESC_LD foo 0x0
+# INSTR: ld.d $ra, $t1, %desc_ld(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_ld(foo), kind: FK_NONE
+
+jirl $ra, $ra, %desc_call(foo)
+# RELOC: R_LARCH_TLS_DESC_CALL foo 0x0
+# INSTR: jirl $ra, $ra, %desc_call(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_call(foo), kind: FK_NONE
+
+lu12i.w $t1, %desc_hi20(foo)
+# RELOC: R_LARCH_TLS_DESC_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %desc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_hi20(foo), kind: FK_NONE
+
+ori $t1, $t1, %desc_lo12(foo)
+# RELOC: R_LARCH_TLS_DESC_LO12 foo 0x0
+# INSTR: ori $t1, $t1, %desc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %desc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %desc64_lo20(foo)
+# RELOC: R_LARCH_TLS_DESC64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %desc64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %desc64_lo20(foo), kind: FK_NONE
+
+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
More information about the llvm-commits
mailing list