Skip to content

Commit dea437e

Browse files
authored
stage2: implement noinline fn
1 parent 903bed9 commit dea437e

File tree

7 files changed

+47
-7
lines changed

7 files changed

+47
-7
lines changed

src/AstGen.zig

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const cc = .Inline;
2+
noinline fn foo() callconv(cc) void {}
3+
4+
comptime {
5+
_ = foo;
6+
}
7+
8+
// error
9+
// backend=stage2
10+
// target=native
11+
//
12+
// :2:28: error: 'noinline' function cannot have callconv 'Inline'

0 commit comments

Comments
 (0)