Zir: turn extended func into func_extended

This commit is contained in:
Veikka Tuominen
2022-04-29 12:23:46 +03:00
parent 1d455896cb
commit 596f7df02e
5 changed files with 75 additions and 80 deletions

View File

@@ -72,6 +72,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
i32 => @bitCast(u32, @field(extra, field.name)),
Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)),
Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
Zir.Inst.ExtendedFunc.Bits => @bitCast(u32, @field(extra, field.name)),
else => @compileError("bad field type"),
};
i += 1;
@@ -2245,6 +2246,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.field_val_named,
.func,
.func_inferred,
.func_extended,
.int,
.int_big,
.float,
@@ -10023,10 +10025,18 @@ const GenZir = struct {
@boolToInt(args.cc != .none),
);
const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{
.src_node = gz.nodeIndexToRelative(args.src_node),
.param_block = args.param_block,
.ret_body_len = @intCast(u32, ret_ty.len),
.body_len = @intCast(u32, body.len),
.bits = .{
.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,
.has_align = args.align_inst != .none,
.is_test = args.is_test,
.is_extern = args.is_extern,
},
});
if (args.lib_name != 0) {
astgen.extra.appendAssumeCapacity(args.lib_name);
@@ -10050,19 +10060,10 @@ const GenZir = struct {
astgen.instructions.items(.data)[args.ret_br].@"break".block_inst = new_index;
}
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,
.has_align = args.align_inst != .none,
.is_test = args.is_test,
.is_extern = args.is_extern,
}),
.operand = payload_index,
.tag = .func_extended,
.data = .{ .pl_node = .{
.src_node = gz.nodeIndexToRelative(args.src_node),
.payload_index = payload_index,
} },
});
gz.instructions.appendAssumeCapacity(new_index);

View File

@@ -1532,10 +1532,10 @@ pub const Fn = struct {
switch (zir_tags[func.zir_body_inst]) {
.func => return false,
.func_inferred => return true,
.extended => {
const extended = zir.instructions.items(.data)[func.zir_body_inst].extended;
const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
return small.is_inferred_error;
.func_extended => {
const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
const extra = zir.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
return extra.data.bits.is_inferred_error;
},
else => unreachable,
}

View File

@@ -745,6 +745,7 @@ fn analyzeBodyInner(
.field_call_bind => try sema.zirFieldCallBind(block, inst),
.func => try sema.zirFunc(block, inst, false),
.func_inferred => try sema.zirFunc(block, inst, true),
.func_extended => try sema.zirFuncExtended(block, inst),
.import => try sema.zirImport(block, inst),
.indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
.int => try sema.zirInt(block, inst),
@@ -911,7 +912,6 @@ fn analyzeBodyInner(
const extended = datas[inst].extended;
break :ext switch (extended.opcode) {
// zig fmt: off
.func => try sema.zirFuncExtended( block, extended, inst),
.variable => try sema.zirVarExtended( block, extended),
.struct_decl => try sema.zirStructDecl( block, extended, inst),
.enum_decl => try sema.zirEnumDecl( block, extended),
@@ -16099,37 +16099,33 @@ fn zirVarExtended(
return result;
}
fn zirFuncExtended(
sema: *Sema,
block: *Block,
extended: Zir.Inst.Extended.InstData,
inst: Zir.Inst.Index,
) CompileError!Air.Inst.Ref {
fn zirFuncExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
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 inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
const align_src: LazySrcLoc = src; // TODO add a LazySrcLoc that points at align
const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
var extra_index: usize = extra.end;
const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
const lib_name: ?[]const u8 = if (extra.data.bits.has_lib_name) blk: {
const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
extra_index += 1;
break :blk lib_name;
} else null;
const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {
const cc: std.builtin.CallingConvention = if (extra.data.bits.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);
break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
} else .Unspecified;
const align_val: Value = if (small.has_align) blk: {
const align_val: Value = if (extra.data.bits.has_align) blk: {
const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
@@ -16146,13 +16142,13 @@ fn zirFuncExtended(
src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
}
const is_var_args = small.is_var_args;
const is_inferred_error = small.is_inferred_error;
const is_extern = small.is_extern;
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;
return sema.funcCommon(
block,
extra.data.src_node,
inst_data.src_node,
inst,
ret_ty_body,
cc,

View File

@@ -73,6 +73,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
i32 => @bitCast(i32, code.extra[i]),
Inst.Call.Flags => @bitCast(Inst.Call.Flags, code.extra[i]),
Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),
Inst.ExtendedFunc.Bits => @bitCast(Inst.ExtendedFunc.Bits, code.extra[i]),
else => @compileError("bad field type"),
};
i += 1;
@@ -415,6 +416,10 @@ pub const Inst = struct {
func,
/// Same as `func` but has an inferred error set.
func_inferred,
/// Represents a function declaration or function prototype, depending on
/// whether body_len is 0.
/// Uses the `pl_node` union field. `payload_index` points to a `ExtendedFunc`.
func_extended,
/// Implements the `@import` builtin.
/// Uses the `str_tok` field.
import,
@@ -1062,6 +1067,7 @@ pub const Inst = struct {
.field_val_named,
.func,
.func_inferred,
.func_extended,
.has_decl,
.int,
.int_big,
@@ -1347,6 +1353,7 @@ pub const Inst = struct {
.field_val_named,
.func,
.func_inferred,
.func_extended,
.has_decl,
.int,
.int_big,
@@ -1601,6 +1608,7 @@ pub const Inst = struct {
.field_call_bind = .pl_node,
.func = .pl_node,
.func_inferred = .pl_node,
.func_extended = .pl_node,
.import = .str_tok,
.int = .int,
.int_big = .str,
@@ -1802,11 +1810,6 @@ 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,
/// Declares a global variable.
/// `operand` is payload index to `ExtendedVar`.
/// `small` is `ExtendedVar.Small`.
@@ -2621,14 +2624,14 @@ pub const Inst = struct {
/// 4. body: Index // for each body_len
/// 5. src_locs: Func.SrcLocs // if body_len != 0
pub const ExtendedFunc = struct {
src_node: i32,
/// If this is 0 it means a void return type.
ret_body_len: u32,
/// Points to the block that contains the param instructions for this function.
param_block: Index,
body_len: u32,
bits: Bits,
pub const Small = packed struct {
pub const Bits = packed struct {
is_var_args: bool,
is_inferred_error: bool,
has_lib_name: bool,
@@ -2636,7 +2639,7 @@ pub const Inst = struct {
has_align: bool,
is_test: bool,
is_extern: bool,
_: u9 = undefined,
_: u25 = undefined,
};
};
@@ -3460,14 +3463,11 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
switch (tags[decl_inst]) {
// Functions are allowed and yield no iterations.
// There is one case matching this in the extended instruction set below.
.func,
.func_inferred,
=> return declIteratorInner(zir, 0, 0),
.func, .func_inferred, .func_extended => return declIteratorInner(zir, 0, 0),
.extended => {
const extended = datas[decl_inst].extended;
switch (extended.opcode) {
.func => return declIteratorInner(zir, 0, 0),
.struct_decl => {
const small = @bitCast(Inst.StructDecl.Small, extended.small);
var extra_index: usize = extended.operand;
@@ -3572,21 +3572,21 @@ fn findDeclsInner(
const body = zir.extra[extra.end..][0..extra.data.body_len];
return zir.findDeclsBody(list, body);
},
.func_extended => {
try list.append(inst);
const inst_data = datas[inst].pl_node;
const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);
var extra_index: usize = extra.end;
extra_index += @boolToInt(extra.data.bits.has_lib_name);
extra_index += @boolToInt(extra.data.bits.has_cc);
extra_index += @boolToInt(extra.data.bits.has_align);
const body = zir.extra[extra_index..][0..extra.data.body_len];
return zir.findDeclsBody(list, body);
},
.extended => {
const extended = datas[inst].extended;
switch (extended.opcode) {
.func => {
try list.append(inst);
const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
var extra_index: usize = extra.end;
extra_index += @boolToInt(small.has_lib_name);
extra_index += @boolToInt(small.has_cc);
extra_index += @boolToInt(small.has_align);
const body = zir.extra[extra_index..][0..extra.data.body_len];
return zir.findDeclsBody(list, body);
},
// Decl instructions are interesting but have no body.
// TODO yes they do have a body actually. recurse over them just like block instructions.
@@ -3733,15 +3733,13 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
.body = body,
};
},
.extended => blk: {
const extended = datas[fn_inst].extended;
assert(extended.opcode == .func);
const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
.func_extended => blk: {
const inst_data = datas[fn_inst].pl_node;
const extra = zir.extraData(Inst.ExtendedFunc, inst_data.payload_index);
var extra_index: usize = extra.end;
extra_index += @boolToInt(small.has_lib_name);
extra_index += @boolToInt(small.has_cc);
extra_index += @boolToInt(small.has_align);
extra_index += @boolToInt(extra.data.bits.has_lib_name);
extra_index += @boolToInt(extra.data.bits.has_cc);
extra_index += @boolToInt(extra.data.bits.has_align);
const ret_ty_body = zir.extra[extra_index..][0..extra.data.ret_body_len];
extra_index += ret_ty_body.len;
const body = zir.extra[extra_index..][0..extra.data.body_len];

View File

@@ -429,6 +429,7 @@ const Writer = struct {
.func => try self.writeFunc(stream, inst, false),
.func_inferred => try self.writeFunc(stream, inst, true),
.func_extended => try self.writeFuncExtended(stream, inst),
.@"unreachable" => try self.writeUnreachable(stream, inst),
@@ -469,7 +470,6 @@ const Writer = struct {
},
.@"asm" => try self.writeAsm(stream, extended),
.func => try self.writeFuncExtended(stream, extended),
.variable => try self.writeVarExtended(stream, extended),
.alloc => try self.writeAllocExtended(stream, extended),
@@ -1920,24 +1920,24 @@ const Writer = struct {
);
}
fn writeFuncExtended(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
const extra = self.code.extraData(Zir.Inst.ExtendedFunc, extended.operand);
const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
fn writeFuncExtended(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const extra = self.code.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
const src = inst_data.src();
var extra_index: usize = extra.end;
if (small.has_lib_name) {
if (extra.data.bits.has_lib_name) {
const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
extra_index += 1;
try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)});
}
try self.writeFlag(stream, "test, ", small.is_test);
const cc: Zir.Inst.Ref = if (!small.has_cc) .none else blk: {
try self.writeFlag(stream, "test, ", extra.data.bits.is_test);
const cc: Zir.Inst.Ref = if (!extra.data.bits.has_cc) .none else blk: {
const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
extra_index += 1;
break :blk cc;
};
const align_inst: Zir.Inst.Ref = if (!small.has_align) .none else blk: {
const align_inst: Zir.Inst.Ref = if (!extra.data.bits.has_align) .none else blk: {
const align_inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
extra_index += 1;
break :blk align_inst;
@@ -1956,9 +1956,9 @@ const Writer = struct {
return self.writeFuncCommon(
stream,
ret_ty_body,
small.is_inferred_error,
small.is_var_args,
small.is_extern,
extra.data.bits.is_inferred_error,
extra.data.bits.is_var_args,
extra.data.bits.is_extern,
cc,
align_inst,
body,