The current binutils implementation does not support offset up to 4GB in IMAGE_REL_ARM64_PAGEBASE_REL21 relocation and is limited to 1MB. This is related to differences in ELF and COFF relocation records. There are ways to fix this. This work on relocation change will be extracted to a separate binutils patch series and discussion.
To unblock the current patch series, the IMAGE_REL_ARM64_PAGEBASE_REL21 relocation will remain unchanged, and the workaround below will be applied to bypass the 1MB offset limitation. Regards, Evgeny The patch will be replaced by this change. diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 03362a975c0..5f17936df1f 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -2896,7 +2896,30 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, if (can_create_pseudo_p ()) tmp_reg = gen_reg_rtx (mode); - emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm))); + do + { + if (TARGET_PECOFF) + { + poly_int64 offset; + HOST_WIDE_INT const_offset; + strip_offset (imm, &offset); + + if (offset.is_constant (&const_offset) + && abs(const_offset) >= 1 << 20) + { + rtx const_int = imm; + const_int = XEXP (const_int, 0); + XEXP (const_int, 1) = GEN_INT(const_offset % (1 << 20)); + + emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx(imm))); + emit_insn (gen_add_hioffset (tmp_reg, GEN_INT(const_offset))); + break; + } + } + + emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm))); + } while(0); + emit_insn (gen_add_losym (dest, tmp_reg, imm)); return; } diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 665a333903c..072110f93e7 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7405,6 +7405,13 @@ DONE; }) +(define_insn "add_hioffset" + [(match_operand 0 "register_operand") + (match_operand 1 "const_int_operand")] + "" + "add %0, %0, (%1 & ~0xfffff) >> 12, lsl #12" +) + (define_insn "add_losym_<mode>" [(set (match_operand:P 0 "register_operand" "=r") (lo_sum:P (match_operand:P 1 "register_operand" "r")