diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 20284b18428bd..73cb80245bca4 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 80429bc45be14..958803b52d4ec 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 0d19d2b0fb1fe..fb0587bf3bed7 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 9ac0128f25172..83812dc3c62a8 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(Expr)->getKind() == diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp index d6fa3b6e50968..34f9bc65ec77c 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 bd828116d7fa4..71dd5bd14e4ee 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 03c6355e40b09..29c9745e4ad86 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 1a1d12d7d7dfd..5c572c8e75a0f 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 2f91cbe004d27..340fea29ed94a 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 bec71e1038933..87df59978c6ea 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