Skip to content

Commit 0f23156

Browse files
authored
[LoongArch] Support parsing the %le_{hi20,add,lo12}_r modifiers
Reviewed By: SixWeining Pull Request: #99485
1 parent 02cb5bc commit 0f23156

File tree

7 files changed

+125
-0
lines changed

7 files changed

+125
-0
lines changed

llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,16 @@ class LoongArchOperand : public MCParsedAsmOperand {
245245
VK == LoongArchMCExpr::VK_LoongArch_None;
246246
}
247247

248+
bool isTPRelAddSymbol() const {
249+
int64_t Imm;
250+
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
251+
// Must be of 'immediate' type but not a constant.
252+
if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
253+
return false;
254+
return LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
255+
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
256+
}
257+
248258
bool isUImm1() const { return isUImm<1>(); }
249259
bool isUImm2() const { return isUImm<2>(); }
250260
bool isUImm2plus1() const { return isUImm<2, 1>(); }
@@ -276,6 +286,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
276286
VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
277287
VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
278288
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12 ||
289+
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R ||
279290
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12 ||
280291
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
281292
return IsConstantImm
@@ -391,6 +402,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
391402
VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
392403
VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
393404
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20 ||
405+
VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R ||
394406
VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_HI20;
395407
return IsConstantImm
396408
? isInt<20>(Imm) && IsValidKind
@@ -1686,6 +1698,10 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16861698
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
16871699
return Error(ErrorLoc, "operand must be a bare symbol name");
16881700
}
1701+
case Match_InvalidTPRelAddSymbol: {
1702+
SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc();
1703+
return Error(ErrorLoc, "operand must be a symbol with %le_add_r modifier");
1704+
}
16891705
}
16901706
llvm_unreachable("Unknown match type detected!");
16911707
}

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,19 @@ def bare_symbol : Operand<GRLenVT> {
456456
let ParserMatchClass = BareSymbol;
457457
}
458458

459+
def TPRelAddSymbol : AsmOperandClass {
460+
let Name = "TPRelAddSymbol";
461+
let RenderMethod = "addImmOperands";
462+
let DiagnosticType = "InvalidTPRelAddSymbol";
463+
let ParserMethod = "parseOperandWithModifier";
464+
}
465+
466+
// A bare symbol with the %le_add_r variant.
467+
def tprel_add_symbol : Operand<GRLenVT> {
468+
let ParserMatchClass = TPRelAddSymbol;
469+
}
470+
471+
459472
// Standalone (codegen-only) immleaf patterns.
460473

461474
// 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), [],
15701583
"tail36", "$tmp, $dst">,
15711584
Requires<[IsLA64]>;
15721585

1586+
// This is a special case of the ADD_W/D instruction used to facilitate the use
1587+
// of a fourth operand to emit a relocation on a symbol relating to this
1588+
// instruction. The relocation does not affect any bits of the instruction itself
1589+
// but is used as a hint to the linker.
1590+
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in {
1591+
def PseudoAddTPRel_W : Pseudo<(outs GPR:$rd),
1592+
(ins GPR:$rj, GPR:$rk, tprel_add_symbol:$sym), [],
1593+
"add.w", "$rd, $rj, $rk, $sym">,
1594+
Requires<[IsLA32]>;
1595+
def PseudoAddTPRel_D : Pseudo<(outs GPR:$rd),
1596+
(ins GPR:$rj, GPR:$rk, tprel_add_symbol:$sym), [],
1597+
"add.d", "$rd, $rj, $rk, $sym">,
1598+
Requires<[IsLA64]>;
1599+
}
1600+
15731601
/// Load address (la*) macro instructions.
15741602

15751603
// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser.

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ enum Fixups {
136136
fixup_loongarch_tls_desc_ld,
137137
// 12-bit fixup corresponding to %desc_call(foo) for instruction jirl.
138138
fixup_loongarch_tls_desc_call,
139+
// 20-bit fixup corresponding to %le_hi20_r(foo) for instruction lu12i.w.
140+
fixup_loongarch_tls_le_hi20_r,
141+
// Fixup corresponding to %le_add_r(foo) for instruction PseudoAddTPRel_W/D.
142+
fixup_loongarch_tls_le_add_r,
143+
// 12-bit fixup corresponding to %le_lo12_r(foo) for instruction addi.w/d.
144+
fixup_loongarch_tls_le_lo12_r,
139145
};
140146
} // end namespace LoongArch
141147
} // end namespace llvm

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ class LoongArchMCCodeEmitter : public MCCodeEmitter {
4949
SmallVectorImpl<MCFixup> &Fixups,
5050
const MCSubtargetInfo &STI) const;
5151

52+
void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
53+
SmallVectorImpl<MCFixup> &Fixups,
54+
const MCSubtargetInfo &STI) const;
55+
5256
/// TableGen'erated function for getting the binary encoding for an
5357
/// instruction.
5458
uint64_t getBinaryCodeForInstr(const MCInst &MI,
@@ -134,6 +138,9 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
134138
case LoongArchMCExpr::VK_LoongArch_None:
135139
case LoongArchMCExpr::VK_LoongArch_Invalid:
136140
llvm_unreachable("Unhandled fixup kind!");
141+
case LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R:
142+
llvm_unreachable("VK_LoongArch_TLS_LE_ADD_R should not represent an "
143+
"instruction operand");
137144
case LoongArchMCExpr::VK_LoongArch_B16:
138145
FixupKind = LoongArch::fixup_loongarch_b16;
139146
break;
@@ -274,6 +281,12 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
274281
case LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL:
275282
FixupKind = LoongArch::fixup_loongarch_tls_desc_call;
276283
break;
284+
case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R:
285+
FixupKind = LoongArch::fixup_loongarch_tls_le_hi20_r;
286+
break;
287+
case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R:
288+
FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r;
289+
break;
277290
}
278291
} else if (Kind == MCExpr::SymbolRef &&
279292
cast<MCSymbolRefExpr>(Expr)->getKind() ==
@@ -346,6 +359,38 @@ void LoongArchMCCodeEmitter::expandToVectorLDI(
346359
support::endian::write(CB, Binary, llvm::endianness::little);
347360
}
348361

362+
void LoongArchMCCodeEmitter::expandAddTPRel(const MCInst &MI,
363+
SmallVectorImpl<char> &CB,
364+
SmallVectorImpl<MCFixup> &Fixups,
365+
const MCSubtargetInfo &STI) const {
366+
MCOperand Rd = MI.getOperand(0);
367+
MCOperand Rj = MI.getOperand(1);
368+
MCOperand Rk = MI.getOperand(2);
369+
MCOperand Symbol = MI.getOperand(3);
370+
assert(Symbol.isExpr() &&
371+
"Expected expression as third input to TP-relative add");
372+
373+
const LoongArchMCExpr *Expr = dyn_cast<LoongArchMCExpr>(Symbol.getExpr());
374+
assert(Expr &&
375+
Expr->getKind() == LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R &&
376+
"Expected %le_add_r relocation on TP-relative symbol");
377+
378+
// Emit the correct %le_add_r relocation for the symbol.
379+
// TODO: Emit R_LARCH_RELAX for %le_add_r where the relax feature is enabled.
380+
Fixups.push_back(MCFixup::create(
381+
0, Expr, MCFixupKind(LoongArch::fixup_loongarch_tls_le_add_r),
382+
MI.getLoc()));
383+
384+
// Emit a normal ADD instruction with the given operands.
385+
unsigned ADD = MI.getOpcode() == LoongArch::PseudoAddTPRel_D
386+
? LoongArch::ADD_D
387+
: LoongArch::ADD_W;
388+
MCInst TmpInst =
389+
MCInstBuilder(ADD).addOperand(Rd).addOperand(Rj).addOperand(Rk);
390+
uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
391+
support::endian::write(CB, Binary, llvm::endianness::little);
392+
}
393+
349394
void LoongArchMCCodeEmitter::encodeInstruction(
350395
const MCInst &MI, SmallVectorImpl<char> &CB,
351396
SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
@@ -366,6 +411,9 @@ void LoongArchMCCodeEmitter::encodeInstruction(
366411
case LoongArch::PseudoXVREPLI_W:
367412
case LoongArch::PseudoXVREPLI_D:
368413
return expandToVectorLDI<LoongArch::XVLDI>(MI, CB, Fixups, STI);
414+
case LoongArch::PseudoAddTPRel_W:
415+
case LoongArch::PseudoAddTPRel_D:
416+
return expandAddTPRel(MI, CB, Fixups, STI);
369417
}
370418

371419
switch (Size) {

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {
160160
return "desc_ld";
161161
case VK_LoongArch_TLS_DESC_CALL:
162162
return "desc_call";
163+
case VK_LoongArch_TLS_LE_HI20_R:
164+
return "le_hi20_r";
165+
case VK_LoongArch_TLS_LE_ADD_R:
166+
return "le_add_r";
167+
case VK_LoongArch_TLS_LE_LO12_R:
168+
return "le_lo12_r";
163169
}
164170
}
165171

@@ -213,6 +219,9 @@ LoongArchMCExpr::getVariantKindForName(StringRef name) {
213219
.Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12)
214220
.Case("desc_ld", VK_LoongArch_TLS_DESC_LD)
215221
.Case("desc_call", VK_LoongArch_TLS_DESC_CALL)
222+
.Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R)
223+
.Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R)
224+
.Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R)
216225
.Default(VK_LoongArch_Invalid);
217226
}
218227

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class LoongArchMCExpr : public MCTargetExpr {
7272
VK_LoongArch_TLS_DESC64_HI12,
7373
VK_LoongArch_TLS_DESC_LD,
7474
VK_LoongArch_TLS_DESC_CALL,
75+
VK_LoongArch_TLS_LE_HI20_R,
76+
VK_LoongArch_TLS_LE_ADD_R,
77+
VK_LoongArch_TLS_LE_LO12_R,
7578
VK_LoongArch_Invalid // Must be the last item.
7679
};
7780

llvm/test/MC/LoongArch/Relocations/relocations.s

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,18 @@ lu52i.d $t1, $t1, %desc64_hi12(foo)
273273
# RELOC: R_LARCH_TLS_DESC64_HI12 foo 0x0
274274
# INSTR: lu52i.d $t1, $t1, %desc64_hi12(foo)
275275
# FIXUP: fixup A - offset: 0, value: %desc64_hi12(foo), kind: FK_NONE
276+
277+
lu12i.w $t1, %le_hi20_r(foo)
278+
# RELOC: R_LARCH_TLS_LE_HI20_R foo 0x0
279+
# INSTR: lu12i.w $t1, %le_hi20_r(foo)
280+
# FIXUP: fixup A - offset: 0, value: %le_hi20_r(foo), kind: FK_NONE
281+
282+
add.d $t1, $t2, $tp, %le_add_r(foo)
283+
# RELOC: R_LARCH_TLS_LE_ADD_R foo 0x0
284+
# INSTR: add.d $t1, $t2, $tp, %le_add_r(foo)
285+
# FIXUP: fixup A - offset: 0, value: %le_add_r(foo), kind: FK_NONE
286+
287+
addi.d $t1, $a2, %le_lo12_r(foo)
288+
# RELOC: R_LARCH_TLS_LE_LO12_R foo 0x0
289+
# INSTR: addi.d $t1, $a2, %le_lo12_r(foo)
290+
# FIXUP: fixup A - offset: 0, value: %le_lo12_r(foo), kind: FK_NONE

0 commit comments

Comments
 (0)