Commit 71b7f4b47f

Andrew Kelley <andrew@ziglang.org>
2019-12-06 20:52:09
remove `@newStackCall` from zig
1 parent 343987c
Changed files (6)
doc
lib
std
special
src
src-self-hosted
test
doc/langref.html.in
@@ -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>
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 }));
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);
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;
         }
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);
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,