remove @newStackCall from zig

This commit is contained in:
Andrew Kelley 2019-12-06 14:52:09 -05:00
parent 343987cd05
commit 71b7f4b47f
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
6 changed files with 66 additions and 56 deletions

View File

@ -6904,6 +6904,41 @@ pub const CallOptions = struct {
};
};
{#code_end#}
{#header_open|Calling with a New Stack#}
<p>
When the {#syntax#}stack{#endsyntax#} option is provided, instead of using the same stack as the caller, the function uses the provided stack.
</p>
{#code_begin|test|new_stack_call#}
const std = @import("std");
const assert = std.debug.assert;
var new_stack_bytes: [1024]u8 align(16) = undefined;
test "calling a function with a new stack" {
const arg = 1234;
const a = @call(.{.stack = new_stack_bytes[0..512]}, targetFunction, .{arg});
const b = @call(.{.stack = new_stack_bytes[512..]}, targetFunction, .{arg});
_ = targetFunction(arg);
assert(arg == 1234);
assert(a < b);
}
fn targetFunction(x: i32) usize {
assert(x == 1234);
var local_variable: i32 = 42;
const ptr = &local_variable;
ptr.* += 1;
assert(local_variable == 43);
return @ptrToInt(ptr);
}
{#code_end#}
{#header_close#}
{#header_close#}
{#header_open|@cDefine#}
@ -7649,48 +7684,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
</p>
{#header_close#}
{#header_open|@newStackCall#}
<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 align(16) = undefined;
test "calling a function with a new stack" {
const arg = 1234;
const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
_ = targetFunction(arg);
assert(arg == 1234);
assert(a < b);
}
fn targetFunction(x: i32) usize {
assert(x == 1234);
var local_variable: i32 = 42;
const ptr = &local_variable;
ptr.* += 1;
assert(local_variable == 43);
return @ptrToInt(ptr);
}
{#code_end#}
{#header_close#}
{#header_open|@OpaqueType#}
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
<p>

View File

@ -184,7 +184,7 @@ fn posixCallMainAndExit() noreturn {
// 0,
//) catch @panic("out of memory");
//std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
//std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));
//std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
}
std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));

View File

@ -321,7 +321,7 @@ pub const Inst = struct {
}
const llvm_cc = llvm.CCallConv;
const fn_inline = llvm.FnInline.Auto;
const call_attr = llvm.CallAttr.Auto;
return llvm.BuildCall(
ofile.builder,
@ -329,7 +329,7 @@ pub const Inst = struct {
args.ptr,
@intCast(c_uint, args.len),
llvm_cc,
fn_inline,
call_attr,
"",
) orelse error.OutOfMemory;
}

View File

@ -13358,6 +13358,15 @@ static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst
return ir_get_deref(ira, source_instr, field_ptr, nullptr);
}
static IrInstruction *ir_analyze_optional_value_payload_value(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *optional_operand, bool safety_check_on)
{
IrInstruction *opt_ptr = ir_get_ref(ira, source_instr, optional_operand, true, false);
IrInstruction *payload_ptr = ir_analyze_unwrap_optional_payload(ira, source_instr, opt_ptr,
safety_check_on, false);
return ir_get_deref(ira, source_instr, payload_ptr, nullptr);
}
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
ZigType *wanted_type, IrInstruction *value)
{
@ -17521,7 +17530,7 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *so
arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)
{
ir_add_error(ira, source_instr,
buf_sprintf("target arch '%s' does not support @newStackCall",
buf_sprintf("target arch '%s' does not support calling with a new stack",
target_arch_name(ira->codegen->zig_target->arch)));
}
@ -18223,13 +18232,21 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc
TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
ir_assert(stack_field != nullptr, source_instr);
IrInstruction *stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);
IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, stack);
IrInstruction *opt_stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);
if (type_is_invalid(opt_stack->value->type))
return ira->codegen->invalid_instruction;
IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, opt_stack);
bool stack_is_non_null;
if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
return ira->codegen->invalid_instruction;
if (!stack_is_non_null)
IrInstruction *stack;
if (stack_is_non_null) {
stack = ir_analyze_optional_value_payload_value(ira, source_instr, opt_stack, false);
if (type_is_invalid(stack->value->type))
return ira->codegen->invalid_instruction;
} else {
stack = nullptr;
}
return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr,
modifier, stack, false, args_ptr, args_len, nullptr, result_loc);

View File

@ -26,8 +26,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\fn baz2() void {}
,
"tmp.zig:2:21: error: expected tuple or struct, found 'void'",
"tmp.zig:5:58: error: unable to perform 'never_inline' call at compile-time",
"tmp.zig:8:56: error: unable to perform 'never_tail' call at compile-time",
"tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time",
"tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time",
"tmp.zig:11:5: error: no-inline call of inline function",
"tmp.zig:15:43: error: unable to evaluate constant expression",
);
@ -44,13 +44,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
);
cases.addCase(x: {
var tc = cases.create("@newStackCall on unsupported target",
var tc = cases.create("call with new stack on unsupported target",
\\export fn entry() void {
\\ var buf: [10]u8 align(16) = undefined;
\\ @newStackCall(&buf, foo);
\\ @call(.{.stack = &buf}, foo);
\\}
\\fn foo() void {}
, "tmp.zig:3:5: error: target arch 'wasm32' does not support @newStackCall");
, "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack");
tc.target = tests.Target{
.Cross = tests.CrossTarget{
.arch = .wasm32,

View File

@ -18,8 +18,8 @@ test "calling a function with a new stack" {
const arg = 1234;
const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
const a = @call(.{ .stack = new_stack_bytes[0..512] }, targetFunction, .{arg});
const b = @call(.{ .stack = new_stack_bytes[512..] }, targetFunction, .{arg});
_ = targetFunction(arg);
expect(arg == 1234);