Source
pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
const tags = zir.instructions.items(.tag);
const datas = zir.instructions.items(.data);
const info: struct {
param_block: Inst.Index,
body: []const Inst.Index,
ret_ty_ref: Inst.Ref,
ret_ty_body: []const Inst.Index,
ret_ty_is_generic: bool,
ies: bool,
} = switch (tags[@intFromEnum(fn_inst)]) {
.func, .func_inferred => |tag| blk: {
const inst_data = datas[@intFromEnum(fn_inst)].pl_node;
const extra = zir.extraData(Inst.Func, inst_data.payload_index);
var extra_index: usize = extra.end;
var ret_ty_ref: Inst.Ref = .none;
var ret_ty_body: []const Inst.Index = &.{};
switch (extra.data.ret_ty.body_len) {
0 => {
ret_ty_ref = .void_type;
},
1 => {
ret_ty_ref = @enumFromInt(zir.extra[extra_index]);
extra_index += 1;
},
else => {
ret_ty_body = zir.bodySlice(extra_index, extra.data.ret_ty.body_len);
extra_index += ret_ty_body.len;
},
}
const body = zir.bodySlice(extra_index, extra.data.body_len);
extra_index += body.len;
break :blk .{
.param_block = extra.data.param_block,
.ret_ty_ref = ret_ty_ref,
.ret_ty_body = ret_ty_body,
.body = body,
.ret_ty_is_generic = extra.data.ret_ty.is_generic,
.ies = tag == .func_inferred,
};
},
.func_fancy => blk: {
const inst_data = datas[@intFromEnum(fn_inst)].pl_node;
const extra = zir.extraData(Inst.FuncFancy, inst_data.payload_index);
var extra_index: usize = extra.end;
var ret_ty_ref: Inst.Ref = .none;
var ret_ty_body: []const Inst.Index = &.{};
if (extra.data.bits.has_cc_body) {
extra_index += zir.extra[extra_index] + 1;
} else if (extra.data.bits.has_cc_ref) {
extra_index += 1;
}
if (extra.data.bits.has_ret_ty_body) {
const body_len = zir.extra[extra_index];
extra_index += 1;
ret_ty_body = zir.bodySlice(extra_index, body_len);
extra_index += ret_ty_body.len;
} else if (extra.data.bits.has_ret_ty_ref) {
ret_ty_ref = @enumFromInt(zir.extra[extra_index]);
extra_index += 1;
} else {
ret_ty_ref = .void_type;
}
extra_index += @intFromBool(extra.data.bits.has_any_noalias);
const body = zir.bodySlice(extra_index, extra.data.body_len);
extra_index += body.len;
break :blk .{
.param_block = extra.data.param_block,
.ret_ty_ref = ret_ty_ref,
.ret_ty_body = ret_ty_body,
.body = body,
.ret_ty_is_generic = extra.data.bits.ret_ty_is_generic,
.ies = extra.data.bits.is_inferred_error,
};
},
else => unreachable,
};
const param_body = zir.getParamBody(fn_inst);
var total_params_len: u32 = 0;
for (param_body) |inst| {
switch (tags[@intFromEnum(inst)]) {
.param, .param_comptime, .param_anytype, .param_anytype_comptime => {
total_params_len += 1;
},
else => continue,
}
}
return .{
.param_body = param_body,
.param_body_inst = info.param_block,
.ret_ty_body = info.ret_ty_body,
.ret_ty_ref = info.ret_ty_ref,
.body = info.body,
.total_params_len = total_params_len,
.ret_ty_is_generic = info.ret_ty_is_generic,
.inferred_error_set = info.ies,
};
}