authorgravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-04-29 04:19:58+02:00
committergravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-04-29 04:19:58+02:00
logbd8b5c25ece2fa158196381004db6e655226576c
tree770abdc5199160fa4cb5b2eafb0baa06a300e2cd
parent0c9c9117bacfcff2b11ab658b89f192e27fc7c3d

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.

3 files changed, 37 insertions(+), 6 deletions(-)

src/Sema.zig+8-2
...@@ -6565,7 +6565,10 @@ fn analyzeCall(...@@ -6565,7 +6565,10 @@ fn analyzeCall(
6565 };6565 };
65666566
6567 if (modifier == .never_inline and func_ty_info.cc == .Inline) {6567 if (modifier == .never_inline and func_ty_info.cc == .Inline) {
6568 return sema.fail(block, call_src, "no-inline call of inline function", .{});6568 return sema.fail(block, call_src, "'never_inline' call of inline function", .{});
6569 }
6570 if (modifier == .always_inline and func_ty_info.is_noinline) {
6571 return sema.fail(block, call_src, "'always_inline' call of noinline function", .{});
6569 }6572 }
65706573
6571 const gpa = sema.gpa;6574 const gpa = sema.gpa;
...@@ -8784,7 +8787,8 @@ fn funcCommon(...@@ -8784,7 +8787,8 @@ fn funcCommon(
8784 if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and8787 if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and
8785 alignment.? == 0 and8788 alignment.? == 0 and
8786 address_space.? == target_util.defaultAddressSpace(target, .function) and8789 address_space.? == target_util.defaultAddressSpace(target, .function) and
8787 section == .default)8790 section == .default and
8791 !is_noinline)
8788 {8792 {
8789 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {8793 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {
8790 break :fn_ty Type.initTag(.fn_noreturn_no_args);8794 break :fn_ty Type.initTag(.fn_noreturn_no_args);
...@@ -9002,6 +9006,7 @@ fn funcCommon(...@@ -9002,6 +9006,7 @@ fn funcCommon(
9002 .addrspace_is_generic = address_space == null,9006 .addrspace_is_generic = address_space == null,
9003 .is_var_args = var_args,9007 .is_var_args = var_args,
9004 .is_generic = is_generic,9008 .is_generic = is_generic,
9009 .is_noinline = is_noinline,
9005 .noalias_bits = noalias_bits,9010 .noalias_bits = noalias_bits,
9006 });9011 });
9007 };9012 };
...@@ -19217,6 +19222,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -19217,6 +19222,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
19217 .cc = cc,19222 .cc = cc,
19218 .is_var_args = is_var_args,19223 .is_var_args = is_var_args,
19219 .is_generic = false,19224 .is_generic = false,
19225 .is_noinline = false,
19220 .align_is_generic = false,19226 .align_is_generic = false,
19221 .cc_is_generic = false,19227 .cc_is_generic = false,
19222 .section_is_generic = false,19228 .section_is_generic = false,
src/type.zig+13
...@@ -666,6 +666,9 @@ pub const Type = extern union {...@@ -666,6 +666,9 @@ pub const Type = extern union {
666 if (a_info.is_generic != b_info.is_generic)666 if (a_info.is_generic != b_info.is_generic)
667 return false;667 return false;
668668
669 if (a_info.is_noinline != b_info.is_noinline)
670 return false;
671
669 if (a_info.noalias_bits != b_info.noalias_bits)672 if (a_info.noalias_bits != b_info.noalias_bits)
670 return false;673 return false;
671674
...@@ -1074,6 +1077,7 @@ pub const Type = extern union {...@@ -1074,6 +1077,7 @@ pub const Type = extern union {
1074 }1077 }
1075 std.hash.autoHash(hasher, fn_info.is_var_args);1078 std.hash.autoHash(hasher, fn_info.is_var_args);
1076 std.hash.autoHash(hasher, fn_info.is_generic);1079 std.hash.autoHash(hasher, fn_info.is_generic);
1080 std.hash.autoHash(hasher, fn_info.is_noinline);
1077 std.hash.autoHash(hasher, fn_info.noalias_bits);1081 std.hash.autoHash(hasher, fn_info.noalias_bits);
10781082
1079 std.hash.autoHash(hasher, fn_info.param_types.len);1083 std.hash.autoHash(hasher, fn_info.param_types.len);
...@@ -1454,6 +1458,7 @@ pub const Type = extern union {...@@ -1454,6 +1458,7 @@ pub const Type = extern union {
1454 .alignment = payload.alignment,1458 .alignment = payload.alignment,
1455 .is_var_args = payload.is_var_args,1459 .is_var_args = payload.is_var_args,
1456 .is_generic = payload.is_generic,1460 .is_generic = payload.is_generic,
1461 .is_noinline = payload.is_noinline,
1457 .comptime_params = comptime_params.ptr,1462 .comptime_params = comptime_params.ptr,
1458 .align_is_generic = payload.align_is_generic,1463 .align_is_generic = payload.align_is_generic,
1459 .cc_is_generic = payload.cc_is_generic,1464 .cc_is_generic = payload.cc_is_generic,
...@@ -2069,6 +2074,9 @@ pub const Type = extern union {...@@ -2069,6 +2074,9 @@ pub const Type = extern union {
20692074
2070 .function => {2075 .function => {
2071 const fn_info = ty.fnInfo();2076 const fn_info = ty.fnInfo();
2077 if (fn_info.is_noinline) {
2078 try writer.writeAll("noinline ");
2079 }
2072 try writer.writeAll("fn(");2080 try writer.writeAll("fn(");
2073 for (fn_info.param_types, 0..) |param_ty, i| {2081 for (fn_info.param_types, 0..) |param_ty, i| {
2074 if (i != 0) try writer.writeAll(", ");2082 if (i != 0) try writer.writeAll(", ");
...@@ -4863,6 +4871,7 @@ pub const Type = extern union {...@@ -4863,6 +4871,7 @@ pub const Type = extern union {
4863 .alignment = 0,4871 .alignment = 0,
4864 .is_var_args = false,4872 .is_var_args = false,
4865 .is_generic = false,4873 .is_generic = false,
4874 .is_noinline = false,
4866 .align_is_generic = false,4875 .align_is_generic = false,
4867 .cc_is_generic = false,4876 .cc_is_generic = false,
4868 .section_is_generic = false,4877 .section_is_generic = false,
...@@ -4877,6 +4886,7 @@ pub const Type = extern union {...@@ -4877,6 +4886,7 @@ pub const Type = extern union {
4877 .alignment = 0,4886 .alignment = 0,
4878 .is_var_args = false,4887 .is_var_args = false,
4879 .is_generic = false,4888 .is_generic = false,
4889 .is_noinline = false,
4880 .align_is_generic = false,4890 .align_is_generic = false,
4881 .cc_is_generic = false,4891 .cc_is_generic = false,
4882 .section_is_generic = false,4892 .section_is_generic = false,
...@@ -4891,6 +4901,7 @@ pub const Type = extern union {...@@ -4891,6 +4901,7 @@ pub const Type = extern union {
4891 .alignment = 0,4901 .alignment = 0,
4892 .is_var_args = false,4902 .is_var_args = false,
4893 .is_generic = false,4903 .is_generic = false,
4904 .is_noinline = false,
4894 .align_is_generic = false,4905 .align_is_generic = false,
4895 .cc_is_generic = false,4906 .cc_is_generic = false,
4896 .section_is_generic = false,4907 .section_is_generic = false,
...@@ -4905,6 +4916,7 @@ pub const Type = extern union {...@@ -4905,6 +4916,7 @@ pub const Type = extern union {
4905 .alignment = 0,4916 .alignment = 0,
4906 .is_var_args = false,4917 .is_var_args = false,
4907 .is_generic = false,4918 .is_generic = false,
4919 .is_noinline = false,
4908 .align_is_generic = false,4920 .align_is_generic = false,
4909 .cc_is_generic = false,4921 .cc_is_generic = false,
4910 .section_is_generic = false,4922 .section_is_generic = false,
...@@ -6367,6 +6379,7 @@ pub const Type = extern union {...@@ -6367,6 +6379,7 @@ pub const Type = extern union {
6367 cc: std.builtin.CallingConvention,6379 cc: std.builtin.CallingConvention,
6368 is_var_args: bool,6380 is_var_args: bool,
6369 is_generic: bool,6381 is_generic: bool,
6382 is_noinline: bool,
6370 align_is_generic: bool,6383 align_is_generic: bool,
6371 cc_is_generic: bool,6384 cc_is_generic: bool,
6372 section_is_generic: bool,6385 section_is_generic: bool,
test/cases/compile_errors/bad_usage_of_call.zig+16-4
...@@ -14,14 +14,25 @@ export fn entry5(c: bool) void {...@@ -14,14 +14,25 @@ export fn entry5(c: bool) void {
14 var baz = if (c) &baz1 else &baz2;14 var baz = if (c) &baz1 else &baz2;
15 @call(.compile_time, baz, .{});15 @call(.compile_time, baz, .{});
16}16}
17export fn entry6() void {
18 _ = @call(.always_inline, dummy, .{});
19}
20export fn entry7() void {
21 _ = @call(.always_inline, dummy2, .{});
22}
17pub export fn entry() void {23pub export fn entry() void {
18 var call_me: *const fn () void = undefined;24 var call_me: *const fn () void = undefined;
19 @call(.always_inline, call_me, .{});25 @call(.always_inline, call_me, .{});
20}26}
27
21fn foo() void {}28fn foo() void {}
22fn bar() callconv(.Inline) void {}29inline fn bar() void {}
23fn baz1() void {}30fn baz1() void {}
24fn baz2() void {}31fn baz2() void {}
32noinline fn dummy() u32 {
33 return 0;
34}
35noinline fn dummy2() void {}
2536
26// error37// error
27// backend=stage238// backend=stage2
...@@ -30,7 +41,8 @@ fn baz2() void {}...@@ -30,7 +41,8 @@ fn baz2() void {}
30// :2:23: error: expected a tuple, found 'void'41// :2:23: error: expected a tuple, found 'void'
31// :5:21: error: unable to perform 'never_inline' call at compile-time42// :5:21: error: unable to perform 'never_inline' call at compile-time
32// :8:21: error: unable to perform 'never_tail' call at compile-time43// :8:21: error: unable to perform 'never_tail' call at compile-time
33// :11:5: error: no-inline call of inline function44// :11:5: error: 'never_inline' call of inline function
34// :15:26: error: modifier 'compile_time' requires a comptime-known function45// :15:26: error: modifier 'compile_time' requires a comptime-known function
35// :19:27: error: modifier 'always_inline' requires a comptime-known function46// :18:9: error: 'always_inline' call of noinline function
3647// :21:9: error: 'always_inline' call of noinline function
48// :25:27: error: modifier 'always_inline' requires a comptime-known function