diff --git a/src/Compilation.zig b/src/Compilation.zig index a39d852563..14a39f1bb3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -229,7 +229,7 @@ pub const Emit = struct { /// Returns the full path to `basename` if it were in the same directory as the /// `Emit` sub_path. - pub fn basenamePath(emit: Emit, arena: Allocator, basename: [:0]const u8) ![:0]const u8 { + pub fn basenamePath(emit: Emit, arena: Allocator, basename: []const u8) ![:0]const u8 { const full_path = if (emit.directory.path) |p| try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path }) else @@ -238,7 +238,7 @@ pub const Emit = struct { if (std.fs.path.dirname(full_path)) |dirname| { return try std.fs.path.joinZ(arena, &.{ dirname, basename }); } else { - return basename; + return try arena.dupeZ(u8, basename); } } }; @@ -1038,8 +1038,8 @@ pub const InitOptions = struct { linker_compress_debug_sections: ?link.File.Elf.CompressDebugSections = null, linker_module_definition_file: ?[]const u8 = null, linker_sort_section: ?link.File.Elf.SortSection = null, - major_subsystem_version: ?u32 = null, - minor_subsystem_version: ?u32 = null, + major_subsystem_version: ?u16 = null, + minor_subsystem_version: ?u16 = null, clang_passthrough_mode: bool = false, verbose_cc: bool = false, verbose_link: bool = false, diff --git a/src/Module.zig b/src/Module.zig index 571301c8e6..6d5a2f78a6 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4309,14 +4309,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err decl.has_linksection_or_addrspace = has_linksection_or_addrspace; decl.zir_decl_index = @enumFromInt(decl_sub_index); if (decl.getOwnedFunction(mod) != null) { - switch (comp.bin_file.tag) { - .coff, .elf, .macho, .plan9 => { - // TODO Look into detecting when this would be unnecessary by storing enough state - // in `Decl` to notice that the line number did not change. - comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); - }, - .c, .wasm, .spirv, .nvptx => {}, - } + // TODO Look into detecting when this would be unnecessary by storing enough state + // in `Decl` to notice that the line number did not change. + comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index }); } } diff --git a/src/Sema.zig b/src/Sema.zig index 6d14deb095..26afd285c7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -20043,7 +20043,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { if (sema.owner_func_index != .none and ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and - mod.ownerModule().error_tracing and + block.ownerModule().error_tracing and mod.backendSupportsFeature(.error_return_trace)) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index dbb87fa566..55e241cbd4 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -800,19 +800,20 @@ pub fn generate( ) CodeGenError!Result { const comp = bin_file.comp; const gpa = comp.gpa; - const mod = comp.module.?; - const func = mod.funcInfo(func_index); - const fn_owner_decl = mod.declPtr(func.owner_decl); + const zcu = 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 = mod.namespacePtr(fn_owner_decl.src_namespace); - const target = namespace.file_scope.mod.resolved_target.result; + const namespace = zcu.namespacePtr(fn_owner_decl.src_namespace); + const mod = namespace.file_scope.mod; var function = Self{ .gpa = gpa, .air = air, .liveness = liveness, - .target = target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .func_index = func_index }, @@ -843,7 +844,7 @@ pub fn generate( wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); - const ip = &mod.intern_pool; + const ip = &zcu.intern_pool; try function.frame_allocs.resize(gpa, FrameIndex.named_count); function.frame_allocs.set( @@ -858,7 +859,7 @@ pub fn generate( FrameAlloc.init(.{ .size = 0, .alignment = .@"1" }), ); - const fn_info = mod.typeToFunc(fn_type).?; + const fn_info = zcu.typeToFunc(fn_type).?; const cc = abi.resolveCallingConvention(fn_info.cc, function.target.*); var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) { error.CodegenFail => return Result{ .fail = function.err_msg.? }, @@ -877,14 +878,14 @@ pub fn generate( function.args = call_info.args; function.ret_mcv = call_info.return_value; function.frame_allocs.set(@intFromEnum(FrameIndex.ret_addr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(mod), - .alignment = Type.usize.abiAlignment(mod).min(call_info.stack_align), + .size = Type.usize.abiSize(zcu), + .alignment = Type.usize.abiAlignment(zcu).min(call_info.stack_align), })); function.frame_allocs.set(@intFromEnum(FrameIndex.base_ptr), FrameAlloc.init(.{ - .size = Type.usize.abiSize(mod), + .size = Type.usize.abiSize(zcu), .alignment = Alignment.min( call_info.stack_align, - Alignment.fromNonzeroByteUnits(target.stackAlignment()), + Alignment.fromNonzeroByteUnits(function.target.stackAlignment()), ), })); function.frame_allocs.set( @@ -927,6 +928,9 @@ pub fn generate( .mir = mir, .cc = cc, .src_loc = src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -970,16 +974,14 @@ pub fn generateLazy( ) CodeGenError!Result { const comp = bin_file.comp; const gpa = comp.gpa; - const zcu = 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.resolved_target.result; + // This function is for generating global code, so we use the root module. + const mod = comp.root_mod; var function = Self{ .gpa = gpa, .air = undefined, .liveness = undefined, - .target = target, + .target = &mod.resolved_target.result, + .mod = mod, .bin_file = bin_file, .debug_output = debug_output, .owner = .{ .lazy_sym = lazy_sym }, @@ -1020,6 +1022,9 @@ pub fn generateLazy( .mir = mir, .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), .src_loc = src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }, .debug_output = debug_output, .code = code, @@ -1104,6 +1109,8 @@ fn formatWipMir( _: std.fmt.FormatOptions, writer: anytype, ) @TypeOf(writer).Error!void { + const comp = data.self.bin_file.comp; + const mod = comp.root_mod; var lower = Lower{ .bin_file = data.self.bin_file, .allocator = data.self.gpa, @@ -1114,6 +1121,9 @@ fn formatWipMir( }, .cc = .Unspecified, .src_loc = data.self.src_loc, + .output_mode = comp.config.output_mode, + .link_mode = comp.config.link_mode, + .pic = mod.pic, }; var first = true; for ((lower.lowerMir(data.inst) catch |err| switch (err) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7e25a4b59b..3a53bddcb8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1168,7 +1168,7 @@ pub const Object = struct { pre_ir_path: ?[]const u8, pre_bc_path: ?[]const u8, bin_path: ?[*:0]const u8, - emit_asm: ?[*:0]const u8, + asm_path: ?[*:0]const u8, post_ir_path: ?[*:0]const u8, post_bc_path: ?[*:0]const u8, diff --git a/src/link.zig b/src/link.zig index 14b180ed2a..3e5caf9fc1 100644 --- a/src/link.zig +++ b/src/link.zig @@ -61,6 +61,7 @@ pub const File = struct { intermediary_basename: ?[]const u8 = null, disable_lld_caching: bool, gc_sections: bool, + print_gc_sections: bool, build_id: std.zig.BuildId, rpath_list: []const []const u8, /// List of symbols forced as undefined in the symbol table @@ -114,8 +115,8 @@ pub const File = struct { disable_lld_caching: bool, hash_style: Elf.HashStyle, sort_section: ?Elf.SortSection, - major_subsystem_version: ?u32, - minor_subsystem_version: ?u32, + major_subsystem_version: ?u16, + minor_subsystem_version: ?u16, gc_sections: ?bool, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, @@ -181,9 +182,15 @@ pub const File = struct { emit: Compilation.Emit, options: OpenOptions, ) !*File { - switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { - inline else => |tag| { - const ptr = try tag.Type().open(arena, comp, emit, options); + const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); + switch (tag) { + .c => { + const ptr = try C.open(arena, comp, emit, options); + return &ptr.base; + }, + inline else => |t| { + if (build_options.only_c) unreachable; + const ptr = try t.Type().open(arena, comp, emit, options); return &ptr.base; }, } @@ -195,9 +202,15 @@ pub const File = struct { emit: Compilation.Emit, options: OpenOptions, ) !*File { - switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) { - inline else => |tag| { - const ptr = try tag.Type().createEmpty(arena, comp, emit, options); + const tag = Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt); + switch (tag) { + .c => { + const ptr = try C.createEmpty(arena, comp, emit, options); + return &ptr.base; + }, + inline else => |t| { + if (build_options.only_c) unreachable; + const ptr = try t.Type().createEmpty(arena, comp, emit, options); return &ptr.base; }, } @@ -360,16 +373,12 @@ pub const File = struct { pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).lowerUnnamedConst(tv, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).lowerUnnamedConst(tv, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerUnnamedConst(tv, decl_index), .spirv => unreachable, - .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).lowerUnnamedConst(tv, decl_index), + .c => unreachable, .nvptx => unreachable, - // zig fmt: on + inline else => |t| { + return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(tv, decl_index); + }, } } @@ -382,16 +391,13 @@ pub const File = struct { if (build_options.only_c) @compileError("unreachable"); log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name }); switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).getGlobalSymbol(name, lib_name), - .elf => return @fieldParentPtr(Elf, "base", base).getGlobalSymbol(name, lib_name), - .macho => return @fieldParentPtr(MachO, "base", base).getGlobalSymbol(name, lib_name), .plan9 => unreachable, .spirv => unreachable, - .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getGlobalSymbol(name, lib_name), + .c => unreachable, .nvptx => unreachable, - // zig fmt: on + inline else => |t| { + return @fieldParentPtr(t.Type(), "base", base).getGlobalSymbol(name, lib_name); + }, } } @@ -399,59 +405,48 @@ pub const File = struct { pub fn updateDecl(base: *File, module: *Module, decl_index: InternPool.DeclIndex) UpdateDeclError!void { const decl = module.declPtr(decl_index); assert(decl.has_tv); - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index); - } switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl_index), - .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl_index), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateDecl(module, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDecl(module, decl_index), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDecl(module, decl_index), - // zig fmt: on + .c => { + return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateDecl(module, decl_index); + }, } } /// May be called before or after updateExports for any given Decl. - pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); - } + pub fn updateFunc( + base: *File, + module: *Module, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, + ) UpdateDeclError!void { switch (base.tag) { - // zig fmt: off - .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness), - .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness), - .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness), - .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness), - // zig fmt: on + .c => { + return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateFunc(module, func_index, air, liveness); + }, } } pub fn updateDeclLineNumber(base: *File, module: *Module, decl_index: InternPool.DeclIndex) UpdateDeclError!void { const decl = module.declPtr(decl_index); assert(decl.has_tv); - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl_index), - .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl_index), - .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl_index), - .c => return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclLineNumber(module, decl_index), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDeclLineNumber(module, decl_index), .spirv, .nvptx => {}, + .c => { + return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateDeclLineNumber(module, decl_index); + }, } } @@ -477,44 +472,11 @@ pub const File = struct { base.misc_errors.deinit(gpa); } switch (base.tag) { - .coff => { + .c => @fieldParentPtr(C, "base", base).deinit(), + + inline else => |tag| { if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Coff, "base", base); - parent.deinit(); - }, - .elf => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Elf, "base", base); - parent.deinit(); - }, - .macho => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(MachO, "base", base); - parent.deinit(); - }, - .c => { - const parent = @fieldParentPtr(C, "base", base); - parent.deinit(); - }, - .wasm => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Wasm, "base", base); - parent.deinit(); - }, - .spirv => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(SpirV, "base", base); - parent.deinit(); - }, - .plan9 => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(Plan9, "base", base); - parent.deinit(); - }, - .nvptx => { - if (build_options.only_c) unreachable; - const parent = @fieldParentPtr(NvPtx, "base", base); - parent.deinit(); + @fieldParentPtr(tag.Type(), "base", base).deinit(); }, } } @@ -619,51 +581,36 @@ pub const File = struct { return base.linkAsArchive(comp, prog_node); } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).flush(comp, prog_node), - .elf => return @fieldParentPtr(Elf, "base", base).flush(comp, prog_node), - .macho => return @fieldParentPtr(MachO, "base", base).flush(comp, prog_node), - .c => return @fieldParentPtr(C, "base", base).flush(comp, prog_node), - .wasm => return @fieldParentPtr(Wasm, "base", base).flush(comp, prog_node), - .spirv => return @fieldParentPtr(SpirV, "base", base).flush(comp, prog_node), - .plan9 => return @fieldParentPtr(Plan9, "base", base).flush(comp, prog_node), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).flush(comp, prog_node), + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).flush(comp, prog_node); + }, } } /// Commit pending changes and write headers. Works based on `effectiveOutputMode` /// rather than final output mode. pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node), - .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node), - .macho => return @fieldParentPtr(MachO, "base", base).flushModule(comp, prog_node), - .c => return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node), - .wasm => return @fieldParentPtr(Wasm, "base", base).flushModule(comp, prog_node), - .spirv => return @fieldParentPtr(SpirV, "base", base).flushModule(comp, prog_node), - .plan9 => return @fieldParentPtr(Plan9, "base", base).flushModule(comp, prog_node), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).flushModule(comp, prog_node), + .c => { + return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).flushModule(comp, prog_node); + }, } } /// Called when a Decl is deleted from the Module. pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).freeDecl(decl_index); - } switch (base.tag) { - .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl_index), - .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl_index), - .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl_index), - .c => @fieldParentPtr(C, "base", base).freeDecl(decl_index), - .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl_index), - .spirv => @fieldParentPtr(SpirV, "base", base).freeDecl(decl_index), - .plan9 => @fieldParentPtr(Plan9, "base", base).freeDecl(decl_index), - .nvptx => @fieldParentPtr(NvPtx, "base", base).freeDecl(decl_index), + .c => { + @fieldParentPtr(C, "base", base).freeDecl(decl_index); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + @fieldParentPtr(tag.Type(), "base", base).freeDecl(decl_index); + }, } } @@ -682,19 +629,14 @@ pub const File = struct { exported: Module.Exported, exports: []const *Module.Export, ) UpdateExportsError!void { - if (build_options.only_c) { - assert(base.tag == .c); - return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports); - } switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).updateExports(module, exported, exports), - .elf => return @fieldParentPtr(Elf, "base", base).updateExports(module, exported, exports), - .macho => return @fieldParentPtr(MachO, "base", base).updateExports(module, exported, exports), - .c => return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports), - .wasm => return @fieldParentPtr(Wasm, "base", base).updateExports(module, exported, exports), - .spirv => return @fieldParentPtr(SpirV, "base", base).updateExports(module, exported, exports), - .plan9 => return @fieldParentPtr(Plan9, "base", base).updateExports(module, exported, exports), - .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateExports(module, exported, exports), + .c => { + return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports); + }, + inline else => |tag| { + if (build_options.only_c) unreachable; + return @fieldParentPtr(tag.Type(), "base", base).updateExports(module, exported, exports); + }, } } @@ -711,60 +653,64 @@ pub const File = struct { /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate /// the block/atom. pub fn getDeclVAddr(base: *File, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) unreachable; + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl_index, reloc_info), - .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl_index, reloc_info), - .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl_index, reloc_info), - .plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl_index, reloc_info), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl_index, reloc_info), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).getDeclVAddr(decl_index, reloc_info); + }, } } pub const LowerResult = @import("codegen.zig").Result; - pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !LowerResult { - if (build_options.only_c) unreachable; + pub fn lowerAnonDecl( + base: *File, + decl_val: InternPool.Index, + decl_align: InternPool.Alignment, + src_loc: Module.SrcLoc, + ) !LowerResult { + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), - .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).lowerAnonDecl(decl_val, decl_align, src_loc); + }, } } pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 { - if (build_options.only_c) unreachable; + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .elf => return @fieldParentPtr(Elf, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .macho => return @fieldParentPtr(MachO, "base", base).getAnonDeclVAddr(decl_val, reloc_info), - .plan9 => return @fieldParentPtr(Plan9, "base", base).getAnonDeclVAddr(decl_val, reloc_info), .c => unreachable, - .wasm => return @fieldParentPtr(Wasm, "base", base).getAnonDeclVAddr(decl_val, reloc_info), .spirv => unreachable, .nvptx => unreachable, + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).getAnonDeclVAddr(decl_val, reloc_info); + }, } } - pub fn deleteDeclExport(base: *File, decl_index: InternPool.DeclIndex, name: InternPool.NullTerminatedString) !void { - if (build_options.only_c) unreachable; + pub fn deleteDeclExport( + base: *File, + decl_index: InternPool.DeclIndex, + name: InternPool.NullTerminatedString, + ) !void { + if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { - .coff => return @fieldParentPtr(Coff, "base", base).deleteDeclExport(decl_index, name), - .elf => return @fieldParentPtr(Elf, "base", base).deleteDeclExport(decl_index, name), - .macho => return @fieldParentPtr(MachO, "base", base).deleteDeclExport(decl_index, name), - .plan9 => {}, - .c => {}, - .wasm => return @fieldParentPtr(Wasm, "base", base).deleteDeclExport(decl_index), - .spirv => {}, - .nvptx => {}, + .plan9, + .c, + .spirv, + .nvptx, + => {}, + + inline else => |tag| { + return @fieldParentPtr(tag.Type(), "base", base).deleteDeclExport(decl_index, name); + }, } } @@ -1049,7 +995,7 @@ pub const File = struct { base: File, arena: Allocator, opt_loc: ?Compilation.EmitLoc, - ) Allocator.Error!?[*:0]u8 { + ) Allocator.Error!?[*:0]const u8 { const loc = opt_loc orelse return null; const slice = if (loc.directory) |directory| try directory.joinZ(arena, &.{loc.basename}) @@ -1071,7 +1017,7 @@ pub const File = struct { sub_prog_node.context.refresh(); defer sub_prog_node.end(); - try llvm_object.emit(comp, .{ + try llvm_object.emit(.{ .pre_ir_path = comp.verbose_llvm_ir, .pre_bc_path = comp.verbose_llvm_bc, .bin_path = try base.resolveEmitLoc(arena, .{ @@ -1079,8 +1025,8 @@ pub const File = struct { .basename = base.intermediary_basename.?, }), .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm), - .post_llvm_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), - .post_llvm_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), + .post_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir), + .post_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc), .is_debug = comp.root_mod.optimize_mode == .Debug, .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, diff --git a/src/link/C.zig b/src/link/C.zig index 3592052cf8..669587bda9 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -135,6 +135,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = file, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index c02aecf2db..98c649ca84 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -14,9 +14,10 @@ nxcompat: bool, dynamicbase: bool, /// TODO this and minor_subsystem_version should be combined into one property and left as /// default or populated together. They should not be separate fields. -major_subsystem_version: u32, -minor_subsystem_version: u32, +major_subsystem_version: u16, +minor_subsystem_version: u16, lib_dirs: []const []const u8, +entry_addr: ?u32, ptr_width: PtrWidth, page_size: u32, @@ -238,7 +239,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Coff { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .coff); @@ -390,6 +390,7 @@ pub fn createEmpty( .emit = emit, .stack_size = options.stack_size orelse 16777216, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, .disable_lld_caching = options.disable_lld_caching, @@ -422,6 +423,8 @@ pub fn createEmpty( .major_subsystem_version = options.major_subsystem_version orelse 6, .minor_subsystem_version = options.minor_subsystem_version orelse 0, .lib_dirs = options.lib_dirs, + .entry_addr = math.cast(u32, options.entry_addr orelse 0) orelse + return error.EntryAddressTooBig, }; const use_llvm = comp.config.use_llvm; @@ -2329,8 +2332,8 @@ fn writeHeader(self: *Coff) !void { .minor_operating_system_version = 0, .major_image_version = 0, .minor_image_version = 0, - .major_subsystem_version = self.major_subsystem_version, - .minor_subsystem_version = self.minor_subsystem_version, + .major_subsystem_version = @intCast(self.major_subsystem_version), + .minor_subsystem_version = @intCast(self.minor_subsystem_version), .win32_version_value = 0, .size_of_image = size_of_image, .size_of_headers = size_of_headers, @@ -2342,7 +2345,7 @@ fn writeHeader(self: *Coff) !void { .size_of_heap_reserve = default_size_of_heap_reserve, .size_of_heap_commit = default_size_of_heap_commit, .loader_flags = 0, - .number_of_rva_and_sizes = @as(u32, @intCast(self.data_directories.len)), + .number_of_rva_and_sizes = @intCast(self.data_directories.len), }; writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; }, diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index ad9e18fa22..a94644a41e 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -21,7 +21,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const tracy = trace(@src()); defer tracy.end(); - var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); @@ -30,7 +31,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. - const module_obj_path: ?[]const u8 = if (self.base.comp.module != null) blk: { + const module_obj_path: ?[]const u8 = if (comp.module != null) blk: { try self.flushModule(comp, prog_node); if (fs.path.dirname(full_out_path)) |dirname| { @@ -45,12 +46,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod sub_prog_node.context.refresh(); defer sub_prog_node.end(); - const is_lib = self.base.comp.config.output_mode == .Lib; - const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib; - const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe; + const is_lib = comp.config.output_mode == .Lib; + const is_dyn_lib = comp.config.link_mode == .Dynamic and is_lib; + const is_exe_or_dyn_lib = is_dyn_lib or comp.config.output_mode == .Exe; const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib; - const target = self.base.comp.root_mod.resolved_target.result; - const optimize_mode = self.base.comp.root_mod.optimize_mode; + const target = comp.root_mod.resolved_target.result; + const optimize_mode = comp.root_mod.optimize_mode; // See link/Elf.zig for comments on how this mechanism works. const id_symlink_basename = "lld.id"; @@ -85,8 +86,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod man.hash.addListOfBytes(self.lib_dirs); man.hash.add(comp.skip_linker_dependencies); if (comp.config.link_libc) { - man.hash.add(self.base.comp.libc_installation != null); - if (self.base.comp.libc_installation) |libc_installation| { + man.hash.add(comp.libc_installation != null); + if (comp.libc_installation) |libc_installation| { man.hash.addBytes(libc_installation.crt_dir.?); if (target.abi == .msvc) { man.hash.addBytes(libc_installation.msvc_lib_dir.?); @@ -94,7 +95,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } } - try link.hashAddSystemLibs(&man, self.base.comp.system_libs); + try link.hashAddSystemLibs(&man, comp.system_libs); man.hash.addListOfBytes(self.base.force_undefined_symbols.keys()); man.hash.addOptional(self.subsystem); man.hash.add(comp.config.is_test); @@ -136,7 +137,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod }; } - if (self.base.comp.config.output_mode == .Obj) { + if (comp.config.output_mode == .Obj) { // LLD's COFF driver does not support the equivalent of `-r` so we do a simple file copy // here. TODO: think carefully about how we can avoid this redundant operation when doing // build-obj. See also the corresponding TODO in linkAsArchive. @@ -161,7 +162,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } else { // Create an LLD command line and invoke it. - var argv = std.ArrayList([]const u8).init(self.base.allocator); + var argv = std.ArrayList([]const u8).init(gpa); defer argv.deinit(); // We will invoke ourselves as a child process to gain access to LLD. // This is necessary because LLD does not behave properly as a library - @@ -192,7 +193,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), } } - if (self.base.comp.config.output_mode == .Exe) { + if (comp.config.output_mode == .Exe) { try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{self.image_base})); @@ -242,7 +243,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } if (comp.config.link_libc) { - if (self.base.comp.libc_installation) |libc_installation| { + if (comp.libc_installation) |libc_installation| { try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?})); if (target.abi == .msvc) { @@ -287,7 +288,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.subsystem) |explicit| break :blk explicit; switch (target.os.tag) { .windows => { - if (self.base.comp.module) |module| { + if (comp.module) |module| { if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib) break :blk null; if (module.stage1_flags.have_c_main or comp.config.is_test or @@ -415,13 +416,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append(try comp.get_libc_crt_file(arena, "uuid.lib")); for (mingw.always_link_libs) |name| { - if (!self.base.comp.system_libs.contains(name)) { + if (!comp.system_libs.contains(name)) { const lib_basename = try allocPrint(arena, "{s}.lib", .{name}); try argv.append(try comp.get_libc_crt_file(arena, lib_basename)); } } } else { - const lib_str = switch (self.base.comp.config.link_mode) { + const lib_str = switch (comp.config.link_mode) { .Dynamic => "", .Static => "lib", }; @@ -429,7 +430,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod .Debug => "d", else => "", }; - switch (self.base.comp.config.link_mode) { + switch (comp.config.link_mode) { .Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})), .Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})), } @@ -448,7 +449,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } else { try argv.append("-NODEFAULTLIB"); if (!is_lib and comp.config.entry == null) { - if (self.base.comp.module) |module| { + if (comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); } else { @@ -485,8 +486,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (comp.compiler_rt_lib) |lib| try argv.append(lib.full_object_path); } - try argv.ensureUnusedCapacity(self.base.comp.system_libs.count()); - for (self.base.comp.system_libs.keys()) |key| { + try argv.ensureUnusedCapacity(comp.system_libs.count()); + for (comp.system_libs.keys()) |key| { const lib_basename = try allocPrint(arena, "{s}.lib", .{key}); if (comp.crt_files.get(lib_basename)) |crt_file| { argv.appendAssumeCapacity(crt_file.full_object_path); @@ -512,7 +513,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod return error.DllImportLibraryNotFound; } - if (self.base.comp.verbose_link) { + if (comp.verbose_link) { // Skip over our own name so that the LLD linker name is the first argv item. Compilation.dump_argv(argv.items[1..]); } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index faaf5100a4..cabaed1add 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1745,6 +1745,7 @@ pub fn freeDecl(self: *Dwarf, decl_index: InternPool.DeclIndex) void { } pub fn writeDbgAbbrev(self: *Dwarf) !void { + const gpa = self.allocator; // These are LEB encoded but since the values are all less than 127 // we can simply append these bytes. // zig fmt: off @@ -1887,7 +1888,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { .wasm => { const wasm_file = self.bin_file.cast(File.Wasm).?; const debug_abbrev = &wasm_file.getAtomPtr(wasm_file.debug_abbrev_atom.?).code; - try debug_abbrev.resize(wasm_file.base.allocator, needed_size); + try debug_abbrev.resize(gpa, needed_size); debug_abbrev.items[0..abbrev_buf.len].* = abbrev_buf; }, else => unreachable, @@ -2236,6 +2237,7 @@ fn writeDbgInfoNopsToArrayList( pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { const comp = self.bin_file.comp; + const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; const target_endian = target.cpu.arch.endian(); const ptr_width_bytes = self.ptrWidthBytes(); @@ -2301,7 +2303,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { .wasm => { const wasm_file = self.bin_file.cast(File.Wasm).?; const debug_ranges = &wasm_file.getAtomPtr(wasm_file.debug_ranges_atom.?).code; - try debug_ranges.resize(wasm_file.base.allocator, needed_size); + try debug_ranges.resize(gpa, needed_size); @memcpy(debug_ranges.items[0..di_buf.items.len], di_buf.items); }, else => unreachable, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 47b4712b57..67478a59e8 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -230,7 +230,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Elf { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .elf); @@ -380,6 +379,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, .file = null, @@ -1175,7 +1175,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node const lib_name = flag["-l".len..]; success: { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lc.crt_dir.?, lib_name, .Dynamic)) break :success; } @@ -1664,7 +1664,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append(p); } } else { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (target.dynamic_linker.get()) |path| { try argv.append("-dynamic-linker"); try argv.append(path); @@ -1742,7 +1742,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try argv.append("now"); } - if (self.isStatic()) { + if (self.base.isStatic()) { try argv.append("-static"); } else if (self.base.isDynLib()) { try argv.append("-shared"); @@ -2023,7 +2023,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { // TODO I think technically we should re-use the mechanism used by the frontend here. // Maybe we should hoist search-strategy all the way here? for (self.lib_dirs) |lib_dir| { - if (!self.isStatic()) { + if (!self.base.isStatic()) { if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic)) break :success; } @@ -3598,7 +3598,7 @@ fn initSyntheticSections(self: *Elf) !void { // In this case, if we do generate .interp section and segment, we will get // a segfault in the dynamic linker trying to load a binary that is static // and doesn't contain .dynamic section. - if (self.isStatic() and !comp.config.pie) break :blk false; + if (self.base.isStatic() and !comp.config.pie) break :blk false; break :blk target.dynamic_linker.get() != null; }; if (needs_interp) { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 9f57dab283..a7b876f619 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -377,8 +377,8 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { } pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void { - const is_static = elf_file.isStatic(); - const is_dyn_lib = elf_file.isDynLib(); + const is_static = elf_file.base.isStatic(); + const is_dyn_lib = elf_file.base.isDynLib(); const file_ptr = self.file(elf_file).?; const rels = self.relocs(elf_file); var i: usize = 0; @@ -660,7 +660,7 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { fn outputType(elf_file: *Elf) u2 { const comp = elf_file.base.comp; - assert(!elf_file.isRelocatable()); + assert(!elf_file.base.isRelocatable()); return switch (elf_file.base.comp.config.output_mode) { .Obj => unreachable, .Lib => 0, diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 35df214b18..b6dced258c 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -250,7 +250,7 @@ fn addAtom(self: *Object, shdr: ElfShdr, shndx: u16, elf_file: *Elf) error{OutOf fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMemory}!u16 { const name = blk: { const name = self.getString(shdr.sh_name); - if (elf_file.isRelocatable()) break :blk name; + if (elf_file.base.isRelocatable()) break :blk name; if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name; const sh_name_prefixes: []const [:0]const u8 = &.{ ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", @@ -278,7 +278,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem }; const flags = blk: { var flags = shdr.sh_flags; - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); } break :blk switch (@"type") { @@ -520,7 +520,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { } const is_import = blk: { - if (!elf_file.isDynLib()) break :blk false; + if (!elf_file.base.isDynLib()) break :blk false; const vis = @as(elf.STV, @enumFromInt(esym.st_other)); if (vis == .HIDDEN) break :blk false; break :blk true; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index b6be4013ce..3a8a77de68 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -370,7 +370,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void { } const is_import = blk: { - if (!elf_file.isDynLib()) break :blk false; + if (!elf_file.base.isDynLib()) break :blk false; const vis = @as(elf.STV, @enumFromInt(esym.st_other)); if (vis == .HIDDEN) break :blk false; break :blk true; diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index e8500e8aa9..75401824ab 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -271,7 +271,7 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { } } - if (!elf_file.isRelocatable()) { + if (!elf_file.base.isRelocatable()) { offset += 4; // NULL terminator } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 9af563b047..35d5c85c2d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -155,6 +155,7 @@ frameworks: []const Framework, install_name: ?[]const u8, /// Path to entitlements file. entitlements: ?[]const u8, +compatibility_version: ?std.SemanticVersion, /// When adding a new field, remember to update `hashAddFrameworks`. pub const Framework = struct { @@ -185,7 +186,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*MachO { - if (build_options.only_c) unreachable; const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -295,6 +295,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -315,6 +316,7 @@ pub fn createEmpty( .frameworks = options.frameworks, .install_name = options.install_name, .entitlements = options.entitlements, + .compatibility_version = options.compatibility_version, }; if (use_llvm and comp.module != null) { @@ -632,7 +634,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No }); { const platform = Platform.fromTarget(target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(self); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else if (platform.isVersionMinCompatible()) { @@ -2237,10 +2239,10 @@ fn allocateGlobal(self: *MachO) !u32 { return index; } -pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.got_table.lookup.contains(target)) return; +pub fn addGotEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.got_table.lookup.contains(reloc_target)) return; const gpa = self.base.comp.gpa; - const got_index = try self.got_table.allocateEntry(gpa, target); + const got_index = try self.got_table.allocateEntry(gpa, reloc_target); if (self.got_section_index == null) { self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{ .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, @@ -2249,20 +2251,22 @@ pub fn addGotEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.mode == .incremental) { try self.writeOffsetTableEntry(got_index); self.got_table_count_dirty = true; - self.markRelocsDirtyByTarget(target); + self.markRelocsDirtyByTarget(reloc_target); } } -pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.stub_table.lookup.contains(target)) return; - const gpa = self.base.comp.gpa; - const stub_index = try self.stub_table.allocateEntry(gpa, target); +pub fn addStubEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.stub_table.lookup.contains(reloc_target)) return; + const comp = self.base.comp; + const gpa = comp.gpa; + const cpu_arch = comp.root_mod.resolved_target.result.cpu.arch; + const stub_index = try self.stub_table.allocateEntry(gpa, reloc_target); if (self.stubs_section_index == null) { self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{ .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, - .reserved2 = stubs.stubSize(target.cpu.arch), + .reserved2 = stubs.stubSize(cpu_arch), }); self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ .flags = macho.S_REGULAR | @@ -2276,14 +2280,14 @@ pub fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void { if (self.mode == .incremental) { try self.writeStubTableEntry(stub_index); self.stub_table_count_dirty = true; - self.markRelocsDirtyByTarget(target); + self.markRelocsDirtyByTarget(reloc_target); } } -pub fn addTlvPtrEntry(self: *MachO, target: SymbolWithLoc) !void { - if (self.tlv_ptr_table.lookup.contains(target)) return; +pub fn addTlvPtrEntry(self: *MachO, reloc_target: SymbolWithLoc) !void { + if (self.tlv_ptr_table.lookup.contains(reloc_target)) return; const gpa = self.base.comp.gpa; - _ = try self.tlv_ptr_table.allocateEntry(gpa, target); + _ = try self.tlv_ptr_table.allocateEntry(gpa, reloc_target); if (self.tlv_ptr_section_index == null) { self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{ .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5185b93386..ad069b845e 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -342,19 +342,22 @@ pub const SplitIntoAtomsError = error{ }; pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) SplitIntoAtomsError!void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; log.debug("splitting object({d}, {s}) into atoms", .{ object_id, self.name }); try self.splitRegularSections(macho_file, object_id); try self.parseEhFrameSection(macho_file, object_id); try self.parseUnwindInfo(macho_file, object_id); - try self.parseDataInCode(macho_file.base.allocator); + try self.parseDataInCode(gpa); } /// Splits input regular sections into Atoms. /// If the Object was compiled with `MH_SUBSECTIONS_VIA_SYMBOLS`, splits section /// into subsections where each subsection then represents an Atom. pub fn splitRegularSections(self: *Object, macho_file: *MachO, object_id: u32) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const sections = self.getSourceSections(); @@ -555,7 +558,8 @@ fn createAtomFromSubsection( alignment: Alignment, out_sect_id: u8, ) !Atom.Index { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const atom_index = try macho_file.createAtom(sym_index, .{ .size = size, .alignment = alignment, @@ -671,7 +675,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void log.debug("parsing __TEXT,__eh_frame section", .{}); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; if (macho_file.eh_frame_section_index == null) { macho_file.eh_frame_section_index = try macho_file.initSection("__TEXT", "__eh_frame", .{}); @@ -767,7 +772,8 @@ fn parseEhFrameSection(self: *Object, macho_file: *MachO, object_id: u32) !void } fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const sect_id = self.unwind_info_sect_id orelse { diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index a92126c07e..02cf68e46e 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -1,7 +1,8 @@ //! An algorithm for dead stripping of unreferenced Atoms. pub fn gcAtoms(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var arena = std.heap.ArenaAllocator.init(gpa); defer arena.deinit(); diff --git a/src/link/MachO/eh_frame.zig b/src/link/MachO/eh_frame.zig index 8223c830e0..4b51d09683 100644 --- a/src/link/MachO/eh_frame.zig +++ b/src/link/MachO/eh_frame.zig @@ -1,5 +1,6 @@ pub fn scanRelocs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; for (macho_file.objects.items, 0..) |*object, object_id| { var cies = std.AutoHashMap(u32, void).init(gpa); @@ -37,7 +38,8 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) error const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var size: u32 = 0; for (macho_file.objects.items, 0..) |*object, object_id| { @@ -89,7 +91,8 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void { const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var eh_records = std.AutoArrayHashMap(u32, EhFrameRecord(true)).init(gpa); defer { diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 8bcf439354..e155a7a8ed 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -63,7 +63,7 @@ fn calcLCsSize(m: *MachO, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 { } // LC_RPATH { - var it = RpathIterator.init(gpa, m.rpath_list); + var it = RpathIterator.init(gpa, m.base.rpath_list); defer it.deinit(); while (try it.next()) |rpath| { sizeofcmds += calcInstallNameLen( @@ -189,17 +189,20 @@ fn writeDylibLC(ctx: WriteDylibLCCtx, lc_writer: anytype) !void { } } -pub fn writeDylibIdLC(gpa: Allocator, options: *const link.Options, lc_writer: anytype) !void { - assert(options.output_mode == .Lib and options.link_mode == .Dynamic); - const emit = options.emit.?; - const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path}); - defer if (options.install_name == null) gpa.free(install_name); - const curr = options.version orelse std.SemanticVersion{ +pub fn writeDylibIdLC(macho_file: *MachO, lc_writer: anytype) !void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + assert(comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic); + const emit = macho_file.base.emit; + const install_name = macho_file.install_name orelse + try emit.directory.join(gpa, &.{emit.sub_path}); + defer if (macho_file.install_name == null) gpa.free(install_name); + const curr = comp.version orelse std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0, }; - const compat = options.compatibility_version orelse std.SemanticVersion{ + const compat = macho_file.compatibility_version orelse std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0, @@ -237,8 +240,11 @@ const RpathIterator = struct { } }; -pub fn writeRpathLCs(gpa: Allocator, options: *const link.Options, lc_writer: anytype) !void { - var it = RpathIterator.init(gpa, options.rpath_list); +pub fn writeRpathLCs(macho_file: *MachO, lc_writer: anytype) !void { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + + var it = RpathIterator.init(gpa, macho_file.base.rpath_list); defer it.deinit(); while (try it.next()) |rpath| { @@ -467,13 +473,14 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { }; } -pub fn inferSdkVersion(gpa: Allocator, comp: *const Compilation) ?std.SemanticVersion { +pub fn inferSdkVersion(macho_file: *MachO) ?std.SemanticVersion { + const comp = macho_file.base.comp; + const gpa = comp.gpa; + var arena_allocator = std.heap.ArenaAllocator.init(gpa); defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const macho_file = comp.bin_file.cast(MachO).?; - const sdk_layout = macho_file.sdk_layout orelse return null; const sdk_dir = switch (sdk_layout) { .sdk => comp.sysroot.?, diff --git a/src/link/MachO/thunks.zig b/src/link/MachO/thunks.zig index 774a8f7344..f080de7f80 100644 --- a/src/link/MachO/thunks.zig +++ b/src/link/MachO/thunks.zig @@ -68,7 +68,8 @@ pub fn createThunks(macho_file: *MachO, sect_id: u8) !void { const header = &macho_file.sections.items(.header)[sect_id]; if (header.size == 0) return; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const first_atom_index = macho_file.sections.items(.first_atom_index)[sect_id].?; header.size = 0; @@ -245,7 +246,8 @@ fn scanRelocs( macho_file.getSymbol(target).n_value, }); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target_sym = macho_file.getSymbol(target); const thunk = &macho_file.thunks.items[thunk_index]; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 06fede6e1b..f8715aa447 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -15,7 +15,7 @@ pub fn linkWithZld( const arena = arena_allocator.allocator(); const directory = emit.directory; // Just an alias to make it shorter to type. - const full_out_path = try directory.join(arena, &[_][]const u8{emit.?.sub_path}); + const full_out_path = try directory.join(arena, &[_][]const u8{emit.sub_path}); const opt_zcu = macho_file.base.comp.module; // If there is no Zig code to compile, then we should skip flushing the output file because it @@ -71,14 +71,14 @@ pub fn linkWithZld( // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.add(stack_size); - man.hash.addOptional(macho_file.pagezero_vmsize); - man.hash.addOptional(macho_file.headerpad_size); + man.hash.add(macho_file.pagezero_vmsize); + man.hash.add(macho_file.headerpad_size); man.hash.add(macho_file.headerpad_max_install_names); man.hash.add(macho_file.base.gc_sections); man.hash.add(macho_file.dead_strip_dylibs); man.hash.add(macho_file.base.comp.root_mod.strip); try MachO.hashAddFrameworks(&man, macho_file.frameworks); - man.hash.addListOfBytes(macho_file.rpath_list); + man.hash.addListOfBytes(macho_file.base.rpath_list); if (is_dyn_lib) { man.hash.addOptionalBytes(macho_file.install_name); man.hash.addOptional(comp.version); @@ -151,7 +151,7 @@ pub fn linkWithZld( try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); } } else { - const sub_path = emit.?.sub_path; + const sub_path = emit.sub_path; const old_file = macho_file.base.file; // TODO is this needed at all? defer macho_file.base.file = old_file; @@ -241,7 +241,7 @@ pub fn linkWithZld( try argv.append(@tagName(platform.os_tag)); try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(macho_file); if (sdk_version) |ver| { try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); } else { @@ -254,13 +254,13 @@ pub fn linkWithZld( try argv.append(syslibroot); } - for (macho_file.rpath_list) |rpath| { + for (macho_file.base.rpath_list) |rpath| { try argv.append("-rpath"); try argv.append(rpath); } try argv.appendSlice(&.{ - "-pagezero_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.pagezero_size}), + "-pagezero_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.pagezero_vmsize}), "-headerpad_size", try std.fmt.allocPrint(arena, "0x{x}", .{macho_file.headerpad_size}), }); @@ -558,7 +558,7 @@ pub fn linkWithZld( }); { const platform = Platform.fromTarget(target); - const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(arena, comp); + const sdk_version: ?std.SemanticVersion = load_commands.inferSdkVersion(macho_file); if (platform.isBuildVersionCompatible()) { try load_commands.writeBuildVersionLC(platform, sdk_version, lc_writer); } else { @@ -609,7 +609,8 @@ pub fn linkWithZld( } fn createSegments(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const page_size = MachO.getPageSize(target.cpu.arch); const aligned_pagezero_vmsize = mem.alignBackward(u64, macho_file.pagezero_vmsize, page_size); @@ -683,7 +684,8 @@ fn createSegments(macho_file: *MachO) !void { } fn writeAtoms(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const slice = macho_file.sections.slice(); for (slice.items(.first_atom_index), 0..) |first_atom_index, sect_id| { @@ -758,7 +760,8 @@ fn writeDyldPrivateAtom(macho_file: *MachO) !void { fn writeThunks(macho_file: *MachO) !void { const target = macho_file.base.comp.root_mod.resolved_target.result; assert(target.cpu.arch == .aarch64); - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const sect_id = macho_file.text_section_index orelse return; const header = macho_file.sections.items(.header)[sect_id]; @@ -778,7 +781,8 @@ fn writeThunks(macho_file: *MachO) !void { } fn writePointerEntries(macho_file: *MachO, sect_id: u8, table: anytype) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const header = macho_file.sections.items(.header)[sect_id]; const capacity = math.cast(usize, header.size) orelse return error.Overflow; var buffer = try std.ArrayList(u8).initCapacity(gpa, capacity); @@ -792,7 +796,8 @@ fn writePointerEntries(macho_file: *MachO, sect_id: u8, table: anytype) !void { } fn writeStubs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const stubs_header = macho_file.sections.items(.header)[macho_file.stubs_section_index.?]; @@ -815,7 +820,8 @@ fn writeStubs(macho_file: *MachO) !void { } fn writeStubHelpers(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const stub_helper_header = macho_file.sections.items(.header)[macho_file.stub_helper_section_index.?]; @@ -859,7 +865,8 @@ fn writeStubHelpers(macho_file: *MachO) !void { } fn writeLaSymbolPtrs(macho_file: *MachO) !void { - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; const target = macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = target.cpu.arch; const la_symbol_ptr_header = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_section_index.?]; @@ -892,7 +899,8 @@ fn pruneAndSortSections(macho_file: *MachO) !void { } }; - const gpa = macho_file.base.allocator; + const comp = macho_file.base.comp; + const gpa = comp.gpa; var entries = try std.ArrayList(Entry).initCapacity(gpa, macho_file.sections.slice().len); defer entries.deinit(); diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index b59a527c5a..2025372323 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -31,8 +31,6 @@ pub fn createEmpty( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*NvPtx { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -55,6 +53,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse false, + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 3fe6aee009..ceabfe2864 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -318,6 +318,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 16777216, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -1314,8 +1315,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Plan9 { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -1525,7 +1524,13 @@ pub fn getDeclVAddr( return undefined; } -pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { +pub fn lowerAnonDecl( + self: *Plan9, + decl_val: InternPool.Index, + explicit_alignment: InternPool.Alignment, + src_loc: Module.SrcLoc, +) !codegen.Result { + _ = explicit_alignment; // This is basically the same as lowerUnnamedConst. // example: // const ty = mod.intern_pool.typeOf(decl_val).toType(); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 853d97b014..5124ff19f6 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -24,7 +24,6 @@ const SpirV = @This(); const std = @import("std"); const Allocator = std.mem.Allocator; -const ArenaAllocator = std.heap.ArenaAllocator; const assert = std.debug.assert; const log = std.log.scoped(.link); @@ -65,6 +64,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse false, + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse 0, .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -98,8 +98,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*SpirV { - if (build_options.only_c) unreachable; - const target = comp.root_mod.resolved_target.result; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -194,7 +192,9 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No const spv = &self.object.spv; + const gpa = comp.gpa; const target = comp.getTarget(); + try writeCapabilities(spv, target); try writeMemoryModel(spv, target); @@ -214,11 +214,11 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No // name if it contains no strange characters is nice for debugging. URI encoding fits the bill. // We're using : as separator, which is a reserved character. - const escaped_name = try std.Uri.escapeString(self.base.allocator, name); - defer self.base.allocator.free(escaped_name); + const escaped_name = try std.Uri.escapeString(gpa, name); + defer gpa.free(escaped_name); try error_info.writer().print(":{s}", .{escaped_name}); } - try spv.sections.debug_strings.emit(spv.gpa, .OpSourceExtension, .{ + try spv.sections.debug_strings.emit(gpa, .OpSourceExtension, .{ .extension = error_info.items, }); @@ -226,6 +226,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No } fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { + const gpa = spv.gpa; // TODO: Integrate with a hypothetical feature system const caps: []const spec.Capability = switch (target.os.tag) { .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .GenericPointer }, @@ -235,13 +236,15 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { }; for (caps) |cap| { - try spv.sections.capabilities.emit(spv.gpa, .OpCapability, .{ + try spv.sections.capabilities.emit(gpa, .OpCapability, .{ .capability = cap, }); } } fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { + const gpa = spv.gpa; + const addressing_model = switch (target.os.tag) { .opencl => switch (target.cpu.arch) { .spirv32 => spec.AddressingModel.Physical32, @@ -260,7 +263,7 @@ fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { }; // TODO: Put this in a proper section. - try spv.sections.extensions.emit(spv.gpa, .OpMemoryModel, .{ + try spv.sections.extensions.emit(gpa, .OpMemoryModel, .{ .addressing_model = addressing_model, .memory_model = memory_model, }); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 874cc2d9b3..7ec9506751 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -378,7 +378,6 @@ pub fn open( emit: Compilation.Emit, options: link.File.OpenOptions, ) !*Wasm { - if (build_options.only_c) unreachable; const gpa = comp.gpa; const target = comp.root_mod.resolved_target.result; assert(target.ofmt == .wasm); @@ -549,6 +548,7 @@ pub fn createEmpty( .comp = comp, .emit = emit, .gc_sections = options.gc_sections orelse (output_mode != .Obj), + .print_gc_sections = options.print_gc_sections, .stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB .allow_shlib_undefined = options.allow_shlib_undefined orelse false, .file = null, @@ -1893,7 +1893,12 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin return target_symbol_index; } -pub fn deleteDeclExport(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { +pub fn deleteDeclExport( + wasm: *Wasm, + decl_index: InternPool.DeclIndex, + name: InternPool.NullTerminatedString, +) void { + _ = name; if (wasm.llvm_object) |_| return; const atom_index = wasm.decls.get(decl_index) orelse return; const sym_index = wasm.getAtom(atom_index).sym_index; diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 610c534c88..f0c21b8c89 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -883,6 +883,8 @@ fn assertEnd(reader: anytype) !void { /// Parses an object file into atoms, for code and data sections pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32, wasm: *Wasm) !Atom.Index { + const comp = wasm.base.comp; + const gpa = comp.gpa; const symbol = &object.symtable[symbol_index]; const relocatable_data: RelocatableData = switch (symbol.tag) { .function => object.relocatable_data.get(.code).?[symbol.index - object.importedCountByKind(.function)], @@ -900,7 +902,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 }; const final_index = try wasm.getMatchingSegment(object_index, symbol_index); const atom_index = @as(Atom.Index, @intCast(wasm.managed_atoms.items.len)); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); + const atom = try wasm.managed_atoms.addOne(gpa); atom.* = Atom.empty; try wasm.appendAtomAtIndex(final_index, atom_index); @@ -910,7 +912,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 atom.alignment = relocatable_data.getAlignment(object); atom.code = std.ArrayListUnmanaged(u8).fromOwnedSlice(relocatable_data.data[0..relocatable_data.size]); atom.original_offset = relocatable_data.offset; - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom_index); + try wasm.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom_index); const segment: *Wasm.Segment = &wasm.segments.items[final_index]; if (relocatable_data.type == .data) { //code section and custom sections are 1-byte aligned segment.alignment = segment.alignment.max(atom.alignment); @@ -927,7 +929,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 .R_WASM_TABLE_INDEX_SLEB, .R_WASM_TABLE_INDEX_SLEB64, => { - try wasm.function_table.put(wasm.base.allocator, .{ + try wasm.function_table.put(gpa, .{ .file = object_index, .index = reloc.index, }, 0); @@ -938,7 +940,7 @@ pub fn parseSymbolIntoAtom(object: *Object, object_index: u16, symbol_index: u32 const sym = object.symtable[reloc.index]; if (sym.tag != .global) { try wasm.got_symbols.append( - wasm.base.allocator, + gpa, .{ .file = object_index, .index = reloc.index }, ); } diff --git a/src/main.zig b/src/main.zig index 26e1d79a7b..f412658a67 100644 --- a/src/main.zig +++ b/src/main.zig @@ -874,8 +874,8 @@ fn buildOutputType( var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; - var major_subsystem_version: ?u32 = null; - var minor_subsystem_version: ?u32 = null; + var major_subsystem_version: ?u16 = null; + var minor_subsystem_version: ?u16 = null; var enable_link_snapshots: bool = false; var debug_incremental: bool = false; var install_name: ?[]const u8 = null; @@ -2321,21 +2321,17 @@ fn buildOutputType( _ = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "--major-subsystem-version")) { const major = linker_args_it.nextOrFatal(); - major_subsystem_version = std.fmt.parseUnsigned( - u32, - major, - 10, - ) catch |err| { - fatal("unable to parse major subsystem version '{s}': {s}", .{ major, @errorName(err) }); + major_subsystem_version = std.fmt.parseUnsigned(u16, major, 10) catch |err| { + fatal("unable to parse major subsystem version '{s}': {s}", .{ + major, @errorName(err), + }); }; } else if (mem.eql(u8, arg, "--minor-subsystem-version")) { const minor = linker_args_it.nextOrFatal(); - minor_subsystem_version = std.fmt.parseUnsigned( - u32, - minor, - 10, - ) catch |err| { - fatal("unable to parse minor subsystem version '{s}': {s}", .{ minor, @errorName(err) }); + minor_subsystem_version = std.fmt.parseUnsigned(u16, minor, 10) catch |err| { + fatal("unable to parse minor subsystem version '{s}': {s}", .{ + minor, @errorName(err), + }); }; } else if (mem.eql(u8, arg, "-framework")) { try frameworks.put(arena, linker_args_it.nextOrFatal(), .{});