authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-06 14:52:09-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-06 14:52:09-05:00
log71b7f4b47f69e9b3241e9d44554572258f5eb5b1
tree9e60d95d273bb488d7ffcef8eaa5217c72f32079
parent343987cd057c5f2f0aad197518d7d573579d0d08
signature Commit is signed but in an unrecognized format.

remove `@newStackCall` from zig


6 files changed, 66 insertions(+), 56 deletions(-)

doc/langref.html.in+35-42
...@@ -6904,6 +6904,41 @@ pub const CallOptions = struct {...@@ -6904,6 +6904,41 @@ pub const CallOptions = struct {
6904 };6904 };
6905};6905};
6906 {#code_end#}6906 {#code_end#}
6907
6908 {#header_open|Calling with a New Stack#}
6909 <p>
6910 When the {#syntax#}stack{#endsyntax#} option is provided, instead of using the same stack as the caller, the function uses the provided stack.
6911 </p>
6912 {#code_begin|test|new_stack_call#}
6913const std = @import("std");
6914const assert = std.debug.assert;
6915
6916var new_stack_bytes: [1024]u8 align(16) = undefined;
6917
6918test "calling a function with a new stack" {
6919 const arg = 1234;
6920
6921 const a = @call(.{.stack = new_stack_bytes[0..512]}, targetFunction, .{arg});
6922 const b = @call(.{.stack = new_stack_bytes[512..]}, targetFunction, .{arg});
6923 _ = targetFunction(arg);
6924
6925 assert(arg == 1234);
6926 assert(a < b);
6927}
6928
6929fn targetFunction(x: i32) usize {
6930 assert(x == 1234);
6931
6932 var local_variable: i32 = 42;
6933 const ptr = &local_variable;
6934 ptr.* += 1;
6935
6936 assert(local_variable == 43);
6937 return @ptrToInt(ptr);
6938}
6939 {#code_end#}
6940 {#header_close#}
6941
6907 {#header_close#}6942 {#header_close#}
69086943
6909 {#header_open|@cDefine#}6944 {#header_open|@cDefine#}
...@@ -7649,48 +7684,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -7649,48 +7684,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
7649 </p>7684 </p>
7650 {#header_close#}7685 {#header_close#}
76517686
7652 {#header_open|@newStackCall#}
7653 <pre>{#syntax#}@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var{#endsyntax#}</pre>
7654 <p>
7655 This calls a function, in the same way that invoking an expression with parentheses does. However,
7656 instead of using the same stack as the caller, the function uses the stack provided in the {#syntax#}new_stack{#endsyntax#}
7657 parameter.
7658 </p>
7659 <p>
7660 The new stack must be aligned to {#syntax#}target_stack_align{#endsyntax#} bytes. This is a target-specific
7661 number. A safe value that will work on all targets is {#syntax#}16{#endsyntax#}. This value can
7662 also be obtained by using {#link|@sizeOf#} on the {#link|@Frame#} type of {#link|Async Functions#}.
7663 </p>
7664 {#code_begin|test#}
7665const std = @import("std");
7666const assert = std.debug.assert;
7667
7668var new_stack_bytes: [1024]u8 align(16) = undefined;
7669
7670test "calling a function with a new stack" {
7671 const arg = 1234;
7672
7673 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
7674 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
7675 _ = targetFunction(arg);
7676
7677 assert(arg == 1234);
7678 assert(a < b);
7679}
7680
7681fn targetFunction(x: i32) usize {
7682 assert(x == 1234);
7683
7684 var local_variable: i32 = 42;
7685 const ptr = &local_variable;
7686 ptr.* += 1;
7687
7688 assert(local_variable == 43);
7689 return @ptrToInt(ptr);
7690}
7691 {#code_end#}
7692 {#header_close#}
7693
7694 {#header_open|@OpaqueType#}7687 {#header_open|@OpaqueType#}
7695 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>7688 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
7696 <p>7689 <p>
lib/std/special/start.zig+1-1
...@@ -184,7 +184,7 @@ fn posixCallMainAndExit() noreturn {...@@ -184,7 +184,7 @@ fn posixCallMainAndExit() noreturn {
184 // 0,184 // 0,
185 //) catch @panic("out of memory");185 //) catch @panic("out of memory");
186 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};186 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
187 //std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));187 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
188 }188 }
189189
190 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));190 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
src-self-hosted/ir.zig+2-2
...@@ -321,7 +321,7 @@ pub const Inst = struct {...@@ -321,7 +321,7 @@ pub const Inst = struct {
321 }321 }
322322
323 const llvm_cc = llvm.CCallConv;323 const llvm_cc = llvm.CCallConv;
324 const fn_inline = llvm.FnInline.Auto;324 const call_attr = llvm.CallAttr.Auto;
325325
326 return llvm.BuildCall(326 return llvm.BuildCall(
327 ofile.builder,327 ofile.builder,
...@@ -329,7 +329,7 @@ pub const Inst = struct {...@@ -329,7 +329,7 @@ pub const Inst = struct {
329 args.ptr,329 args.ptr,
330 @intCast(c_uint, args.len),330 @intCast(c_uint, args.len),
331 llvm_cc,331 llvm_cc,
332 fn_inline,332 call_attr,
333 "",333 "",
334 ) orelse error.OutOfMemory;334 ) orelse error.OutOfMemory;
335 }335 }
src/ir.cpp+21-4
...@@ -13358,6 +13358,15 @@ static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst...@@ -13358,6 +13358,15 @@ static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst
13358 return ir_get_deref(ira, source_instr, field_ptr, nullptr);13358 return ir_get_deref(ira, source_instr, field_ptr, nullptr);
13359}13359}
1336013360
13361static IrInstruction *ir_analyze_optional_value_payload_value(IrAnalyze *ira, IrInstruction *source_instr,
13362 IrInstruction *optional_operand, bool safety_check_on)
13363{
13364 IrInstruction *opt_ptr = ir_get_ref(ira, source_instr, optional_operand, true, false);
13365 IrInstruction *payload_ptr = ir_analyze_unwrap_optional_payload(ira, source_instr, opt_ptr,
13366 safety_check_on, false);
13367 return ir_get_deref(ira, source_instr, payload_ptr, nullptr);
13368}
13369
13361static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,13370static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
13362 ZigType *wanted_type, IrInstruction *value)13371 ZigType *wanted_type, IrInstruction *value)
13363{13372{
...@@ -17521,7 +17530,7 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *so...@@ -17521,7 +17530,7 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *so
17521 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)17530 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)
17522 {17531 {
17523 ir_add_error(ira, source_instr,17532 ir_add_error(ira, source_instr,
17524 buf_sprintf("target arch '%s' does not support @newStackCall",17533 buf_sprintf("target arch '%s' does not support calling with a new stack",
17525 target_arch_name(ira->codegen->zig_target->arch)));17534 target_arch_name(ira->codegen->zig_target->arch)));
17526 }17535 }
1752717536
...@@ -18223,13 +18232,21 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc...@@ -18223,13 +18232,21 @@ static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *sourc
1822318232
18224 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));18233 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
18225 ir_assert(stack_field != nullptr, source_instr);18234 ir_assert(stack_field != nullptr, source_instr);
18226 IrInstruction *stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);18235 IrInstruction *opt_stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);
18227 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, stack);18236 if (type_is_invalid(opt_stack->value->type))
18237 return ira->codegen->invalid_instruction;
18238 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, opt_stack);
18228 bool stack_is_non_null;18239 bool stack_is_non_null;
18229 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))18240 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
18230 return ira->codegen->invalid_instruction;18241 return ira->codegen->invalid_instruction;
18231 if (!stack_is_non_null)18242 IrInstruction *stack;
18243 if (stack_is_non_null) {
18244 stack = ir_analyze_optional_value_payload_value(ira, source_instr, opt_stack, false);
18245 if (type_is_invalid(stack->value->type))
18246 return ira->codegen->invalid_instruction;
18247 } else {
18232 stack = nullptr;18248 stack = nullptr;
18249 }
1823318250
18234 return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr,18251 return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr,
18235 modifier, stack, false, args_ptr, args_len, nullptr, result_loc);18252 modifier, stack, false, args_ptr, args_len, nullptr, result_loc);
test/compile_errors.zig+5-5
...@@ -26,8 +26,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -26,8 +26,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26 \\fn baz2() void {}26 \\fn baz2() void {}
27 ,27 ,
28 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",28 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",
29 "tmp.zig:5:58: error: unable to perform 'never_inline' call at compile-time",29 "tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time",
30 "tmp.zig:8:56: error: unable to perform 'never_tail' call at compile-time",30 "tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time",
31 "tmp.zig:11:5: error: no-inline call of inline function",31 "tmp.zig:11:5: error: no-inline call of inline function",
32 "tmp.zig:15:43: error: unable to evaluate constant expression",32 "tmp.zig:15:43: error: unable to evaluate constant expression",
33 );33 );
...@@ -44,13 +44,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -44,13 +44,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
44 );44 );
4545
46 cases.addCase(x: {46 cases.addCase(x: {
47 var tc = cases.create("@newStackCall on unsupported target",47 var tc = cases.create("call with new stack on unsupported target",
48 \\export fn entry() void {48 \\export fn entry() void {
49 \\ var buf: [10]u8 align(16) = undefined;49 \\ var buf: [10]u8 align(16) = undefined;
50 \\ @newStackCall(&buf, foo);50 \\ @call(.{.stack = &buf}, foo);
51 \\}51 \\}
52 \\fn foo() void {}52 \\fn foo() void {}
53 , "tmp.zig:3:5: error: target arch 'wasm32' does not support @newStackCall");53 , "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack");
54 tc.target = tests.Target{54 tc.target = tests.Target{
55 .Cross = tests.CrossTarget{55 .Cross = tests.CrossTarget{
56 .arch = .wasm32,56 .arch = .wasm32,
test/stage1/behavior/new_stack_call.zig+2-2
...@@ -18,8 +18,8 @@ test "calling a function with a new stack" {...@@ -18,8 +18,8 @@ test "calling a function with a new stack" {
1818
19 const arg = 1234;19 const arg = 1234;
2020
21 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);21 const a = @call(.{ .stack = new_stack_bytes[0..512] }, targetFunction, .{arg});
22 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);22 const b = @call(.{ .stack = new_stack_bytes[512..] }, targetFunction, .{arg});
23 _ = targetFunction(arg);23 _ = targetFunction(arg);
2424
25 expect(arg == 1234);25 expect(arg == 1234);