authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2022-07-24 01:56:33-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-24 11:56:33+03:00
logdea437edfb124b8a4cf4f2e09330ef4282991cc9
treecff1a5c5f9b89c4f8f94def8006f7d07f9757dbc
parent903bed931dddc8b3f7ad1fa87e57eca13375dd32
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

stage2: implement `noinline fn`


7 files changed, 47 insertions(+), 7 deletions(-)

src/AstGen.zig+13-5
......@@ -1274,6 +1274,7 @@ fn fnProtoExpr(
12741274 .is_inferred_error = false,
12751275 .is_test = false,
12761276 .is_extern = false,
1277 .is_noinline = false,
12771278 .noalias_bits = noalias_bits,
12781279 });
12791280
......@@ -3389,7 +3390,6 @@ fn fnDecl(
33893390 };
33903391 defer fn_gz.unstack();
33913392
3392 // TODO: support noinline
33933393 const is_pub = fn_proto.visib_token != null;
33943394 const is_export = blk: {
33953395 const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
......@@ -3403,6 +3403,10 @@ fn fnDecl(
34033403 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
34043404 break :blk token_tags[maybe_inline_token] == .keyword_inline;
34053405 };
3406 const is_noinline = blk: {
3407 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
3408 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
3409 };
34063410
34073411 const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());
34083412
......@@ -3610,6 +3614,7 @@ fn fnDecl(
36103614 .is_inferred_error = false,
36113615 .is_test = false,
36123616 .is_extern = true,
3617 .is_noinline = is_noinline,
36133618 .noalias_bits = noalias_bits,
36143619 });
36153620 } else func: {
......@@ -3658,6 +3663,7 @@ fn fnDecl(
36583663 .is_inferred_error = is_inferred_error,
36593664 .is_test = false,
36603665 .is_extern = false,
3666 .is_noinline = is_noinline,
36613667 .noalias_bits = noalias_bits,
36623668 });
36633669 };
......@@ -4093,6 +4099,7 @@ fn testDecl(
40934099 .is_inferred_error = true,
40944100 .is_test = true,
40954101 .is_extern = false,
4102 .is_noinline = false,
40964103 .noalias_bits = 0,
40974104 });
40984105
......@@ -10175,6 +10182,7 @@ const GenZir = struct {
1017510182 is_inferred_error: bool,
1017610183 is_test: bool,
1017710184 is_extern: bool,
10185 is_noinline: bool,
1017810186 }) !Zir.Inst.Ref {
1017910187 assert(args.src_node != 0);
1018010188 const astgen = gz.astgen;
......@@ -10216,10 +10224,9 @@ const GenZir = struct {
1021610224 }
1021710225 const body_len = astgen.countBodyLenAfterFixups(body);
1021810226
10219 if (args.cc_ref != .none or args.lib_name != 0 or
10220 args.is_var_args or args.is_test or args.is_extern or
10221 args.align_ref != .none or args.section_ref != .none or
10222 args.addrspace_ref != .none or args.noalias_bits != 0)
10227 if (args.cc_ref != .none or args.lib_name != 0 or args.is_var_args or args.is_test or
10228 args.is_extern or args.align_ref != .none or args.section_ref != .none or
10229 args.addrspace_ref != .none or args.noalias_bits != 0 or args.is_noinline)
1022310230 {
1022410231 var align_body: []Zir.Inst.Index = &.{};
1022510232 var addrspace_body: []Zir.Inst.Index = &.{};
......@@ -10252,6 +10259,7 @@ const GenZir = struct {
1025210259 .is_inferred_error = args.is_inferred_error,
1025310260 .is_test = args.is_test,
1025410261 .is_extern = args.is_extern,
10262 .is_noinline = args.is_noinline,
1025510263 .has_lib_name = args.lib_name != 0,
1025610264 .has_any_noalias = args.noalias_bits != 0,
1025710265
src/Module.zig+1-1
......@@ -1488,7 +1488,7 @@ pub const Fn = struct {
14881488 branch_quota: u32,
14891489 state: Analysis,
14901490 is_cold: bool = false,
1491 is_noinline: bool = false,
1491 is_noinline: bool,
14921492 calls_or_awaits_errorable_fn: bool = false,
14931493
14941494 /// Any inferred error sets that this function owns, both its own inferred error set and
src/Sema.zig+9
......@@ -7252,6 +7252,7 @@ fn zirFunc(
72527252 src_locs,
72537253 null,
72547254 0,
7255 false,
72557256 );
72567257}
72577258
......@@ -7382,6 +7383,7 @@ fn funcCommon(
73827383 src_locs: Zir.Inst.Func.SrcLocs,
73837384 opt_lib_name: ?[]const u8,
73847385 noalias_bits: u32,
7386 is_noinline: bool,
73857387) CompileError!Air.Inst.Ref {
73867388 const fn_src = LazySrcLoc.nodeOffset(src_node_offset);
73877389 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
......@@ -7577,6 +7579,10 @@ fn funcCommon(
75777579 });
75787580 }
75797581
7582 if (cc_workaround == .Inline and is_noinline) {
7583 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
7584 }
7585
75807586 break :fn_ty try Type.Tag.function.create(sema.arena, .{
75817587 .param_types = param_types,
75827588 .comptime_params = comptime_params.ptr,
......@@ -7657,6 +7663,7 @@ fn funcCommon(
76577663 .rbrace_column = @truncate(u16, src_locs.columns >> 16),
76587664 .param_names = param_names,
76597665 .branch_quota = default_branch_quota,
7666 .is_noinline = is_noinline,
76607667 };
76617668 if (maybe_inferred_error_set_node) |node| {
76627669 new_func.inferred_error_sets.prepend(node);
......@@ -18443,6 +18450,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1844318450 const is_var_args = extra.data.bits.is_var_args;
1844418451 const is_inferred_error = extra.data.bits.is_inferred_error;
1844518452 const is_extern = extra.data.bits.is_extern;
18453 const is_noinline = extra.data.bits.is_noinline;
1844618454
1844718455 return sema.funcCommon(
1844818456 block,
......@@ -18460,6 +18468,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1846018468 src_locs,
1846118469 lib_name,
1846218470 noalias_bits,
18471 is_noinline,
1846318472 );
1846418473}
1846518474
src/Zir.zig+2-1
......@@ -2736,6 +2736,7 @@ pub const Inst = struct {
27362736 is_inferred_error: bool,
27372737 is_test: bool,
27382738 is_extern: bool,
2739 is_noinline: bool,
27392740 has_align_ref: bool,
27402741 has_align_body: bool,
27412742 has_addrspace_ref: bool,
......@@ -2748,7 +2749,7 @@ pub const Inst = struct {
27482749 has_ret_ty_body: bool,
27492750 has_lib_name: bool,
27502751 has_any_noalias: bool,
2751 _: u16 = undefined,
2752 _: u15 = undefined,
27522753 };
27532754 };
27542755
src/codegen/llvm.zig+6
......@@ -699,6 +699,12 @@ pub const Object = struct {
699699 DeclGen.removeFnAttr(llvm_func, "cold");
700700 }
701701
702 if (func.is_noinline) {
703 dg.addFnAttr(llvm_func, "noinline");
704 } else {
705 DeclGen.removeFnAttr(llvm_func, "noinline");
706 }
707
702708 // Remove all the basic blocks of a function in order to start over, generating
703709 // LLVM IR from an empty function body.
704710 while (llvm_func.getFirstBasicBlock()) |bb| {
src/print_zir.zig+4
......@@ -1984,6 +1984,7 @@ const Writer = struct {
19841984 inferred_error_set,
19851985 false,
19861986 false,
1987 false,
19871988
19881989 .none,
19891990 &.{},
......@@ -2091,6 +2092,7 @@ const Writer = struct {
20912092 extra.data.bits.is_inferred_error,
20922093 extra.data.bits.is_var_args,
20932094 extra.data.bits.is_extern,
2095 extra.data.bits.is_noinline,
20942096 align_ref,
20952097 align_body,
20962098 addrspace_ref,
......@@ -2250,6 +2252,7 @@ const Writer = struct {
22502252 inferred_error_set: bool,
22512253 var_args: bool,
22522254 is_extern: bool,
2255 is_noinline: bool,
22532256 align_ref: Zir.Inst.Ref,
22542257 align_body: []const Zir.Inst.Index,
22552258 addrspace_ref: Zir.Inst.Ref,
......@@ -2273,6 +2276,7 @@ const Writer = struct {
22732276 try self.writeFlag(stream, "vargs, ", var_args);
22742277 try self.writeFlag(stream, "extern, ", is_extern);
22752278 try self.writeFlag(stream, "inferror, ", inferred_error_set);
2279 try self.writeFlag(stream, "noinline, ", is_noinline);
22762280
22772281 if (noalias_bits != 0) {
22782282 try stream.print("noalias=0b{b}, ", .{noalias_bits});
test/cases/compile_errors/noinline_fn_cc_inline.zig created+12
......@@ -0,0 +1,12 @@
1const cc = .Inline;
2noinline fn foo() callconv(cc) void {}
3
4comptime {
5 _ = foo;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :2:28: error: 'noinline' function cannot have callconv 'Inline'