| author | |
| committer | |
| log | 50926341036c3ba377215d1c70c3e97adb07a292 |
| tree | 3c282b9bae56f4bfbf0748af62a4138084b72985 |
| parent | 82d4ebe53a9d86559dee4e82cde97ab26e76a375 |
| signature |
23 files changed, 175 insertions(+), 199 deletions(-)
BRANCH_TODO+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | * grep for "coroutine" and "coro" and replace all that nomenclature with "async functions" | |
| 1 | * zig fmt support for the syntax | |
| 2 | 2 | * alignment of variables not being respected in async functions |
| 3 | 3 | * await of a non async function |
| 4 | 4 | * async call on a non async function |
doc/langref.html.in+20-20| ... | ... | @@ -5968,9 +5968,10 @@ test "global assembly" { |
| 5968 | 5968 | <p>TODO: @atomic rmw</p> |
| 5969 | 5969 | <p>TODO: builtin atomic memory ordering enum</p> |
| 5970 | 5970 | {#header_close#} |
| 5971 | {#header_open|Coroutines#} | |
| 5971 | {#header_open|Async Functions#} | |
| 5972 | 5972 | <p> |
| 5973 | A coroutine is a generalization of a function. | |
| 5973 | An async function is a function whose callsite is split into an {#syntax#}async{#endsyntax#} initiation, | |
| 5974 | followed by an {#syntax#}await{#endsyntax#} completion. They can also be canceled. | |
| 5974 | 5975 | </p> |
| 5975 | 5976 | <p> |
| 5976 | 5977 | When you call a function, it creates a stack frame, |
| ... | ... | @@ -5980,14 +5981,14 @@ test "global assembly" { |
| 5980 | 5981 | until the function returns. |
| 5981 | 5982 | </p> |
| 5982 | 5983 | <p> |
| 5983 | A coroutine is like a function, but it can be suspended | |
| 5984 | An async function is like a function, but it can be suspended | |
| 5984 | 5985 | and resumed any number of times, and then it must be |
| 5985 | explicitly destroyed. When a coroutine suspends, it | |
| 5986 | explicitly destroyed. When an async function suspends, it | |
| 5986 | 5987 | returns to the resumer. |
| 5987 | 5988 | </p> |
| 5988 | {#header_open|Minimal Coroutine Example#} | |
| 5989 | {#header_open|Minimal Async Function Example#} | |
| 5989 | 5990 | <p> |
| 5990 | Declare a coroutine with the {#syntax#}async{#endsyntax#} keyword. | |
| 5991 | Declare an async function with the {#syntax#}async{#endsyntax#} keyword. | |
| 5991 | 5992 | The expression in angle brackets must evaluate to a struct |
| 5992 | 5993 | which has these fields: |
| 5993 | 5994 | </p> |
| ... | ... | @@ -6006,8 +6007,8 @@ test "global assembly" { |
| 6006 | 6007 | the function generic. Zig will infer the allocator type when the async function is called. |
| 6007 | 6008 | </p> |
| 6008 | 6009 | <p> |
| 6009 | Call a coroutine with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets | |
| 6010 | is a pointer to the allocator struct that the coroutine expects. | |
| 6010 | Call an async function with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets | |
| 6011 | is a pointer to the allocator struct that the async function expects. | |
| 6011 | 6012 | </p> |
| 6012 | 6013 | <p> |
| 6013 | 6014 | The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#} |
| ... | ... | @@ -6058,7 +6059,7 @@ const assert = std.debug.assert; |
| 6058 | 6059 | var the_frame: anyframe = undefined; |
| 6059 | 6060 | var result = false; |
| 6060 | 6061 | |
| 6061 | test "coroutine suspend with block" { | |
| 6062 | test "async function suspend with block" { | |
| 6062 | 6063 | _ = async testSuspendBlock(); |
| 6063 | 6064 | std.debug.assert(!result); |
| 6064 | 6065 | resume the_frame; |
| ... | ... | @@ -6074,7 +6075,7 @@ fn testSuspendBlock() void { |
| 6074 | 6075 | } |
| 6075 | 6076 | {#code_end#} |
| 6076 | 6077 | <p> |
| 6077 | Every suspend point in an async function represents a point at which the coroutine | |
| 6078 | Every suspend point in an async function represents a point at which the async function | |
| 6078 | 6079 | could be destroyed. If that happens, {#syntax#}defer{#endsyntax#} expressions that are in |
| 6079 | 6080 | scope are run, as well as {#syntax#}errdefer{#endsyntax#} expressions. |
| 6080 | 6081 | </p> |
| ... | ... | @@ -6083,14 +6084,14 @@ fn testSuspendBlock() void { |
| 6083 | 6084 | </p> |
| 6084 | 6085 | {#header_open|Resuming from Suspend Blocks#} |
| 6085 | 6086 | <p> |
| 6086 | Upon entering a {#syntax#}suspend{#endsyntax#} block, the coroutine is already considered | |
| 6087 | Upon entering a {#syntax#}suspend{#endsyntax#} block, the async function is already considered | |
| 6087 | 6088 | suspended, and can be resumed. For example, if you started another kernel thread, |
| 6088 | 6089 | and had that thread call {#syntax#}resume{#endsyntax#} on the promise handle provided by the |
| 6089 | 6090 | {#syntax#}suspend{#endsyntax#} block, the new thread would begin executing after the suspend |
| 6090 | 6091 | block, while the old thread continued executing the suspend block. |
| 6091 | 6092 | </p> |
| 6092 | 6093 | <p> |
| 6093 | However, the coroutine can be directly resumed from the suspend block, in which case it | |
| 6094 | However, the async function can be directly resumed from the suspend block, in which case it | |
| 6094 | 6095 | never returns to its resumer and continues executing. |
| 6095 | 6096 | </p> |
| 6096 | 6097 | {#code_begin|test#} |
| ... | ... | @@ -6127,8 +6128,8 @@ async fn testResumeFromSuspend(my_result: *i32) void { |
| 6127 | 6128 | If the async function associated with the promise handle has already returned, |
| 6128 | 6129 | then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value. |
| 6129 | 6130 | Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its |
| 6130 | promise handle with the target coroutine. It becomes the target coroutine's responsibility | |
| 6131 | to have ensured that it will be resumed or destroyed. When the target coroutine reaches | |
| 6131 | promise handle with the target async function. It becomes the target async function's responsibility | |
| 6132 | to have ensured that it will be resumed or destroyed. When the target async function reaches | |
| 6132 | 6133 | its return statement, it gives the return value to the awaiter, destroys itself, and then |
| 6133 | 6134 | resumes the awaiter. |
| 6134 | 6135 | </p> |
| ... | ... | @@ -6137,7 +6138,7 @@ async fn testResumeFromSuspend(my_result: *i32) void { |
| 6137 | 6138 | </p> |
| 6138 | 6139 | <p> |
| 6139 | 6140 | {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#}, |
| 6140 | a coroutine can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions. | |
| 6141 | a async function can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions. | |
| 6141 | 6142 | </p> |
| 6142 | 6143 | {#code_begin|test#} |
| 6143 | 6144 | const std = @import("std"); |
| ... | ... | @@ -6146,7 +6147,7 @@ const assert = std.debug.assert; |
| 6146 | 6147 | var the_frame: anyframe = undefined; |
| 6147 | 6148 | var final_result: i32 = 0; |
| 6148 | 6149 | |
| 6149 | test "coroutine await" { | |
| 6150 | test "async function await" { | |
| 6150 | 6151 | seq('a'); |
| 6151 | 6152 | _ = async amain(); |
| 6152 | 6153 | seq('f'); |
| ... | ... | @@ -6188,7 +6189,7 @@ fn seq(c: u8) void { |
| 6188 | 6189 | {#header_close#} |
| 6189 | 6190 | {#header_open|Open Issues#} |
| 6190 | 6191 | <p> |
| 6191 | There are a few issues with coroutines that are considered unresolved. Best be aware of them, | |
| 6192 | There are a few issues with async function that are considered unresolved. Best be aware of them, | |
| 6192 | 6193 | as the situation is likely to change before 1.0.0: |
| 6193 | 6194 | </p> |
| 6194 | 6195 | <ul> |
| ... | ... | @@ -6202,7 +6203,7 @@ fn seq(c: u8) void { |
| 6202 | 6203 | </li> |
| 6203 | 6204 | <li> |
| 6204 | 6205 | Zig does not take advantage of LLVM's allocation elision optimization for |
| 6205 | coroutines. It crashed LLVM when I tried to do it the first time. This is | |
| 6206 | async function. It crashed LLVM when I tried to do it the first time. This is | |
| 6206 | 6207 | related to the other 2 bullet points here. See |
| 6207 | 6208 | <a href="https://github.com/ziglang/zig/issues/802">#802</a>. |
| 6208 | 6209 | </li> |
| ... | ... | @@ -8016,8 +8017,7 @@ pub fn build(b: *Builder) void { |
| 8016 | 8017 | <p>Zig has a compile option <code>--single-threaded</code> which has the following effects: |
| 8017 | 8018 | <ul> |
| 8018 | 8019 | <li>All {#link|Thread Local Variables#} are treated as {#link|Global Variables#}.</li> |
| 8019 | <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead. | |
| 8020 | TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li> | |
| 8020 | <li>The overhead of {#link|Async Functions#} becomes equivalent to function call overhead.</li> | |
| 8021 | 8021 | <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#} |
| 8022 | 8022 | and therefore various userland APIs which read this variable become more efficient. |
| 8023 | 8023 | For example {#syntax#}std.Mutex{#endsyntax#} becomes |
src-self-hosted/ir.zig-14| ... | ... | @@ -1904,20 +1904,6 @@ pub const Builder = struct { |
| 1904 | 1904 | } |
| 1905 | 1905 | return error.Unimplemented; |
| 1906 | 1906 | |
| 1907 | //ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_field_ptr, return_value); | |
| 1908 | //IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, | |
| 1909 | // get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); | |
| 1910 | //// TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig | |
| 1911 | //IrInstruction *replacement_value = irb->exec->coro_handle; | |
| 1912 | //IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node, | |
| 1913 | // promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr, | |
| 1914 | // AtomicRmwOp_xchg, AtomicOrderSeqCst); | |
| 1915 | //ir_build_store_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, maybe_await_handle); | |
| 1916 | //IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle); | |
| 1917 | //IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false); | |
| 1918 | //return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final, | |
| 1919 | // is_comptime); | |
| 1920 | //// the above blocks are rendered by ir_gen after the rest of codegen | |
| 1921 | 1907 | } |
| 1922 | 1908 | |
| 1923 | 1909 | const Ident = union(enum) { |
src-self-hosted/link.zig+1-1| ... | ... | @@ -627,7 +627,7 @@ fn constructLinkerArgsWasm(ctx: *Context) void { |
| 627 | 627 | |
| 628 | 628 | fn addFnObjects(ctx: *Context) !void { |
| 629 | 629 | // at this point it's guaranteed nobody else has this lock, so we circumvent it |
| 630 | // and avoid having to be a coroutine | |
| 630 | // and avoid having to be an async function | |
| 631 | 631 | const fn_link_set = &ctx.comp.fn_link_set.private_data; |
| 632 | 632 | |
| 633 | 633 | var it = fn_link_set.first; |
src-self-hosted/main.zig+1-1| ... | ... | @@ -52,7 +52,7 @@ const Command = struct { |
| 52 | 52 | |
| 53 | 53 | pub fn main() !void { |
| 54 | 54 | // This allocator needs to be thread-safe because we use it for the event.Loop |
| 55 | // which multiplexes coroutines onto kernel threads. | |
| 55 | // which multiplexes async functions onto kernel threads. | |
| 56 | 56 | // libc allocator is guaranteed to have this property. |
| 57 | 57 | const allocator = std.heap.c_allocator; |
| 58 | 58 |
src-self-hosted/stage1.zig+2-1| ... | ... | @@ -142,7 +142,8 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { |
| 142 | 142 | return Error.None; |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | // TODO: just use the actual self-hosted zig fmt. Until the coroutine rewrite, we use a blocking implementation. | |
| 145 | // TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, | |
| 146 | // we use a blocking implementation. | |
| 146 | 147 | export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int { |
| 147 | 148 | if (std.debug.runtime_safety) { |
| 148 | 149 | fmtMain(argc, argv) catch unreachable; |
src/all_types.hpp+12-12| ... | ... | @@ -1265,7 +1265,7 @@ enum ZigTypeId { |
| 1265 | 1265 | ZigTypeIdBoundFn, |
| 1266 | 1266 | ZigTypeIdArgTuple, |
| 1267 | 1267 | ZigTypeIdOpaque, |
| 1268 | ZigTypeIdCoroFrame, | |
| 1268 | ZigTypeIdFnFrame, | |
| 1269 | 1269 | ZigTypeIdAnyFrame, |
| 1270 | 1270 | ZigTypeIdVector, |
| 1271 | 1271 | ZigTypeIdEnumLiteral, |
| ... | ... | @@ -1281,7 +1281,7 @@ struct ZigTypeOpaque { |
| 1281 | 1281 | Buf *bare_name; |
| 1282 | 1282 | }; |
| 1283 | 1283 | |
| 1284 | struct ZigTypeCoroFrame { | |
| 1284 | struct ZigTypeFnFrame { | |
| 1285 | 1285 | ZigFn *fn; |
| 1286 | 1286 | ZigType *locals_struct; |
| 1287 | 1287 | }; |
| ... | ... | @@ -1315,7 +1315,7 @@ struct ZigType { |
| 1315 | 1315 | ZigTypeBoundFn bound_fn; |
| 1316 | 1316 | ZigTypeVector vector; |
| 1317 | 1317 | ZigTypeOpaque opaque; |
| 1318 | ZigTypeCoroFrame frame; | |
| 1318 | ZigTypeFnFrame frame; | |
| 1319 | 1319 | ZigTypeAnyFrame any_frame; |
| 1320 | 1320 | } data; |
| 1321 | 1321 | |
| ... | ... | @@ -1376,7 +1376,7 @@ struct ZigFn { |
| 1376 | 1376 | LLVMTypeRef raw_type_ref; |
| 1377 | 1377 | ZigLLVMDIType *raw_di_type; |
| 1378 | 1378 | |
| 1379 | ZigType *frame_type; // coro frame type | |
| 1379 | ZigType *frame_type; | |
| 1380 | 1380 | // in the case of normal functions this is the implicit return type |
| 1381 | 1381 | // in the case of async functions this is the implicit return type according to the |
| 1382 | 1382 | // zig source code, not according to zig ir |
| ... | ... | @@ -2368,7 +2368,7 @@ enum IrInstructionId { |
| 2368 | 2368 | IrInstructionIdSuspendFinish, |
| 2369 | 2369 | IrInstructionIdAwaitSrc, |
| 2370 | 2370 | IrInstructionIdAwaitGen, |
| 2371 | IrInstructionIdCoroResume, | |
| 2371 | IrInstructionIdResume, | |
| 2372 | 2372 | IrInstructionIdTestCancelRequested, |
| 2373 | 2373 | IrInstructionIdSpillBegin, |
| 2374 | 2374 | IrInstructionIdSpillEnd, |
| ... | ... | @@ -3640,7 +3640,7 @@ struct IrInstructionAwaitGen { |
| 3640 | 3640 | IrInstruction *result_loc; |
| 3641 | 3641 | }; |
| 3642 | 3642 | |
| 3643 | struct IrInstructionCoroResume { | |
| 3643 | struct IrInstructionResume { | |
| 3644 | 3644 | IrInstruction base; |
| 3645 | 3645 | |
| 3646 | 3646 | IrInstruction *frame; |
| ... | ... | @@ -3751,12 +3751,12 @@ static const size_t maybe_null_index = 1; |
| 3751 | 3751 | static const size_t err_union_payload_index = 0; |
| 3752 | 3752 | static const size_t err_union_err_index = 1; |
| 3753 | 3753 | |
| 3754 | // label (grep this): [coro_frame_struct_layout] | |
| 3755 | static const size_t coro_fn_ptr_index = 0; | |
| 3756 | static const size_t coro_resume_index = 1; | |
| 3757 | static const size_t coro_awaiter_index = 2; | |
| 3758 | static const size_t coro_prev_val_index = 3; | |
| 3759 | static const size_t coro_ret_start = 4; | |
| 3754 | // label (grep this): [fn_frame_struct_layout] | |
| 3755 | static const size_t frame_fn_ptr_index = 0; | |
| 3756 | static const size_t frame_resume_index = 1; | |
| 3757 | static const size_t frame_awaiter_index = 2; | |
| 3758 | static const size_t frame_prev_val_index = 3; | |
| 3759 | static const size_t frame_ret_start = 4; | |
| 3760 | 3760 | |
| 3761 | 3761 | // TODO https://github.com/ziglang/zig/issues/3056 |
| 3762 | 3762 | // We require this to be a power of 2 so that we can use shifting rather than |
src/analyze.cpp+45-45| ... | ... | @@ -234,7 +234,7 @@ AstNode *type_decl_node(ZigType *type_entry) { |
| 234 | 234 | return type_entry->data.enumeration.decl_node; |
| 235 | 235 | case ZigTypeIdUnion: |
| 236 | 236 | return type_entry->data.unionation.decl_node; |
| 237 | case ZigTypeIdCoroFrame: | |
| 237 | case ZigTypeIdFnFrame: | |
| 238 | 238 | return type_entry->data.frame.fn->proto_node; |
| 239 | 239 | case ZigTypeIdOpaque: |
| 240 | 240 | case ZigTypeIdMetaType: |
| ... | ... | @@ -271,7 +271,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { |
| 271 | 271 | return type_entry->data.structure.resolve_status >= status; |
| 272 | 272 | case ZigTypeIdUnion: |
| 273 | 273 | return type_entry->data.unionation.resolve_status >= status; |
| 274 | case ZigTypeIdCoroFrame: | |
| 274 | case ZigTypeIdFnFrame: | |
| 275 | 275 | switch (status) { |
| 276 | 276 | case ResolveStatusInvalid: |
| 277 | 277 | zig_unreachable(); |
| ... | ... | @@ -394,18 +394,18 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) { |
| 394 | 394 | zig_unreachable(); |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn) { | |
| 397 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { | |
| 398 | 398 | if (fn->frame_type != nullptr) { |
| 399 | 399 | return fn->frame_type; |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | ZigType *entry = new_type_table_entry(ZigTypeIdCoroFrame); | |
| 402 | ZigType *entry = new_type_table_entry(ZigTypeIdFnFrame); | |
| 403 | 403 | buf_resize(&entry->name, 0); |
| 404 | 404 | buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name)); |
| 405 | 405 | |
| 406 | 406 | entry->data.frame.fn = fn; |
| 407 | 407 | |
| 408 | // Coroutine frames are always non-zero bits because they always have a resume index. | |
| 408 | // Async function frames are always non-zero bits because they always have a resume index. | |
| 409 | 409 | entry->abi_size = SIZE_MAX; |
| 410 | 410 | entry->size_in_bits = SIZE_MAX; |
| 411 | 411 | |
| ... | ... | @@ -1108,7 +1108,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType |
| 1108 | 1108 | case ZigTypeIdBoundFn: |
| 1109 | 1109 | case ZigTypeIdArgTuple: |
| 1110 | 1110 | case ZigTypeIdOpaque: |
| 1111 | case ZigTypeIdCoroFrame: | |
| 1111 | case ZigTypeIdFnFrame: | |
| 1112 | 1112 | case ZigTypeIdAnyFrame: |
| 1113 | 1113 | add_node_error(g, source_node, |
| 1114 | 1114 | buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", |
| ... | ... | @@ -1198,7 +1198,7 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1198 | 1198 | case ZigTypeIdBoundFn: |
| 1199 | 1199 | case ZigTypeIdArgTuple: |
| 1200 | 1200 | case ZigTypeIdVoid: |
| 1201 | case ZigTypeIdCoroFrame: | |
| 1201 | case ZigTypeIdFnFrame: | |
| 1202 | 1202 | case ZigTypeIdAnyFrame: |
| 1203 | 1203 | return false; |
| 1204 | 1204 | case ZigTypeIdOpaque: |
| ... | ... | @@ -1370,7 +1370,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1370 | 1370 | case ZigTypeIdUnion: |
| 1371 | 1371 | case ZigTypeIdFn: |
| 1372 | 1372 | case ZigTypeIdVector: |
| 1373 | case ZigTypeIdCoroFrame: | |
| 1373 | case ZigTypeIdFnFrame: | |
| 1374 | 1374 | case ZigTypeIdAnyFrame: |
| 1375 | 1375 | switch (type_requires_comptime(g, type_entry)) { |
| 1376 | 1376 | case ReqCompTimeNo: |
| ... | ... | @@ -1467,7 +1467,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1467 | 1467 | case ZigTypeIdUnion: |
| 1468 | 1468 | case ZigTypeIdFn: |
| 1469 | 1469 | case ZigTypeIdVector: |
| 1470 | case ZigTypeIdCoroFrame: | |
| 1470 | case ZigTypeIdFnFrame: | |
| 1471 | 1471 | case ZigTypeIdAnyFrame: |
| 1472 | 1472 | switch (type_requires_comptime(g, fn_type_id.return_type)) { |
| 1473 | 1473 | case ReqCompTimeInvalid: |
| ... | ... | @@ -3080,7 +3080,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 3080 | 3080 | case ZigTypeIdFn: |
| 3081 | 3081 | case ZigTypeIdBoundFn: |
| 3082 | 3082 | case ZigTypeIdVector: |
| 3083 | case ZigTypeIdCoroFrame: | |
| 3083 | case ZigTypeIdFnFrame: | |
| 3084 | 3084 | case ZigTypeIdAnyFrame: |
| 3085 | 3085 | return type_entry; |
| 3086 | 3086 | } |
| ... | ... | @@ -3582,7 +3582,7 @@ bool is_container(ZigType *type_entry) { |
| 3582 | 3582 | case ZigTypeIdArgTuple: |
| 3583 | 3583 | case ZigTypeIdOpaque: |
| 3584 | 3584 | case ZigTypeIdVector: |
| 3585 | case ZigTypeIdCoroFrame: | |
| 3585 | case ZigTypeIdFnFrame: | |
| 3586 | 3586 | case ZigTypeIdAnyFrame: |
| 3587 | 3587 | return false; |
| 3588 | 3588 | } |
| ... | ... | @@ -3640,7 +3640,7 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) { |
| 3640 | 3640 | case ZigTypeIdArgTuple: |
| 3641 | 3641 | case ZigTypeIdOpaque: |
| 3642 | 3642 | case ZigTypeIdVector: |
| 3643 | case ZigTypeIdCoroFrame: | |
| 3643 | case ZigTypeIdFnFrame: | |
| 3644 | 3644 | case ZigTypeIdAnyFrame: |
| 3645 | 3645 | zig_unreachable(); |
| 3646 | 3646 | } |
| ... | ... | @@ -3672,7 +3672,7 @@ bool type_is_nonnull_ptr(ZigType *type) { |
| 3672 | 3672 | return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type); |
| 3673 | 3673 | } |
| 3674 | 3674 | |
| 3675 | static uint32_t get_coro_frame_align_bytes(CodeGen *g) { | |
| 3675 | static uint32_t get_async_frame_align_bytes(CodeGen *g) { | |
| 3676 | 3676 | uint32_t a = g->pointer_size_bytes * 2; |
| 3677 | 3677 | // promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw |
| 3678 | 3678 | if (a < 8) a = 8; |
| ... | ... | @@ -3691,7 +3691,7 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) { |
| 3691 | 3691 | // See http://lists.llvm.org/pipermail/llvm-dev/2018-September/126142.html |
| 3692 | 3692 | return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; |
| 3693 | 3693 | } else if (ptr_type->id == ZigTypeIdAnyFrame) { |
| 3694 | return get_coro_frame_align_bytes(g); | |
| 3694 | return get_async_frame_align_bytes(g); | |
| 3695 | 3695 | } else { |
| 3696 | 3696 | zig_unreachable(); |
| 3697 | 3697 | } |
| ... | ... | @@ -3779,7 +3779,7 @@ bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *sour |
| 3779 | 3779 | } |
| 3780 | 3780 | |
| 3781 | 3781 | static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) { |
| 3782 | ZigType *frame_type = get_coro_frame_type(g, fn); | |
| 3782 | ZigType *frame_type = get_fn_frame_type(g, fn); | |
| 3783 | 3783 | Error err; |
| 3784 | 3784 | if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) { |
| 3785 | 3785 | fn->anal_state = FnAnalStateInvalid; |
| ... | ... | @@ -4218,7 +4218,7 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4218 | 4218 | return false; |
| 4219 | 4219 | case ZigTypeIdArray: |
| 4220 | 4220 | case ZigTypeIdStruct: |
| 4221 | case ZigTypeIdCoroFrame: | |
| 4221 | case ZigTypeIdFnFrame: | |
| 4222 | 4222 | return type_has_bits(type_entry); |
| 4223 | 4223 | case ZigTypeIdErrorUnion: |
| 4224 | 4224 | return type_has_bits(type_entry->data.error_union.payload_type); |
| ... | ... | @@ -4463,7 +4463,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4463 | 4463 | case ZigTypeIdVector: |
| 4464 | 4464 | // TODO better hashing algorithm |
| 4465 | 4465 | return 3647867726; |
| 4466 | case ZigTypeIdCoroFrame: | |
| 4466 | case ZigTypeIdFnFrame: | |
| 4467 | 4467 | // TODO better hashing algorithm |
| 4468 | 4468 | return 675741936; |
| 4469 | 4469 | case ZigTypeIdAnyFrame: |
| ... | ... | @@ -4533,7 +4533,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4533 | 4533 | case ZigTypeIdOpaque: |
| 4534 | 4534 | case ZigTypeIdErrorSet: |
| 4535 | 4535 | case ZigTypeIdEnum: |
| 4536 | case ZigTypeIdCoroFrame: | |
| 4536 | case ZigTypeIdFnFrame: | |
| 4537 | 4537 | case ZigTypeIdAnyFrame: |
| 4538 | 4538 | return false; |
| 4539 | 4539 | |
| ... | ... | @@ -4606,7 +4606,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { |
| 4606 | 4606 | case ZigTypeIdEnum: |
| 4607 | 4607 | case ZigTypeIdPointer: |
| 4608 | 4608 | case ZigTypeIdVector: |
| 4609 | case ZigTypeIdCoroFrame: | |
| 4609 | case ZigTypeIdFnFrame: | |
| 4610 | 4610 | case ZigTypeIdAnyFrame: |
| 4611 | 4611 | return true; |
| 4612 | 4612 | |
| ... | ... | @@ -4739,7 +4739,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 4739 | 4739 | case ZigTypeIdBool: |
| 4740 | 4740 | case ZigTypeIdFloat: |
| 4741 | 4741 | case ZigTypeIdErrorUnion: |
| 4742 | case ZigTypeIdCoroFrame: | |
| 4742 | case ZigTypeIdFnFrame: | |
| 4743 | 4743 | case ZigTypeIdAnyFrame: |
| 4744 | 4744 | return OnePossibleValueNo; |
| 4745 | 4745 | case ZigTypeIdUndefined: |
| ... | ... | @@ -4828,7 +4828,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 4828 | 4828 | case ZigTypeIdFloat: |
| 4829 | 4829 | case ZigTypeIdVoid: |
| 4830 | 4830 | case ZigTypeIdUnreachable: |
| 4831 | case ZigTypeIdCoroFrame: | |
| 4831 | case ZigTypeIdFnFrame: | |
| 4832 | 4832 | case ZigTypeIdAnyFrame: |
| 4833 | 4833 | return ReqCompTimeNo; |
| 4834 | 4834 | } |
| ... | ... | @@ -5161,7 +5161,7 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { |
| 5161 | 5161 | return fn_type; |
| 5162 | 5162 | } |
| 5163 | 5163 | |
| 5164 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | |
| 5164 | static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { | |
| 5165 | 5165 | Error err; |
| 5166 | 5166 | |
| 5167 | 5167 | if (frame_type->data.frame.locals_struct != nullptr) |
| ... | ... | @@ -5231,7 +5231,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5231 | 5231 | if (!fn_is_async(callee)) |
| 5232 | 5232 | continue; |
| 5233 | 5233 | |
| 5234 | ZigType *callee_frame_type = get_coro_frame_type(g, callee); | |
| 5234 | ZigType *callee_frame_type = get_fn_frame_type(g, callee); | |
| 5235 | 5235 | |
| 5236 | 5236 | IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); |
| 5237 | 5237 | alloca_gen->base.id = IrInstructionIdAllocaGen; |
| ... | ... | @@ -5244,7 +5244,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5244 | 5244 | call->frame_result_loc = &alloca_gen->base; |
| 5245 | 5245 | } |
| 5246 | 5246 | |
| 5247 | // label (grep this): [coro_frame_struct_layout] | |
| 5247 | // label (grep this): [fn_frame_struct_layout] | |
| 5248 | 5248 | ZigList<ZigType *> field_types = {}; |
| 5249 | 5249 | ZigList<const char *> field_names = {}; |
| 5250 | 5250 | |
| ... | ... | @@ -5366,8 +5366,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { |
| 5366 | 5366 | return resolve_enum_zero_bits(g, ty); |
| 5367 | 5367 | } else if (ty->id == ZigTypeIdUnion) { |
| 5368 | 5368 | return resolve_union_alignment(g, ty); |
| 5369 | } else if (ty->id == ZigTypeIdCoroFrame) { | |
| 5370 | return resolve_coro_frame(g, ty); | |
| 5369 | } else if (ty->id == ZigTypeIdFnFrame) { | |
| 5370 | return resolve_async_frame(g, ty); | |
| 5371 | 5371 | } |
| 5372 | 5372 | return ErrorNone; |
| 5373 | 5373 | case ResolveStatusSizeKnown: |
| ... | ... | @@ -5377,8 +5377,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { |
| 5377 | 5377 | return resolve_enum_zero_bits(g, ty); |
| 5378 | 5378 | } else if (ty->id == ZigTypeIdUnion) { |
| 5379 | 5379 | return resolve_union_type(g, ty); |
| 5380 | } else if (ty->id == ZigTypeIdCoroFrame) { | |
| 5381 | return resolve_coro_frame(g, ty); | |
| 5380 | } else if (ty->id == ZigTypeIdFnFrame) { | |
| 5381 | return resolve_async_frame(g, ty); | |
| 5382 | 5382 | } |
| 5383 | 5383 | return ErrorNone; |
| 5384 | 5384 | case ResolveStatusLLVMFwdDecl: |
| ... | ... | @@ -5573,7 +5573,7 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5573 | 5573 | return false; |
| 5574 | 5574 | } |
| 5575 | 5575 | return true; |
| 5576 | case ZigTypeIdCoroFrame: | |
| 5576 | case ZigTypeIdFnFrame: | |
| 5577 | 5577 | zig_panic("TODO"); |
| 5578 | 5578 | case ZigTypeIdAnyFrame: |
| 5579 | 5579 | zig_panic("TODO"); |
| ... | ... | @@ -5929,7 +5929,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5929 | 5929 | buf_appendf(buf, "(args value)"); |
| 5930 | 5930 | return; |
| 5931 | 5931 | } |
| 5932 | case ZigTypeIdCoroFrame: | |
| 5932 | case ZigTypeIdFnFrame: | |
| 5933 | 5933 | buf_appendf(buf, "(TODO: async function frame value)"); |
| 5934 | 5934 | return; |
| 5935 | 5935 | |
| ... | ... | @@ -5992,7 +5992,7 @@ uint32_t type_id_hash(TypeId x) { |
| 5992 | 5992 | case ZigTypeIdFn: |
| 5993 | 5993 | case ZigTypeIdBoundFn: |
| 5994 | 5994 | case ZigTypeIdArgTuple: |
| 5995 | case ZigTypeIdCoroFrame: | |
| 5995 | case ZigTypeIdFnFrame: | |
| 5996 | 5996 | case ZigTypeIdAnyFrame: |
| 5997 | 5997 | zig_unreachable(); |
| 5998 | 5998 | case ZigTypeIdErrorUnion: |
| ... | ... | @@ -6042,7 +6042,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 6042 | 6042 | case ZigTypeIdBoundFn: |
| 6043 | 6043 | case ZigTypeIdArgTuple: |
| 6044 | 6044 | case ZigTypeIdOpaque: |
| 6045 | case ZigTypeIdCoroFrame: | |
| 6045 | case ZigTypeIdFnFrame: | |
| 6046 | 6046 | case ZigTypeIdAnyFrame: |
| 6047 | 6047 | zig_unreachable(); |
| 6048 | 6048 | case ZigTypeIdErrorUnion: |
| ... | ... | @@ -6209,7 +6209,7 @@ static const ZigTypeId all_type_ids[] = { |
| 6209 | 6209 | ZigTypeIdBoundFn, |
| 6210 | 6210 | ZigTypeIdArgTuple, |
| 6211 | 6211 | ZigTypeIdOpaque, |
| 6212 | ZigTypeIdCoroFrame, | |
| 6212 | ZigTypeIdFnFrame, | |
| 6213 | 6213 | ZigTypeIdAnyFrame, |
| 6214 | 6214 | ZigTypeIdVector, |
| 6215 | 6215 | ZigTypeIdEnumLiteral, |
| ... | ... | @@ -6274,7 +6274,7 @@ size_t type_id_index(ZigType *entry) { |
| 6274 | 6274 | return 20; |
| 6275 | 6275 | case ZigTypeIdOpaque: |
| 6276 | 6276 | return 21; |
| 6277 | case ZigTypeIdCoroFrame: | |
| 6277 | case ZigTypeIdFnFrame: | |
| 6278 | 6278 | return 22; |
| 6279 | 6279 | case ZigTypeIdAnyFrame: |
| 6280 | 6280 | return 23; |
| ... | ... | @@ -6338,7 +6338,7 @@ const char *type_id_name(ZigTypeId id) { |
| 6338 | 6338 | return "Opaque"; |
| 6339 | 6339 | case ZigTypeIdVector: |
| 6340 | 6340 | return "Vector"; |
| 6341 | case ZigTypeIdCoroFrame: | |
| 6341 | case ZigTypeIdFnFrame: | |
| 6342 | 6342 | return "Frame"; |
| 6343 | 6343 | case ZigTypeIdAnyFrame: |
| 6344 | 6344 | return "AnyFrame"; |
| ... | ... | @@ -6782,7 +6782,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa |
| 6782 | 6782 | } |
| 6783 | 6783 | |
| 6784 | 6784 | static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status, |
| 6785 | ZigType *coro_frame_type) | |
| 6785 | ZigType *async_frame_type) | |
| 6786 | 6786 | { |
| 6787 | 6787 | assert(struct_type->id == ZigTypeIdStruct); |
| 6788 | 6788 | assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid); |
| ... | ... | @@ -6887,11 +6887,11 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 6887 | 6887 | packed_bits_offset = next_packed_bits_offset; |
| 6888 | 6888 | } else { |
| 6889 | 6889 | LLVMTypeRef llvm_type; |
| 6890 | if (i == 0 && coro_frame_type != nullptr) { | |
| 6891 | assert(coro_frame_type->id == ZigTypeIdCoroFrame); | |
| 6890 | if (i == 0 && async_frame_type != nullptr) { | |
| 6891 | assert(async_frame_type->id == ZigTypeIdFnFrame); | |
| 6892 | 6892 | assert(field_type->id == ZigTypeIdFn); |
| 6893 | resolve_llvm_types_fn(g, coro_frame_type->data.frame.fn); | |
| 6894 | llvm_type = LLVMPointerType(coro_frame_type->data.frame.fn->raw_type_ref, 0); | |
| 6893 | resolve_llvm_types_fn(g, async_frame_type->data.frame.fn); | |
| 6894 | llvm_type = LLVMPointerType(async_frame_type->data.frame.fn->raw_type_ref, 0); | |
| 6895 | 6895 | } else { |
| 6896 | 6896 | llvm_type = get_llvm_type(g, field_type); |
| 6897 | 6897 | } |
| ... | ... | @@ -7594,7 +7594,7 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) { |
| 7594 | 7594 | // first "parameter" is return value |
| 7595 | 7595 | param_di_types.append(get_llvm_di_type(g, gen_return_type)); |
| 7596 | 7596 | |
| 7597 | ZigType *frame_type = get_coro_frame_type(g, fn); | |
| 7597 | ZigType *frame_type = get_fn_frame_type(g, fn); | |
| 7598 | 7598 | ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); |
| 7599 | 7599 | if ((err = type_resolve(g, ptr_type, ResolveStatusLLVMFwdDecl))) |
| 7600 | 7600 | zig_unreachable(); |
| ... | ... | @@ -7634,7 +7634,7 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { |
| 7634 | 7634 | get_llvm_di_type(g, g->err_tag_type), ""); |
| 7635 | 7635 | } |
| 7636 | 7636 | |
| 7637 | static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) { | |
| 7637 | static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) { | |
| 7638 | 7638 | resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type); |
| 7639 | 7639 | frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type; |
| 7640 | 7640 | frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type; |
| ... | ... | @@ -7673,7 +7673,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re |
| 7673 | 7673 | ZigList<LLVMTypeRef> field_types = {}; |
| 7674 | 7674 | ZigList<ZigLLVMDIType *> di_element_types = {}; |
| 7675 | 7675 | |
| 7676 | // label (grep this): [coro_frame_struct_layout] | |
| 7676 | // label (grep this): [fn_frame_struct_layout] | |
| 7677 | 7677 | field_types.append(ptr_fn_llvm_type); // fn_ptr |
| 7678 | 7678 | field_types.append(usize_type_ref); // resume_index |
| 7679 | 7679 | field_types.append(usize_type_ref); // awaiter |
| ... | ... | @@ -7824,8 +7824,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r |
| 7824 | 7824 | type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len); |
| 7825 | 7825 | return; |
| 7826 | 7826 | } |
| 7827 | case ZigTypeIdCoroFrame: | |
| 7828 | return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status); | |
| 7827 | case ZigTypeIdFnFrame: | |
| 7828 | return resolve_llvm_types_async_frame(g, type, wanted_resolve_status); | |
| 7829 | 7829 | case ZigTypeIdAnyFrame: |
| 7830 | 7830 | return resolve_llvm_types_any_frame(g, type, wanted_resolve_status); |
| 7831 | 7831 | } |
src/analyze.hpp+1-1| ... | ... | @@ -16,7 +16,7 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg); |
| 16 | 16 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); |
| 17 | 17 | void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg); |
| 18 | 18 | ZigType *new_type_table_entry(ZigTypeId id); |
| 19 | ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn); | |
| 19 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); | |
| 20 | 20 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); |
| 21 | 21 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 22 | 22 | bool is_volatile, PtrLen ptr_len, |
src/codegen.cpp+30-32| ... | ... | @@ -305,16 +305,16 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 305 | 305 | zig_unreachable(); |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | // label (grep this): [coro_frame_struct_layout] | |
| 308 | // label (grep this): [fn_frame_struct_layout] | |
| 309 | 309 | static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) { |
| 310 | 310 | // [0] *ReturnType (callee's) |
| 311 | 311 | // [1] *ReturnType (awaiter's) |
| 312 | 312 | // [2] ReturnType |
| 313 | 313 | uint32_t return_field_count = type_has_bits(return_type) ? 3 : 0; |
| 314 | return coro_ret_start + return_field_count; | |
| 314 | return frame_ret_start + return_field_count; | |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | // label (grep this): [coro_frame_struct_layout] | |
| 317 | // label (grep this): [fn_frame_struct_layout] | |
| 318 | 318 | static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) { |
| 319 | 319 | bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type); |
| 320 | 320 | // [0] *StackTrace |
| ... | ... | @@ -322,7 +322,7 @@ static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) { |
| 322 | 322 | return frame_index_trace_arg(g, return_type) + trace_field_count; |
| 323 | 323 | } |
| 324 | 324 | |
| 325 | // label (grep this): [coro_frame_struct_layout] | |
| 325 | // label (grep this): [fn_frame_struct_layout] | |
| 326 | 326 | static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) { |
| 327 | 327 | uint32_t result = frame_index_arg(g, fn_type_id->return_type); |
| 328 | 328 | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { |
| ... | ... | @@ -2224,7 +2224,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar |
| 2224 | 2224 | { |
| 2225 | 2225 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2226 | 2226 | if (fn_val == nullptr) { |
| 2227 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_fn_ptr_index, ""); | |
| 2227 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, ""); | |
| 2228 | 2228 | fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); |
| 2229 | 2229 | } |
| 2230 | 2230 | if (arg_val == nullptr) { |
| ... | ... | @@ -2373,7 +2373,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 2373 | 2373 | // If the awaiter result pointer is non-null, we need to copy the result to there. |
| 2374 | 2374 | LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); |
| 2375 | 2375 | LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); |
| 2376 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start + 1, ""); | |
| 2376 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, ""); | |
| 2377 | 2377 | LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); |
| 2378 | 2378 | LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); |
| 2379 | 2379 | LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); |
| ... | ... | @@ -3858,7 +3858,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3858 | 3858 | |
| 3859 | 3859 | if (ret_has_bits) { |
| 3860 | 3860 | // Use the result location which is inside the frame if this is an async call. |
| 3861 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); | |
| 3861 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); | |
| 3862 | 3862 | } |
| 3863 | 3863 | } else { |
| 3864 | 3864 | LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); |
| ... | ... | @@ -3897,14 +3897,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3897 | 3897 | if (ret_has_bits) { |
| 3898 | 3898 | if (result_loc == nullptr) { |
| 3899 | 3899 | // return type is a scalar, but we still need a pointer to it. Use the async fn frame. |
| 3900 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); | |
| 3900 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); | |
| 3901 | 3901 | } else { |
| 3902 | 3902 | // Use the call instruction's result location. |
| 3903 | 3903 | ret_ptr = result_loc; |
| 3904 | 3904 | } |
| 3905 | 3905 | |
| 3906 | 3906 | // Store a zero in the awaiter's result ptr to indicate we do not need a copy made. |
| 3907 | LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, ""); | |
| 3907 | LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, ""); | |
| 3908 | 3908 | LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr))); |
| 3909 | 3909 | LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); |
| 3910 | 3910 | } |
| ... | ... | @@ -3919,19 +3919,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3919 | 3919 | if (instruction->is_async || callee_is_async) { |
| 3920 | 3920 | assert(frame_result_loc != nullptr); |
| 3921 | 3921 | |
| 3922 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_fn_ptr_index, ""); | |
| 3922 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, ""); | |
| 3923 | 3923 | LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, |
| 3924 | 3924 | LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), ""); |
| 3925 | 3925 | LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); |
| 3926 | 3926 | |
| 3927 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index, ""); | |
| 3927 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_resume_index, ""); | |
| 3928 | 3928 | LLVMBuildStore(g->builder, zero, resume_index_ptr); |
| 3929 | 3929 | |
| 3930 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_awaiter_index, ""); | |
| 3930 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, ""); | |
| 3931 | 3931 | LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); |
| 3932 | 3932 | |
| 3933 | 3933 | if (ret_has_bits) { |
| 3934 | LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start, ""); | |
| 3934 | LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); | |
| 3935 | 3935 | LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); |
| 3936 | 3936 | } |
| 3937 | 3937 | } else { |
| ... | ... | @@ -4018,7 +4018,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 4018 | 4018 | if (result_loc != nullptr) |
| 4019 | 4019 | return get_handle_value(g, result_loc, src_return_type, ptr_result_type); |
| 4020 | 4020 | |
| 4021 | LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); | |
| 4021 | LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); | |
| 4022 | 4022 | return LLVMBuildLoad(g->builder, result_ptr, ""); |
| 4023 | 4023 | } |
| 4024 | 4024 | |
| ... | ... | @@ -5491,7 +5491,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns |
| 5491 | 5491 | |
| 5492 | 5492 | // supply null for the awaiter return pointer (no copy needed) |
| 5493 | 5493 | if (type_has_bits(result_type)) { |
| 5494 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start + 1, ""); | |
| 5494 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); | |
| 5495 | 5495 | LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), |
| 5496 | 5496 | awaiter_ret_ptr_ptr); |
| 5497 | 5497 | } |
| ... | ... | @@ -5506,7 +5506,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns |
| 5506 | 5506 | |
| 5507 | 5507 | LLVMValueRef awaiter_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); |
| 5508 | 5508 | LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, ""); |
| 5509 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); | |
| 5509 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, ""); | |
| 5510 | 5510 | |
| 5511 | 5511 | LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val, |
| 5512 | 5512 | LLVMAtomicOrderingRelease); |
| ... | ... | @@ -5549,7 +5549,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5549 | 5549 | LLVMValueRef result_loc = (instruction->result_loc == nullptr) ? |
| 5550 | 5550 | nullptr : ir_llvm_value(g, instruction->result_loc); |
| 5551 | 5551 | if (type_has_bits(result_type)) { |
| 5552 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start + 1, ""); | |
| 5552 | LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); | |
| 5553 | 5553 | if (result_loc == nullptr) { |
| 5554 | 5554 | // no copy needed |
| 5555 | 5555 | LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), |
| ... | ... | @@ -5570,7 +5570,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5570 | 5570 | |
| 5571 | 5571 | // caller's own frame pointer |
| 5572 | 5572 | LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); |
| 5573 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); | |
| 5573 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, ""); | |
| 5574 | 5574 | LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, |
| 5575 | 5575 | LLVMAtomicOrderingRelease, g->is_single_threaded); |
| 5576 | 5576 | |
| ... | ... | @@ -5608,9 +5608,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5608 | 5608 | return nullptr; |
| 5609 | 5609 | } |
| 5610 | 5610 | |
| 5611 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | |
| 5612 | IrInstructionCoroResume *instruction) | |
| 5613 | { | |
| 5611 | static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrInstructionResume *instruction) { | |
| 5614 | 5612 | LLVMValueRef frame = ir_llvm_value(g, instruction->frame); |
| 5615 | 5613 | ZigType *frame_type = instruction->frame->value.type; |
| 5616 | 5614 | assert(frame_type->id == ZigTypeIdAnyFrame); |
| ... | ... | @@ -5921,8 +5919,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5921 | 5919 | return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction); |
| 5922 | 5920 | case IrInstructionIdSuspendFinish: |
| 5923 | 5921 | return ir_render_suspend_finish(g, executable, (IrInstructionSuspendFinish *)instruction); |
| 5924 | case IrInstructionIdCoroResume: | |
| 5925 | return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); | |
| 5922 | case IrInstructionIdResume: | |
| 5923 | return ir_render_resume(g, executable, (IrInstructionResume *)instruction); | |
| 5926 | 5924 | case IrInstructionIdFrameSizeGen: |
| 5927 | 5925 | return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction); |
| 5928 | 5926 | case IrInstructionIdAwaitGen: |
| ... | ... | @@ -6195,7 +6193,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 6195 | 6193 | } |
| 6196 | 6194 | return val; |
| 6197 | 6195 | } |
| 6198 | case ZigTypeIdCoroFrame: | |
| 6196 | case ZigTypeIdFnFrame: | |
| 6199 | 6197 | zig_panic("TODO bit pack an async function frame"); |
| 6200 | 6198 | case ZigTypeIdAnyFrame: |
| 6201 | 6199 | zig_panic("TODO bit pack an anyframe"); |
| ... | ... | @@ -6727,7 +6725,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 6727 | 6725 | case ZigTypeIdArgTuple: |
| 6728 | 6726 | case ZigTypeIdOpaque: |
| 6729 | 6727 | zig_unreachable(); |
| 6730 | case ZigTypeIdCoroFrame: | |
| 6728 | case ZigTypeIdFnFrame: | |
| 6731 | 6729 | zig_panic("TODO"); |
| 6732 | 6730 | case ZigTypeIdAnyFrame: |
| 6733 | 6731 | zig_panic("TODO"); |
| ... | ... | @@ -7171,12 +7169,12 @@ static void do_code_gen(CodeGen *g) { |
| 7171 | 7169 | |
| 7172 | 7170 | LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); |
| 7173 | 7171 | render_async_spills(g); |
| 7174 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_awaiter_index, ""); | |
| 7175 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_resume_index, ""); | |
| 7172 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_awaiter_index, ""); | |
| 7173 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, ""); | |
| 7176 | 7174 | g->cur_async_resume_index_ptr = resume_index_ptr; |
| 7177 | 7175 | |
| 7178 | 7176 | if (type_has_bits(fn_type_id->return_type)) { |
| 7179 | LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start, ""); | |
| 7177 | LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, ""); | |
| 7180 | 7178 | g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); |
| 7181 | 7179 | } |
| 7182 | 7180 | if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { |
| ... | ... | @@ -7190,7 +7188,7 @@ static void do_code_gen(CodeGen *g) { |
| 7190 | 7188 | trace_field_index_stack, ""); |
| 7191 | 7189 | } |
| 7192 | 7190 | g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, |
| 7193 | coro_prev_val_index, ""); | |
| 7191 | frame_prev_val_index, ""); | |
| 7194 | 7192 | |
| 7195 | 7193 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| 7196 | 7194 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); |
| ... | ... | @@ -9229,7 +9227,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e |
| 9229 | 9227 | case ZigTypeIdArgTuple: |
| 9230 | 9228 | case ZigTypeIdErrorUnion: |
| 9231 | 9229 | case ZigTypeIdErrorSet: |
| 9232 | case ZigTypeIdCoroFrame: | |
| 9230 | case ZigTypeIdFnFrame: | |
| 9233 | 9231 | case ZigTypeIdAnyFrame: |
| 9234 | 9232 | zig_unreachable(); |
| 9235 | 9233 | case ZigTypeIdVoid: |
| ... | ... | @@ -9414,7 +9412,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu |
| 9414 | 9412 | case ZigTypeIdUndefined: |
| 9415 | 9413 | case ZigTypeIdNull: |
| 9416 | 9414 | case ZigTypeIdArgTuple: |
| 9417 | case ZigTypeIdCoroFrame: | |
| 9415 | case ZigTypeIdFnFrame: | |
| 9418 | 9416 | case ZigTypeIdAnyFrame: |
| 9419 | 9417 | zig_unreachable(); |
| 9420 | 9418 | } |
| ... | ... | @@ -9583,7 +9581,7 @@ static void gen_h_file(CodeGen *g) { |
| 9583 | 9581 | case ZigTypeIdOptional: |
| 9584 | 9582 | case ZigTypeIdFn: |
| 9585 | 9583 | case ZigTypeIdVector: |
| 9586 | case ZigTypeIdCoroFrame: | |
| 9584 | case ZigTypeIdFnFrame: | |
| 9587 | 9585 | case ZigTypeIdAnyFrame: |
| 9588 | 9586 | zig_unreachable(); |
| 9589 | 9587 |
src/ir.cpp+30-32| ... | ... | @@ -321,7 +321,7 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 321 | 321 | case ZigTypeIdFn: |
| 322 | 322 | case ZigTypeIdArgTuple: |
| 323 | 323 | case ZigTypeIdVector: |
| 324 | case ZigTypeIdCoroFrame: | |
| 324 | case ZigTypeIdFnFrame: | |
| 325 | 325 | return false; |
| 326 | 326 | } |
| 327 | 327 | zig_unreachable(); |
| ... | ... | @@ -1058,8 +1058,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitGen *) { |
| 1058 | 1058 | return IrInstructionIdAwaitGen; |
| 1059 | 1059 | } |
| 1060 | 1060 | |
| 1061 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) { | |
| 1062 | return IrInstructionIdCoroResume; | |
| 1061 | static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) { | |
| 1062 | return IrInstructionIdResume; | |
| 1063 | 1063 | } |
| 1064 | 1064 | |
| 1065 | 1065 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelRequested *) { |
| ... | ... | @@ -3321,10 +3321,8 @@ static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_i |
| 3321 | 3321 | return &instruction->base; |
| 3322 | 3322 | } |
| 3323 | 3323 | |
| 3324 | static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3325 | IrInstruction *frame) | |
| 3326 | { | |
| 3327 | IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node); | |
| 3324 | static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) { | |
| 3325 | IrInstructionResume *instruction = ir_build_instruction<IrInstructionResume>(irb, scope, source_node); | |
| 3328 | 3326 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 3329 | 3327 | instruction->frame = frame; |
| 3330 | 3328 | |
| ... | ... | @@ -7964,7 +7962,7 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node) |
| 7964 | 7962 | if (target_inst == irb->codegen->invalid_instruction) |
| 7965 | 7963 | return irb->codegen->invalid_instruction; |
| 7966 | 7964 | |
| 7967 | return ir_build_coro_resume(irb, scope, node, target_inst); | |
| 7965 | return ir_build_resume(irb, scope, node, target_inst); | |
| 7968 | 7966 | } |
| 7969 | 7967 | |
| 7970 | 7968 | static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, |
| ... | ... | @@ -12223,7 +12221,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 12223 | 12221 | |
| 12224 | 12222 | // *@Frame(func) to anyframe->T or anyframe |
| 12225 | 12223 | if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && |
| 12226 | actual_type->data.pointer.child_type->id == ZigTypeIdCoroFrame && wanted_type->id == ZigTypeIdAnyFrame) | |
| 12224 | actual_type->data.pointer.child_type->id == ZigTypeIdFnFrame && wanted_type->id == ZigTypeIdAnyFrame) | |
| 12227 | 12225 | { |
| 12228 | 12226 | bool ok = true; |
| 12229 | 12227 | if (wanted_type->data.any_frame.result_type != nullptr) { |
| ... | ... | @@ -13123,7 +13121,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 13123 | 13121 | case ZigTypeIdNull: |
| 13124 | 13122 | case ZigTypeIdErrorUnion: |
| 13125 | 13123 | case ZigTypeIdUnion: |
| 13126 | case ZigTypeIdCoroFrame: | |
| 13124 | case ZigTypeIdFnFrame: | |
| 13127 | 13125 | operator_allowed = false; |
| 13128 | 13126 | break; |
| 13129 | 13127 | case ZigTypeIdOptional: |
| ... | ... | @@ -14488,7 +14486,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 14488 | 14486 | case ZigTypeIdBoundFn: |
| 14489 | 14487 | case ZigTypeIdArgTuple: |
| 14490 | 14488 | case ZigTypeIdOpaque: |
| 14491 | case ZigTypeIdCoroFrame: | |
| 14489 | case ZigTypeIdFnFrame: | |
| 14492 | 14490 | case ZigTypeIdAnyFrame: |
| 14493 | 14491 | ir_add_error(ira, target, |
| 14494 | 14492 | buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); |
| ... | ... | @@ -14514,7 +14512,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 14514 | 14512 | case ZigTypeIdArgTuple: |
| 14515 | 14513 | case ZigTypeIdOpaque: |
| 14516 | 14514 | case ZigTypeIdEnumLiteral: |
| 14517 | case ZigTypeIdCoroFrame: | |
| 14515 | case ZigTypeIdFnFrame: | |
| 14518 | 14516 | case ZigTypeIdAnyFrame: |
| 14519 | 14517 | ir_add_error(ira, target, |
| 14520 | 14518 | buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); |
| ... | ... | @@ -15060,7 +15058,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc |
| 15060 | 15058 | return ira->codegen->invalid_instruction; |
| 15061 | 15059 | } |
| 15062 | 15060 | |
| 15063 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); | |
| 15061 | ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry); | |
| 15064 | 15062 | IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, |
| 15065 | 15063 | frame_type, nullptr, true, true, false); |
| 15066 | 15064 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| ... | ... | @@ -16121,7 +16119,7 @@ static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp |
| 16121 | 16119 | case ZigTypeIdFn: |
| 16122 | 16120 | case ZigTypeIdBoundFn: |
| 16123 | 16121 | case ZigTypeIdArgTuple: |
| 16124 | case ZigTypeIdCoroFrame: | |
| 16122 | case ZigTypeIdFnFrame: | |
| 16125 | 16123 | case ZigTypeIdAnyFrame: |
| 16126 | 16124 | return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry)); |
| 16127 | 16125 | |
| ... | ... | @@ -17910,7 +17908,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 17910 | 17908 | case ZigTypeIdFn: |
| 17911 | 17909 | case ZigTypeIdBoundFn: |
| 17912 | 17910 | case ZigTypeIdVector: |
| 17913 | case ZigTypeIdCoroFrame: | |
| 17911 | case ZigTypeIdFnFrame: | |
| 17914 | 17912 | case ZigTypeIdAnyFrame: |
| 17915 | 17913 | { |
| 17916 | 17914 | ResolveStatus needed_status = (align_bytes == 0) ? |
| ... | ... | @@ -18026,7 +18024,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 18026 | 18024 | case ZigTypeIdFn: |
| 18027 | 18025 | case ZigTypeIdBoundFn: |
| 18028 | 18026 | case ZigTypeIdVector: |
| 18029 | case ZigTypeIdCoroFrame: | |
| 18027 | case ZigTypeIdFnFrame: | |
| 18030 | 18028 | case ZigTypeIdAnyFrame: |
| 18031 | 18029 | { |
| 18032 | 18030 | if ((err = ensure_complete_type(ira->codegen, child_type))) |
| ... | ... | @@ -18078,7 +18076,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 18078 | 18076 | case ZigTypeIdUnion: |
| 18079 | 18077 | case ZigTypeIdFn: |
| 18080 | 18078 | case ZigTypeIdVector: |
| 18081 | case ZigTypeIdCoroFrame: | |
| 18079 | case ZigTypeIdFnFrame: | |
| 18082 | 18080 | case ZigTypeIdAnyFrame: |
| 18083 | 18081 | { |
| 18084 | 18082 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| ... | ... | @@ -18643,7 +18641,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 18643 | 18641 | case ZigTypeIdArgTuple: |
| 18644 | 18642 | case ZigTypeIdOpaque: |
| 18645 | 18643 | case ZigTypeIdVector: |
| 18646 | case ZigTypeIdCoroFrame: | |
| 18644 | case ZigTypeIdFnFrame: | |
| 18647 | 18645 | case ZigTypeIdAnyFrame: |
| 18648 | 18646 | ir_add_error(ira, &switch_target_instruction->base, |
| 18649 | 18647 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| ... | ... | @@ -20500,7 +20498,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 20500 | 20498 | |
| 20501 | 20499 | break; |
| 20502 | 20500 | } |
| 20503 | case ZigTypeIdCoroFrame: | |
| 20501 | case ZigTypeIdFnFrame: | |
| 20504 | 20502 | zig_panic("TODO @typeInfo for async function frames"); |
| 20505 | 20503 | } |
| 20506 | 20504 | |
| ... | ... | @@ -22219,7 +22217,7 @@ static IrInstruction *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInst |
| 22219 | 22217 | ZigFn *fn = exec_fn_entry(ira->new_irb.exec); |
| 22220 | 22218 | ir_assert(fn != nullptr, &instruction->base); |
| 22221 | 22219 | |
| 22222 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn); | |
| 22220 | ZigType *frame_type = get_fn_frame_type(ira->codegen, fn); | |
| 22223 | 22221 | ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false); |
| 22224 | 22222 | |
| 22225 | 22223 | IrInstruction *result = ir_build_handle(&ira->new_irb, instruction->base.scope, instruction->base.source_node); |
| ... | ... | @@ -22232,7 +22230,7 @@ static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstru |
| 22232 | 22230 | if (fn == nullptr) |
| 22233 | 22231 | return ira->codegen->invalid_instruction; |
| 22234 | 22232 | |
| 22235 | ZigType *ty = get_coro_frame_type(ira->codegen, fn); | |
| 22233 | ZigType *ty = get_fn_frame_type(ira->codegen, fn); | |
| 22236 | 22234 | return ir_const_type(ira, &instruction->base, ty); |
| 22237 | 22235 | } |
| 22238 | 22236 | |
| ... | ... | @@ -22293,7 +22291,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct |
| 22293 | 22291 | case ZigTypeIdUnion: |
| 22294 | 22292 | case ZigTypeIdFn: |
| 22295 | 22293 | case ZigTypeIdVector: |
| 22296 | case ZigTypeIdCoroFrame: | |
| 22294 | case ZigTypeIdFnFrame: | |
| 22297 | 22295 | case ZigTypeIdAnyFrame: |
| 22298 | 22296 | { |
| 22299 | 22297 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); |
| ... | ... | @@ -23438,7 +23436,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 23438 | 23436 | zig_panic("TODO buf_write_value_bytes fn type"); |
| 23439 | 23437 | case ZigTypeIdUnion: |
| 23440 | 23438 | zig_panic("TODO buf_write_value_bytes union type"); |
| 23441 | case ZigTypeIdCoroFrame: | |
| 23439 | case ZigTypeIdFnFrame: | |
| 23442 | 23440 | zig_panic("TODO buf_write_value_bytes async fn frame type"); |
| 23443 | 23441 | case ZigTypeIdAnyFrame: |
| 23444 | 23442 | zig_panic("TODO buf_write_value_bytes anyframe type"); |
| ... | ... | @@ -23621,7 +23619,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 23621 | 23619 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 23622 | 23620 | case ZigTypeIdUnion: |
| 23623 | 23621 | zig_panic("TODO buf_read_value_bytes union type"); |
| 23624 | case ZigTypeIdCoroFrame: | |
| 23622 | case ZigTypeIdFnFrame: | |
| 23625 | 23623 | zig_panic("TODO buf_read_value_bytes async fn frame type"); |
| 23626 | 23624 | case ZigTypeIdAnyFrame: |
| 23627 | 23625 | zig_panic("TODO buf_read_value_bytes anyframe type"); |
| ... | ... | @@ -24674,7 +24672,7 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct |
| 24674 | 24672 | IrInstruction *frame; |
| 24675 | 24673 | if (frame_ptr->value.type->id == ZigTypeIdPointer && |
| 24676 | 24674 | frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle && |
| 24677 | frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) | |
| 24675 | frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame) | |
| 24678 | 24676 | { |
| 24679 | 24677 | result_type = frame_ptr->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type; |
| 24680 | 24678 | frame = frame_ptr; |
| ... | ... | @@ -24682,7 +24680,7 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct |
| 24682 | 24680 | frame = ir_get_deref(ira, source_instr, frame_ptr, nullptr); |
| 24683 | 24681 | if (frame->value.type->id == ZigTypeIdPointer && |
| 24684 | 24682 | frame->value.type->data.pointer.ptr_len == PtrLenSingle && |
| 24685 | frame->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) | |
| 24683 | frame->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame) | |
| 24686 | 24684 | { |
| 24687 | 24685 | result_type = frame->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type; |
| 24688 | 24686 | } else if (frame->value.type->id != ZigTypeIdAnyFrame || |
| ... | ... | @@ -24751,7 +24749,7 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction |
| 24751 | 24749 | return ir_finish_anal(ira, result); |
| 24752 | 24750 | } |
| 24753 | 24751 | |
| 24754 | static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) { | |
| 24752 | static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructionResume *instruction) { | |
| 24755 | 24753 | IrInstruction *frame_ptr = instruction->frame->child; |
| 24756 | 24754 | if (type_is_invalid(frame_ptr->value.type)) |
| 24757 | 24755 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -24759,7 +24757,7 @@ static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstr |
| 24759 | 24757 | IrInstruction *frame; |
| 24760 | 24758 | if (frame_ptr->value.type->id == ZigTypeIdPointer && |
| 24761 | 24759 | frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle && |
| 24762 | frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) | |
| 24760 | frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame) | |
| 24763 | 24761 | { |
| 24764 | 24762 | frame = frame_ptr; |
| 24765 | 24763 | } else { |
| ... | ... | @@ -24771,7 +24769,7 @@ static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstr |
| 24771 | 24769 | if (type_is_invalid(casted_frame->value.type)) |
| 24772 | 24770 | return ira->codegen->invalid_instruction; |
| 24773 | 24771 | |
| 24774 | return ir_build_coro_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame); | |
| 24772 | return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame); | |
| 24775 | 24773 | } |
| 24776 | 24774 | |
| 24777 | 24775 | static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ira, |
| ... | ... | @@ -25112,8 +25110,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 25112 | 25110 | return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction); |
| 25113 | 25111 | case IrInstructionIdSuspendFinish: |
| 25114 | 25112 | return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction); |
| 25115 | case IrInstructionIdCoroResume: | |
| 25116 | return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction); | |
| 25113 | case IrInstructionIdResume: | |
| 25114 | return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction); | |
| 25117 | 25115 | case IrInstructionIdAwaitSrc: |
| 25118 | 25116 | return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction); |
| 25119 | 25117 | case IrInstructionIdTestCancelRequested: |
| ... | ... | @@ -25256,7 +25254,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 25256 | 25254 | case IrInstructionIdResetResult: |
| 25257 | 25255 | case IrInstructionIdSuspendBegin: |
| 25258 | 25256 | case IrInstructionIdSuspendFinish: |
| 25259 | case IrInstructionIdCoroResume: | |
| 25257 | case IrInstructionIdResume: | |
| 25260 | 25258 | case IrInstructionIdAwaitSrc: |
| 25261 | 25259 | case IrInstructionIdAwaitGen: |
| 25262 | 25260 | case IrInstructionIdSpillBegin: |
src/ir_print.cpp+4-5| ... | ... | @@ -1528,10 +1528,9 @@ static void ir_print_suspend_finish(IrPrint *irp, IrInstructionSuspendFinish *in |
| 1528 | 1528 | fprintf(irp->f, "@suspendFinish()"); |
| 1529 | 1529 | } |
| 1530 | 1530 | |
| 1531 | static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) { | |
| 1532 | fprintf(irp->f, "@coroResume("); | |
| 1531 | static void ir_print_resume(IrPrint *irp, IrInstructionResume *instruction) { | |
| 1532 | fprintf(irp->f, "resume "); | |
| 1533 | 1533 | ir_print_other_instruction(irp, instruction->frame); |
| 1534 | fprintf(irp->f, ")"); | |
| 1535 | 1534 | } |
| 1536 | 1535 | |
| 1537 | 1536 | static void ir_print_await_src(IrPrint *irp, IrInstructionAwaitSrc *instruction) { |
| ... | ... | @@ -2039,8 +2038,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 2039 | 2038 | case IrInstructionIdSuspendFinish: |
| 2040 | 2039 | ir_print_suspend_finish(irp, (IrInstructionSuspendFinish *)instruction); |
| 2041 | 2040 | break; |
| 2042 | case IrInstructionIdCoroResume: | |
| 2043 | ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction); | |
| 2041 | case IrInstructionIdResume: | |
| 2042 | ir_print_resume(irp, (IrInstructionResume *)instruction); | |
| 2044 | 2043 | break; |
| 2045 | 2044 | case IrInstructionIdAwaitSrc: |
| 2046 | 2045 | ir_print_await_src(irp, (IrInstructionAwaitSrc *)instruction); |
src/zig_llvm.cpp-3| ... | ... | @@ -42,7 +42,6 @@ |
| 42 | 42 | #include <llvm/Support/TargetRegistry.h> |
| 43 | 43 | #include <llvm/Target/TargetMachine.h> |
| 44 | 44 | #include <llvm/Target/CodeGenCWrappers.h> |
| 45 | #include <llvm/Transforms/Coroutines.h> | |
| 46 | 45 | #include <llvm/Transforms/IPO.h> |
| 47 | 46 | #include <llvm/Transforms/IPO/AlwaysInliner.h> |
| 48 | 47 | #include <llvm/Transforms/IPO/PassManagerBuilder.h> |
| ... | ... | @@ -203,8 +202,6 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 203 | 202 | PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false); |
| 204 | 203 | } |
| 205 | 204 | |
| 206 | addCoroutinePassesToExtensionPoints(*PMBuilder); | |
| 207 | ||
| 208 | 205 | // Set up the per-function pass manager. |
| 209 | 206 | legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module); |
| 210 | 207 | auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii); |
std/event/fs.zig+3-3| ... | ... | @@ -799,7 +799,7 @@ pub const WatchEventId = enum { |
| 799 | 799 | // pub fn destroy(self: *Self) void { |
| 800 | 800 | // switch (builtin.os) { |
| 801 | 801 | // .macosx, .freebsd, .netbsd => { |
| 802 | // // TODO we need to cancel the coroutines before destroying the lock | |
| 802 | // // TODO we need to cancel the frames before destroying the lock | |
| 803 | 803 | // self.os_data.table_lock.deinit(); |
| 804 | 804 | // var it = self.os_data.file_table.iterator(); |
| 805 | 805 | // while (it.next()) |entry| { |
| ... | ... | @@ -1088,7 +1088,7 @@ pub const WatchEventId = enum { |
| 1088 | 1088 | // |
| 1089 | 1089 | // while (true) { |
| 1090 | 1090 | // { |
| 1091 | // // TODO only 1 beginOneEvent for the whole coroutine | |
| 1091 | // // TODO only 1 beginOneEvent for the whole function | |
| 1092 | 1092 | // self.channel.loop.beginOneEvent(); |
| 1093 | 1093 | // errdefer self.channel.loop.finishOneEvent(); |
| 1094 | 1094 | // errdefer { |
| ... | ... | @@ -1252,7 +1252,7 @@ pub const WatchEventId = enum { |
| 1252 | 1252 | |
| 1253 | 1253 | const test_tmp_dir = "std_event_fs_test"; |
| 1254 | 1254 | |
| 1255 | // TODO this test is disabled until the coroutine rewrite is finished. | |
| 1255 | // TODO this test is disabled until the async function rewrite is finished. | |
| 1256 | 1256 | //test "write a file, watch it, write it again" { |
| 1257 | 1257 | // return error.SkipZigTest; |
| 1258 | 1258 | // const allocator = std.heap.direct_allocator; |
std/event/future.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const Lock = std.event.Lock; |
| 6 | 6 | const Loop = std.event.Loop; |
| 7 | 7 | |
| 8 | 8 | /// This is a value that starts out unavailable, until resolve() is called |
| 9 | /// While it is unavailable, coroutines suspend when they try to get() it, | |
| 9 | /// While it is unavailable, functions suspend when they try to get() it, | |
| 10 | 10 | /// and then are resumed when resolve() is called. |
| 11 | 11 | /// At this point the value remains forever available, and another resolve() is not allowed. |
| 12 | 12 | pub fn Future(comptime T: type) type { |
std/event/group.zig+6-6| ... | ... | @@ -7,7 +7,7 @@ const testing = std.testing; |
| 7 | 7 | /// ReturnType must be `void` or `E!void` |
| 8 | 8 | pub fn Group(comptime ReturnType: type) type { |
| 9 | 9 | return struct { |
| 10 | coro_stack: Stack, | |
| 10 | frame_stack: Stack, | |
| 11 | 11 | alloc_stack: Stack, |
| 12 | 12 | lock: Lock, |
| 13 | 13 | |
| ... | ... | @@ -21,7 +21,7 @@ pub fn Group(comptime ReturnType: type) type { |
| 21 | 21 | |
| 22 | 22 | pub fn init(loop: *Loop) Self { |
| 23 | 23 | return Self{ |
| 24 | .coro_stack = Stack.init(), | |
| 24 | .frame_stack = Stack.init(), | |
| 25 | 25 | .alloc_stack = Stack.init(), |
| 26 | 26 | .lock = Lock.init(loop), |
| 27 | 27 | }; |
| ... | ... | @@ -29,7 +29,7 @@ pub fn Group(comptime ReturnType: type) type { |
| 29 | 29 | |
| 30 | 30 | /// Cancel all the outstanding frames. Can be called even if wait was already called. |
| 31 | 31 | pub fn deinit(self: *Self) void { |
| 32 | while (self.coro_stack.pop()) |node| { | |
| 32 | while (self.frame_stack.pop()) |node| { | |
| 33 | 33 | cancel node.data; |
| 34 | 34 | } |
| 35 | 35 | while (self.alloc_stack.pop()) |node| { |
| ... | ... | @@ -50,11 +50,11 @@ pub fn Group(comptime ReturnType: type) type { |
| 50 | 50 | |
| 51 | 51 | /// Add a node to the group. Thread-safe. Cannot fail. |
| 52 | 52 | /// `node.data` should be the frame handle to add to the group. |
| 53 | /// The node's memory should be in the coroutine frame of | |
| 53 | /// The node's memory should be in the function frame of | |
| 54 | 54 | /// the handle that is in the node, or somewhere guaranteed to live |
| 55 | 55 | /// at least as long. |
| 56 | 56 | pub fn addNode(self: *Self, node: *Stack.Node) void { |
| 57 | self.coro_stack.push(node); | |
| 57 | self.frame_stack.push(node); | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | /// Wait for all the calls and promises of the group to complete. |
| ... | ... | @@ -64,7 +64,7 @@ pub fn Group(comptime ReturnType: type) type { |
| 64 | 64 | const held = self.lock.acquire(); |
| 65 | 65 | defer held.release(); |
| 66 | 66 | |
| 67 | while (self.coro_stack.pop()) |node| { | |
| 67 | while (self.frame_stack.pop()) |node| { | |
| 68 | 68 | if (Error == void) { |
| 69 | 69 | await node.data; |
| 70 | 70 | } else { |
std/event/lock.zig+2-3| ... | ... | @@ -6,7 +6,7 @@ const mem = std.mem; |
| 6 | 6 | const Loop = std.event.Loop; |
| 7 | 7 | |
| 8 | 8 | /// Thread-safe async/await lock. |
| 9 | /// coroutines which are waiting for the lock are suspended, and | |
| 9 | /// Functions which are waiting for the lock are suspended, and | |
| 10 | 10 | /// are resumed when the lock is released, in order. |
| 11 | 11 | /// Allows only one actor to hold the lock. |
| 12 | 12 | pub const Lock = struct { |
| ... | ... | @@ -96,8 +96,7 @@ pub const Lock = struct { |
| 96 | 96 | suspend { |
| 97 | 97 | self.queue.put(&my_tick_node); |
| 98 | 98 | |
| 99 | // At this point, we are in the queue, so we might have already been resumed and this coroutine | |
| 100 | // frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame. | |
| 99 | // At this point, we are in the queue, so we might have already been resumed. | |
| 101 | 100 | |
| 102 | 101 | // We set this bit so that later we can rely on the fact, that if queue_empty_bit is 1, some actor |
| 103 | 102 | // will attempt to grab the lock. |
std/event/locked.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ const Lock = std.event.Lock; |
| 3 | 3 | const Loop = std.event.Loop; |
| 4 | 4 | |
| 5 | 5 | /// Thread-safe async/await lock that protects one piece of data. |
| 6 | /// coroutines which are waiting for the lock are suspended, and | |
| 6 | /// Functions which are waiting for the lock are suspended, and | |
| 7 | 7 | /// are resumed when the lock is released, in order. |
| 8 | 8 | pub fn Locked(comptime T: type) type { |
| 9 | 9 | return struct { |
std/event/loop.zig+1-1| ... | ... | @@ -118,7 +118,7 @@ pub const Loop = struct { |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | /// The allocator must be thread-safe because we use it for multiplexing |
| 121 | /// coroutines onto kernel threads. | |
| 121 | /// async functions onto kernel threads. | |
| 122 | 122 | /// After initialization, call run(). |
| 123 | 123 | /// TODO copy elision / named return values so that the threads referencing *Loop |
| 124 | 124 | /// have the correct pointer value. |
std/event/net.zig+7-7| ... | ... | @@ -13,7 +13,7 @@ pub const Server = struct { |
| 13 | 13 | |
| 14 | 14 | loop: *Loop, |
| 15 | 15 | sockfd: ?i32, |
| 16 | accept_coro: ?anyframe, | |
| 16 | accept_frame: ?anyframe, | |
| 17 | 17 | listen_address: std.net.Address, |
| 18 | 18 | |
| 19 | 19 | waiting_for_emfile_node: PromiseNode, |
| ... | ... | @@ -22,11 +22,11 @@ pub const Server = struct { |
| 22 | 22 | const PromiseNode = std.TailQueue(anyframe).Node; |
| 23 | 23 | |
| 24 | 24 | pub fn init(loop: *Loop) Server { |
| 25 | // TODO can't initialize handler coroutine here because we need well defined copy elision | |
| 25 | // TODO can't initialize handler here because we need well defined copy elision | |
| 26 | 26 | return Server{ |
| 27 | 27 | .loop = loop, |
| 28 | 28 | .sockfd = null, |
| 29 | .accept_coro = null, | |
| 29 | .accept_frame = null, | |
| 30 | 30 | .handleRequestFn = undefined, |
| 31 | 31 | .waiting_for_emfile_node = undefined, |
| 32 | 32 | .listen_address = undefined, |
| ... | ... | @@ -53,10 +53,10 @@ pub const Server = struct { |
| 53 | 53 | try os.listen(sockfd, os.SOMAXCONN); |
| 54 | 54 | self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd)); |
| 55 | 55 | |
| 56 | self.accept_coro = async Server.handler(self); | |
| 57 | errdefer cancel self.accept_coro.?; | |
| 56 | self.accept_frame = async Server.handler(self); | |
| 57 | errdefer cancel self.accept_frame.?; | |
| 58 | 58 | |
| 59 | self.listen_resume_node.handle = self.accept_coro.?; | |
| 59 | self.listen_resume_node.handle = self.accept_frame.?; | |
| 60 | 60 | try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); |
| 61 | 61 | errdefer self.loop.removeFd(sockfd); |
| 62 | 62 | } |
| ... | ... | @@ -71,7 +71,7 @@ pub const Server = struct { |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | pub fn deinit(self: *Server) void { |
| 74 | if (self.accept_coro) |accept_coro| cancel accept_coro; | |
| 74 | if (self.accept_frame) |accept_frame| cancel accept_frame; | |
| 75 | 75 | if (self.sockfd) |sockfd| os.close(sockfd); |
| 76 | 76 | } |
| 77 | 77 |
std/event/rwlock.zig+3-5| ... | ... | @@ -6,7 +6,7 @@ const mem = std.mem; |
| 6 | 6 | const Loop = std.event.Loop; |
| 7 | 7 | |
| 8 | 8 | /// Thread-safe async/await lock. |
| 9 | /// coroutines which are waiting for the lock are suspended, and | |
| 9 | /// Functions which are waiting for the lock are suspended, and | |
| 10 | 10 | /// are resumed when the lock is released, in order. |
| 11 | 11 | /// Many readers can hold the lock at the same time; however locking for writing is exclusive. |
| 12 | 12 | /// When a read lock is held, it will not be released until the reader queue is empty. |
| ... | ... | @@ -107,8 +107,7 @@ pub const RwLock = struct { |
| 107 | 107 | |
| 108 | 108 | self.reader_queue.put(&my_tick_node); |
| 109 | 109 | |
| 110 | // At this point, we are in the reader_queue, so we might have already been resumed and this coroutine | |
| 111 | // frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame. | |
| 110 | // At this point, we are in the reader_queue, so we might have already been resumed. | |
| 112 | 111 | |
| 113 | 112 | // We set this bit so that later we can rely on the fact, that if reader_queue_empty_bit is 1, |
| 114 | 113 | // some actor will attempt to grab the lock. |
| ... | ... | @@ -139,8 +138,7 @@ pub const RwLock = struct { |
| 139 | 138 | |
| 140 | 139 | self.writer_queue.put(&my_tick_node); |
| 141 | 140 | |
| 142 | // At this point, we are in the writer_queue, so we might have already been resumed and this coroutine | |
| 143 | // frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame. | |
| 141 | // At this point, we are in the writer_queue, so we might have already been resumed. | |
| 144 | 142 | |
| 145 | 143 | // We set this bit so that later we can rely on the fact, that if writer_queue_empty_bit is 1, |
| 146 | 144 | // some actor will attempt to grab the lock. |
std/event/rwlocked.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ const RwLock = std.event.RwLock; |
| 3 | 3 | const Loop = std.event.Loop; |
| 4 | 4 | |
| 5 | 5 | /// Thread-safe async/await RW lock that protects one piece of data. |
| 6 | /// coroutines which are waiting for the lock are suspended, and | |
| 6 | /// Functions which are waiting for the lock are suspended, and | |
| 7 | 7 | /// are resumed when the lock is released, in order. |
| 8 | 8 | pub fn RwLocked(comptime T: type) type { |
| 9 | 9 | return struct { |
std/zig/parser_test.zig+3-3| ... | ... | @@ -2103,7 +2103,7 @@ test "zig fmt: inline asm" { |
| 2103 | 2103 | ); |
| 2104 | 2104 | } |
| 2105 | 2105 | |
| 2106 | test "zig fmt: coroutines" { | |
| 2106 | test "zig fmt: async functions" { | |
| 2107 | 2107 | try testCanonical( |
| 2108 | 2108 | \\async fn simpleAsyncFn() void { |
| 2109 | 2109 | \\ const a = async a.b(); |
| ... | ... | @@ -2115,8 +2115,8 @@ test "zig fmt: coroutines" { |
| 2115 | 2115 | \\ await p; |
| 2116 | 2116 | \\} |
| 2117 | 2117 | \\ |
| 2118 | \\test "coroutine suspend, resume, cancel" { | |
| 2119 | \\ const p: anyframe = try async<std.debug.global_allocator> testAsyncSeq(); | |
| 2118 | \\test "suspend, resume, cancel" { | |
| 2119 | \\ const p: anyframe = async testAsyncSeq(); | |
| 2120 | 2120 | \\ resume p; |
| 2121 | 2121 | \\ cancel p; |
| 2122 | 2122 | \\} |