authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-08 12:30:22-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-08 12:30:22-04:00
log8d4cb852856631543aa961a6149b9a22021a1573
tree2ced15044153a7fcc810a08443f93e23897e1f49
parentd813805f775b74416337ce8f1bd7b2e789caf185
signaturelock-open Commit is signed but in an unrecognized format.

async functions in single threaded mode do not use atomic ops


2 files changed, 29 insertions(+), 7 deletions(-)

BRANCH_TODO-2
......@@ -15,7 +15,6 @@
1515 * compile error for copying a frame
1616 * compile error for resuming a const frame pointer
1717 * runtime safety enabling/disabling scope has to be coordinated across resume/await/calls/return
18 * await in single-threaded mode
1918 * calling a generic function which is async
2019 * make sure `await @asyncCall` and `await async` are handled correctly.
2120 * allow @asyncCall with a real @Frame(func) (the point of this is result pointer)
......@@ -28,7 +27,6 @@
2827 - suspend
2928 - resume
3029 - anyframe, anyframe->T
31 * safety for double await
3230 * call graph analysis to have fewer stack trace frames
3331 * grep for "coroutine" and "coro" and replace all that nomenclature with "async functions"
3432 * when there are multiple calls to async functions in a function, reuse the same frame buffer, so that the
src/codegen.cpp+29-5
......@@ -2236,6 +2236,29 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
22362236 return resume_bb;
22372237}
22382238
2239static 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
22392262static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
22402263 IrInstructionReturnBegin *instruction)
22412264{
......@@ -2259,8 +2282,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
22592282
22602283 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
22612284 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);
22642287
22652288 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");
22662289 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");
......@@ -5278,7 +5301,8 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
52785301 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
52795302 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");
52805303 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);
52825306 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
52835307}
52845308
......@@ -5441,8 +5465,8 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
54415465 LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, "");
54425466 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, "");
54435467
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);
54465470
54475471 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CancelSuspend");
54485472 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");