/src/WasmEdge/lib/llvm/compiler/threadInstr.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include "compiler/function_compiler.h" |
5 | | |
6 | | namespace WasmEdge { |
7 | | |
8 | | Expect<void> |
9 | 238 | FunctionCompiler::compileAtomicOp(const AST::Instruction &Instr) noexcept { |
10 | 238 | switch (Instr.getOpCode()) { |
11 | 192 | case OpCode::Atomic__fence: |
12 | 192 | compileMemoryFence(); |
13 | 192 | break; |
14 | 39 | case OpCode::Memory__atomic__notify: |
15 | 39 | compileAtomicNotify(Instr.getTargetIndex(), Instr.getMemoryOffset()); |
16 | 39 | break; |
17 | 5 | case OpCode::Memory__atomic__wait32: |
18 | 5 | compileAtomicWait(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
19 | 5 | Context.Int32Ty, 32); |
20 | 5 | break; |
21 | 2 | case OpCode::Memory__atomic__wait64: |
22 | 2 | compileAtomicWait(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
23 | 2 | Context.Int64Ty, 64); |
24 | 2 | break; |
25 | 0 | case OpCode::I32__atomic__load: |
26 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
27 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int32Ty, |
28 | 0 | true); |
29 | 0 | break; |
30 | 0 | case OpCode::I64__atomic__load: |
31 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
32 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int64Ty, |
33 | 0 | true); |
34 | 0 | break; |
35 | 0 | case OpCode::I32__atomic__load8_u: |
36 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
37 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int8Ty); |
38 | 0 | break; |
39 | 0 | case OpCode::I32__atomic__load16_u: |
40 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
41 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int16Ty); |
42 | 0 | break; |
43 | 0 | case OpCode::I64__atomic__load8_u: |
44 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
45 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int8Ty); |
46 | 0 | break; |
47 | 0 | case OpCode::I64__atomic__load16_u: |
48 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
49 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int16Ty); |
50 | 0 | break; |
51 | 0 | case OpCode::I64__atomic__load32_u: |
52 | 0 | compileAtomicLoad(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
53 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int32Ty); |
54 | 0 | break; |
55 | 0 | case OpCode::I32__atomic__store: |
56 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
57 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int32Ty, |
58 | 0 | true); |
59 | 0 | break; |
60 | 0 | case OpCode::I64__atomic__store: |
61 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
62 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int64Ty, |
63 | 0 | true); |
64 | 0 | break; |
65 | 0 | case OpCode::I32__atomic__store8: |
66 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
67 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int8Ty, |
68 | 0 | true); |
69 | 0 | break; |
70 | 0 | case OpCode::I32__atomic__store16: |
71 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
72 | 0 | Instr.getMemoryAlign(), Context.Int32Ty, Context.Int16Ty, |
73 | 0 | true); |
74 | 0 | break; |
75 | 0 | case OpCode::I64__atomic__store8: |
76 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
77 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int8Ty, |
78 | 0 | true); |
79 | 0 | break; |
80 | 0 | case OpCode::I64__atomic__store16: |
81 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
82 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int16Ty, |
83 | 0 | true); |
84 | 0 | break; |
85 | 0 | case OpCode::I64__atomic__store32: |
86 | 0 | compileAtomicStore(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
87 | 0 | Instr.getMemoryAlign(), Context.Int64Ty, Context.Int32Ty, |
88 | 0 | true); |
89 | 0 | break; |
90 | 0 | case OpCode::I32__atomic__rmw__add: |
91 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
92 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
93 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
94 | 0 | break; |
95 | 0 | case OpCode::I64__atomic__rmw__add: |
96 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
97 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
98 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
99 | 0 | break; |
100 | 0 | case OpCode::I32__atomic__rmw8__add_u: |
101 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
102 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
103 | 0 | Context.Int32Ty, Context.Int8Ty); |
104 | 0 | break; |
105 | 0 | case OpCode::I32__atomic__rmw16__add_u: |
106 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
107 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
108 | 0 | Context.Int32Ty, Context.Int16Ty); |
109 | 0 | break; |
110 | 0 | case OpCode::I64__atomic__rmw8__add_u: |
111 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
112 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
113 | 0 | Context.Int64Ty, Context.Int8Ty); |
114 | 0 | break; |
115 | 0 | case OpCode::I64__atomic__rmw16__add_u: |
116 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
117 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
118 | 0 | Context.Int64Ty, Context.Int16Ty); |
119 | 0 | break; |
120 | 0 | case OpCode::I64__atomic__rmw32__add_u: |
121 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
122 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAdd, |
123 | 0 | Context.Int64Ty, Context.Int32Ty); |
124 | 0 | break; |
125 | 0 | case OpCode::I32__atomic__rmw__sub: |
126 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
127 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
128 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
129 | 0 | break; |
130 | 0 | case OpCode::I64__atomic__rmw__sub: |
131 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
132 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
133 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
134 | 0 | break; |
135 | 0 | case OpCode::I32__atomic__rmw8__sub_u: |
136 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
137 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
138 | 0 | Context.Int32Ty, Context.Int8Ty); |
139 | 0 | break; |
140 | 0 | case OpCode::I32__atomic__rmw16__sub_u: |
141 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
142 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
143 | 0 | Context.Int32Ty, Context.Int16Ty); |
144 | 0 | break; |
145 | 0 | case OpCode::I64__atomic__rmw8__sub_u: |
146 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
147 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
148 | 0 | Context.Int64Ty, Context.Int8Ty); |
149 | 0 | break; |
150 | 0 | case OpCode::I64__atomic__rmw16__sub_u: |
151 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
152 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
153 | 0 | Context.Int64Ty, Context.Int16Ty); |
154 | 0 | break; |
155 | 0 | case OpCode::I64__atomic__rmw32__sub_u: |
156 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
157 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpSub, |
158 | 0 | Context.Int64Ty, Context.Int32Ty); |
159 | 0 | break; |
160 | 0 | case OpCode::I32__atomic__rmw__and: |
161 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
162 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
163 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
164 | 0 | break; |
165 | 0 | case OpCode::I64__atomic__rmw__and: |
166 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
167 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
168 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
169 | 0 | break; |
170 | 0 | case OpCode::I32__atomic__rmw8__and_u: |
171 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
172 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
173 | 0 | Context.Int32Ty, Context.Int8Ty); |
174 | 0 | break; |
175 | 0 | case OpCode::I32__atomic__rmw16__and_u: |
176 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
177 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
178 | 0 | Context.Int32Ty, Context.Int16Ty); |
179 | 0 | break; |
180 | 0 | case OpCode::I64__atomic__rmw8__and_u: |
181 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
182 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
183 | 0 | Context.Int64Ty, Context.Int8Ty); |
184 | 0 | break; |
185 | 0 | case OpCode::I64__atomic__rmw16__and_u: |
186 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
187 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
188 | 0 | Context.Int64Ty, Context.Int16Ty); |
189 | 0 | break; |
190 | 0 | case OpCode::I64__atomic__rmw32__and_u: |
191 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
192 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpAnd, |
193 | 0 | Context.Int64Ty, Context.Int32Ty); |
194 | 0 | break; |
195 | 0 | case OpCode::I32__atomic__rmw__or: |
196 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
197 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
198 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
199 | 0 | break; |
200 | 0 | case OpCode::I64__atomic__rmw__or: |
201 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
202 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
203 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
204 | 0 | break; |
205 | 0 | case OpCode::I32__atomic__rmw8__or_u: |
206 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
207 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
208 | 0 | Context.Int32Ty, Context.Int8Ty); |
209 | 0 | break; |
210 | 0 | case OpCode::I32__atomic__rmw16__or_u: |
211 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
212 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
213 | 0 | Context.Int32Ty, Context.Int16Ty); |
214 | 0 | break; |
215 | 0 | case OpCode::I64__atomic__rmw8__or_u: |
216 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
217 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
218 | 0 | Context.Int64Ty, Context.Int8Ty); |
219 | 0 | break; |
220 | 0 | case OpCode::I64__atomic__rmw16__or_u: |
221 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
222 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
223 | 0 | Context.Int64Ty, Context.Int16Ty); |
224 | 0 | break; |
225 | 0 | case OpCode::I64__atomic__rmw32__or_u: |
226 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
227 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpOr, |
228 | 0 | Context.Int64Ty, Context.Int32Ty); |
229 | 0 | break; |
230 | 0 | case OpCode::I32__atomic__rmw__xor: |
231 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
232 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
233 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
234 | 0 | break; |
235 | 0 | case OpCode::I64__atomic__rmw__xor: |
236 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
237 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
238 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
239 | 0 | break; |
240 | 0 | case OpCode::I32__atomic__rmw8__xor_u: |
241 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
242 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
243 | 0 | Context.Int32Ty, Context.Int8Ty); |
244 | 0 | break; |
245 | 0 | case OpCode::I32__atomic__rmw16__xor_u: |
246 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
247 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
248 | 0 | Context.Int32Ty, Context.Int16Ty); |
249 | 0 | break; |
250 | 0 | case OpCode::I64__atomic__rmw8__xor_u: |
251 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
252 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
253 | 0 | Context.Int64Ty, Context.Int8Ty); |
254 | 0 | break; |
255 | 0 | case OpCode::I64__atomic__rmw16__xor_u: |
256 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
257 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
258 | 0 | Context.Int64Ty, Context.Int16Ty); |
259 | 0 | break; |
260 | 0 | case OpCode::I64__atomic__rmw32__xor_u: |
261 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
262 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXor, |
263 | 0 | Context.Int64Ty, Context.Int32Ty); |
264 | 0 | break; |
265 | 0 | case OpCode::I32__atomic__rmw__xchg: |
266 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
267 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
268 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
269 | 0 | break; |
270 | 0 | case OpCode::I64__atomic__rmw__xchg: |
271 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
272 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
273 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
274 | 0 | break; |
275 | 0 | case OpCode::I32__atomic__rmw8__xchg_u: |
276 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
277 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
278 | 0 | Context.Int32Ty, Context.Int8Ty); |
279 | 0 | break; |
280 | 0 | case OpCode::I32__atomic__rmw16__xchg_u: |
281 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
282 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
283 | 0 | Context.Int32Ty, Context.Int16Ty); |
284 | 0 | break; |
285 | 0 | case OpCode::I64__atomic__rmw8__xchg_u: |
286 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
287 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
288 | 0 | Context.Int64Ty, Context.Int8Ty); |
289 | 0 | break; |
290 | 0 | case OpCode::I64__atomic__rmw16__xchg_u: |
291 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
292 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
293 | 0 | Context.Int64Ty, Context.Int16Ty); |
294 | 0 | break; |
295 | 0 | case OpCode::I64__atomic__rmw32__xchg_u: |
296 | 0 | compileAtomicRMWOp(Instr.getTargetIndex(), Instr.getMemoryOffset(), |
297 | 0 | Instr.getMemoryAlign(), LLVMAtomicRMWBinOpXchg, |
298 | 0 | Context.Int64Ty, Context.Int32Ty); |
299 | 0 | break; |
300 | 0 | case OpCode::I32__atomic__rmw__cmpxchg: |
301 | 0 | compileAtomicCompareExchange( |
302 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
303 | 0 | Context.Int32Ty, Context.Int32Ty, true); |
304 | 0 | break; |
305 | 0 | case OpCode::I64__atomic__rmw__cmpxchg: |
306 | 0 | compileAtomicCompareExchange( |
307 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
308 | 0 | Context.Int64Ty, Context.Int64Ty, true); |
309 | 0 | break; |
310 | 0 | case OpCode::I32__atomic__rmw8__cmpxchg_u: |
311 | 0 | compileAtomicCompareExchange( |
312 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
313 | 0 | Context.Int32Ty, Context.Int8Ty); |
314 | 0 | break; |
315 | 0 | case OpCode::I32__atomic__rmw16__cmpxchg_u: |
316 | 0 | compileAtomicCompareExchange( |
317 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
318 | 0 | Context.Int32Ty, Context.Int16Ty); |
319 | 0 | break; |
320 | 0 | case OpCode::I64__atomic__rmw8__cmpxchg_u: |
321 | 0 | compileAtomicCompareExchange( |
322 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
323 | 0 | Context.Int64Ty, Context.Int8Ty); |
324 | 0 | break; |
325 | 0 | case OpCode::I64__atomic__rmw16__cmpxchg_u: |
326 | 0 | compileAtomicCompareExchange( |
327 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
328 | 0 | Context.Int64Ty, Context.Int16Ty); |
329 | 0 | break; |
330 | 0 | case OpCode::I64__atomic__rmw32__cmpxchg_u: |
331 | 0 | compileAtomicCompareExchange( |
332 | 0 | Instr.getTargetIndex(), Instr.getMemoryOffset(), Instr.getMemoryAlign(), |
333 | 0 | Context.Int64Ty, Context.Int32Ty); |
334 | 0 | break; |
335 | | |
336 | 0 | default: |
337 | 0 | assumingUnreachable(); |
338 | 238 | } |
339 | 238 | return {}; |
340 | 238 | } |
341 | | |
342 | | void FunctionCompiler::compileAtomicCheckOffsetAlignment( |
343 | 46 | LLVM::Value Offset, LLVM::Type IntType) noexcept { |
344 | 46 | const auto BitWidth = IntType.getIntegerBitWidth(); |
345 | 46 | auto BWMask = LLContext.getInt64((BitWidth >> 3) - 1); |
346 | 46 | auto Value = Builder.createAnd(Offset, BWMask); |
347 | 46 | auto OkBB = LLVM::BasicBlock::create(LLContext, F.Fn, "address_align_ok"); |
348 | 46 | auto IsAddressAligned = |
349 | 46 | Builder.createLikely(Builder.createICmpEQ(Value, LLContext.getInt64(0))); |
350 | 46 | Builder.createCondBr(IsAddressAligned, OkBB, |
351 | 46 | getTrapBB(ErrCode::Value::UnalignedAtomicAccess)); |
352 | | |
353 | 46 | Builder.positionAtEnd(OkBB); |
354 | 46 | } |
355 | | |
356 | 192 | void FunctionCompiler::compileMemoryFence() noexcept { |
357 | 192 | Builder.createFence(LLVMAtomicOrderingSequentiallyConsistent); |
358 | 192 | } |
359 | | |
360 | | void FunctionCompiler::compileAtomicNotify(unsigned MemoryIndex, |
361 | 39 | uint64_t MemoryOffset) noexcept { |
362 | 39 | auto Count = Builder.createZExt(stackPop(), Context.Int64Ty); |
363 | 39 | auto Offset = Builder.createZExt(stackPop(), Context.Int64Ty); |
364 | 39 | if (MemoryOffset != 0) { |
365 | 32 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
366 | 32 | } |
367 | 39 | compileAtomicCheckOffsetAlignment(Offset, Context.Int32Ty); |
368 | 39 | stackPush(Builder.createTrunc( |
369 | 39 | Builder.createCall( |
370 | 39 | Context.getIntrinsic( |
371 | 39 | Builder, Executable::Intrinsics::kMemAtomicNotify, |
372 | 39 | LLVM::Type::getFunctionType( |
373 | 39 | Context.Int64Ty, |
374 | 39 | {Context.Int32Ty, Context.Int64Ty, Context.Int64Ty}, false)), |
375 | 39 | {LLContext.getInt32(MemoryIndex), Offset, Count}), |
376 | 39 | Context.MemoryAddrTypes[MemoryIndex])); |
377 | 39 | } |
378 | | |
379 | | void FunctionCompiler::compileAtomicWait(unsigned MemoryIndex, |
380 | | uint64_t MemoryOffset, |
381 | | LLVM::Type TargetType, |
382 | 7 | uint32_t BitWidth) noexcept { |
383 | 7 | auto Timeout = stackPop(); |
384 | 7 | auto ExpectedValue = Builder.createZExtOrTrunc(stackPop(), Context.Int64Ty); |
385 | 7 | auto Offset = Builder.createZExt(stackPop(), Context.Int64Ty); |
386 | 7 | if (MemoryOffset != 0) { |
387 | 3 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
388 | 3 | } |
389 | 7 | compileAtomicCheckOffsetAlignment(Offset, TargetType); |
390 | 7 | stackPush(Builder.createTrunc( |
391 | 7 | Builder.createCall( |
392 | 7 | Context.getIntrinsic( |
393 | 7 | Builder, Executable::Intrinsics::kMemAtomicWait, |
394 | 7 | LLVM::Type::getFunctionType(Context.Int64Ty, |
395 | 7 | {Context.Int32Ty, Context.Int64Ty, |
396 | 7 | Context.Int64Ty, Context.Int64Ty, |
397 | 7 | Context.Int32Ty}, |
398 | 7 | false)), |
399 | 7 | {LLContext.getInt32(MemoryIndex), Offset, ExpectedValue, Timeout, |
400 | 7 | LLContext.getInt32(BitWidth)}), |
401 | 7 | Context.MemoryAddrTypes[MemoryIndex])); |
402 | 7 | } |
403 | | |
404 | | void FunctionCompiler::compileAtomicLoad(unsigned MemoryIndex, |
405 | | uint64_t MemoryOffset, |
406 | | unsigned Alignment, LLVM::Type IntType, |
407 | | LLVM::Type TargetType, |
408 | 0 | bool Signed) noexcept { |
409 | |
|
410 | 0 | auto Offset = Builder.createZExt(Stack.back(), Context.Int64Ty); |
411 | 0 | if (MemoryOffset != 0) { |
412 | 0 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
413 | 0 | } |
414 | 0 | compileAtomicCheckOffsetAlignment(Offset, TargetType); |
415 | 0 | auto VPtr = Builder.createInBoundsGEP1( |
416 | 0 | Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Offset); |
417 | |
|
418 | 0 | auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); |
419 | 0 | auto Load = switchEndian(Builder.createLoad(TargetType, Ptr, true)); |
420 | 0 | Load.setAlignment(1 << Alignment); |
421 | 0 | Load.setOrdering(LLVMAtomicOrderingSequentiallyConsistent); |
422 | |
|
423 | 0 | if (Signed) { |
424 | 0 | Stack.back() = Builder.createSExt(Load, IntType); |
425 | 0 | } else { |
426 | 0 | Stack.back() = Builder.createZExt(Load, IntType); |
427 | 0 | } |
428 | 0 | } |
429 | | |
430 | | void FunctionCompiler::compileAtomicStore(unsigned MemoryIndex, |
431 | | uint64_t MemoryOffset, |
432 | | unsigned Alignment, LLVM::Type, |
433 | | LLVM::Type TargetType, |
434 | 0 | bool Signed) noexcept { |
435 | 0 | auto V = stackPop(); |
436 | |
|
437 | 0 | if (Signed) { |
438 | 0 | V = Builder.createSExtOrTrunc(V, TargetType); |
439 | 0 | } else { |
440 | 0 | V = Builder.createZExtOrTrunc(V, TargetType); |
441 | 0 | } |
442 | 0 | V = switchEndian(V); |
443 | 0 | auto Offset = Builder.createZExt(Stack.back(), Context.Int64Ty); |
444 | 0 | if (MemoryOffset != 0) { |
445 | 0 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
446 | 0 | } |
447 | 0 | compileAtomicCheckOffsetAlignment(Offset, TargetType); |
448 | 0 | auto VPtr = Builder.createInBoundsGEP1( |
449 | 0 | Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Offset); |
450 | 0 | auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); |
451 | 0 | auto Store = Builder.createStore(V, Ptr, true); |
452 | 0 | Store.setAlignment(1 << Alignment); |
453 | 0 | Store.setOrdering(LLVMAtomicOrderingSequentiallyConsistent); |
454 | 0 | } |
455 | | |
456 | | void FunctionCompiler::compileAtomicRMWOp( |
457 | | unsigned MemoryIndex, uint64_t MemoryOffset, |
458 | | [[maybe_unused]] unsigned Alignment, LLVMAtomicRMWBinOp BinOp, |
459 | 0 | LLVM::Type IntType, LLVM::Type TargetType, bool Signed) noexcept { |
460 | 0 | auto Value = Builder.createSExtOrTrunc(stackPop(), TargetType); |
461 | 0 | auto Offset = Builder.createZExt(Stack.back(), Context.Int64Ty); |
462 | 0 | if (MemoryOffset != 0) { |
463 | 0 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
464 | 0 | } |
465 | 0 | compileAtomicCheckOffsetAlignment(Offset, TargetType); |
466 | 0 | auto VPtr = Builder.createInBoundsGEP1( |
467 | 0 | Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Offset); |
468 | 0 | auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); |
469 | |
|
470 | 0 | LLVM::Value Ret; |
471 | | if constexpr (Endian::native == Endian::big) { |
472 | | if (BinOp == LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpAdd || |
473 | | BinOp == LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpSub) { |
474 | | auto AtomicBB = LLVM::BasicBlock::create(LLContext, F.Fn, "atomic.rmw"); |
475 | | auto OkBB = LLVM::BasicBlock::create(LLContext, F.Fn, "atomic.rmw.ok"); |
476 | | Builder.createBr(AtomicBB); |
477 | | Builder.positionAtEnd(AtomicBB); |
478 | | |
479 | | auto Load = Builder.createLoad(TargetType, Ptr, true); |
480 | | Load.setOrdering(LLVMAtomicOrderingMonotonic); |
481 | | Load.setAlignment(1 << Alignment); |
482 | | |
483 | | LLVM::Value New; |
484 | | if (BinOp == LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpAdd) |
485 | | New = Builder.createAdd(switchEndian(Load), Value); |
486 | | else if (BinOp == LLVMAtomicRMWBinOp::LLVMAtomicRMWBinOpSub) { |
487 | | New = Builder.createSub(switchEndian(Load), Value); |
488 | | } else { |
489 | | assumingUnreachable(); |
490 | | } |
491 | | New = switchEndian(New); |
492 | | |
493 | | auto Exchange = Builder.createAtomicCmpXchg( |
494 | | Ptr, Load, New, LLVMAtomicOrderingSequentiallyConsistent, |
495 | | LLVMAtomicOrderingSequentiallyConsistent); |
496 | | |
497 | | Ret = Builder.createExtractValue(Exchange, 0); |
498 | | auto Success = Builder.createExtractValue(Exchange, 1); |
499 | | Builder.createCondBr(Success, OkBB, AtomicBB); |
500 | | Builder.positionAtEnd(OkBB); |
501 | | } else { |
502 | | Ret = Builder.createAtomicRMW(BinOp, Ptr, switchEndian(Value), |
503 | | LLVMAtomicOrderingSequentiallyConsistent); |
504 | | } |
505 | 0 | } else { |
506 | 0 | Ret = Builder.createAtomicRMW(BinOp, Ptr, switchEndian(Value), |
507 | 0 | LLVMAtomicOrderingSequentiallyConsistent); |
508 | 0 | } |
509 | 0 | Ret = switchEndian(Ret); |
510 | | #if LLVM_VERSION_MAJOR >= 13 |
511 | | Ret.setAlignment(1 << Alignment); |
512 | | #endif |
513 | 0 | if (Signed) { |
514 | 0 | Stack.back() = Builder.createSExt(Ret, IntType); |
515 | 0 | } else { |
516 | 0 | Stack.back() = Builder.createZExt(Ret, IntType); |
517 | 0 | } |
518 | 0 | } |
519 | | |
520 | | void FunctionCompiler::compileAtomicCompareExchange( |
521 | | unsigned MemoryIndex, uint64_t MemoryOffset, |
522 | | [[maybe_unused]] unsigned Alignment, LLVM::Type IntType, |
523 | 0 | LLVM::Type TargetType, bool Signed) noexcept { |
524 | |
|
525 | 0 | auto Replacement = Builder.createSExtOrTrunc(stackPop(), TargetType); |
526 | 0 | auto Expected = Builder.createSExtOrTrunc(stackPop(), TargetType); |
527 | 0 | auto Offset = Builder.createZExt(Stack.back(), Context.Int64Ty); |
528 | 0 | if (MemoryOffset != 0) { |
529 | 0 | Offset = Builder.createAdd(Offset, LLContext.getInt64(MemoryOffset)); |
530 | 0 | } |
531 | 0 | compileAtomicCheckOffsetAlignment(Offset, TargetType); |
532 | 0 | auto VPtr = Builder.createInBoundsGEP1( |
533 | 0 | Context.Int8Ty, Context.getMemory(Builder, ExecCtx, MemoryIndex), Offset); |
534 | 0 | auto Ptr = Builder.createBitCast(VPtr, TargetType.getPointerTo()); |
535 | |
|
536 | 0 | auto Ret = Builder.createAtomicCmpXchg( |
537 | 0 | Ptr, switchEndian(Expected), switchEndian(Replacement), |
538 | 0 | LLVMAtomicOrderingSequentiallyConsistent, |
539 | 0 | LLVMAtomicOrderingSequentiallyConsistent); |
540 | | #if LLVM_VERSION_MAJOR >= 13 |
541 | | Ret.setAlignment(1 << Alignment); |
542 | | #endif |
543 | 0 | auto OldVal = Builder.createExtractValue(Ret, 0); |
544 | 0 | OldVal = switchEndian(OldVal); |
545 | 0 | if (Signed) { |
546 | 0 | Stack.back() = Builder.createSExt(OldVal, IntType); |
547 | 0 | } else { |
548 | 0 | Stack.back() = Builder.createZExt(OldVal, IntType); |
549 | 0 | } |
550 | 0 | } |
551 | | |
552 | | } // namespace WasmEdge |