remove `@noInlineCall` from zig
parent
1f602fe8c5
commit
ef83358eb6
|
@ -6841,6 +6841,71 @@ async fn func(y: *i32) void {
|
|||
</p>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@call#}
|
||||
<pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre>
|
||||
<p>
|
||||
Calls a function, in the same way that invoking an expression with parentheses does:
|
||||
</p>
|
||||
{#code_begin|test|call#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "noinline function call" {
|
||||
assert(@call(.{}, add, .{3, 9}) == 12);
|
||||
}
|
||||
|
||||
fn add(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
{#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The
|
||||
{#syntax#}CallOptions{#endsyntax#} struct is reproduced here:
|
||||
</p>
|
||||
{#code_begin|syntax#}
|
||||
pub const CallOptions = struct {
|
||||
modifier: Modifier = .auto,
|
||||
stack: ?[]align(std.Target.stack_align) u8 = null,
|
||||
|
||||
pub const Modifier = enum {
|
||||
/// Equivalent to function call syntax.
|
||||
auto,
|
||||
|
||||
/// Asserts that the function call will not suspend. This allows a
|
||||
/// non-async function to call an async function.
|
||||
no_async,
|
||||
|
||||
/// The function call will return an async function frame instead of
|
||||
/// the function's result, which is expected to then be awaited.
|
||||
/// This is equivalent to using the `async` keyword in front of function
|
||||
/// call syntax.
|
||||
async_call,
|
||||
|
||||
/// Prevents tail call optimization. This guarantees that the return
|
||||
/// address will point to the callsite, as opposed to the callsite's
|
||||
/// callsite. If the call is otherwise required to be tail-called
|
||||
/// or inlined, a compile error is emitted instead.
|
||||
never_tail,
|
||||
|
||||
/// Guarantees that the call will not be inlined. If the call is
|
||||
/// otherwise required to be inlined, a compile error is emitted instead.
|
||||
never_inline,
|
||||
|
||||
/// Guarantees that the call will be generated with tail call optimization.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_tail,
|
||||
|
||||
/// Guarantees that the call will inlined at the callsite.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_inline,
|
||||
|
||||
/// Evaluates the call at compile-time. If the call cannot be completed at
|
||||
/// compile-time, a compile error is emitted instead.
|
||||
compile_time,
|
||||
};
|
||||
};
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@cDefine#}
|
||||
<pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>
|
||||
<p>
|
||||
|
@ -7445,7 +7510,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
|||
Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
|
||||
will be inlined. If the call cannot be inlined, a compile error is emitted.
|
||||
</p>
|
||||
{#see_also|@noInlineCall#}
|
||||
{#see_also|@call#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@intCast#}
|
||||
|
@ -7647,29 +7712,6 @@ fn targetFunction(x: i32) usize {
|
|||
{#code_end#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@noInlineCall#}
|
||||
<pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
|
||||
<p>
|
||||
This calls a function, in the same way that invoking an expression with parentheses does:
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "noinline function call" {
|
||||
assert(@noInlineCall(add, 3, 9) == 12);
|
||||
}
|
||||
|
||||
fn add(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
|
||||
will not be inlined. If the call must be inlined, a compile error is emitted.
|
||||
</p>
|
||||
{#see_also|@inlineCall#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@OpaqueType#}
|
||||
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
|
||||
<p>
|
||||
|
|
|
@ -379,13 +379,39 @@ pub const CallOptions = struct {
|
|||
stack: ?[]align(std.Target.stack_align) u8 = null,
|
||||
|
||||
pub const Modifier = enum {
|
||||
/// Equivalent to function call syntax.
|
||||
auto,
|
||||
|
||||
/// Asserts that the function call will not suspend. This allows a
|
||||
/// non-async function to call an async function.
|
||||
no_async,
|
||||
|
||||
/// The function call will return an async function frame instead of
|
||||
/// the function's result, which is expected to then be awaited.
|
||||
/// This is equivalent to using the `async` keyword in front of function
|
||||
/// call syntax.
|
||||
async_call,
|
||||
|
||||
/// Prevents tail call optimization. This guarantees that the return
|
||||
/// address will point to the callsite, as opposed to the callsite's
|
||||
/// callsite. If the call is otherwise required to be tail-called
|
||||
/// or inlined, a compile error is emitted instead.
|
||||
never_tail,
|
||||
|
||||
/// Guarantees that the call will not be inlined. If the call is
|
||||
/// otherwise required to be inlined, a compile error is emitted instead.
|
||||
never_inline,
|
||||
|
||||
/// Guarantees that the call will be generated with tail call optimization.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_tail,
|
||||
|
||||
/// Guarantees that the call will inlined at the callsite.
|
||||
/// If this is not possible, a compile error is emitted instead.
|
||||
always_inline,
|
||||
|
||||
/// Evaluates the call at compile-time. If the call cannot be completed at
|
||||
/// compile-time, a compile error is emitted instead.
|
||||
compile_time,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -125,7 +125,7 @@ nakedcc fn _start() noreturn {
|
|||
}
|
||||
// If LLVM inlines stack variables into _start, they will overwrite
|
||||
// the command line argument data.
|
||||
@noInlineCall(posixCallMainAndExit);
|
||||
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
|
||||
}
|
||||
|
||||
stdcallcc fn WinMainCRTStartup() noreturn {
|
||||
|
|
|
@ -1701,7 +1701,6 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdByteOffsetOf,
|
||||
BuiltinFnIdBitOffsetOf,
|
||||
BuiltinFnIdInlineCall,
|
||||
BuiltinFnIdNoInlineCall,
|
||||
BuiltinFnIdNewStackCall,
|
||||
BuiltinFnIdAsyncCall,
|
||||
BuiltinFnIdTypeId,
|
||||
|
|
|
@ -8133,7 +8133,6 @@ static void define_builtin_fns(CodeGen *g) {
|
|||
create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
|
||||
create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
|
||||
create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
|
||||
|
|
|
@ -6014,7 +6014,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdInlineCall:
|
||||
case BuiltinFnIdNoInlineCall:
|
||||
{
|
||||
if (node->data.fn_call_expr.params.length == 0) {
|
||||
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
|
|||
if (args[i] == irb->codegen->invalid_instruction)
|
||||
return args[i];
|
||||
}
|
||||
CallModifier modifier = (builtin_fn->id == BuiltinFnIdInlineCall) ?
|
||||
CallModifierAlwaysInline : CallModifierNeverInline;
|
||||
|
||||
IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
|
||||
nullptr, modifier, false, nullptr, result_loc);
|
||||
nullptr, CallModifierAlwaysInline, false, nullptr, result_loc);
|
||||
return ir_lval_wrap(irb, scope, call, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdNewStackCall:
|
||||
|
|
|
@ -13,11 +13,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
\\export fn entry3() void {
|
||||
\\ comptime @call(.{ .modifier = .never_tail }, foo, .{});
|
||||
\\}
|
||||
\\export fn entry4() void {
|
||||
\\ @call(.{ .modifier = .never_inline }, bar, .{});
|
||||
\\}
|
||||
\\export fn entry5(c: bool) void {
|
||||
\\ var baz = if (c) baz1 else baz2;
|
||||
\\ @call(.{ .modifier = .compile_time }, baz, .{});
|
||||
\\}
|
||||
\\fn foo() void {}
|
||||
\\inline fn bar() void {}
|
||||
\\fn baz1() 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:11:5: error: no-inline call of inline function",
|
||||
"tmp.zig:15:43: error: unable to evaluate constant expression",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
@ -1945,17 +1957,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
"tmp.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"@noInlineCall on an inline function",
|
||||
\\inline fn foo() void {}
|
||||
\\
|
||||
\\export fn entry() void {
|
||||
\\ @noInlineCall(foo);
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:4:5: error: no-inline call of inline function",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime catch",
|
||||
\\export fn entry(c: bool) void {
|
||||
|
|
Loading…
Reference in New Issue