diff options
author | Sergei Trofimovich <slyfox@gentoo.org> | 2016-03-06 09:55:12 +0000 |
---|---|---|
committer | Sergei Trofimovich <siarheit@google.com> | 2016-03-06 09:55:21 +0000 |
commit | ade1a461ab4ba3e6de3c4afe9fe9766b7b4e51b3 (patch) | |
tree | 726618be2610df530d458a5a61f3956bacc346b4 /compiler/cmm/PprC.hs | |
parent | bd681bceba535d0e67e8182964dc167877e4756d (diff) | |
download | haskell-ade1a461ab4ba3e6de3c4afe9fe9766b7b4e51b3.tar.gz |
Fix minimum alignment for StgClosure (Trac #11395)
The bug is observed on m68k-linux target as crash
in RTS:
-- a.hs:
main = print 43
$ inplace/bin/ghc-stage1 --make -debug a.hs
$ ./a
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x80463b0a in LOOKS_LIKE_INFO_PTR_NOT_NULL (p=32858)
at includes/rts/storage/ClosureMacros.h:248
(gdb) bt
#0 0x80463b0a in LOOKS_LIKE_INFO_PTR_NOT_NULL (p=32858)
at includes/rts/storage/ClosureMacros.h:248
#1 0x80463b46 in LOOKS_LIKE_INFO_PTR (p=32858)
at includes/rts/storage/ClosureMacros.h:253
#2 0x80463b6c in LOOKS_LIKE_CLOSURE_PTR (
p=0x805aac6e <stg_dummy_ret_closure>)
at includes/rts/storage/ClosureMacros.h:258
#3 0x80463e4c in initStorage ()
at rts/sm/Storage.c:121
#4 0x8043ffb4 in hs_init_ghc (...)
at rts/RtsStartup.c:181
#5 0x80455982 in hs_main (...)
at rts/RtsMain.c:51
#6 0x80003c1c in main ()
GHC assumes last 2 pointer bits are tags on 32-bit targets.
But here 'stg_dummy_ret_closure' address violates the assumption:
LOOKS_LIKE_CLOSURE_PTR (p=0x805aac6e <stg_dummy_ret_closure>)
I've added compiler hint for static StgClosure objects to
align closures at least by their natural alignment (what GHC assumes).
See Note [StgWord alignment].
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
Test Plan: ran basic test on m68k qemu, it got past ASSERTs
Reviewers: simonmar, austin, bgamari
Reviewed By: bgamari
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D1974
GHC Trac Issues: #11395
Diffstat (limited to 'compiler/cmm/PprC.hs')
-rw-r--r-- | compiler/cmm/PprC.hs | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs index e679d5516b..c269530409 100644 --- a/compiler/cmm/PprC.hs +++ b/compiler/cmm/PprC.hs @@ -148,10 +148,34 @@ pprWordArray :: CLabel -> [CmmStatic] -> SDoc pprWordArray lbl ds = sdocWithDynFlags $ \dflags -> hcat [ pprLocalness lbl, text "StgWord" - , space, ppr lbl, text "[] = {" ] + , space, ppr lbl, text "[]" + -- See Note [StgWord alignment] + , pprAlignment (wordWidth dflags) + , text "= {" ] $$ nest 8 (commafy (pprStatics dflags ds)) $$ text "};" +pprAlignment :: Width -> SDoc +pprAlignment words = + text "__attribute__((aligned(" <> int (widthInBytes words) <> text ")))" + +-- Note [StgWord alignment] +-- C codegen builds static closures as StgWord C arrays (pprWordArray). +-- Their real C type is 'StgClosure'. Macros like UNTAG_CLOSURE assume +-- pointers to 'StgClosure' are aligned at pointer size boundary: +-- 4 byte boundary on 32 systems +-- and 8 bytes on 64-bit systems +-- see TAG_MASK and TAG_BITS definition and usage. +-- +-- It's a reasonable assumption also known as natural alignment. +-- Although some architectures have different alignment rules. +-- One of known exceptions is m68k (Trac #11395, comment:16) where: +-- __alignof__(StgWord) == 2, sizeof(StgWord) == 4 +-- +-- Thus we explicitly increase alignment by using +-- __attribute__((aligned(4))) +-- declaration. + -- -- has to be static, if it isn't globally visible -- |