Commit b8a64b8e authored by Clemens Fruhwirth's avatar Clemens Fruhwirth
Browse files

Sign extension hack to work around PC64 relocation limitation for binutils <2.17 for x86_64.

binutils <2.17 can't generate PC64 relocations for x86_64. Hence we
emit only 32 bit PC relative offsets, and artifically stick a zero in
front of them to make them 64 bit (see PprMach.sh ppr_item in
pprDataItem). This works as long as the offset is <32bit AND it's
positive. This is not the case for offsets in jump tables, they are
all negative. This hack sign extends them with a MOVSXL instruction
into the dead index register, then adding the properly sign extended
offset to the jump table base label giving the correct target address
for the following jump.
parent 873dc895
...@@ -3896,7 +3896,8 @@ genSwitch expr ids ...@@ -3896,7 +3896,8 @@ genSwitch expr ids
op = OpAddr (AddrBaseIndex (EABaseReg tableReg) op = OpAddr (AddrBaseIndex (EABaseReg tableReg)
(EAIndex reg wORD_SIZE) (ImmInt 0)) (EAIndex reg wORD_SIZE) (ImmInt 0))
#if x86_64_TARGET_ARCH && darwin_TARGET_OS #if x86_64_TARGET_ARCH
#if darwin_TARGET_OS
-- on Mac OS X/x86_64, put the jump table in the text section -- on Mac OS X/x86_64, put the jump table in the text section
-- to work around a limitation of the linker. -- to work around a limitation of the linker.
-- ld64 is unable to handle the relocations for -- ld64 is unable to handle the relocations for
...@@ -3908,6 +3909,23 @@ genSwitch expr ids ...@@ -3908,6 +3909,23 @@ genSwitch expr ids
JMP_TBL (OpReg tableReg) [ id | Just id <- ids ], JMP_TBL (OpReg tableReg) [ id | Just id <- ids ],
LDATA Text (CmmDataLabel lbl : jumpTable) LDATA Text (CmmDataLabel lbl : jumpTable)
] ]
#else
-- HACK: On x86_64 binutils<2.17 is only able to generate PC32
-- relocations, hence we only get 32-bit offsets in the jump
-- table. As these offsets are always negative we need to properly
-- sign extend them to 64-bit. This hack should be removed in
-- conjunction with the hack in PprMach.hs/pprDataItem once
-- binutils 2.17 is standard.
code = e_code `appOL` t_code `appOL` toOL [
LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable),
MOVSxL I32
(OpAddr (AddrBaseIndex (EABaseReg tableReg)
(EAIndex reg wORD_SIZE) (ImmInt 0)))
(OpReg reg),
ADD wordRep (OpReg reg) (OpReg tableReg),
JMP_TBL (OpReg tableReg) [ id | Just id <- ids ]
]
#endif
#else #else
code = e_code `appOL` t_code `appOL` toOL [ code = e_code `appOL` t_code `appOL` toOL [
LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable), LDATA ReadOnlyData (CmmDataLabel lbl : jumpTable),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment