mirror of
https://github.com/ziglang/zig.git
synced 2026-01-27 09:45:27 +00:00
stage2: implement noinline fn
This commit is contained in:
parent
903bed931d
commit
dea437edfb
@ -1274,6 +1274,7 @@ fn fnProtoExpr(
|
||||
.is_inferred_error = false,
|
||||
.is_test = false,
|
||||
.is_extern = false,
|
||||
.is_noinline = false,
|
||||
.noalias_bits = noalias_bits,
|
||||
});
|
||||
|
||||
@ -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;
|
||||
@ -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());
|
||||
|
||||
@ -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: {
|
||||
@ -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,
|
||||
});
|
||||
};
|
||||
@ -4093,6 +4099,7 @@ fn testDecl(
|
||||
.is_inferred_error = true,
|
||||
.is_test = true,
|
||||
.is_extern = false,
|
||||
.is_noinline = false,
|
||||
.noalias_bits = 0,
|
||||
});
|
||||
|
||||
@ -10175,6 +10182,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;
|
||||
@ -10216,10 +10224,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 = &.{};
|
||||
@ -10252,6 +10259,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,
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -7252,6 +7252,7 @@ fn zirFunc(
|
||||
src_locs,
|
||||
null,
|
||||
0,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
@ -7382,6 +7383,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 };
|
||||
@ -7577,6 +7579,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,
|
||||
@ -7657,6 +7663,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);
|
||||
@ -18443,6 +18450,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,
|
||||
@ -18460,6 +18468,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
src_locs,
|
||||
lib_name,
|
||||
noalias_bits,
|
||||
is_noinline,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -2736,6 +2736,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,
|
||||
@ -2748,7 +2749,7 @@ pub const Inst = struct {
|
||||
has_ret_ty_body: bool,
|
||||
has_lib_name: bool,
|
||||
has_any_noalias: bool,
|
||||
_: u16 = undefined,
|
||||
_: u15 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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| {
|
||||
|
||||
@ -1984,6 +1984,7 @@ const Writer = struct {
|
||||
inferred_error_set,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
|
||||
.none,
|
||||
&.{},
|
||||
@ -2091,6 +2092,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,
|
||||
@ -2250,6 +2252,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,
|
||||
@ -2273,6 +2276,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});
|
||||
|
||||
12
test/cases/compile_errors/noinline_fn_cc_inline.zig
Normal file
12
test/cases/compile_errors/noinline_fn_cc_inline.zig
Normal file
@ -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'
|
||||
Loading…
x
Reference in New Issue
Block a user