mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
parent
456a244d62
commit
4d8a6f6fea
@ -6379,7 +6379,7 @@ comptime {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@asyncCall#}
|
||||
<pre>{#syntax#}@asyncCall(frame_buffer: []u8, result_ptr, function_ptr, args: ...) anyframe->T{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: ...) anyframe->T{#endsyntax#}</pre>
|
||||
<p>
|
||||
{#syntax#}@asyncCall{#endsyntax#} performs an {#syntax#}async{#endsyntax#} call on a function pointer,
|
||||
which may or may not be an {#link|async function|Async Functions#}.
|
||||
@ -6405,7 +6405,7 @@ test "async fn pointer in a struct field" {
|
||||
bar: async fn (*i32) void,
|
||||
};
|
||||
var foo = Foo{ .bar = func };
|
||||
var bytes: [64]u8 = undefined;
|
||||
var bytes: [64]u8 align(@alignOf(@Frame(func))) = undefined;
|
||||
const f = @asyncCall(&bytes, {}, foo.bar, &data);
|
||||
assert(data == 2);
|
||||
resume f;
|
||||
@ -7322,17 +7322,22 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@newStackCall#}
|
||||
<pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var{#endsyntax#}</pre>
|
||||
<p>
|
||||
This calls a function, in the same way that invoking an expression with parentheses does. However,
|
||||
instead of using the same stack as the caller, the function uses the stack provided in the {#syntax#}new_stack{#endsyntax#}
|
||||
parameter.
|
||||
</p>
|
||||
<p>
|
||||
The new stack must be aligned to {#syntax#}target_stack_align{#endsyntax#} bytes. This is a target-specific
|
||||
number. A safe value that will work on all targets is {#syntax#}16{#endsyntax#}. This value can
|
||||
also be obtained by using {#link|@sizeOf#} on the {#link|@Frame#} type of {#link|Async Functions#}.
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
var new_stack_bytes: [1024]u8 = undefined;
|
||||
var new_stack_bytes: [1024]u8 align(16) = undefined;
|
||||
|
||||
test "calling a function with a new stack" {
|
||||
const arg = 1234;
|
||||
|
||||
23
src/ir.cpp
23
src/ir.cpp
@ -12110,7 +12110,26 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
array_type->data.array.child_type, source_node,
|
||||
!slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk)
|
||||
{
|
||||
return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
|
||||
// If the pointers both have ABI align, it works.
|
||||
bool ok_align = slice_ptr_type->data.pointer.explicit_alignment == 0 &&
|
||||
actual_type->data.pointer.explicit_alignment == 0;
|
||||
if (!ok_align) {
|
||||
// If either one has non ABI align, we have to resolve them both
|
||||
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
|
||||
ResolveStatusAlignmentKnown)))
|
||||
{
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type,
|
||||
ResolveStatusAlignmentKnown)))
|
||||
{
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
|
||||
}
|
||||
if (ok_align) {
|
||||
return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15421,7 +15440,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
|
||||
IrInstruction *casted_new_stack = nullptr;
|
||||
if (call_instruction->new_stack != nullptr) {
|
||||
ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
|
||||
false, false, PtrLenUnknown, 0, 0, 0, false);
|
||||
false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
|
||||
ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
|
||||
IrInstruction *new_stack = call_instruction->new_stack->child;
|
||||
if (type_is_invalid(new_stack->value.type))
|
||||
|
||||
@ -2,6 +2,28 @@ const tests = @import("tests.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"bad alignment in @asyncCall",
|
||||
\\export fn entry() void {
|
||||
\\ var ptr: async fn () void = func;
|
||||
\\ var bytes: [64]u8 = undefined;
|
||||
\\ _ = @asyncCall(&bytes, {}, ptr);
|
||||
\\}
|
||||
\\async fn func() void {}
|
||||
,
|
||||
"tmp.zig:4:21: error: expected type '[]align(16) u8', found '*[64]u8'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"bad alignment in implicit cast from array pointer to slice",
|
||||
\\export fn a() void {
|
||||
\\ var x: [10]u8 = undefined;
|
||||
\\ var y: []align(16) u8 = &x;
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:3:30: error: expected type '[]align(16) u8', found '*[10]u8'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"result location incompatibility mismatching handle_is_ptr (generic call)",
|
||||
\\export fn entry() void {
|
||||
@ -164,7 +186,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"non async function pointer passed to @asyncCall",
|
||||
\\export fn entry() void {
|
||||
\\ var ptr = afunc;
|
||||
\\ var bytes: [100]u8 = undefined;
|
||||
\\ var bytes: [100]u8 align(16) = undefined;
|
||||
\\ _ = @asyncCall(&bytes, {}, ptr);
|
||||
\\}
|
||||
\\fn afunc() void { }
|
||||
|
||||
@ -30,7 +30,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
|
||||
\\ @import("std").os.exit(126);
|
||||
\\}
|
||||
\\pub fn main() void {
|
||||
\\ var bytes: [1]u8 = undefined;
|
||||
\\ var bytes: [1]u8 align(16) = undefined;
|
||||
\\ var ptr = other;
|
||||
\\ var frame = @asyncCall(&bytes, {}, ptr);
|
||||
\\}
|
||||
|
||||
@ -280,7 +280,7 @@ test "async fn pointer in a struct field" {
|
||||
bar: async fn (*i32) void,
|
||||
};
|
||||
var foo = Foo{ .bar = simpleAsyncFn2 };
|
||||
var bytes: [64]u8 = undefined;
|
||||
var bytes: [64]u8 align(16) = undefined;
|
||||
const f = @asyncCall(&bytes, {}, foo.bar, &data);
|
||||
comptime expect(@typeOf(f) == anyframe->void);
|
||||
expect(data == 2);
|
||||
@ -317,7 +317,7 @@ test "@asyncCall with return type" {
|
||||
}
|
||||
};
|
||||
var foo = Foo{ .bar = Foo.middle };
|
||||
var bytes: [150]u8 = undefined;
|
||||
var bytes: [150]u8 align(16) = undefined;
|
||||
var aresult: i32 = 0;
|
||||
_ = @asyncCall(&bytes, &aresult, foo.bar);
|
||||
expect(aresult == 0);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
|
||||
var new_stack_bytes: [1024]u8 = undefined;
|
||||
var new_stack_bytes: [1024]u8 align(16) = undefined;
|
||||
|
||||
test "calling a function with a new stack" {
|
||||
const arg = 1234;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user