Skip to content

Commit 56c24f9

Browse files
committed
Relax TLSDESC code sequence.
Original code sequence: * pcalau12i $a0, %desc_pc_hi20(sym_desc) * addi.d $a0, $a0, %desc_pc_lo12(sym_desc) * ld.d $ra, $a0, %desc_ld(sym_desc) * jirl $ra, $ra, %desc_call(sym_desc) Cannot convert to LE/IE, but relax: * pcaddi $a0, %desc_pcrel_20(sym_desc) * ld.d $ra, $a0, %desc_ld(sym_desc) * jirl $ra, $ra, %desc_call(sym_desc) FIXME: The conversion of TLSDESC GD/LD to LE/IE will implement in a future patch.
1 parent b57c40e commit 56c24f9

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

lld/ELF/Arch/LoongArch.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,9 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
782782
(rHi20.type == R_LARCH_TLS_GD_PC_HI20 &&
783783
rLo12.type == R_LARCH_GOT_PC_LO12) ||
784784
(rHi20.type == R_LARCH_TLS_LD_PC_HI20 &&
785-
rLo12.type == R_LARCH_GOT_PC_LO12)))
785+
rLo12.type == R_LARCH_GOT_PC_LO12) ||
786+
(rHi20.type == R_LARCH_TLS_DESC_PC_HI20 &&
787+
rLo12.type == R_LARCH_TLS_DESC_PC_LO12)))
786788
return;
787789

788790
// GOT references to absolute symbols can't be relaxed to use pcaddi in
@@ -804,6 +806,8 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
804806
symBase = rHi20.sym->getVA(ctx);
805807
else if (rHi20.expr == RE_LOONGARCH_TLSGD_PAGE_PC)
806808
symBase = ctx.in.got->getGlobalDynAddr(*rHi20.sym);
809+
else if (rHi20.expr == RE_LOONGARCH_TLSDESC_PAGE_PC)
810+
symBase = ctx.in.got->getTlsDescAddr(*rHi20.sym);
807811
else {
808812
Err(ctx) << getErrorLoc(ctx, (const uint8_t *)loc) << "unknown expr ("
809813
<< rHi20.expr << ") against symbol " << rHi20.sym
@@ -837,6 +841,8 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
837841
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_GD_PCREL20_S2;
838842
else if (rHi20.type == R_LARCH_TLS_LD_PC_HI20)
839843
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_LD_PCREL20_S2;
844+
else if (rHi20.type == R_LARCH_TLS_DESC_PC_HI20)
845+
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_DESC_PCREL20_S2;
840846
else
841847
sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
842848
sec.relaxAux->writes.push_back(insn(PCADDI, getD5(nextInsn), 0, 0));
@@ -903,6 +909,33 @@ static void relaxTlsLe(Ctx &ctx, const InputSection &sec, size_t i,
903909
}
904910
}
905911

912+
// Relax TLSDESC code sequence. In LoongArch, the conversion of TLSDESC GD/LD to
913+
// LE/IE is closely tied to relaxation, similar to how GCC handles it. (Due to
914+
// the lack of an efficient way for handling conversions in the extreme code
915+
// model and the difficulty in determining whether the extreme code model is
916+
// being used in handleTlsRelocation, this approach may seem like a workaround).
917+
// Consequently, the resulting code sequence depends on whether the conversion
918+
// to LE/IE is performed.
919+
//
920+
// Original code sequence:
921+
// * pcalau12i $a0, %desc_pc_hi20(sym_desc)
922+
// * addi.d $a0, $a0, %desc_pc_lo12(sym_desc)
923+
// * ld.d $ra, $a0, %desc_ld(sym_desc)
924+
// * jirl $ra, $ra, %desc_call(sym_desc)
925+
//
926+
// Cannot convert to LE/IE, but relax:
927+
// * pcaddi $a0, %desc_pcrel_20(sym_desc)
928+
// * ld.d $ra, $a0, %desc_ld(sym_desc)
929+
// * jirl $ra, $ra, %desc_call(sym_desc)
930+
//
931+
// FIXME: Implement TLSDESC GD/LD to LE/IE.
932+
static void relaxTlsdesc(Ctx &ctx, const InputSection &sec, size_t i,
933+
uint64_t loc, Relocation &rHi20, Relocation &rLo12,
934+
uint32_t &remove) {
935+
if (ctx.arg.shared && rHi20.type == R_LARCH_TLS_DESC_PC_HI20)
936+
return relaxPCHi20Lo12(ctx, sec, i, loc, rHi20, rLo12, remove);
937+
}
938+
906939
static bool relax(Ctx &ctx, InputSection &sec) {
907940
const uint64_t secAddr = sec.getVA();
908941
const MutableArrayRef<Relocation> relocs = sec.relocs();
@@ -959,6 +992,10 @@ static bool relax(Ctx &ctx, InputSection &sec) {
959992
if (relaxable(relocs, i))
960993
relaxTlsLe(ctx, sec, i, loc, r, remove);
961994
break;
995+
case R_LARCH_TLS_DESC_PC_HI20:
996+
if (isPairRelaxable(relocs, i))
997+
relaxTlsdesc(ctx, sec, i, loc, r, relocs[i + 2], remove);
998+
break;
962999
}
9631000

9641001
// For all anchors whose offsets are <= r.offset, they are preceded by
@@ -1078,6 +1115,11 @@ void LoongArch::finalizeRelax(int passes) const {
10781115
write32le(p, aux.writes[writesIdx++]);
10791116
r.expr = R_TLSGD_PC;
10801117
break;
1118+
case R_LARCH_TLS_DESC_PCREL20_S2:
1119+
skip = 4;
1120+
write32le(p, aux.writes[writesIdx++]);
1121+
r.expr = R_TLSDESC_PC;
1122+
break;
10811123
default:
10821124
llvm_unreachable("unsupported type");
10831125
}

0 commit comments

Comments
 (0)