mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
stage2: support inline keyword on function decls
This is an alternative to callconv(.Inline). Using an inline keyword as well as an explicit callconv() is a compile error.
This commit is contained in:
parent
569525f03e
commit
3fd8ac092e
@ -1833,7 +1833,7 @@ pub const Tree = struct {
|
||||
var result: full.FnProto = .{
|
||||
.ast = info,
|
||||
.visib_token = null,
|
||||
.extern_export_token = null,
|
||||
.extern_export_inline_token = null,
|
||||
.lib_name = null,
|
||||
.name_token = null,
|
||||
.lparen = undefined,
|
||||
@ -1842,7 +1842,11 @@ pub const Tree = struct {
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
switch (token_tags[i]) {
|
||||
.keyword_extern, .keyword_export => result.extern_export_token = i,
|
||||
.keyword_extern,
|
||||
.keyword_export,
|
||||
.keyword_inline,
|
||||
.keyword_noinline,
|
||||
=> result.extern_export_inline_token = i,
|
||||
.keyword_pub => result.visib_token = i,
|
||||
.string_literal => result.lib_name = i,
|
||||
else => break,
|
||||
@ -2123,7 +2127,7 @@ pub const full = struct {
|
||||
|
||||
pub const FnProto = struct {
|
||||
visib_token: ?TokenIndex,
|
||||
extern_export_token: ?TokenIndex,
|
||||
extern_export_inline_token: ?TokenIndex,
|
||||
lib_name: ?TokenIndex,
|
||||
name_token: ?TokenIndex,
|
||||
lparen: TokenIndex,
|
||||
|
||||
@ -995,7 +995,7 @@ fn fnProtoExpr(
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const is_extern = blk: {
|
||||
const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
|
||||
const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
|
||||
break :blk token_tags[maybe_extern_token] == .keyword_extern;
|
||||
};
|
||||
assert(!is_extern);
|
||||
@ -2735,15 +2735,20 @@ fn fnDecl(
|
||||
};
|
||||
defer decl_gz.instructions.deinit(gpa);
|
||||
|
||||
// TODO: support noinline
|
||||
const is_pub = fn_proto.visib_token != null;
|
||||
const is_export = blk: {
|
||||
const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;
|
||||
const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
|
||||
break :blk token_tags[maybe_export_token] == .keyword_export;
|
||||
};
|
||||
const is_extern = blk: {
|
||||
const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
|
||||
const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
|
||||
break :blk token_tags[maybe_extern_token] == .keyword_extern;
|
||||
};
|
||||
const has_inline_keyword = blk: {
|
||||
const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
|
||||
break :blk token_tags[maybe_inline_token] == .keyword_inline;
|
||||
};
|
||||
const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
|
||||
break :inst try expr(&decl_gz, &decl_gz.base, align_rl, fn_proto.ast.align_expr);
|
||||
};
|
||||
@ -2812,17 +2817,30 @@ fn fnDecl(
|
||||
fn_proto.ast.return_type,
|
||||
);
|
||||
|
||||
const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
|
||||
try AstGen.expr(
|
||||
&decl_gz,
|
||||
&decl_gz.base,
|
||||
.{ .ty = .calling_convention_type },
|
||||
fn_proto.ast.callconv_expr,
|
||||
)
|
||||
else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269
|
||||
Zir.Inst.Ref.calling_convention_c
|
||||
else
|
||||
Zir.Inst.Ref.none;
|
||||
const cc: Zir.Inst.Ref = blk: {
|
||||
if (fn_proto.ast.callconv_expr != 0) {
|
||||
if (has_inline_keyword) {
|
||||
return astgen.failNode(
|
||||
fn_proto.ast.callconv_expr,
|
||||
"explicit callconv incompatible with inline keyword",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
break :blk try AstGen.expr(
|
||||
&decl_gz,
|
||||
&decl_gz.base,
|
||||
.{ .ty = .calling_convention_type },
|
||||
fn_proto.ast.callconv_expr,
|
||||
);
|
||||
} else if (is_extern) {
|
||||
// note: https://github.com/ziglang/zig/issues/5269
|
||||
break :blk .calling_convention_c;
|
||||
} else if (has_inline_keyword) {
|
||||
break :blk .calling_convention_inline;
|
||||
} else {
|
||||
break :blk .none;
|
||||
}
|
||||
};
|
||||
|
||||
const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
|
||||
if (!is_extern) {
|
||||
|
||||
13
src/Zir.zig
13
src/Zir.zig
@ -1687,6 +1687,8 @@ pub const Inst = struct {
|
||||
one_usize,
|
||||
/// `std.builtin.CallingConvention.C`
|
||||
calling_convention_c,
|
||||
/// `std.builtin.CallingConvention.Inline`
|
||||
calling_convention_inline,
|
||||
|
||||
_,
|
||||
|
||||
@ -1954,6 +1956,10 @@ pub const Inst = struct {
|
||||
.ty = Type.initTag(.calling_convention),
|
||||
.val = .{ .ptr_otherwise = &calling_convention_c_payload.base },
|
||||
},
|
||||
.calling_convention_inline = .{
|
||||
.ty = Type.initTag(.calling_convention),
|
||||
.val = .{ .ptr_otherwise = &calling_convention_inline_payload.base },
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -1964,6 +1970,13 @@ pub const Inst = struct {
|
||||
.data = @enumToInt(std.builtin.CallingConvention.C),
|
||||
};
|
||||
|
||||
/// We would like this to be const but `Value` wants a mutable pointer for
|
||||
/// its payload field. Nothing should mutate this though.
|
||||
var calling_convention_inline_payload: Value.Payload.U32 = .{
|
||||
.base = .{ .tag = .enum_field_index },
|
||||
.data = @enumToInt(std.builtin.CallingConvention.Inline),
|
||||
};
|
||||
|
||||
/// All instructions have an 8-byte payload, which is contained within
|
||||
/// this union. `Tag` determines which union field is active, as well as
|
||||
/// how to interpret the data within.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user