mirror of
https://github.com/ziglang/zig.git
synced 2026-01-30 19:23:37 +00:00
parent
19961c50e4
commit
2fa588e81d
@ -5583,7 +5583,7 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, TypeT
|
||||
return;
|
||||
}
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
buf_appendf(buf, "(*%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->data.pointer.child_type->name),
|
||||
buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
|
||||
const_val->data.x_ptr.data.hard_coded_addr.addr);
|
||||
return;
|
||||
case ConstPtrSpecialDiscard:
|
||||
|
||||
17
src/ir.cpp
17
src/ir.cpp
@ -7112,6 +7112,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||
IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
|
||||
ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
|
||||
}
|
||||
// Before we destroy the coroutine frame, we need to load the target promise into
|
||||
// a register or local variable which does not get spilled into the frame,
|
||||
// otherwise llvm tries to access memory inside the destroyed frame.
|
||||
IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
|
||||
irb->exec->await_handle_var_ptr, false);
|
||||
IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
|
||||
ir_build_br(irb, scope, node, check_free_block, const_bool_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block);
|
||||
@ -7126,6 +7132,14 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||
incoming_values[1] = const_bool_true;
|
||||
IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
|
||||
|
||||
IrBasicBlock **merge_incoming_blocks = allocate<IrBasicBlock *>(2);
|
||||
IrInstruction **merge_incoming_values = allocate<IrInstruction *>(2);
|
||||
merge_incoming_blocks[0] = irb->exec->coro_final_cleanup_block;
|
||||
merge_incoming_values[0] = ir_build_const_undefined(irb, scope, node);
|
||||
merge_incoming_blocks[1] = irb->exec->coro_normal_final;
|
||||
merge_incoming_values[1] = await_handle_in_block;
|
||||
IrInstruction *awaiter_handle = ir_build_phi(irb, scope, node, 2, merge_incoming_blocks, merge_incoming_values);
|
||||
|
||||
Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);
|
||||
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
|
||||
ImplicitAllocatorIdLocalVar);
|
||||
@ -7152,9 +7166,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
||||
ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, resume_block);
|
||||
IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
|
||||
irb->exec->await_handle_var_ptr, false);
|
||||
IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
|
||||
ir_build_coro_resume(irb, scope, node, awaiter_handle);
|
||||
ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);
|
||||
}
|
||||
|
||||
@ -5,7 +5,10 @@ const assert = std.debug.assert;
|
||||
var x: i32 = 1;
|
||||
|
||||
test "create a coroutine and cancel it" {
|
||||
const p = try async<std.debug.global_allocator> simpleAsyncFn();
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
const p = try async<&da.allocator> simpleAsyncFn();
|
||||
comptime assert(@typeOf(p) == promise->void);
|
||||
cancel p;
|
||||
assert(x == 2);
|
||||
@ -17,8 +20,11 @@ async fn simpleAsyncFn() void {
|
||||
}
|
||||
|
||||
test "coroutine suspend, resume, cancel" {
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
seq('a');
|
||||
const p = try async<std.debug.global_allocator> testAsyncSeq();
|
||||
const p = try async<&da.allocator> testAsyncSeq();
|
||||
seq('c');
|
||||
resume p;
|
||||
seq('f');
|
||||
@ -43,7 +49,10 @@ fn seq(c: u8) void {
|
||||
}
|
||||
|
||||
test "coroutine suspend with block" {
|
||||
const p = try async<std.debug.global_allocator> testSuspendBlock();
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
const p = try async<&da.allocator> testSuspendBlock();
|
||||
std.debug.assert(!result);
|
||||
resume a_promise;
|
||||
std.debug.assert(result);
|
||||
@ -64,8 +73,11 @@ var await_a_promise: promise = undefined;
|
||||
var await_final_result: i32 = 0;
|
||||
|
||||
test "coroutine await" {
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
await_seq('a');
|
||||
const p = async<std.debug.global_allocator> await_amain() catch unreachable;
|
||||
const p = async<&da.allocator> await_amain() catch unreachable;
|
||||
await_seq('f');
|
||||
resume await_a_promise;
|
||||
await_seq('i');
|
||||
@ -100,8 +112,11 @@ fn await_seq(c: u8) void {
|
||||
var early_final_result: i32 = 0;
|
||||
|
||||
test "coroutine await early return" {
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
early_seq('a');
|
||||
const p = async<std.debug.global_allocator> early_amain() catch unreachable;
|
||||
const p = async<&da.allocator> early_amain() catch unreachable;
|
||||
early_seq('f');
|
||||
assert(early_final_result == 1234);
|
||||
assert(std.mem.eql(u8, early_points, "abcdef"));
|
||||
@ -146,7 +161,9 @@ test "async function with dot syntax" {
|
||||
suspend;
|
||||
}
|
||||
};
|
||||
const p = try async<std.debug.global_allocator> S.foo();
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
const p = try async<&da.allocator> S.foo();
|
||||
cancel p;
|
||||
assert(S.y == 2);
|
||||
}
|
||||
@ -157,7 +174,9 @@ test "async fn pointer in a struct field" {
|
||||
bar: async<*std.mem.Allocator> fn (*i32) void,
|
||||
};
|
||||
var foo = Foo{ .bar = simpleAsyncFn2 };
|
||||
const p = (async<std.debug.global_allocator> foo.bar(&data)) catch unreachable;
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
|
||||
assert(data == 2);
|
||||
cancel p;
|
||||
assert(data == 4);
|
||||
@ -169,7 +188,9 @@ async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
|
||||
}
|
||||
|
||||
test "async fn with inferred error set" {
|
||||
const p = (async<std.debug.global_allocator> failing()) catch unreachable;
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
const p = (async<&da.allocator> failing()) catch unreachable;
|
||||
resume p;
|
||||
cancel p;
|
||||
}
|
||||
@ -181,7 +202,9 @@ async fn failing() !void {
|
||||
test "error return trace across suspend points - early return" {
|
||||
const p = nonFailing();
|
||||
resume p;
|
||||
const p2 = try async<std.debug.global_allocator> printTrace(p);
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
const p2 = try async<&da.allocator> printTrace(p);
|
||||
cancel p2;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user