diff options
author | Magnus Lång <[email protected]> | 2016-11-07 17:37:22 +0100 |
---|---|---|
committer | Magnus Lång <[email protected]> | 2016-11-07 18:04:53 +0100 |
commit | d5f0e614ab2998a153de569290bf2fca78d88af6 (patch) | |
tree | 0527dbcff1380e23b50299b3fa03639ae545ae2c /lib/hipe/llvm | |
parent | 3e06b82f0f29d90bff0783e7f3d1dabb435782f5 (diff) | |
download | otp-d5f0e614ab2998a153de569290bf2fca78d88af6.tar.gz otp-d5f0e614ab2998a153de569290bf2fca78d88af6.tar.bz2 otp-d5f0e614ab2998a153de569290bf2fca78d88af6.zip |
hipe_llvm: Fix incorrect atom alignment assumption
ErLLVM was declaring atoms in the following manner:
@atom_ok = external constant i64
; Used inside a function like this
%var = ptrtoint i64* @atom_ok to i64
However, doing so makes LLVM think the `atom_ok` is 8-byte aligned,
since it refers to a i64 value. This resulted in LLVM occasionally
incorrectly optimising away type tests on atoms, causing incorrect
behaviour or even segfaults. One such case is in
bs_match_compiler:coverage_apply/2, in which an is_boxed test on a
literal atom was optimised away, causing the code to try and load the
"header" of an atom. This problem reproduces with LLVM versions 3.7
through 3.9.
By declaring atoms as i8 (byte) constants instead, LLVM no longer makes
these alignment assumptions, and the bug is fixed.
Diffstat (limited to 'lib/hipe/llvm')
-rw-r--r-- | lib/hipe/llvm/hipe_rtl_to_llvm.erl | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 66b2e10fb8..46201cb2ef 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1496,16 +1496,18 @@ seperate_relocs([R|Rs], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) -> %% @doc External declaration of an atom. declare_atom({AtomName, _}) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", WordTy, ""). + %% The type has to be byte, or a backend might assume the constant is aligned + %% and incorrectly optimise away type tests + ByteTy = hipe_llvm:mk_int(8), + hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", ByteTy, ""). %% @doc Creation of local variable for an atom. load_atom({AtomName, _}) -> Dst = "%" ++ AtomName ++ "_var", Name = "@" ++ AtomName, WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - WordTyPtr = hipe_llvm:mk_pointer(WordTy), - hipe_llvm:mk_conversion(Dst, ptrtoint, WordTyPtr, Name, WordTy). + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy). %% @doc External declaration of a closure. declare_closure({ClosureName, _})-> |