Commit c0a1b4fa46

Cody Tapscott <topolarity@tapscott.me>
2022-07-30 15:34:49
stage2: Fix AIR printing
Packed structs never have comptime fields, and a slice might actually be backed by a variable, which we need to catch before iterating its elements.
1 parent 8632e4f
Changed files (2)
src/TypedValue.zig
@@ -73,6 +73,9 @@ pub fn print(
     const target = mod.getTarget();
     var val = tv.val;
     var ty = tv.ty;
+    if (val.isVariable(mod))
+        return writer.writeAll("(variable)");
+
     while (true) switch (val.tag()) {
         .u1_type => return writer.writeAll("u1"),
         .u8_type => return writer.writeAll("u8"),
@@ -155,9 +158,12 @@ pub fn print(
                     }
                     try print(.{
                         .ty = ty.structFieldType(i),
-                        .val = ty.structFieldValueComptime(i) orelse b: {
-                            const vals = val.castTag(.aggregate).?.data;
-                            break :b vals[i];
+                        .val = switch (ty.containerLayout()) {
+                            .Packed => val.castTag(.aggregate).?.data[i],
+                            else => ty.structFieldValueComptime(i) orelse b: {
+                                const vals = val.castTag(.aggregate).?.data;
+                                break :b vals[i];
+                            },
                         },
                     }, writer, level - 1, mod);
                 }
@@ -241,7 +247,7 @@ pub fn print(
             mod.declPtr(val.castTag(.function).?.data.owner_decl).name,
         }),
         .extern_fn => return writer.writeAll("(extern function)"),
-        .variable => return writer.writeAll("(variable)"),
+        .variable => unreachable,
         .decl_ref_mut => {
             const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
             const decl = mod.declPtr(decl_index);
src/value.zig
@@ -2664,6 +2664,26 @@ pub const Value = extern union {
         }
     }
 
+    /// Returns true if a Value is backed by a variable
+    pub fn isVariable(
+        val: Value,
+        mod: *Module,
+    ) bool {
+        return switch (val.tag()) {
+            .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
+            .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
+            .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
+            .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
+            .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
+            .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
+            .decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isVariable(mod),
+            .decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isVariable(mod),
+
+            .variable => true,
+            else => false,
+        };
+    }
+
     // Asserts that the provided start/end are in-bounds.
     pub fn sliceArray(
         val: Value,