| ... | ... | @@ -2236,6 +2236,29 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { |
| 2236 | 2236 | return resume_bb; |
| 2237 | 2237 | } |
| 2238 | 2238 | |
| 2239 | static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val, |
| 2240 | LLVMAtomicOrdering order) |
| 2241 | { |
| 2242 | if (g->is_single_threaded) { |
| 2243 | LLVMValueRef loaded = LLVMBuildLoad(g->builder, ptr, ""); |
| 2244 | LLVMValueRef modified; |
| 2245 | switch (op) { |
| 2246 | case LLVMAtomicRMWBinOpXchg: |
| 2247 | modified = val; |
| 2248 | break; |
| 2249 | case LLVMAtomicRMWBinOpXor: |
| 2250 | modified = LLVMBuildXor(g->builder, loaded, val, ""); |
| 2251 | break; |
| 2252 | default: |
| 2253 | zig_unreachable(); |
| 2254 | } |
| 2255 | LLVMBuildStore(g->builder, modified, ptr); |
| 2256 | return loaded; |
| 2257 | } else { |
| 2258 | return LLVMBuildAtomicRMW(g->builder, op, ptr, val, order, false); |
| 2259 | } |
| 2260 | } |
| 2261 | |
| 2239 | 2262 | static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2240 | 2263 | IrInstructionReturnBegin *instruction) |
| 2241 | 2264 | { |
| ... | ... | @@ -2259,8 +2282,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, |
| 2259 | 2282 | |
| 2260 | 2283 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); |
| 2261 | 2284 | LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref); |
| 2262 | | LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr, |
| 2263 | | all_ones, LLVMAtomicOrderingAcquire, g->is_single_threaded); |
| 2285 | LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr, |
| 2286 | all_ones, LLVMAtomicOrderingAcquire); |
| 2264 | 2287 | |
| 2265 | 2288 | LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn"); |
| 2266 | 2289 | LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn"); |
| ... | ... | @@ -5278,7 +5301,8 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, |
| 5278 | 5301 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr, |
| 5279 | 5302 | LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), ""); |
| 5280 | 5303 | LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, ""); |
| 5281 | | LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, false); |
| 5304 | LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, |
| 5305 | g->is_single_threaded); |
| 5282 | 5306 | return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); |
| 5283 | 5307 | } |
| 5284 | 5308 | |
| ... | ... | @@ -5441,8 +5465,8 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns |
| 5441 | 5465 | LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, ""); |
| 5442 | 5466 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); |
| 5443 | 5467 | |
| 5444 | | LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val, |
| 5445 | | LLVMAtomicOrderingRelease, g->is_single_threaded); |
| 5468 | LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val, |
| 5469 | LLVMAtomicOrderingRelease); |
| 5446 | 5470 | |
| 5447 | 5471 | LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CancelSuspend"); |
| 5448 | 5472 | LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn"); |