authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-05 17:37:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-05 17:37:29-05:00
logef83358eb6702e8541816817e98c3e7279033672
tree2d57f0633a84f188cc4bd0c9e25fc0484a39b6f5
parent1f602fe8c5b3dea9f00f96e70dad73ebce405b49
signature Commit is signed but in an unrecognized format.

remove `@noInlineCall` from zig


7 files changed, 106 insertions(+), 42 deletions(-)

doc/langref.html.in+66-24
...@@ -6841,6 +6841,71 @@ async fn func(y: *i32) void {...@@ -6841,6 +6841,71 @@ async fn func(y: *i32) void {
6841 </p>6841 </p>
6842 {#header_close#}6842 {#header_close#}
68436843
6844 {#header_open|@call#}
6845 <pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre>
6846 <p>
6847 Calls a function, in the same way that invoking an expression with parentheses does:
6848 </p>
6849 {#code_begin|test|call#}
6850const assert = @import("std").debug.assert;
6851
6852test "noinline function call" {
6853 assert(@call(.{}, add, .{3, 9}) == 12);
6854}
6855
6856fn add(a: i32, b: i32) i32 {
6857 return a + b;
6858}
6859 {#code_end#}
6860 <p>
6861 {#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The
6862 {#syntax#}CallOptions{#endsyntax#} struct is reproduced here:
6863 </p>
6864 {#code_begin|syntax#}
6865pub const CallOptions = struct {
6866 modifier: Modifier = .auto,
6867 stack: ?[]align(std.Target.stack_align) u8 = null,
6868
6869 pub const Modifier = enum {
6870 /// Equivalent to function call syntax.
6871 auto,
6872
6873 /// Asserts that the function call will not suspend. This allows a
6874 /// non-async function to call an async function.
6875 no_async,
6876
6877 /// The function call will return an async function frame instead of
6878 /// the function's result, which is expected to then be awaited.
6879 /// This is equivalent to using the `async` keyword in front of function
6880 /// call syntax.
6881 async_call,
6882
6883 /// Prevents tail call optimization. This guarantees that the return
6884 /// address will point to the callsite, as opposed to the callsite's
6885 /// callsite. If the call is otherwise required to be tail-called
6886 /// or inlined, a compile error is emitted instead.
6887 never_tail,
6888
6889 /// Guarantees that the call will not be inlined. If the call is
6890 /// otherwise required to be inlined, a compile error is emitted instead.
6891 never_inline,
6892
6893 /// Guarantees that the call will be generated with tail call optimization.
6894 /// If this is not possible, a compile error is emitted instead.
6895 always_tail,
6896
6897 /// Guarantees that the call will inlined at the callsite.
6898 /// If this is not possible, a compile error is emitted instead.
6899 always_inline,
6900
6901 /// Evaluates the call at compile-time. If the call cannot be completed at
6902 /// compile-time, a compile error is emitted instead.
6903 compile_time,
6904 };
6905};
6906 {#code_end#}
6907 {#header_close#}
6908
6844 {#header_open|@cDefine#}6909 {#header_open|@cDefine#}
6845 <pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>6910 <pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>
6846 <p>6911 <p>
...@@ -7445,7 +7510,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -7445,7 +7510,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
7445 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call7510 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
7446 will be inlined. If the call cannot be inlined, a compile error is emitted.7511 will be inlined. If the call cannot be inlined, a compile error is emitted.
7447 </p>7512 </p>
7448 {#see_also|@noInlineCall#}7513 {#see_also|@call#}
7449 {#header_close#}7514 {#header_close#}
74507515
7451 {#header_open|@intCast#}7516 {#header_open|@intCast#}
...@@ -7647,29 +7712,6 @@ fn targetFunction(x: i32) usize {...@@ -7647,29 +7712,6 @@ fn targetFunction(x: i32) usize {
7647 {#code_end#}7712 {#code_end#}
7648 {#header_close#}7713 {#header_close#}
76497714
7650 {#header_open|@noInlineCall#}
7651 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
7652 <p>
7653 This calls a function, in the same way that invoking an expression with parentheses does:
7654 </p>
7655 {#code_begin|test#}
7656const assert = @import("std").debug.assert;
7657
7658test "noinline function call" {
7659 assert(@noInlineCall(add, 3, 9) == 12);
7660}
7661
7662fn add(a: i32, b: i32) i32 {
7663 return a + b;
7664}
7665 {#code_end#}
7666 <p>
7667 Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
7668 will not be inlined. If the call must be inlined, a compile error is emitted.
7669 </p>
7670 {#see_also|@inlineCall#}
7671 {#header_close#}
7672
7673 {#header_open|@OpaqueType#}7715 {#header_open|@OpaqueType#}
7674 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>7716 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
7675 <p>7717 <p>
lib/std/builtin.zig+26
...@@ -379,13 +379,39 @@ pub const CallOptions = struct {...@@ -379,13 +379,39 @@ pub const CallOptions = struct {
379 stack: ?[]align(std.Target.stack_align) u8 = null,379 stack: ?[]align(std.Target.stack_align) u8 = null,
380380
381 pub const Modifier = enum {381 pub const Modifier = enum {
382 /// Equivalent to function call syntax.
382 auto,383 auto,
384
385 /// Asserts that the function call will not suspend. This allows a
386 /// non-async function to call an async function.
383 no_async,387 no_async,
388
389 /// The function call will return an async function frame instead of
390 /// the function's result, which is expected to then be awaited.
391 /// This is equivalent to using the `async` keyword in front of function
392 /// call syntax.
384 async_call,393 async_call,
394
395 /// Prevents tail call optimization. This guarantees that the return
396 /// address will point to the callsite, as opposed to the callsite's
397 /// callsite. If the call is otherwise required to be tail-called
398 /// or inlined, a compile error is emitted instead.
385 never_tail,399 never_tail,
400
401 /// Guarantees that the call will not be inlined. If the call is
402 /// otherwise required to be inlined, a compile error is emitted instead.
386 never_inline,403 never_inline,
404
405 /// Guarantees that the call will be generated with tail call optimization.
406 /// If this is not possible, a compile error is emitted instead.
387 always_tail,407 always_tail,
408
409 /// Guarantees that the call will inlined at the callsite.
410 /// If this is not possible, a compile error is emitted instead.
388 always_inline,411 always_inline,
412
413 /// Evaluates the call at compile-time. If the call cannot be completed at
414 /// compile-time, a compile error is emitted instead.
389 compile_time,415 compile_time,
390 };416 };
391};417};
lib/std/special/start.zig+1-1
...@@ -125,7 +125,7 @@ nakedcc fn _start() noreturn {...@@ -125,7 +125,7 @@ nakedcc fn _start() noreturn {
125 }125 }
126 // If LLVM inlines stack variables into _start, they will overwrite126 // If LLVM inlines stack variables into _start, they will overwrite
127 // the command line argument data.127 // the command line argument data.
128 @noInlineCall(posixCallMainAndExit);128 @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
129}129}
130130
131stdcallcc fn WinMainCRTStartup() noreturn {131stdcallcc fn WinMainCRTStartup() noreturn {
src/all_types.hpp-1
...@@ -1701,7 +1701,6 @@ enum BuiltinFnId {...@@ -1701,7 +1701,6 @@ enum BuiltinFnId {
1701 BuiltinFnIdByteOffsetOf,1701 BuiltinFnIdByteOffsetOf,
1702 BuiltinFnIdBitOffsetOf,1702 BuiltinFnIdBitOffsetOf,
1703 BuiltinFnIdInlineCall,1703 BuiltinFnIdInlineCall,
1704 BuiltinFnIdNoInlineCall,
1705 BuiltinFnIdNewStackCall,1704 BuiltinFnIdNewStackCall,
1706 BuiltinFnIdAsyncCall,1705 BuiltinFnIdAsyncCall,
1707 BuiltinFnIdTypeId,1706 BuiltinFnIdTypeId,
src/codegen.cpp-1
...@@ -8133,7 +8133,6 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8133,7 +8133,6 @@ static void define_builtin_fns(CodeGen *g) {
8133 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);8133 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
8134 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);8134 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
8135 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);8135 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
8136 create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
8137 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);8136 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
8138 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);8137 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
8139 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);8138 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
src/ir.cpp+1-4
...@@ -6014,7 +6014,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6014,7 +6014,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6014 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);6014 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
6015 }6015 }
6016 case BuiltinFnIdInlineCall:6016 case BuiltinFnIdInlineCall:
6017 case BuiltinFnIdNoInlineCall:
6018 {6017 {
6019 if (node->data.fn_call_expr.params.length == 0) {6018 if (node->data.fn_call_expr.params.length == 0) {
6020 add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));6019 add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));
...@@ -6035,11 +6034,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6035,11 +6034,9 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6035 if (args[i] == irb->codegen->invalid_instruction)6034 if (args[i] == irb->codegen->invalid_instruction)
6036 return args[i];6035 return args[i];
6037 }6036 }
6038 CallModifier modifier = (builtin_fn->id == BuiltinFnIdInlineCall) ?
6039 CallModifierAlwaysInline : CallModifierNeverInline;
60406037
6041 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,6038 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
6042 nullptr, modifier, false, nullptr, result_loc);6039 nullptr, CallModifierAlwaysInline, false, nullptr, result_loc);
6043 return ir_lval_wrap(irb, scope, call, lval, result_loc);6040 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6044 }6041 }
6045 case BuiltinFnIdNewStackCall:6042 case BuiltinFnIdNewStackCall:
test/compile_errors.zig+12-11
...@@ -13,11 +13,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -13,11 +13,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
13 \\export fn entry3() void {13 \\export fn entry3() void {
14 \\ comptime @call(.{ .modifier = .never_tail }, foo, .{});14 \\ comptime @call(.{ .modifier = .never_tail }, foo, .{});
15 \\}15 \\}
16 \\export fn entry4() void {
17 \\ @call(.{ .modifier = .never_inline }, bar, .{});
18 \\}
19 \\export fn entry5(c: bool) void {
20 \\ var baz = if (c) baz1 else baz2;
21 \\ @call(.{ .modifier = .compile_time }, baz, .{});
22 \\}
16 \\fn foo() void {}23 \\fn foo() void {}
24 \\inline fn bar() void {}
25 \\fn baz1() void {}
26 \\fn baz2() void {}
17 ,27 ,
18 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",28 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",
19 "tmp.zig:5:58: error: unable to perform 'never_inline' call at compile-time",29 "tmp.zig:5:58: error: unable to perform 'never_inline' call at compile-time",
20 "tmp.zig:8:56: error: unable to perform 'never_tail' call at compile-time",30 "tmp.zig:8:56: error: unable to perform 'never_tail' call at compile-time",
31 "tmp.zig:11:5: error: no-inline call of inline function",
32 "tmp.zig:15:43: error: unable to evaluate constant expression",
21 );33 );
2234
23 cases.add(35 cases.add(
...@@ -1945,17 +1957,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1945,17 +1957,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1945 "tmp.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",1957 "tmp.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",
1946 );1958 );
19471959
1948 cases.add(
1949 "@noInlineCall on an inline function",
1950 \\inline fn foo() void {}
1951 \\
1952 \\export fn entry() void {
1953 \\ @noInlineCall(foo);
1954 \\}
1955 ,
1956 "tmp.zig:4:5: error: no-inline call of inline function",
1957 );
1958
1959 cases.add(1960 cases.add(
1960 "comptime continue inside runtime catch",1961 "comptime continue inside runtime catch",
1961 \\export fn entry(c: bool) void {1962 \\export fn entry(c: bool) void {