Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LoongArch] Support parsing la.tls.desc pseudo instruction #90158

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
170 changes: 163 additions & 7 deletions llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
Expand Down Expand Up @@ -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) &&
Expand All @@ -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) &&
Expand All @@ -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) &&
Expand All @@ -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) &&
Expand All @@ -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) &&
Expand All @@ -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) &&
Expand All @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() ==
Expand Down