Skip to content

llvmGen: Set alignment for objects of the data section

Stefan Schulze Frielinghaus requested to merge wip/stefansf/fix-llvm-align into master

Compiling with GHC 9.4.7 cabal 3.8.1.0 on s390x results in a segfault when running cabal update with a non-existing $HOME/.cabal directory:

Thread 1 "cabal" received signal SIGSEGV, Segmentation fault.
0x0000000082f629d2 in LOOKS_LIKE_INFO_PTR_NOT_NULL (p=17942122799824896) at rts/include/rts/storage/ClosureMacros.h:259
(gdb) bt
#0  0x0000000082f629d2 in LOOKS_LIKE_INFO_PTR_NOT_NULL (p=17942122799824896) at rts/include/rts/storage/ClosureMacros.h:259
#1  0x0000000082f62a5c in LOOKS_LIKE_INFO_PTR (p=17942122799824896) at rts/include/rts/storage/ClosureMacros.h:264
#2  0x0000000082f62ad2 in LOOKS_LIKE_CLOSURE_PTR (p=0x8359d300 <base+30716>) at rts/include/rts/storage/ClosureMacros.h:270
#3  0x0000000082f63fd4 in evacuate1 (p=0x8359d888 <r8yz_closure$def+8>) at rts/sm/Evac.c:694
#4  0x0000000082f21f62 in scavenge_static () at rts/sm/Scav.c:1813
#5  0x0000000082f22806 in scavenge_loop1 () at rts/sm/Scav.c:2164
#6  0x0000000082f0790c in scavenge_until_all_done () at rts/sm/GC.c:1323
#7  0x0000000082f05752 in GarbageCollect (config=..., cap=0x843f8f00 <MainCapability>, idle_cap=0x844260f0) at rts/sm/GC.c:552
#8  0x0000000082ee8520 in scheduleDoGC (pcap=0x3ffffff9e10, task=0x843fd380, force_major=false, is_overflow_gc=true, deadlock_detect=false, nonconcurrent=false) at rts/Schedule.c:1879
#9  0x0000000082ee5c98 in schedule (initialCapability=0x843f8f00 <MainCapability>, task=0x843fd380) at rts/Schedule.c:583
#10 0x0000000082ee9c50 in scheduleWaitThread (tso=0x4200406ce8, ret=0x0, pcap=0x3ffffffa100) at rts/Schedule.c:2651
#11 0x0000000082ed7f5a in rts_evalLazyIO (cap=0x3ffffffa100, p=0x83161430 <ZCMain_main_closure$def>, ret=0x0) at rts/RtsAPI.c:566
#12 0x0000000082edd58c in hs_main (argc=2, argv=0x3ffffffa588, main_closure=0x83161430 <ZCMain_main_closure$def>, rts_config=...) at rts/RtsMain.c:72
#13 0x000000008002370e in main ()

Before executing statement q = UNTAG_CLOSURE(q); we have

(gdb) print q
$1 = (StgClosure *) 0x8359d305 <r8y4_closure$def+1>
(gdb) print *q
$2 = {header = {info = 0x84259620ff}, payload = 0x8359d30d <r8y4_closure$def+9>}

and afterwards

(gdb) print q
$3 = (StgClosure *) 0x8359d300 <base+30716>
(gdb) print *q
$4 = {header = {info = 0x3fbe4400000000}, payload = 0x8359d308 <r8y4_closure$def+4>}

Howver, the actual address of closure r8y4_closure$def is at a 4-byte boundary:

(gdb) info address r8y4_closure$def
Symbol "r8y4_closure$def" is at 0x8359d304 in a file compiled without debugging.
(gdb) print *(StgClosure *)0x8359d304
$5 = {header = {info = 0x84259620 <base_GHCziWord_W8zh_con_info$def>}, payload = 0x8359d30c <r8y4_closure$def+8>}

and therefore untagging results in a wrong address. In the generated llvm IR we also see that no explicit alignment is given:

@r8y4_closure$def = internal global %r8y4_closure_struct<{i64 ptrtoint (i8* @base_GHCziWord_W8zh_con_info to i64), i8 255, i32 0, i16 0, i8 0}>

With this patch an 8-byte alignment is enforced:

@r8y4_closure$def = internal global %r8y4_closure_struct<{i64 ptrtoint (i8* @base_GHCziWord_W8zh_con_info to i64), i8 255, i32 0, i16 0, i8 0}>, align 8

Currently I've bounded the change to s390x because it manifested there. However, I suspect that this should apply to all targets? If for all targets, then ideally we would take the maximum of the natural alignment and 8.

Furthermore, this change enforces an 8-byte alignment to every object in the data section. I'm not sure whether there exist other (non-closure) objects which are not accessed via tagged pointers and therefore could have a natural alignment. Maybe those objects are just a few and special casing them is not worthwhile?

Any thoughts?

Merge request reports