1 ; Test that some errors trigger when the usage of NaCl atomic 2 ; intrinsics does not match the required ABI. 3 ; REQUIRES: allow_dump 4 5 ; RUN: %p2i -i %s --args --verbose none --exit-success -threads=0 2>&1 \ 6 ; RUN: | FileCheck %s 7 8 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32) 9 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32) 10 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32) 11 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) 12 declare void @llvm.nacl.atomic.store.i64(i64, i64*, i32) 13 declare i8 @llvm.nacl.atomic.rmw.i8(i32, i8*, i8, i32) 14 declare i16 @llvm.nacl.atomic.rmw.i16(i32, i16*, i16, i32) 15 declare i32 @llvm.nacl.atomic.rmw.i32(i32, i32*, i32, i32) 16 declare i64 @llvm.nacl.atomic.rmw.i64(i32, i64*, i64, i32) 17 declare i32 @llvm.nacl.atomic.cmpxchg.i32(i32*, i32, i32, i32, i32) 18 declare i64 @llvm.nacl.atomic.cmpxchg.i64(i64*, i64, i64, i32, i32) 19 declare void @llvm.nacl.atomic.fence(i32) 20 declare i1 @llvm.nacl.atomic.is.lock.free(i32, i8*) 21 22 ;;; Load 23 ;;; Check unexpected memory order parameter (release=4 and acq_rel=5 24 ;;; are disallowed). 25 26 define internal i32 @error_atomic_load_8(i32 %iptr) { 27 entry: 28 %ptr = inttoptr i32 %iptr to i8* 29 %i = call i8 @llvm.nacl.atomic.load.i8(i8* %ptr, i32 0) 30 %r = zext i8 %i to i32 31 ret i32 %r 32 } 33 ; CHECK: Unexpected memory ordering for AtomicLoad 34 35 define internal i32 @error_atomic_load_16(i32 %iptr) { 36 entry: 37 %ptr = inttoptr i32 %iptr to i16* 38 %i = call i16 @llvm.nacl.atomic.load.i16(i16* %ptr, i32 4) 39 %r = zext i16 %i to i32 40 ret i32 %r 41 } 42 ; CHECK: Unexpected memory ordering for AtomicLoad 43 44 define internal i64 @error_atomic_load_64(i32 %iptr) { 45 entry: 46 %ptr = inttoptr i32 %iptr to i64* 47 %r = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 5) 48 ret i64 %r 49 } 50 ; CHECK: Unexpected memory ordering for AtomicLoad 51 52 53 ;;; Store 54 ;;; consume=2, acquire=3, acq_rel=5 are disallowed 55 56 define internal void @error_atomic_store_32(i32 %iptr, i32 %v) { 57 entry: 58 %ptr = inttoptr i32 %iptr to i32* 59 call void @llvm.nacl.atomic.store.i32(i32 %v, i32* %ptr, i32 2) 60 ret void 61 } 62 ; CHECK: Unexpected memory ordering for AtomicStore 63 64 define internal void @error_atomic_store_64(i32 %iptr, i64 %v) { 65 entry: 66 %ptr = inttoptr i32 %iptr to i64* 67 call void @llvm.nacl.atomic.store.i64(i64 %v, i64* %ptr, i32 3) 68 ret void 69 } 70 ; CHECK: Unexpected memory ordering for AtomicStore 71 72 define internal void @error_atomic_store_64_const(i32 %iptr) { 73 entry: 74 %ptr = inttoptr i32 %iptr to i64* 75 call void @llvm.nacl.atomic.store.i64(i64 12345678901234, i64* %ptr, i32 5) 76 ret void 77 } 78 ; CHECK: Unexpected memory ordering for AtomicStore 79 80 ;;; RMW 81 ;;; Test atomic memory order and operation. 82 ;;; Modes 3:6 allowed. 83 84 define internal i32 @error_atomic_rmw_add_8(i32 %iptr, i32 %v) { 85 entry: 86 %trunc = trunc i32 %v to i8 87 %ptr = inttoptr i32 %iptr to i8* 88 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 1, i8* %ptr, i8 %trunc, i32 1) 89 %a_ext = zext i8 %a to i32 90 ret i32 %a_ext 91 } 92 ; CHECK: Unexpected memory ordering for AtomicRMW 93 94 define internal i64 @error_atomic_rmw_add_64(i32 %iptr, i64 %v) { 95 entry: 96 %ptr = inttoptr i32 %iptr to i64* 97 %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 7) 98 ret i64 %a 99 } 100 ; CHECK: Unexpected memory ordering for AtomicRMW 101 102 define internal i32 @error_atomic_rmw_add_16(i32 %iptr, i32 %v) { 103 entry: 104 %trunc = trunc i32 %v to i16 105 %ptr = inttoptr i32 %iptr to i16* 106 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 0, i16* %ptr, i16 %trunc, i32 6) 107 %a_ext = zext i16 %a to i32 108 ret i32 %a_ext 109 } 110 ; CHECK: Unknown AtomicRMW operation 111 112 define internal i32 @error_atomic_rmw_add_32(i32 %iptr, i32 %v) { 113 entry: 114 %ptr = inttoptr i32 %iptr to i32* 115 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 7, i32* %ptr, i32 %v, i32 6) 116 ret i32 %a 117 } 118 ; CHECK: Unknown AtomicRMW operation 119 120 define internal i32 @error_atomic_rmw_add_32_max(i32 %iptr, i32 %v) { 121 entry: 122 %ptr = inttoptr i32 %iptr to i32* 123 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 4294967295, i32* %ptr, i32 %v, i32 6) 124 ret i32 %a 125 } 126 ; CHECK: Unknown AtomicRMW operation 127 128 ;;; Cmpxchg 129 130 define internal i32 @error_atomic_cmpxchg_32_success(i32 %iptr, i32 %expected, 131 i32 %desired) { 132 entry: 133 %ptr = inttoptr i32 %iptr to i32* 134 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 135 i32 %desired, i32 0, i32 6) 136 ret i32 %old 137 } 138 ; CHECK: Unexpected memory ordering for AtomicCmpxchg 139 140 define internal i32 @error_atomic_cmpxchg_32_failure(i32 %iptr, i32 %expected, 141 i32 %desired) { 142 entry: 143 %ptr = inttoptr i32 %iptr to i32* 144 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 145 i32 %desired, i32 6, i32 0) 146 ret i32 %old 147 } 148 ; CHECK: Unexpected memory ordering for AtomicCmpxchg 149 150 define internal i64 @error_atomic_cmpxchg_64_failure(i32 %iptr, i64 %expected, 151 i64 %desired) { 152 entry: 153 %ptr = inttoptr i32 %iptr to i64* 154 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, 155 i64 %desired, i32 4, i32 1) 156 ret i64 %old 157 } 158 ; CHECK: Unexpected memory ordering for AtomicCmpxchg 159 160 ;;; Fence and is-lock-free. 161 162 define internal void @error_atomic_fence() { 163 entry: 164 call void @llvm.nacl.atomic.fence(i32 0) 165 ret void 166 } 167 ; CHECK: Unexpected memory ordering for AtomicFence 168 169 define internal i32 @error_atomic_is_lock_free_var(i32 %iptr, i32 %bs) { 170 entry: 171 %ptr = inttoptr i32 %iptr to i8* 172 %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 %bs, i8* %ptr) 173 %r = zext i1 %i to i32 174 ret i32 %r 175 } 176 ; CHECK: AtomicIsLockFree byte size should be compile-time const 177 178 179 ;;; Test bad non-constant memory ordering values. 180 181 define internal i32 @error_atomic_load_8_nonconst(i32 %iptr) { 182 entry: 183 %ptr = inttoptr i32 %iptr to i8* 184 %i = call i8 @llvm.nacl.atomic.load.i8(i8* %ptr, i32 %iptr) 185 %r = zext i8 %i to i32 186 ret i32 %r 187 } 188 ; CHECK: Unexpected memory ordering for AtomicLoad 189 190 define internal void @error_atomic_store_32_nonconst(i32 %iptr, i32 %v) { 191 entry: 192 %ptr = inttoptr i32 %iptr to i32* 193 call void @llvm.nacl.atomic.store.i32(i32 %v, i32* %ptr, i32 %v) 194 ret void 195 } 196 ; CHECK: Unexpected memory ordering for AtomicStore 197 198 define internal i32 @error_atomic_rmw_add_8_nonconst(i32 %iptr, i32 %v) { 199 entry: 200 %trunc = trunc i32 %v to i8 201 %ptr = inttoptr i32 %iptr to i8* 202 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 1, i8* %ptr, i8 %trunc, i32 %iptr) 203 %a_ext = zext i8 %a to i32 204 ret i32 %a_ext 205 } 206 ; CHECK: Unexpected memory ordering for AtomicRMW 207 208 define internal i32 @error_atomic_cmpxchg_32_success_nonconst_1(i32 %iptr, i32 %expected, 209 i32 %desired) { 210 entry: 211 %ptr = inttoptr i32 %iptr to i32* 212 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 213 i32 %desired, i32 %iptr, i32 6) 214 ret i32 %old 215 } 216 ; CHECK: Unexpected memory ordering for AtomicCmpxchg 217 218 define internal i32 @error_atomic_cmpxchg_32_success_nonconst_2(i32 %iptr, i32 %expected, 219 i32 %desired) { 220 entry: 221 %ptr = inttoptr i32 %iptr to i32* 222 %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, 223 i32 %desired, i32 6, i32 %iptr) 224 ret i32 %old 225 } 226 ; CHECK: Unexpected memory ordering for AtomicCmpxchg 227 228 define internal void @error_atomic_fence_nonconst(i32 %v) { 229 entry: 230 call void @llvm.nacl.atomic.fence(i32 %v) 231 ret void 232 } 233 ; CHECK: Unexpected memory ordering for AtomicFence 234