Commit 6f10b11658

Jacob Young <jacobly0@users.noreply.github.com>
2024-03-29 01:14:16
cbe: fix bugs revealed by an upcoming commit
Closes #18023
1 parent aff71c6
Changed files (5)
lib/zig.h
@@ -165,11 +165,14 @@ typedef char bool;
 #endif
 
 #if zig_has_attribute(section)
-#define zig_linksection(name, def, ...) def __attribute__((section(name)))
+#define zig_linksection(name) __attribute__((section(name)))
+#define zig_linksection_fn zig_linksection
 #elif _MSC_VER
-#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def
+#define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name))
+#define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name))
 #else
-#define zig_linksection(name, def, ...) zig_linksection_unavailable
+#define zig_linksection(name) zig_linksection_unavailable
+#define zig_linksection_fn zig_linksection
 #endif
 
 #if zig_has_builtin(unreachable) || defined(zig_gnuc)
src/codegen/c/type.zig
@@ -3,10 +3,10 @@ const mem = std.mem;
 const Allocator = mem.Allocator;
 const assert = std.debug.assert;
 const autoHash = std.hash.autoHash;
-const Target = std.Target;
 
 const Alignment = @import("../../InternPool.zig").Alignment;
-const Module = @import("../../Module.zig");
+const Zcu = @import("../../Module.zig");
+const Module = @import("../../Package/Module.zig");
 const InternPool = @import("../../InternPool.zig");
 const Type = @import("../../type.zig").Type;
 
@@ -280,7 +280,7 @@ pub const CType = extern union {
         };
     };
 
-    pub const AlignAs = struct {
+    pub const AlignAs = packed struct {
         @"align": Alignment,
         abi: Alignment,
 
@@ -298,19 +298,19 @@ pub const CType = extern union {
                 Alignment.fromNonzeroByteUnits(abi_alignment),
             );
         }
-        pub fn abiAlign(ty: Type, mod: *Module) AlignAs {
-            const abi_align = ty.abiAlignment(mod);
+        pub fn abiAlign(ty: Type, zcu: *Zcu) AlignAs {
+            const abi_align = ty.abiAlignment(zcu);
             return init(abi_align, abi_align);
         }
-        pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs {
+        pub fn fieldAlign(struct_ty: Type, field_i: usize, zcu: *Zcu) AlignAs {
             return init(
-                struct_ty.structFieldAlign(field_i, mod),
-                struct_ty.structFieldType(field_i, mod).abiAlignment(mod),
+                struct_ty.structFieldAlign(field_i, zcu),
+                struct_ty.structFieldType(field_i, zcu).abiAlignment(zcu),
             );
         }
-        pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {
-            const union_obj = mod.typeToUnion(union_ty).?;
-            const union_payload_align = mod.unionAbiAlignment(union_obj);
+        pub fn unionPayloadAlign(union_ty: Type, zcu: *Zcu) AlignAs {
+            const union_obj = zcu.typeToUnion(union_ty).?;
+            const union_payload_align = zcu.unionAbiAlignment(union_obj);
             return init(union_payload_align, union_payload_align);
         }
 
@@ -356,8 +356,8 @@ pub const CType = extern union {
                 return self.map.entries.items(.hash)[index - Tag.no_payload_count];
             }
 
-            pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index {
-                const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } };
+            pub fn typeToIndex(self: Set, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) ?Index {
+                const lookup = Convert.Lookup{ .imm = .{ .set = &self, .zcu = zcu, .mod = mod } };
 
                 var convert: Convert = undefined;
                 convert.initType(ty, kind, lookup) catch unreachable;
@@ -398,10 +398,11 @@ pub const CType = extern union {
             pub fn typeToIndex(
                 self: *Promoted,
                 ty: Type,
+                zcu: *Zcu,
                 mod: *Module,
                 kind: Kind,
             ) Allocator.Error!Index {
-                const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .mod = mod } };
+                const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .zcu = zcu, .mod = mod } };
 
                 var convert: Convert = undefined;
                 try convert.initType(ty, kind, lookup);
@@ -417,7 +418,7 @@ pub const CType = extern union {
                 );
                 if (!gop.found_existing) {
                     errdefer _ = self.set.map.pop();
-                    gop.key_ptr.* = try createFromConvert(self, ty, lookup.getModule(), kind, convert);
+                    gop.key_ptr.* = try createFromConvert(self, ty, zcu, mod, kind, convert);
                 }
                 if (std.debug.runtime_safety) {
                     const adapter = TypeAdapter64{
@@ -457,15 +458,15 @@ pub const CType = extern union {
             return promoted.cTypeToIndex(cty);
         }
 
-        pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !CType {
-            const idx = try self.typeToIndex(gpa, ty, mod, kind);
+        pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType {
+            const idx = try self.typeToIndex(gpa, ty, zcu, mod, kind);
             return self.indexToCType(idx);
         }
 
-        pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !Index {
+        pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !Index {
             var promoted = self.promote(gpa);
             defer self.demote(promoted);
-            return promoted.typeToIndex(ty, mod, kind);
+            return promoted.typeToIndex(ty, zcu, mod, kind);
         }
 
         pub fn clearRetainingCapacity(self: *Store, gpa: Allocator) void {
@@ -549,9 +550,9 @@ pub const CType = extern union {
         };
     }
 
-    pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness {
+    pub fn signedness(self: CType, mod: *Module) std.builtin.Signedness {
         return switch (self.tag()) {
-            .char => target.charSignedness(),
+            .char => mod.resolved_target.result.charSignedness(),
             .@"signed char",
             .short,
             .int,
@@ -854,7 +855,8 @@ pub const CType = extern union {
         }
     }
 
-    pub fn floatActiveBits(self: CType, target: Target) u16 {
+    pub fn floatActiveBits(self: CType, mod: *Module) u16 {
+        const target = &mod.resolved_target.result;
         return switch (self.tag()) {
             .float => target.c_type_bit_size(.float),
             .double => target.c_type_bit_size(.double),
@@ -868,7 +870,8 @@ pub const CType = extern union {
         };
     }
 
-    pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 {
+    pub fn byteSize(self: CType, store: Store.Set, mod: *Module) u64 {
+        const target = &mod.resolved_target.result;
         return switch (self.tag()) {
             .void => 0,
             .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1,
@@ -906,7 +909,7 @@ pub const CType = extern union {
             .vector,
             => {
                 const data = self.cast(Payload.Sequence).?.data;
-                return data.len * store.indexToCType(data.elem_type).byteSize(store, target);
+                return data.len * store.indexToCType(data.elem_type).byteSize(store, mod);
             },
 
             .fwd_anon_struct,
@@ -1248,13 +1251,18 @@ pub const CType = extern union {
         }
 
         pub const Lookup = union(enum) {
-            fail: *Module,
+            fail: struct {
+                zcu: *Zcu,
+                mod: *Module,
+            },
             imm: struct {
                 set: *const Store.Set,
+                zcu: *Zcu,
                 mod: *Module,
             },
             mut: struct {
                 promoted: *Store.Promoted,
+                zcu: *Zcu,
                 mod: *Module,
             },
 
@@ -1265,15 +1273,15 @@ pub const CType = extern union {
                 };
             }
 
-            pub fn getTarget(self: @This()) Target {
-                return self.getModule().getTarget();
+            pub fn getZcu(self: @This()) *Zcu {
+                return switch (self) {
+                    inline else => |pl| pl.zcu,
+                };
             }
 
             pub fn getModule(self: @This()) *Module {
                 return switch (self) {
-                    .fail => |mod| mod,
-                    .imm => |imm| imm.mod,
-                    .mut => |mut| mut.mod,
+                    inline else => |pl| pl.mod,
                 };
             }
 
@@ -1288,8 +1296,8 @@ pub const CType = extern union {
             pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index {
                 return switch (self) {
                     .fail => null,
-                    .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind),
-                    .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind),
+                    .imm => |imm| imm.set.typeToIndex(ty, imm.zcu, imm.mod, kind),
+                    .mut => |mut| try mut.promoted.typeToIndex(ty, mut.zcu, mut.mod, kind),
                 };
             }
 
@@ -1300,7 +1308,7 @@ pub const CType = extern union {
             pub fn freeze(self: @This()) @This() {
                 return switch (self) {
                     .fail, .imm => self,
-                    .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .mod = mut.mod } },
+                    .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .zcu = mut.zcu, .mod = mut.mod } },
                 };
             }
         };
@@ -1354,7 +1362,7 @@ pub const CType = extern union {
                     self.storage.anon.fields[0] = .{
                         .name = "array",
                         .type = array_idx,
-                        .alignas = AlignAs.abiAlign(ty, lookup.getModule()),
+                        .alignas = AlignAs.abiAlign(ty, lookup.getZcu()),
                     };
                     self.initAnon(kind, fwd_idx, 1);
                 } else self.init(switch (kind) {
@@ -1366,13 +1374,13 @@ pub const CType = extern union {
         }
 
         pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {
-            const mod = lookup.getModule();
-            const ip = &mod.intern_pool;
+            const zcu = lookup.getZcu();
+            const ip = &zcu.intern_pool;
 
             self.* = undefined;
-            if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod))
+            if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu))
                 self.init(.void)
-            else if (ty.isAbiInt(mod)) switch (ty.ip_index) {
+            else if (ty.isAbiInt(zcu)) switch (ty.ip_index) {
                 .usize_type => self.init(.uintptr_t),
                 .isize_type => self.init(.intptr_t),
                 .c_char_type => self.init(.char),
@@ -1384,13 +1392,13 @@ pub const CType = extern union {
                 .c_ulong_type => self.init(.@"unsigned long"),
                 .c_longlong_type => self.init(.@"long long"),
                 .c_ulonglong_type => self.init(.@"unsigned long long"),
-                else => switch (tagFromIntInfo(ty.intInfo(mod))) {
+                else => switch (tagFromIntInfo(ty.intInfo(zcu))) {
                     .void => unreachable,
                     else => |t| self.init(t),
                     .array => switch (kind) {
                         .forward, .complete, .global => {
-                            const abi_size = ty.abiSize(mod);
-                            const abi_align = ty.abiAlignment(mod).toByteUnits(0);
+                            const abi_size = ty.abiSize(zcu);
+                            const abi_align = ty.abiAlignment(zcu).toByteUnits(0);
                             self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
                                 .len = @divExact(abi_size, abi_align),
                                 .elem_type = tagFromIntInfo(.{
@@ -1406,7 +1414,7 @@ pub const CType = extern union {
                         .payload => unreachable,
                     },
                 },
-            } else switch (ty.zigTypeTag(mod)) {
+            } else switch (ty.zigTypeTag(zcu)) {
                 .Frame => unreachable,
                 .AnyFrame => unreachable,
 
@@ -1436,7 +1444,7 @@ pub const CType = extern union {
                 }),
 
                 .Pointer => {
-                    const info = ty.ptrInfo(mod);
+                    const info = ty.ptrInfo(zcu);
                     switch (info.flags.size) {
                         .Slice => {
                             if (switch (kind) {
@@ -1444,18 +1452,18 @@ pub const CType = extern union {
                                 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
                                 .payload => unreachable,
                             }) |fwd_idx| {
-                                const ptr_ty = ty.slicePtrFieldType(mod);
+                                const ptr_ty = ty.slicePtrFieldType(zcu);
                                 if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| {
                                     self.storage = .{ .anon = undefined };
                                     self.storage.anon.fields[0] = .{
                                         .name = "ptr",
                                         .type = ptr_idx,
-                                        .alignas = AlignAs.abiAlign(ptr_ty, mod),
+                                        .alignas = AlignAs.abiAlign(ptr_ty, zcu),
                                     };
                                     self.storage.anon.fields[1] = .{
                                         .name = "len",
                                         .type = Tag.uintptr_t.toIndex(),
-                                        .alignas = AlignAs.abiAlign(Type.usize, mod),
+                                        .alignas = AlignAs.abiAlign(Type.usize, zcu),
                                     };
                                     self.initAnon(kind, fwd_idx, 2);
                                 } else self.init(switch (kind) {
@@ -1478,11 +1486,16 @@ pub const CType = extern union {
                                 },
                             };
 
-                            const pointee_ty = if (info.packed_offset.host_size > 0 and
-                                info.flags.vector_index == .none)
-                                try mod.intType(.unsigned, info.packed_offset.host_size * 8)
+                            const pointee_ty = if (info.packed_offset.host_size > 0 and info.flags.vector_index == .none)
+                                try zcu.intType(.unsigned, info.packed_offset.host_size * 8)
+                            else if (info.flags.alignment == .none or
+                                info.flags.alignment.compareStrict(.gte, Type.fromInterned(info.child).abiAlignment(zcu)))
+                                Type.fromInterned(info.child)
                             else
-                                Type.fromInterned(info.child);
+                                try zcu.intType(.unsigned, @min(
+                                    info.flags.alignment.toByteUnitsOptional().?,
+                                    lookup.getModule().resolved_target.result.maxIntAlignment(),
+                                ) * 8);
 
                             if (try lookup.typeToIndex(pointee_ty, .forward)) |child_idx| {
                                 self.storage = .{ .child = .{
@@ -1495,24 +1508,24 @@ pub const CType = extern union {
                     }
                 },
 
-                .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .@"packed") {
-                    if (mod.typeToPackedStruct(ty)) |packed_struct| {
+                .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(zcu) == .@"packed") {
+                    if (zcu.typeToPackedStruct(ty)) |packed_struct| {
                         try self.initType(Type.fromInterned(packed_struct.backingIntType(ip).*), kind, lookup);
                     } else {
-                        const bits: u16 = @intCast(ty.bitSize(mod));
-                        const int_ty = try mod.intType(.unsigned, bits);
+                        const bits: u16 = @intCast(ty.bitSize(zcu));
+                        const int_ty = try zcu.intType(.unsigned, bits);
                         try self.initType(int_ty, kind, lookup);
                     }
-                } else if (ty.isTupleOrAnonStruct(mod)) {
+                } else if (ty.isTupleOrAnonStruct(zcu)) {
                     if (lookup.isMutable()) {
                         for (0..switch (zig_ty_tag) {
-                            .Struct => ty.structFieldCount(mod),
-                            .Union => mod.typeToUnion(ty).?.field_types.len,
+                            .Struct => ty.structFieldCount(zcu),
+                            .Union => zcu.typeToUnion(ty).?.field_types.len,
                             else => unreachable,
                         }) |field_i| {
-                            const field_ty = ty.structFieldType(field_i, mod);
-                            if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
-                                !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                            const field_ty = ty.structFieldType(field_i, zcu);
+                            if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or
+                                !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
                             _ = try lookup.typeToIndex(field_ty, switch (kind) {
                                 .forward, .forward_parameter => .forward,
                                 .complete, .parameter => .complete,
@@ -1540,14 +1553,14 @@ pub const CType = extern union {
                         .payload => unreachable,
                     });
                 } else {
-                    const tag_ty = ty.unionTagTypeSafety(mod);
+                    const tag_ty = ty.unionTagTypeSafety(zcu);
                     const is_tagged_union_wrapper = kind != .payload and tag_ty != null;
                     const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper;
                     switch (kind) {
                         .forward, .forward_parameter => {
                             self.storage = .{ .fwd = .{
                                 .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union },
-                                .data = ty.getOwnerDecl(mod),
+                                .data = ty.getOwnerDecl(zcu),
                             } };
                             self.value = .{ .cty = initPayload(&self.storage.fwd) };
                         },
@@ -1562,7 +1575,7 @@ pub const CType = extern union {
                                     self.storage.anon.fields[field_count] = .{
                                         .name = "payload",
                                         .type = payload_idx.?,
-                                        .alignas = AlignAs.unionPayloadAlign(ty, mod),
+                                        .alignas = AlignAs.unionPayloadAlign(ty, zcu),
                                     };
                                     field_count += 1;
                                 }
@@ -1570,7 +1583,7 @@ pub const CType = extern union {
                                     self.storage.anon.fields[field_count] = .{
                                         .name = "tag",
                                         .type = tag_idx.?,
-                                        .alignas = AlignAs.abiAlign(tag_ty.?, mod),
+                                        .alignas = AlignAs.abiAlign(tag_ty.?, zcu),
                                     };
                                     field_count += 1;
                                 }
@@ -1583,19 +1596,19 @@ pub const CType = extern union {
                                 } };
                                 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };
                             } else self.init(.@"struct");
-                        } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) {
+                        } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(zcu)) {
                             self.init(.void);
                         } else {
                             var is_packed = false;
                             for (0..switch (zig_ty_tag) {
-                                .Struct => ty.structFieldCount(mod),
-                                .Union => mod.typeToUnion(ty).?.field_types.len,
+                                .Struct => ty.structFieldCount(zcu),
+                                .Union => zcu.typeToUnion(ty).?.field_types.len,
                                 else => unreachable,
                             }) |field_i| {
-                                const field_ty = ty.structFieldType(field_i, mod);
-                                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                const field_ty = ty.structFieldType(field_i, zcu);
+                                if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
-                                const field_align = AlignAs.fieldAlign(ty, field_i, mod);
+                                const field_align = AlignAs.fieldAlign(ty, field_i, zcu);
                                 if (field_align.abiOrder().compare(.lt)) {
                                     is_packed = true;
                                     if (!lookup.isMutable()) break;
@@ -1634,9 +1647,9 @@ pub const CType = extern union {
                                 .Vector => .vector,
                                 else => unreachable,
                             };
-                            if (try lookup.typeToIndex(ty.childType(mod), kind)) |child_idx| {
+                            if (try lookup.typeToIndex(ty.childType(zcu), kind)) |child_idx| {
                                 self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{
-                                    .len = ty.arrayLenIncludingSentinel(mod),
+                                    .len = ty.arrayLenIncludingSentinel(zcu),
                                     .elem_type = child_idx,
                                 } } };
                                 self.value = .{ .cty = initPayload(&self.storage.seq) };
@@ -1648,9 +1661,9 @@ pub const CType = extern union {
                 },
 
                 .Optional => {
-                    const payload_ty = ty.optionalChild(mod);
-                    if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
-                        if (ty.optionalReprIsPayload(mod)) {
+                    const payload_ty = ty.optionalChild(zcu);
+                    if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
+                        if (ty.optionalReprIsPayload(zcu)) {
                             try self.initType(payload_ty, kind, lookup);
                         } else if (switch (kind) {
                             .forward, .forward_parameter => @as(Index, undefined),
@@ -1667,12 +1680,12 @@ pub const CType = extern union {
                                 self.storage.anon.fields[0] = .{
                                     .name = "payload",
                                     .type = payload_idx,
-                                    .alignas = AlignAs.abiAlign(payload_ty, mod),
+                                    .alignas = AlignAs.abiAlign(payload_ty, zcu),
                                 };
                                 self.storage.anon.fields[1] = .{
                                     .name = "is_null",
                                     .type = Tag.bool.toIndex(),
-                                    .alignas = AlignAs.abiAlign(Type.bool, mod),
+                                    .alignas = AlignAs.abiAlign(Type.bool, zcu),
                                 };
                                 self.initAnon(kind, fwd_idx, 2);
                             } else self.init(switch (kind) {
@@ -1690,14 +1703,14 @@ pub const CType = extern union {
                         .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
                         .payload => unreachable,
                     }) |fwd_idx| {
-                        const payload_ty = ty.errorUnionPayload(mod);
+                        const payload_ty = ty.errorUnionPayload(zcu);
                         if (try lookup.typeToIndex(payload_ty, switch (kind) {
                             .forward, .forward_parameter => .forward,
                             .complete, .parameter => .complete,
                             .global => .global,
                             .payload => unreachable,
                         })) |payload_idx| {
-                            const error_ty = ty.errorUnionSet(mod);
+                            const error_ty = ty.errorUnionSet(zcu);
                             if (payload_idx == Tag.void.toIndex()) {
                                 try self.initType(error_ty, kind, lookup);
                             } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {
@@ -1705,12 +1718,12 @@ pub const CType = extern union {
                                 self.storage.anon.fields[0] = .{
                                     .name = "payload",
                                     .type = payload_idx,
-                                    .alignas = AlignAs.abiAlign(payload_ty, mod),
+                                    .alignas = AlignAs.abiAlign(payload_ty, zcu),
                                 };
                                 self.storage.anon.fields[1] = .{
                                     .name = "error",
                                     .type = error_idx,
-                                    .alignas = AlignAs.abiAlign(error_ty, mod),
+                                    .alignas = AlignAs.abiAlign(error_ty, zcu),
                                 };
                                 self.initAnon(kind, fwd_idx, 2);
                             } else self.init(switch (kind) {
@@ -1729,7 +1742,7 @@ pub const CType = extern union {
                 .Opaque => self.init(.void),
 
                 .Fn => {
-                    const info = mod.typeToFunc(ty).?;
+                    const info = zcu.typeToFunc(ty).?;
                     if (!info.is_generic) {
                         if (lookup.isMutable()) {
                             const param_kind: Kind = switch (kind) {
@@ -1739,7 +1752,7 @@ pub const CType = extern union {
                             };
                             _ = try lookup.typeToIndex(Type.fromInterned(info.return_type), param_kind);
                             for (info.param_types.get(ip)) |param_type| {
-                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue;
                                 _ = try lookup.typeToIndex(Type.fromInterned(param_type), param_kind);
                             }
                         }
@@ -1906,20 +1919,21 @@ pub const CType = extern union {
         }
     }
 
-    fn createFromType(store: *Store.Promoted, ty: Type, mod: *Module, kind: Kind) !CType {
+    fn createFromType(store: *Store.Promoted, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType {
         var convert: Convert = undefined;
-        try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } });
-        return createFromConvert(store, ty, mod, kind, &convert);
+        try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .zcu = zcu } });
+        return createFromConvert(store, ty, zcu, mod, kind, &convert);
     }
 
     fn createFromConvert(
         store: *Store.Promoted,
         ty: Type,
+        zcu: *Zcu,
         mod: *Module,
         kind: Kind,
         convert: Convert,
     ) !CType {
-        const ip = &mod.intern_pool;
+        const ip = &zcu.intern_pool;
         const arena = store.arena.allocator();
         switch (convert.value) {
             .cty => |c| return c.copy(arena),
@@ -1937,18 +1951,18 @@ pub const CType = extern union {
                 .packed_struct,
                 .packed_union,
                 => {
-                    const zig_ty_tag = ty.zigTypeTag(mod);
+                    const zig_ty_tag = ty.zigTypeTag(zcu);
                     const fields_len = switch (zig_ty_tag) {
-                        .Struct => ty.structFieldCount(mod),
-                        .Union => mod.typeToUnion(ty).?.field_types.len,
+                        .Struct => ty.structFieldCount(zcu),
+                        .Union => zcu.typeToUnion(ty).?.field_types.len,
                         else => unreachable,
                     };
 
                     var c_fields_len: usize = 0;
                     for (0..fields_len) |field_i| {
-                        const field_ty = ty.structFieldType(field_i, mod);
-                        if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
-                            !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                        const field_ty = ty.structFieldType(field_i, zcu);
+                        if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or
+                            !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
                         c_fields_len += 1;
                     }
 
@@ -1956,26 +1970,26 @@ pub const CType = extern union {
                     var c_field_i: usize = 0;
                     for (0..fields_len) |field_i_usize| {
                         const field_i: u32 = @intCast(field_i_usize);
-                        const field_ty = ty.structFieldType(field_i, mod);
-                        if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
-                            !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                        const field_ty = ty.structFieldType(field_i, zcu);
+                        if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or
+                            !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                         defer c_field_i += 1;
                         fields_pl[c_field_i] = .{
-                            .name = try if (ty.isSimpleTuple(mod))
+                            .name = try if (ty.isSimpleTuple(zcu))
                                 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
                             else
                                 arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) {
-                                    .Struct => ty.legacyStructFieldName(field_i, mod),
+                                    .Struct => ty.legacyStructFieldName(field_i, zcu),
                                     .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
                                     else => unreachable,
                                 })),
-                            .type = store.set.typeToIndex(field_ty, mod, switch (kind) {
+                            .type = store.set.typeToIndex(field_ty, zcu, mod, switch (kind) {
                                 .forward, .forward_parameter => .forward,
                                 .complete, .parameter, .payload => .complete,
                                 .global => .global,
                             }).?,
-                            .alignas = AlignAs.fieldAlign(ty, field_i, mod),
+                            .alignas = AlignAs.fieldAlign(ty, field_i, zcu),
                         };
                     }
 
@@ -1996,8 +2010,8 @@ pub const CType = extern union {
                             const unnamed_pl = try arena.create(Payload.Unnamed);
                             unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{
                                 .fields = fields_pl,
-                                .owner_decl = ty.getOwnerDecl(mod),
-                                .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable,
+                                .owner_decl = ty.getOwnerDecl(zcu),
+                                .id = if (ty.unionTagTypeSafety(zcu)) |_| 0 else unreachable,
                             } };
                             return initPayload(unnamed_pl);
                         },
@@ -2012,7 +2026,7 @@ pub const CType = extern union {
                             const struct_pl = try arena.create(Payload.Aggregate);
                             struct_pl.* = .{ .base = .{ .tag = t }, .data = .{
                                 .fields = fields_pl,
-                                .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?,
+                                .fwd_decl = store.set.typeToIndex(ty, zcu, mod, .forward).?,
                             } };
                             return initPayload(struct_pl);
                         },
@@ -2024,7 +2038,7 @@ pub const CType = extern union {
                 .function,
                 .varargs_function,
                 => {
-                    const info = mod.typeToFunc(ty).?;
+                    const info = zcu.typeToFunc(ty).?;
                     assert(!info.is_generic);
                     const param_kind: Kind = switch (kind) {
                         .forward, .forward_parameter => .forward_parameter,
@@ -2034,21 +2048,21 @@ pub const CType = extern union {
 
                     var c_params_len: usize = 0;
                     for (info.param_types.get(ip)) |param_type| {
-                        if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue;
+                        if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue;
                         c_params_len += 1;
                     }
 
                     const params_pl = try arena.alloc(Index, c_params_len);
                     var c_param_i: usize = 0;
                     for (info.param_types.get(ip)) |param_type| {
-                        if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue;
-                        params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), mod, param_kind).?;
+                        if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue;
+                        params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), zcu, mod, param_kind).?;
                         c_param_i += 1;
                     }
 
                     const fn_pl = try arena.create(Payload.Function);
                     fn_pl.* = .{ .base = .{ .tag = t }, .data = .{
-                        .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), mod, param_kind).?,
+                        .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), zcu, mod, param_kind).?,
                         .param_types = params_pl,
                     } };
                     return initPayload(fn_pl);
@@ -2075,8 +2089,8 @@ pub const CType = extern union {
         }
 
         pub fn eql(self: @This(), ty: Type, cty: CType) bool {
-            const mod = self.lookup.getModule();
-            const ip = &mod.intern_pool;
+            const zcu = self.lookup.getZcu();
+            const ip = &zcu.intern_pool;
             switch (self.convert.value) {
                 .cty => |c| return c.eql(cty),
                 .tag => |t| {
@@ -2086,24 +2100,24 @@ pub const CType = extern union {
                         .fwd_anon_struct,
                         .fwd_anon_union,
                         => {
-                            if (!ty.isTupleOrAnonStruct(mod)) return false;
+                            if (!ty.isTupleOrAnonStruct(zcu)) return false;
 
                             var name_buf: [
                                 std.fmt.count("f{}", .{std.math.maxInt(usize)})
                             ]u8 = undefined;
                             const c_fields = cty.cast(Payload.Fields).?.data;
 
-                            const zig_ty_tag = ty.zigTypeTag(mod);
+                            const zig_ty_tag = ty.zigTypeTag(zcu);
                             var c_field_i: usize = 0;
                             for (0..switch (zig_ty_tag) {
-                                .Struct => ty.structFieldCount(mod),
-                                .Union => mod.typeToUnion(ty).?.field_types.len,
+                                .Struct => ty.structFieldCount(zcu),
+                                .Union => zcu.typeToUnion(ty).?.field_types.len,
                                 else => unreachable,
                             }) |field_i_usize| {
                                 const field_i: u32 = @intCast(field_i_usize);
-                                const field_ty = ty.structFieldType(field_i, mod);
-                                if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
-                                    !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                const field_ty = ty.structFieldType(field_i, zcu);
+                                if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or
+                                    !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                                 defer c_field_i += 1;
                                 const c_field = &c_fields[c_field_i];
@@ -2115,16 +2129,16 @@ pub const CType = extern union {
                                     .payload => unreachable,
                                 }) or !mem.eql(
                                     u8,
-                                    if (ty.isSimpleTuple(mod))
+                                    if (ty.isSimpleTuple(zcu))
                                         std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable
                                     else
                                         ip.stringToSlice(switch (zig_ty_tag) {
-                                            .Struct => ty.legacyStructFieldName(field_i, mod),
+                                            .Struct => ty.legacyStructFieldName(field_i, zcu),
                                             .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
                                             else => unreachable,
                                         }),
                                     mem.span(c_field.name),
-                                ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" !=
+                                ) or AlignAs.fieldAlign(ty, field_i, zcu).@"align" !=
                                     c_field.alignas.@"align") return false;
                             }
                             return true;
@@ -2136,9 +2150,9 @@ pub const CType = extern union {
                         .packed_unnamed_union,
                         => switch (self.kind) {
                             .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
-                            .payload => if (ty.unionTagTypeSafety(mod)) |_| {
+                            .payload => if (ty.unionTagTypeSafety(zcu)) |_| {
                                 const data = cty.cast(Payload.Unnamed).?.data;
-                                return ty.getOwnerDecl(mod) == data.owner_decl and data.id == 0;
+                                return ty.getOwnerDecl(zcu) == data.owner_decl and data.id == 0;
                             } else unreachable,
                         },
 
@@ -2157,9 +2171,9 @@ pub const CType = extern union {
                         .function,
                         .varargs_function,
                         => {
-                            if (ty.zigTypeTag(mod) != .Fn) return false;
+                            if (ty.zigTypeTag(zcu) != .Fn) return false;
 
-                            const info = mod.typeToFunc(ty).?;
+                            const info = zcu.typeToFunc(ty).?;
                             assert(!info.is_generic);
                             const data = cty.cast(Payload.Function).?.data;
                             const param_kind: Kind = switch (self.kind) {
@@ -2173,7 +2187,7 @@ pub const CType = extern union {
 
                             var c_param_i: usize = 0;
                             for (info.param_types.get(ip)) |param_type| {
-                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                                 if (c_param_i >= data.param_types.len) return false;
                                 const param_cty = data.param_types[c_param_i];
@@ -2213,8 +2227,8 @@ pub const CType = extern union {
                 .tag => |t| {
                     autoHash(hasher, t);
 
-                    const mod = self.lookup.getModule();
-                    const ip = &mod.intern_pool;
+                    const zcu = self.lookup.getZcu();
+                    const ip = &zcu.intern_pool;
                     switch (t) {
                         .fwd_anon_struct,
                         .fwd_anon_union,
@@ -2223,16 +2237,16 @@ pub const CType = extern union {
                                 std.fmt.count("f{}", .{std.math.maxInt(usize)})
                             ]u8 = undefined;
 
-                            const zig_ty_tag = ty.zigTypeTag(mod);
-                            for (0..switch (ty.zigTypeTag(mod)) {
-                                .Struct => ty.structFieldCount(mod),
-                                .Union => mod.typeToUnion(ty).?.field_types.len,
+                            const zig_ty_tag = ty.zigTypeTag(zcu);
+                            for (0..switch (ty.zigTypeTag(zcu)) {
+                                .Struct => ty.structFieldCount(zcu),
+                                .Union => zcu.typeToUnion(ty).?.field_types.len,
                                 else => unreachable,
                             }) |field_i_usize| {
                                 const field_i: u32 = @intCast(field_i_usize);
-                                const field_ty = ty.structFieldType(field_i, mod);
-                                if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
-                                    !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                const field_ty = ty.structFieldType(field_i, zcu);
+                                if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or
+                                    !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                                 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {
                                     .forward, .forward_parameter => .forward,
@@ -2240,15 +2254,15 @@ pub const CType = extern union {
                                     .global => .global,
                                     .payload => unreachable,
                                 });
-                                hasher.update(if (ty.isSimpleTuple(mod))
+                                hasher.update(if (ty.isSimpleTuple(zcu))
                                     std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
                                 else
-                                    mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
-                                        .Struct => ty.legacyStructFieldName(field_i, mod),
+                                    zcu.intern_pool.stringToSlice(switch (zig_ty_tag) {
+                                        .Struct => ty.legacyStructFieldName(field_i, zcu),
                                         .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i],
                                         else => unreachable,
                                     }));
-                                autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");
+                                autoHash(hasher, AlignAs.fieldAlign(ty, field_i, zcu).@"align");
                             }
                         },
 
@@ -2258,8 +2272,8 @@ pub const CType = extern union {
                         .packed_unnamed_union,
                         => switch (self.kind) {
                             .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
-                            .payload => if (ty.unionTagTypeSafety(mod)) |_| {
-                                autoHash(hasher, ty.getOwnerDecl(mod));
+                            .payload => if (ty.unionTagTypeSafety(zcu)) |_| {
+                                autoHash(hasher, ty.getOwnerDecl(zcu));
                                 autoHash(hasher, @as(u32, 0));
                             } else unreachable,
                         },
@@ -2275,7 +2289,7 @@ pub const CType = extern union {
                         .function,
                         .varargs_function,
                         => {
-                            const info = mod.typeToFunc(ty).?;
+                            const info = zcu.typeToFunc(ty).?;
                             assert(!info.is_generic);
                             const param_kind: Kind = switch (self.kind) {
                                 .forward, .forward_parameter => .forward_parameter,
@@ -2285,7 +2299,7 @@ pub const CType = extern union {
 
                             self.updateHasherRecurse(hasher, Type.fromInterned(info.return_type), param_kind);
                             for (info.param_types.get(ip)) |param_type| {
-                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue;
                                 self.updateHasherRecurse(hasher, Type.fromInterned(param_type), param_kind);
                             }
                         },
src/codegen/c.zig
@@ -5,12 +5,13 @@ const mem = std.mem;
 const log = std.log.scoped(.c);
 
 const link = @import("../link.zig");
-const Module = @import("../Module.zig");
+const Zcu = @import("../Module.zig");
+const Module = @import("../Package/Module.zig");
 const Compilation = @import("../Compilation.zig");
 const Value = @import("../Value.zig");
 const Type = @import("../type.zig").Type;
 const C = link.File.C;
-const Decl = Module.Decl;
+const Decl = Zcu.Decl;
 const trace = @import("../tracy.zig").trace;
 const LazySrcLoc = std.zig.LazySrcLoc;
 const Air = @import("../Air.zig");
@@ -30,7 +31,7 @@ pub const CValue = union(enum) {
     /// Address of a local.
     local_ref: LocalIndex,
     /// A constant instruction, to be rendered inline.
-    constant: InternPool.Index,
+    constant: Value,
     /// Index into the parameters
     arg: usize,
     /// The array field of a parameter
@@ -72,13 +73,15 @@ pub const LazyFnValue = struct {
 };
 pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
 
-const LoopDepth = u16;
 const Local = struct {
     cty_idx: CType.Index,
-    alignas: CType.AlignAs,
+    flags: packed struct(u32) {
+        alignas: CType.AlignAs,
+        _: u20 = undefined,
+    },
 
     pub fn getType(local: Local) LocalType {
-        return .{ .cty_idx = local.cty_idx, .alignas = local.alignas };
+        return .{ .cty_idx = local.cty_idx, .alignas = local.flags.alignas };
     }
 };
 
@@ -300,11 +303,11 @@ pub const Function = struct {
         const gop = try f.value_map.getOrPut(ref);
         if (gop.found_existing) return gop.value_ptr.*;
 
-        const mod = f.object.dg.module;
-        const val = (try f.air.value(ref, mod)).?;
+        const zcu = f.object.dg.zcu;
+        const val = (try f.air.value(ref, zcu)).?;
         const ty = f.typeOf(ref);
 
-        const result: CValue = if (lowersToArray(ty, mod)) result: {
+        const result: CValue = if (lowersToArray(ty, zcu)) result: {
             const writer = f.object.codeHeaderWriter();
             const alignment: Alignment = .none;
             const decl_c_value = try f.allocLocalValue(ty, alignment);
@@ -313,17 +316,17 @@ pub const Function = struct {
             try writer.writeAll("static ");
             try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
             try writer.writeAll(" = ");
-            try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
+            try f.object.dg.renderValue(writer, val, .StaticInitializer);
             try writer.writeAll(";\n ");
             break :result decl_c_value;
-        } else .{ .constant = val.toIntern() };
+        } else .{ .constant = val };
 
         gop.value_ptr.* = result;
         return result;
     }
 
     fn wantSafety(f: *Function) bool {
-        return switch (f.object.dg.module.optimizeMode()) {
+        return switch (f.object.dg.zcu.optimizeMode()) {
             .Debug, .ReleaseSafe => true,
             .ReleaseFast, .ReleaseSmall => false,
         };
@@ -333,11 +336,13 @@ pub const Function = struct {
     /// those which go into `allocs`. This function does not add the resulting local into `allocs`;
     /// that responsibility lies with the caller.
     fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue {
-        const mod = f.object.dg.module;
+        const zcu = f.object.dg.zcu;
         const gpa = f.object.dg.gpa;
         try f.locals.append(gpa, .{
             .cty_idx = try f.typeToIndex(ty, .complete),
-            .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
+            .flags = .{
+                .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)),
+            },
         });
         return .{ .new_local = @intCast(f.locals.items.len - 1) };
     }
@@ -355,79 +360,100 @@ pub const Function = struct {
     /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
     /// not be used for persistent locals (i.e. those in `allocs`).
     fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue {
-        const mod = f.object.dg.module;
+        const zcu = f.object.dg.zcu;
         if (f.free_locals_map.getPtr(.{
             .cty_idx = try f.typeToIndex(ty, .complete),
-            .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
+            .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)),
         })) |locals_list| {
             if (locals_list.popOrNull()) |local_entry| {
                 return .{ .new_local = local_entry.key };
             }
         }
 
-        return try f.allocLocalValue(ty, alignment);
+        return f.allocLocalValue(ty, alignment);
     }
 
     fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
         switch (c_value) {
-            .constant => |val| try f.object.dg.renderValue(
-                w,
-                Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
-                Value.fromInterned(val),
-                location,
-            ),
-            .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
+            .none => unreachable,
+            .new_local, .local => |i| try w.print("t{d}", .{i}),
+            .local_ref => |i| {
+                const local = &f.locals.items[i];
+                if (local.flags.alignas.abiOrder().compare(.lt)) {
+                    const zcu = f.object.dg.zcu;
+                    const pointee_ty = try zcu.intType(.unsigned, @min(
+                        local.flags.alignas.@"align".toByteUnitsOptional().?,
+                        f.object.dg.mod.resolved_target.result.maxIntAlignment(),
+                    ) * 8);
+                    const ptr_ty = try zcu.singleMutPtrType(pointee_ty);
+
+                    try w.writeByte('(');
+                    try f.renderType(w, ptr_ty);
+                    try w.writeByte(')');
+                }
+                try w.print("&t{d}", .{i});
+            },
+            .constant => |val| try f.object.dg.renderValue(w, val, location),
+            .arg => |i| try w.print("a{d}", .{i}),
+            .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }),
+            .undef => |ty| try f.object.dg.renderUndefValue(w, ty, location),
             else => try f.object.dg.writeCValue(w, c_value),
         }
     }
 
     fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
         switch (c_value) {
-            .constant => |val| {
+            .none => unreachable,
+            .new_local, .local, .constant => {
                 try w.writeAll("(*");
-                try f.object.dg.renderValue(
-                    w,
-                    Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
-                    Value.fromInterned(val),
-                    .Other,
-                );
+                try f.writeCValue(w, c_value, .Other);
+                try w.writeByte(')');
+            },
+            .local_ref => |i| try w.print("t{d}", .{i}),
+            .arg => |i| try w.print("(*a{d})", .{i}),
+            .arg_array => |i| {
+                try w.writeAll("(*");
+                try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" });
                 try w.writeByte(')');
             },
             else => try f.object.dg.writeCValueDeref(w, c_value),
         }
     }
 
-    fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
+    fn writeCValueMember(
+        f: *Function,
+        writer: anytype,
+        c_value: CValue,
+        member: CValue,
+    ) error{ OutOfMemory, AnalysisFail }!void {
         switch (c_value) {
-            .constant => |val| {
-                try f.object.dg.renderValue(
-                    w,
-                    Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
-                    Value.fromInterned(val),
-                    .Other,
-                );
-                try w.writeByte('.');
-                try f.writeCValue(w, member, .Other);
+            .new_local, .local, .local_ref, .constant, .arg, .arg_array => {
+                try f.writeCValue(writer, c_value, .Other);
+                try writer.writeByte('.');
+                try f.writeCValue(writer, member, .Other);
             },
-            else => try f.object.dg.writeCValueMember(w, c_value, member),
+            else => return f.object.dg.writeCValueMember(writer, c_value, member),
         }
     }
 
-    fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
+    fn writeCValueDerefMember(f: *Function, writer: anytype, c_value: CValue, member: CValue) !void {
         switch (c_value) {
-            .constant => |val| {
-                try w.writeByte('(');
-                try f.object.dg.renderValue(
-                    w,
-                    Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)),
-                    Value.fromInterned(val),
-                    .Other,
-                );
-                try w.writeAll(")->");
-                try f.writeCValue(w, member, .Other);
+            .new_local, .local, .arg, .arg_array => {
+                try f.writeCValue(writer, c_value, .Other);
+                try writer.writeAll("->");
+            },
+            .constant => {
+                try writer.writeByte('(');
+                try f.writeCValue(writer, c_value, .Other);
+                try writer.writeAll(")->");
+            },
+            .local_ref => {
+                try f.writeCValueDeref(writer, c_value);
+                try writer.writeByte('.');
             },
-            else => try f.object.dg.writeCValueDerefMember(w, c_value, member),
+            else => return f.object.dg.writeCValueDerefMember(writer, c_value, member),
         }
+        try f.writeCValue(writer, member, .Other);
     }
 
     fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
@@ -462,8 +488,8 @@ pub const Function = struct {
         return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location);
     }
 
-    fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
-        return f.object.dg.fmtIntLiteral(ty, val, .Other);
+    fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) {
+        return f.object.dg.fmtIntLiteral(val, .Other);
     }
 
     fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 {
@@ -475,7 +501,7 @@ pub const Function = struct {
             var promoted = f.object.dg.ctypes.promote(gpa);
             defer f.object.dg.ctypes.demote(promoted);
             const arena = promoted.arena.allocator();
-            const mod = f.object.dg.module;
+            const zcu = f.object.dg.zcu;
 
             gop.value_ptr.* = .{
                 .fn_name = switch (key) {
@@ -484,7 +510,7 @@ pub const Function = struct {
                     .never_inline,
                     => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{
                         @tagName(key),
-                        fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
+                        fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
                         @intFromEnum(owner_decl),
                     }),
                 },
@@ -510,17 +536,17 @@ pub const Function = struct {
     }
 
     fn typeOf(f: *Function, inst: Air.Inst.Ref) Type {
-        const mod = f.object.dg.module;
-        return f.air.typeOf(inst, &mod.intern_pool);
+        const zcu = f.object.dg.zcu;
+        return f.air.typeOf(inst, &zcu.intern_pool);
     }
 
     fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type {
-        const mod = f.object.dg.module;
-        return f.air.typeOfIndex(inst, &mod.intern_pool);
+        const zcu = f.object.dg.zcu;
+        return f.air.typeOfIndex(inst, &zcu.intern_pool);
     }
 };
 
-/// This data is available when outputting .c code for a `Module`.
+/// This data is available when outputting .c code for a `Zcu`.
 /// It is not available when generating .h file.
 pub const Object = struct {
     dg: DeclGen,
@@ -542,12 +568,13 @@ pub const Object = struct {
 /// This data is available both when outputting .c code and when outputting an .h file.
 pub const DeclGen = struct {
     gpa: mem.Allocator,
-    module: *Module,
+    zcu: *Zcu,
+    mod: *Module,
     pass: Pass,
     is_naked_fn: bool,
     /// This is a borrowed reference from `link.C`.
     fwd_decl: std.ArrayList(u8),
-    error_msg: ?*Module.ErrorMsg,
+    error_msg: ?*Zcu.ErrorMsg,
     ctypes: CType.Store,
     /// Keeps track of anonymous decls that need to be rendered before this
     /// (named) Decl in the output C code.
@@ -566,75 +593,70 @@ pub const DeclGen = struct {
 
     fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
         @setCold(true);
-        const mod = dg.module;
+        const zcu = dg.zcu;
         const decl_index = dg.pass.decl;
-        const decl = mod.declPtr(decl_index);
-        const src_loc = decl.srcLoc(mod);
-        dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
+        const decl = zcu.declPtr(decl_index);
+        const src_loc = decl.srcLoc(zcu);
+        dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);
         return error.AnalysisFail;
     }
 
     fn renderAnonDeclValue(
         dg: *DeclGen,
         writer: anytype,
-        ty: Type,
         ptr_val: Value,
         anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
         location: ValueRenderLocation,
     ) error{ OutOfMemory, AnalysisFail }!void {
-        const mod = dg.module;
-        const ip = &mod.intern_pool;
-        const decl_val = anon_decl.val;
-        const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
+        const zcu = dg.zcu;
+        const ip = &zcu.intern_pool;
+        const decl_val = Value.fromInterned(anon_decl.val);
+        const decl_ty = decl_val.typeOf(zcu);
 
         // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
-        if (ty.isPtrAtRuntime(mod) and !decl_ty.isFnOrHasRuntimeBits(mod)) {
-            return dg.writeCValue(writer, .{ .undef = ty });
+        const ptr_ty = ptr_val.typeOf(zcu);
+        if (ptr_ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) {
+            return dg.writeCValue(writer, .{ .undef = ptr_ty });
         }
 
         // Chase function values in order to be able to reference the original function.
-        if (Value.fromInterned(decl_val).getFunction(mod)) |func| {
-            _ = func;
-            _ = ptr_val;
-            _ = location;
-            @panic("TODO");
-        }
-        if (Value.fromInterned(decl_val).getExternFunc(mod)) |extern_func| {
-            _ = extern_func;
-            _ = ptr_val;
-            _ = location;
-            @panic("TODO");
-        }
+        if (decl_val.getFunction(zcu)) |func|
+            return dg.renderDeclValue(writer, ptr_val, func.owner_decl, location);
+        if (decl_val.getExternFunc(zcu)) |extern_func|
+            return dg.renderDeclValue(writer, ptr_val, extern_func.decl, location);
 
-        assert(Value.fromInterned(decl_val).getVariable(mod) == null);
+        assert(decl_val.getVariable(zcu) == null);
 
         // We shouldn't cast C function pointers as this is UB (when you call
         // them).  The analysis until now should ensure that the C function
         // pointers are compatible.  If they are not, then there is a bug
         // somewhere and we should let the C compiler tell us about it.
-        const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl_ty, mod);
-        if (need_typecast) {
+        const child_cty = (try dg.typeToCType(ptr_ty, .complete)).cast(CType.Payload.Child).?.data;
+        const decl_cty = try dg.typeToIndex(decl_ty, .complete);
+        const need_cast = child_cty != decl_cty and
+            (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function);
+        if (need_cast) {
             try writer.writeAll("((");
-            try dg.renderType(writer, ty);
+            try dg.renderType(writer, ptr_ty);
             try writer.writeByte(')');
         }
         try writer.writeByte('&');
         try renderAnonDeclName(writer, decl_val);
-        if (need_typecast) try writer.writeByte(')');
+        if (need_cast) try writer.writeByte(')');
 
         // Indicate that the anon decl should be rendered to the output so that
         // our reference above is not undefined.
         const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type;
-        const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val);
+        const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, anon_decl.val);
         if (!gop.found_existing) gop.value_ptr.* = .{};
 
         // Only insert an alignment entry if the alignment is greater than ABI
         // alignment. If there is already an entry, keep the greater alignment.
         const explicit_alignment = ptr_type.flags.alignment;
         if (explicit_alignment != .none) {
-            const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(mod);
+            const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu);
             if (explicit_alignment.compareStrict(.gt, abi_alignment)) {
-                const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val);
+                const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val);
                 aligned_gop.value_ptr.* = if (aligned_gop.found_existing)
                     aligned_gop.value_ptr.maxStrict(explicit_alignment)
                 else
@@ -646,41 +668,45 @@ pub const DeclGen = struct {
     fn renderDeclValue(
         dg: *DeclGen,
         writer: anytype,
-        ty: Type,
         val: Value,
         decl_index: InternPool.DeclIndex,
         location: ValueRenderLocation,
     ) error{ OutOfMemory, AnalysisFail }!void {
-        const mod = dg.module;
-        const decl = mod.declPtr(decl_index);
+        const zcu = dg.zcu;
+        const decl = zcu.declPtr(decl_index);
         assert(decl.has_tv);
 
         // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
-        if (ty.isPtrAtRuntime(mod) and !decl.typeOf(mod).isFnOrHasRuntimeBits(mod)) {
+        const ty = val.typeOf(zcu);
+        const decl_ty = decl.typeOf(zcu);
+        if (ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) {
             return dg.writeCValue(writer, .{ .undef = ty });
         }
 
         // Chase function values in order to be able to reference the original function.
-        if (decl.val.getFunction(mod)) |func| if (func.owner_decl != decl_index)
-            return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
-        if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
-            return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
+        if (decl.val.getFunction(zcu)) |func| if (func.owner_decl != decl_index)
+            return dg.renderDeclValue(writer, val, func.owner_decl, location);
+        if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)
+            return dg.renderDeclValue(writer, val, extern_func.decl, location);
 
-        if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
+        if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
 
         // We shouldn't cast C function pointers as this is UB (when you call
         // them).  The analysis until now should ensure that the C function
         // pointers are compatible.  If they are not, then there is a bug
         // somewhere and we should let the C compiler tell us about it.
-        const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.typeOf(mod), mod);
-        if (need_typecast) {
+        const child_cty = (try dg.typeToCType(ty, .complete)).cast(CType.Payload.Child).?.data;
+        const decl_cty = try dg.typeToIndex(decl_ty, .complete);
+        const need_cast = child_cty != decl_cty and
+            (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function);
+        if (need_cast) {
             try writer.writeAll("((");
             try dg.renderType(writer, ty);
             try writer.writeByte(')');
         }
         try writer.writeByte('&');
         try dg.renderDeclName(writer, decl_index, 0);
-        if (need_typecast) try writer.writeByte(')');
+        if (need_cast) try writer.writeByte(')');
     }
 
     /// Renders a "parent" pointer by recursing to the root decl/variable
@@ -691,31 +717,32 @@ pub const DeclGen = struct {
         ptr_val: InternPool.Index,
         location: ValueRenderLocation,
     ) error{ OutOfMemory, AnalysisFail }!void {
-        const mod = dg.module;
-        const ptr_ty = Type.fromInterned(mod.intern_pool.typeOf(ptr_val));
+        const zcu = dg.zcu;
+        const ip = &zcu.intern_pool;
+        const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val));
         const ptr_cty = try dg.typeToIndex(ptr_ty, .complete);
-        const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
+        const ptr_child_cty = dg.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data;
+        const ptr = ip.indexToKey(ptr_val).ptr;
         switch (ptr.addr) {
-            .decl => |d| try dg.renderDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), d, location),
-            .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), anon_decl, location),
+            .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location),
+            .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location),
             .int => |int| {
                 try writer.writeByte('(');
                 try dg.renderCType(writer, ptr_cty);
-                try writer.print("){x}", .{try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), .Other)});
+                try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)});
             },
             .eu_payload, .opt_payload => |base| {
-                const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(base));
-                const base_ty = ptr_base_ty.childType(mod);
+                const ptr_base_ty = Type.fromInterned(ip.typeOf(base));
+                const base_ty = ptr_base_ty.childType(zcu);
                 // Ensure complete type definition is visible before accessing fields.
                 _ = try dg.typeToIndex(base_ty, .complete);
                 const payload_ty = switch (ptr.addr) {
-                    .eu_payload => base_ty.errorUnionPayload(mod),
-                    .opt_payload => base_ty.optionalChild(mod),
+                    .eu_payload => base_ty.errorUnionPayload(zcu),
+                    .opt_payload => base_ty.optionalChild(zcu),
                     else => unreachable,
                 };
-                const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty);
-                const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete);
-                if (ptr_cty != ptr_payload_cty) {
+                const payload_cty = try dg.typeToIndex(payload_ty, .forward);
+                if (ptr_child_cty != payload_cty) {
                     try writer.writeByte('(');
                     try dg.renderCType(writer, ptr_cty);
                     try writer.writeByte(')');
@@ -725,70 +752,90 @@ pub const DeclGen = struct {
                 try writer.writeAll(")->payload");
             },
             .elem => |elem| {
-                const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base));
-                const elem_ty = ptr_base_ty.elemType2(mod);
-                const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty);
-                const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete);
-                if (ptr_cty != ptr_elem_cty) {
+                const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base));
+                const elem_ty = ptr_base_ty.elemType2(zcu);
+                const elem_cty = try dg.typeToIndex(elem_ty, .forward);
+                if (ptr_child_cty != elem_cty) {
                     try writer.writeByte('(');
                     try dg.renderCType(writer, ptr_cty);
                     try writer.writeByte(')');
                 }
                 try writer.writeAll("&(");
-                if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One)
+                if (ip.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One)
                     try writer.writeByte('*');
                 try dg.renderParentPtr(writer, elem.base, location);
                 try writer.print(")[{d}]", .{elem.index});
             },
             .field => |field| {
-                const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base));
-                const base_ty = ptr_base_ty.childType(mod);
+                const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base));
+                const base_ty = ptr_base_ty.childType(zcu);
                 // Ensure complete type definition is visible before accessing fields.
                 _ = try dg.typeToIndex(base_ty, .complete);
-                const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
-                    .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@as(usize, @intCast(field.index)), mod),
-                    .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
-                        .One, .Many, .C => unreachable,
-                        .Slice => switch (field.index) {
-                            Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
-                            Value.slice_len_index => Type.usize,
-                            else => unreachable,
-                        },
+                switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) {
+                    .begin => {
+                        const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete);
+                        if (ptr_cty != ptr_base_cty) {
+                            try writer.writeByte('(');
+                            try dg.renderCType(writer, ptr_cty);
+                            try writer.writeByte(')');
+                        }
+                        try dg.renderParentPtr(writer, field.base, location);
                     },
-                    else => unreachable,
-                };
-                const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty);
-                const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete);
-                if (ptr_cty != ptr_field_cty) {
-                    try writer.writeByte('(');
-                    try dg.renderCType(writer, ptr_cty);
-                    try writer.writeByte(')');
-                }
-                switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), mod)) {
-                    .begin => try dg.renderParentPtr(writer, field.base, location),
                     .field => |name| {
+                        const field_ty = switch (ip.indexToKey(base_ty.toIntern())) {
+                            .anon_struct_type,
+                            .struct_type,
+                            .union_type,
+                            => base_ty.structFieldType(@as(usize, @intCast(field.index)), zcu),
+                            .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
+                                .One, .Many, .C => unreachable,
+                                .Slice => switch (field.index) {
+                                    Value.slice_ptr_index => base_ty.slicePtrFieldType(zcu),
+                                    Value.slice_len_index => Type.usize,
+                                    else => unreachable,
+                                },
+                            },
+                            else => unreachable,
+                        };
+                        const field_cty = try dg.typeToIndex(field_ty, .forward);
+                        if (ptr_child_cty != field_cty) {
+                            try writer.writeByte('(');
+                            try dg.renderCType(writer, ptr_cty);
+                            try writer.writeByte(')');
+                        }
                         try writer.writeAll("&(");
                         try dg.renderParentPtr(writer, field.base, location);
                         try writer.writeAll(")->");
                         try dg.writeCValue(writer, name);
                     },
                     .byte_offset => |byte_offset| {
-                        const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
-                        const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
+                        const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8);
+                        const u8_ptr_cty = try dg.typeToIndex(u8_ptr_ty, .complete);
 
+                        if (ptr_cty != u8_ptr_cty) {
+                            try writer.writeByte('(');
+                            try dg.renderCType(writer, ptr_cty);
+                            try writer.writeByte(')');
+                        }
                         try writer.writeAll("((");
-                        try dg.renderType(writer, u8_ptr_ty);
+                        try dg.renderCType(writer, u8_ptr_cty);
                         try writer.writeByte(')');
                         try dg.renderParentPtr(writer, field.base, location);
                         try writer.print(" + {})", .{
-                            try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
+                            try dg.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset), .Other),
                         });
                     },
                     .end => {
+                        const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete);
+                        if (ptr_cty != ptr_base_cty) {
+                            try writer.writeByte('(');
+                            try dg.renderCType(writer, ptr_cty);
+                            try writer.writeByte(')');
+                        }
                         try writer.writeAll("((");
                         try dg.renderParentPtr(writer, field.base, location);
                         try writer.print(") + {})", .{
-                            try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),
+                            try dg.fmtIntLiteral(try zcu.intValue(Type.usize, 1), .Other),
                         });
                     },
                 }
@@ -800,215 +847,21 @@ pub const DeclGen = struct {
     fn renderValue(
         dg: *DeclGen,
         writer: anytype,
-        ty: Type,
         val: Value,
         location: ValueRenderLocation,
     ) error{ OutOfMemory, AnalysisFail }!void {
-        const mod = dg.module;
-        const ip = &mod.intern_pool;
+        const zcu = dg.zcu;
+        const ip = &zcu.intern_pool;
+        const target = &dg.mod.resolved_target.result;
 
-        const target = mod.getTarget();
         const initializer_type: ValueRenderLocation = switch (location) {
             .StaticInitializer => .StaticInitializer,
             else => .Initializer,
         };
 
-        const safety_on = switch (mod.optimizeMode()) {
-            .Debug, .ReleaseSafe => true,
-            .ReleaseFast, .ReleaseSmall => false,
-        };
-
-        if (val.isUndefDeep(mod)) {
-            switch (ty.zigTypeTag(mod)) {
-                .Bool => {
-                    if (safety_on) {
-                        return writer.writeAll("0xaa");
-                    } else {
-                        return writer.writeAll("false");
-                    }
-                },
-                .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),
-                .Float => {
-                    const bits = ty.floatBits(target);
-                    // All unsigned ints matching float types are pre-allocated.
-                    const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
-
-                    try writer.writeAll("zig_make_");
-                    try dg.renderTypeForBuiltinFnName(writer, ty);
-                    try writer.writeByte('(');
-                    switch (bits) {
-                        16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
-                        32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
-                        64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
-                        80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
-                        128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
-                        else => unreachable,
-                    }
-                    try writer.writeAll(", ");
-                    try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument);
-                    return writer.writeByte(')');
-                },
-                .Pointer => if (ty.isSlice(mod)) {
-                    if (!location.isInitializer()) {
-                        try writer.writeByte('(');
-                        try dg.renderType(writer, ty);
-                        try writer.writeByte(')');
-                    }
-
-                    try writer.writeAll("{(");
-                    const ptr_ty = ty.slicePtrFieldType(mod);
-                    try dg.renderType(writer, ptr_ty);
-                    return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
-                } else {
-                    try writer.writeAll("((");
-                    try dg.renderType(writer, ty);
-                    return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
-                },
-                .Optional => {
-                    const payload_ty = ty.optionalChild(mod);
-
-                    if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
-                        return dg.renderValue(writer, Type.bool, val, location);
-                    }
-
-                    if (ty.optionalReprIsPayload(mod)) {
-                        return dg.renderValue(writer, payload_ty, val, location);
-                    }
-
-                    if (!location.isInitializer()) {
-                        try writer.writeByte('(');
-                        try dg.renderType(writer, ty);
-                        try writer.writeByte(')');
-                    }
-
-                    try writer.writeAll("{ .payload = ");
-                    try dg.renderValue(writer, payload_ty, val, initializer_type);
-                    try writer.writeAll(", .is_null = ");
-                    try dg.renderValue(writer, Type.bool, val, initializer_type);
-                    return writer.writeAll(" }");
-                },
-                .Struct => switch (ty.containerLayout(mod)) {
-                    .auto, .@"extern" => {
-                        if (!location.isInitializer()) {
-                            try writer.writeByte('(');
-                            try dg.renderType(writer, ty);
-                            try writer.writeByte(')');
-                        }
-
-                        try writer.writeByte('{');
-                        var empty = true;
-                        for (0..ty.structFieldCount(mod)) |field_index| {
-                            if (ty.structFieldIsComptime(field_index, mod)) continue;
-                            const field_ty = ty.structFieldType(field_index, mod);
-                            if (!field_ty.hasRuntimeBits(mod)) continue;
-
-                            if (!empty) try writer.writeByte(',');
-                            try dg.renderValue(writer, field_ty, val, initializer_type);
-
-                            empty = false;
-                        }
-
-                        return writer.writeByte('}');
-                    },
-                    .@"packed" => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}),
-                },
-                .Union => {
-                    if (!location.isInitializer()) {
-                        try writer.writeByte('(');
-                        try dg.renderType(writer, ty);
-                        try writer.writeByte(')');
-                    }
-
-                    try writer.writeByte('{');
-                    if (ty.unionTagTypeSafety(mod)) |tag_ty| {
-                        const layout = ty.unionGetLayout(mod);
-                        if (layout.tag_size != 0) {
-                            try writer.writeAll(" .tag = ");
-                            try dg.renderValue(writer, tag_ty, val, initializer_type);
-                        }
-                        if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
-                        if (layout.tag_size != 0) try writer.writeByte(',');
-                        try writer.writeAll(" .payload = {");
-                    }
-                    const union_obj = mod.typeToUnion(ty).?;
-                    for (0..union_obj.field_types.len) |field_index| {
-                        const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
-                        if (!field_ty.hasRuntimeBits(mod)) continue;
-                        try dg.renderValue(writer, field_ty, val, initializer_type);
-                        break;
-                    }
-                    if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
-                    return writer.writeByte('}');
-                },
-                .ErrorUnion => {
-                    const payload_ty = ty.errorUnionPayload(mod);
-                    const error_ty = ty.errorUnionSet(mod);
-
-                    if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
-                        return dg.renderValue(writer, error_ty, val, location);
-                    }
-
-                    if (!location.isInitializer()) {
-                        try writer.writeByte('(');
-                        try dg.renderType(writer, ty);
-                        try writer.writeByte(')');
-                    }
-
-                    try writer.writeAll("{ .payload = ");
-                    try dg.renderValue(writer, payload_ty, val, initializer_type);
-                    try writer.writeAll(", .error = ");
-                    try dg.renderValue(writer, error_ty, val, initializer_type);
-                    return writer.writeAll(" }");
-                },
-                .Array, .Vector => {
-                    const ai = ty.arrayInfo(mod);
-                    if (ai.elem_type.eql(Type.u8, mod)) {
-                        const c_len = ty.arrayLenIncludingSentinel(mod);
-                        var literal = stringLiteral(writer, c_len);
-                        try literal.start();
-                        var index: u64 = 0;
-                        while (index < c_len) : (index += 1)
-                            try literal.writeChar(0xaa);
-                        return literal.end();
-                    } else {
-                        if (!location.isInitializer()) {
-                            try writer.writeByte('(');
-                            try dg.renderType(writer, ty);
-                            try writer.writeByte(')');
-                        }
-
-                        try writer.writeByte('{');
-                        const c_len = ty.arrayLenIncludingSentinel(mod);
-                        var index: u64 = 0;
-                        while (index < c_len) : (index += 1) {
-                            if (index > 0) try writer.writeAll(", ");
-                            try dg.renderValue(writer, ty.childType(mod), val, initializer_type);
-                        }
-                        return writer.writeByte('}');
-                    }
-                },
-                .ComptimeInt,
-                .ComptimeFloat,
-                .Type,
-                .EnumLiteral,
-                .Void,
-                .NoReturn,
-                .Undefined,
-                .Null,
-                .Opaque,
-                => unreachable,
-
-                .Fn,
-                .Frame,
-                .AnyFrame,
-                => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
-                    @tagName(tag),
-                }),
-            }
-            unreachable;
-        }
-
-        switch (ip.indexToKey(val.ip_index)) {
+        const ty = val.typeOf(zcu);
+        if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location);
+        switch (ip.indexToKey(val.toIntern())) {
             // types, not values
             .int_type,
             .ptr_type,
@@ -1050,26 +903,28 @@ pub const DeclGen = struct {
             .empty_enum_value,
             => unreachable, // non-runtime values
             .int => |int| switch (int.storage) {
-                .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
+                .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}),
                 .lazy_align, .lazy_size => {
                     try writer.writeAll("((");
                     try dg.renderType(writer, ty);
-                    return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
+                    try writer.print("){x})", .{try dg.fmtIntLiteral(
+                        try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)),
+                        .Other,
+                    )});
                 },
             },
             .err => |err| try writer.print("zig_error_{}", .{
                 fmtIdent(ip.stringToSlice(err.name)),
             }),
             .error_union => |error_union| {
-                const payload_ty = ty.errorUnionPayload(mod);
-                const error_ty = ty.errorUnionSet(mod);
-                const err_int_ty = try mod.errorIntType();
-                if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+                const payload_ty = ty.errorUnionPayload(zcu);
+                const error_ty = ty.errorUnionSet(zcu);
+                const err_int_ty = try zcu.errorIntType();
+                if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
                     switch (error_union.val) {
                         .err_name => |err_name| return dg.renderValue(
                             writer,
-                            error_ty,
-                            Value.fromInterned((try mod.intern(.{ .err = .{
+                            Value.fromInterned((try zcu.intern(.{ .err = .{
                                 .ty = error_ty.toIntern(),
                                 .name = err_name,
                             } }))),
@@ -1077,8 +932,7 @@ pub const DeclGen = struct {
                         ),
                         .payload => return dg.renderValue(
                             writer,
-                            err_int_ty,
-                            try mod.intValue(err_int_ty, 0),
+                            try zcu.intValue(err_int_ty, 0),
                             location,
                         ),
                     }
@@ -1093,9 +947,8 @@ pub const DeclGen = struct {
                 try writer.writeAll("{ .payload = ");
                 try dg.renderValue(
                     writer,
-                    payload_ty,
                     Value.fromInterned(switch (error_union.val) {
-                        .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
+                        .err_name => (try zcu.undefValue(payload_ty)).toIntern(),
                         .payload => |payload| payload,
                     }),
                     initializer_type,
@@ -1104,8 +957,7 @@ pub const DeclGen = struct {
                 switch (error_union.val) {
                     .err_name => |err_name| try dg.renderValue(
                         writer,
-                        error_ty,
-                        Value.fromInterned((try mod.intern(.{ .err = .{
+                        Value.fromInterned((try zcu.intern(.{ .err = .{
                             .ty = error_ty.toIntern(),
                             .name = err_name,
                         } }))),
@@ -1113,24 +965,23 @@ pub const DeclGen = struct {
                     ),
                     .payload => try dg.renderValue(
                         writer,
-                        err_int_ty,
-                        try mod.intValue(err_int_ty, 0),
+                        try zcu.intValue(err_int_ty, 0),
                         location,
                     ),
                 }
                 try writer.writeAll(" }");
             },
-            .enum_tag => {
-                const enum_tag = ip.indexToKey(val.ip_index).enum_tag;
-                const int_tag_ty = ip.typeOf(enum_tag.int);
-                try dg.renderValue(writer, Type.fromInterned(int_tag_ty), Value.fromInterned(enum_tag.int), location);
-            },
+            .enum_tag => |enum_tag| try dg.renderValue(
+                writer,
+                Value.fromInterned(enum_tag.int),
+                location,
+            ),
             .float => {
-                const bits = ty.floatBits(target);
-                const f128_val = val.toFloat(f128, mod);
+                const bits = ty.floatBits(target.*);
+                const f128_val = val.toFloat(f128, zcu);
 
                 // All unsigned ints matching float types are pre-allocated.
-                const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
+                const repr_ty = zcu.intType(.unsigned, bits) catch unreachable;
 
                 assert(bits <= 128);
                 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
@@ -1141,26 +992,24 @@ pub const DeclGen = struct {
                 };
 
                 switch (bits) {
-                    16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, mod)))),
-                    32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, mod)))),
-                    64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, mod)))),
-                    80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, mod)))),
+                    16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))),
+                    32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))),
+                    64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))),
+                    80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))),
                     128 => repr_val_big.set(@as(u128, @bitCast(f128_val))),
                     else => unreachable,
                 }
 
-                const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
-
                 var empty = true;
                 if (std.math.isFinite(f128_val)) {
                     try writer.writeAll("zig_make_");
                     try dg.renderTypeForBuiltinFnName(writer, ty);
                     try writer.writeByte('(');
                     switch (bits) {
-                        16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
-                        32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
-                        64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
-                        80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
+                        16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}),
+                        32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}),
+                        64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}),
+                        80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}),
                         128 => try writer.print("{x}", .{f128_val}),
                         else => unreachable,
                     }
@@ -1200,17 +1049,20 @@ pub const DeclGen = struct {
                     if (std.math.isNan(f128_val)) switch (bits) {
                         // We only actually need to pass the significand, but it will get
                         // properly masked anyway, so just pass the whole value.
-                        16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, mod)))}),
-                        32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, mod)))}),
-                        64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, mod)))}),
-                        80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, mod)))}),
+                        16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}),
+                        32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}),
+                        64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}),
+                        80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}),
                         128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}),
                         else => unreachable,
                     };
                     try writer.writeAll(", ");
                     empty = false;
                 }
-                try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});
+                try writer.print("{x}", .{try dg.fmtIntLiteral(
+                    try zcu.intValue_big(repr_ty, repr_val_big.toConst()),
+                    location,
+                )});
                 if (!empty) try writer.writeByte(')');
             },
             .slice => |slice| {
@@ -1220,42 +1072,39 @@ pub const DeclGen = struct {
                     try writer.writeByte(')');
                 }
                 try writer.writeByte('{');
-                try dg.renderValue(writer, ty.slicePtrFieldType(mod), Value.fromInterned(slice.ptr), initializer_type);
+                try dg.renderValue(writer, Value.fromInterned(slice.ptr), initializer_type);
                 try writer.writeAll(", ");
-                try dg.renderValue(writer, Type.usize, Value.fromInterned(slice.len), initializer_type);
+                try dg.renderValue(writer, Value.fromInterned(slice.len), initializer_type);
                 try writer.writeByte('}');
             },
             .ptr => |ptr| switch (ptr.addr) {
-                .decl => |d| try dg.renderDeclValue(writer, ty, val, d, location),
-                .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ty, val, decl_val, location),
+                .decl => |d| try dg.renderDeclValue(writer, val, d, location),
+                .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location),
                 .int => |int| {
                     try writer.writeAll("((");
                     try dg.renderType(writer, ty);
-                    try writer.print("){x})", .{
-                        try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), location),
-                    });
+                    try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)});
                 },
                 .eu_payload,
                 .opt_payload,
                 .elem,
                 .field,
-                => try dg.renderParentPtr(writer, val.ip_index, location),
+                => try dg.renderParentPtr(writer, val.toIntern(), location),
                 .comptime_field, .comptime_alloc => unreachable,
             },
             .opt => |opt| {
-                const payload_ty = ty.optionalChild(mod);
+                const payload_ty = ty.optionalChild(zcu);
 
                 const is_null_val = Value.makeBool(opt.val == .none);
-                if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
-                    return dg.renderValue(writer, Type.bool, is_null_val, location);
+                if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
+                    return dg.renderValue(writer, is_null_val, location);
 
-                if (ty.optionalReprIsPayload(mod)) return dg.renderValue(
+                if (ty.optionalReprIsPayload(zcu)) return dg.renderValue(
                     writer,
-                    payload_ty,
                     switch (opt.val) {
-                        .none => switch (payload_ty.zigTypeTag(mod)) {
-                            .ErrorSet => try mod.intValue(try mod.errorIntType(), 0),
-                            .Pointer => try mod.getCoerced(val, payload_ty),
+                        .none => switch (payload_ty.zigTypeTag(zcu)) {
+                            .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0),
+                            .Pointer => try zcu.getCoerced(val, payload_ty),
                             else => unreachable,
                         },
                         else => |payload| Value.fromInterned(payload),
@@ -1270,15 +1119,19 @@ pub const DeclGen = struct {
                 }
 
                 try writer.writeAll("{ .payload = ");
-                try dg.renderValue(writer, payload_ty, Value.fromInterned(switch (opt.val) {
-                    .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
-                    else => |payload| payload,
-                }), initializer_type);
+                switch (opt.val) {
+                    .none => try dg.renderUndefValue(writer, payload_ty, initializer_type),
+                    else => |payload| try dg.renderValue(
+                        writer,
+                        Value.fromInterned(payload),
+                        initializer_type,
+                    ),
+                }
                 try writer.writeAll(", .is_null = ");
-                try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
+                try dg.renderValue(writer, is_null_val, initializer_type);
                 try writer.writeAll(" }");
             },
-            .aggregate => switch (ip.indexToKey(ty.ip_index)) {
+            .aggregate => switch (ip.indexToKey(ty.toIntern())) {
                 .array_type, .vector_type => {
                     if (location == .FunctionArgument) {
                         try writer.writeByte('(');
@@ -1287,21 +1140,21 @@ pub const DeclGen = struct {
                     }
                     // Fall back to generic implementation.
 
-                    const ai = ty.arrayInfo(mod);
-                    if (ai.elem_type.eql(Type.u8, mod)) {
-                        var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(mod));
+                    const ai = ty.arrayInfo(zcu);
+                    if (ai.elem_type.eql(Type.u8, zcu)) {
+                        var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu));
                         try literal.start();
                         var index: usize = 0;
                         while (index < ai.len) : (index += 1) {
-                            const elem_val = try val.elemValue(mod, index);
-                            const elem_val_u8: u8 = if (elem_val.isUndef(mod))
+                            const elem_val = try val.elemValue(zcu, index);
+                            const elem_val_u8: u8 = if (elem_val.isUndef(zcu))
                                 undefPattern(u8)
                             else
-                                @intCast(elem_val.toUnsignedInt(mod));
+                                @intCast(elem_val.toUnsignedInt(zcu));
                             try literal.writeChar(elem_val_u8);
                         }
                         if (ai.sentinel) |s| {
-                            const s_u8: u8 = @intCast(s.toUnsignedInt(mod));
+                            const s_u8: u8 = @intCast(s.toUnsignedInt(zcu));
                             if (s_u8 != 0) try literal.writeChar(s_u8);
                         }
                         try literal.end();
@@ -1310,12 +1163,12 @@ pub const DeclGen = struct {
                         var index: usize = 0;
                         while (index < ai.len) : (index += 1) {
                             if (index != 0) try writer.writeByte(',');
-                            const elem_val = try val.elemValue(mod, index);
-                            try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
+                            const elem_val = try val.elemValue(zcu, index);
+                            try dg.renderValue(writer, elem_val, initializer_type);
                         }
                         if (ai.sentinel) |s| {
                             if (index != 0) try writer.writeByte(',');
-                            try dg.renderValue(writer, ai.elem_type, s, initializer_type);
+                            try dg.renderValue(writer, s, initializer_type);
                         }
                         try writer.writeByte('}');
                     }
@@ -1333,19 +1186,21 @@ pub const DeclGen = struct {
                         const comptime_val = tuple.values.get(ip)[field_index];
                         if (comptime_val != .none) continue;
                         const field_ty = Type.fromInterned(tuple.types.get(ip)[field_index]);
-                        if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                        if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                         if (!empty) try writer.writeByte(',');
 
-                        const field_val = Value.fromInterned(switch (ip.indexToKey(val.ip_index).aggregate.storage) {
-                            .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
-                                .ty = field_ty.toIntern(),
-                                .storage = .{ .u64 = bytes[field_index] },
-                            } }),
-                            .elems => |elems| elems[field_index],
-                            .repeated_elem => |elem| elem,
-                        });
-                        try dg.renderValue(writer, field_ty, field_val, initializer_type);
+                        const field_val = Value.fromInterned(
+                            switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+                                .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
+                                    .ty = field_ty.toIntern(),
+                                    .storage = .{ .u64 = bytes[field_index] },
+                                } }),
+                                .elems => |elems| elems[field_index],
+                                .repeated_elem => |elem| elem,
+                            },
+                        );
+                        try dg.renderValue(writer, field_val, initializer_type);
 
                         empty = false;
                     }
@@ -1366,43 +1221,43 @@ pub const DeclGen = struct {
                             for (0..struct_type.field_types.len) |field_index| {
                                 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
                                 if (struct_type.fieldIsComptime(ip, field_index)) continue;
-                                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                                 if (!empty) try writer.writeByte(',');
-                                const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
-                                    .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
+                                const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+                                    .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
                                         .ty = field_ty.toIntern(),
                                         .storage = .{ .u64 = bytes[field_index] },
                                     } }),
                                     .elems => |elems| elems[field_index],
                                     .repeated_elem => |elem| elem,
                                 };
-                                try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type);
+                                try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type);
 
                                 empty = false;
                             }
                             try writer.writeByte('}');
                         },
                         .@"packed" => {
-                            const int_info = ty.intInfo(mod);
+                            const int_info = ty.intInfo(zcu);
 
                             const bits = Type.smallestUnsignedBits(int_info.bits - 1);
-                            const bit_offset_ty = try mod.intType(.unsigned, bits);
+                            const bit_offset_ty = try zcu.intType(.unsigned, bits);
 
                             var bit_offset: u64 = 0;
                             var eff_num_fields: usize = 0;
 
                             for (0..struct_type.field_types.len) |field_index| {
                                 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
-                                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
                                 eff_num_fields += 1;
                             }
 
                             if (eff_num_fields == 0) {
                                 try writer.writeByte('(');
-                                try dg.renderValue(writer, ty, Value.undef, initializer_type);
+                                try dg.renderUndefValue(writer, ty, initializer_type);
                                 try writer.writeByte(')');
-                            } else if (ty.bitSize(mod) > 64) {
+                            } else if (ty.bitSize(zcu) > 64) {
                                 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
                                 var num_or = eff_num_fields - 1;
                                 while (num_or > 0) : (num_or -= 1) {
@@ -1415,10 +1270,10 @@ pub const DeclGen = struct {
                                 var needs_closing_paren = false;
                                 for (0..struct_type.field_types.len) |field_index| {
                                     const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
-                                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                    if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
-                                    const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
-                                        .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
+                                    const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+                                        .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
                                             .ty = field_ty.toIntern(),
                                             .storage = .{ .u64 = bytes[field_index] },
                                         } }),
@@ -1432,8 +1287,7 @@ pub const DeclGen = struct {
                                         try writer.writeByte('(');
                                         try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
                                         try writer.writeAll(", ");
-                                        const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
-                                        try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
+                                        try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
                                         try writer.writeByte(')');
                                     } else {
                                         try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
@@ -1442,7 +1296,7 @@ pub const DeclGen = struct {
                                     if (needs_closing_paren) try writer.writeByte(')');
                                     if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
 
-                                    bit_offset += field_ty.bitSize(mod);
+                                    bit_offset += field_ty.bitSize(zcu);
                                     needs_closing_paren = true;
                                     eff_index += 1;
                                 }
@@ -1452,15 +1306,15 @@ pub const DeclGen = struct {
                                 var empty = true;
                                 for (0..struct_type.field_types.len) |field_index| {
                                     const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
-                                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                                    if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                                     if (!empty) try writer.writeAll(" | ");
                                     try writer.writeByte('(');
                                     try dg.renderType(writer, ty);
                                     try writer.writeByte(')');
 
-                                    const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) {
-                                        .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{
+                                    const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
+                                        .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{
                                             .ty = field_ty.toIntern(),
                                             .storage = .{ .u64 = bytes[field_index] },
                                         } }),
@@ -1469,15 +1323,14 @@ pub const DeclGen = struct {
                                     };
 
                                     if (bit_offset != 0) {
-                                        try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);
+                                        try dg.renderValue(writer, Value.fromInterned(field_val), .Other);
                                         try writer.writeAll(" << ");
-                                        const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
-                                        try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
+                                        try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
                                     } else {
-                                        try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other);
+                                        try dg.renderValue(writer, Value.fromInterned(field_val), .Other);
                                     }
 
-                                    bit_offset += field_ty.bitSize(mod);
+                                    bit_offset += field_ty.bitSize(zcu);
                                     empty = false;
                                 }
                                 try writer.writeByte(')');
@@ -1488,9 +1341,9 @@ pub const DeclGen = struct {
                 else => unreachable,
             },
             .un => |un| {
-                const union_obj = mod.typeToUnion(ty).?;
+                const union_obj = zcu.typeToUnion(ty).?;
                 if (un.tag == .none) {
-                    const backing_ty = try ty.unionBackingType(mod);
+                    const backing_ty = try ty.unionBackingType(zcu);
                     switch (union_obj.getLayout(ip)) {
                         .@"packed" => {
                             if (!location.isInitializer()) {
@@ -1498,20 +1351,20 @@ pub const DeclGen = struct {
                                 try dg.renderType(writer, backing_ty);
                                 try writer.writeByte(')');
                             }
-                            try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type);
+                            try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
                         },
                         .@"extern" => {
                             if (location == .StaticInitializer) {
                                 return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{});
                             }
 
-                            const ptr_ty = try mod.singleConstPtrType(ty);
+                            const ptr_ty = try zcu.singleConstPtrType(ty);
                             try writer.writeAll("*((");
                             try dg.renderType(writer, ptr_ty);
                             try writer.writeAll(")(");
                             try dg.renderType(writer, backing_ty);
                             try writer.writeAll("){");
-                            try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type);
+                            try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
                             try writer.writeAll("})");
                         },
                         else => unreachable,
@@ -1523,21 +1376,21 @@ pub const DeclGen = struct {
                         try writer.writeByte(')');
                     }
 
-                    const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
+                    const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
                     const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
                     const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
                     if (union_obj.getLayout(ip) == .@"packed") {
-                        if (field_ty.hasRuntimeBits(mod)) {
-                            if (field_ty.isPtrAtRuntime(mod)) {
+                        if (field_ty.hasRuntimeBits(zcu)) {
+                            if (field_ty.isPtrAtRuntime(zcu)) {
                                 try writer.writeByte('(');
                                 try dg.renderType(writer, ty);
                                 try writer.writeByte(')');
-                            } else if (field_ty.zigTypeTag(mod) == .Float) {
+                            } else if (field_ty.zigTypeTag(zcu) == .Float) {
                                 try writer.writeByte('(');
                                 try dg.renderType(writer, ty);
                                 try writer.writeByte(')');
                             }
-                            try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type);
+                            try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
                         } else {
                             try writer.writeAll("0");
                         }
@@ -1545,30 +1398,236 @@ pub const DeclGen = struct {
                     }
 
                     try writer.writeByte('{');
-                    if (ty.unionTagTypeSafety(mod)) |tag_ty| {
-                        const layout = mod.getUnionLayout(union_obj);
+                    if (ty.unionTagTypeSafety(zcu)) |_| {
+                        const layout = zcu.getUnionLayout(union_obj);
                         if (layout.tag_size != 0) {
                             try writer.writeAll(" .tag = ");
-                            try dg.renderValue(writer, tag_ty, Value.fromInterned(un.tag), initializer_type);
+                            try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type);
                         }
-                        if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
+                        if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}');
                         if (layout.tag_size != 0) try writer.writeByte(',');
                         try writer.writeAll(" .payload = {");
                     }
-                    if (field_ty.hasRuntimeBits(mod)) {
+                    if (field_ty.hasRuntimeBits(zcu)) {
                         try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))});
-                        try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type);
+                        try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type);
                         try writer.writeByte(' ');
                     } else for (0..union_obj.field_types.len) |this_field_index| {
                         const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]);
-                        if (!this_field_ty.hasRuntimeBits(mod)) continue;
-                        try dg.renderValue(writer, this_field_ty, Value.undef, initializer_type);
+                        if (!this_field_ty.hasRuntimeBits(zcu)) continue;
+                        try dg.renderUndefValue(writer, this_field_ty, initializer_type);
                         break;
                     }
-                    if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
+                    if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}');
+                    try writer.writeByte('}');
+                }
+            },
+        }
+    }
+
+    fn renderUndefValue(
+        dg: *DeclGen,
+        writer: anytype,
+        ty: Type,
+        location: ValueRenderLocation,
+    ) error{ OutOfMemory, AnalysisFail }!void {
+        const zcu = dg.zcu;
+        const ip = &zcu.intern_pool;
+        const target = &dg.mod.resolved_target.result;
+
+        const initializer_type: ValueRenderLocation = switch (location) {
+            .StaticInitializer => .StaticInitializer,
+            else => .Initializer,
+        };
+
+        const safety_on = switch (zcu.optimizeMode()) {
+            .Debug, .ReleaseSafe => true,
+            .ReleaseFast, .ReleaseSmall => false,
+        };
+
+        switch (ty.zigTypeTag(zcu)) {
+            .Bool => try writer.writeAll(if (safety_on) "0xaa" else "false"),
+            .Int, .Enum, .ErrorSet => try writer.print("{x}", .{
+                try dg.fmtIntLiteral(try zcu.undefValue(ty), location),
+            }),
+            .Float => {
+                const bits = ty.floatBits(target.*);
+                // All unsigned ints matching float types are pre-allocated.
+                const repr_ty = zcu.intType(.unsigned, bits) catch unreachable;
+
+                try writer.writeAll("zig_make_");
+                try dg.renderTypeForBuiltinFnName(writer, ty);
+                try writer.writeByte('(');
+                switch (bits) {
+                    16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}),
+                    32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}),
+                    64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}),
+                    80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}),
+                    128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}),
+                    else => unreachable,
+                }
+                try writer.writeAll(", ");
+                try dg.renderUndefValue(writer, repr_ty, .FunctionArgument);
+                try writer.writeByte(')');
+            },
+            .Pointer => if (ty.isSlice(zcu)) {
+                if (!location.isInitializer()) {
+                    try writer.writeByte('(');
+                    try dg.renderType(writer, ty);
+                    try writer.writeByte(')');
+                }
+
+                try writer.writeAll("{(");
+                const ptr_ty = ty.slicePtrFieldType(zcu);
+                try dg.renderType(writer, ptr_ty);
+                try writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)});
+            } else {
+                try writer.writeAll("((");
+                try dg.renderType(writer, ty);
+                try writer.print("){x})", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)});
+            },
+            .Optional => {
+                const payload_ty = ty.optionalChild(zcu);
+
+                if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
+                    return dg.renderUndefValue(writer, Type.bool, location);
+                }
+
+                if (ty.optionalReprIsPayload(zcu)) {
+                    return dg.renderUndefValue(writer, payload_ty, location);
+                }
+
+                if (!location.isInitializer()) {
+                    try writer.writeByte('(');
+                    try dg.renderType(writer, ty);
+                    try writer.writeByte(')');
+                }
+
+                try writer.writeAll("{ .payload = ");
+                try dg.renderUndefValue(writer, payload_ty, initializer_type);
+                try writer.writeAll(", .is_null = ");
+                try dg.renderUndefValue(writer, Type.bool, initializer_type);
+                try writer.writeAll(" }");
+            },
+            .Struct => switch (ty.containerLayout(zcu)) {
+                .auto, .@"extern" => {
+                    if (!location.isInitializer()) {
+                        try writer.writeByte('(');
+                        try dg.renderType(writer, ty);
+                        try writer.writeByte(')');
+                    }
+
+                    try writer.writeByte('{');
+                    var empty = true;
+                    for (0..ty.structFieldCount(zcu)) |field_index| {
+                        if (ty.structFieldIsComptime(field_index, zcu)) continue;
+                        const field_ty = ty.structFieldType(field_index, zcu);
+                        if (!field_ty.hasRuntimeBits(zcu)) continue;
+
+                        if (!empty) try writer.writeByte(',');
+                        try dg.renderUndefValue(writer, field_ty, initializer_type);
+
+                        empty = false;
+                    }
+
                     try writer.writeByte('}');
+                },
+                .@"packed" => try writer.print("{x}", .{
+                    try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other),
+                }),
+            },
+            .Union => {
+                if (!location.isInitializer()) {
+                    try writer.writeByte('(');
+                    try dg.renderType(writer, ty);
+                    try writer.writeByte(')');
                 }
+
+                try writer.writeByte('{');
+                if (ty.unionTagTypeSafety(zcu)) |tag_ty| {
+                    const layout = ty.unionGetLayout(zcu);
+                    if (layout.tag_size != 0) {
+                        try writer.writeAll(" .tag = ");
+                        try dg.renderUndefValue(writer, tag_ty, initializer_type);
+                    }
+                    if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}');
+                    if (layout.tag_size != 0) try writer.writeByte(',');
+                    try writer.writeAll(" .payload = {");
+                }
+                const union_obj = zcu.typeToUnion(ty).?;
+                for (0..union_obj.field_types.len) |field_index| {
+                    const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
+                    if (!field_ty.hasRuntimeBits(zcu)) continue;
+                    try dg.renderUndefValue(writer, field_ty, initializer_type);
+                    break;
+                }
+                if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}');
+                try writer.writeByte('}');
             },
+            .ErrorUnion => {
+                const payload_ty = ty.errorUnionPayload(zcu);
+                const error_ty = ty.errorUnionSet(zcu);
+
+                if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
+                    return dg.renderUndefValue(writer, error_ty, location);
+                }
+
+                if (!location.isInitializer()) {
+                    try writer.writeByte('(');
+                    try dg.renderType(writer, ty);
+                    try writer.writeByte(')');
+                }
+
+                try writer.writeAll("{ .payload = ");
+                try dg.renderUndefValue(writer, payload_ty, initializer_type);
+                try writer.writeAll(", .error = ");
+                try dg.renderUndefValue(writer, error_ty, initializer_type);
+                try writer.writeAll(" }");
+            },
+            .Array, .Vector => {
+                const ai = ty.arrayInfo(zcu);
+                if (ai.elem_type.eql(Type.u8, zcu)) {
+                    const c_len = ty.arrayLenIncludingSentinel(zcu);
+                    var literal = stringLiteral(writer, c_len);
+                    try literal.start();
+                    var index: u64 = 0;
+                    while (index < c_len) : (index += 1)
+                        try literal.writeChar(0xaa);
+                    try literal.end();
+                } else {
+                    if (!location.isInitializer()) {
+                        try writer.writeByte('(');
+                        try dg.renderType(writer, ty);
+                        try writer.writeByte(')');
+                    }
+
+                    try writer.writeByte('{');
+                    const c_len = ty.arrayLenIncludingSentinel(zcu);
+                    var index: u64 = 0;
+                    while (index < c_len) : (index += 1) {
+                        if (index > 0) try writer.writeAll(", ");
+                        try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type);
+                    }
+                    try writer.writeByte('}');
+                }
+            },
+            .ComptimeInt,
+            .ComptimeFloat,
+            .Type,
+            .EnumLiteral,
+            .Void,
+            .NoReturn,
+            .Undefined,
+            .Null,
+            .Opaque,
+            => unreachable,
+
+            .Fn,
+            .Frame,
+            .AnyFrame,
+            => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
+                @tagName(tag),
+            }),
         }
     }
 
@@ -1583,14 +1642,14 @@ pub const DeclGen = struct {
         },
     ) !void {
         const store = &dg.ctypes.set;
-        const mod = dg.module;
-        const ip = &mod.intern_pool;
+        const zcu = dg.zcu;
+        const ip = &zcu.intern_pool;
 
-        const fn_decl = mod.declPtr(fn_decl_index);
-        const fn_ty = fn_decl.typeOf(mod);
+        const fn_decl = zcu.declPtr(fn_decl_index);
+        const fn_ty = fn_decl.typeOf(zcu);
         const fn_cty_idx = try dg.typeToIndex(fn_ty, kind);
 
-        const fn_info = mod.typeToFunc(fn_ty).?;
+        const fn_info = zcu.typeToFunc(fn_ty).?;
         if (fn_info.cc == .Naked) {
             switch (kind) {
                 .forward => try w.writeAll("zig_naked_decl "),
@@ -1598,11 +1657,11 @@ pub const DeclGen = struct {
                 else => unreachable,
             }
         }
-        if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold)
+        if (fn_decl.val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold)
             try w.writeAll("zig_cold ");
         if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
 
-        var trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
+        var trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, fn_cty_idx, .suffix, .{});
 
         if (toCallingConvention(fn_info.cc)) |call_conv| {
             try w.print("{}zig_callconv({s})", .{ trailing, call_conv });
@@ -1629,7 +1688,7 @@ pub const DeclGen = struct {
         try renderTypeSuffix(
             dg.pass,
             store.*,
-            mod,
+            zcu,
             w,
             fn_cty_idx,
             .suffix,
@@ -1647,11 +1706,11 @@ pub const DeclGen = struct {
                 }
                 switch (name) {
                     .export_index => |export_index| mangled: {
-                        const maybe_exports = mod.decl_exports.get(fn_decl_index);
+                        const maybe_exports = zcu.decl_exports.get(fn_decl_index);
                         const external_name = ip.stringToSlice(
                             if (maybe_exports) |exports|
                                 exports.items[export_index].opts.name
-                            else if (fn_decl.isExtern(mod))
+                            else if (fn_decl.isExtern(zcu))
                                 fn_decl.name
                             else
                                 break :mangled,
@@ -1694,15 +1753,15 @@ pub const DeclGen = struct {
     }
 
     fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index {
-        return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind);
+        return dg.ctypes.typeToIndex(dg.gpa, ty, dg.zcu, dg.mod, kind);
     }
 
     fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType {
-        return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind);
+        return dg.ctypes.typeToCType(dg.gpa, ty, dg.zcu, dg.mod, kind);
     }
 
     fn byteSize(dg: *DeclGen, cty: CType) u64 {
-        return cty.byteSize(dg.ctypes.set, dg.module.getTarget());
+        return cty.byteSize(dg.ctypes.set, dg.mod);
     }
 
     /// Renders a type as a single identifier, generating intermediate typedefs
@@ -1722,9 +1781,9 @@ pub const DeclGen = struct {
 
     fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
         const store = &dg.ctypes.set;
-        const mod = dg.module;
-        _ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{});
-        try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{});
+        const zcu = dg.zcu;
+        _ = try renderTypePrefix(dg.pass, store.*, zcu, w, idx, .suffix, .{});
+        try renderTypeSuffix(dg.pass, store.*, zcu, w, idx, .suffix, .{});
     }
 
     const IntCastContext = union(enum) {
@@ -1737,15 +1796,13 @@ pub const DeclGen = struct {
             value: Value,
         },
 
-        pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, value_ty: Type, location: ValueRenderLocation) !void {
+        pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, location: ValueRenderLocation) !void {
             switch (self.*) {
                 .c_value => |v| {
                     try v.f.writeCValue(w, v.value, location);
                     try v.v.elem(v.f, w);
                 },
-                .value => |v| {
-                    try dg.renderValue(w, value_ty, v.value, location);
-                },
+                .value => |v| try dg.renderValue(w, v.value, location),
             }
         }
     };
@@ -1764,18 +1821,18 @@ pub const DeclGen = struct {
     ///   | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
     ///   | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
     fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
-        const mod = dg.module;
-        const dest_bits = dest_ty.bitSize(mod);
-        const dest_int_info = dest_ty.intInfo(mod);
+        const zcu = dg.zcu;
+        const dest_bits = dest_ty.bitSize(zcu);
+        const dest_int_info = dest_ty.intInfo(zcu);
 
-        const src_is_ptr = src_ty.isPtrAtRuntime(mod);
+        const src_is_ptr = src_ty.isPtrAtRuntime(zcu);
         const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
             .unsigned => Type.usize,
             .signed => Type.isize,
         } else src_ty;
 
-        const src_bits = src_eff_ty.bitSize(mod);
-        const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null;
+        const src_bits = src_eff_ty.bitSize(zcu);
+        const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null;
         if (dest_bits <= 64 and src_bits <= 64) {
             const needs_cast = src_int_info == null or
                 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
@@ -1791,7 +1848,7 @@ pub const DeclGen = struct {
                 try dg.renderType(w, src_eff_ty);
                 try w.writeByte(')');
             }
-            try context.writeValue(dg, w, src_ty, location);
+            try context.writeValue(dg, w, location);
         } else if (dest_bits <= 64 and src_bits > 64) {
             assert(!src_is_ptr);
             if (dest_bits < 64) {
@@ -1802,7 +1859,7 @@ pub const DeclGen = struct {
             try w.writeAll("zig_lo_");
             try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
             try w.writeByte('(');
-            try context.writeValue(dg, w, src_ty, .FunctionArgument);
+            try context.writeValue(dg, w, .FunctionArgument);
             try w.writeByte(')');
         } else if (dest_bits > 64 and src_bits <= 64) {
             try w.writeAll("zig_make_");
@@ -1813,7 +1870,7 @@ pub const DeclGen = struct {
                 try dg.renderType(w, src_eff_ty);
                 try w.writeByte(')');
             }
-            try context.writeValue(dg, w, src_ty, .FunctionArgument);
+            try context.writeValue(dg, w, .FunctionArgument);
             try w.writeByte(')');
         } else {
             assert(!src_is_ptr);
@@ -1822,11 +1879,11 @@ pub const DeclGen = struct {
             try w.writeAll("(zig_hi_");
             try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
             try w.writeByte('(');
-            try context.writeValue(dg, w, src_ty, .FunctionArgument);
+            try context.writeValue(dg, w, .FunctionArgument);
             try w.writeAll("), zig_lo_");
             try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
             try w.writeByte('(');
-            try context.writeValue(dg, w, src_ty, .FunctionArgument);
+            try context.writeValue(dg, w, .FunctionArgument);
             try w.writeAll("))");
         }
     }
@@ -1848,8 +1905,8 @@ pub const DeclGen = struct {
         alignment: Alignment,
         kind: CType.Kind,
     ) error{ OutOfMemory, AnalysisFail }!void {
-        const mod = dg.module;
-        const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod));
+        const zcu = dg.zcu;
+        const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu));
         try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);
     }
 
@@ -1862,7 +1919,7 @@ pub const DeclGen = struct {
         alignas: CType.AlignAs,
     ) error{ OutOfMemory, AnalysisFail }!void {
         const store = &dg.ctypes.set;
-        const mod = dg.module;
+        const zcu = dg.zcu;
 
         switch (alignas.abiOrder()) {
             .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}),
@@ -1870,39 +1927,46 @@ pub const DeclGen = struct {
             .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
         }
 
-        const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers);
+        const trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, cty_idx, .suffix, qualifiers);
         try w.print("{}", .{trailing});
-        try dg.writeCValue(w, name);
-        try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
+        try dg.writeName(w, name);
+        try renderTypeSuffix(dg.pass, store.*, zcu, w, cty_idx, .suffix, .{});
     }
 
     fn declIsGlobal(dg: *DeclGen, val: Value) bool {
-        const mod = dg.module;
-        return switch (mod.intern_pool.indexToKey(val.ip_index)) {
-            .variable => |variable| mod.decl_exports.contains(variable.decl),
+        const zcu = dg.zcu;
+        return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
+            .variable => |variable| zcu.decl_exports.contains(variable.decl),
             .extern_func => true,
-            .func => |func| mod.decl_exports.contains(func.owner_decl),
+            .func => |func| zcu.decl_exports.contains(func.owner_decl),
             else => unreachable,
         };
     }
 
+    fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {
+        switch (c_value) {
+            .new_local, .local => |i| try w.print("t{d}", .{i}),
+            .constant => |val| try renderAnonDeclName(w, val),
+            .decl => |decl| try dg.renderDeclName(w, decl, 0),
+            .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
+            else => unreachable,
+        }
+    }
+
     fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
         switch (c_value) {
-            .none => unreachable,
-            .local, .new_local => |i| return w.print("t{d}", .{i}),
-            .local_ref => |i| return w.print("&t{d}", .{i}),
-            .constant => |val| return renderAnonDeclName(w, val),
-            .arg => |i| return w.print("a{d}", .{i}),
-            .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }),
-            .field => |i| return w.print("f{d}", .{i}),
-            .decl => |decl| return dg.renderDeclName(w, decl, 0),
+            .none, .new_local, .local, .local_ref => unreachable,
+            .constant => |val| try renderAnonDeclName(w, val),
+            .arg, .arg_array => unreachable,
+            .field => |i| try w.print("f{d}", .{i}),
+            .decl => |decl| try dg.renderDeclName(w, decl, 0),
             .decl_ref => |decl| {
                 try w.writeByte('&');
-                return dg.renderDeclName(w, decl, 0);
+                try dg.renderDeclName(w, decl, 0);
             },
-            .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),
-            .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
-            .payload_identifier => |ident| return w.print("{ }.{ }", .{
+            .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
+            .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
+            .payload_identifier => |ident| try w.print("{ }.{ }", .{
                 fmtIdent("payload"),
                 fmtIdent(ident),
             }),
@@ -1911,26 +1975,17 @@ pub const DeclGen = struct {
 
     fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
         switch (c_value) {
-            .none => unreachable,
-            .local, .new_local => |i| return w.print("(*t{d})", .{i}),
-            .local_ref => |i| return w.print("t{d}", .{i}),
-            .constant => unreachable,
-            .arg => |i| return w.print("(*a{d})", .{i}),
-            .arg_array => |i| {
-                try w.writeAll("(*");
-                try dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" });
-                return w.writeByte(')');
-            },
-            .field => |i| return w.print("f{d}", .{i}),
+            .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable,
+            .field => |i| try w.print("f{d}", .{i}),
             .decl => |decl| {
                 try w.writeAll("(*");
                 try dg.renderDeclName(w, decl, 0);
-                return w.writeByte(')');
+                try w.writeByte(')');
             },
-            .decl_ref => |decl| return dg.renderDeclName(w, decl, 0),
+            .decl_ref => |decl| try dg.renderDeclName(w, decl, 0),
             .undef => unreachable,
-            .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
-            .payload_identifier => |ident| return w.print("(*{ }.{ })", .{
+            .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
+            .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
                 fmtIdent("payload"),
                 fmtIdent(ident),
             }),
@@ -1950,12 +2005,12 @@ pub const DeclGen = struct {
 
     fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
         switch (c_value) {
-            .none, .constant, .field, .undef => unreachable,
-            .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier => {
+            .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable,
+            .decl, .identifier, .payload_identifier => {
                 try dg.writeCValue(writer, c_value);
                 try writer.writeAll("->");
             },
-            .local_ref, .decl_ref => {
+            .decl_ref => {
                 try dg.writeCValueDeref(writer, c_value);
                 try writer.writeByte('.');
             },
@@ -1969,11 +2024,12 @@ pub const DeclGen = struct {
         variable: InternPool.Key.Variable,
         fwd_kind: enum { tentative, final },
     ) !void {
-        const decl = dg.module.declPtr(decl_index);
+        const zcu = dg.zcu;
+        const decl = zcu.declPtr(decl_index);
         const fwd = dg.fwdDeclWriter();
         const is_global = variable.is_extern or dg.declIsGlobal(decl.val);
         try fwd.writeAll(if (is_global) "zig_extern " else "static ");
-        const maybe_exports = dg.module.decl_exports.get(decl_index);
+        const maybe_exports = zcu.decl_exports.get(decl_index);
         const export_weak_linkage = if (maybe_exports) |exports|
             exports.items[0].opts.linkage == .weak
         else
@@ -1982,14 +2038,14 @@ pub const DeclGen = struct {
         if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal ");
         try dg.renderTypeAndName(
             fwd,
-            decl.typeOf(dg.module),
+            decl.typeOf(zcu),
             .{ .decl = decl_index },
             CQualifiers.init(.{ .@"const" = variable.is_const }),
             decl.alignment,
             .complete,
         );
         mangled: {
-            const external_name = dg.module.intern_pool.stringToSlice(if (maybe_exports) |exports|
+            const external_name = zcu.intern_pool.stringToSlice(if (maybe_exports) |exports|
                 exports.items[0].opts.name
             else if (variable.is_extern)
                 decl.name
@@ -2007,23 +2063,23 @@ pub const DeclGen = struct {
     }
 
     fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {
-        const mod = dg.module;
-        const decl = mod.declPtr(decl_index);
+        const zcu = dg.zcu;
+        const decl = zcu.declPtr(decl_index);
 
-        if (mod.decl_exports.get(decl_index)) |exports| {
+        if (zcu.decl_exports.get(decl_index)) |exports| {
             try writer.print("{ }", .{
-                fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name)),
+                fmtIdent(zcu.intern_pool.stringToSlice(exports.items[export_index].opts.name)),
             });
-        } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| {
+        } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| {
             try writer.print("{ }", .{
-                fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name)),
+                fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(extern_decl_index).name)),
             });
         } else {
             // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
             // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
             var name: [100]u8 = undefined;
             var name_stream = std.io.fixedBufferStream(&name);
-            decl.renderFullyQualifiedName(mod, name_stream.writer()) catch |err| switch (err) {
+            decl.renderFullyQualifiedName(zcu, name_stream.writer()) catch |err| switch (err) {
                 error.NoSpaceLeft => {},
             };
             try writer.print("{}__{d}", .{
@@ -2033,8 +2089,8 @@ pub const DeclGen = struct {
         }
     }
 
-    fn renderAnonDeclName(writer: anytype, anon_decl_val: InternPool.Index) !void {
-        return writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val)});
+    fn renderAnonDeclName(writer: anytype, anon_decl_val: Value) !void {
+        try writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val.toIntern())});
     }
 
     fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void {
@@ -2047,7 +2103,7 @@ pub const DeclGen = struct {
                 if (cty.isBool())
                     signAbbrev(.unsigned)
                 else if (cty.isInteger())
-                    signAbbrev(cty.signedness(dg.module.getTarget()))
+                    signAbbrev(cty.signedness(dg.mod))
                 else if (cty.isFloat())
                     @as(u8, 'f')
                 else if (cty.isPointer())
@@ -2056,7 +2112,7 @@ pub const DeclGen = struct {
                     return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
                         cty.tag(),
                     }),
-                if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8,
+                if (cty.isFloat()) cty.floatActiveBits(dg.mod) else dg.byteSize(cty) * 8,
             }),
             .array => try writer.writeAll("big"),
         }
@@ -2065,43 +2121,39 @@ pub const DeclGen = struct {
     fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
         const cty = try dg.typeToCType(ty, .complete);
         const is_big = cty.tag() == .array;
-
         switch (info) {
             .none => if (!is_big) return,
             .bits => {},
         }
 
-        const mod = dg.module;
-        const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
+        const zcu = dg.zcu;
+        const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{
             .signedness = .unsigned,
-            .bits = @as(u16, @intCast(ty.bitSize(mod))),
+            .bits = @as(u16, @intCast(ty.bitSize(zcu))),
         };
 
         if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
-
-        const bits_ty = if (is_big) Type.u16 else Type.u8;
         try writer.print(", {}", .{try dg.fmtIntLiteral(
-            bits_ty,
-            try mod.intValue(bits_ty, int_info.bits),
+            try zcu.intValue(if (is_big) Type.u16 else Type.u8, int_info.bits),
             .FunctionArgument,
         )});
     }
 
     fn fmtIntLiteral(
         dg: *DeclGen,
-        ty: Type,
         val: Value,
         loc: ValueRenderLocation,
     ) !std.fmt.Formatter(formatIntLiteral) {
-        const mod = dg.module;
+        const zcu = dg.zcu;
         const kind: CType.Kind = switch (loc) {
             .FunctionArgument => .parameter,
             .Initializer, .Other => .complete,
             .StaticInitializer => .global,
         };
+        const ty = val.typeOf(zcu);
         return std.fmt.Formatter(formatIntLiteral){ .data = .{
             .dg = dg,
-            .int_info = ty.intInfo(mod),
+            .int_info = ty.intInfo(zcu),
             .kind = kind,
             .cty = try dg.typeToCType(ty, kind),
             .val = val,
@@ -2133,7 +2185,7 @@ const RenderCTypeTrailing = enum {
     }
 };
 fn renderTypeName(
-    mod: *Module,
+    zcu: *Zcu,
     w: anytype,
     idx: CType.Index,
     cty: CType,
@@ -2157,7 +2209,7 @@ fn renderTypeName(
             try w.print("{s} {s}{}__{d}", .{
                 @tagName(tag)["fwd_".len..],
                 attributes,
-                fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
+                fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)),
                 @intFromEnum(owner_decl),
             });
         },
@@ -2166,7 +2218,7 @@ fn renderTypeName(
 fn renderTypePrefix(
     pass: DeclGen.Pass,
     store: CType.Store.Set,
-    mod: *Module,
+    zcu: *Zcu,
     w: anytype,
     idx: CType.Index,
     parent_fix: CTypeFix,
@@ -2224,7 +2276,7 @@ fn renderTypePrefix(
             const child_trailing = try renderTypePrefix(
                 pass,
                 store,
-                mod,
+                zcu,
                 w,
                 child_idx,
                 .prefix,
@@ -2247,7 +2299,7 @@ fn renderTypePrefix(
         => {
             const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
             const child_trailing =
-                try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers);
+                try renderTypePrefix(pass, store, zcu, w, child_idx, .suffix, qualifiers);
             switch (parent_fix) {
                 .prefix => {
                     try w.print("{}(", .{child_trailing});
@@ -2262,12 +2314,12 @@ fn renderTypePrefix(
         => switch (pass) {
             .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }),
             .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }),
-            .flush => try renderTypeName(mod, w, idx, cty, ""),
+            .flush => try renderTypeName(zcu, w, idx, cty, ""),
         },
 
         .fwd_struct,
         .fwd_union,
-        => try renderTypeName(mod, w, idx, cty, ""),
+        => try renderTypeName(zcu, w, idx, cty, ""),
 
         .unnamed_struct,
         .unnamed_union,
@@ -2278,7 +2330,7 @@ fn renderTypePrefix(
                 @tagName(tag)["unnamed_".len..],
                 if (cty.isPacked()) "zig_packed(" else "",
             });
-            try renderAggregateFields(mod, w, store, cty, 1);
+            try renderAggregateFields(zcu, w, store, cty, 1);
             if (cty.isPacked()) try w.writeByte(')');
         },
 
@@ -2291,7 +2343,7 @@ fn renderTypePrefix(
         => return renderTypePrefix(
             pass,
             store,
-            mod,
+            zcu,
             w,
             cty.cast(CType.Payload.Aggregate).?.data.fwd_decl,
             parent_fix,
@@ -2304,7 +2356,7 @@ fn renderTypePrefix(
             const child_trailing = try renderTypePrefix(
                 pass,
                 store,
-                mod,
+                zcu,
                 w,
                 cty.cast(CType.Payload.Function).?.data.return_type,
                 .suffix,
@@ -2331,7 +2383,7 @@ fn renderTypePrefix(
 fn renderTypeSuffix(
     pass: DeclGen.Pass,
     store: CType.Store.Set,
-    mod: *Module,
+    zcu: *Zcu,
     w: anytype,
     idx: CType.Index,
     parent_fix: CTypeFix,
@@ -2385,7 +2437,7 @@ fn renderTypeSuffix(
         => try renderTypeSuffix(
             pass,
             store,
-            mod,
+            zcu,
             w,
             cty.cast(CType.Payload.Child).?.data,
             .prefix,
@@ -2404,7 +2456,7 @@ fn renderTypeSuffix(
             try renderTypeSuffix(
                 pass,
                 store,
-                mod,
+                zcu,
                 w,
                 cty.cast(CType.Payload.Sequence).?.data.elem_type,
                 .suffix,
@@ -2444,9 +2496,9 @@ fn renderTypeSuffix(
                 if (need_comma) try w.writeAll(", ");
                 need_comma = true;
                 const trailing =
-                    try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers);
+                    try renderTypePrefix(pass, store, zcu, w, param_type, .suffix, qualifiers);
                 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i });
-                try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{});
+                try renderTypeSuffix(pass, store, zcu, w, param_type, .suffix, .{});
             }
             switch (tag) {
                 .function => {},
@@ -2460,12 +2512,12 @@ fn renderTypeSuffix(
             if (!need_comma) try w.writeAll("void");
             try w.writeByte(')');
 
-            try renderTypeSuffix(pass, store, mod, w, data.return_type, .suffix, .{});
+            try renderTypeSuffix(pass, store, zcu, w, data.return_type, .suffix, .{});
         },
     }
 }
 fn renderAggregateFields(
-    mod: *Module,
+    zcu: *Zcu,
     writer: anytype,
     store: CType.Store.Set,
     cty: CType,
@@ -2480,9 +2532,9 @@ fn renderAggregateFields(
             .eq => {},
             .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}),
         }
-        const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{});
+        const trailing = try renderTypePrefix(.flush, store, zcu, writer, field.type, .suffix, .{});
         try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) });
-        try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{});
+        try renderTypeSuffix(.flush, store, zcu, writer, field.type, .suffix, .{});
         try writer.writeAll(";\n");
     }
     try writer.writeByteNTimes(' ', indent);
@@ -2490,7 +2542,7 @@ fn renderAggregateFields(
 }
 
 pub fn genTypeDecl(
-    mod: *Module,
+    zcu: *Zcu,
     writer: anytype,
     global_store: CType.Store.Set,
     global_idx: CType.Index,
@@ -2503,9 +2555,9 @@ pub fn genTypeDecl(
     switch (global_cty.tag()) {
         .fwd_anon_struct => if (pass != .flush) {
             try writer.writeAll("typedef ");
-            _ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{});
+            _ = try renderTypePrefix(.flush, global_store, zcu, writer, global_idx, .suffix, .{});
             try writer.writeByte(' ');
-            _ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{});
+            _ = try renderTypePrefix(pass, decl_store, zcu, writer, decl_idx, .suffix, .{});
             try writer.writeAll(";\n");
         },
 
@@ -2526,14 +2578,14 @@ pub fn genTypeDecl(
                     _ = try renderTypePrefix(
                         .flush,
                         global_store,
-                        mod,
+                        zcu,
                         writer,
                         global_idx,
                         .suffix,
                         .{},
                     );
                     try writer.writeAll("; /* ");
-                    try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer);
+                    try zcu.declPtr(owner_decl).renderFullyQualifiedName(zcu, writer);
                     try writer.writeAll(" */\n");
                 },
 
@@ -2546,14 +2598,14 @@ pub fn genTypeDecl(
                 => {
                     const fwd_idx = global_cty.cast(CType.Payload.Aggregate).?.data.fwd_decl;
                     try renderTypeName(
-                        mod,
+                        zcu,
                         writer,
                         fwd_idx,
                         global_store.indexToCType(fwd_idx),
                         if (global_cty.isPacked()) "zig_packed(" else "",
                     );
                     try writer.writeByte(' ');
-                    try renderAggregateFields(mod, writer, global_store, global_cty, 0);
+                    try renderAggregateFields(zcu, writer, global_store, global_cty, 0);
                     if (global_cty.isPacked()) try writer.writeByte(')');
                     try writer.writeAll(";\n");
                 },
@@ -2566,30 +2618,30 @@ pub fn genTypeDecl(
     }
 }
 
-pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
-    for (mod.global_assembly.values()) |asm_source| {
+pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void {
+    for (zcu.global_assembly.values()) |asm_source| {
         try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)});
     }
 }
 
 pub fn genErrDecls(o: *Object) !void {
-    const mod = o.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = o.dg.zcu;
+    const ip = &zcu.intern_pool;
     const writer = o.writer();
 
     var max_name_len: usize = 0;
     // do not generate an invalid empty enum when the global error set is empty
-    if (mod.global_error_set.keys().len > 1) {
+    if (zcu.global_error_set.keys().len > 1) {
         try writer.writeAll("enum {\n");
         o.indent_writer.pushIndent();
-        for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| {
+        for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| {
             const name = ip.stringToSlice(name_nts);
             max_name_len = @max(name.len, max_name_len);
-            const err_val = try mod.intern(.{ .err = .{
+            const err_val = try zcu.intern(.{ .err = .{
                 .ty = .anyerror_type,
                 .name = name_nts,
             } });
-            try o.dg.renderValue(writer, Type.anyerror, Value.fromInterned(err_val), .Other);
+            try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other);
             try writer.print(" = {d}u,\n", .{value});
         }
         o.indent_writer.popIndent();
@@ -2601,44 +2653,56 @@ pub fn genErrDecls(o: *Object) !void {
     defer o.dg.gpa.free(name_buf);
 
     @memcpy(name_buf[0..name_prefix.len], name_prefix);
-    for (mod.global_error_set.keys()) |name_ip| {
+    for (zcu.global_error_set.keys()) |name_ip| {
         const name = ip.stringToSlice(name_ip);
         @memcpy(name_buf[name_prefix.len..][0..name.len], name);
         const identifier = name_buf[0 .. name_prefix.len + name.len];
 
-        const name_ty = try mod.arrayType(.{
+        const name_ty = try zcu.arrayType(.{
             .len = name.len,
             .child = .u8_type,
             .sentinel = .zero_u8,
         });
-        const name_val = try mod.intern(.{ .aggregate = .{
+        const name_val = try zcu.intern(.{ .aggregate = .{
             .ty = name_ty.toIntern(),
             .storage = .{ .bytes = name },
         } });
 
         try writer.writeAll("static ");
-        try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, .none, .complete);
+        try o.dg.renderTypeAndName(
+            writer,
+            name_ty,
+            .{ .identifier = identifier },
+            Const,
+            .none,
+            .complete,
+        );
         try writer.writeAll(" = ");
-        try o.dg.renderValue(writer, name_ty, Value.fromInterned(name_val), .StaticInitializer);
+        try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer);
         try writer.writeAll(";\n");
     }
 
-    const name_array_ty = try mod.arrayType(.{
-        .len = mod.global_error_set.count(),
+    const name_array_ty = try zcu.arrayType(.{
+        .len = zcu.global_error_set.count(),
         .child = .slice_const_u8_sentinel_0_type,
     });
 
     try writer.writeAll("static ");
-    try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, .none, .complete);
+    try o.dg.renderTypeAndName(
+        writer,
+        name_array_ty,
+        .{ .identifier = array_identifier },
+        Const,
+        .none,
+        .complete,
+    );
     try writer.writeAll(" = {");
-    for (mod.global_error_set.keys(), 0..) |name_nts, value| {
+    for (zcu.global_error_set.keys(), 0..) |name_nts, value| {
         const name = ip.stringToSlice(name_nts);
         if (value != 0) try writer.writeByte(',');
-
-        const len_val = try mod.intValue(Type.usize, name.len);
-
         try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
-            fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .StaticInitializer),
+            fmtIdent(name),
+            try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, name.len), .StaticInitializer),
         });
     }
     try writer.writeAll("};\n");
@@ -2648,16 +2712,16 @@ fn genExports(o: *Object) !void {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const mod = o.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = o.dg.zcu;
+    const ip = &zcu.intern_pool;
     const decl_index = switch (o.dg.pass) {
         .decl => |decl| decl,
         .anon, .flush => return,
     };
-    const decl = mod.declPtr(decl_index);
+    const decl = zcu.declPtr(decl_index);
     const fwd = o.dg.fwdDeclWriter();
 
-    const exports = mod.decl_exports.get(decl_index) orelse return;
+    const exports = zcu.decl_exports.get(decl_index) orelse return;
     if (exports.items.len < 2) return;
 
     const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) {
@@ -2685,7 +2749,7 @@ fn genExports(o: *Object) !void {
         const export_name = ip.stringToSlice(@"export".opts.name);
         try o.dg.renderTypeAndName(
             fwd,
-            decl.typeOf(mod),
+            decl.typeOf(zcu),
             .{ .identifier = export_name },
             CQualifiers.init(.{ .@"const" = is_variable_const }),
             decl.alignment,
@@ -2708,8 +2772,8 @@ fn genExports(o: *Object) !void {
 }
 
 pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
-    const mod = o.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = o.dg.zcu;
+    const ip = &zcu.intern_pool;
     const w = o.writer();
     const key = lazy_fn.key_ptr.*;
     const val = lazy_fn.value_ptr;
@@ -2727,47 +2791,45 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
             try w.writeByte('(');
             try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete);
             try w.writeAll(") {\n switch (tag) {\n");
-            const tag_names = enum_ty.enumFields(mod);
+            const tag_names = enum_ty.enumFields(zcu);
             for (0..tag_names.len) |tag_index| {
                 const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]);
-                const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index));
+                const tag_val = try zcu.enumValueFieldIndex(enum_ty, @intCast(tag_index));
 
-                const int_val = try tag_val.intFromEnum(enum_ty, mod);
-
-                const name_ty = try mod.arrayType(.{
+                const name_ty = try zcu.arrayType(.{
                     .len = tag_name.len,
                     .child = .u8_type,
                     .sentinel = .zero_u8,
                 });
-                const name_val = try mod.intern(.{ .aggregate = .{
+                const name_val = try zcu.intern(.{ .aggregate = .{
                     .ty = name_ty.toIntern(),
                     .storage = .{ .bytes = tag_name },
                 } });
-                const len_val = try mod.intValue(Type.usize, tag_name.len);
 
                 try w.print("  case {}: {{\n   static ", .{
-                    try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
+                    try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, zcu), .Other),
                 });
                 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete);
                 try w.writeAll(" = ");
-                try o.dg.renderValue(w, name_ty, Value.fromInterned(name_val), .Initializer);
+                try o.dg.renderValue(w, Value.fromInterned(name_val), .Initializer);
                 try w.writeAll(";\n   return (");
                 try o.dg.renderType(w, name_slice_ty);
                 try w.print("){{{}, {}}};\n", .{
-                    fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
+                    fmtIdent("name"),
+                    try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name.len), .Other),
                 });
 
                 try w.writeAll("  }\n");
             }
             try w.writeAll(" }\n while (");
-            try o.dg.renderValue(w, Type.bool, Value.true, .Other);
+            try o.dg.renderValue(w, Value.true, .Other);
             try w.writeAll(") ");
             _ = try airBreakpoint(w);
             try w.writeAll("}\n");
         },
         .never_tail, .never_inline => |fn_decl_index| {
-            const fn_decl = mod.declPtr(fn_decl_index);
-            const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(mod), .complete);
+            const fn_decl = zcu.declPtr(fn_decl_index);
+            const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(zcu), .complete);
             const fn_info = fn_cty.cast(CType.Payload.Function).?.data;
 
             const fwd_decl_writer = o.dg.fwdDeclWriter();
@@ -2799,10 +2861,10 @@ pub fn genFunc(f: *Function) !void {
     defer tracy.end();
 
     const o = &f.object;
-    const mod = o.dg.module;
+    const zcu = o.dg.zcu;
     const gpa = o.dg.gpa;
     const decl_index = o.dg.pass.decl;
-    const decl = mod.declPtr(decl_index);
+    const decl = zcu.declPtr(decl_index);
 
     o.code_header = std.ArrayList(u8).init(gpa);
     defer o.code_header.deinit();
@@ -2811,7 +2873,7 @@ pub fn genFunc(f: *Function) !void {
     const fwd_decl_writer = o.dg.fwdDeclWriter();
     try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
 
-    if (mod.decl_exports.get(decl_index)) |exports|
+    if (zcu.decl_exports.get(decl_index)) |exports|
         if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");
     try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
     try fwd_decl_writer.writeAll(";\n");
@@ -2819,6 +2881,8 @@ pub fn genFunc(f: *Function) !void {
 
     try o.indent_writer.insertNewline();
     if (!is_global) try o.writer().writeAll("static ");
+    if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
+        try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
     try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });
     try o.writer().writeByte(' ');
 
@@ -2867,7 +2931,7 @@ pub fn genFunc(f: *Function) !void {
     for (free_locals.values()) |list| {
         for (list.keys()) |local_index| {
             const local = f.locals.items[local_index];
-            try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.alignas);
+            try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.flags.alignas);
             try w.writeAll(";\n ");
         }
     }
@@ -2884,43 +2948,41 @@ pub fn genDecl(o: *Object) !void {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const mod = o.dg.module;
+    const zcu = o.dg.zcu;
     const decl_index = o.dg.pass.decl;
-    const decl = mod.declPtr(decl_index);
-    const decl_val = decl.val;
-    const decl_ty = decl_val.typeOf(mod);
+    const decl = zcu.declPtr(decl_index);
+    const decl_ty = decl.typeOf(zcu);
 
-    if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
-    if (decl_val.getExternFunc(mod)) |_| {
+    if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
+    if (decl.val.getExternFunc(zcu)) |_| {
         const fwd_decl_writer = o.dg.fwdDeclWriter();
         try fwd_decl_writer.writeAll("zig_extern ");
         try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
         try fwd_decl_writer.writeAll(";\n");
         try genExports(o);
-    } else if (decl_val.getVariable(mod)) |variable| {
+    } else if (decl.val.getVariable(zcu)) |variable| {
         try o.dg.renderFwdDecl(decl_index, variable, .final);
         try genExports(o);
 
         if (variable.is_extern) return;
 
-        const is_global = variable.is_extern or o.dg.declIsGlobal(decl_val);
+        const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val);
         const w = o.writer();
         if (!is_global) try w.writeAll("static ");
         if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
         if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
-        if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
-            try w.print("zig_linksection(\"{s}\", ", .{s});
+        if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
+            try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
         const decl_c_value = .{ .decl = decl_index };
         try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete);
-        if (decl.@"linksection" != .none) try w.writeAll(", read, write)");
         try w.writeAll(" = ");
-        try o.dg.renderValue(w, decl_ty, Value.fromInterned(variable.init), .StaticInitializer);
+        try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer);
         try w.writeByte(';');
         try o.indent_writer.insertNewline();
     } else {
-        const is_global = o.dg.module.decl_exports.contains(decl_index);
+        const is_global = o.dg.zcu.decl_exports.contains(decl_index);
         const decl_c_value = .{ .decl = decl_index };
-        try genDeclValue(o, decl_val, is_global, decl_c_value, decl.alignment, decl.@"linksection");
+        try genDeclValue(o, decl.val, is_global, decl_c_value, decl.alignment, decl.@"linksection");
     }
 }
 
@@ -2930,19 +2992,19 @@ pub fn genDeclValue(
     is_global: bool,
     decl_c_value: CValue,
     alignment: Alignment,
-    link_section: InternPool.OptionalNullTerminatedString,
+    @"linksection": InternPool.OptionalNullTerminatedString,
 ) !void {
-    const mod = o.dg.module;
+    const zcu = o.dg.zcu;
     const fwd_decl_writer = o.dg.fwdDeclWriter();
 
-    const ty = val.typeOf(mod);
+    const ty = val.typeOf(zcu);
 
     try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
     try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);
     switch (o.dg.pass) {
         .decl => |decl_index| {
-            if (mod.decl_exports.get(decl_index)) |exports| {
-                const export_name = mod.intern_pool.stringToSlice(exports.items[0].opts.name);
+            if (zcu.decl_exports.get(decl_index)) |exports| {
+                const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name);
                 if (isMangledIdent(export_name, true)) {
                     try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
                         fmtIdent(export_name), fmtStringLiteral(export_name, null),
@@ -2958,13 +3020,11 @@ pub fn genDeclValue(
 
     const w = o.writer();
     if (!is_global) try w.writeAll("static ");
-
-    if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s|
-        try w.print("zig_linksection(\"{s}\", ", .{s});
+    if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s|
+        try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
     try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
-    if (link_section != .none) try w.writeAll(", read)");
     try w.writeAll(" = ");
-    try o.dg.renderValue(w, ty, val, .StaticInitializer);
+    try o.dg.renderValue(w, val, .StaticInitializer);
     try w.writeAll(";\n");
 }
 
@@ -2972,12 +3032,12 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const mod = dg.module;
+    const zcu = dg.zcu;
     const decl_index = dg.pass.decl;
-    const decl = mod.declPtr(decl_index);
+    const decl = zcu.declPtr(decl_index);
     const writer = dg.fwdDeclWriter();
 
-    switch (decl.val.typeOf(mod).zigTypeTag(mod)) {
+    switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
         .Fn => if (dg.declIsGlobal(decl.val)) {
             try writer.writeAll("zig_extern ");
             try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
@@ -3060,8 +3120,8 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
 }
 
 fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
-    const mod = f.object.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = f.object.dg.zcu;
+    const ip = &zcu.intern_pool;
     const air_tags = f.air.instructions.items(.tag);
 
     for (body) |inst| {
@@ -3096,10 +3156,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
             .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
             .rem => blk: {
                 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
-                const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(mod);
+                const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);
                 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
                 // so we only check one.
-                break :blk if (lhs_scalar_ty.isInt(mod))
+                break :blk if (lhs_scalar_ty.isInt(zcu))
                     try airBinOp(f, inst, "%", "rem", .none)
                 else
                     try airBinFloatOp(f, inst, "fmod");
@@ -3359,10 +3419,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
 }
 
 fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const inst_ty = f.typeOfIndex(inst);
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
-    if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
         return .none;
     }
@@ -3385,14 +3445,17 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
 
     const inst_ty = f.typeOfIndex(inst);
     const ptr_ty = f.typeOf(bin_op.lhs);
-    const elem_ty = ptr_ty.childType(mod);
-    const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
+    const ptr_align = ptr_ty.ptrAlignment(zcu);
+    const elem_ty = ptr_ty.elemType2(zcu);
+    const elem_align = elem_ty.abiAlignment(zcu);
+    const is_under_aligned = ptr_align.compareStrict(.lt, elem_align);
+    const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu);
 
     const ptr = try f.resolveInst(bin_op.lhs);
     const index = try f.resolveInst(bin_op.rhs);
@@ -3407,13 +3470,22 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
     try f.renderType(writer, inst_ty);
     try writer.writeByte(')');
     if (elem_has_bits) try writer.writeByte('&');
-    if (elem_has_bits and ptr_ty.ptrSize(mod) == .One) {
+    if (elem_has_bits and ptr_ty.ptrSize(zcu) == .One and !is_under_aligned) {
         // It's a pointer to an array, so we need to de-reference.
         try f.writeCValueDeref(writer, ptr);
     } else try f.writeCValue(writer, ptr, .Other);
     if (elem_has_bits) {
         try writer.writeByte('[');
         try f.writeCValue(writer, index, .Other);
+        if (is_under_aligned) {
+            const factor = @divExact(elem_align.toByteUnitsOptional().?, @min(
+                ptr_align.toByteUnitsOptional().?,
+                f.object.dg.mod.resolved_target.result.maxIntAlignment(),
+            ));
+            try writer.print(" * {}", .{
+                try f.fmtIntLiteral(try zcu.intValue(Type.usize, factor)),
+            });
+        }
         try writer.writeByte(']');
     }
     try a.end(f, writer);
@@ -3421,10 +3493,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const inst_ty = f.typeOfIndex(inst);
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
-    if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
         return .none;
     }
@@ -3447,14 +3519,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
 
     const inst_ty = f.typeOfIndex(inst);
     const slice_ty = f.typeOf(bin_op.lhs);
-    const elem_ty = slice_ty.elemType2(mod);
-    const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
+    const elem_ty = slice_ty.elemType2(zcu);
+    const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu);
 
     const slice = try f.resolveInst(bin_op.lhs);
     const index = try f.resolveInst(bin_op.rhs);
@@ -3477,10 +3549,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const inst_ty = f.typeOfIndex(inst);
-    if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
         return .none;
     }
@@ -3503,33 +3575,33 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const inst_ty = f.typeOfIndex(inst);
-    const elem_type = inst_ty.childType(mod);
-    if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
+    const elem_type = inst_ty.childType(zcu);
+    if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty };
 
     const local = try f.allocLocalValue(
         elem_type,
-        inst_ty.ptrAlignment(mod),
+        inst_ty.ptrAlignment(zcu),
     );
     log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
-    const gpa = f.object.dg.module.gpa;
+    const gpa = f.object.dg.zcu.gpa;
     try f.allocs.put(gpa, local.new_local, true);
     return .{ .local_ref = local.new_local };
 }
 
 fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const inst_ty = f.typeOfIndex(inst);
-    const elem_ty = inst_ty.childType(mod);
-    if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
+    const elem_ty = inst_ty.childType(zcu);
+    if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty };
 
     const local = try f.allocLocalValue(
         elem_ty,
-        inst_ty.ptrAlignment(mod),
+        inst_ty.ptrAlignment(zcu),
     );
     log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
-    const gpa = f.object.dg.module.gpa;
+    const gpa = f.object.dg.zcu.gpa;
     try f.allocs.put(gpa, local.new_local, true);
     return .{ .local_ref = local.new_local };
 }
@@ -3559,15 +3631,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const ptr_ty = f.typeOf(ty_op.operand);
-    const ptr_scalar_ty = ptr_ty.scalarType(mod);
-    const ptr_info = ptr_scalar_ty.ptrInfo(mod);
+    const ptr_scalar_ty = ptr_ty.scalarType(zcu);
+    const ptr_info = ptr_scalar_ty.ptrInfo(zcu);
     const src_ty = Type.fromInterned(ptr_info.child);
 
-    if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try reap(f, inst, &.{ty_op.operand});
         return .none;
     }
@@ -3577,10 +3649,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
     try reap(f, inst, &.{ty_op.operand});
 
     const is_aligned = if (ptr_info.flags.alignment != .none)
-        ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod))
+        ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu))
     else
         true;
-    const is_array = lowersToArray(src_ty, mod);
+    const is_array = lowersToArray(src_ty, zcu);
     const need_memcpy = !is_aligned or is_array;
 
     const writer = f.object.writer();
@@ -3600,12 +3672,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
         try writer.writeAll("))");
     } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
         const host_bits: u16 = ptr_info.packed_offset.host_size * 8;
-        const host_ty = try mod.intType(.unsigned, host_bits);
+        const host_ty = try zcu.intType(.unsigned, host_bits);
 
-        const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
-        const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
+        const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
+        const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
 
-        const field_ty = try mod.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(mod))));
+        const field_ty = try zcu.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu))));
 
         try f.writeCValue(writer, local, .Other);
         try v.elem(f, writer);
@@ -3616,9 +3688,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
         try writer.writeAll("((");
         try f.renderType(writer, field_ty);
         try writer.writeByte(')');
-        const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64;
+        const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
         if (cant_cast) {
-            if (field_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
+            if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
             try writer.writeAll("zig_lo_");
             try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
             try writer.writeByte('(');
@@ -3628,7 +3700,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
         try writer.writeByte('(');
         try f.writeCValueDeref(writer, operand);
         try v.elem(f, writer);
-        try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
+        try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)});
         if (cant_cast) try writer.writeByte(')');
         try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits);
         try writer.writeByte(')');
@@ -3646,22 +3718,22 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
     const writer = f.object.writer();
     const op_inst = un_op.toIndex();
     const op_ty = f.typeOf(un_op);
-    const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
-    const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
+    const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty;
+    const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu);
 
     if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) {
         try reap(f, inst, &.{un_op});
         _ = try airCall(f, op_inst.?, .always_tail);
-    } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         const operand = try f.resolveInst(un_op);
         try reap(f, inst, &.{un_op});
         var deref = is_ptr;
-        const is_array = lowersToArray(ret_ty, mod);
+        const is_array = lowersToArray(ret_ty, zcu);
         const ret_val = if (is_array) ret_val: {
             const array_local = try f.allocLocal(inst, lowered_ret_ty);
             try writer.writeAll("memcpy(");
@@ -3696,16 +3768,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
 }
 
 fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
     const operand_ty = f.typeOf(ty_op.operand);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -3722,20 +3794,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
-    const dest_int_info = inst_scalar_ty.intInfo(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
+    const dest_int_info = inst_scalar_ty.intInfo(zcu);
     const dest_bits = dest_int_info.bits;
     const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
         return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
     const operand_ty = f.typeOf(ty_op.operand);
-    const scalar_ty = operand_ty.scalarType(mod);
-    const scalar_int_info = scalar_ty.intInfo(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
+    const scalar_int_info = scalar_ty.intInfo(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -3763,18 +3835,19 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
         try v.elem(f, writer);
     } else switch (dest_int_info.signedness) {
         .unsigned => {
-            const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty);
             try writer.writeAll("zig_and_");
             try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
             try writer.writeByte('(');
             try f.writeCValue(writer, operand, .FunctionArgument);
             try v.elem(f, writer);
-            try writer.print(", {x})", .{try f.fmtIntLiteral(scalar_ty, mask_val)});
+            try writer.print(", {x})", .{
+                try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(zcu, scalar_ty)),
+            });
         },
         .signed => {
             const c_bits = toCIntBits(scalar_int_info.bits) orelse
                 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
-            const shift_val = try mod.intValue(Type.u8, c_bits - dest_bits);
+            const shift_val = try zcu.intValue(Type.u8, c_bits - dest_bits);
 
             try writer.writeAll("zig_shr_");
             try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
@@ -3792,9 +3865,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
             try f.writeCValue(writer, operand, .FunctionArgument);
             try v.elem(f, writer);
             if (c_bits == 128) try writer.writeByte(')');
-            try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)});
+            try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});
             if (c_bits == 128) try writer.writeByte(')');
-            try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)});
+            try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)});
         },
     }
 
@@ -3821,18 +3894,18 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     // *a = b;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
 
     const ptr_ty = f.typeOf(bin_op.lhs);
-    const ptr_scalar_ty = ptr_ty.scalarType(mod);
-    const ptr_info = ptr_scalar_ty.ptrInfo(mod);
+    const ptr_scalar_ty = ptr_ty.scalarType(zcu);
+    const ptr_info = ptr_scalar_ty.ptrInfo(zcu);
 
     const ptr_val = try f.resolveInst(bin_op.lhs);
     const src_ty = f.typeOf(bin_op.rhs);
 
-    const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep(mod) else false;
+    const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |v| v.isUndefDeep(zcu) else false;
 
     if (val_is_undef) {
         try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
@@ -3848,10 +3921,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
     }
 
     const is_aligned = if (ptr_info.flags.alignment != .none)
-        ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod))
+        ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu))
     else
         true;
-    const is_array = lowersToArray(Type.fromInterned(ptr_info.child), mod);
+    const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu);
     const need_memcpy = !is_aligned or is_array;
 
     const src_val = try f.resolveInst(bin_op.rhs);
@@ -3863,7 +3936,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
     if (need_memcpy) {
         // For this memcpy to safely work we need the rhs to have the same
         // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
-        assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.module));
+        assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.zcu));
 
         // If the source is a constant, writeCValue will emit a brace initialization
         // so work around this by initializing into new local.
@@ -3893,12 +3966,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         }
     } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) {
         const host_bits = ptr_info.packed_offset.host_size * 8;
-        const host_ty = try mod.intType(.unsigned, host_bits);
+        const host_ty = try zcu.intType(.unsigned, host_bits);
 
-        const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
-        const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
+        const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
+        const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset);
 
-        const src_bits = src_ty.bitSize(mod);
+        const src_bits = src_ty.bitSize(zcu);
 
         const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;
         var stack align(@alignOf(ExpectedContents)) =
@@ -3911,7 +3984,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset);
         try mask.bitNotWrap(&mask, .unsigned, host_bits);
 
-        const mask_val = try mod.intValue_big(host_ty, mask.toConst());
+        const mask_val = try zcu.intValue_big(host_ty, mask.toConst());
 
         try f.writeCValueDeref(writer, ptr_val);
         try v.elem(f, writer);
@@ -3922,12 +3995,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         try writer.writeByte('(');
         try f.writeCValueDeref(writer, ptr_val);
         try v.elem(f, writer);
-        try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
+        try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)});
         try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
         try writer.writeByte('(');
-        const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64;
+        const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64;
         if (cant_cast) {
-            if (src_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
+            if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
             try writer.writeAll("zig_make_");
             try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
             try writer.writeAll("(0, ");
@@ -3937,7 +4010,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
             try writer.writeByte(')');
         }
 
-        if (src_ty.isPtrAtRuntime(mod)) {
+        if (src_ty.isPtrAtRuntime(zcu)) {
             try writer.writeByte('(');
             try f.renderType(writer, Type.usize);
             try writer.writeByte(')');
@@ -3945,7 +4018,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         try f.writeCValue(writer, src_val, .Other);
         try v.elem(f, writer);
         if (cant_cast) try writer.writeByte(')');
-        try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
+        try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)});
     } else {
         try f.writeCValueDeref(writer, ptr_val);
         try v.elem(f, writer);
@@ -3960,7 +4033,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
 }
 
 fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
 
@@ -3970,7 +4043,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
 
     const inst_ty = f.typeOfIndex(inst);
     const operand_ty = f.typeOf(bin_op.lhs);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const w = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -3998,11 +4071,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
 }
 
 fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
     const operand_ty = f.typeOf(ty_op.operand);
-    const scalar_ty = operand_ty.scalarType(mod);
-    if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
+    const scalar_ty = operand_ty.scalarType(zcu);
+    if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
 
     const op = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
@@ -4031,11 +4104,11 @@ fn airBinOp(
     operation: []const u8,
     info: BuiltinInfo,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const operand_ty = f.typeOf(bin_op.lhs);
-    const scalar_ty = operand_ty.scalarType(mod);
-    if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat())
+    const scalar_ty = operand_ty.scalarType(zcu);
+    if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat())
         return try airBinBuiltinCall(f, inst, operation, info);
 
     const lhs = try f.resolveInst(bin_op.lhs);
@@ -4069,12 +4142,12 @@ fn airCmpOp(
     data: anytype,
     operator: std.math.CompareOperator,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const lhs_ty = f.typeOf(data.lhs);
-    const scalar_ty = lhs_ty.scalarType(mod);
+    const scalar_ty = lhs_ty.scalarType(zcu);
 
-    const scalar_bits = scalar_ty.bitSize(mod);
-    if (scalar_ty.isInt(mod) and scalar_bits > 64)
+    const scalar_bits = scalar_ty.bitSize(zcu);
+    if (scalar_ty.isInt(zcu) and scalar_bits > 64)
         return airCmpBuiltinCall(
             f,
             inst,
@@ -4092,7 +4165,7 @@ fn airCmpOp(
     try reap(f, inst, &.{ data.lhs, data.rhs });
 
     const rhs_ty = f.typeOf(data.rhs);
-    const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod);
+    const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu);
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
     const v = try Vectorize.start(f, inst, writer, lhs_ty);
@@ -4117,12 +4190,12 @@ fn airEquality(
     inst: Air.Inst.Index,
     operator: std.math.CompareOperator,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
 
     const operand_ty = f.typeOf(bin_op.lhs);
-    const operand_bits = operand_ty.bitSize(mod);
-    if (operand_ty.isInt(mod) and operand_bits > 64)
+    const operand_bits = operand_ty.bitSize(zcu);
+    if (operand_ty.isInt(zcu) and operand_bits > 64)
         return airCmpBuiltinCall(
             f,
             inst,
@@ -4145,7 +4218,7 @@ fn airEquality(
     try f.writeCValue(writer, local, .Other);
     try a.assign(f, writer);
 
-    if (operand_ty.zigTypeTag(mod) == .Optional and !operand_ty.optionalReprIsPayload(mod)) {
+    if (operand_ty.zigTypeTag(zcu) == .Optional and !operand_ty.optionalReprIsPayload(zcu)) {
         try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" });
         try writer.writeAll(" || ");
         try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" });
@@ -4184,7 +4257,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
 
@@ -4193,8 +4266,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
-    const elem_ty = inst_scalar_ty.elemType2(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
+    const elem_ty = inst_scalar_ty.elemType2(zcu);
 
     const local = try f.allocLocal(inst, inst_ty);
     const writer = f.object.writer();
@@ -4203,7 +4276,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
     try v.elem(f, writer);
     try writer.writeAll(" = ");
 
-    if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         // We must convert to and from integer types to prevent UB if the operation
         // results in a NULL pointer, or if LHS is NULL. The operation is only UB
         // if the result is NULL and then dereferenced.
@@ -4232,13 +4305,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
 }
 
 fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
 
-    if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64)
+    if (inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64)
         return try airBinBuiltinCall(f, inst, operation[1..], .none);
     if (inst_scalar_ty.isRuntimeFloat())
         return try airBinFloatOp(f, inst, operation);
@@ -4274,7 +4347,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
 }
 
 fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
 
@@ -4283,7 +4356,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.typeOfIndex(inst);
-    const ptr_ty = inst_ty.slicePtrFieldType(mod);
+    const ptr_ty = inst_ty.slicePtrFieldType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -4291,9 +4364,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
         const a = try Assignment.start(f, writer, ptr_ty);
         try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
         try a.assign(f, writer);
-        try writer.writeByte('(');
-        try f.renderType(writer, ptr_ty);
-        try writer.writeByte(')');
         try f.writeCValue(writer, ptr, .Other);
         try a.end(f, writer);
     }
@@ -4301,7 +4371,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
         const a = try Assignment.start(f, writer, Type.usize);
         try f.writeCValueMember(writer, local, .{ .identifier = "len" });
         try a.assign(f, writer);
-        try f.writeCValue(writer, len, .Other);
+        try f.writeCValue(writer, len, .Initializer);
         try a.end(f, writer);
     }
     return local;
@@ -4312,7 +4382,7 @@ fn airCall(
     inst: Air.Inst.Index,
     modifier: std.builtin.CallModifier,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     // Not even allowed to call panic in a naked function.
     if (f.object.dg.is_naked_fn) return .none;
 
@@ -4334,7 +4404,7 @@ fn airCall(
         }
         resolved_arg.* = try f.resolveInst(arg);
         if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
-            const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
+            const lowered_arg_ty = try lowerFnRetTy(arg_ty, zcu);
 
             const array_local = try f.allocLocal(inst, lowered_arg_ty);
             try writer.writeAll("memcpy(");
@@ -4357,20 +4427,19 @@ fn airCall(
     }
 
     const callee_ty = f.typeOf(pl_op.operand);
-    const fn_ty = switch (callee_ty.zigTypeTag(mod)) {
+    const fn_info = zcu.typeToFunc(switch (callee_ty.zigTypeTag(zcu)) {
         .Fn => callee_ty,
-        .Pointer => callee_ty.childType(mod),
+        .Pointer => callee_ty.childType(zcu),
         else => unreachable,
-    };
-
-    const ret_ty = fn_ty.fnReturnType(mod);
-    const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
+    }).?;
+    const ret_ty = Type.fromInterned(fn_info.return_type);
+    const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu);
 
     const result_local = result: {
         if (modifier == .always_tail) {
             try writer.writeAll("zig_always_tail return ");
             break :result .none;
-        } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+        } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
             break :result .none;
         } else if (f.liveness.isUnused(inst)) {
             try writer.writeByte('(');
@@ -4388,8 +4457,8 @@ fn airCall(
     callee: {
         known: {
             const fn_decl = fn_decl: {
-                const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
-                break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
+                const callee_val = (try f.air.value(pl_op.operand, zcu)) orelse break :known;
+                break :fn_decl switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) {
                     .extern_func => |extern_func| extern_func.decl,
                     .func => |func| func.owner_decl,
                     .ptr => |ptr| switch (ptr.addr) {
@@ -4420,18 +4489,21 @@ fn airCall(
     }
 
     try writer.writeByte('(');
-    var args_written: usize = 0;
+    var need_comma = false;
     for (resolved_args) |resolved_arg| {
         if (resolved_arg == .none) continue;
-        if (args_written != 0) try writer.writeAll(", ");
+        if (need_comma) try writer.writeAll(", ");
+        need_comma = true;
         try f.writeCValue(writer, resolved_arg, .FunctionArgument);
-        if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, null);
-        args_written += 1;
+        switch (resolved_arg) {
+            .new_local => |local| try freeLocal(f, inst, local, null),
+            else => {},
+        }
     }
     try writer.writeAll(");\n");
 
     const result = result: {
-        if (result_local == .none or !lowersToArray(ret_ty, mod))
+        if (result_local == .none or !lowersToArray(ret_ty, zcu))
             break :result result_local;
 
         const array_local = try f.allocLocal(inst, ret_ty);
@@ -4465,22 +4537,22 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
-    const owner_decl = mod.funcOwnerDeclPtr(extra.data.func);
+    const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func);
     const writer = f.object.writer();
     try writer.writeAll("/* ");
-    try owner_decl.renderFullyQualifiedName(mod, writer);
+    try owner_decl.renderFullyQualifiedName(zcu, writer);
     try writer.writeAll(" */ ");
     return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
 }
 
 fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
     const name = f.air.nullTerminatedString(pl_op.payload);
-    const operand_is_undef = if (try f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep(mod) else false;
+    const operand_is_undef = if (try f.air.value(pl_op.operand, zcu)) |v| v.isUndefDeep(zcu) else false;
     if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
 
     try reap(f, inst, &.{pl_op.operand});
@@ -4496,7 +4568,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const liveness_block = f.liveness.getBlock(inst);
 
     const block_id: usize = f.next_block_index;
@@ -4504,7 +4576,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
     const writer = f.object.writer();
 
     const inst_ty = f.typeOfIndex(inst);
-    const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !f.liveness.isUnused(inst))
+    const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst))
         try f.allocLocal(inst, inst_ty)
     else
         .none;
@@ -4526,7 +4598,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index)
     try f.object.indent_writer.insertNewline();
 
     // noreturn blocks have no `br` instructions reaching them, so we don't want a label
-    if (!f.typeOfIndex(inst).isNoReturn(mod)) {
+    if (!f.typeOfIndex(inst).isNoReturn(zcu)) {
         // label must be followed by an expression, include an empty one.
         try writer.print("zig_block_{d}:;\n", .{block_id});
     }
@@ -4543,11 +4615,11 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
     const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]);
-    const err_union_ty = f.typeOf(extra.data.ptr).childType(mod);
+    const err_union_ty = f.typeOf(extra.data.ptr).childType(zcu);
     return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);
 }
 
@@ -4559,15 +4631,15 @@ fn lowerTry(
     err_union_ty: Type,
     is_ptr: bool,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const err_union = try f.resolveInst(operand);
     const inst_ty = f.typeOfIndex(inst);
     const liveness_condbr = f.liveness.getCondBr(inst);
     const writer = f.object.writer();
-    const payload_ty = err_union_ty.errorUnionPayload(mod);
-    const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
+    const payload_ty = err_union_ty.errorUnionPayload(zcu);
+    const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
 
-    if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
+    if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) {
         try writer.writeAll("if (");
         if (!payload_has_bits) {
             if (is_ptr)
@@ -4661,7 +4733,7 @@ const LocalResult = struct {
     need_free: bool,
 
     fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue {
-        const mod = f.object.dg.module;
+        const zcu = f.object.dg.zcu;
 
         if (lr.need_free) {
             // Move the freshly allocated local to be owned by this instruction,
@@ -4673,7 +4745,7 @@ const LocalResult = struct {
         try lr.free(f);
         const writer = f.object.writer();
         try f.writeCValue(writer, local, .Other);
-        if (dest_ty.isAbiInt(mod)) {
+        if (dest_ty.isAbiInt(zcu)) {
             try writer.writeAll(" = ");
         } else {
             try writer.writeAll(" = (");
@@ -4693,13 +4765,13 @@ const LocalResult = struct {
 };
 
 fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {
-    const mod = f.object.dg.module;
-    const target = mod.getTarget();
+    const zcu = f.object.dg.zcu;
+    const target = &f.object.dg.mod.resolved_target.result;
     const writer = f.object.writer();
 
-    if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) {
-        const src_info = dest_ty.intInfo(mod);
-        const dest_info = operand_ty.intInfo(mod);
+    if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) {
+        const src_info = dest_ty.intInfo(zcu);
+        const dest_info = operand_ty.intInfo(zcu);
         if (src_info.signedness == dest_info.signedness and
             src_info.bits == dest_info.bits)
         {
@@ -4710,7 +4782,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
         }
     }
 
-    if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) {
+    if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) {
         const local = try f.allocLocal(null, dest_ty);
         try f.writeCValue(writer, local, .Other);
         try writer.writeAll(" = (");
@@ -4727,7 +4799,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
     const operand_lval = if (operand == .constant) blk: {
         const operand_local = try f.allocLocal(null, operand_ty);
         try f.writeCValue(writer, operand_local, .Other);
-        if (operand_ty.isAbiInt(mod)) {
+        if (operand_ty.isAbiInt(zcu)) {
             try writer.writeAll(" = ");
         } else {
             try writer.writeAll(" = (");
@@ -4747,14 +4819,14 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
     try writer.writeAll(", sizeof(");
     try f.renderType(
         writer,
-        if (dest_ty.abiSize(mod) <= operand_ty.abiSize(mod)) dest_ty else operand_ty,
+        if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty,
     );
     try writer.writeAll("));\n");
 
     // Ensure padding bits have the expected value.
-    if (dest_ty.isAbiInt(mod)) {
+    if (dest_ty.isAbiInt(zcu)) {
         const dest_cty = try f.typeToCType(dest_ty, .complete);
-        const dest_info = dest_ty.intInfo(mod);
+        const dest_info = dest_ty.intInfo(zcu);
         var bits: u16 = dest_info.bits;
         var wrap_cty: ?CType = null;
         var need_bitcasts = false;
@@ -4779,7 +4851,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
             try writer.writeByte('(');
         }
         try writer.writeAll("zig_wrap_");
-        const info_ty = try mod.intType(dest_info.signedness, bits);
+        const info_ty = try zcu.intType(dest_info.signedness, bits);
         if (wrap_cty) |cty|
             try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)
         else
@@ -4912,7 +4984,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
     const condition = try f.resolveInst(pl_op.operand);
     try reap(f, inst, &.{pl_op.operand});
@@ -4921,11 +4993,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
     const writer = f.object.writer();
 
     try writer.writeAll("switch (");
-    if (condition_ty.zigTypeTag(mod) == .Bool) {
+    if (condition_ty.zigTypeTag(zcu) == .Bool) {
         try writer.writeByte('(');
         try f.renderType(writer, Type.u1);
         try writer.writeByte(')');
-    } else if (condition_ty.isPtrAtRuntime(mod)) {
+    } else if (condition_ty.isPtrAtRuntime(zcu)) {
         try writer.writeByte('(');
         try f.renderType(writer, Type.usize);
         try writer.writeByte(')');
@@ -4952,12 +5024,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
         for (items) |item| {
             try f.object.indent_writer.insertNewline();
             try writer.writeAll("case ");
-            if (condition_ty.isPtrAtRuntime(mod)) {
+            if (condition_ty.isPtrAtRuntime(zcu)) {
                 try writer.writeByte('(');
                 try f.renderType(writer, Type.usize);
                 try writer.writeByte(')');
             }
-            try f.object.dg.renderValue(writer, condition_ty, (try f.air.value(item, mod)).?, .Other);
+            try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other);
             try writer.writeByte(':');
         }
         try writer.writeByte(' ');
@@ -4994,13 +5066,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
-    const target = f.object.dg.module.getTarget();
+    const target = &f.object.dg.mod.resolved_target.result;
     return switch (constraint[0]) {
         '{' => true,
         'i', 'r' => false,
         'I' => !target.cpu.arch.isArmOrThumb(),
         else => switch (value) {
-            .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) {
+            .constant => |val| switch (f.object.dg.zcu.intern_pool.indexToKey(val.toIntern())) {
                 .ptr => |ptr| switch (ptr.addr) {
                     .decl => false,
                     else => true,
@@ -5013,7 +5085,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool
 }
 
 fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.Asm, ty_pl.payload);
     const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
@@ -5028,7 +5100,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
     const result = result: {
         const writer = f.object.writer();
         const inst_ty = f.typeOfIndex(inst);
-        const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: {
+        const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: {
             const local = try f.allocLocal(inst, inst_ty);
             if (f.wantSafety()) {
                 try f.writeCValue(writer, local, .Other);
@@ -5057,7 +5129,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
 
             const is_reg = constraint[1] == '{';
             if (is_reg) {
-                const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(mod);
+                const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu);
                 try writer.writeAll("register ");
                 const alignment: Alignment = .none;
                 const local_value = try f.allocLocalValue(output_ty, alignment);
@@ -5275,7 +5347,7 @@ fn airIsNull(
     operator: []const u8,
     is_ptr: bool,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
 
     const writer = f.object.writer();
@@ -5292,22 +5364,22 @@ fn airIsNull(
     }
 
     const operand_ty = f.typeOf(un_op);
-    const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
-    const payload_ty = optional_ty.optionalChild(mod);
-    const err_int_ty = try mod.errorIntType();
+    const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
+    const payload_ty = optional_ty.optionalChild(zcu);
+    const err_int_ty = try zcu.errorIntType();
 
-    const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
+    const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu))
         Value.true
-    else if (optional_ty.isPtrLikeOptional(mod))
+    else if (optional_ty.isPtrLikeOptional(zcu))
         // operand is a regular pointer, test `operand !=/== NULL`
-        try mod.getCoerced(Value.null, optional_ty)
-    else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
-        try mod.intValue(err_int_ty, 0)
-    else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
+        try zcu.getCoerced(Value.null, optional_ty)
+    else if (payload_ty.zigTypeTag(zcu) == .ErrorSet)
+        try zcu.intValue(err_int_ty, 0)
+    else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: {
         try writer.writeAll(".ptr");
-        const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
-        const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());
-        break :rhs try mod.nullValue(opt_slice_ptr_ty);
+        const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu);
+        const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern());
+        break :rhs try zcu.nullValue(opt_slice_ptr_ty);
     } else rhs: {
         try writer.writeAll(".is_null");
         break :rhs Value.true;
@@ -5315,22 +5387,22 @@ fn airIsNull(
     try writer.writeByte(' ');
     try writer.writeAll(operator);
     try writer.writeByte(' ');
-    try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other);
+    try f.object.dg.renderValue(writer, rhs, .Other);
     try writer.writeAll(";\n");
     return local;
 }
 
 fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const opt_ty = f.typeOf(ty_op.operand);
 
-    const payload_ty = opt_ty.optionalChild(mod);
+    const payload_ty = opt_ty.optionalChild(zcu);
 
-    if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         return .none;
     }
 
@@ -5338,7 +5410,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
 
-    if (opt_ty.optionalReprIsPayload(mod)) {
+    if (opt_ty.optionalReprIsPayload(zcu)) {
         try f.writeCValue(writer, local, .Other);
         try writer.writeAll(" = ");
         try f.writeCValue(writer, operand, .Other);
@@ -5355,24 +5427,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const writer = f.object.writer();
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const ptr_ty = f.typeOf(ty_op.operand);
-    const opt_ty = ptr_ty.childType(mod);
+    const opt_ty = ptr_ty.childType(zcu);
     const inst_ty = f.typeOfIndex(inst);
 
-    if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) {
         return .{ .undef = inst_ty };
     }
 
     const local = try f.allocLocal(inst, inst_ty);
     try f.writeCValue(writer, local, .Other);
 
-    if (opt_ty.optionalReprIsPayload(mod)) {
+    if (opt_ty.optionalReprIsPayload(zcu)) {
         // the operand is just a regular pointer, no need to do anything special.
         // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
         try writer.writeAll(" = ");
@@ -5386,18 +5458,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
     const writer = f.object.writer();
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const operand_ty = f.typeOf(ty_op.operand);
 
-    const opt_ty = operand_ty.childType(mod);
+    const opt_ty = operand_ty.childType(zcu);
 
     const inst_ty = f.typeOfIndex(inst);
 
-    if (opt_ty.optionalReprIsPayload(mod)) {
+    if (opt_ty.optionalReprIsPayload(zcu)) {
         if (f.liveness.isUnused(inst)) {
             return .none;
         }
@@ -5412,7 +5484,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
     } else {
         try f.writeCValueDeref(writer, operand);
         try writer.writeAll(".is_null = ");
-        try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer);
+        try f.object.dg.renderValue(writer, Value.false, .Initializer);
         try writer.writeAll(";\n");
 
         if (f.liveness.isUnused(inst)) {
@@ -5432,50 +5504,50 @@ fn fieldLocation(
     container_ptr_ty: Type,
     field_ptr_ty: Type,
     field_index: u32,
-    mod: *Module,
+    zcu: *Zcu,
 ) union(enum) {
     begin: void,
     field: CValue,
     byte_offset: u32,
     end: void,
 } {
-    const ip = &mod.intern_pool;
-    const container_ty = container_ptr_ty.childType(mod);
-    return switch (container_ty.zigTypeTag(mod)) {
+    const ip = &zcu.intern_pool;
+    const container_ty = container_ptr_ty.childType(zcu);
+    return switch (container_ty.zigTypeTag(zcu)) {
         .Struct => blk: {
-            if (mod.typeToPackedStruct(container_ty)) |struct_type| {
-                if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0)
-                    break :blk .{ .byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) }
+            if (zcu.typeToPackedStruct(container_ty)) |struct_type| {
+                if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0)
+                    break :blk .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) }
                 else
                     break :blk .begin;
             }
 
-            for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| {
+            for (field_index..container_ty.structFieldCount(zcu)) |next_field_index_usize| {
                 const next_field_index: u32 = @intCast(next_field_index_usize);
-                if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
-                const field_ty = container_ty.structFieldType(next_field_index, mod);
-                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                if (container_ty.structFieldIsComptime(next_field_index, zcu)) continue;
+                const field_ty = container_ty.structFieldType(next_field_index, zcu);
+                if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
-                break :blk .{ .field = if (container_ty.isSimpleTuple(mod))
+                break :blk .{ .field = if (container_ty.isSimpleTuple(zcu))
                     .{ .field = next_field_index }
                 else
-                    .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } };
+                    .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, zcu)) } };
             }
-            break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin;
+            break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin;
         },
         .Union => {
-            const union_obj = mod.typeToUnion(container_ty).?;
+            const union_obj = zcu.typeToUnion(container_ty).?;
             return switch (union_obj.getLayout(ip)) {
                 .auto, .@"extern" => {
                     const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
-                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
-                        return if (container_ty.unionTagTypeSafety(mod) != null and
-                            !container_ty.unionHasAllZeroBitFieldTypes(mod))
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu))
+                        return if (container_ty.unionTagTypeSafety(zcu) != null and
+                            !container_ty.unionHasAllZeroBitFieldTypes(zcu))
                             .{ .field = .{ .identifier = "payload" } }
                         else
                             .begin;
                     const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
-                    return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
+                    return .{ .field = if (container_ty.unionTagTypeSafety(zcu)) |_|
                         .{ .payload_identifier = ip.stringToSlice(field_name) }
                     else
                         .{ .identifier = ip.stringToSlice(field_name) } };
@@ -5483,7 +5555,7 @@ fn fieldLocation(
                 .@"packed" => .begin,
             };
         },
-        .Pointer => switch (container_ty.ptrSize(mod)) {
+        .Pointer => switch (container_ty.ptrSize(zcu)) {
             .Slice => switch (field_index) {
                 0 => .{ .field = .{ .identifier = "ptr" } },
                 1 => .{ .field = .{ .identifier = "len" } },
@@ -5515,12 +5587,12 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
 }
 
 fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
 
     const container_ptr_ty = f.typeOfIndex(inst);
-    const container_ty = container_ptr_ty.childType(mod);
+    const container_ty = container_ptr_ty.childType(zcu);
 
     const field_ptr_ty = f.typeOf(extra.field_ptr);
     const field_ptr_val = try f.resolveInst(extra.field_ptr);
@@ -5533,10 +5605,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
     try f.renderType(writer, container_ptr_ty);
     try writer.writeByte(')');
 
-    switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, mod)) {
+    switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) {
         .begin => try f.writeCValue(writer, field_ptr_val, .Initializer),
         .field => |field| {
-            const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
+            const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8);
 
             try writer.writeAll("((");
             try f.renderType(writer, u8_ptr_ty);
@@ -5549,19 +5621,19 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
             try writer.writeAll("))");
         },
         .byte_offset => |byte_offset| {
-            const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
-
-            const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
+            const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8);
 
             try writer.writeAll("((");
             try f.renderType(writer, u8_ptr_ty);
             try writer.writeByte(')');
             try f.writeCValue(writer, field_ptr_val, .Other);
-            try writer.print(" - {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
+            try writer.print(" - {})", .{
+                try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)),
+            });
         },
         .end => {
             try f.writeCValue(writer, field_ptr_val, .Other);
-            try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
+            try writer.print(" - {}", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))});
         },
     }
 
@@ -5576,8 +5648,8 @@ fn fieldPtr(
     container_ptr_val: CValue,
     field_index: u32,
 ) !CValue {
-    const mod = f.object.dg.module;
-    const container_ty = container_ptr_ty.childType(mod);
+    const zcu = f.object.dg.zcu;
+    const container_ty = container_ptr_ty.childType(zcu);
     const field_ptr_ty = f.typeOfIndex(inst);
 
     // Ensure complete type definition is visible before accessing fields.
@@ -5590,27 +5662,27 @@ fn fieldPtr(
     try f.renderType(writer, field_ptr_ty);
     try writer.writeByte(')');
 
-    switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, mod)) {
+    switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) {
         .begin => try f.writeCValue(writer, container_ptr_val, .Initializer),
         .field => |field| {
             try writer.writeByte('&');
             try f.writeCValueDerefMember(writer, container_ptr_val, field);
         },
         .byte_offset => |byte_offset| {
-            const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
-
-            const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
+            const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8);
 
             try writer.writeAll("((");
             try f.renderType(writer, u8_ptr_ty);
             try writer.writeByte(')');
             try f.writeCValue(writer, container_ptr_val, .Other);
-            try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
+            try writer.print(" + {})", .{
+                try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)),
+            });
         },
         .end => {
             try writer.writeByte('(');
             try f.writeCValue(writer, container_ptr_val, .Other);
-            try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
+            try writer.print(" + {})", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))});
         },
     }
 
@@ -5619,13 +5691,13 @@ fn fieldPtr(
 }
 
 fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = f.object.dg.zcu;
+    const ip = &zcu.intern_pool;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
 
     const inst_ty = f.typeOfIndex(inst);
-    if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try reap(f, inst, &.{extra.struct_operand});
         return .none;
     }
@@ -5638,26 +5710,25 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
     // Ensure complete type definition is visible before accessing fields.
     _ = try f.typeToIndex(struct_ty, .complete);
 
-    const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
-        .struct_type => switch (struct_ty.containerLayout(mod)) {
-            .auto, .@"extern" => if (struct_ty.isSimpleTuple(mod))
+    const field_name: CValue = switch (zcu.intern_pool.indexToKey(struct_ty.toIntern())) {
+        .struct_type => switch (struct_ty.containerLayout(zcu)) {
+            .auto, .@"extern" => if (struct_ty.isSimpleTuple(zcu))
                 .{ .field = extra.field_index }
             else
-                .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
+                .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) },
             .@"packed" => {
-                const struct_type = mod.typeToStruct(struct_ty).?;
-                const int_info = struct_ty.intInfo(mod);
+                const struct_type = zcu.typeToStruct(struct_ty).?;
+                const int_info = struct_ty.intInfo(zcu);
 
-                const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
+                const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
 
-                const bit_offset = mod.structPackedFieldBitOffset(struct_type, extra.field_index);
-                const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
+                const bit_offset = zcu.structPackedFieldBitOffset(struct_type, extra.field_index);
 
-                const field_int_signedness = if (inst_ty.isAbiInt(mod))
-                    inst_ty.intInfo(mod).signedness
+                const field_int_signedness = if (inst_ty.isAbiInt(zcu))
+                    inst_ty.intInfo(zcu).signedness
                 else
                     .unsigned;
-                const field_int_ty = try mod.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(mod))));
+                const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu))));
 
                 const temp_local = try f.allocLocal(inst, field_int_ty);
                 try f.writeCValue(writer, temp_local, .Other);
@@ -5668,7 +5739,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
                 try writer.writeByte(')');
                 const cant_cast = int_info.bits > 64;
                 if (cant_cast) {
-                    if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
+                    if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
                     try writer.writeAll("zig_lo_");
                     try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
                     try writer.writeByte('(');
@@ -5681,13 +5752,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
                 try f.writeCValue(writer, struct_byval, .Other);
                 if (bit_offset > 0) {
                     try writer.writeAll(", ");
-                    try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
+                    try f.object.dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument);
                     try writer.writeByte(')');
                 }
                 if (cant_cast) try writer.writeByte(')');
                 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits);
                 try writer.writeAll(");\n");
-                if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
+                if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local;
 
                 const local = try f.allocLocal(inst, inst_ty);
                 try writer.writeAll("memcpy(");
@@ -5705,7 +5776,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
         .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
             .{ .field = extra.field_index }
         else
-            .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) },
+            .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) },
 
         .union_type => field_name: {
             const union_obj = ip.loadUnionType(struct_ty.toIntern());
@@ -5757,7 +5828,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
 /// *(E!T) -> E
 /// Note that the result is never a pointer.
 fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
@@ -5765,13 +5836,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
     const operand_ty = f.typeOf(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
 
-    const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer;
-    const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
-    const error_ty = error_union_ty.errorUnionSet(mod);
-    const payload_ty = error_union_ty.errorUnionPayload(mod);
+    const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .Pointer;
+    const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty;
+    const error_ty = error_union_ty.errorUnionSet(zcu);
+    const payload_ty = error_union_ty.errorUnionPayload(zcu);
     const local = try f.allocLocal(inst, inst_ty);
 
-    if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) {
+    if (!payload_ty.hasRuntimeBits(zcu) and operand == .local and operand.local == local.new_local) {
         // The store will be 'x = x'; elide it.
         return local;
     }
@@ -5780,35 +5851,32 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
     try f.writeCValue(writer, local, .Other);
     try writer.writeAll(" = ");
 
-    if (!payload_ty.hasRuntimeBits(mod)) {
-        try f.writeCValue(writer, operand, .Other);
-    } else {
-        if (!error_ty.errorSetIsEmpty(mod))
-            if (operand_is_ptr)
-                try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
-            else
-                try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
-        else {
-            const err_int_ty = try mod.errorIntType();
-            try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer);
-        }
-    }
+    if (!payload_ty.hasRuntimeBits(zcu))
+        try f.writeCValue(writer, operand, .Other)
+    else if (error_ty.errorSetIsEmpty(zcu))
+        try writer.print("{}", .{
+            try f.fmtIntLiteral(try zcu.intValue(try zcu.errorIntType(), 0)),
+        })
+    else if (operand_is_ptr)
+        try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
+    else
+        try f.writeCValueMember(writer, operand, .{ .identifier = "error" });
     try writer.writeAll(";\n");
     return local;
 }
 
 fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const operand_ty = f.typeOf(ty_op.operand);
-    const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
+    const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
 
     const writer = f.object.writer();
-    if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) {
+    if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) {
         if (!is_ptr) return .none;
 
         const local = try f.allocLocal(inst, inst_ty);
@@ -5834,11 +5902,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
 }
 
 fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
-    const repr_is_payload = inst_ty.optionalReprIsPayload(mod);
+    const repr_is_payload = inst_ty.optionalReprIsPayload(zcu);
     const payload_ty = f.typeOf(ty_op.operand);
     const payload = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
@@ -5859,20 +5927,20 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
         const a = try Assignment.start(f, writer, Type.bool);
         try f.writeCValueMember(writer, local, .{ .identifier = "is_null" });
         try a.assign(f, writer);
-        try f.object.dg.renderValue(writer, Type.bool, Value.false, .Other);
+        try f.object.dg.renderValue(writer, Value.false, .Other);
         try a.end(f, writer);
     }
     return local;
 }
 
 fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
-    const payload_ty = inst_ty.errorUnionPayload(mod);
-    const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
-    const err_ty = inst_ty.errorUnionSet(mod);
+    const payload_ty = inst_ty.errorUnionPayload(zcu);
+    const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
+    const err_ty = inst_ty.errorUnionSet(zcu);
     const err = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
 
@@ -5888,7 +5956,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
         const a = try Assignment.start(f, writer, payload_ty);
         try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
         try a.assign(f, writer);
-        try f.object.dg.renderValue(writer, payload_ty, Value.undef, .Other);
+        try f.object.dg.renderUndefValue(writer, payload_ty, .Other);
         try a.end(f, writer);
     }
     {
@@ -5905,29 +5973,25 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const writer = f.object.writer();
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
     const operand = try f.resolveInst(ty_op.operand);
-    const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
+    const error_union_ty = f.typeOf(ty_op.operand).childType(zcu);
 
-    const payload_ty = error_union_ty.errorUnionPayload(mod);
-    const err_int_ty = try mod.errorIntType();
+    const payload_ty = error_union_ty.errorUnionPayload(zcu);
+    const err_int_ty = try zcu.errorIntType();
+    const no_err = try zcu.intValue(err_int_ty, 0);
 
     // First, set the non-error value.
-    if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
+    if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
         try f.writeCValueDeref(writer, operand);
-        try writer.writeAll(" = ");
-        try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
-        try writer.writeAll(";\n ");
-
+        try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)});
         return operand;
     }
     try reap(f, inst, &.{ty_op.operand});
     try f.writeCValueDeref(writer, operand);
-    try writer.writeAll(".error = ");
-    try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
-    try writer.writeAll(";\n");
+    try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)});
 
     // Then return the payload pointer (only if it is used)
     if (f.liveness.isUnused(inst)) return .none;
@@ -5956,14 +6020,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
-    const payload_ty = inst_ty.errorUnionPayload(mod);
+    const payload_ty = inst_ty.errorUnionPayload(zcu);
     const payload = try f.resolveInst(ty_op.operand);
-    const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
-    const err_ty = inst_ty.errorUnionSet(mod);
+    const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu);
+    const err_ty = inst_ty.errorUnionSet(zcu);
     try reap(f, inst, &.{ty_op.operand});
 
     const writer = f.object.writer();
@@ -5982,15 +6046,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
         else
             try f.writeCValueMember(writer, local, .{ .identifier = "error" });
         try a.assign(f, writer);
-        const err_int_ty = try mod.errorIntType();
-        try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
+        try f.object.dg.renderValue(writer, try zcu.intValue(try zcu.errorIntType(), 0), .Other);
         try a.end(f, writer);
     }
     return local;
 }
 
 fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
 
     const writer = f.object.writer();
@@ -5998,16 +6061,16 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
     try reap(f, inst, &.{un_op});
     const operand_ty = f.typeOf(un_op);
     const local = try f.allocLocal(inst, Type.bool);
-    const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
-    const payload_ty = err_union_ty.errorUnionPayload(mod);
-    const error_ty = err_union_ty.errorUnionSet(mod);
+    const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty;
+    const payload_ty = err_union_ty.errorUnionPayload(zcu);
+    const error_ty = err_union_ty.errorUnionSet(zcu);
 
+    const a = try Assignment.start(f, writer, Type.bool);
     try f.writeCValue(writer, local, .Other);
-    try writer.writeAll(" = ");
-
-    const err_int_ty = try mod.errorIntType();
-    if (!error_ty.errorSetIsEmpty(mod))
-        if (payload_ty.hasRuntimeBits(mod))
+    try a.assign(f, writer);
+    const err_int_ty = try zcu.errorIntType();
+    if (!error_ty.errorSetIsEmpty(zcu))
+        if (payload_ty.hasRuntimeBits(zcu))
             if (is_ptr)
                 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
             else
@@ -6015,63 +6078,84 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
         else
             try f.writeCValue(writer, operand, .Other)
     else
-        try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
+        try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other);
     try writer.writeByte(' ');
     try writer.writeAll(operator);
     try writer.writeByte(' ');
-    try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
-    try writer.writeAll(";\n");
+    try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other);
+    try a.end(f, writer);
     return local;
 }
 
 fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const inst_ty = f.typeOfIndex(inst);
+    const ptr_ty = inst_ty.slicePtrFieldType(zcu);
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
-    const array_ty = f.typeOf(ty_op.operand).childType(mod);
-
-    try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
-    try writer.writeAll(" = ");
-    // Unfortunately, C does not support any equivalent to
-    // &(*(void *)p)[0], although LLVM does via GetElementPtr
-    if (operand == .undef) {
-        try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(mod) }, .Initializer);
-    } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
-        try writer.writeAll("&(");
-        try f.writeCValueDeref(writer, operand);
-        try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
-    } else try f.writeCValue(writer, operand, .Initializer);
-    try writer.writeAll("; ");
+    const operand_ty = f.typeOf(ty_op.operand);
+    const array_ty = operand_ty.childType(zcu);
 
-    const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
-    try f.writeCValueMember(writer, local, .{ .identifier = "len" });
-    try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
+    {
+        const a = try Assignment.start(f, writer, ptr_ty);
+        try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
+        try a.assign(f, writer);
+        if (operand == .undef) {
+            try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer);
+        } else {
+            const ptr_cty = try f.typeToIndex(ptr_ty, .complete);
+            const ptr_child_cty = f.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data;
+            const elem_ty = array_ty.childType(zcu);
+            const elem_cty = try f.typeToIndex(elem_ty, .complete);
+            if (ptr_child_cty != elem_cty) {
+                try writer.writeByte('(');
+                try f.renderCType(writer, ptr_cty);
+                try writer.writeByte(')');
+            }
+            const operand_cty = try f.typeToCType(operand_ty, .complete);
+            const operand_child_cty = operand_cty.cast(CType.Payload.Child).?.data;
+            if (f.indexToCType(operand_child_cty).tag() == .array) {
+                try writer.writeByte('&');
+                try f.writeCValueDeref(writer, operand);
+                try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))});
+            } else try f.writeCValue(writer, operand, .Initializer);
+        }
+        try a.end(f, writer);
+    }
+    {
+        const a = try Assignment.start(f, writer, Type.usize);
+        try f.writeCValueMember(writer, local, .{ .identifier = "len" });
+        try a.assign(f, writer);
+        try writer.print("{}", .{
+            try f.fmtIntLiteral(try zcu.intValue(Type.usize, array_ty.arrayLen(zcu))),
+        });
+        try a.end(f, writer);
+    }
 
     return local;
 }
 
 fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const operand_ty = f.typeOf(ty_op.operand);
-    const scalar_ty = operand_ty.scalarType(mod);
-    const target = f.object.dg.module.getTarget();
+    const scalar_ty = operand_ty.scalarType(zcu);
+    const target = &f.object.dg.mod.resolved_target.result;
     const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat())
-        if (inst_scalar_ty.floatBits(target) < scalar_ty.floatBits(target)) "trunc" else "extend"
-    else if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat())
-        if (inst_scalar_ty.isSignedInt(mod)) "fix" else "fixuns"
-    else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(mod))
-        if (scalar_ty.isSignedInt(mod)) "float" else "floatun"
+        if (inst_scalar_ty.floatBits(target.*) < scalar_ty.floatBits(target.*)) "trunc" else "extend"
+    else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat())
+        if (inst_scalar_ty.isSignedInt(zcu)) "fix" else "fixuns"
+    else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(zcu))
+        if (scalar_ty.isSignedInt(zcu)) "float" else "floatun"
     else
         unreachable;
 
@@ -6082,20 +6166,20 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
     try f.writeCValue(writer, local, .Other);
     try v.elem(f, writer);
     try a.assign(f, writer);
-    if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) {
+    if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
         try writer.writeAll("zig_wrap_");
         try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
         try writer.writeByte('(');
     }
     try writer.writeAll("zig_");
     try writer.writeAll(operation);
-    try writer.writeAll(compilerRtAbbrev(scalar_ty, mod));
-    try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, mod));
+    try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target.*));
+    try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target.*));
     try writer.writeByte('(');
     try f.writeCValue(writer, operand, .FunctionArgument);
     try v.elem(f, writer);
     try writer.writeByte(')');
-    if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) {
+    if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) {
         try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits);
         try writer.writeByte(')');
     }
@@ -6106,7 +6190,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
 
     const operand = try f.resolveInst(un_op);
@@ -6120,7 +6204,7 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(" = (");
     try f.renderType(writer, inst_ty);
     try writer.writeByte(')');
-    if (operand_ty.isSlice(mod)) {
+    if (operand_ty.isSlice(zcu)) {
         try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" });
     } else {
         try f.writeCValue(writer, operand, .Other);
@@ -6135,15 +6219,15 @@ fn airUnBuiltinCall(
     operation: []const u8,
     info: BuiltinInfo,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
     const operand_ty = f.typeOf(ty_op.operand);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
     const ref_ret = inst_scalar_cty.tag() == .array;
@@ -6179,7 +6263,7 @@ fn airBinBuiltinCall(
     operation: []const u8,
     info: BuiltinInfo,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
 
     const operand_ty = f.typeOf(bin_op.lhs);
@@ -6191,8 +6275,8 @@ fn airBinBuiltinCall(
     if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
     const ref_ret = inst_scalar_cty.tag() == .array;
@@ -6234,15 +6318,15 @@ fn airCmpBuiltinCall(
     operation: enum { cmp, operator },
     info: BuiltinInfo,
 ) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const lhs = try f.resolveInst(data.lhs);
     const rhs = try f.resolveInst(data.rhs);
     try reap(f, inst, &.{ data.lhs, data.rhs });
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
     const operand_ty = f.typeOf(data.lhs);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
     const ref_ret = inst_scalar_cty.tag() == .array;
@@ -6275,7 +6359,7 @@ fn airCmpBuiltinCall(
     try writer.writeByte(')');
     if (!ref_ret) try writer.print("{s}{}", .{
         compareOperatorC(operator),
-        try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)),
+        try f.fmtIntLiteral(try zcu.intValue(Type.i32, 0)),
     });
     try writer.writeAll(";\n");
     try v.end(f, inst, writer);
@@ -6284,7 +6368,7 @@ fn airCmpBuiltinCall(
 }
 
 fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
     const inst_ty = f.typeOfIndex(inst);
@@ -6292,19 +6376,19 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
     const expected_value = try f.resolveInst(extra.expected_value);
     const new_value = try f.resolveInst(extra.new_value);
     const ptr_ty = f.typeOf(extra.ptr);
-    const ty = ptr_ty.childType(mod);
+    const ty = ptr_ty.childType(zcu);
 
     const writer = f.object.writer();
     const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);
     try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
 
     const repr_ty = if (ty.isRuntimeFloat())
-        mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
+        zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
     else
         ty;
 
     const local = try f.allocLocal(inst, inst_ty);
-    if (inst_ty.isPtrLikeOptional(mod)) {
+    if (inst_ty.isPtrLikeOptional(zcu)) {
         {
             const a = try Assignment.start(f, writer, ty);
             try f.writeCValue(writer, local, .Other);
@@ -6317,7 +6401,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
         try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
         try f.renderType(writer, ty);
         try writer.writeByte(')');
-        if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
+        if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
         try writer.writeAll(" *)");
         try f.writeCValue(writer, ptr, .Other);
         try writer.writeAll(", ");
@@ -6331,7 +6415,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
         try writer.writeAll(", ");
         try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
         try writer.writeAll(", ");
-        try f.object.dg.renderType(writer, repr_ty);
+        try f.renderType(writer, repr_ty);
         try writer.writeByte(')');
         try writer.writeAll(") {\n");
         f.object.indent_writer.pushIndent();
@@ -6359,7 +6443,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
             try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
             try f.renderType(writer, ty);
             try writer.writeByte(')');
-            if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
+            if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
             try writer.writeAll(" *)");
             try f.writeCValue(writer, ptr, .Other);
             try writer.writeAll(", ");
@@ -6373,7 +6457,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
             try writer.writeAll(", ");
             try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
             try writer.writeAll(", ");
-            try f.object.dg.renderType(writer, repr_ty);
+            try f.renderType(writer, repr_ty);
             try writer.writeByte(')');
             try a.end(f, writer);
         }
@@ -6389,12 +6473,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
 }
 
 fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
     const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;
     const inst_ty = f.typeOfIndex(inst);
     const ptr_ty = f.typeOf(pl_op.operand);
-    const ty = ptr_ty.childType(mod);
+    const ty = ptr_ty.childType(zcu);
     const ptr = try f.resolveInst(pl_op.operand);
     const operand = try f.resolveInst(extra.operand);
 
@@ -6402,10 +6486,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
     const operand_mat = try Materialize.start(f, inst, writer, ty, operand);
     try reap(f, inst, &.{ pl_op.operand, extra.operand });
 
-    const repr_bits = @as(u16, @intCast(ty.abiSize(mod) * 8));
+    const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8));
     const is_float = ty.isRuntimeFloat();
     const is_128 = repr_bits == 128;
-    const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty;
+    const repr_ty = if (is_float) zcu.intType(.unsigned, repr_bits) catch unreachable else ty;
 
     const local = try f.allocLocal(inst, inst_ty);
     try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
@@ -6421,7 +6505,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
     if (use_atomic) try writer.writeAll("zig_atomic(");
     try f.renderType(writer, ty);
     if (use_atomic) try writer.writeByte(')');
-    if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
+    if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
     try writer.writeAll(" *)");
     try f.writeCValue(writer, ptr, .Other);
     try writer.writeAll(", ");
@@ -6431,7 +6515,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(", ");
     try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
     try writer.writeAll(", ");
-    try f.object.dg.renderType(writer, repr_ty);
+    try f.renderType(writer, repr_ty);
     try writer.writeAll(");\n");
     try operand_mat.end(f, inst);
 
@@ -6444,15 +6528,15 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load;
     const ptr = try f.resolveInst(atomic_load.ptr);
     try reap(f, inst, &.{atomic_load.ptr});
     const ptr_ty = f.typeOf(atomic_load.ptr);
-    const ty = ptr_ty.childType(mod);
+    const ty = ptr_ty.childType(zcu);
 
     const repr_ty = if (ty.isRuntimeFloat())
-        mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
+        zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
     else
         ty;
 
@@ -6465,7 +6549,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(", (zig_atomic(");
     try f.renderType(writer, ty);
     try writer.writeByte(')');
-    if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
+    if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
     try writer.writeAll(" *)");
     try f.writeCValue(writer, ptr, .Other);
     try writer.writeAll(", ");
@@ -6473,17 +6557,17 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(", ");
     try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
     try writer.writeAll(", ");
-    try f.object.dg.renderType(writer, repr_ty);
+    try f.renderType(writer, repr_ty);
     try writer.writeAll(");\n");
 
     return local;
 }
 
 fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const ptr_ty = f.typeOf(bin_op.lhs);
-    const ty = ptr_ty.childType(mod);
+    const ty = ptr_ty.childType(zcu);
     const ptr = try f.resolveInst(bin_op.lhs);
     const element = try f.resolveInst(bin_op.rhs);
 
@@ -6492,14 +6576,14 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const repr_ty = if (ty.isRuntimeFloat())
-        mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable
+        zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable
     else
         ty;
 
     try writer.writeAll("zig_atomic_store((zig_atomic(");
     try f.renderType(writer, ty);
     try writer.writeByte(')');
-    if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
+    if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile");
     try writer.writeAll(" *)");
     try f.writeCValue(writer, ptr, .Other);
     try writer.writeAll(", ");
@@ -6507,7 +6591,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
     try writer.print(", {s}, ", .{order});
     try f.object.dg.renderTypeForBuiltinFnName(writer, ty);
     try writer.writeAll(", ");
-    try f.object.dg.renderType(writer, repr_ty);
+    try f.renderType(writer, repr_ty);
     try writer.writeAll(");\n");
     try element_mat.end(f, inst);
 
@@ -6515,8 +6599,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
 }
 
 fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {
-    const mod = f.object.dg.module;
-    if (ptr_ty.isSlice(mod)) {
+    const zcu = f.object.dg.zcu;
+    if (ptr_ty.isSlice(zcu)) {
         try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
     } else {
         try f.writeCValue(writer, ptr, .FunctionArgument);
@@ -6524,14 +6608,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo
 }
 
 fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const dest_ty = f.typeOf(bin_op.lhs);
     const dest_slice = try f.resolveInst(bin_op.lhs);
     const value = try f.resolveInst(bin_op.rhs);
     const elem_ty = f.typeOf(bin_op.rhs);
-    const elem_abi_size = elem_ty.abiSize(mod);
-    const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
+    const elem_abi_size = elem_ty.abiSize(zcu);
+    const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |val| val.isUndefDeep(zcu) else false;
     const writer = f.object.writer();
 
     if (val_is_undef) {
@@ -6541,7 +6625,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         }
 
         try writer.writeAll("memset(");
-        switch (dest_ty.ptrSize(mod)) {
+        switch (dest_ty.ptrSize(zcu)) {
             .Slice => {
                 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
                 try writer.writeAll(", 0xaa, ");
@@ -6553,8 +6637,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
                 }
             },
             .One => {
-                const array_ty = dest_ty.childType(mod);
-                const len = array_ty.arrayLen(mod) * elem_abi_size;
+                const array_ty = dest_ty.childType(zcu);
+                const len = array_ty.arrayLen(zcu) * elem_abi_size;
 
                 try f.writeCValue(writer, dest_slice, .FunctionArgument);
                 try writer.print(", 0xaa, {d});\n", .{len});
@@ -6565,12 +6649,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         return .none;
     }
 
-    if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) {
+    if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) {
         // For the assignment in this loop, the array pointer needs to get
         // casted to a regular pointer, otherwise an error like this occurs:
         // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
-        const elem_ptr_ty = try mod.ptrType(.{
-            .child = elem_ty.ip_index,
+        const elem_ptr_ty = try zcu.ptrType(.{
+            .child = elem_ty.toIntern(),
             .flags = .{
                 .size = .C,
             },
@@ -6581,17 +6665,17 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
         try writer.writeAll("for (");
         try f.writeCValue(writer, index, .Other);
         try writer.writeAll(" = ");
-        try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, 0), .Initializer);
+        try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, 0), .Initializer);
         try writer.writeAll("; ");
         try f.writeCValue(writer, index, .Other);
         try writer.writeAll(" != ");
-        switch (dest_ty.ptrSize(mod)) {
+        switch (dest_ty.ptrSize(zcu)) {
             .Slice => {
                 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
             },
             .One => {
-                const array_ty = dest_ty.childType(mod);
-                try writer.print("{d}", .{array_ty.arrayLen(mod)});
+                const array_ty = dest_ty.childType(zcu);
+                try writer.print("{d}", .{array_ty.arrayLen(zcu)});
             },
             .Many, .C => unreachable,
         }
@@ -6620,7 +6704,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
     const bitcasted = try bitcast(f, Type.u8, value, elem_ty);
 
     try writer.writeAll("memset(");
-    switch (dest_ty.ptrSize(mod)) {
+    switch (dest_ty.ptrSize(zcu)) {
         .Slice => {
             try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
             try writer.writeAll(", ");
@@ -6630,8 +6714,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
             try writer.writeAll(");\n");
         },
         .One => {
-            const array_ty = dest_ty.childType(mod);
-            const len = array_ty.arrayLen(mod) * elem_abi_size;
+            const array_ty = dest_ty.childType(zcu);
+            const len = array_ty.arrayLen(zcu) * elem_abi_size;
 
             try f.writeCValue(writer, dest_slice, .FunctionArgument);
             try writer.writeAll(", ");
@@ -6646,7 +6730,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
 }
 
 fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const dest_ptr = try f.resolveInst(bin_op.lhs);
     const src_ptr = try f.resolveInst(bin_op.rhs);
@@ -6659,10 +6743,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
     try writer.writeAll(", ");
     try writeSliceOrPtr(f, writer, src_ptr, src_ty);
     try writer.writeAll(", ");
-    switch (dest_ty.ptrSize(mod)) {
+    switch (dest_ty.ptrSize(zcu)) {
         .Slice => {
-            const elem_ty = dest_ty.childType(mod);
-            const elem_abi_size = elem_ty.abiSize(mod);
+            const elem_ty = dest_ty.childType(zcu);
+            const elem_abi_size = elem_ty.abiSize(zcu);
             try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" });
             if (elem_abi_size > 1) {
                 try writer.print(" * {d});\n", .{elem_abi_size});
@@ -6671,10 +6755,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
             }
         },
         .One => {
-            const array_ty = dest_ty.childType(mod);
-            const elem_ty = array_ty.childType(mod);
-            const elem_abi_size = elem_ty.abiSize(mod);
-            const len = array_ty.arrayLen(mod) * elem_abi_size;
+            const array_ty = dest_ty.childType(zcu);
+            const elem_ty = array_ty.childType(zcu);
+            const elem_abi_size = elem_ty.abiSize(zcu);
+            const len = array_ty.arrayLen(zcu) * elem_abi_size;
             try writer.print("{d});\n", .{len});
         },
         .Many, .C => unreachable,
@@ -6685,16 +6769,16 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
     const union_ptr = try f.resolveInst(bin_op.lhs);
     const new_tag = try f.resolveInst(bin_op.rhs);
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
-    const union_ty = f.typeOf(bin_op.lhs).childType(mod);
-    const layout = union_ty.unionGetLayout(mod);
+    const union_ty = f.typeOf(bin_op.lhs).childType(zcu);
+    const layout = union_ty.unionGetLayout(zcu);
     if (layout.tag_size == 0) return .none;
-    const tag_ty = union_ty.unionTagTypeSafety(mod).?;
+    const tag_ty = union_ty.unionTagTypeSafety(zcu).?;
 
     const writer = f.object.writer();
     const a = try Assignment.start(f, writer, tag_ty);
@@ -6706,14 +6790,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
 
     const union_ty = f.typeOf(ty_op.operand);
-    const layout = union_ty.unionGetLayout(mod);
+    const layout = union_ty.unionGetLayout(zcu);
     if (layout.tag_size == 0) return .none;
 
     const inst_ty = f.typeOfIndex(inst);
@@ -6728,7 +6812,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
 
     const inst_ty = f.typeOfIndex(inst);
@@ -6740,7 +6824,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
     const local = try f.allocLocal(inst, inst_ty);
     try f.writeCValue(writer, local, .Other);
     try writer.print(" = {s}(", .{
-        try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(mod) }, .{ .tag_name = enum_ty }),
+        try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(zcu) }, .{ .tag_name = enum_ty }),
     });
     try f.writeCValue(writer, operand, .Other);
     try writer.writeAll(");\n");
@@ -6765,14 +6849,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
 
     const operand = try f.resolveInst(ty_op.operand);
     try reap(f, inst, &.{ty_op.operand});
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -6820,7 +6904,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data;
 
@@ -6836,15 +6920,15 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
     for (0..extra.mask_len) |index| {
         try f.writeCValue(writer, local, .Other);
         try writer.writeByte('[');
-        try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, index), .Other);
+        try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, index), .Other);
         try writer.writeAll("] = ");
 
-        const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
-        const src_val = try mod.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63)));
+        const mask_elem = (try mask.elemValue(zcu, index)).toSignedInt(zcu);
+        const src_val = try zcu.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63)));
 
         try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
         try writer.writeByte('[');
-        try f.object.dg.renderValue(writer, Type.usize, src_val, .Other);
+        try f.object.dg.renderValue(writer, src_val, .Other);
         try writer.writeAll("];\n");
     }
 
@@ -6852,7 +6936,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce;
 
     const scalar_ty = f.typeOfIndex(inst);
@@ -6861,7 +6945,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
     const operand_ty = f.typeOf(reduce.operand);
     const writer = f.object.writer();
 
-    const use_operator = scalar_ty.bitSize(mod) <= 64;
+    const use_operator = scalar_ty.bitSize(zcu) <= 64;
     const op: union(enum) {
         const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
         float_op: Func,
@@ -6872,28 +6956,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
         .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },
         .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
         .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
-        .Min => switch (scalar_ty.zigTypeTag(mod)) {
+        .Min => switch (scalar_ty.zigTypeTag(zcu)) {
             .Int => if (use_operator) .{ .ternary = " < " } else .{
                 .builtin = .{ .operation = "min" },
             },
             .Float => .{ .float_op = .{ .operation = "fmin" } },
             else => unreachable,
         },
-        .Max => switch (scalar_ty.zigTypeTag(mod)) {
+        .Max => switch (scalar_ty.zigTypeTag(zcu)) {
             .Int => if (use_operator) .{ .ternary = " > " } else .{
                 .builtin = .{ .operation = "max" },
             },
             .Float => .{ .float_op = .{ .operation = "fmax" } },
             else => unreachable,
         },
-        .Add => switch (scalar_ty.zigTypeTag(mod)) {
+        .Add => switch (scalar_ty.zigTypeTag(zcu)) {
             .Int => if (use_operator) .{ .infix = " += " } else .{
                 .builtin = .{ .operation = "addw", .info = .bits },
             },
             .Float => .{ .builtin = .{ .operation = "add" } },
             else => unreachable,
         },
-        .Mul => switch (scalar_ty.zigTypeTag(mod)) {
+        .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
             .Int => if (use_operator) .{ .infix = " *= " } else .{
                 .builtin = .{ .operation = "mulw", .info = .bits },
             },
@@ -6908,7 +6992,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
     // Equivalent to:
     //   reduce: {
     //     var accum: T = init;
-    //     for (vec) : (elem) {
+    //     for (vec) |elem| {
     //       accum = func(accum, elem);
     //     }
     //     break :reduce accum;
@@ -6918,40 +7002,40 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
     try f.writeCValue(writer, accum, .Other);
     try writer.writeAll(" = ");
 
-    try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
-        .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
+    try f.object.dg.renderValue(writer, switch (reduce.operation) {
+        .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) {
             .Bool => Value.false,
-            .Int => try mod.intValue(scalar_ty, 0),
+            .Int => try zcu.intValue(scalar_ty, 0),
             else => unreachable,
         },
-        .And => switch (scalar_ty.zigTypeTag(mod)) {
+        .And => switch (scalar_ty.zigTypeTag(zcu)) {
             .Bool => Value.true,
-            .Int => switch (scalar_ty.intInfo(mod).signedness) {
-                .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty),
-                .signed => try mod.intValue(scalar_ty, -1),
+            .Int => switch (scalar_ty.intInfo(zcu).signedness) {
+                .unsigned => try scalar_ty.maxIntScalar(zcu, scalar_ty),
+                .signed => try zcu.intValue(scalar_ty, -1),
             },
             else => unreachable,
         },
-        .Add => switch (scalar_ty.zigTypeTag(mod)) {
-            .Int => try mod.intValue(scalar_ty, 0),
-            .Float => try mod.floatValue(scalar_ty, 0.0),
+        .Add => switch (scalar_ty.zigTypeTag(zcu)) {
+            .Int => try zcu.intValue(scalar_ty, 0),
+            .Float => try zcu.floatValue(scalar_ty, 0.0),
             else => unreachable,
         },
-        .Mul => switch (scalar_ty.zigTypeTag(mod)) {
-            .Int => try mod.intValue(scalar_ty, 1),
-            .Float => try mod.floatValue(scalar_ty, 1.0),
+        .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
+            .Int => try zcu.intValue(scalar_ty, 1),
+            .Float => try zcu.floatValue(scalar_ty, 1.0),
             else => unreachable,
         },
-        .Min => switch (scalar_ty.zigTypeTag(mod)) {
+        .Min => switch (scalar_ty.zigTypeTag(zcu)) {
             .Bool => Value.true,
-            .Int => try scalar_ty.maxIntScalar(mod, scalar_ty),
-            .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
+            .Int => try scalar_ty.maxIntScalar(zcu, scalar_ty),
+            .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)),
             else => unreachable,
         },
-        .Max => switch (scalar_ty.zigTypeTag(mod)) {
+        .Max => switch (scalar_ty.zigTypeTag(zcu)) {
             .Bool => Value.false,
-            .Int => try scalar_ty.minIntScalar(mod, scalar_ty),
-            .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)),
+            .Int => try scalar_ty.minIntScalar(zcu, scalar_ty),
+            .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)),
             else => unreachable,
         },
     }, .Initializer);
@@ -7007,11 +7091,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = f.object.dg.zcu;
+    const ip = &zcu.intern_pool;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const inst_ty = f.typeOfIndex(inst);
-    const len = @as(usize, @intCast(inst_ty.arrayLen(mod)));
+    const len = @as(usize, @intCast(inst_ty.arrayLen(zcu)));
     const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len]));
     const gpa = f.object.dg.gpa;
     const resolved_elements = try gpa.alloc(CValue, elements.len);
@@ -7028,10 +7112,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
-    switch (inst_ty.zigTypeTag(mod)) {
+    switch (inst_ty.zigTypeTag(zcu)) {
         .Array, .Vector => {
-            const elem_ty = inst_ty.childType(mod);
-            const a = try Assignment.init(f, elem_ty);
+            const a = try Assignment.init(f, inst_ty.childType(zcu));
             for (resolved_elements, 0..) |element, i| {
                 try a.restart(f, writer);
                 try f.writeCValue(writer, local, .Other);
@@ -7040,26 +7123,26 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
                 try f.writeCValue(writer, element, .Other);
                 try a.end(f, writer);
             }
-            if (inst_ty.sentinel(mod)) |sentinel| {
+            if (inst_ty.sentinel(zcu)) |sentinel| {
                 try a.restart(f, writer);
                 try f.writeCValue(writer, local, .Other);
                 try writer.print("[{d}]", .{resolved_elements.len});
                 try a.assign(f, writer);
-                try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other);
+                try f.object.dg.renderValue(writer, sentinel, .Other);
                 try a.end(f, writer);
             }
         },
-        .Struct => switch (inst_ty.containerLayout(mod)) {
+        .Struct => switch (inst_ty.containerLayout(zcu)) {
             .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| {
-                if (inst_ty.structFieldIsComptime(field_index, mod)) continue;
-                const field_ty = inst_ty.structFieldType(field_index, mod);
-                if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                if (inst_ty.structFieldIsComptime(field_index, zcu)) continue;
+                const field_ty = inst_ty.structFieldType(field_index, zcu);
+                if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                 const a = try Assignment.start(f, writer, field_ty);
-                try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
+                try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(zcu))
                     .{ .field = field_index }
                 else
-                    .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), mod)) });
+                    .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), zcu)) });
                 try a.assign(f, writer);
                 try f.writeCValue(writer, element, .Other);
                 try a.end(f, writer);
@@ -7067,17 +7150,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
             .@"packed" => {
                 try f.writeCValue(writer, local, .Other);
                 try writer.writeAll(" = ");
-                const int_info = inst_ty.intInfo(mod);
+                const int_info = inst_ty.intInfo(zcu);
 
-                const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
+                const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
 
                 var bit_offset: u64 = 0;
 
                 var empty = true;
                 for (0..elements.len) |field_index| {
-                    if (inst_ty.structFieldIsComptime(field_index, mod)) continue;
-                    const field_ty = inst_ty.structFieldType(field_index, mod);
-                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                    if (inst_ty.structFieldIsComptime(field_index, zcu)) continue;
+                    const field_ty = inst_ty.structFieldType(field_index, zcu);
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                     if (!empty) {
                         try writer.writeAll("zig_or_");
@@ -7088,9 +7171,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
                 }
                 empty = true;
                 for (resolved_elements, 0..) |element, field_index| {
-                    if (inst_ty.structFieldIsComptime(field_index, mod)) continue;
-                    const field_ty = inst_ty.structFieldType(field_index, mod);
-                    if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
+                    if (inst_ty.structFieldIsComptime(field_index, zcu)) continue;
+                    const field_ty = inst_ty.structFieldType(field_index, zcu);
+                    if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
 
                     if (!empty) try writer.writeAll(", ");
                     // TODO: Skip this entire shift if val is 0?
@@ -7098,13 +7181,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
                     try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
                     try writer.writeByte('(');
 
-                    if (inst_ty.isAbiInt(mod) and (field_ty.isAbiInt(mod) or field_ty.isPtrAtRuntime(mod))) {
+                    if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) {
                         try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
                     } else {
                         try writer.writeByte('(');
                         try f.renderType(writer, inst_ty);
                         try writer.writeByte(')');
-                        if (field_ty.isPtrAtRuntime(mod)) {
+                        if (field_ty.isPtrAtRuntime(zcu)) {
                             try writer.writeByte('(');
                             try f.renderType(writer, switch (int_info.signedness) {
                                 .unsigned => Type.usize,
@@ -7115,14 +7198,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
                         try f.writeCValue(writer, element, .Other);
                     }
 
-                    try writer.writeAll(", ");
-                    const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
-                    try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
+                    try writer.print(", {}", .{
+                        try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)),
+                    });
                     try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
                     try writer.writeByte(')');
                     if (!empty) try writer.writeByte(')');
 
-                    bit_offset += field_ty.bitSize(mod);
+                    bit_offset += field_ty.bitSize(zcu);
                     empty = false;
                 }
 
@@ -7136,13 +7219,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
-    const ip = &mod.intern_pool;
+    const zcu = f.object.dg.zcu;
+    const ip = &zcu.intern_pool;
     const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
     const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;
 
     const union_ty = f.typeOfIndex(inst);
-    const union_obj = mod.typeToUnion(union_ty).?;
+    const union_obj = zcu.typeToUnion(union_ty).?;
     const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
     const payload_ty = f.typeOf(extra.init);
     const payload = try f.resolveInst(extra.init);
@@ -7158,19 +7241,16 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
         return local;
     }
 
-    const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: {
-        const layout = union_ty.unionGetLayout(mod);
+    const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: {
+        const layout = union_ty.unionGetLayout(zcu);
         if (layout.tag_size != 0) {
-            const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
-
-            const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
-
-            const int_val = try tag_val.intFromEnum(tag_ty, mod);
+            const field_index = tag_ty.enumFieldIndex(field_name, zcu).?;
+            const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index);
 
             const a = try Assignment.start(f, writer, tag_ty);
             try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
             try a.assign(f, writer);
-            try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)});
+            try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))});
             try a.end(f, writer);
         }
         break :field .{ .payload_identifier = ip.stringToSlice(field_name) };
@@ -7185,7 +7265,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch;
 
     const ptr_ty = f.typeOf(prefetch.ptr);
@@ -7196,7 +7276,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
     switch (prefetch.cache) {
         .data => {
             try writer.writeAll("zig_prefetch(");
-            if (ptr_ty.isSlice(mod))
+            if (ptr_ty.isSlice(zcu))
                 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" })
             else
                 try f.writeCValue(writer, ptr, .FunctionArgument);
@@ -7242,14 +7322,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
 
     const operand = try f.resolveInst(un_op);
     try reap(f, inst, &.{un_op});
 
     const operand_ty = f.typeOf(un_op);
-    const scalar_ty = operand_ty.scalarType(mod);
+    const scalar_ty = operand_ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, operand_ty);
@@ -7268,15 +7348,15 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
     const operand = try f.resolveInst(ty_op.operand);
     const ty = f.typeOf(ty_op.operand);
-    const scalar_ty = ty.scalarType(mod);
+    const scalar_ty = ty.scalarType(zcu);
 
-    switch (scalar_ty.zigTypeTag(mod)) {
-        .Int => if (ty.zigTypeTag(mod) == .Vector) {
-            return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)});
+    switch (scalar_ty.zigTypeTag(zcu)) {
+        .Int => if (ty.zigTypeTag(zcu) == .Vector) {
+            return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(zcu)});
         } else {
             return airUnBuiltinCall(f, inst, "abs", .none);
         },
@@ -7286,8 +7366,8 @@ fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue {
-    const mod = f.object.dg.module;
-    const scalar_ty = ty.scalarType(mod);
+    const zcu = f.object.dg.zcu;
+    const scalar_ty = ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, ty);
@@ -7316,7 +7396,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
 }
 
 fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
 
     const lhs = try f.resolveInst(bin_op.lhs);
@@ -7324,7 +7404,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -7346,7 +7426,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
 }
 
 fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
     const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data;
 
@@ -7356,7 +7436,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
 
     const inst_ty = f.typeOfIndex(inst);
-    const inst_scalar_ty = inst_ty.scalarType(mod);
+    const inst_scalar_ty = inst_ty.scalarType(zcu);
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
@@ -7381,11 +7461,11 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
 }
 
 fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
-    const mod = f.object.dg.module;
+    const zcu = f.object.dg.zcu;
     const inst_ty = f.typeOfIndex(inst);
     const decl_index = f.object.dg.pass.decl;
-    const decl = mod.declPtr(decl_index);
-    const fn_cty = try f.typeToCType(decl.typeOf(mod), .complete);
+    const decl = zcu.declPtr(decl_index);
+    const fn_cty = try f.typeToCType(decl.typeOf(zcu), .complete);
     const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
 
     const writer = f.object.writer();
@@ -7589,9 +7669,8 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
     };
 }
 
-fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 {
-    const target = mod.getTarget();
-    return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) {
+fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: std.Target) []const u8 {
+    return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) {
         1...32 => "si",
         33...64 => "di",
         65...128 => "ti",
@@ -7753,8 +7832,8 @@ fn formatIntLiteral(
     options: std.fmt.FormatOptions,
     writer: anytype,
 ) @TypeOf(writer).Error!void {
-    const mod = data.dg.module;
-    const target = mod.getTarget();
+    const zcu = data.dg.zcu;
+    const target = &data.dg.mod.resolved_target.result;
 
     const ExpectedContents = struct {
         const base = 10;
@@ -7774,7 +7853,7 @@ fn formatIntLiteral(
     defer allocator.free(undef_limbs);
 
     var int_buf: Value.BigIntSpace = undefined;
-    const int = if (data.val.isUndefDeep(mod)) blk: {
+    const int = if (data.val.isUndefDeep(zcu)) blk: {
         undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
         @memset(undef_limbs, undefPattern(BigIntLimb));
 
@@ -7785,10 +7864,10 @@ fn formatIntLiteral(
         };
         undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
         break :blk undef_int.toConst();
-    } else data.val.toBigInt(&int_buf, mod);
+    } else data.val.toBigInt(&int_buf, zcu);
     assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
 
-    const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8);
+    const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, data.dg.mod) * 8);
     var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
     const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
 
@@ -7919,7 +7998,7 @@ fn formatIntLiteral(
                 .int_info = c_limb_int_info,
                 .kind = data.kind,
                 .cty = c_limb_cty,
-                .val = try mod.intValue_big(Type.comptime_int, c_limb_mut.toConst()),
+                .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()),
             }, fmt, options, writer);
         }
     }
@@ -8016,21 +8095,17 @@ const Vectorize = struct {
     index: CValue = .none,
 
     pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
-        const mod = f.object.dg.module;
-        return if (ty.zigTypeTag(mod) == .Vector) index: {
-            const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod));
-
+        const zcu = f.object.dg.zcu;
+        return if (ty.zigTypeTag(zcu) == .Vector) index: {
             const local = try f.allocLocal(inst, Type.usize);
 
             try writer.writeAll("for (");
             try f.writeCValue(writer, local, .Other);
-            try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
+            try writer.print(" = {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))});
             try f.writeCValue(writer, local, .Other);
-            try writer.print(" < {d}; ", .{
-                try f.fmtIntLiteral(Type.usize, len_val),
-            });
+            try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, ty.vectorLen(zcu)))});
             try f.writeCValue(writer, local, .Other);
-            try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
+            try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))});
             f.object.indent_writer.pushIndent();
 
             break :index .{ .index = local };
@@ -8054,16 +8129,16 @@ const Vectorize = struct {
     }
 };
 
-fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
-    if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
+fn lowerFnRetTy(ret_ty: Type, zcu: *Zcu) !Type {
+    if (ret_ty.toIntern() == .noreturn_type) return Type.noreturn;
 
-    if (lowersToArray(ret_ty, mod)) {
-        const gpa = mod.gpa;
-        const ip = &mod.intern_pool;
+    if (lowersToArray(ret_ty, zcu)) {
+        const gpa = zcu.gpa;
+        const ip = &zcu.intern_pool;
         const names = [1]InternPool.NullTerminatedString{
             try ip.getOrPutString(gpa, "array"),
         };
-        const types = [1]InternPool.Index{ret_ty.ip_index};
+        const types = [1]InternPool.Index{ret_ty.toIntern()};
         const values = [1]InternPool.Index{.none};
         const interned = try ip.getAnonStructType(gpa, .{
             .names = &names,
@@ -8073,13 +8148,13 @@ fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
         return Type.fromInterned(interned);
     }
 
-    return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;
+    return if (ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) ret_ty else Type.void;
 }
 
-fn lowersToArray(ty: Type, mod: *Module) bool {
-    return switch (ty.zigTypeTag(mod)) {
+fn lowersToArray(ty: Type, zcu: *Zcu) bool {
+    return switch (ty.zigTypeTag(zcu)) {
         .Array, .Vector => return true,
-        else => return ty.isAbiInt(mod) and toCIntBits(@as(u32, @intCast(ty.bitSize(mod)))) == null,
+        else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null,
     };
 }
 
@@ -8098,7 +8173,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
     const ref_inst = ref.toIndex() orelse return;
     const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
     const local_index = switch (c_value) {
-        .local, .new_local => |l| l,
+        .new_local, .local => |l| l,
         else => return,
     };
     try freeLocal(f, inst, local_index, ref_inst);
src/link/C.zig
@@ -6,7 +6,8 @@ const fs = std.fs;
 
 const C = @This();
 const build_options = @import("build_options");
-const Module = @import("../Module.zig");
+const Zcu = @import("../Module.zig");
+const Module = @import("../Package/Module.zig");
 const InternPool = @import("../InternPool.zig");
 const Alignment = InternPool.Alignment;
 const Compilation = @import("../Compilation.zig");
@@ -177,16 +178,16 @@ pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void {
 
 pub fn updateFunc(
     self: *C,
-    module: *Module,
+    zcu: *Zcu,
     func_index: InternPool.Index,
     air: Air,
     liveness: Liveness,
 ) !void {
     const gpa = self.base.comp.gpa;
 
-    const func = module.funcInfo(func_index);
+    const func = zcu.funcInfo(func_index);
     const decl_index = func.owner_decl;
-    const decl = module.declPtr(decl_index);
+    const decl = zcu.declPtr(decl_index);
     const gop = try self.decl_table.getOrPut(gpa, decl_index);
     if (!gop.found_existing) gop.value_ptr.* = .{};
     const ctypes = &gop.value_ptr.ctypes;
@@ -206,10 +207,11 @@ pub fn updateFunc(
         .object = .{
             .dg = .{
                 .gpa = gpa,
-                .module = module,
+                .zcu = zcu,
+                .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod,
                 .error_msg = null,
                 .pass = .{ .decl = decl_index },
-                .is_naked_fn = decl.typeOf(module).fnCallingConvention(module) == .Naked,
+                .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked,
                 .fwd_decl = fwd_decl.toManaged(gpa),
                 .ctypes = ctypes.*,
                 .anon_decl_deps = self.anon_decls,
@@ -232,7 +234,7 @@ pub fn updateFunc(
 
     codegen.genFunc(&function) catch |err| switch (err) {
         error.AnalysisFail => {
-            try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?);
+            try zcu.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?);
             return;
         },
         else => |e| return e,
@@ -249,7 +251,7 @@ pub fn updateFunc(
     gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items);
 }
 
-fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
+fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
     const gpa = self.base.comp.gpa;
     const anon_decl = self.anon_decls.keys()[i];
 
@@ -261,7 +263,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
     var object: codegen.Object = .{
         .dg = .{
             .gpa = gpa,
-            .module = module,
+            .zcu = zcu,
+            .mod = zcu.root_mod,
             .error_msg = null,
             .pass = .{ .anon = anon_decl },
             .is_naked_fn = false,
@@ -283,12 +286,12 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
         code.* = object.code.moveToUnmanaged();
     }
 
-    const c_value: codegen.CValue = .{ .constant = anon_decl };
+    const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };
     const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;
-    codegen.genDeclValue(&object, Value.fromInterned(anon_decl), false, c_value, alignment, .none) catch |err| switch (err) {
+    codegen.genDeclValue(&object, c_value.constant, false, c_value, alignment, .none) catch |err| switch (err) {
         error.AnalysisFail => {
             @panic("TODO: C backend AnalysisFail on anonymous decl");
-            //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
+            //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
             //return;
         },
         else => |e| return e,
@@ -304,12 +307,13 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
     };
 }
 
-pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void {
+pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
     const tracy = trace(@src());
     defer tracy.end();
 
     const gpa = self.base.comp.gpa;
 
+    const decl = zcu.declPtr(decl_index);
     const gop = try self.decl_table.getOrPut(gpa, decl_index);
     if (!gop.found_existing) {
         gop.value_ptr.* = .{};
@@ -324,7 +328,8 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !
     var object: codegen.Object = .{
         .dg = .{
             .gpa = gpa,
-            .module = module,
+            .zcu = zcu,
+            .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod,
             .error_msg = null,
             .pass = .{ .decl = decl_index },
             .is_naked_fn = false,
@@ -347,7 +352,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !
 
     codegen.genDecl(&object) catch |err| switch (err) {
         error.AnalysisFail => {
-            try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
+            try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
             return;
         },
         else => |e| return e,
@@ -362,11 +367,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !
     gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
 }
 
-pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void {
+pub fn updateDeclLineNumber(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
     // The C backend does not have the ability to fix line numbers without re-generating
     // the entire Decl.
     _ = self;
-    _ = module;
+    _ = zcu;
     _ = decl_index;
 }
 
@@ -399,12 +404,12 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
 
     const comp = self.base.comp;
     const gpa = comp.gpa;
-    const module = self.base.comp.module.?;
+    const zcu = self.base.comp.module.?;
 
     {
         var i: usize = 0;
         while (i < self.anon_decls.count()) : (i += 1) {
-            try updateAnonDecl(self, module, i);
+            try updateAnonDecl(self, zcu, i);
         }
     }
 
@@ -414,7 +419,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
     var f: Flush = .{};
     defer f.deinit(gpa);
 
-    const abi_defines = try self.abiDefines(module.getTarget());
+    const abi_defines = try self.abiDefines(zcu.getTarget());
     defer abi_defines.deinit();
 
     // Covers defines, zig.h, ctypes, asm, lazy fwd.
@@ -429,7 +434,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
     {
         var asm_buf = f.asm_buf.toManaged(gpa);
         defer f.asm_buf = asm_buf.moveToUnmanaged();
-        try codegen.genGlobalAsm(module, asm_buf.writer());
+        try codegen.genGlobalAsm(zcu, asm_buf.writer());
         f.appendBufAssumeCapacity(asm_buf.items);
     }
 
@@ -438,7 +443,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
 
     self.lazy_fwd_decl_buf.clearRetainingCapacity();
     self.lazy_code_buf.clearRetainingCapacity();
-    try self.flushErrDecls(&f.lazy_ctypes);
+    try self.flushErrDecls(zcu, &f.lazy_ctypes);
 
     // Unlike other backends, the .c code we are emitting has order-dependent decls.
     // `CType`s, forward decls, and non-functions first.
@@ -446,19 +451,20 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
     {
         var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
         defer export_names.deinit(gpa);
-        try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len));
-        for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
+        try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len));
+        for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"|
             try export_names.put(gpa, @"export".opts.name, {});
 
         for (self.anon_decls.values()) |*decl_block| {
-            try self.flushDeclBlock(&f, decl_block, export_names, .none);
+            try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none);
         }
 
         for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {
-            assert(module.declPtr(decl_index).has_tv);
-            const decl = module.declPtr(decl_index);
-            const extern_symbol_name = if (decl.isExtern(module)) decl.name.toOptional() else .none;
-            try self.flushDeclBlock(&f, decl_block, export_names, extern_symbol_name);
+            const decl = zcu.declPtr(decl_index);
+            assert(decl.has_tv);
+            const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
+            const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod;
+            try self.flushDeclBlock(zcu, mod, &f, decl_block, export_names, extern_symbol_name);
         }
     }
 
@@ -466,14 +472,14 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v
         // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
         // This ensures that every lazy CType.Index exactly matches the global CType.Index.
         assert(f.ctypes.count() == 0);
-        try self.flushCTypes(&f, .flush, f.lazy_ctypes);
+        try self.flushCTypes(zcu, &f, .flush, f.lazy_ctypes);
 
         for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| {
-            try self.flushCTypes(&f, .{ .anon = anon_decl }, decl_block.ctypes);
+            try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, decl_block.ctypes);
         }
 
         for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| {
-            try self.flushCTypes(&f, .{ .decl = decl_index }, decl_block.ctypes);
+            try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, decl_block.ctypes);
         }
     }
 
@@ -543,12 +549,12 @@ const FlushDeclError = error{
 
 fn flushCTypes(
     self: *C,
+    zcu: *Zcu,
     f: *Flush,
     pass: codegen.DeclGen.Pass,
     decl_ctypes: codegen.CType.Store,
 ) FlushDeclError!void {
     const gpa = self.base.comp.gpa;
-    const mod = self.base.comp.module.?;
 
     const decl_ctypes_len = decl_ctypes.count();
     f.ctypes_map.clearRetainingCapacity();
@@ -615,7 +621,7 @@ fn flushCTypes(
             assert(decl_cty.hash(decl_ctypes.set) == global_cty.hash(global_ctypes.set));
         }
         try codegen.genTypeDecl(
-            mod,
+            zcu,
             writer,
             global_ctypes.set,
             global_idx,
@@ -627,7 +633,7 @@ fn flushCTypes(
     }
 }
 
-fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
+fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclError!void {
     const gpa = self.base.comp.gpa;
 
     const fwd_decl = &self.lazy_fwd_decl_buf;
@@ -636,7 +642,8 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
     var object = codegen.Object{
         .dg = .{
             .gpa = gpa,
-            .module = self.base.comp.module.?,
+            .zcu = zcu,
+            .mod = zcu.root_mod,
             .error_msg = null,
             .pass = .flush,
             .is_naked_fn = false,
@@ -667,6 +674,8 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
 
 fn flushLazyFn(
     self: *C,
+    zcu: *Zcu,
+    mod: *Module,
     ctypes: *codegen.CType.Store,
     lazy_fn: codegen.LazyFnMap.Entry,
 ) FlushDeclError!void {
@@ -678,7 +687,8 @@ fn flushLazyFn(
     var object = codegen.Object{
         .dg = .{
             .gpa = gpa,
-            .module = self.base.comp.module.?,
+            .zcu = zcu,
+            .mod = mod,
             .error_msg = null,
             .pass = .flush,
             .is_naked_fn = false,
@@ -709,7 +719,13 @@ fn flushLazyFn(
     ctypes.* = object.dg.ctypes.move();
 }
 
-fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {
+fn flushLazyFns(
+    self: *C,
+    zcu: *Zcu,
+    mod: *Module,
+    f: *Flush,
+    lazy_fns: codegen.LazyFnMap,
+) FlushDeclError!void {
     const gpa = self.base.comp.gpa;
     try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count()));
 
@@ -718,19 +734,21 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError
         const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
         if (gop.found_existing) continue;
         gop.value_ptr.* = {};
-        try self.flushLazyFn(&f.lazy_ctypes, entry);
+        try self.flushLazyFn(zcu, mod, &f.lazy_ctypes, entry);
     }
 }
 
 fn flushDeclBlock(
     self: *C,
+    zcu: *Zcu,
+    mod: *Module,
     f: *Flush,
     decl_block: *DeclBlock,
     export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
     extern_symbol_name: InternPool.OptionalNullTerminatedString,
 ) FlushDeclError!void {
     const gpa = self.base.comp.gpa;
-    try self.flushLazyFns(f, decl_block.lazy_fns);
+    try self.flushLazyFns(zcu, mod, f, decl_block.lazy_fns);
     try f.all_buffers.ensureUnusedCapacity(gpa, 1);
     fwd_decl: {
         if (extern_symbol_name.unwrap()) |name| {
@@ -740,15 +758,15 @@ fn flushDeclBlock(
     }
 }
 
-pub fn flushEmitH(module: *Module) !void {
+pub fn flushEmitH(zcu: *Zcu) !void {
     const tracy = trace(@src());
     defer tracy.end();
 
-    const emit_h = module.emit_h orelse return;
+    const emit_h = zcu.emit_h orelse return;
 
     // We collect a list of buffers to write, and write them all at once with pwritev ๐Ÿ˜Ž
     const num_buffers = emit_h.decl_table.count() + 1;
-    var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(module.gpa, num_buffers);
+    var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(zcu.gpa, num_buffers);
     defer all_buffers.deinit();
 
     var file_size: u64 = zig_h.len;
@@ -771,7 +789,7 @@ pub fn flushEmitH(module: *Module) !void {
         }
     }
 
-    const directory = emit_h.loc.directory orelse module.comp.local_cache_directory;
+    const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory;
     const file = try directory.handle.createFile(emit_h.loc.basename, .{
         // We set the end position explicitly below; by not truncating the file, we possibly
         // make it easier on the file system by doing 1 reallocation instead of two.
@@ -785,12 +803,12 @@ pub fn flushEmitH(module: *Module) !void {
 
 pub fn updateExports(
     self: *C,
-    module: *Module,
-    exported: Module.Exported,
-    exports: []const *Module.Export,
+    zcu: *Zcu,
+    exported: Zcu.Exported,
+    exports: []const *Zcu.Export,
 ) !void {
     _ = exports;
     _ = exported;
-    _ = module;
+    _ = zcu;
     _ = self;
 }
src/Compilation.zig
@@ -3451,7 +3451,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
 
                     var dg: c_codegen.DeclGen = .{
                         .gpa = gpa,
-                        .module = module,
+                        .zcu = module,
+                        .mod = module.namespacePtr(decl.src_namespace).file_scope.mod,
                         .error_msg = null,
                         .pass = .{ .decl = decl_index },
                         .is_naked_fn = false,