@@ -39,7 +39,11 @@ class LoongArch final : public TargetInfo {
39
39
void relocate (uint8_t *loc, const Relocation &rel,
40
40
uint64_t val) const override ;
41
41
bool relaxOnce (int pass) const override ;
42
+ void relocateAlloc (InputSectionBase &sec, uint8_t *buf) const override ;
42
43
void finalizeRelax (int passes) const override ;
44
+
45
+ private:
46
+ void tlsIeToLe (uint8_t *loc, const Relocation &rel, uint64_t val) const ;
43
47
};
44
48
} // end anonymous namespace
45
49
@@ -53,6 +57,8 @@ enum Op {
53
57
ADDI_W = 0x02800000 ,
54
58
ADDI_D = 0x02c00000 ,
55
59
ANDI = 0x03400000 ,
60
+ ORI = 0x03800000 ,
61
+ LU12I_W = 0x14000000 ,
56
62
PCADDI = 0x18000000 ,
57
63
PCADDU12I = 0x1c000000 ,
58
64
LD_W = 0x28800000 ,
@@ -1002,6 +1008,87 @@ static bool relax(Ctx &ctx, InputSection &sec) {
1002
1008
return changed;
1003
1009
}
1004
1010
1011
+ // Convert TLS IE to LE in the normal or medium code model.
1012
+ // Original code sequence:
1013
+ // * pcalau12i $a0, %ie_pc_hi20(sym)
1014
+ // * ld.d $a0, $a0, %ie_pc_lo12(sym)
1015
+ //
1016
+ // The code sequence converted is as follows:
1017
+ // * lu12i.w $a0, %le_hi20(sym) # le_hi20 != 0, otherwise NOP
1018
+ // * ori $a0 $a0, %le_lo12(sym)
1019
+ //
1020
+ // When relaxation enables, redundant NOPs can be removed.
1021
+ void LoongArch::tlsIeToLe (uint8_t *loc, const Relocation &rel,
1022
+ uint64_t val) const {
1023
+ assert (isInt<32 >(val) &&
1024
+ " val exceeds the range of medium code model in tlsIeToLe" );
1025
+
1026
+ bool isUInt12 = isUInt<12 >(val);
1027
+ const uint32_t currInsn = read32le (loc);
1028
+ switch (rel.type ) {
1029
+ case R_LARCH_TLS_IE_PC_HI20:
1030
+ if (isUInt12)
1031
+ write32le (loc, insn (ANDI, R_ZERO, R_ZERO, 0 )); // nop
1032
+ else
1033
+ write32le (loc, insn (LU12I_W, getD5 (currInsn), extractBits (val, 31 , 12 ),
1034
+ 0 )); // lu12i.w $a0, %le_hi20
1035
+ break ;
1036
+ case R_LARCH_TLS_IE_PC_LO12:
1037
+ if (isUInt12)
1038
+ write32le (loc, insn (ORI, getD5 (currInsn), R_ZERO,
1039
+ val)); // ori $a0, $r0, %le_lo12
1040
+ else
1041
+ write32le (loc, insn (ORI, getD5 (currInsn), getJ5 (currInsn),
1042
+ lo12 (val))); // ori $a0, $a0, %le_lo12
1043
+ break ;
1044
+ }
1045
+ }
1046
+
1047
+ void LoongArch::relocateAlloc (InputSectionBase &sec, uint8_t *buf) const {
1048
+ const unsigned bits = ctx.arg .is64 ? 64 : 32 ;
1049
+ uint64_t secAddr = sec.getOutputSection ()->addr ;
1050
+ if (auto *s = dyn_cast<InputSection>(&sec))
1051
+ secAddr += s->outSecOff ;
1052
+ else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
1053
+ secAddr += ehIn->getParent ()->outSecOff ;
1054
+ bool isExtreme = false ;
1055
+ const MutableArrayRef<Relocation> relocs = sec.relocs ();
1056
+ for (size_t i = 0 , size = relocs.size (); i != size; ++i) {
1057
+ Relocation &rel = relocs[i];
1058
+ uint8_t *loc = buf + rel.offset ;
1059
+ uint64_t val = SignExtend64 (
1060
+ sec.getRelocTargetVA (ctx, rel, secAddr + rel.offset ), bits);
1061
+
1062
+ switch (rel.expr ) {
1063
+ case R_RELAX_HINT:
1064
+ continue ;
1065
+ case R_RELAX_TLS_IE_TO_LE:
1066
+ if (rel.type == R_LARCH_TLS_IE_PC_HI20) {
1067
+ // LoongArch does not support IE to LE optimize in the extreme code
1068
+ // model. In this case, the relocs are as follows:
1069
+ //
1070
+ // * i -- R_LARCH_TLS_IE_PC_HI20
1071
+ // * i+1 -- R_LARCH_TLS_IE_PC_LO12
1072
+ // * i+2 -- R_LARCH_TLS_IE64_PC_LO20
1073
+ // * i+3 -- R_LARCH_TLS_IE64_PC_HI12
1074
+ isExtreme =
1075
+ (i + 2 < size && relocs[i + 2 ].type == R_LARCH_TLS_IE64_PC_LO20);
1076
+ }
1077
+ if (isExtreme) {
1078
+ rel.expr = getRelExpr (rel.type , *rel.sym , loc);
1079
+ val = SignExtend64 (sec.getRelocTargetVA (ctx, rel, secAddr + rel.offset ),
1080
+ bits);
1081
+ relocateNoSym (loc, rel.type , val);
1082
+ } else
1083
+ tlsIeToLe (loc, rel, val);
1084
+ continue ;
1085
+ default :
1086
+ break ;
1087
+ }
1088
+ relocate (loc, rel, val);
1089
+ }
1090
+ }
1091
+
1005
1092
// When relaxing just R_LARCH_ALIGN, relocDeltas is usually changed only once in
1006
1093
// the absence of a linker script. For call and load/store R_LARCH_RELAX, code
1007
1094
// shrinkage may reduce displacement and make more relocations eligible for
0 commit comments