From 71b7f4b47f69e9b3241e9d44554572258f5eb5b1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 6 Dec 2019 14:52:09 -0500 Subject: [PATCH] remove `@newStackCall` from zig --- doc/langref.html.in | 77 +++++++++++-------------- lib/std/special/start.zig | 2 +- src-self-hosted/ir.zig | 4 +- src/ir.cpp | 25 ++++++-- test/compile_errors.zig | 10 ++-- test/stage1/behavior/new_stack_call.zig | 4 +- 6 files changed, 66 insertions(+), 56 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index e30f920af4..ba0aa7a778 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6904,6 +6904,41 @@ pub const CallOptions = struct { }; }; {#code_end#} + + {#header_open|Calling with a New Stack#} +

+ When the {#syntax#}stack{#endsyntax#} option is provided, instead of using the same stack as the caller, the function uses the provided stack. +

+ {#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#}

{#header_close#} - {#header_open|@newStackCall#} -
{#syntax#}@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var{#endsyntax#}
-

- 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. -

-

- 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#}. -

- {#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#}
{#syntax#}@OpaqueType() type{#endsyntax#}

diff --git a/lib/std/special/start.zig b/lib/std/special/start.zig index b00b5213a7..d10431da20 100644 --- a/lib/std/special/start.zig +++ b/lib/std/special/start.zig @@ -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 })); diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index 8d1c32cefd..1d11d7969d 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -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; } diff --git a/src/ir.cpp b/src/ir.cpp index 6e0e321300..e6978eae77 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -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); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d1244188e6..9494879f71 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -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, diff --git a/test/stage1/behavior/new_stack_call.zig b/test/stage1/behavior/new_stack_call.zig index b057566d9c..69763a52c6 100644 --- a/test/stage1/behavior/new_stack_call.zig +++ b/test/stage1/behavior/new_stack_call.zig @@ -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);