avoid the word "coroutine", they're "async functions"

This commit is contained in:
Andrew Kelley 2019-08-13 14:14:19 -04:00
parent 82d4ebe53a
commit 5092634103
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
23 changed files with 175 additions and 199 deletions

View File

@ -1,4 +1,4 @@
* grep for "coroutine" and "coro" and replace all that nomenclature with "async functions" * zig fmt support for the syntax
* alignment of variables not being respected in async functions * alignment of variables not being respected in async functions
* await of a non async function * await of a non async function
* async call on a non async function * async call on a non async function

View File

@ -5968,9 +5968,10 @@ test "global assembly" {
<p>TODO: @atomic rmw</p> <p>TODO: @atomic rmw</p>
<p>TODO: builtin atomic memory ordering enum</p> <p>TODO: builtin atomic memory ordering enum</p>
{#header_close#} {#header_close#}
{#header_open|Coroutines#} {#header_open|Async Functions#}
<p> <p>
A coroutine is a generalization of a function. An async function is a function whose callsite is split into an {#syntax#}async{#endsyntax#} initiation,
followed by an {#syntax#}await{#endsyntax#} completion. They can also be canceled.
</p> </p>
<p> <p>
When you call a function, it creates a stack frame, When you call a function, it creates a stack frame,
@ -5980,14 +5981,14 @@ test "global assembly" {
until the function returns. until the function returns.
</p> </p>
<p> <p>
A coroutine is like a function, but it can be suspended An async function is like a function, but it can be suspended
and resumed any number of times, and then it must be and resumed any number of times, and then it must be
explicitly destroyed. When a coroutine suspends, it explicitly destroyed. When an async function suspends, it
returns to the resumer. returns to the resumer.
</p> </p>
{#header_open|Minimal Coroutine Example#} {#header_open|Minimal Async Function Example#}
<p> <p>
Declare a coroutine with the {#syntax#}async{#endsyntax#} keyword. Declare an async function with the {#syntax#}async{#endsyntax#} keyword.
The expression in angle brackets must evaluate to a struct The expression in angle brackets must evaluate to a struct
which has these fields: which has these fields:
</p> </p>
@ -6006,8 +6007,8 @@ test "global assembly" {
the function generic. Zig will infer the allocator type when the async function is called. the function generic. Zig will infer the allocator type when the async function is called.
</p> </p>
<p> <p>
Call a coroutine with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets Call an async function with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets
is a pointer to the allocator struct that the coroutine expects. is a pointer to the allocator struct that the async function expects.
</p> </p>
<p> <p>
The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#} 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;
var the_frame: anyframe = undefined; var the_frame: anyframe = undefined;
var result = false; var result = false;
test "coroutine suspend with block" { test "async function suspend with block" {
_ = async testSuspendBlock(); _ = async testSuspendBlock();
std.debug.assert(!result); std.debug.assert(!result);
resume the_frame; resume the_frame;
@ -6074,7 +6075,7 @@ fn testSuspendBlock() void {
} }
{#code_end#} {#code_end#}
<p> <p>
Every suspend point in an async function represents a point at which the coroutine Every suspend point in an async function represents a point at which the async function
could be destroyed. If that happens, {#syntax#}defer{#endsyntax#} expressions that are in could be destroyed. If that happens, {#syntax#}defer{#endsyntax#} expressions that are in
scope are run, as well as {#syntax#}errdefer{#endsyntax#} expressions. scope are run, as well as {#syntax#}errdefer{#endsyntax#} expressions.
</p> </p>
@ -6083,14 +6084,14 @@ fn testSuspendBlock() void {
</p> </p>
{#header_open|Resuming from Suspend Blocks#} {#header_open|Resuming from Suspend Blocks#}
<p> <p>
Upon entering a {#syntax#}suspend{#endsyntax#} block, the coroutine is already considered Upon entering a {#syntax#}suspend{#endsyntax#} block, the async function is already considered
suspended, and can be resumed. For example, if you started another kernel thread, suspended, and can be resumed. For example, if you started another kernel thread,
and had that thread call {#syntax#}resume{#endsyntax#} on the promise handle provided by the and had that thread call {#syntax#}resume{#endsyntax#} on the promise handle provided by the
{#syntax#}suspend{#endsyntax#} block, the new thread would begin executing after the suspend {#syntax#}suspend{#endsyntax#} block, the new thread would begin executing after the suspend
block, while the old thread continued executing the suspend block. block, while the old thread continued executing the suspend block.
</p> </p>
<p> <p>
However, the coroutine can be directly resumed from the suspend block, in which case it However, the async function can be directly resumed from the suspend block, in which case it
never returns to its resumer and continues executing. never returns to its resumer and continues executing.
</p> </p>
{#code_begin|test#} {#code_begin|test#}
@ -6127,8 +6128,8 @@ async fn testResumeFromSuspend(my_result: *i32) void {
If the async function associated with the promise handle has already returned, If the async function associated with the promise handle has already returned,
then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value. then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.
Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its
promise handle with the target coroutine. It becomes the target coroutine's responsibility promise handle with the target async function. It becomes the target async function's responsibility
to have ensured that it will be resumed or destroyed. When the target coroutine reaches to have ensured that it will be resumed or destroyed. When the target async function reaches
its return statement, it gives the return value to the awaiter, destroys itself, and then its return statement, it gives the return value to the awaiter, destroys itself, and then
resumes the awaiter. resumes the awaiter.
</p> </p>
@ -6137,7 +6138,7 @@ async fn testResumeFromSuspend(my_result: *i32) void {
</p> </p>
<p> <p>
{#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#}, {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},
a coroutine can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions. a async function can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions.
</p> </p>
{#code_begin|test#} {#code_begin|test#}
const std = @import("std"); const std = @import("std");
@ -6146,7 +6147,7 @@ const assert = std.debug.assert;
var the_frame: anyframe = undefined; var the_frame: anyframe = undefined;
var final_result: i32 = 0; var final_result: i32 = 0;
test "coroutine await" { test "async function await" {
seq('a'); seq('a');
_ = async amain(); _ = async amain();
seq('f'); seq('f');
@ -6188,7 +6189,7 @@ fn seq(c: u8) void {
{#header_close#} {#header_close#}
{#header_open|Open Issues#} {#header_open|Open Issues#}
<p> <p>
There are a few issues with coroutines that are considered unresolved. Best be aware of them, There are a few issues with async function that are considered unresolved. Best be aware of them,
as the situation is likely to change before 1.0.0: as the situation is likely to change before 1.0.0:
</p> </p>
<ul> <ul>
@ -6202,7 +6203,7 @@ fn seq(c: u8) void {
</li> </li>
<li> <li>
Zig does not take advantage of LLVM's allocation elision optimization for Zig does not take advantage of LLVM's allocation elision optimization for
coroutines. It crashed LLVM when I tried to do it the first time. This is async function. It crashed LLVM when I tried to do it the first time. This is
related to the other 2 bullet points here. See related to the other 2 bullet points here. See
<a href="https://github.com/ziglang/zig/issues/802">#802</a>. <a href="https://github.com/ziglang/zig/issues/802">#802</a>.
</li> </li>
@ -8016,8 +8017,7 @@ pub fn build(b: *Builder) void {
<p>Zig has a compile option <code>--single-threaded</code> which has the following effects: <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
<ul> <ul>
<li>All {#link|Thread Local Variables#} are treated as {#link|Global Variables#}.</li> <li>All {#link|Thread Local Variables#} are treated as {#link|Global Variables#}.</li>
<li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead. <li>The overhead of {#link|Async Functions#} becomes equivalent to function call overhead.</li>
TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>
<li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#} <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
and therefore various userland APIs which read this variable become more efficient. and therefore various userland APIs which read this variable become more efficient.
For example {#syntax#}std.Mutex{#endsyntax#} becomes For example {#syntax#}std.Mutex{#endsyntax#} becomes

View File

@ -1904,20 +1904,6 @@ pub const Builder = struct {
} }
return error.Unimplemented; return error.Unimplemented;
//ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_field_ptr, return_value);
//IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node,
// get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
//// TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig
//IrInstruction *replacement_value = irb->exec->coro_handle;
//IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node,
// promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr,
// AtomicRmwOp_xchg, AtomicOrderSeqCst);
//ir_build_store_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, maybe_await_handle);
//IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);
//IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
//return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,
// is_comptime);
//// the above blocks are rendered by ir_gen after the rest of codegen
} }
const Ident = union(enum) { const Ident = union(enum) {

View File

@ -627,7 +627,7 @@ fn constructLinkerArgsWasm(ctx: *Context) void {
fn addFnObjects(ctx: *Context) !void { fn addFnObjects(ctx: *Context) !void {
// at this point it's guaranteed nobody else has this lock, so we circumvent it // at this point it's guaranteed nobody else has this lock, so we circumvent it
// and avoid having to be a coroutine // and avoid having to be an async function
const fn_link_set = &ctx.comp.fn_link_set.private_data; const fn_link_set = &ctx.comp.fn_link_set.private_data;
var it = fn_link_set.first; var it = fn_link_set.first;

View File

@ -52,7 +52,7 @@ const Command = struct {
pub fn main() !void { pub fn main() !void {
// This allocator needs to be thread-safe because we use it for the event.Loop // This allocator needs to be thread-safe because we use it for the event.Loop
// which multiplexes coroutines onto kernel threads. // which multiplexes async functions onto kernel threads.
// libc allocator is guaranteed to have this property. // libc allocator is guaranteed to have this property.
const allocator = std.heap.c_allocator; const allocator = std.heap.c_allocator;

View File

@ -142,7 +142,8 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
return Error.None; return Error.None;
} }
// TODO: just use the actual self-hosted zig fmt. Until the coroutine rewrite, we use a blocking implementation. // TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
// we use a blocking implementation.
export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int { export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
if (std.debug.runtime_safety) { if (std.debug.runtime_safety) {
fmtMain(argc, argv) catch unreachable; fmtMain(argc, argv) catch unreachable;

View File

@ -1265,7 +1265,7 @@ enum ZigTypeId {
ZigTypeIdBoundFn, ZigTypeIdBoundFn,
ZigTypeIdArgTuple, ZigTypeIdArgTuple,
ZigTypeIdOpaque, ZigTypeIdOpaque,
ZigTypeIdCoroFrame, ZigTypeIdFnFrame,
ZigTypeIdAnyFrame, ZigTypeIdAnyFrame,
ZigTypeIdVector, ZigTypeIdVector,
ZigTypeIdEnumLiteral, ZigTypeIdEnumLiteral,
@ -1281,7 +1281,7 @@ struct ZigTypeOpaque {
Buf *bare_name; Buf *bare_name;
}; };
struct ZigTypeCoroFrame { struct ZigTypeFnFrame {
ZigFn *fn; ZigFn *fn;
ZigType *locals_struct; ZigType *locals_struct;
}; };
@ -1315,7 +1315,7 @@ struct ZigType {
ZigTypeBoundFn bound_fn; ZigTypeBoundFn bound_fn;
ZigTypeVector vector; ZigTypeVector vector;
ZigTypeOpaque opaque; ZigTypeOpaque opaque;
ZigTypeCoroFrame frame; ZigTypeFnFrame frame;
ZigTypeAnyFrame any_frame; ZigTypeAnyFrame any_frame;
} data; } data;
@ -1376,7 +1376,7 @@ struct ZigFn {
LLVMTypeRef raw_type_ref; LLVMTypeRef raw_type_ref;
ZigLLVMDIType *raw_di_type; ZigLLVMDIType *raw_di_type;
ZigType *frame_type; // coro frame type ZigType *frame_type;
// in the case of normal functions this is the implicit return type // in the case of normal functions this is the implicit return type
// in the case of async functions this is the implicit return type according to the // in the case of async functions this is the implicit return type according to the
// zig source code, not according to zig ir // zig source code, not according to zig ir
@ -2368,7 +2368,7 @@ enum IrInstructionId {
IrInstructionIdSuspendFinish, IrInstructionIdSuspendFinish,
IrInstructionIdAwaitSrc, IrInstructionIdAwaitSrc,
IrInstructionIdAwaitGen, IrInstructionIdAwaitGen,
IrInstructionIdCoroResume, IrInstructionIdResume,
IrInstructionIdTestCancelRequested, IrInstructionIdTestCancelRequested,
IrInstructionIdSpillBegin, IrInstructionIdSpillBegin,
IrInstructionIdSpillEnd, IrInstructionIdSpillEnd,
@ -3640,7 +3640,7 @@ struct IrInstructionAwaitGen {
IrInstruction *result_loc; IrInstruction *result_loc;
}; };
struct IrInstructionCoroResume { struct IrInstructionResume {
IrInstruction base; IrInstruction base;
IrInstruction *frame; IrInstruction *frame;
@ -3751,12 +3751,12 @@ static const size_t maybe_null_index = 1;
static const size_t err_union_payload_index = 0; static const size_t err_union_payload_index = 0;
static const size_t err_union_err_index = 1; static const size_t err_union_err_index = 1;
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
static const size_t coro_fn_ptr_index = 0; static const size_t frame_fn_ptr_index = 0;
static const size_t coro_resume_index = 1; static const size_t frame_resume_index = 1;
static const size_t coro_awaiter_index = 2; static const size_t frame_awaiter_index = 2;
static const size_t coro_prev_val_index = 3; static const size_t frame_prev_val_index = 3;
static const size_t coro_ret_start = 4; static const size_t frame_ret_start = 4;
// TODO https://github.com/ziglang/zig/issues/3056 // TODO https://github.com/ziglang/zig/issues/3056
// We require this to be a power of 2 so that we can use shifting rather than // We require this to be a power of 2 so that we can use shifting rather than

View File

@ -234,7 +234,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
return type_entry->data.enumeration.decl_node; return type_entry->data.enumeration.decl_node;
case ZigTypeIdUnion: case ZigTypeIdUnion:
return type_entry->data.unionation.decl_node; return type_entry->data.unionation.decl_node;
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return type_entry->data.frame.fn->proto_node; return type_entry->data.frame.fn->proto_node;
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdMetaType: case ZigTypeIdMetaType:
@ -271,7 +271,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
return type_entry->data.structure.resolve_status >= status; return type_entry->data.structure.resolve_status >= status;
case ZigTypeIdUnion: case ZigTypeIdUnion:
return type_entry->data.unionation.resolve_status >= status; return type_entry->data.unionation.resolve_status >= status;
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
switch (status) { switch (status) {
case ResolveStatusInvalid: case ResolveStatusInvalid:
zig_unreachable(); zig_unreachable();
@ -394,18 +394,18 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) {
zig_unreachable(); zig_unreachable();
} }
ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn) { ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
if (fn->frame_type != nullptr) { if (fn->frame_type != nullptr) {
return fn->frame_type; return fn->frame_type;
} }
ZigType *entry = new_type_table_entry(ZigTypeIdCoroFrame); ZigType *entry = new_type_table_entry(ZigTypeIdFnFrame);
buf_resize(&entry->name, 0); buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name)); buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name));
entry->data.frame.fn = fn; entry->data.frame.fn = fn;
// Coroutine frames are always non-zero bits because they always have a resume index. // Async function frames are always non-zero bits because they always have a resume index.
entry->abi_size = SIZE_MAX; entry->abi_size = SIZE_MAX;
entry->size_in_bits = SIZE_MAX; entry->size_in_bits = SIZE_MAX;
@ -1108,7 +1108,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
add_node_error(g, source_node, add_node_error(g, source_node,
buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", 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) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdVoid: case ZigTypeIdVoid:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return false; return false;
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
@ -1370,7 +1370,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
switch (type_requires_comptime(g, type_entry)) { switch (type_requires_comptime(g, type_entry)) {
case ReqCompTimeNo: case ReqCompTimeNo:
@ -1467,7 +1467,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
switch (type_requires_comptime(g, fn_type_id.return_type)) { switch (type_requires_comptime(g, fn_type_id.return_type)) {
case ReqCompTimeInvalid: case ReqCompTimeInvalid:
@ -3080,7 +3080,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return type_entry; return type_entry;
} }
@ -3582,7 +3582,7 @@ bool is_container(ZigType *type_entry) {
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return false; return false;
} }
@ -3640,7 +3640,7 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
} }
@ -3672,7 +3672,7 @@ bool type_is_nonnull_ptr(ZigType *type) {
return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type); return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type);
} }
static uint32_t get_coro_frame_align_bytes(CodeGen *g) { static uint32_t get_async_frame_align_bytes(CodeGen *g) {
uint32_t a = g->pointer_size_bytes * 2; uint32_t a = g->pointer_size_bytes * 2;
// promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw // promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw
if (a < 8) a = 8; if (a < 8) a = 8;
@ -3691,7 +3691,7 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
// See http://lists.llvm.org/pipermail/llvm-dev/2018-September/126142.html // See http://lists.llvm.org/pipermail/llvm-dev/2018-September/126142.html
return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
} else if (ptr_type->id == ZigTypeIdAnyFrame) { } else if (ptr_type->id == ZigTypeIdAnyFrame) {
return get_coro_frame_align_bytes(g); return get_async_frame_align_bytes(g);
} else { } else {
zig_unreachable(); zig_unreachable();
} }
@ -3779,7 +3779,7 @@ bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *sour
} }
static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) { static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {
ZigType *frame_type = get_coro_frame_type(g, fn); ZigType *frame_type = get_fn_frame_type(g, fn);
Error err; Error err;
if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) { if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) {
fn->anal_state = FnAnalStateInvalid; fn->anal_state = FnAnalStateInvalid;
@ -4218,7 +4218,7 @@ bool handle_is_ptr(ZigType *type_entry) {
return false; return false;
case ZigTypeIdArray: case ZigTypeIdArray:
case ZigTypeIdStruct: case ZigTypeIdStruct:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return type_has_bits(type_entry); return type_has_bits(type_entry);
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
return type_has_bits(type_entry->data.error_union.payload_type); return type_has_bits(type_entry->data.error_union.payload_type);
@ -4463,7 +4463,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
case ZigTypeIdVector: case ZigTypeIdVector:
// TODO better hashing algorithm // TODO better hashing algorithm
return 3647867726; return 3647867726;
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
// TODO better hashing algorithm // TODO better hashing algorithm
return 675741936; return 675741936;
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
@ -4533,7 +4533,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdErrorSet: case ZigTypeIdErrorSet:
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return false; return false;
@ -4606,7 +4606,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdPointer: case ZigTypeIdPointer:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return true; return true;
@ -4739,7 +4739,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdBool: case ZigTypeIdBool:
case ZigTypeIdFloat: case ZigTypeIdFloat:
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return OnePossibleValueNo; return OnePossibleValueNo;
case ZigTypeIdUndefined: case ZigTypeIdUndefined:
@ -4828,7 +4828,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdFloat: case ZigTypeIdFloat:
case ZigTypeIdVoid: case ZigTypeIdVoid:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return ReqCompTimeNo; return ReqCompTimeNo;
} }
@ -5161,7 +5161,7 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
return fn_type; return fn_type;
} }
static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
Error err; Error err;
if (frame_type->data.frame.locals_struct != nullptr) if (frame_type->data.frame.locals_struct != nullptr)
@ -5231,7 +5231,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
if (!fn_is_async(callee)) if (!fn_is_async(callee))
continue; continue;
ZigType *callee_frame_type = get_coro_frame_type(g, callee); ZigType *callee_frame_type = get_fn_frame_type(g, callee);
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1); IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
alloca_gen->base.id = IrInstructionIdAllocaGen; alloca_gen->base.id = IrInstructionIdAllocaGen;
@ -5244,7 +5244,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
call->frame_result_loc = &alloca_gen->base; call->frame_result_loc = &alloca_gen->base;
} }
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
ZigList<ZigType *> field_types = {}; ZigList<ZigType *> field_types = {};
ZigList<const char *> field_names = {}; ZigList<const char *> field_names = {};
@ -5366,8 +5366,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
return resolve_enum_zero_bits(g, ty); return resolve_enum_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdUnion) { } else if (ty->id == ZigTypeIdUnion) {
return resolve_union_alignment(g, ty); return resolve_union_alignment(g, ty);
} else if (ty->id == ZigTypeIdCoroFrame) { } else if (ty->id == ZigTypeIdFnFrame) {
return resolve_coro_frame(g, ty); return resolve_async_frame(g, ty);
} }
return ErrorNone; return ErrorNone;
case ResolveStatusSizeKnown: case ResolveStatusSizeKnown:
@ -5377,8 +5377,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
return resolve_enum_zero_bits(g, ty); return resolve_enum_zero_bits(g, ty);
} else if (ty->id == ZigTypeIdUnion) { } else if (ty->id == ZigTypeIdUnion) {
return resolve_union_type(g, ty); return resolve_union_type(g, ty);
} else if (ty->id == ZigTypeIdCoroFrame) { } else if (ty->id == ZigTypeIdFnFrame) {
return resolve_coro_frame(g, ty); return resolve_async_frame(g, ty);
} }
return ErrorNone; return ErrorNone;
case ResolveStatusLLVMFwdDecl: case ResolveStatusLLVMFwdDecl:
@ -5573,7 +5573,7 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
return false; return false;
} }
return true; return true;
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_panic("TODO"); zig_panic("TODO");
@ -5929,7 +5929,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
buf_appendf(buf, "(args value)"); buf_appendf(buf, "(args value)");
return; return;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
buf_appendf(buf, "(TODO: async function frame value)"); buf_appendf(buf, "(TODO: async function frame value)");
return; return;
@ -5992,7 +5992,7 @@ uint32_t type_id_hash(TypeId x) {
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
@ -6042,7 +6042,7 @@ bool type_id_eql(TypeId a, TypeId b) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
@ -6209,7 +6209,7 @@ static const ZigTypeId all_type_ids[] = {
ZigTypeIdBoundFn, ZigTypeIdBoundFn,
ZigTypeIdArgTuple, ZigTypeIdArgTuple,
ZigTypeIdOpaque, ZigTypeIdOpaque,
ZigTypeIdCoroFrame, ZigTypeIdFnFrame,
ZigTypeIdAnyFrame, ZigTypeIdAnyFrame,
ZigTypeIdVector, ZigTypeIdVector,
ZigTypeIdEnumLiteral, ZigTypeIdEnumLiteral,
@ -6274,7 +6274,7 @@ size_t type_id_index(ZigType *entry) {
return 20; return 20;
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
return 21; return 21;
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return 22; return 22;
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return 23; return 23;
@ -6338,7 +6338,7 @@ const char *type_id_name(ZigTypeId id) {
return "Opaque"; return "Opaque";
case ZigTypeIdVector: case ZigTypeIdVector:
return "Vector"; return "Vector";
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return "Frame"; return "Frame";
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return "AnyFrame"; return "AnyFrame";
@ -6782,7 +6782,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
} }
static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status, static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,
ZigType *coro_frame_type) ZigType *async_frame_type)
{ {
assert(struct_type->id == ZigTypeIdStruct); assert(struct_type->id == ZigTypeIdStruct);
assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid); assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid);
@ -6887,11 +6887,11 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
packed_bits_offset = next_packed_bits_offset; packed_bits_offset = next_packed_bits_offset;
} else { } else {
LLVMTypeRef llvm_type; LLVMTypeRef llvm_type;
if (i == 0 && coro_frame_type != nullptr) { if (i == 0 && async_frame_type != nullptr) {
assert(coro_frame_type->id == ZigTypeIdCoroFrame); assert(async_frame_type->id == ZigTypeIdFnFrame);
assert(field_type->id == ZigTypeIdFn); assert(field_type->id == ZigTypeIdFn);
resolve_llvm_types_fn(g, coro_frame_type->data.frame.fn); resolve_llvm_types_fn(g, async_frame_type->data.frame.fn);
llvm_type = LLVMPointerType(coro_frame_type->data.frame.fn->raw_type_ref, 0); llvm_type = LLVMPointerType(async_frame_type->data.frame.fn->raw_type_ref, 0);
} else { } else {
llvm_type = get_llvm_type(g, field_type); llvm_type = get_llvm_type(g, field_type);
} }
@ -7594,7 +7594,7 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
// first "parameter" is return value // first "parameter" is return value
param_di_types.append(get_llvm_di_type(g, gen_return_type)); param_di_types.append(get_llvm_di_type(g, gen_return_type));
ZigType *frame_type = get_coro_frame_type(g, fn); ZigType *frame_type = get_fn_frame_type(g, fn);
ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); ZigType *ptr_type = get_pointer_to_type(g, frame_type, false);
if ((err = type_resolve(g, ptr_type, ResolveStatusLLVMFwdDecl))) if ((err = type_resolve(g, ptr_type, ResolveStatusLLVMFwdDecl)))
zig_unreachable(); zig_unreachable();
@ -7634,7 +7634,7 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
get_llvm_di_type(g, g->err_tag_type), ""); get_llvm_di_type(g, g->err_tag_type), "");
} }
static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) { static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type); resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type);
frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type; frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type; 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
ZigList<LLVMTypeRef> field_types = {}; ZigList<LLVMTypeRef> field_types = {};
ZigList<ZigLLVMDIType *> di_element_types = {}; ZigList<ZigLLVMDIType *> di_element_types = {};
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
field_types.append(ptr_fn_llvm_type); // fn_ptr field_types.append(ptr_fn_llvm_type); // fn_ptr
field_types.append(usize_type_ref); // resume_index field_types.append(usize_type_ref); // resume_index
field_types.append(usize_type_ref); // awaiter field_types.append(usize_type_ref); // awaiter
@ -7824,8 +7824,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len); type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len);
return; return;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status); return resolve_llvm_types_async_frame(g, type, wanted_resolve_status);
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return resolve_llvm_types_any_frame(g, type, wanted_resolve_status); return resolve_llvm_types_any_frame(g, type, wanted_resolve_status);
} }

View File

@ -16,7 +16,7 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg);
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg);
void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg); void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg);
ZigType *new_type_table_entry(ZigTypeId id); ZigType *new_type_table_entry(ZigTypeId id);
ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn); ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn);
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, bool is_volatile, PtrLen ptr_len,

View File

@ -305,16 +305,16 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
zig_unreachable(); zig_unreachable();
} }
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) { static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) {
// [0] *ReturnType (callee's) // [0] *ReturnType (callee's)
// [1] *ReturnType (awaiter's) // [1] *ReturnType (awaiter's)
// [2] ReturnType // [2] ReturnType
uint32_t return_field_count = type_has_bits(return_type) ? 3 : 0; uint32_t return_field_count = type_has_bits(return_type) ? 3 : 0;
return coro_ret_start + return_field_count; return frame_ret_start + return_field_count;
} }
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) { static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {
bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type); bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type);
// [0] *StackTrace // [0] *StackTrace
@ -322,7 +322,7 @@ static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) {
return frame_index_trace_arg(g, return_type) + trace_field_count; return frame_index_trace_arg(g, return_type) + trace_field_count;
} }
// label (grep this): [coro_frame_struct_layout] // label (grep this): [fn_frame_struct_layout]
static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) { static uint32_t frame_index_trace_stack(CodeGen *g, FnTypeId *fn_type_id) {
uint32_t result = frame_index_arg(g, fn_type_id->return_type); uint32_t result = frame_index_arg(g, fn_type_id->return_type);
for (size_t i = 0; i < fn_type_id->param_count; i += 1) { 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
{ {
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
if (fn_val == nullptr) { if (fn_val == nullptr) {
LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_fn_ptr_index, ""); LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, "");
fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
} }
if (arg_val == nullptr) { if (arg_val == nullptr) {
@ -2373,7 +2373,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
// If the awaiter result pointer is non-null, we need to copy the result to there. // If the awaiter result pointer is non-null, we need to copy the result to there.
LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult");
LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd");
LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start + 1, ""); LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, "");
LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, "");
LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr));
LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); 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
if (ret_has_bits) { if (ret_has_bits) {
// Use the result location which is inside the frame if this is an async call. // Use the result location which is inside the frame if this is an async call.
ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
} }
} else { } else {
LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); 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
if (ret_has_bits) { if (ret_has_bits) {
if (result_loc == nullptr) { if (result_loc == nullptr) {
// return type is a scalar, but we still need a pointer to it. Use the async fn frame. // return type is a scalar, but we still need a pointer to it. Use the async fn frame.
ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
} else { } else {
// Use the call instruction's result location. // Use the call instruction's result location.
ret_ptr = result_loc; ret_ptr = result_loc;
} }
// Store a zero in the awaiter's result ptr to indicate we do not need a copy made. // Store a zero in the awaiter's result ptr to indicate we do not need a copy made.
LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, ""); LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, "");
LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr))); LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr)));
LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr);
} }
@ -3919,19 +3919,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (instruction->is_async || callee_is_async) { if (instruction->is_async || callee_is_async) {
assert(frame_result_loc != nullptr); assert(frame_result_loc != nullptr);
LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_fn_ptr_index, ""); LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, "");
LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val,
LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), ""); LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), "");
LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr);
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index, ""); LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_resume_index, "");
LLVMBuildStore(g->builder, zero, resume_index_ptr); LLVMBuildStore(g->builder, zero, resume_index_ptr);
LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_awaiter_index, ""); LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, "");
LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);
if (ret_has_bits) { if (ret_has_bits) {
LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start, ""); LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");
LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
} }
} else { } else {
@ -4018,7 +4018,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
if (result_loc != nullptr) if (result_loc != nullptr)
return get_handle_value(g, result_loc, src_return_type, ptr_result_type); return get_handle_value(g, result_loc, src_return_type, ptr_result_type);
LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 2, ""); LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
return LLVMBuildLoad(g->builder, result_ptr, ""); return LLVMBuildLoad(g->builder, result_ptr, "");
} }
@ -5491,7 +5491,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
// supply null for the awaiter return pointer (no copy needed) // supply null for the awaiter return pointer (no copy needed)
if (type_has_bits(result_type)) { if (type_has_bits(result_type)) {
LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start + 1, ""); LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");
LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))),
awaiter_ret_ptr_ptr); awaiter_ret_ptr_ptr);
} }
@ -5506,7 +5506,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
LLVMValueRef awaiter_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); LLVMValueRef awaiter_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, ""); LLVMValueRef awaiter_ored_val = LLVMBuildOr(g->builder, awaiter_val, one, "");
LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, "");
LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val, LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_ored_val,
LLVMAtomicOrderingRelease); LLVMAtomicOrderingRelease);
@ -5549,7 +5549,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
LLVMValueRef result_loc = (instruction->result_loc == nullptr) ? LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
nullptr : ir_llvm_value(g, instruction->result_loc); nullptr : ir_llvm_value(g, instruction->result_loc);
if (type_has_bits(result_type)) { if (type_has_bits(result_type)) {
LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start + 1, ""); LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");
if (result_loc == nullptr) { if (result_loc == nullptr) {
// no copy needed // no copy needed
LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))),
@ -5570,7 +5570,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
// caller's own frame pointer // caller's own frame pointer
LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, "");
LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, "");
LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, LLVMValueRef prev_val = LLVMBuildAtomicRMW(g->builder, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val,
LLVMAtomicOrderingRelease, g->is_single_threaded); LLVMAtomicOrderingRelease, g->is_single_threaded);
@ -5608,9 +5608,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
return nullptr; return nullptr;
} }
static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutable *executable, IrInstructionResume *instruction) {
IrInstructionCoroResume *instruction)
{
LLVMValueRef frame = ir_llvm_value(g, instruction->frame); LLVMValueRef frame = ir_llvm_value(g, instruction->frame);
ZigType *frame_type = instruction->frame->value.type; ZigType *frame_type = instruction->frame->value.type;
assert(frame_type->id == ZigTypeIdAnyFrame); assert(frame_type->id == ZigTypeIdAnyFrame);
@ -5921,8 +5919,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction); return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction);
case IrInstructionIdSuspendFinish: case IrInstructionIdSuspendFinish:
return ir_render_suspend_finish(g, executable, (IrInstructionSuspendFinish *)instruction); return ir_render_suspend_finish(g, executable, (IrInstructionSuspendFinish *)instruction);
case IrInstructionIdCoroResume: case IrInstructionIdResume:
return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction); return ir_render_resume(g, executable, (IrInstructionResume *)instruction);
case IrInstructionIdFrameSizeGen: case IrInstructionIdFrameSizeGen:
return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction); return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
case IrInstructionIdAwaitGen: case IrInstructionIdAwaitGen:
@ -6195,7 +6193,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
} }
return val; return val;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO bit pack an async function frame"); zig_panic("TODO bit pack an async function frame");
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_panic("TODO bit pack an anyframe"); zig_panic("TODO bit pack an anyframe");
@ -6727,7 +6725,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
zig_unreachable(); zig_unreachable();
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_panic("TODO"); zig_panic("TODO");
@ -7171,12 +7169,12 @@ static void do_code_gen(CodeGen *g) {
LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block);
render_async_spills(g); render_async_spills(g);
g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_awaiter_index, ""); g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_awaiter_index, "");
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_resume_index, ""); LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, "");
g->cur_async_resume_index_ptr = resume_index_ptr; g->cur_async_resume_index_ptr = resume_index_ptr;
if (type_has_bits(fn_type_id->return_type)) { if (type_has_bits(fn_type_id->return_type)) {
LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, coro_ret_start, ""); LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, "");
g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, "");
} }
if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { 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) {
trace_field_index_stack, ""); trace_field_index_stack, "");
} }
g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, g->cur_async_prev_val_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr,
coro_prev_val_index, ""); frame_prev_val_index, "");
LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); 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
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet: case ZigTypeIdErrorSet:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdVoid: case ZigTypeIdVoid:
@ -9414,7 +9412,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
case ZigTypeIdUndefined: case ZigTypeIdUndefined:
case ZigTypeIdNull: case ZigTypeIdNull:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
} }
@ -9583,7 +9581,7 @@ static void gen_h_file(CodeGen *g) {
case ZigTypeIdOptional: case ZigTypeIdOptional:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();

View File

@ -321,7 +321,7 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
return false; return false;
} }
zig_unreachable(); zig_unreachable();
@ -1058,8 +1058,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAwaitGen *) {
return IrInstructionIdAwaitGen; return IrInstructionIdAwaitGen;
} }
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) { static constexpr IrInstructionId ir_instruction_id(IrInstructionResume *) {
return IrInstructionIdCoroResume; return IrInstructionIdResume;
} }
static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelRequested *) { static constexpr IrInstructionId ir_instruction_id(IrInstructionTestCancelRequested *) {
@ -3321,10 +3321,8 @@ static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_i
return &instruction->base; return &instruction->base;
} }
static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) {
IrInstruction *frame) IrInstructionResume *instruction = ir_build_instruction<IrInstructionResume>(irb, scope, source_node);
{
IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node);
instruction->base.value.type = irb->codegen->builtin_types.entry_void; instruction->base.value.type = irb->codegen->builtin_types.entry_void;
instruction->frame = frame; instruction->frame = frame;
@ -7964,7 +7962,7 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
if (target_inst == irb->codegen->invalid_instruction) if (target_inst == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
return ir_build_coro_resume(irb, scope, node, target_inst); return ir_build_resume(irb, scope, node, target_inst);
} }
static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, 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
// *@Frame(func) to anyframe->T or anyframe // *@Frame(func) to anyframe->T or anyframe
if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && if (actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdCoroFrame && wanted_type->id == ZigTypeIdAnyFrame) actual_type->data.pointer.child_type->id == ZigTypeIdFnFrame && wanted_type->id == ZigTypeIdAnyFrame)
{ {
bool ok = true; bool ok = true;
if (wanted_type->data.any_frame.result_type != nullptr) { if (wanted_type->data.any_frame.result_type != nullptr) {
@ -13123,7 +13121,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
case ZigTypeIdNull: case ZigTypeIdNull:
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
operator_allowed = false; operator_allowed = false;
break; break;
case ZigTypeIdOptional: case ZigTypeIdOptional:
@ -14488,7 +14486,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
ir_add_error(ira, target, ir_add_error(ira, target,
buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
@ -14514,7 +14512,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdEnumLiteral: case ZigTypeIdEnumLiteral:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
ir_add_error(ira, target, ir_add_error(ira, target,
buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); 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
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
} }
ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);
IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
frame_type, nullptr, true, true, false); frame_type, nullptr, true, true, false);
if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { 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
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry)); return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
@ -17910,7 +17908,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
{ {
ResolveStatus needed_status = (align_bytes == 0) ? ResolveStatus needed_status = (align_bytes == 0) ?
@ -18026,7 +18024,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
{ {
if ((err = ensure_complete_type(ira->codegen, child_type))) if ((err = ensure_complete_type(ira->codegen, child_type)))
@ -18078,7 +18076,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
{ {
uint64_t size_in_bytes = type_size(ira->codegen, type_entry); uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
@ -18643,7 +18641,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
ir_add_error(ira, &switch_target_instruction->base, ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); 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
break; break;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO @typeInfo for async function frames"); zig_panic("TODO @typeInfo for async function frames");
} }
@ -22219,7 +22217,7 @@ static IrInstruction *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInst
ZigFn *fn = exec_fn_entry(ira->new_irb.exec); ZigFn *fn = exec_fn_entry(ira->new_irb.exec);
ir_assert(fn != nullptr, &instruction->base); ir_assert(fn != nullptr, &instruction->base);
ZigType *frame_type = get_coro_frame_type(ira->codegen, fn); ZigType *frame_type = get_fn_frame_type(ira->codegen, fn);
ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false); ZigType *ptr_frame_type = get_pointer_to_type(ira->codegen, frame_type, false);
IrInstruction *result = ir_build_handle(&ira->new_irb, instruction->base.scope, instruction->base.source_node); 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
if (fn == nullptr) if (fn == nullptr)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
ZigType *ty = get_coro_frame_type(ira->codegen, fn); ZigType *ty = get_fn_frame_type(ira->codegen, fn);
return ir_const_type(ira, &instruction->base, ty); return ir_const_type(ira, &instruction->base, ty);
} }
@ -22293,7 +22291,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
case ZigTypeIdUnion: case ZigTypeIdUnion:
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
{ {
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); 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
zig_panic("TODO buf_write_value_bytes fn type"); zig_panic("TODO buf_write_value_bytes fn type");
case ZigTypeIdUnion: case ZigTypeIdUnion:
zig_panic("TODO buf_write_value_bytes union type"); zig_panic("TODO buf_write_value_bytes union type");
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO buf_write_value_bytes async fn frame type"); zig_panic("TODO buf_write_value_bytes async fn frame type");
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_panic("TODO buf_write_value_bytes anyframe type"); 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
zig_panic("TODO buf_read_value_bytes fn type"); zig_panic("TODO buf_read_value_bytes fn type");
case ZigTypeIdUnion: case ZigTypeIdUnion:
zig_panic("TODO buf_read_value_bytes union type"); zig_panic("TODO buf_read_value_bytes union type");
case ZigTypeIdCoroFrame: case ZigTypeIdFnFrame:
zig_panic("TODO buf_read_value_bytes async fn frame type"); zig_panic("TODO buf_read_value_bytes async fn frame type");
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
zig_panic("TODO buf_read_value_bytes anyframe type"); zig_panic("TODO buf_read_value_bytes anyframe type");
@ -24674,7 +24672,7 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
IrInstruction *frame; IrInstruction *frame;
if (frame_ptr->value.type->id == ZigTypeIdPointer && if (frame_ptr->value.type->id == ZigTypeIdPointer &&
frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle && frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&
frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
{ {
result_type = frame_ptr->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type; result_type = frame_ptr->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type;
frame = frame_ptr; frame = frame_ptr;
@ -24682,7 +24680,7 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
frame = ir_get_deref(ira, source_instr, frame_ptr, nullptr); frame = ir_get_deref(ira, source_instr, frame_ptr, nullptr);
if (frame->value.type->id == ZigTypeIdPointer && if (frame->value.type->id == ZigTypeIdPointer &&
frame->value.type->data.pointer.ptr_len == PtrLenSingle && frame->value.type->data.pointer.ptr_len == PtrLenSingle &&
frame->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) frame->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
{ {
result_type = frame->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type; result_type = frame->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type;
} else if (frame->value.type->id != ZigTypeIdAnyFrame || } else if (frame->value.type->id != ZigTypeIdAnyFrame ||
@ -24751,7 +24749,7 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction
return ir_finish_anal(ira, result); return ir_finish_anal(ira, result);
} }
static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) { static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructionResume *instruction) {
IrInstruction *frame_ptr = instruction->frame->child; IrInstruction *frame_ptr = instruction->frame->child;
if (type_is_invalid(frame_ptr->value.type)) if (type_is_invalid(frame_ptr->value.type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -24759,7 +24757,7 @@ static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstr
IrInstruction *frame; IrInstruction *frame;
if (frame_ptr->value.type->id == ZigTypeIdPointer && if (frame_ptr->value.type->id == ZigTypeIdPointer &&
frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle && frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&
frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame) frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
{ {
frame = frame_ptr; frame = frame_ptr;
} else { } else {
@ -24771,7 +24769,7 @@ static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstr
if (type_is_invalid(casted_frame->value.type)) if (type_is_invalid(casted_frame->value.type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
return ir_build_coro_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame); return ir_build_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_frame);
} }
static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_test_cancel_requested(IrAnalyze *ira,
@ -25112,8 +25110,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction); return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction);
case IrInstructionIdSuspendFinish: case IrInstructionIdSuspendFinish:
return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction); return ir_analyze_instruction_suspend_finish(ira, (IrInstructionSuspendFinish *)instruction);
case IrInstructionIdCoroResume: case IrInstructionIdResume:
return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction); return ir_analyze_instruction_resume(ira, (IrInstructionResume *)instruction);
case IrInstructionIdAwaitSrc: case IrInstructionIdAwaitSrc:
return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction); return ir_analyze_instruction_await(ira, (IrInstructionAwaitSrc *)instruction);
case IrInstructionIdTestCancelRequested: case IrInstructionIdTestCancelRequested:
@ -25256,7 +25254,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdResetResult: case IrInstructionIdResetResult:
case IrInstructionIdSuspendBegin: case IrInstructionIdSuspendBegin:
case IrInstructionIdSuspendFinish: case IrInstructionIdSuspendFinish:
case IrInstructionIdCoroResume: case IrInstructionIdResume:
case IrInstructionIdAwaitSrc: case IrInstructionIdAwaitSrc:
case IrInstructionIdAwaitGen: case IrInstructionIdAwaitGen:
case IrInstructionIdSpillBegin: case IrInstructionIdSpillBegin:

View File

@ -1528,10 +1528,9 @@ static void ir_print_suspend_finish(IrPrint *irp, IrInstructionSuspendFinish *in
fprintf(irp->f, "@suspendFinish()"); fprintf(irp->f, "@suspendFinish()");
} }
static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) { static void ir_print_resume(IrPrint *irp, IrInstructionResume *instruction) {
fprintf(irp->f, "@coroResume("); fprintf(irp->f, "resume ");
ir_print_other_instruction(irp, instruction->frame); ir_print_other_instruction(irp, instruction->frame);
fprintf(irp->f, ")");
} }
static void ir_print_await_src(IrPrint *irp, IrInstructionAwaitSrc *instruction) { static void ir_print_await_src(IrPrint *irp, IrInstructionAwaitSrc *instruction) {
@ -2039,8 +2038,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSuspendFinish: case IrInstructionIdSuspendFinish:
ir_print_suspend_finish(irp, (IrInstructionSuspendFinish *)instruction); ir_print_suspend_finish(irp, (IrInstructionSuspendFinish *)instruction);
break; break;
case IrInstructionIdCoroResume: case IrInstructionIdResume:
ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction); ir_print_resume(irp, (IrInstructionResume *)instruction);
break; break;
case IrInstructionIdAwaitSrc: case IrInstructionIdAwaitSrc:
ir_print_await_src(irp, (IrInstructionAwaitSrc *)instruction); ir_print_await_src(irp, (IrInstructionAwaitSrc *)instruction);

View File

@ -42,7 +42,6 @@
#include <llvm/Support/TargetRegistry.h> #include <llvm/Support/TargetRegistry.h>
#include <llvm/Target/TargetMachine.h> #include <llvm/Target/TargetMachine.h>
#include <llvm/Target/CodeGenCWrappers.h> #include <llvm/Target/CodeGenCWrappers.h>
#include <llvm/Transforms/Coroutines.h>
#include <llvm/Transforms/IPO.h> #include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/AlwaysInliner.h> #include <llvm/Transforms/IPO/AlwaysInliner.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h> #include <llvm/Transforms/IPO/PassManagerBuilder.h>
@ -203,8 +202,6 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false); PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false);
} }
addCoroutinePassesToExtensionPoints(*PMBuilder);
// Set up the per-function pass manager. // Set up the per-function pass manager.
legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module); legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii); auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii);

View File

@ -799,7 +799,7 @@ pub const WatchEventId = enum {
// pub fn destroy(self: *Self) void { // pub fn destroy(self: *Self) void {
// switch (builtin.os) { // switch (builtin.os) {
// .macosx, .freebsd, .netbsd => { // .macosx, .freebsd, .netbsd => {
// // TODO we need to cancel the coroutines before destroying the lock // // TODO we need to cancel the frames before destroying the lock
// self.os_data.table_lock.deinit(); // self.os_data.table_lock.deinit();
// var it = self.os_data.file_table.iterator(); // var it = self.os_data.file_table.iterator();
// while (it.next()) |entry| { // while (it.next()) |entry| {
@ -1088,7 +1088,7 @@ pub const WatchEventId = enum {
// //
// while (true) { // while (true) {
// { // {
// // TODO only 1 beginOneEvent for the whole coroutine // // TODO only 1 beginOneEvent for the whole function
// self.channel.loop.beginOneEvent(); // self.channel.loop.beginOneEvent();
// errdefer self.channel.loop.finishOneEvent(); // errdefer self.channel.loop.finishOneEvent();
// errdefer { // errdefer {
@ -1252,7 +1252,7 @@ pub const WatchEventId = enum {
const test_tmp_dir = "std_event_fs_test"; const test_tmp_dir = "std_event_fs_test";
// TODO this test is disabled until the coroutine rewrite is finished. // TODO this test is disabled until the async function rewrite is finished.
//test "write a file, watch it, write it again" { //test "write a file, watch it, write it again" {
// return error.SkipZigTest; // return error.SkipZigTest;
// const allocator = std.heap.direct_allocator; // const allocator = std.heap.direct_allocator;

View File

@ -6,7 +6,7 @@ const Lock = std.event.Lock;
const Loop = std.event.Loop; const Loop = std.event.Loop;
/// This is a value that starts out unavailable, until resolve() is called /// This is a value that starts out unavailable, until resolve() is called
/// While it is unavailable, coroutines suspend when they try to get() it, /// While it is unavailable, functions suspend when they try to get() it,
/// and then are resumed when resolve() is called. /// and then are resumed when resolve() is called.
/// At this point the value remains forever available, and another resolve() is not allowed. /// At this point the value remains forever available, and another resolve() is not allowed.
pub fn Future(comptime T: type) type { pub fn Future(comptime T: type) type {

View File

@ -7,7 +7,7 @@ const testing = std.testing;
/// ReturnType must be `void` or `E!void` /// ReturnType must be `void` or `E!void`
pub fn Group(comptime ReturnType: type) type { pub fn Group(comptime ReturnType: type) type {
return struct { return struct {
coro_stack: Stack, frame_stack: Stack,
alloc_stack: Stack, alloc_stack: Stack,
lock: Lock, lock: Lock,
@ -21,7 +21,7 @@ pub fn Group(comptime ReturnType: type) type {
pub fn init(loop: *Loop) Self { pub fn init(loop: *Loop) Self {
return Self{ return Self{
.coro_stack = Stack.init(), .frame_stack = Stack.init(),
.alloc_stack = Stack.init(), .alloc_stack = Stack.init(),
.lock = Lock.init(loop), .lock = Lock.init(loop),
}; };
@ -29,7 +29,7 @@ pub fn Group(comptime ReturnType: type) type {
/// Cancel all the outstanding frames. Can be called even if wait was already called. /// Cancel all the outstanding frames. Can be called even if wait was already called.
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
while (self.coro_stack.pop()) |node| { while (self.frame_stack.pop()) |node| {
cancel node.data; cancel node.data;
} }
while (self.alloc_stack.pop()) |node| { while (self.alloc_stack.pop()) |node| {
@ -50,11 +50,11 @@ pub fn Group(comptime ReturnType: type) type {
/// Add a node to the group. Thread-safe. Cannot fail. /// Add a node to the group. Thread-safe. Cannot fail.
/// `node.data` should be the frame handle to add to the group. /// `node.data` should be the frame handle to add to the group.
/// The node's memory should be in the coroutine frame of /// The node's memory should be in the function frame of
/// the handle that is in the node, or somewhere guaranteed to live /// the handle that is in the node, or somewhere guaranteed to live
/// at least as long. /// at least as long.
pub fn addNode(self: *Self, node: *Stack.Node) void { pub fn addNode(self: *Self, node: *Stack.Node) void {
self.coro_stack.push(node); self.frame_stack.push(node);
} }
/// Wait for all the calls and promises of the group to complete. /// Wait for all the calls and promises of the group to complete.
@ -64,7 +64,7 @@ pub fn Group(comptime ReturnType: type) type {
const held = self.lock.acquire(); const held = self.lock.acquire();
defer held.release(); defer held.release();
while (self.coro_stack.pop()) |node| { while (self.frame_stack.pop()) |node| {
if (Error == void) { if (Error == void) {
await node.data; await node.data;
} else { } else {

View File

@ -6,7 +6,7 @@ const mem = std.mem;
const Loop = std.event.Loop; const Loop = std.event.Loop;
/// Thread-safe async/await lock. /// Thread-safe async/await lock.
/// coroutines which are waiting for the lock are suspended, and /// Functions which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order. /// are resumed when the lock is released, in order.
/// Allows only one actor to hold the lock. /// Allows only one actor to hold the lock.
pub const Lock = struct { pub const Lock = struct {
@ -96,8 +96,7 @@ pub const Lock = struct {
suspend { suspend {
self.queue.put(&my_tick_node); self.queue.put(&my_tick_node);
// At this point, we are in the queue, so we might have already been resumed and this coroutine // At this point, we are in the queue, so we might have already been resumed.
// frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame.
// We set this bit so that later we can rely on the fact, that if queue_empty_bit is 1, some actor // We set this bit so that later we can rely on the fact, that if queue_empty_bit is 1, some actor
// will attempt to grab the lock. // will attempt to grab the lock.

View File

@ -3,7 +3,7 @@ const Lock = std.event.Lock;
const Loop = std.event.Loop; const Loop = std.event.Loop;
/// Thread-safe async/await lock that protects one piece of data. /// Thread-safe async/await lock that protects one piece of data.
/// coroutines which are waiting for the lock are suspended, and /// Functions which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order. /// are resumed when the lock is released, in order.
pub fn Locked(comptime T: type) type { pub fn Locked(comptime T: type) type {
return struct { return struct {

View File

@ -118,7 +118,7 @@ pub const Loop = struct {
} }
/// The allocator must be thread-safe because we use it for multiplexing /// The allocator must be thread-safe because we use it for multiplexing
/// coroutines onto kernel threads. /// async functions onto kernel threads.
/// After initialization, call run(). /// After initialization, call run().
/// TODO copy elision / named return values so that the threads referencing *Loop /// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value. /// have the correct pointer value.

View File

@ -13,7 +13,7 @@ pub const Server = struct {
loop: *Loop, loop: *Loop,
sockfd: ?i32, sockfd: ?i32,
accept_coro: ?anyframe, accept_frame: ?anyframe,
listen_address: std.net.Address, listen_address: std.net.Address,
waiting_for_emfile_node: PromiseNode, waiting_for_emfile_node: PromiseNode,
@ -22,11 +22,11 @@ pub const Server = struct {
const PromiseNode = std.TailQueue(anyframe).Node; const PromiseNode = std.TailQueue(anyframe).Node;
pub fn init(loop: *Loop) Server { pub fn init(loop: *Loop) Server {
// TODO can't initialize handler coroutine here because we need well defined copy elision // TODO can't initialize handler here because we need well defined copy elision
return Server{ return Server{
.loop = loop, .loop = loop,
.sockfd = null, .sockfd = null,
.accept_coro = null, .accept_frame = null,
.handleRequestFn = undefined, .handleRequestFn = undefined,
.waiting_for_emfile_node = undefined, .waiting_for_emfile_node = undefined,
.listen_address = undefined, .listen_address = undefined,
@ -53,10 +53,10 @@ pub const Server = struct {
try os.listen(sockfd, os.SOMAXCONN); try os.listen(sockfd, os.SOMAXCONN);
self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd)); self.listen_address = std.net.Address.initPosix(try os.getsockname(sockfd));
self.accept_coro = async Server.handler(self); self.accept_frame = async Server.handler(self);
errdefer cancel self.accept_coro.?; errdefer cancel self.accept_frame.?;
self.listen_resume_node.handle = self.accept_coro.?; self.listen_resume_node.handle = self.accept_frame.?;
try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET); try self.loop.linuxAddFd(sockfd, &self.listen_resume_node, os.EPOLLIN | os.EPOLLOUT | os.EPOLLET);
errdefer self.loop.removeFd(sockfd); errdefer self.loop.removeFd(sockfd);
} }
@ -71,7 +71,7 @@ pub const Server = struct {
} }
pub fn deinit(self: *Server) void { pub fn deinit(self: *Server) void {
if (self.accept_coro) |accept_coro| cancel accept_coro; if (self.accept_frame) |accept_frame| cancel accept_frame;
if (self.sockfd) |sockfd| os.close(sockfd); if (self.sockfd) |sockfd| os.close(sockfd);
} }

View File

@ -6,7 +6,7 @@ const mem = std.mem;
const Loop = std.event.Loop; const Loop = std.event.Loop;
/// Thread-safe async/await lock. /// Thread-safe async/await lock.
/// coroutines which are waiting for the lock are suspended, and /// Functions which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order. /// are resumed when the lock is released, in order.
/// Many readers can hold the lock at the same time; however locking for writing is exclusive. /// Many readers can hold the lock at the same time; however locking for writing is exclusive.
/// When a read lock is held, it will not be released until the reader queue is empty. /// 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 {
self.reader_queue.put(&my_tick_node); self.reader_queue.put(&my_tick_node);
// At this point, we are in the reader_queue, so we might have already been resumed and this coroutine // At this point, we are in the reader_queue, so we might have already been resumed.
// frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame.
// We set this bit so that later we can rely on the fact, that if reader_queue_empty_bit is 1, // We set this bit so that later we can rely on the fact, that if reader_queue_empty_bit is 1,
// some actor will attempt to grab the lock. // some actor will attempt to grab the lock.
@ -139,8 +138,7 @@ pub const RwLock = struct {
self.writer_queue.put(&my_tick_node); self.writer_queue.put(&my_tick_node);
// At this point, we are in the writer_queue, so we might have already been resumed and this coroutine // At this point, we are in the writer_queue, so we might have already been resumed.
// frame might be destroyed. For the rest of the suspend block we cannot access the coroutine frame.
// We set this bit so that later we can rely on the fact, that if writer_queue_empty_bit is 1, // We set this bit so that later we can rely on the fact, that if writer_queue_empty_bit is 1,
// some actor will attempt to grab the lock. // some actor will attempt to grab the lock.

View File

@ -3,7 +3,7 @@ const RwLock = std.event.RwLock;
const Loop = std.event.Loop; const Loop = std.event.Loop;
/// Thread-safe async/await RW lock that protects one piece of data. /// Thread-safe async/await RW lock that protects one piece of data.
/// coroutines which are waiting for the lock are suspended, and /// Functions which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order. /// are resumed when the lock is released, in order.
pub fn RwLocked(comptime T: type) type { pub fn RwLocked(comptime T: type) type {
return struct { return struct {

View File

@ -2103,7 +2103,7 @@ test "zig fmt: inline asm" {
); );
} }
test "zig fmt: coroutines" { test "zig fmt: async functions" {
try testCanonical( try testCanonical(
\\async fn simpleAsyncFn() void { \\async fn simpleAsyncFn() void {
\\ const a = async a.b(); \\ const a = async a.b();
@ -2115,8 +2115,8 @@ test "zig fmt: coroutines" {
\\ await p; \\ await p;
\\} \\}
\\ \\
\\test "coroutine suspend, resume, cancel" { \\test "suspend, resume, cancel" {
\\ const p: anyframe = try async<std.debug.global_allocator> testAsyncSeq(); \\ const p: anyframe = async testAsyncSeq();
\\ resume p; \\ resume p;
\\ cancel p; \\ cancel p;
\\} \\}