mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
AstGen: implement functions with inferred error sets
This commit also reclaims +2 ZIR instruction tags by moving the following to `extended`: * func_var_args * func_extra * func_extra_var_args The following ZIR instruction tag is added: * func_inferred
This commit is contained in:
parent
22015c1b3b
commit
2083208f19
24
BRANCH_TODO
24
BRANCH_TODO
@ -737,3 +737,27 @@ fn errorSetDecl(
|
||||
try mod.analyzeExport(&decl_scope.base, export_src, name, decl);
|
||||
}
|
||||
}
|
||||
|
||||
fn writeFuncExtra(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
var_args: bool,
|
||||
) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const extra = self.code.extraData(Inst.FuncExtra, inst_data.payload_index);
|
||||
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
const cc = extra.data.cc;
|
||||
const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
|
||||
return self.writeFuncCommon(
|
||||
stream,
|
||||
param_types,
|
||||
extra.data.return_type,
|
||||
var_args,
|
||||
cc,
|
||||
body,
|
||||
src,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1375,9 +1375,7 @@ fn blockExprStmts(
|
||||
.field_ptr_named,
|
||||
.field_val_named,
|
||||
.func,
|
||||
.func_var_args,
|
||||
.func_extra,
|
||||
.func_extra_var_args,
|
||||
.func_inferred,
|
||||
.int,
|
||||
.float,
|
||||
.float128,
|
||||
@ -2129,9 +2127,8 @@ fn fnDecl(
|
||||
}
|
||||
|
||||
const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
|
||||
if (token_tags[maybe_bang] == .bang) {
|
||||
return astgen.failTok(maybe_bang, "TODO implement inferred error sets", .{});
|
||||
}
|
||||
const is_inferred_error = token_tags[maybe_bang] == .bang;
|
||||
|
||||
const return_type_inst = try AstGen.expr(
|
||||
&decl_gz,
|
||||
&decl_gz.base,
|
||||
@ -2153,31 +2150,24 @@ fn fnDecl(
|
||||
|
||||
const func_inst: Zir.Inst.Ref = if (body_node == 0) func: {
|
||||
if (is_extern) {
|
||||
return astgen.failNode(fn_proto.ast.fn_token, "non-extern function has no body", .{});
|
||||
return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
|
||||
}
|
||||
|
||||
if (cc != .none or lib_name != 0) {
|
||||
const tag: Zir.Inst.Tag = if (is_var_args) .func_extra_var_args else .func_extra;
|
||||
break :func try decl_gz.addFuncExtra(tag, .{
|
||||
.src_node = fn_proto.ast.proto_node,
|
||||
.ret_ty = return_type_inst,
|
||||
.param_types = param_types,
|
||||
.cc = cc,
|
||||
.lib_name = lib_name,
|
||||
.body = &[0]Zir.Inst.Index{},
|
||||
});
|
||||
if (is_inferred_error) {
|
||||
return astgen.failTok(maybe_bang, "function prototype requires explicit error set", .{});
|
||||
}
|
||||
|
||||
const tag: Zir.Inst.Tag = if (is_var_args) .func_var_args else .func;
|
||||
break :func try decl_gz.addFunc(tag, .{
|
||||
break :func try decl_gz.addFunc(.{
|
||||
.src_node = fn_proto.ast.proto_node,
|
||||
.ret_ty = return_type_inst,
|
||||
.param_types = param_types,
|
||||
.body = &[0]Zir.Inst.Index{},
|
||||
.cc = cc,
|
||||
.lib_name = lib_name,
|
||||
.is_var_args = is_var_args,
|
||||
.is_inferred_error = false,
|
||||
});
|
||||
} else func: {
|
||||
if (is_var_args) {
|
||||
return astgen.failNode(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
|
||||
return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{});
|
||||
}
|
||||
|
||||
var fn_gz: Scope.GenZir = .{
|
||||
@ -2224,30 +2214,20 @@ fn fnDecl(
|
||||
if (fn_gz.instructions.items.len == 0 or
|
||||
!astgen.instructions.items(.tag)[fn_gz.instructions.items.len - 1].isNoReturn())
|
||||
{
|
||||
// astgen uses result location semantics to coerce return operands.
|
||||
// Since we are adding the return instruction here, we must handle the coercion.
|
||||
// We do this by using the `ret_coerce` instruction.
|
||||
_ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
|
||||
}
|
||||
|
||||
if (cc != .none or lib_name != 0) {
|
||||
const tag: Zir.Inst.Tag = if (is_var_args) .func_extra_var_args else .func_extra;
|
||||
break :func try decl_gz.addFuncExtra(tag, .{
|
||||
.src_node = fn_proto.ast.proto_node,
|
||||
.ret_ty = return_type_inst,
|
||||
.param_types = param_types,
|
||||
.cc = cc,
|
||||
.lib_name = lib_name,
|
||||
.body = fn_gz.instructions.items,
|
||||
});
|
||||
}
|
||||
|
||||
const tag: Zir.Inst.Tag = if (is_var_args) .func_var_args else .func;
|
||||
break :func try decl_gz.addFunc(tag, .{
|
||||
break :func try decl_gz.addFunc(.{
|
||||
.src_node = fn_proto.ast.proto_node,
|
||||
.ret_ty = return_type_inst,
|
||||
.param_types = param_types,
|
||||
.body = fn_gz.instructions.items,
|
||||
.cc = cc,
|
||||
.lib_name = lib_name,
|
||||
.is_var_args = is_var_args,
|
||||
.is_inferred_error = is_inferred_error,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
129
src/Module.zig
129
src/Module.zig
@ -1278,79 +1278,90 @@ pub const Scope = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addFuncExtra(gz: *GenZir, tag: Zir.Inst.Tag, args: struct {
|
||||
pub fn addFunc(gz: *GenZir, args: struct {
|
||||
src_node: ast.Node.Index,
|
||||
param_types: []const Zir.Inst.Ref,
|
||||
body: []const Zir.Inst.Index,
|
||||
ret_ty: Zir.Inst.Ref,
|
||||
cc: Zir.Inst.Ref,
|
||||
body: []const Zir.Inst.Index,
|
||||
lib_name: u32,
|
||||
is_var_args: bool,
|
||||
is_inferred_error: bool,
|
||||
}) !Zir.Inst.Ref {
|
||||
assert(args.src_node != 0);
|
||||
assert(args.ret_ty != .none);
|
||||
assert(args.cc != .none);
|
||||
const gpa = gz.astgen.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
|
||||
try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
|
||||
@typeInfo(Zir.Inst.FuncExtra).Struct.fields.len + args.param_types.len +
|
||||
args.body.len);
|
||||
const astgen = gz.astgen;
|
||||
const gpa = astgen.gpa;
|
||||
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.FuncExtra{
|
||||
.return_type = args.ret_ty,
|
||||
.cc = args.cc,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
.body_len = @intCast(u32, args.body.len),
|
||||
.lib_name = args.lib_name,
|
||||
});
|
||||
gz.astgen.appendRefsAssumeCapacity(args.param_types);
|
||||
gz.astgen.extra.appendSliceAssumeCapacity(args.body);
|
||||
try gz.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
|
||||
gz.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
if (args.cc != .none or args.lib_name != 0 or args.is_var_args) {
|
||||
try astgen.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
|
||||
args.param_types.len + args.body.len +
|
||||
@boolToInt(args.lib_name != 0) +
|
||||
@boolToInt(args.cc != .none),
|
||||
);
|
||||
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
|
||||
.src_node = gz.nodeIndexToRelative(args.src_node),
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
}
|
||||
.return_type = args.ret_ty,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
.body_len = @intCast(u32, args.body.len),
|
||||
});
|
||||
if (args.cc != .none) {
|
||||
astgen.extra.appendAssumeCapacity(@enumToInt(args.cc));
|
||||
}
|
||||
if (args.lib_name != 0) {
|
||||
astgen.extra.appendAssumeCapacity(args.lib_name);
|
||||
}
|
||||
astgen.appendRefsAssumeCapacity(args.param_types);
|
||||
astgen.extra.appendSliceAssumeCapacity(args.body);
|
||||
|
||||
pub fn addFunc(gz: *GenZir, tag: Zir.Inst.Tag, args: struct {
|
||||
src_node: ast.Node.Index,
|
||||
ret_ty: Zir.Inst.Ref,
|
||||
param_types: []const Zir.Inst.Ref,
|
||||
body: []const Zir.Inst.Index,
|
||||
}) !Zir.Inst.Ref {
|
||||
assert(args.src_node != 0);
|
||||
assert(args.ret_ty != .none);
|
||||
const gpa = gz.astgen.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
|
||||
try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
|
||||
@typeInfo(Zir.Inst.Func).Struct.fields.len + args.param_types.len +
|
||||
args.body.len);
|
||||
const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
|
||||
astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = .extended,
|
||||
.data = .{ .extended = .{
|
||||
.opcode = .func,
|
||||
.small = @bitCast(u16, Zir.Inst.ExtendedFunc.Small{
|
||||
.is_var_args = args.is_var_args,
|
||||
.is_inferred_error = args.is_inferred_error,
|
||||
.has_lib_name = args.lib_name != 0,
|
||||
.has_cc = args.cc != .none,
|
||||
}),
|
||||
.operand = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
} else {
|
||||
try gz.astgen.extra.ensureUnusedCapacity(
|
||||
gpa,
|
||||
@typeInfo(Zir.Inst.Func).Struct.fields.len +
|
||||
args.param_types.len + args.body.len,
|
||||
);
|
||||
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
|
||||
.return_type = args.ret_ty,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
.body_len = @intCast(u32, args.body.len),
|
||||
});
|
||||
gz.astgen.appendRefsAssumeCapacity(args.param_types);
|
||||
gz.astgen.extra.appendSliceAssumeCapacity(args.body);
|
||||
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
|
||||
.return_type = args.ret_ty,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
.body_len = @intCast(u32, args.body.len),
|
||||
});
|
||||
gz.astgen.appendRefsAssumeCapacity(args.param_types);
|
||||
gz.astgen.extra.appendSliceAssumeCapacity(args.body);
|
||||
|
||||
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
|
||||
gz.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
.src_node = gz.nodeIndexToRelative(args.src_node),
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
|
||||
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
|
||||
gz.astgen.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
.src_node = gz.nodeIndexToRelative(args.src_node),
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return gz.indexToRef(new_index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addCall(
|
||||
|
||||
107
src/Sema.zig
107
src/Sema.zig
@ -194,9 +194,7 @@ pub fn analyzeBody(
|
||||
.field_val => try sema.zirFieldVal(block, inst),
|
||||
.field_val_named => try sema.zirFieldValNamed(block, inst),
|
||||
.func => try sema.zirFunc(block, inst, false),
|
||||
.func_extra => try sema.zirFuncExtra(block, inst, false),
|
||||
.func_extra_var_args => try sema.zirFuncExtra(block, inst, true),
|
||||
.func_var_args => try sema.zirFunc(block, inst, true),
|
||||
.func_inferred => try sema.zirFunc(block, inst, true),
|
||||
.import => try sema.zirImport(block, inst),
|
||||
.indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
|
||||
.int => try sema.zirInt(block, inst),
|
||||
@ -2646,7 +2644,12 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
|
||||
}
|
||||
}
|
||||
|
||||
fn zirFunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: bool) InnerError!*Inst {
|
||||
fn zirFunc(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
inst: Zir.Inst.Index,
|
||||
inferred_error_set: bool,
|
||||
) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -2654,40 +2657,17 @@ fn zirFunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: boo
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
|
||||
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
const body = sema.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
|
||||
|
||||
return sema.funcCommon(
|
||||
block,
|
||||
inst_data.src_node,
|
||||
param_types,
|
||||
body,
|
||||
extra.data.return_type,
|
||||
.Unspecified,
|
||||
var_args,
|
||||
);
|
||||
}
|
||||
|
||||
fn zirFuncExtra(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, var_args: bool) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
|
||||
const extra = sema.code.extraData(Zir.Inst.FuncExtra, inst_data.payload_index);
|
||||
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
|
||||
const cc_tv = try sema.resolveInstConst(block, cc_src, extra.data.cc);
|
||||
// TODO once we're capable of importing and analyzing decls from
|
||||
// std.builtin, this needs to change
|
||||
const cc_str = cc_tv.val.castTag(.enum_literal).?.data;
|
||||
const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse
|
||||
return sema.mod.fail(&block.base, cc_src, "Unknown calling convention {s}", .{cc_str});
|
||||
return sema.funcCommon(
|
||||
block,
|
||||
inst_data.src_node,
|
||||
param_types,
|
||||
extra.data.return_type,
|
||||
cc,
|
||||
var_args,
|
||||
false,
|
||||
inferred_error_set,
|
||||
);
|
||||
}
|
||||
|
||||
@ -2696,9 +2676,11 @@ fn funcCommon(
|
||||
block: *Scope.Block,
|
||||
src_node_offset: i32,
|
||||
zir_param_types: []const Zir.Inst.Ref,
|
||||
body: []const Zir.Inst.Index,
|
||||
zir_return_type: Zir.Inst.Ref,
|
||||
cc: std.builtin.CallingConvention,
|
||||
var_args: bool,
|
||||
inferred_error_set: bool,
|
||||
) InnerError!*Inst {
|
||||
const src: LazySrcLoc = .{ .node_offset = src_node_offset };
|
||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
|
||||
@ -5307,15 +5289,68 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
|
||||
const extended = sema.code.instructions.items(.data)[inst].extended;
|
||||
switch (extended.opcode) {
|
||||
// zig fmt: off
|
||||
.c_undef => return sema.zirCUndef( block, inst, extended),
|
||||
.c_include => return sema.zirCInclude( block, inst, extended),
|
||||
.c_define => return sema.zirCDefine( block, inst, extended),
|
||||
.wasm_memory_size => return sema.zirWasmMemorySize( block, inst, extended),
|
||||
.wasm_memory_grow => return sema.zirWasmMemoryGrow( block, inst, extended),
|
||||
.func => return sema.zirFuncExtended( block, inst, extended),
|
||||
.c_undef => return sema.zirCUndef( block, inst, extended),
|
||||
.c_include => return sema.zirCInclude( block, inst, extended),
|
||||
.c_define => return sema.zirCDefine( block, inst, extended),
|
||||
.wasm_memory_size => return sema.zirWasmMemorySize(block, inst, extended),
|
||||
.wasm_memory_grow => return sema.zirWasmMemoryGrow(block, inst, extended),
|
||||
// zig fmt: on
|
||||
}
|
||||
}
|
||||
|
||||
fn zirFuncExtended(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
inst: Zir.Inst.Index,
|
||||
extended: Zir.Inst.Extended.InstData,
|
||||
) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
|
||||
const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
|
||||
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = extra.data.src_node };
|
||||
const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
|
||||
|
||||
var extra_index: usize = extra.end;
|
||||
if (small.has_lib_name) {
|
||||
const lib_name = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{});
|
||||
}
|
||||
const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {
|
||||
const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
|
||||
// TODO this needs to resolve other kinds of Value tags rather than
|
||||
// assuming the tag will be .enum_field_index.
|
||||
const cc_field_index = cc_tv.val.castTag(.enum_field_index).?.data;
|
||||
// TODO should `@intToEnum` do this `@intCast` for you?
|
||||
const cc = @intToEnum(
|
||||
std.builtin.CallingConvention,
|
||||
@intCast(@typeInfo(std.builtin.CallingConvention).Enum.tag_type, cc_field_index),
|
||||
);
|
||||
break :blk cc;
|
||||
} else .Unspecified;
|
||||
|
||||
const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
|
||||
extra_index += 1;
|
||||
|
||||
const body = sema.code.extra[extra_index..][0..extra.data.body_len];
|
||||
|
||||
return sema.funcCommon(
|
||||
block,
|
||||
extra.data.src_node,
|
||||
param_types,
|
||||
body,
|
||||
extra.data.return_type,
|
||||
cc,
|
||||
small.is_var_args,
|
||||
small.is_inferred_error,
|
||||
);
|
||||
}
|
||||
|
||||
fn zirCUndef(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
|
||||
76
src/Zir.zig
76
src/Zir.zig
@ -371,15 +371,8 @@ pub const Inst = struct {
|
||||
/// the body_len is 0. Calling convention is auto.
|
||||
/// Uses the `pl_node` union field. `payload_index` points to a `Func`.
|
||||
func,
|
||||
/// Same as `func` but the function is variadic.
|
||||
func_var_args,
|
||||
/// Same as `func` but with extra fields:
|
||||
/// * calling convention
|
||||
/// * extern lib name
|
||||
/// Uses the `pl_node` union field. `payload_index` points to a `FuncExtra`.
|
||||
func_extra,
|
||||
/// Same as `func_extra` but the function is variadic.
|
||||
func_extra_var_args,
|
||||
/// Same as `func` but has an inferred error set.
|
||||
func_inferred,
|
||||
/// Implements the `@import` builtin.
|
||||
/// Uses the `str_tok` field.
|
||||
import,
|
||||
@ -1010,9 +1003,7 @@ pub const Inst = struct {
|
||||
.field_ptr_named,
|
||||
.field_val_named,
|
||||
.func,
|
||||
.func_var_args,
|
||||
.func_extra,
|
||||
.func_extra_var_args,
|
||||
.func_inferred,
|
||||
.has_decl,
|
||||
.int,
|
||||
.float,
|
||||
@ -1211,6 +1202,11 @@ pub const Inst = struct {
|
||||
/// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
|
||||
/// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
|
||||
pub const Extended = enum(u16) {
|
||||
/// Represents a function declaration or function prototype, depending on
|
||||
/// whether body_len is 0.
|
||||
/// `operand` is payload index to `ExtendedFunc`.
|
||||
/// `small` is `ExtendedFunc.Small`.
|
||||
func,
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
c_undef,
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
@ -1774,15 +1770,23 @@ pub const Inst = struct {
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. param_type: Ref // for each param_types_len
|
||||
/// 1. body: Index // for each body_len
|
||||
pub const FuncExtra = struct {
|
||||
cc: Ref,
|
||||
/// null terminated string index, or 0 to mean none.
|
||||
lib_name: u32,
|
||||
/// 0. lib_name: u32, // null terminated string index, if has_lib_name is set
|
||||
/// 1. cc: Ref, // if has_cc is set
|
||||
/// 2. param_type: Ref // for each param_types_len
|
||||
/// 3. body: Index // for each body_len
|
||||
pub const ExtendedFunc = struct {
|
||||
src_node: i32,
|
||||
return_type: Ref,
|
||||
param_types_len: u32,
|
||||
body_len: u32,
|
||||
|
||||
pub const Small = packed struct {
|
||||
is_var_args: bool,
|
||||
is_inferred_error: bool,
|
||||
has_lib_name: bool,
|
||||
has_cc: bool,
|
||||
_: u12 = undefined,
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
@ -2459,9 +2463,7 @@ const Writer = struct {
|
||||
=> try self.writeStrTok(stream, inst),
|
||||
|
||||
.func => try self.writeFunc(stream, inst, false),
|
||||
.func_extra => try self.writeFuncExtra(stream, inst, false),
|
||||
.func_var_args => try self.writeFunc(stream, inst, true),
|
||||
.func_extra_var_args => try self.writeFuncExtra(stream, inst, true),
|
||||
.func_inferred => try self.writeFunc(stream, inst, true),
|
||||
|
||||
.@"unreachable" => try self.writeUnreachable(stream, inst),
|
||||
|
||||
@ -3099,7 +3101,7 @@ const Writer = struct {
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
var_args: bool,
|
||||
inferred_error_set: bool,
|
||||
) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
@ -3110,36 +3112,14 @@ const Writer = struct {
|
||||
stream,
|
||||
param_types,
|
||||
extra.data.return_type,
|
||||
var_args,
|
||||
inferred_error_set,
|
||||
false,
|
||||
.none,
|
||||
body,
|
||||
src,
|
||||
);
|
||||
}
|
||||
|
||||
fn writeFuncExtra(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
var_args: bool,
|
||||
) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const extra = self.code.extraData(Inst.FuncExtra, inst_data.payload_index);
|
||||
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
const cc = extra.data.cc;
|
||||
const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
|
||||
return self.writeFuncCommon(
|
||||
stream,
|
||||
param_types,
|
||||
extra.data.return_type,
|
||||
var_args,
|
||||
cc,
|
||||
body,
|
||||
src,
|
||||
);
|
||||
}
|
||||
|
||||
fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].bool_br;
|
||||
const extra = self.code.extraData(Inst.Block, inst_data.payload_index);
|
||||
@ -3184,6 +3164,7 @@ const Writer = struct {
|
||||
stream: anytype,
|
||||
param_types: []const Inst.Ref,
|
||||
ret_ty: Inst.Ref,
|
||||
inferred_error_set: bool,
|
||||
var_args: bool,
|
||||
cc: Inst.Ref,
|
||||
body: []const Inst.Index,
|
||||
@ -3197,7 +3178,8 @@ const Writer = struct {
|
||||
try stream.writeAll("], ");
|
||||
try self.writeInstRef(stream, ret_ty);
|
||||
try self.writeOptionalInstRef(stream, ", cc=", cc);
|
||||
try self.writeFlag(stream, ", var_args", var_args);
|
||||
try self.writeFlag(stream, ", vargs", var_args);
|
||||
try self.writeFlag(stream, ", inferror", inferred_error_set);
|
||||
|
||||
try stream.writeAll(", {\n");
|
||||
self.indent += 2;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user