Commit 596f7df02e

Veikka Tuominen <git@vexu.eu>
2022-04-29 11:23:46
Zir: turn extended func into func_extended
1 parent 1d45589
src/AstGen.zig
@@ -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);
src/Module.zig
@@ -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,
         }
src/print_zir.zig
@@ -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,
src/Sema.zig
@@ -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,
src/Zir.zig
@@ -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];