Commit bc4d2b646d

Andrew Kelley <andrew@ziglang.org>
2023-12-13 23:19:51
compiler: update references to target
1 parent 1642c00
src/arch/aarch64/CodeGen.zig
@@ -329,7 +329,7 @@ const BigTomb = struct {
 const Self = @This();
 
 pub fn generate(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     func_index: InternPool.Index,
     air: Air,
@@ -337,31 +337,30 @@ pub fn generate(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
-        @panic("Attempted to compile for architecture that was disabled by build configuration");
-    }
-
-    const mod = bin_file.comp.module.?;
-    const func = mod.funcInfo(func_index);
-    const fn_owner_decl = mod.declPtr(func.owner_decl);
+    const gpa = lf.comp.gpa;
+    const zcu = lf.comp.module.?;
+    const func = zcu.funcInfo(func_index);
+    const fn_owner_decl = zcu.declPtr(func.owner_decl);
     assert(fn_owner_decl.has_tv);
     const fn_type = fn_owner_decl.ty;
+    const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
+    const target = &namespace.file_scope.mod.target;
 
-    var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
+    var branch_stack = std.ArrayList(Branch).init(gpa);
     defer {
         assert(branch_stack.items.len == 1);
-        branch_stack.items[0].deinit(bin_file.allocator);
+        branch_stack.items[0].deinit(gpa);
         branch_stack.deinit();
     }
     try branch_stack.append(.{});
 
     var function = Self{
-        .gpa = bin_file.allocator,
+        .gpa = gpa,
         .air = air,
         .liveness = liveness,
         .debug_output = debug_output,
-        .target = &bin_file.options.target,
-        .bin_file = bin_file,
+        .target = target,
+        .bin_file = lf,
         .func_index = func_index,
         .owner_decl = func.owner_decl,
         .err_msg = null,
@@ -375,15 +374,15 @@ pub fn generate(
         .end_di_line = func.rbrace_line,
         .end_di_column = func.rbrace_column,
     };
-    defer function.stack.deinit(bin_file.allocator);
-    defer function.blocks.deinit(bin_file.allocator);
-    defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
-    defer function.dbg_info_relocs.deinit(bin_file.allocator);
+    defer function.stack.deinit(gpa);
+    defer function.blocks.deinit(gpa);
+    defer function.exitlude_jump_relocs.deinit(gpa);
+    defer function.dbg_info_relocs.deinit(gpa);
 
     var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -397,7 +396,7 @@ pub fn generate(
     function.gen() catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -408,15 +407,15 @@ pub fn generate(
 
     var mir = Mir{
         .instructions = function.mir_instructions.toOwnedSlice(),
-        .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator),
+        .extra = try function.mir_extra.toOwnedSlice(gpa),
     };
-    defer mir.deinit(bin_file.allocator);
+    defer mir.deinit(gpa);
 
     var emit = Emit{
         .mir = mir,
-        .bin_file = bin_file,
+        .bin_file = lf,
         .debug_output = debug_output,
-        .target = &bin_file.options.target,
+        .target = target,
         .src_loc = src_loc,
         .code = code,
         .prev_di_pc = 0,
src/arch/arm/CodeGen.zig
@@ -336,7 +336,7 @@ const DbgInfoReloc = struct {
 const Self = @This();
 
 pub fn generate(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     func_index: InternPool.Index,
     air: Air,
@@ -344,30 +344,29 @@ pub fn generate(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
-        @panic("Attempted to compile for architecture that was disabled by build configuration");
-    }
-
-    const mod = bin_file.comp.module.?;
-    const func = mod.funcInfo(func_index);
-    const fn_owner_decl = mod.declPtr(func.owner_decl);
+    const gpa = lf.comp.gpa;
+    const zcu = lf.comp.module.?;
+    const func = zcu.funcInfo(func_index);
+    const fn_owner_decl = zcu.declPtr(func.owner_decl);
     assert(fn_owner_decl.has_tv);
     const fn_type = fn_owner_decl.ty;
+    const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
+    const target = &namespace.file_scope.mod.target;
 
-    var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
+    var branch_stack = std.ArrayList(Branch).init(gpa);
     defer {
         assert(branch_stack.items.len == 1);
-        branch_stack.items[0].deinit(bin_file.allocator);
+        branch_stack.items[0].deinit(gpa);
         branch_stack.deinit();
     }
     try branch_stack.append(.{});
 
-    var function = Self{
-        .gpa = bin_file.allocator,
+    var function: Self = .{
+        .gpa = gpa,
         .air = air,
         .liveness = liveness,
-        .target = &bin_file.options.target,
-        .bin_file = bin_file,
+        .target = target,
+        .bin_file = lf,
         .debug_output = debug_output,
         .func_index = func_index,
         .err_msg = null,
@@ -381,15 +380,15 @@ pub fn generate(
         .end_di_line = func.rbrace_line,
         .end_di_column = func.rbrace_column,
     };
-    defer function.stack.deinit(bin_file.allocator);
-    defer function.blocks.deinit(bin_file.allocator);
-    defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
-    defer function.dbg_info_relocs.deinit(bin_file.allocator);
+    defer function.stack.deinit(gpa);
+    defer function.blocks.deinit(gpa);
+    defer function.exitlude_jump_relocs.deinit(gpa);
+    defer function.dbg_info_relocs.deinit(gpa);
 
     var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -403,7 +402,7 @@ pub fn generate(
     function.gen() catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -414,15 +413,15 @@ pub fn generate(
 
     var mir = Mir{
         .instructions = function.mir_instructions.toOwnedSlice(),
-        .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator),
+        .extra = try function.mir_extra.toOwnedSlice(gpa),
     };
-    defer mir.deinit(bin_file.allocator);
+    defer mir.deinit(gpa);
 
     var emit = Emit{
         .mir = mir,
-        .bin_file = bin_file,
+        .bin_file = lf,
         .debug_output = debug_output,
-        .target = &bin_file.options.target,
+        .target = target,
         .src_loc = src_loc,
         .code = code,
         .prev_di_pc = 0,
src/arch/riscv64/CodeGen.zig
@@ -217,7 +217,7 @@ const BigTomb = struct {
 const Self = @This();
 
 pub fn generate(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     func_index: InternPool.Index,
     air: Air,
@@ -225,30 +225,29 @@ pub fn generate(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
-        @panic("Attempted to compile for architecture that was disabled by build configuration");
-    }
-
-    const mod = bin_file.comp.module.?;
-    const func = mod.funcInfo(func_index);
-    const fn_owner_decl = mod.declPtr(func.owner_decl);
+    const gpa = lf.comp.gpa;
+    const zcu = lf.comp.module.?;
+    const func = zcu.funcInfo(func_index);
+    const fn_owner_decl = zcu.declPtr(func.owner_decl);
     assert(fn_owner_decl.has_tv);
     const fn_type = fn_owner_decl.ty;
+    const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
+    const target = &namespace.file_scope.mod.target;
 
-    var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
+    var branch_stack = std.ArrayList(Branch).init(gpa);
     defer {
         assert(branch_stack.items.len == 1);
-        branch_stack.items[0].deinit(bin_file.allocator);
+        branch_stack.items[0].deinit(gpa);
         branch_stack.deinit();
     }
     try branch_stack.append(.{});
 
     var function = Self{
-        .gpa = bin_file.allocator,
+        .gpa = gpa,
         .air = air,
         .liveness = liveness,
-        .target = &bin_file.options.target,
-        .bin_file = bin_file,
+        .target = target,
+        .bin_file = lf,
         .func_index = func_index,
         .code = code,
         .debug_output = debug_output,
@@ -263,14 +262,14 @@ pub fn generate(
         .end_di_line = func.rbrace_line,
         .end_di_column = func.rbrace_column,
     };
-    defer function.stack.deinit(bin_file.allocator);
-    defer function.blocks.deinit(bin_file.allocator);
-    defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
+    defer function.stack.deinit(gpa);
+    defer function.blocks.deinit(gpa);
+    defer function.exitlude_jump_relocs.deinit(gpa);
 
     var call_info = function.resolveCallingConventionValues(fn_type) catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -284,22 +283,22 @@ pub fn generate(
     function.gen() catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
 
     var mir = Mir{
         .instructions = function.mir_instructions.toOwnedSlice(),
-        .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator),
+        .extra = try function.mir_extra.toOwnedSlice(gpa),
     };
-    defer mir.deinit(bin_file.allocator);
+    defer mir.deinit(gpa);
 
     var emit = Emit{
         .mir = mir,
-        .bin_file = bin_file,
+        .bin_file = lf,
         .debug_output = debug_output,
-        .target = &bin_file.options.target,
+        .target = target,
         .src_loc = src_loc,
         .code = code,
         .prev_di_pc = 0,
src/arch/sparc64/CodeGen.zig
@@ -260,7 +260,7 @@ const BigTomb = struct {
 };
 
 pub fn generate(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     func_index: InternPool.Index,
     air: Air,
@@ -268,31 +268,30 @@ pub fn generate(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
-        @panic("Attempted to compile for architecture that was disabled by build configuration");
-    }
-
-    const mod = bin_file.comp.module.?;
-    const func = mod.funcInfo(func_index);
-    const fn_owner_decl = mod.declPtr(func.owner_decl);
+    const gpa = lf.comp.gpa;
+    const zcu = lf.comp.module.?;
+    const func = zcu.funcInfo(func_index);
+    const fn_owner_decl = zcu.declPtr(func.owner_decl);
     assert(fn_owner_decl.has_tv);
     const fn_type = fn_owner_decl.ty;
+    const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace);
+    const target = &namespace.file_scope.mod.target;
 
-    var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
+    var branch_stack = std.ArrayList(Branch).init(gpa);
     defer {
         assert(branch_stack.items.len == 1);
-        branch_stack.items[0].deinit(bin_file.allocator);
+        branch_stack.items[0].deinit(gpa);
         branch_stack.deinit();
     }
     try branch_stack.append(.{});
 
     var function = Self{
-        .gpa = bin_file.allocator,
+        .gpa = gpa,
         .air = air,
         .liveness = liveness,
-        .target = &bin_file.options.target,
+        .target = target,
         .func_index = func_index,
-        .bin_file = bin_file,
+        .bin_file = lf,
         .code = code,
         .debug_output = debug_output,
         .err_msg = null,
@@ -306,14 +305,14 @@ pub fn generate(
         .end_di_line = func.rbrace_line,
         .end_di_column = func.rbrace_column,
     };
-    defer function.stack.deinit(bin_file.allocator);
-    defer function.blocks.deinit(bin_file.allocator);
-    defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
+    defer function.stack.deinit(gpa);
+    defer function.blocks.deinit(gpa);
+    defer function.exitlude_jump_relocs.deinit(gpa);
 
     var call_info = function.resolveCallingConventionValues(fn_type, .callee) catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
@@ -327,22 +326,22 @@ pub fn generate(
     function.gen() catch |err| switch (err) {
         error.CodegenFail => return Result{ .fail = function.err_msg.? },
         error.OutOfRegisters => return Result{
-            .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
+            .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
         },
         else => |e| return e,
     };
 
     var mir = Mir{
         .instructions = function.mir_instructions.toOwnedSlice(),
-        .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator),
+        .extra = try function.mir_extra.toOwnedSlice(gpa),
     };
-    defer mir.deinit(bin_file.allocator);
+    defer mir.deinit(gpa);
 
     var emit = Emit{
         .mir = mir,
-        .bin_file = bin_file,
+        .bin_file = lf,
         .debug_output = debug_output,
-        .target = &bin_file.options.target,
+        .target = target,
         .src_loc = src_loc,
         .code = code,
         .prev_di_pc = 0,
src/arch/wasm/CodeGen.zig
@@ -1212,16 +1212,19 @@ pub fn generate(
     _ = src_loc;
     const mod = bin_file.comp.module.?;
     const func = mod.funcInfo(func_index);
+    const decl = mod.declPtr(func.owner_decl);
+    const namespace = mod.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
     var code_gen: CodeGen = .{
         .gpa = bin_file.allocator,
         .air = air,
         .liveness = liveness,
         .code = code,
         .decl_index = func.owner_decl,
-        .decl = mod.declPtr(func.owner_decl),
+        .decl = decl,
         .err_msg = undefined,
         .locals = .{},
-        .target = bin_file.options.target,
+        .target = target,
         .bin_file = bin_file.cast(link.File.Wasm).?,
         .debug_output = debug_output,
         .func_index = func_index,
src/arch/x86_64/CodeGen.zig
@@ -795,22 +795,20 @@ pub fn generate(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
-        @panic("Attempted to compile for architecture that was disabled by build configuration");
-    }
-
     const mod = bin_file.comp.module.?;
     const func = mod.funcInfo(func_index);
     const fn_owner_decl = mod.declPtr(func.owner_decl);
     assert(fn_owner_decl.has_tv);
     const fn_type = fn_owner_decl.ty;
+    const namespace = mod.namespacePtr(fn_owner_decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
 
     const gpa = bin_file.allocator;
     var function = Self{
         .gpa = gpa,
         .air = air,
         .liveness = liveness,
-        .target = &bin_file.options.target,
+        .target = target,
         .bin_file = bin_file,
         .debug_output = debug_output,
         .owner = .{ .func_index = func_index },
@@ -882,7 +880,7 @@ pub fn generate(
         .size = Type.usize.abiSize(mod),
         .alignment = Alignment.min(
             call_info.stack_align,
-            Alignment.fromNonzeroByteUnits(bin_file.options.target.stackAlignment()),
+            Alignment.fromNonzeroByteUnits(target.stackAlignment()),
         ),
     }));
     function.frame_allocs.set(
@@ -967,11 +965,16 @@ pub fn generateLazy(
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
     const gpa = bin_file.allocator;
+    const zcu = bin_file.comp.module.?;
+    const decl_index = lazy_sym.ty.getOwnerDecl(zcu);
+    const decl = zcu.declPtr(decl_index);
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
     var function = Self{
         .gpa = gpa,
         .air = undefined,
         .liveness = undefined,
-        .target = &bin_file.options.target,
+        .target = target,
         .bin_file = bin_file,
         .debug_output = debug_output,
         .owner = .{ .lazy_sym = lazy_sym },
src/link/Dwarf.zig
@@ -1192,7 +1192,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: InternPool.DeclInde
 
 pub fn commitDeclState(
     self: *Dwarf,
-    mod: *Module,
+    zcu: *Module,
     decl_index: InternPool.DeclIndex,
     sym_addr: u64,
     sym_size: u64,
@@ -1202,15 +1202,17 @@ pub fn commitDeclState(
     defer tracy.end();
 
     const gpa = self.allocator;
+    const decl = zcu.declPtr(decl_index);
+    const ip = &zcu.intern_pool;
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
+    const target_endian = target.cpu.arch.endian();
+
     var dbg_line_buffer = &decl_state.dbg_line;
     var dbg_info_buffer = &decl_state.dbg_info;
-    const decl = mod.declPtr(decl_index);
-    const ip = &mod.intern_pool;
-
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
 
     assert(decl.has_tv);
-    switch (decl.ty.zigTypeTag(mod)) {
+    switch (decl.ty.zigTypeTag(zcu)) {
         .Fn => {
             try decl_state.setInlineFunc(decl.val.toIntern());
 
@@ -1409,18 +1411,18 @@ pub fn commitDeclState(
             if (ip.isErrorSetType(ty.toIntern())) continue;
 
             symbol.offset = @intCast(dbg_info_buffer.items.len);
-            try decl_state.addDbgInfoType(mod, di_atom_index, ty);
+            try decl_state.addDbgInfoType(zcu, di_atom_index, ty);
         }
     }
 
     try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len));
 
     while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
-        if (reloc.target) |target| {
-            const symbol = decl_state.abbrev_table.items[target];
+        if (reloc.target) |reloc_target| {
+            const symbol = decl_state.abbrev_table.items[reloc_target];
             const ty = symbol.type;
             if (ip.isErrorSetType(ty.toIntern())) {
-                log.debug("resolving %{d} deferred until flush", .{target});
+                log.debug("resolving %{d} deferred until flush", .{reloc_target});
                 try self.global_abbrev_relocs.append(gpa, .{
                     .target = null,
                     .offset = reloc.offset,
@@ -1433,8 +1435,8 @@ pub fn commitDeclState(
                 log.debug("{x}: [() => {x}] (%{d}, '{}')", .{
                     reloc.offset,
                     value,
-                    target,
-                    ty.fmt(mod),
+                    reloc_target,
+                    ty.fmt(zcu),
                 });
                 mem.writeInt(
                     u32,
@@ -1897,7 +1899,7 @@ fn dbgInfoHeaderBytes(self: *Dwarf) usize {
     return 120;
 }
 
-pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u64) !void {
+pub fn writeDbgInfoHeader(self: *Dwarf, zcu: *Module, low_pc: u64, high_pc: u64) !void {
     // If this value is null it means there is an error in the module;
     // leave debug_info_header_dirty=true.
     const first_dbg_info_off = self.getDebugInfoOff() orelse return;
@@ -1908,7 +1910,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
     var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);
     defer di_buf.deinit();
 
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
+    const comp = self.bin_file.comp;
+    const target = comp.root_mod.resolved_target.result;
+    const target_endian = target.cpu.arch.endian();
     const init_len_size: usize = switch (self.format) {
         .dwarf32 => 4,
         .dwarf64 => 12,
@@ -1931,9 +1935,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
     di_buf.appendAssumeCapacity(self.ptrWidthBytes()); // address size
 
     // Write the form for the compile unit, which must match the abbrev table above.
-    const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path);
+    const name_strp = try self.strtab.insert(self.allocator, zcu.root_mod.root_src_path);
     var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
-    const compile_unit_dir = resolveCompilationDir(module, &compile_unit_dir_buffer);
+    const compile_unit_dir = resolveCompilationDir(zcu, &compile_unit_dir_buffer);
     const comp_dir_strp = try self.strtab.insert(self.allocator, compile_unit_dir);
     const producer_strp = try self.strtab.insert(self.allocator, link.producer_string);
 
@@ -1997,7 +2001,9 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) []
 }
 
 fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void {
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
+    const comp = self.bin_file.comp;
+    const target = comp.root_mod.resolved_target.result;
+    const target_endian = target.cpu.arch.endian();
     switch (self.ptr_width) {
         .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(addr), target_endian),
         .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
@@ -2005,7 +2011,9 @@ fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) voi
 }
 
 fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void {
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
+    const comp = self.bin_file.comp;
+    const target = comp.root_mod.resolved_target.result;
+    const target_endian = target.cpu.arch.endian();
     switch (self.format) {
         .dwarf32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @intCast(off), target_endian),
         .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian),
@@ -2227,7 +2235,9 @@ fn writeDbgInfoNopsToArrayList(
 }
 
 pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
+    const comp = self.bin_file.comp;
+    const target = comp.root_mod.resolved_target.result;
+    const target_endian = target.cpu.arch.endian();
     const ptr_width_bytes = self.ptrWidthBytes();
 
     // Enough for all the data without resizing. When support for more compilation units
@@ -2299,9 +2309,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
 }
 
 pub fn writeDbgLineHeader(self: *Dwarf) !void {
+    const comp = self.bin_file.comp;
     const gpa = self.allocator;
-
-    const target_endian = self.bin_file.options.target.cpu.arch.endian();
+    const target = comp.root_mod.resolved_target.result;
+    const target_endian = target.cpu.arch.endian();
     const init_len_size: usize = switch (self.format) {
         .dwarf32 => 4,
         .dwarf64 => 12,
@@ -2565,7 +2576,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
 }
 
 pub fn flushModule(self: *Dwarf, module: *Module) !void {
-    const target = self.bin_file.options.target;
+    const comp = self.bin_file.comp;
+    const target = comp.root_mod.resolved_target.result;
 
     if (self.global_abbrev_relocs.items.len > 0) {
         const gpa = self.allocator;
src/codegen.zig
@@ -45,7 +45,7 @@ pub const DebugInfoOutput = union(enum) {
 };
 
 pub fn generateFunction(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     func_index: InternPool.Index,
     air: Air,
@@ -53,33 +53,43 @@ pub fn generateFunction(
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    switch (bin_file.options.target.cpu.arch) {
+    const zcu = lf.comp.module.?;
+    const func = zcu.funcInfo(func_index);
+    const decl = zcu.declPtr(func.owner_decl);
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
+    switch (target.cpu.arch) {
         .arm,
         .armeb,
-        => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
+        => return @import("arch/arm/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
         .aarch64,
         .aarch64_be,
         .aarch64_32,
-        => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
-        .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
-        .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
-        .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
+        => return @import("arch/aarch64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
+        .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
+        .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
+        .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
         .wasm32,
         .wasm64,
-        => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
+        => return @import("arch/wasm/CodeGen.zig").generate(lf, src_loc, func_index, air, liveness, code, debug_output),
         else => unreachable,
     }
 }
 
 pub fn generateLazyFunction(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     lazy_sym: link.File.LazySymbol,
     code: *std.ArrayList(u8),
     debug_output: DebugInfoOutput,
 ) CodeGenError!Result {
-    switch (bin_file.options.target.cpu.arch) {
-        .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(bin_file, src_loc, lazy_sym, code, debug_output),
+    const zcu = lf.comp.module.?;
+    const decl_index = lazy_sym.ty.getOwnerDecl(zcu);
+    const decl = zcu.declPtr(decl_index);
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
+    switch (target.cpu.arch) {
+        .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(lf, src_loc, lazy_sym, code, debug_output),
         else => unreachable,
     }
 }
@@ -107,13 +117,16 @@ pub fn generateLazySymbol(
     const tracy = trace(@src());
     defer tracy.end();
 
-    const target = bin_file.options.target;
+    const zcu = bin_file.comp.module.?;
+    const decl_index = lazy_sym.ty.getOwnerDecl(zcu);
+    const decl = zcu.declPtr(decl_index);
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
     const endian = target.cpu.arch.endian();
 
-    const mod = bin_file.comp.module.?;
     log.debug("generateLazySymbol: kind = {s}, ty = {}", .{
         @tagName(lazy_sym.kind),
-        lazy_sym.ty.fmt(mod),
+        lazy_sym.ty.fmt(zcu),
     });
 
     if (lazy_sym.kind == .code) {
@@ -121,14 +134,14 @@ pub fn generateLazySymbol(
         return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);
     }
 
-    if (lazy_sym.ty.isAnyError(mod)) {
+    if (lazy_sym.ty.isAnyError(zcu)) {
         alignment.* = .@"4";
-        const err_names = mod.global_error_set.keys();
+        const err_names = zcu.global_error_set.keys();
         mem.writeInt(u32, try code.addManyAsArray(4), @as(u32, @intCast(err_names.len)), endian);
         var offset = code.items.len;
         try code.resize((1 + err_names.len + 1) * 4);
         for (err_names) |err_name_nts| {
-            const err_name = mod.intern_pool.stringToSlice(err_name_nts);
+            const err_name = zcu.intern_pool.stringToSlice(err_name_nts);
             mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
             offset += 4;
             try code.ensureUnusedCapacity(err_name.len + 1);
@@ -137,10 +150,10 @@ pub fn generateLazySymbol(
         }
         mem.writeInt(u32, code.items[offset..][0..4], @as(u32, @intCast(code.items.len)), endian);
         return Result.ok;
-    } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) {
+    } else if (lazy_sym.ty.zigTypeTag(zcu) == .Enum) {
         alignment.* = .@"1";
-        for (lazy_sym.ty.enumFields(mod)) |tag_name_ip| {
-            const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
+        for (lazy_sym.ty.enumFields(zcu)) |tag_name_ip| {
+            const tag_name = zcu.intern_pool.stringToSlice(tag_name_ip);
             try code.ensureUnusedCapacity(tag_name.len + 1);
             code.appendSliceAssumeCapacity(tag_name);
             code.appendAssumeCapacity(0);
@@ -150,7 +163,7 @@ pub fn generateLazySymbol(
         bin_file.allocator,
         src_loc,
         "TODO implement generateLazySymbol for {s} {}",
-        .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod) },
+        .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(zcu) },
     ) };
 }
 
@@ -757,7 +770,7 @@ const RelocInfo = struct {
 };
 
 fn lowerAnonDeclRef(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
     code: *std.ArrayList(u8),
@@ -765,27 +778,27 @@ fn lowerAnonDeclRef(
     reloc_info: RelocInfo,
 ) CodeGenError!Result {
     _ = debug_output;
-    const target = bin_file.options.target;
-    const mod = bin_file.comp.module.?;
+    const zcu = lf.comp.module.?;
+    const target = lf.comp.root_mod.resolved_target.result;
 
     const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
     const decl_val = anon_decl.val;
-    const decl_ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val));
-    log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(mod)});
-    const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
-    if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) {
+    const decl_ty = Type.fromInterned(zcu.intern_pool.typeOf(decl_val));
+    log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(zcu)});
+    const is_fn_body = decl_ty.zigTypeTag(zcu) == .Fn;
+    if (!is_fn_body and !decl_ty.hasRuntimeBits(zcu)) {
         try code.appendNTimes(0xaa, ptr_width_bytes);
         return Result.ok;
     }
 
-    const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
-    const res = try bin_file.lowerAnonDecl(decl_val, decl_align, src_loc);
+    const decl_align = zcu.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
+    const res = try lf.lowerAnonDecl(decl_val, decl_align, src_loc);
     switch (res) {
         .ok => {},
         .fail => |em| return .{ .fail = em },
     }
 
-    const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{
+    const vaddr = try lf.getAnonDeclVAddr(decl_val, .{
         .parent_atom_index = reloc_info.parent_atom_index,
         .offset = code.items.len,
         .addend = reloc_info.addend orelse 0,
@@ -802,7 +815,7 @@ fn lowerAnonDeclRef(
 }
 
 fn lowerDeclRef(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     decl_index: InternPool.DeclIndex,
     code: *std.ArrayList(u8),
@@ -811,20 +824,21 @@ fn lowerDeclRef(
 ) CodeGenError!Result {
     _ = src_loc;
     _ = debug_output;
-    const target = bin_file.options.target;
-    const mod = bin_file.comp.module.?;
+    const zcu = lf.comp.module.?;
+    const decl = zcu.declPtr(decl_index);
+    const namespace = zcu.namespacePtr(decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
 
     const ptr_width = target.ptrBitWidth();
-    const decl = mod.declPtr(decl_index);
-    const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
-    if (!is_fn_body and !decl.ty.hasRuntimeBits(mod)) {
+    const is_fn_body = decl.ty.zigTypeTag(zcu) == .Fn;
+    if (!is_fn_body and !decl.ty.hasRuntimeBits(zcu)) {
         try code.appendNTimes(0xaa, @divExact(ptr_width, 8));
         return Result.ok;
     }
 
-    try mod.markDeclAlive(decl);
+    try zcu.markDeclAlive(decl);
 
-    const vaddr = try bin_file.getDeclVAddr(decl_index, .{
+    const vaddr = try lf.getDeclVAddr(decl_index, .{
         .parent_atom_index = reloc_info.parent_atom_index,
         .offset = code.items.len,
         .addend = reloc_info.addend orelse 0,
@@ -897,27 +911,29 @@ pub const GenResult = union(enum) {
 };
 
 fn genDeclRef(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     tv: TypedValue,
     ptr_decl_index: InternPool.DeclIndex,
 ) CodeGenError!GenResult {
-    const mod = bin_file.comp.module.?;
-    log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) });
+    const zcu = lf.comp.module.?;
+    log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) });
+
+    const ptr_decl = zcu.declPtr(ptr_decl_index);
+    const namespace = zcu.namespacePtr(ptr_decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
 
-    const target = bin_file.options.target;
     const ptr_bits = target.ptrBitWidth();
     const ptr_bytes: u64 = @divExact(ptr_bits, 8);
 
-    const ptr_decl = mod.declPtr(ptr_decl_index);
-    const decl_index = switch (mod.intern_pool.indexToKey(try ptr_decl.internValue(mod))) {
+    const decl_index = switch (zcu.intern_pool.indexToKey(try ptr_decl.internValue(zcu))) {
         .func => |func| func.owner_decl,
         .extern_func => |extern_func| extern_func.decl,
         else => ptr_decl_index,
     };
-    const decl = mod.declPtr(decl_index);
+    const decl = zcu.declPtr(decl_index);
 
-    if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
+    if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
         const imm: u64 = switch (ptr_bytes) {
             1 => 0xaa,
             2 => 0xaaaa,
@@ -929,30 +945,30 @@ fn genDeclRef(
     }
 
     // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
-    if (tv.ty.castPtrToFn(mod)) |fn_ty| {
-        if (mod.typeToFunc(fn_ty).?.is_generic) {
-            return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod).toByteUnitsOptional().? });
+    if (tv.ty.castPtrToFn(zcu)) |fn_ty| {
+        if (zcu.typeToFunc(fn_ty).?.is_generic) {
+            return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? });
         }
-    } else if (tv.ty.zigTypeTag(mod) == .Pointer) {
-        const elem_ty = tv.ty.elemType2(mod);
-        if (!elem_ty.hasRuntimeBits(mod)) {
-            return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod).toByteUnitsOptional().? });
+    } else if (tv.ty.zigTypeTag(zcu) == .Pointer) {
+        const elem_ty = tv.ty.elemType2(zcu);
+        if (!elem_ty.hasRuntimeBits(zcu)) {
+            return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? });
         }
     }
 
-    try mod.markDeclAlive(decl);
+    try zcu.markDeclAlive(decl);
 
-    const decl_namespace = mod.namespacePtr(decl.namespace_index);
-    const single_threaded = decl_namespace.file_scope.mod.single_threaded;
-    const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !single_threaded;
-    const is_extern = decl.isExtern(mod);
+    const decl_namespace = zcu.namespacePtr(decl.namespace_index);
+    const single_threaded = decl_namespace.file_scope.zcu.single_threaded;
+    const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded;
+    const is_extern = decl.isExtern(zcu);
 
-    if (bin_file.cast(link.File.Elf)) |elf_file| {
+    if (lf.cast(link.File.Elf)) |elf_file| {
         if (is_extern) {
-            const name = mod.intern_pool.stringToSlice(decl.name);
+            const name = zcu.intern_pool.stringToSlice(decl.name);
             // TODO audit this
-            const lib_name = if (decl.getOwnedVariable(mod)) |ov|
-                mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
+            const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
+                zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
             else
                 null;
             const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
@@ -965,12 +981,12 @@ fn genDeclRef(
             return GenResult.mcv(.{ .load_tlv = sym.esym_index });
         }
         return GenResult.mcv(.{ .load_symbol = sym.esym_index });
-    } else if (bin_file.cast(link.File.MachO)) |macho_file| {
+    } else if (lf.cast(link.File.MachO)) |macho_file| {
         if (is_extern) {
             // TODO make this part of getGlobalSymbol
-            const name = mod.intern_pool.stringToSlice(decl.name);
-            const sym_name = try std.fmt.allocPrint(bin_file.allocator, "_{s}", .{name});
-            defer bin_file.allocator.free(sym_name);
+            const name = zcu.intern_pool.stringToSlice(decl.name);
+            const sym_name = try std.fmt.allocPrint(lf.allocator, "_{s}", .{name});
+            defer lf.allocator.free(sym_name);
             const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true });
             return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index });
         }
@@ -980,110 +996,118 @@ fn genDeclRef(
             return GenResult.mcv(.{ .load_tlv = sym_index });
         }
         return GenResult.mcv(.{ .load_got = sym_index });
-    } else if (bin_file.cast(link.File.Coff)) |coff_file| {
+    } else if (lf.cast(link.File.Coff)) |coff_file| {
         if (is_extern) {
-            const name = mod.intern_pool.stringToSlice(decl.name);
+            const name = zcu.intern_pool.stringToSlice(decl.name);
             // TODO audit this
-            const lib_name = if (decl.getOwnedVariable(mod)) |ov|
-                mod.intern_pool.stringToSliceUnwrap(ov.lib_name)
+            const lib_name = if (decl.getOwnedVariable(zcu)) |ov|
+                zcu.intern_pool.stringToSliceUnwrap(ov.lib_name)
             else
                 null;
             const global_index = try coff_file.getGlobalSymbol(name, lib_name);
-            try coff_file.need_got_table.put(bin_file.allocator, global_index, {}); // needs GOT
+            try coff_file.need_got_table.put(lf.allocator, global_index, {}); // needs GOT
             return GenResult.mcv(.{ .load_got = link.File.Coff.global_symbol_bit | global_index });
         }
         const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
         const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
         return GenResult.mcv(.{ .load_got = sym_index });
-    } else if (bin_file.cast(link.File.Plan9)) |p9| {
+    } else if (lf.cast(link.File.Plan9)) |p9| {
         const atom_index = try p9.seeDecl(decl_index);
         const atom = p9.getAtom(atom_index);
         return GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(p9) });
     } else {
-        return GenResult.fail(bin_file.allocator, src_loc, "TODO genDeclRef for target {}", .{target});
+        return GenResult.fail(lf.allocator, src_loc, "TODO genDeclRef for target {}", .{target});
     }
 }
 
 fn genUnnamedConst(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     tv: TypedValue,
     owner_decl_index: InternPool.DeclIndex,
 ) CodeGenError!GenResult {
-    const mod = bin_file.comp.module.?;
-    log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) });
+    const zcu = lf.comp.module.?;
+    const gpa = lf.comp.gpa;
+    log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) });
 
-    const target = bin_file.options.target;
-    const local_sym_index = bin_file.lowerUnnamedConst(tv, owner_decl_index) catch |err| {
-        return GenResult.fail(bin_file.allocator, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
+    const local_sym_index = lf.lowerUnnamedConst(tv, owner_decl_index) catch |err| {
+        return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
     };
-    if (bin_file.cast(link.File.Elf)) |elf_file| {
-        const local = elf_file.symbol(local_sym_index);
-        return GenResult.mcv(.{ .load_symbol = local.esym_index });
-    } else if (bin_file.cast(link.File.MachO)) |_| {
-        return GenResult.mcv(.{ .load_direct = local_sym_index });
-    } else if (bin_file.cast(link.File.Coff)) |_| {
-        return GenResult.mcv(.{ .load_direct = local_sym_index });
-    } else if (bin_file.cast(link.File.Plan9)) |_| {
-        const atom_index = local_sym_index; // plan9 returns the atom_index
-        return GenResult.mcv(.{ .load_direct = atom_index });
-    } else {
-        return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target});
+    switch (lf.tag) {
+        .elf => {
+            const elf_file = lf.cast(link.File.Elf).?;
+            const local = elf_file.symbol(local_sym_index);
+            return GenResult.mcv(.{ .load_symbol = local.esym_index });
+        },
+        .macho, .coff => {
+            return GenResult.mcv(.{ .load_direct = local_sym_index });
+        },
+        .plan9 => {
+            const atom_index = local_sym_index; // plan9 returns the atom_index
+            return GenResult.mcv(.{ .load_direct = atom_index });
+        },
+
+        .c => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for -ofmt=c", .{}),
+        .wasm => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for wasm", .{}),
+        .spirv => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for spirv", .{}),
+        .nvptx => return GenResult.fail(gpa, src_loc, "TODO genUnnamedConst for nvptx", .{}),
     }
 }
 
 pub fn genTypedValue(
-    bin_file: *link.File,
+    lf: *link.File,
     src_loc: Module.SrcLoc,
     arg_tv: TypedValue,
     owner_decl_index: InternPool.DeclIndex,
 ) CodeGenError!GenResult {
-    const mod = bin_file.comp.module.?;
+    const zcu = lf.comp.module.?;
     const typed_value = arg_tv;
 
     log.debug("genTypedValue: ty = {}, val = {}", .{
-        typed_value.ty.fmt(mod),
-        typed_value.val.fmtValue(typed_value.ty, mod),
+        typed_value.ty.fmt(zcu),
+        typed_value.val.fmtValue(typed_value.ty, zcu),
     });
 
-    if (typed_value.val.isUndef(mod))
+    if (typed_value.val.isUndef(zcu))
         return GenResult.mcv(.undef);
 
-    const target = bin_file.options.target;
+    const owner_decl = zcu.declPtr(owner_decl_index);
+    const namespace = zcu.namespacePtr(owner_decl.src_namespace);
+    const target = namespace.file_scope.mod.target;
     const ptr_bits = target.ptrBitWidth();
 
-    if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
+    if (!typed_value.ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) {
         .ptr => |ptr| switch (ptr.addr) {
-            .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl),
-            .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl),
+            .decl => |decl| return genDeclRef(lf, src_loc, typed_value, decl),
+            .mut_decl => |mut_decl| return genDeclRef(lf, src_loc, typed_value, mut_decl.decl),
             else => {},
         },
         else => {},
     };
 
-    switch (typed_value.ty.zigTypeTag(mod)) {
+    switch (typed_value.ty.zigTypeTag(zcu)) {
         .Void => return GenResult.mcv(.none),
-        .Pointer => switch (typed_value.ty.ptrSize(mod)) {
+        .Pointer => switch (typed_value.ty.ptrSize(zcu)) {
             .Slice => {},
             else => switch (typed_value.val.toIntern()) {
                 .null_value => {
                     return GenResult.mcv(.{ .immediate = 0 });
                 },
                 .none => {},
-                else => switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
+                else => switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) {
                     .int => {
-                        return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) });
+                        return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(zcu) });
                     },
                     else => {},
                 },
             },
         },
         .Int => {
-            const info = typed_value.ty.intInfo(mod);
+            const info = typed_value.ty.intInfo(zcu);
             if (info.bits <= ptr_bits) {
                 const unsigned = switch (info.signedness) {
-                    .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(mod))),
-                    .unsigned => typed_value.val.toUnsignedInt(mod),
+                    .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(zcu))),
+                    .unsigned => typed_value.val.toUnsignedInt(zcu),
                 };
                 return GenResult.mcv(.{ .immediate = unsigned });
             }
@@ -1092,45 +1116,45 @@ pub fn genTypedValue(
             return GenResult.mcv(.{ .immediate = @intFromBool(typed_value.val.toBool()) });
         },
         .Optional => {
-            if (typed_value.ty.isPtrLikeOptional(mod)) {
-                return genTypedValue(bin_file, src_loc, .{
-                    .ty = typed_value.ty.optionalChild(mod),
-                    .val = typed_value.val.optionalValue(mod) orelse return GenResult.mcv(.{ .immediate = 0 }),
+            if (typed_value.ty.isPtrLikeOptional(zcu)) {
+                return genTypedValue(lf, src_loc, .{
+                    .ty = typed_value.ty.optionalChild(zcu),
+                    .val = typed_value.val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }),
                 }, owner_decl_index);
-            } else if (typed_value.ty.abiSize(mod) == 1) {
-                return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(mod)) });
+            } else if (typed_value.ty.abiSize(zcu) == 1) {
+                return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(zcu)) });
             }
         },
         .Enum => {
-            const enum_tag = mod.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag;
-            const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
-            return genTypedValue(bin_file, src_loc, .{
+            const enum_tag = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag;
+            const int_tag_ty = zcu.intern_pool.typeOf(enum_tag.int);
+            return genTypedValue(lf, src_loc, .{
                 .ty = Type.fromInterned(int_tag_ty),
                 .val = Value.fromInterned(enum_tag.int),
             }, owner_decl_index);
         },
         .ErrorSet => {
-            const err_name = mod.intern_pool.indexToKey(typed_value.val.toIntern()).err.name;
-            const error_index = mod.global_error_set.getIndex(err_name).?;
+            const err_name = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).err.name;
+            const error_index = zcu.global_error_set.getIndex(err_name).?;
             return GenResult.mcv(.{ .immediate = error_index });
         },
         .ErrorUnion => {
-            const err_type = typed_value.ty.errorUnionSet(mod);
-            const payload_type = typed_value.ty.errorUnionPayload(mod);
-            if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
+            const err_type = typed_value.ty.errorUnionSet(zcu);
+            const payload_type = typed_value.ty.errorUnionPayload(zcu);
+            if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {
                 // We use the error type directly as the type.
-                const err_int_ty = try mod.errorIntType();
-                switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
-                    .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
+                const err_int_ty = try zcu.errorIntType();
+                switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
+                    .err_name => |err_name| return genTypedValue(lf, src_loc, .{
                         .ty = err_type,
-                        .val = Value.fromInterned((try mod.intern(.{ .err = .{
+                        .val = Value.fromInterned((try zcu.intern(.{ .err = .{
                             .ty = err_type.toIntern(),
                             .name = err_name,
                         } }))),
                     }, owner_decl_index),
-                    .payload => return genTypedValue(bin_file, src_loc, .{
+                    .payload => return genTypedValue(lf, src_loc, .{
                         .ty = err_int_ty,
-                        .val = try mod.intValue(err_int_ty, 0),
+                        .val = try zcu.intValue(err_int_ty, 0),
                     }, owner_decl_index),
                 }
             }
@@ -1148,7 +1172,7 @@ pub fn genTypedValue(
         else => {},
     }
 
-    return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);
+    return genUnnamedConst(lf, src_loc, typed_value, owner_decl_index);
 }
 
 pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 {
src/Compilation.zig
@@ -1915,9 +1915,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
 }
 
 pub fn destroy(self: *Compilation) void {
-    const optional_module = self.module;
-    self.bin_file.destroy();
-    if (optional_module) |module| module.deinit();
+    if (self.bin_file) |lf| lf.destroy();
+    if (self.module) |zcu| zcu.deinit();
 
     const gpa = self.gpa;
     self.work_queue.deinit();
@@ -2059,9 +2058,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
 
     // If using the whole caching strategy, we check for *everything* up front, including
     // C source files.
-    if (comp.bin_file.options.cache_mode == .whole) {
+    if (comp.cache_mode == .whole) {
         // We are about to obtain this lock, so here we give other processes a chance first.
-        comp.bin_file.releaseLock();
+        if (comp.bin_file) |lf| lf.releaseLock();
 
         man = comp.cache_parent.obtain();
         comp.whole_cache_manifest = &man;
@@ -5948,14 +5947,14 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const
 }
 
 fn wantBuildLibCFromSource(comp: Compilation) bool {
-    const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) {
+    const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
         .Obj => false,
-        .Lib => comp.bin_file.options.link_mode == .Dynamic,
+        .Lib => comp.config.link_mode == .Dynamic,
         .Exe => true,
     };
+    const ofmt = comp.root_mod.resolved_target.result.ofmt;
     return comp.config.link_libc and is_exe_or_dyn_lib and
-        comp.bin_file.options.libc_installation == null and
-        comp.bin_file.options.target.ofmt != .c;
+        comp.libc_installation == null and ofmt != .c;
 }
 
 fn wantBuildGLibCFromSource(comp: Compilation) bool {
@@ -5977,13 +5976,13 @@ fn wantBuildMinGWFromSource(comp: Compilation) bool {
 }
 
 fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
-    const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) {
+    const is_exe_or_dyn_lib = switch (comp.config.output_mode) {
         .Obj => false,
-        .Lib => comp.bin_file.options.link_mode == .Dynamic,
+        .Lib => comp.config.link_mode == .Dynamic,
         .Exe => true,
     };
-    return is_exe_or_dyn_lib and comp.bin_file.options.link_libunwind and
-        comp.bin_file.options.target.ofmt != .c;
+    const ofmt = comp.root_mod.resolved_target.result.ofmt;
+    return is_exe_or_dyn_lib and comp.config.link_libunwind and ofmt != .c;
 }
 
 fn setAllocFailure(comp: *Compilation) void {
@@ -6112,7 +6111,7 @@ fn canBuildZigLibC(target: std.Target, use_llvm: bool) bool {
 }
 
 pub fn getZigBackend(comp: Compilation) std.builtin.CompilerBackend {
-    const target = comp.bin_file.options.target;
+    const target = comp.root_mod.resolved_target.result;
     return target_util.zigBackend(target, comp.bin_file.options.use_llvm);
 }
 
src/Module.zig
@@ -623,7 +623,8 @@ pub const Decl = struct {
         // Sanitize the name for nvptx which is more restrictive.
         // TODO This should be handled by the backend, not the frontend. Have a
         // look at how the C backend does it for inspiration.
-        if (mod.comp.bin_file.options.target.cpu.arch.isNvptx()) {
+        const cpu_arch = mod.root_mod.resolved_target.cpu.arch;
+        if (cpu_arch.isNvptx()) {
             for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) {
                 '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
                 else => {},
@@ -4873,12 +4874,18 @@ pub fn errNoteNonLazy(
     };
 }
 
-pub fn getTarget(mod: Module) Target {
-    return mod.comp.bin_file.options.target;
+/// Deprecated. There is no global target for a Zig Compilation Unit. Instead,
+/// look up the target based on the Module that contains the source code being
+/// analyzed.
+pub fn getTarget(zcu: Module) Target {
+    return zcu.root_mod.resolved_target.result;
 }
 
-pub fn optimizeMode(mod: Module) std.builtin.OptimizeMode {
-    return mod.comp.bin_file.options.optimize_mode;
+/// Deprecated. There is no global optimization mode for a Zig Compilation
+/// Unit. Instead, look up the optimization mode based on the Module that
+/// contains the source code being analyzed.
+pub fn optimizeMode(zcu: Module) std.builtin.OptimizeMode {
+    return zcu.root_mod.optimize_mode;
 }
 
 fn lockAndClearFileCompileError(mod: *Module, file: *File) void {
@@ -5620,20 +5627,19 @@ pub const Feature = enum {
     safety_checked_instructions,
 };
 
-pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
+pub fn backendSupportsFeature(zcu: Module, feature: Feature) bool {
+    const cpu_arch = zcu.root_mod.resolved_target.cpu.arch;
+    const ofmt = zcu.root_mod.resolved_target.ofmt;
+    const use_llvm = zcu.comp.config.use_llvm;
     return switch (feature) {
-        .panic_fn => mod.comp.bin_file.options.target.ofmt == .c or
-            mod.comp.bin_file.options.use_llvm or
-            mod.comp.bin_file.options.target.cpu.arch == .x86_64,
-        .panic_unwrap_error => mod.comp.bin_file.options.target.ofmt == .c or
-            mod.comp.bin_file.options.use_llvm,
-        .safety_check_formatted => mod.comp.bin_file.options.target.ofmt == .c or
-            mod.comp.bin_file.options.use_llvm,
-        .error_return_trace => mod.comp.bin_file.options.use_llvm,
-        .is_named_enum_value => mod.comp.bin_file.options.use_llvm,
-        .error_set_has_value => mod.comp.bin_file.options.use_llvm or mod.comp.bin_file.options.target.isWasm(),
-        .field_reordering => mod.comp.bin_file.options.use_llvm,
-        .safety_checked_instructions => mod.comp.bin_file.options.use_llvm,
+        .panic_fn => ofmt == .c or use_llvm or cpu_arch == .x86_64,
+        .panic_unwrap_error => ofmt == .c or use_llvm,
+        .safety_check_formatted => ofmt == .c or use_llvm,
+        .error_return_trace => use_llvm,
+        .is_named_enum_value => use_llvm,
+        .error_set_has_value => use_llvm or cpu_arch.isWasm(),
+        .field_reordering => use_llvm,
+        .safety_checked_instructions => use_llvm,
     };
 }