aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-11-07 17:37:22 +0100
committerMagnus Lång <[email protected]>2016-11-07 18:04:53 +0100
commitd5f0e614ab2998a153de569290bf2fca78d88af6 (patch)
tree0527dbcff1380e23b50299b3fa03639ae545ae2c
parent3e06b82f0f29d90bff0783e7f3d1dabb435782f5 (diff)
downloadotp-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.
-rw-r--r--lib/hipe/llvm/hipe_rtl_to_llvm.erl10
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, _})->