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 @@...@@ -15,7 +15,6 @@
15 * compile error for copying a frame15 * compile error for copying a frame
16 * compile error for resuming a const frame pointer16 * compile error for resuming a const frame pointer
17 * runtime safety enabling/disabling scope has to be coordinated across resume/await/calls/return17 * runtime safety enabling/disabling scope has to be coordinated across resume/await/calls/return
18 * await in single-threaded mode
19 * calling a generic function which is async18 * calling a generic function which is async
20 * make sure `await @asyncCall` and `await async` are handled correctly.19 * make sure `await @asyncCall` and `await async` are handled correctly.
21 * allow @asyncCall with a real @Frame(func) (the point of this is result pointer)20 * allow @asyncCall with a real @Frame(func) (the point of this is result pointer)
...@@ -28,7 +27,6 @@...@@ -28,7 +27,6 @@
28 - suspend27 - suspend
29 - resume28 - resume
30 - anyframe, anyframe->T29 - anyframe, anyframe->T
31 * safety for double await
32 * call graph analysis to have fewer stack trace frames30 * call graph analysis to have fewer stack trace frames
33 * grep for "coroutine" and "coro" and replace all that nomenclature with "async functions"31 * grep for "coroutine" and "coro" and replace all that nomenclature with "async functions"
34 * when there are multiple calls to async functions in a function, reuse the same frame buffer, so that the32 * 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) {...@@ -2236,6 +2236,29 @@ static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
2236 return resume_bb;2236 return resume_bb;
2237}2237}
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
2239static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,2262static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2240 IrInstructionReturnBegin *instruction)2263 IrInstructionReturnBegin *instruction)
2241{2264{
...@@ -2259,8 +2282,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,...@@ -2259,8 +2282,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
22592282
2260 LLVMValueRef zero = LLVMConstNull(usize_type_ref);2283 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
2261 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);2284 LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref);
2262 LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,2285 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXor, g->cur_async_awaiter_ptr,
2263 all_ones, LLVMAtomicOrderingAcquire, g->is_single_threaded);2286 all_ones, LLVMAtomicOrderingAcquire);
22642287
2265 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");2288 LLVMBasicBlockRef bad_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadReturn");
2266 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");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,7 +5301,8 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
5278 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,5301 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
5279 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");5302 LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), "");
5280 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, "");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 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");5306 return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), "");
5283}5307}
52845308
...@@ -5441,8 +5465,8 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns...@@ -5441,8 +5465,8 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
5441 LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, "");5465 LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, "");
5442 LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, "");5466 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,5468 LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val,
5445 LLVMAtomicOrderingRelease, g->is_single_threaded);5469 LLVMAtomicOrderingRelease);
54465470
5447 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CancelSuspend");5471 LLVMBasicBlockRef complete_suspend_block = LLVMAppendBasicBlock(g->cur_fn_val, "CancelSuspend");
5448 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");5472 LLVMBasicBlockRef early_return_block = LLVMAppendBasicBlock(g->cur_fn_val, "EarlyReturn");