Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stage2: implement noinline fn #12179

Merged
merged 2 commits into from
Jul 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,7 @@ fn fnProtoExpr(
.is_inferred_error = false,
.is_test = false,
.is_extern = false,
.is_noinline = false,
.noalias_bits = noalias_bits,
});

Expand Down Expand Up @@ -3389,7 +3390,6 @@ fn fnDecl(
};
defer fn_gz.unstack();

// TODO: support noinline
const is_pub = fn_proto.visib_token != null;
const is_export = blk: {
const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
Expand All @@ -3403,6 +3403,10 @@ fn fnDecl(
const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
break :blk token_tags[maybe_inline_token] == .keyword_inline;
};
const is_noinline = blk: {
const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
};

const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken());

Expand Down Expand Up @@ -3610,6 +3614,7 @@ fn fnDecl(
.is_inferred_error = false,
.is_test = false,
.is_extern = true,
.is_noinline = is_noinline,
.noalias_bits = noalias_bits,
});
} else func: {
Expand Down Expand Up @@ -3658,6 +3663,7 @@ fn fnDecl(
.is_inferred_error = is_inferred_error,
.is_test = false,
.is_extern = false,
.is_noinline = is_noinline,
.noalias_bits = noalias_bits,
});
};
Expand Down Expand Up @@ -4093,6 +4099,7 @@ fn testDecl(
.is_inferred_error = true,
.is_test = true,
.is_extern = false,
.is_noinline = false,
.noalias_bits = 0,
});

Expand Down Expand Up @@ -10170,6 +10177,7 @@ const GenZir = struct {
is_inferred_error: bool,
is_test: bool,
is_extern: bool,
is_noinline: bool,
}) !Zir.Inst.Ref {
assert(args.src_node != 0);
const astgen = gz.astgen;
Expand Down Expand Up @@ -10211,10 +10219,9 @@ const GenZir = struct {
}
const body_len = astgen.countBodyLenAfterFixups(body);

if (args.cc_ref != .none or args.lib_name != 0 or
args.is_var_args or args.is_test or args.is_extern or
args.align_ref != .none or args.section_ref != .none or
args.addrspace_ref != .none or args.noalias_bits != 0)
if (args.cc_ref != .none or args.lib_name != 0 or args.is_var_args or args.is_test or
args.is_extern or args.align_ref != .none or args.section_ref != .none or
args.addrspace_ref != .none or args.noalias_bits != 0 or args.is_noinline)
{
var align_body: []Zir.Inst.Index = &.{};
var addrspace_body: []Zir.Inst.Index = &.{};
Expand Down Expand Up @@ -10247,6 +10254,7 @@ const GenZir = struct {
.is_inferred_error = args.is_inferred_error,
.is_test = args.is_test,
.is_extern = args.is_extern,
.is_noinline = args.is_noinline,
.has_lib_name = args.lib_name != 0,
.has_any_noalias = args.noalias_bits != 0,

Expand Down
2 changes: 1 addition & 1 deletion src/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1488,7 +1488,7 @@ pub const Fn = struct {
branch_quota: u32,
state: Analysis,
is_cold: bool = false,
is_noinline: bool = false,
is_noinline: bool,
calls_or_awaits_errorable_fn: bool = false,

/// Any inferred error sets that this function owns, both its own inferred error set and
Expand Down
9 changes: 9 additions & 0 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7229,6 +7229,7 @@ fn zirFunc(
src_locs,
null,
0,
false,
);
}

Expand Down Expand Up @@ -7359,6 +7360,7 @@ fn funcCommon(
src_locs: Zir.Inst.Func.SrcLocs,
opt_lib_name: ?[]const u8,
noalias_bits: u32,
is_noinline: bool,
) CompileError!Air.Inst.Ref {
const fn_src = LazySrcLoc.nodeOffset(src_node_offset);
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
Expand Down Expand Up @@ -7554,6 +7556,10 @@ fn funcCommon(
});
}

if (cc_workaround == .Inline and is_noinline) {
return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
}

break :fn_ty try Type.Tag.function.create(sema.arena, .{
.param_types = param_types,
.comptime_params = comptime_params.ptr,
Expand Down Expand Up @@ -7634,6 +7640,7 @@ fn funcCommon(
.rbrace_column = @truncate(u16, src_locs.columns >> 16),
.param_names = param_names,
.branch_quota = default_branch_quota,
.is_noinline = is_noinline,
};
if (maybe_inferred_error_set_node) |node| {
new_func.inferred_error_sets.prepend(node);
Expand Down Expand Up @@ -18194,6 +18201,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const is_var_args = extra.data.bits.is_var_args;
const is_inferred_error = extra.data.bits.is_inferred_error;
const is_extern = extra.data.bits.is_extern;
const is_noinline = extra.data.bits.is_noinline;

return sema.funcCommon(
block,
Expand All @@ -18211,6 +18219,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
src_locs,
lib_name,
noalias_bits,
is_noinline,
);
}

Expand Down
3 changes: 2 additions & 1 deletion src/Zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2731,6 +2731,7 @@ pub const Inst = struct {
is_inferred_error: bool,
is_test: bool,
is_extern: bool,
is_noinline: bool,
has_align_ref: bool,
has_align_body: bool,
has_addrspace_ref: bool,
Expand All @@ -2743,7 +2744,7 @@ pub const Inst = struct {
has_ret_ty_body: bool,
has_lib_name: bool,
has_any_noalias: bool,
_: u16 = undefined,
_: u15 = undefined,
};
};

Expand Down
6 changes: 6 additions & 0 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,12 @@ pub const Object = struct {
DeclGen.removeFnAttr(llvm_func, "cold");
}

if (func.is_noinline) {
dg.addFnAttr(llvm_func, "noinline");
} else {
DeclGen.removeFnAttr(llvm_func, "noinline");
}

// Remove all the basic blocks of a function in order to start over, generating
// LLVM IR from an empty function body.
while (llvm_func.getFirstBasicBlock()) |bb| {
Expand Down
4 changes: 4 additions & 0 deletions src/print_zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1983,6 +1983,7 @@ const Writer = struct {
inferred_error_set,
false,
false,
false,

.none,
&.{},
Expand Down Expand Up @@ -2090,6 +2091,7 @@ const Writer = struct {
extra.data.bits.is_inferred_error,
extra.data.bits.is_var_args,
extra.data.bits.is_extern,
extra.data.bits.is_noinline,
align_ref,
align_body,
addrspace_ref,
Expand Down Expand Up @@ -2249,6 +2251,7 @@ const Writer = struct {
inferred_error_set: bool,
var_args: bool,
is_extern: bool,
is_noinline: bool,
align_ref: Zir.Inst.Ref,
align_body: []const Zir.Inst.Index,
addrspace_ref: Zir.Inst.Ref,
Expand All @@ -2272,6 +2275,7 @@ const Writer = struct {
try self.writeFlag(stream, "vargs, ", var_args);
try self.writeFlag(stream, "extern, ", is_extern);
try self.writeFlag(stream, "inferror, ", inferred_error_set);
try self.writeFlag(stream, "noinline, ", is_noinline);

if (noalias_bits != 0) {
try stream.print("noalias=0b{b}, ", .{noalias_bits});
Expand Down
12 changes: 12 additions & 0 deletions test/cases/compile_errors/noinline_fn_cc_inline.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const cc = .Inline;
noinline fn foo() callconv(cc) void {}

comptime {
_ = foo;
}

// error
// backend=stage2
// target=native
//
// :2:28: error: 'noinline' function cannot have callconv 'Inline'