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