From 0c9c9117bacfcff2b11ab658b89f192e27fc7c3d Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Sat, 29 Apr 2023 03:35:16 +0200 Subject: [PATCH 1/2] std.builtin.CallModifier: add missing word --- lib/std/builtin.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 3523c5ac12..4a5e8a28d6 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -646,7 +646,7 @@ pub const CallModifier = enum { /// If this is not possible, a compile error is emitted instead. always_tail, - /// Guarantees that the call will inlined at the callsite. + /// Guarantees that the call will be inlined at the callsite. /// If this is not possible, a compile error is emitted instead. always_inline, From bd8b5c25ece2fa158196381004db6e655226576c Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Sat, 29 Apr 2023 04:19:58 +0200 Subject: [PATCH 2/2] Sema: emit error for always_inline call of noinline function Fixes #15489 This also lays the groundwork for exposing the whether or not a function is noinline in std.builtin.Fn as an `is_noinline: bool` field if we ever want to do that. --- src/Sema.zig | 10 ++++++++-- src/type.zig | 13 ++++++++++++ .../compile_errors/bad_usage_of_call.zig | 20 +++++++++++++++---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 8b47f1877b..207ccb41a9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6565,7 +6565,10 @@ fn analyzeCall( }; if (modifier == .never_inline and func_ty_info.cc == .Inline) { - return sema.fail(block, call_src, "no-inline call of inline function", .{}); + return sema.fail(block, call_src, "'never_inline' call of inline function", .{}); + } + if (modifier == .always_inline and func_ty_info.is_noinline) { + return sema.fail(block, call_src, "'always_inline' call of noinline function", .{}); } const gpa = sema.gpa; @@ -8784,7 +8787,8 @@ fn funcCommon( if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and alignment.? == 0 and address_space.? == target_util.defaultAddressSpace(target, .function) and - section == .default) + section == .default and + !is_noinline) { if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) { break :fn_ty Type.initTag(.fn_noreturn_no_args); @@ -9002,6 +9006,7 @@ fn funcCommon( .addrspace_is_generic = address_space == null, .is_var_args = var_args, .is_generic = is_generic, + .is_noinline = is_noinline, .noalias_bits = noalias_bits, }); }; @@ -19217,6 +19222,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in .cc = cc, .is_var_args = is_var_args, .is_generic = false, + .is_noinline = false, .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, diff --git a/src/type.zig b/src/type.zig index c7b2844970..82896800ed 100644 --- a/src/type.zig +++ b/src/type.zig @@ -666,6 +666,9 @@ pub const Type = extern union { if (a_info.is_generic != b_info.is_generic) return false; + if (a_info.is_noinline != b_info.is_noinline) + return false; + if (a_info.noalias_bits != b_info.noalias_bits) return false; @@ -1074,6 +1077,7 @@ pub const Type = extern union { } std.hash.autoHash(hasher, fn_info.is_var_args); std.hash.autoHash(hasher, fn_info.is_generic); + std.hash.autoHash(hasher, fn_info.is_noinline); std.hash.autoHash(hasher, fn_info.noalias_bits); std.hash.autoHash(hasher, fn_info.param_types.len); @@ -1454,6 +1458,7 @@ pub const Type = extern union { .alignment = payload.alignment, .is_var_args = payload.is_var_args, .is_generic = payload.is_generic, + .is_noinline = payload.is_noinline, .comptime_params = comptime_params.ptr, .align_is_generic = payload.align_is_generic, .cc_is_generic = payload.cc_is_generic, @@ -2069,6 +2074,9 @@ pub const Type = extern union { .function => { const fn_info = ty.fnInfo(); + if (fn_info.is_noinline) { + try writer.writeAll("noinline "); + } try writer.writeAll("fn("); for (fn_info.param_types, 0..) |param_ty, i| { if (i != 0) try writer.writeAll(", "); @@ -4863,6 +4871,7 @@ pub const Type = extern union { .alignment = 0, .is_var_args = false, .is_generic = false, + .is_noinline = false, .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, @@ -4877,6 +4886,7 @@ pub const Type = extern union { .alignment = 0, .is_var_args = false, .is_generic = false, + .is_noinline = false, .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, @@ -4891,6 +4901,7 @@ pub const Type = extern union { .alignment = 0, .is_var_args = false, .is_generic = false, + .is_noinline = false, .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, @@ -4905,6 +4916,7 @@ pub const Type = extern union { .alignment = 0, .is_var_args = false, .is_generic = false, + .is_noinline = false, .align_is_generic = false, .cc_is_generic = false, .section_is_generic = false, @@ -6367,6 +6379,7 @@ pub const Type = extern union { cc: std.builtin.CallingConvention, is_var_args: bool, is_generic: bool, + is_noinline: bool, align_is_generic: bool, cc_is_generic: bool, section_is_generic: bool, diff --git a/test/cases/compile_errors/bad_usage_of_call.zig b/test/cases/compile_errors/bad_usage_of_call.zig index c0b632bef6..3669cda3bf 100644 --- a/test/cases/compile_errors/bad_usage_of_call.zig +++ b/test/cases/compile_errors/bad_usage_of_call.zig @@ -14,14 +14,25 @@ export fn entry5(c: bool) void { var baz = if (c) &baz1 else &baz2; @call(.compile_time, baz, .{}); } +export fn entry6() void { + _ = @call(.always_inline, dummy, .{}); +} +export fn entry7() void { + _ = @call(.always_inline, dummy2, .{}); +} pub export fn entry() void { var call_me: *const fn () void = undefined; @call(.always_inline, call_me, .{}); } + fn foo() void {} -fn bar() callconv(.Inline) void {} +inline fn bar() void {} fn baz1() void {} fn baz2() void {} +noinline fn dummy() u32 { + return 0; +} +noinline fn dummy2() void {} // error // backend=stage2 @@ -30,7 +41,8 @@ fn baz2() void {} // :2:23: error: expected a tuple, found 'void' // :5:21: error: unable to perform 'never_inline' call at compile-time // :8:21: error: unable to perform 'never_tail' call at compile-time -// :11:5: error: no-inline call of inline function +// :11:5: error: 'never_inline' call of inline function // :15:26: error: modifier 'compile_time' requires a comptime-known function -// :19:27: error: modifier 'always_inline' requires a comptime-known function - +// :18:9: error: 'always_inline' call of noinline function +// :21:9: error: 'always_inline' call of noinline function +// :25:27: error: modifier 'always_inline' requires a comptime-known function