Commit f54471b54c
Changed files (21)
src/codegen/llvm.zig
@@ -854,9 +854,8 @@ pub const Object = struct {
/// want to iterate over it while adding entries to it.
pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
- pub fn create(arena: Allocator, options: link.File.OpenOptions) !*Object {
+ pub fn create(arena: Allocator, comp: *Compilation) !*Object {
if (build_options.only_c) unreachable;
- const comp = options.comp;
const gpa = comp.gpa;
const target = comp.root_mod.resolved_target.result;
const llvm_target_triple = try targetTriple(arena, target);
@@ -878,14 +877,7 @@ pub const Object = struct {
var target_data: if (build_options.have_llvm) *llvm.TargetData else void = undefined;
if (builder.useLibLlvm()) {
debug_info: {
- const debug_format = options.debug_format orelse b: {
- if (strip) break :b .strip;
- break :b switch (target.ofmt) {
- .coff => .code_view,
- else => .{ .dwarf = .@"32" },
- };
- };
- switch (debug_format) {
+ switch (comp.config.debug_format) {
.strip => break :debug_info,
.code_view => builder.llvm.module.?.addModuleCodeViewFlag(),
.dwarf => |f| builder.llvm.module.?.addModuleDebugInfoFlag(f == .@"64"),
@@ -961,8 +953,8 @@ pub const Object = struct {
opt_level,
reloc_mode,
code_model,
- options.function_sections orelse false,
- options.data_sections orelse false,
+ comp.function_sections,
+ comp.data_sections,
float_abi,
if (target_util.llvmMachineAbi(target)) |s| s.ptr else null,
);
src/Compilation/Config.zig
@@ -33,9 +33,16 @@ shared_memory: bool,
is_test: bool,
test_evented_io: bool,
entry: ?[]const u8,
+debug_format: DebugFormat,
pub const CFrontend = enum { clang, aro };
+pub const DebugFormat = union(enum) {
+ strip,
+ dwarf: std.dwarf.Format,
+ code_view,
+};
+
pub const Options = struct {
output_mode: std.builtin.OutputMode,
resolved_target: Module.ResolvedTarget,
@@ -43,6 +50,7 @@ pub const Options = struct {
have_zcu: bool,
emit_bin: bool,
root_optimize_mode: ?std.builtin.OptimizeMode = null,
+ root_strip: ?bool = null,
link_mode: ?std.builtin.LinkMode = null,
ensure_libc_on_non_freestanding: bool = false,
ensure_libcpp_on_non_freestanding: bool = false,
@@ -51,6 +59,7 @@ pub const Options = struct {
any_unwind_tables: bool = false,
any_dyn_libs: bool = false,
any_c_source_files: bool = false,
+ any_non_stripped: bool = false,
emit_llvm_ir: bool = false,
emit_llvm_bc: bool = false,
link_libc: ?bool = null,
@@ -74,6 +83,7 @@ pub const Options = struct {
export_memory: ?bool = null,
shared_memory: ?bool = null,
test_evented_io: bool = false,
+ debug_format: ?Config.DebugFormat = null,
};
pub fn resolve(options: Options) !Config {
@@ -365,6 +375,26 @@ pub fn resolve(options: Options) !Config {
break :b false;
};
+ const root_strip = b: {
+ if (options.root_strip) |x| break :b x;
+ if (root_optimize_mode == .ReleaseSmall) break :b true;
+ if (!target_util.hasDebugInfo(target)) break :b true;
+ break :b false;
+ };
+
+ const debug_format: DebugFormat = b: {
+ if (root_strip and !options.any_non_stripped) break :b .strip;
+ break :b switch (target.ofmt) {
+ .elf, .macho, .wasm => .{ .dwarf = .@"32" },
+ .coff => .code_view,
+ .c => switch (target.os.tag) {
+ .windows, .uefi => .code_view,
+ else => .{ .dwarf = .@"32" },
+ },
+ .spirv, .nvptx, .dxcontainer, .hex, .raw, .plan9 => .strip,
+ };
+ };
+
return .{
.output_mode = options.output_mode,
.have_zcu = options.have_zcu,
@@ -388,6 +418,7 @@ pub fn resolve(options: Options) !Config {
.use_lld = use_lld,
.entry = entry,
.wasi_exec_model = wasi_exec_model,
+ .debug_format = debug_format,
};
}
src/link/Coff/lld.zig
@@ -171,7 +171,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
try argv.append("-ERRORLIMIT:0");
try argv.append("-NOLOGO");
- if (self.base.debug_format != .strip) {
+ if (comp.config.debug_format != .strip) {
try argv.append("-DEBUG");
const out_ext = std.fs.path.extension(full_out_path);
src/link/Elf/Object.zig
@@ -293,13 +293,14 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem
}
fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
+ const comp = elf_file.base.comp;
const shdr = self.shdrs.items[index];
const name = self.getString(shdr.sh_name);
const ignore = blk: {
if (mem.startsWith(u8, name, ".note")) break :blk true;
if (mem.startsWith(u8, name, ".comment")) break :blk true;
if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
- if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
+ if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
mem.startsWith(u8, name, ".debug")) break :blk true;
break :blk false;
};
src/link/Elf/ZigObject.zig
@@ -76,7 +76,8 @@ pub const symbol_mask: u32 = 0x7fffffff;
pub const SHN_ATOM: u16 = 0x100;
pub fn init(self: *ZigObject, elf_file: *Elf) !void {
- const gpa = elf_file.base.comp.gpa;
+ const comp = elf_file.base.comp;
+ const gpa = comp.gpa;
try self.atoms.append(gpa, 0); // null input section
try self.relocs.append(gpa, .{}); // null relocs section
@@ -96,8 +97,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
esym.st_shndx = elf.SHN_ABS;
symbol_ptr.esym_index = esym_index;
- if (elf_file.base.debug_format != .strip) {
- self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
+ switch (comp.config.debug_format) {
+ .strip => {},
+ .dwarf => |v| {
+ assert(v == .@"32");
+ self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
+ },
+ .code_view => unreachable,
}
}
src/link/C.zig
@@ -92,21 +92,24 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
};
}
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
- const target = options.comp.root_mod.resolved_target.result;
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*C {
+ const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .c);
- const optimize_mode = options.comp.root_mod.optimize_mode;
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
- const output_mode = options.comp.config.output_mode;
- const link_mode = options.comp.config.link_mode;
+ const optimize_mode = comp.root_mod.optimize_mode;
+ const use_lld = build_options.have_llvm and comp.config.use_lld;
+ const use_llvm = comp.config.use_llvm;
+ const output_mode = comp.config.output_mode;
+ const link_mode = comp.config.link_mode;
// These are caught by `Compilation.Config.resolve`.
assert(!use_lld);
assert(!use_llvm);
- const emit = options.emit;
-
const file = try emit.directory.handle.createFile(emit.sub_path, .{
// Truncation is done on `flush`.
.truncate = false,
@@ -119,7 +122,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
c_file.* = .{
.base = .{
.tag = .c,
- .comp = options.comp,
+ .comp = comp,
.emit = emit,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
.stack_size = options.stack_size orelse 16777216,
@@ -129,9 +132,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
};
src/link/Coff.zig
@@ -234,44 +234,49 @@ const ideal_factor = 3;
const minimum_text_block_size = 64;
pub const min_text_capacity = padToIdeal(minimum_text_block_size);
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Coff {
if (build_options.only_c) unreachable;
- const target = options.comp.root_mod.resolved_target.result;
+ const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .coff);
- const self = try createEmpty(arena, options);
+ const self = try createEmpty(arena, comp, emit, options);
errdefer self.base.destroy();
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
+ const use_lld = build_options.have_llvm and comp.config.use_lld;
+ const use_llvm = comp.config.use_llvm;
if (use_lld and use_llvm) {
// LLVM emits the object file; LLD links it into the final product.
return self;
}
- const sub_path = if (!use_lld) options.emit.sub_path else p: {
+ const sub_path = if (!use_lld) emit.sub_path else p: {
// Open a temporary object file, not the final output file because we
// want to link with LLD.
const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
- options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
+ emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
});
self.base.intermediary_basename = o_file_path;
break :p o_file_path;
};
- self.base.file = try options.emit.directory.handle.createFile(sub_path, .{
+ self.base.file = try emit.directory.handle.createFile(sub_path, .{
.truncate = false,
.read = true,
.mode = link.File.determineMode(
use_lld,
- options.comp.config.output_mode,
- options.comp.config.link_mode,
+ comp.config.output_mode,
+ comp.config.link_mode,
),
});
assert(self.llvm_object == null);
- const gpa = self.base.comp.gpa;
+ const gpa = comp.gpa;
try self.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
self.strtab.buffer.appendNTimesAssumeCapacity(0, @sizeOf(u32));
@@ -362,8 +367,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
return self;
}
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
- const comp = options.comp;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Coff {
const target = comp.root_mod.resolved_target.result;
const optimize_mode = comp.root_mod.optimize_mode;
const output_mode = comp.config.output_mode;
@@ -380,7 +389,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
.base = .{
.tag = .coff,
.comp = comp,
- .emit = options.emit,
+ .emit = emit,
.stack_size = options.stack_size orelse 16777216,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -389,9 +398,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .code_view,
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
.ptr_width = ptr_width,
.page_size = page_size,
@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
const use_llvm = comp.config.use_llvm;
if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, options);
+ self.llvm_object = try LlvmObject.create(arena, comp);
}
return self;
}
src/link/Elf.zig
@@ -228,18 +228,23 @@ pub const HashStyle = enum { sysv, gnu, both };
pub const CompressDebugSections = enum { none, zlib, zstd };
pub const SortSection = enum { name, alignment };
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Elf {
if (build_options.only_c) unreachable;
- const target = options.comp.root_mod.resolved_target.result;
+ const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .elf);
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
- const opt_zcu = options.comp.module;
- const output_mode = options.comp.config.output_mode;
- const link_mode = options.comp.config.link_mode;
+ const use_lld = build_options.have_llvm and comp.config.use_lld;
+ const use_llvm = comp.config.use_llvm;
+ const opt_zcu = comp.module;
+ const output_mode = comp.config.output_mode;
+ const link_mode = comp.config.link_mode;
- const self = try createEmpty(arena, options);
+ const self = try createEmpty(arena, comp, emit, options);
errdefer self.base.destroy();
if (use_lld and use_llvm) {
@@ -250,23 +255,23 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
const is_obj = output_mode == .Obj;
const is_obj_or_ar = is_obj or (output_mode == .Lib and link_mode == .Static);
- const sub_path = if (!use_lld) options.emit.sub_path else p: {
+ const sub_path = if (!use_lld) emit.sub_path else p: {
// Open a temporary object file, not the final output file because we
// want to link with LLD.
const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
- options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
+ emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
});
self.base.intermediary_basename = o_file_path;
break :p o_file_path;
};
- self.base.file = try options.emit.directory.handle.createFile(sub_path, .{
+ self.base.file = try emit.directory.handle.createFile(sub_path, .{
.truncate = false,
.read = true,
.mode = link.File.determineMode(use_lld, output_mode, link_mode),
});
- const gpa = options.comp.gpa;
+ const gpa = comp.gpa;
// Index 0 is always a null symbol.
try self.symbols.append(gpa, .{});
@@ -343,8 +348,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
return self;
}
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
- const comp = options.comp;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Elf {
const use_llvm = comp.config.use_llvm;
const optimize_mode = comp.root_mod.optimize_mode;
const target = comp.root_mod.resolved_target.result;
@@ -373,7 +382,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
.base = .{
.tag = .elf,
.comp = comp,
- .emit = options.emit,
+ .emit = emit,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os,
@@ -382,9 +391,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
.ptr_width = ptr_width,
.page_size = page_size,
@@ -423,7 +429,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
.version_script = options.version_script,
};
if (use_llvm and comp.config.have_zcu) {
- self.llvm_object = try LlvmObject.create(arena, options);
+ self.llvm_object = try LlvmObject.create(arena, comp);
}
return self;
@@ -1753,7 +1759,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
try argv.append("-pie");
}
- if (self.base.debug_format == .strip) {
+ if (comp.config.debug_format == .strip) {
try argv.append("-s");
}
@@ -2640,7 +2646,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
try argv.append("--export-dynamic");
}
- if (self.base.debug_format == .strip) {
+ if (comp.config.debug_format == .strip) {
try argv.append("-s");
}
src/link/MachO.zig
@@ -182,18 +182,21 @@ pub const SdkLayout = enum {
vendored,
};
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*MachO {
if (build_options.only_c) unreachable;
- const comp = options.comp;
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;
assert(target.ofmt == .macho);
const gpa = comp.gpa;
- const emit = options.emit;
const mode: Mode = mode: {
- if (use_llvm or comp.module == null or comp.cache_mode == .whole)
+ if (use_llvm or comp.module == null or comp.cache_use == .whole)
break :mode .zld;
break :mode .incremental;
};
@@ -201,7 +204,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
if (comp.module == null) {
// No point in opening a file, we would not write anything to it.
// Initialize with empty.
- return createEmpty(arena, options);
+ return createEmpty(arena, comp, emit, options);
}
// Open a temporary object file, not the final output file because we
// want to link with LLD.
@@ -210,7 +213,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
});
} else emit.sub_path;
- const self = try createEmpty(arena, options);
+ const self = try createEmpty(arena, comp, emit, options);
errdefer self.base.destroy();
if (mode == .zld) {
@@ -232,7 +235,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
});
self.base.file = file;
- if (self.base.debug_format != .strip and comp.module != null) {
+ if (comp.config.debug_format != .strip and comp.module != null) {
// Create dSYM bundle.
log.debug("creating {s}.dSYM bundle", .{sub_path});
@@ -279,8 +282,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
return self;
}
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
- const comp = options.comp;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*MachO {
const optimize_mode = comp.root_mod.optimize_mode;
const use_llvm = comp.config.use_llvm;
@@ -289,7 +296,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
.base = .{
.tag = .macho,
.comp = comp,
- .emit = options.emit,
+ .emit = emit,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -298,11 +305,8 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
- .mode = if (use_llvm or comp.module == null or comp.cache_mode == .whole)
+ .mode = if (use_llvm or comp.module == null or comp.cache_use == .whole)
.zld
else
.incremental,
@@ -317,7 +321,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*MachO {
};
if (use_llvm and comp.module != null) {
- self.llvm_object = try LlvmObject.create(arena, options);
+ self.llvm_object = try LlvmObject.create(arena, comp);
}
log.debug("selected linker mode '{s}'", .{@tagName(self.mode)});
@@ -4313,7 +4317,8 @@ fn addLocalToSymtab(self: *MachO, sym_loc: SymbolWithLoc, locals: *std.ArrayList
}
fn writeSymtab(self: *MachO) !SymtabCtx {
- const gpa = self.base.comp.gpa;
+ const comp = self.base.comp;
+ const gpa = comp.gpa;
var locals = std.ArrayList(macho.nlist_64).init(gpa);
defer locals.deinit();
@@ -4368,7 +4373,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
// We generate stabs last in order to ensure that the strtab always has debug info
// strings trailing
- if (self.base.debug_format != .strip) {
+ if (comp.config.debug_format != .strip) {
for (self.objects.items) |object| {
assert(self.d_sym == null); // TODO
try self.generateSymbolStabs(object, &locals);
src/link/NvPtx.zig
@@ -25,12 +25,17 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
base: link.File,
llvm_object: *LlvmObject,
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*NvPtx {
if (build_options.only_c) unreachable;
- const target = options.comp.root_mod.resolved_target.result;
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
+ 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;
assert(use_llvm); // Caught by Compilation.Config.resolve.
assert(!use_lld); // Caught by Compilation.Config.resolve.
@@ -42,13 +47,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
else => return error.PtxArchNotSupported,
}
- const llvm_object = try LlvmObject.create(arena, options);
+ const llvm_object = try LlvmObject.create(arena, comp);
const nvptx = try arena.create(NvPtx);
nvptx.* = .{
.base = .{
.tag = .nvptx,
- .comp = options.comp,
- .emit = options.emit,
+ .comp = comp,
+ .emit = emit,
.gc_sections = options.gc_sections orelse false,
.stack_size = options.stack_size orelse 0,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -57,9 +62,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
.llvm_object = llvm_object,
};
@@ -67,10 +69,15 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
return nvptx;
}
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
- const target = options.comp.root_mod.resolved_target.result;
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*NvPtx {
+ const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .nvptx);
- return createEmpty(arena, options);
+ return createEmpty(arena, comp, emit, options);
}
pub fn deinit(self: *NvPtx) void {
src/link/Plan9.zig
@@ -294,8 +294,12 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
};
}
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
- const comp = options.comp;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Plan9 {
const target = comp.root_mod.resolved_target.result;
const gpa = comp.gpa;
const optimize_mode = comp.root_mod.optimize_mode;
@@ -313,7 +317,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
.base = .{
.tag = .plan9,
.comp = comp,
- .emit = options.emit,
+ .emit = emit,
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
.stack_size = options.stack_size orelse 16777216,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -322,9 +326,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
.sixtyfour_bit = sixtyfour_bit,
.bases = undefined,
@@ -1308,26 +1309,31 @@ pub fn deinit(self: *Plan9) void {
}
}
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Plan9 {
if (build_options.only_c) unreachable;
- const target = options.comp.root_mod.resolved_target.result;
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
+ 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;
assert(!use_llvm); // Caught by Compilation.Config.resolve.
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.ofmt == .plan9);
- const self = try createEmpty(arena, options);
+ const self = try createEmpty(arena, comp, emit, options);
errdefer self.base.destroy();
- const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
+ const file = try emit.directory.handle.createFile(emit.sub_path, .{
.read = true,
.mode = link.File.determineMode(
use_lld,
- options.comp.config.output_mode,
- options.comp.config.link_mode,
+ comp.config.output_mode,
+ comp.config.link_mode,
),
});
errdefer file.close();
@@ -1335,7 +1341,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
self.bases = defaultBaseAddrs(target.cpu.arch);
- const gpa = options.comp.gpa;
+ const gpa = comp.gpa;
try self.syms.appendSlice(gpa, &.{
// we include the global offset table to make it easier for debugging
src/link/SpirV.zig
@@ -49,16 +49,21 @@ object: codegen.Object,
pub const base_tag: link.File.Tag = .spirv;
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
- const gpa = options.comp.gpa;
- const target = options.comp.root_mod.resolved_target.result;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*SpirV {
+ const gpa = comp.gpa;
+ const target = comp.root_mod.resolved_target.result;
const self = try arena.create(SpirV);
self.* = .{
.base = .{
.tag = .spirv,
- .comp = options.comp,
- .emit = options.emit,
+ .comp = comp,
+ .emit = emit,
.gc_sections = options.gc_sections orelse false,
.stack_size = options.stack_size orelse 0,
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -67,9 +72,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
},
.object = codegen.Object.init(gpa),
};
@@ -90,22 +92,27 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
return self;
}
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*SpirV {
if (build_options.only_c) unreachable;
- const target = options.comp.root_mod.resolved_target.result;
- const use_lld = build_options.have_llvm and options.comp.config.use_lld;
- const use_llvm = options.comp.config.use_llvm;
+ 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;
assert(!use_llvm); // Caught by Compilation.Config.resolve.
assert(!use_lld); // Caught by Compilation.Config.resolve.
assert(target.ofmt == .spirv); // Caught by Compilation.Config.resolve.
- const spirv = try createEmpty(arena, options);
+ const spirv = try createEmpty(arena, comp, emit, options);
errdefer spirv.base.destroy();
// TODO: read the file and keep valid parts instead of truncating
- const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
+ const file = try emit.directory.handle.createFile(emit.sub_path, .{
.truncate = true,
.read = true,
});
src/link/Wasm.zig
@@ -373,9 +373,13 @@ pub const StringTable = struct {
}
};
-pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
+pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Wasm {
if (build_options.only_c) unreachable;
- const comp = options.comp;
const gpa = comp.gpa;
const target = comp.root_mod.resolved_target.result;
assert(target.ofmt == .wasm);
@@ -385,7 +389,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
const output_mode = comp.config.output_mode;
const shared_memory = comp.config.shared_memory;
- const wasm = try createEmpty(arena, options);
+ const wasm = try createEmpty(arena, comp, emit, options);
errdefer wasm.base.destroy();
if (use_lld and use_llvm) {
@@ -393,18 +397,18 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
return wasm;
}
- const sub_path = if (!use_lld) options.emit.sub_path else p: {
+ const sub_path = if (!use_lld) emit.sub_path else p: {
// Open a temporary object file, not the final output file because we
// want to link with LLD.
const o_file_path = try std.fmt.allocPrint(arena, "{s}{s}", .{
- options.emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
+ emit.sub_path, target.ofmt.fileExt(target.cpu.arch),
});
wasm.base.intermediary_basename = o_file_path;
break :p o_file_path;
};
// TODO: read the file and keep valid parts instead of truncating
- const file = try options.emit.directory.handle.createFile(sub_path, .{
+ const file = try emit.directory.handle.createFile(sub_path, .{
.truncate = true,
.read = true,
.mode = if (fs.has_executable_bit)
@@ -530,8 +534,12 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
return wasm;
}
-pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
- const comp = options.comp;
+pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ emit: Compilation.Emit,
+ options: link.File.OpenOptions,
+) !*Wasm {
const use_llvm = comp.config.use_llvm;
const output_mode = comp.config.output_mode;
@@ -540,7 +548,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
.base = .{
.tag = .wasm,
.comp = comp,
- .emit = options.emit,
+ .emit = emit,
.gc_sections = options.gc_sections orelse (output_mode != .Obj),
.stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
@@ -549,9 +557,6 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
.build_id = options.build_id,
.rpath_list = options.rpath_list,
.force_undefined_symbols = options.force_undefined_symbols,
- .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
},
.name = undefined,
.import_table = options.import_table,
@@ -566,7 +571,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
};
if (use_llvm) {
- wasm.llvm_object = try LlvmObject.create(arena, options);
+ wasm.llvm_object = try LlvmObject.create(arena, comp);
}
return wasm;
}
@@ -4205,11 +4210,11 @@ fn writeToFile(
if (data_section_index) |data_index| {
try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
}
- } else if (wasm.base.debug_format != .strip) {
+ } else if (comp.config.debug_format != .strip) {
try wasm.emitNameSection(&binary_bytes, arena);
}
- if (wasm.base.debug_format != .strip) {
+ if (comp.config.debug_format != .strip) {
// The build id must be computed on the main sections only,
// so we have to do it now, before the debug sections.
switch (wasm.base.build_id) {
@@ -4748,7 +4753,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
try argv.append("--no-gc-sections");
}
- if (wasm.base.debug_format == .strip) {
+ if (comp.config.debug_format == .strip) {
try argv.append("-s");
}
@@ -5276,7 +5281,9 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s
fn markReferences(wasm: *Wasm) !void {
const tracy = trace(@src());
defer tracy.end();
+
const do_garbage_collect = wasm.base.gc_sections;
+ const comp = wasm.base.comp;
for (wasm.resolved_symbols.keys()) |sym_loc| {
const sym = sym_loc.getSymbol(wasm);
@@ -5287,7 +5294,7 @@ fn markReferences(wasm: *Wasm) !void {
// Debug sections may require to be parsed and marked when it contains
// relocations to alive symbols.
- if (sym.tag == .section and wasm.base.debug_format != .strip) {
+ if (sym.tag == .section and comp.config.debug_format != .strip) {
const file = sym_loc.file orelse continue; // Incremental debug info is done independently
const object = &wasm.objects.items[file];
const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);
src/Package/Module.zig
@@ -33,11 +33,16 @@ cc_argv: []const []const u8,
/// (SPIR-V) whether to generate a structured control flow graph or not
structured_cfg: bool,
-/// The contents of `@import("builtin")` for this module.
-generated_builtin_source: []const u8,
+/// If the module is an `@import("builtin")` module, this is the `File` that
+/// is preallocated for it. Otherwise this field is null.
+builtin_file: ?*File,
pub const Deps = std.StringArrayHashMapUnmanaged(*Module);
+pub fn isBuiltin(m: Module) bool {
+ return m.file != null;
+}
+
pub const Tree = struct {
/// Each `Package` exposes a `Module` with build.zig as its root source file.
build_module_table: std.AutoArrayHashMapUnmanaged(MultiHashHexDigest, *Module),
@@ -329,6 +334,8 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
.wasi_exec_model = options.global.wasi_exec_model,
}, arena);
+ const new_file = try arena.create(File);
+
const digest = Cache.HashHelper.oneShot(generated_builtin_source);
const builtin_sub_path = try arena.dupe(u8, "b" ++ std.fs.path.sep_str ++ digest);
const new = try arena.create(Module);
@@ -359,12 +366,25 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
.stack_protector = stack_protector,
.code_model = code_model,
.red_zone = red_zone,
- .generated_builtin_source = generated_builtin_source,
.sanitize_c = sanitize_c,
.sanitize_thread = sanitize_thread,
.unwind_tables = unwind_tables,
.cc_argv = &.{},
.structured_cfg = structured_cfg,
+ .builtin_file = new_file,
+ };
+ new_file.* = .{
+ .sub_file_path = "builtin.zig",
+ .source = generated_builtin_source,
+ .source_loaded = true,
+ .tree_loaded = false,
+ .zir_loaded = false,
+ .stat = undefined,
+ .tree = undefined,
+ .zir = undefined,
+ .status = .never_loaded,
+ .mod = new,
+ .root_decl = .none,
};
break :b new;
};
@@ -391,12 +411,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
.stack_protector = stack_protector,
.code_model = code_model,
.red_zone = red_zone,
- .generated_builtin_source = builtin_mod.generated_builtin_source,
.sanitize_c = sanitize_c,
.sanitize_thread = sanitize_thread,
.unwind_tables = unwind_tables,
.cc_argv = options.cc_argv,
.structured_cfg = structured_cfg,
+ .builtin_file = null,
};
try mod.deps.ensureUnusedCapacity(arena, 1);
@@ -437,8 +457,8 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
.sanitize_thread = undefined,
.unwind_tables = undefined,
.cc_argv = undefined,
- .generated_builtin_source = undefined,
.structured_cfg = undefined,
+ .builtin_file = null,
};
return mod;
}
@@ -457,3 +477,4 @@ const Cache = std.Build.Cache;
const Builtin = @import("../Builtin.zig");
const assert = std.debug.assert;
const Compilation = @import("../Compilation.zig");
+const File = @import("../Module.zig").File;
src/Builtin.zig
@@ -20,8 +20,11 @@ wasi_exec_model: std.builtin.WasiExecModel,
pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
var buffer = std.ArrayList(u8).init(allocator);
- defer buffer.deinit();
+ try append(opts, &buffer);
+ return buffer.toOwnedSliceSentinel(0);
+}
+pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
const target = opts.target;
const generic_arch_name = target.cpu.arch.genericName();
const zig_backend = opts.zig_backend;
@@ -231,10 +234,65 @@ pub fn generate(opts: @This(), allocator: Allocator) Allocator.Error![:0]u8 {
);
}
}
+}
- return buffer.toOwnedSliceSentinel(0);
+pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {
+ assert(file.source_loaded == true);
+
+ if (mod.root.statFile(mod.root_src_path)) |stat| {
+ if (stat.size != file.source.len) {
+ std.log.warn(
+ "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++
+ "Overwriting with correct file contents now",
+ .{ mod.root, mod.root_src_path, file.source.len, stat.size },
+ );
+
+ try writeFile(file, mod);
+ } else {
+ file.stat = .{
+ .size = stat.size,
+ .inode = stat.inode,
+ .mtime = stat.mtime,
+ };
+ }
+ } else |err| switch (err) {
+ error.BadPathName => unreachable, // it's always "builtin.zig"
+ error.NameTooLong => unreachable, // it's always "builtin.zig"
+ error.PipeBusy => unreachable, // it's not a pipe
+ error.WouldBlock => unreachable, // not asking for non-blocking I/O
+
+ error.FileNotFound => try writeFile(file, mod),
+
+ else => |e| return e,
+ }
+
+ file.tree = try std.zig.Ast.parse(comp.gpa, file.source, .zig);
+ file.tree_loaded = true;
+ assert(file.tree.errors.len == 0); // builtin.zig must parse
+
+ file.zir = try AstGen.generate(comp.gpa, file.tree);
+ file.zir_loaded = true;
+ file.status = .success_zir;
+}
+
+fn writeFile(file: *File, mod: *Module) !void {
+ var af = try mod.root.atomicFile(mod.root_src_path, .{});
+ defer af.deinit();
+ try af.file.writeAll(file.source);
+ try af.finish();
+
+ file.stat = .{
+ .size = file.source.len,
+ .inode = 0, // dummy value
+ .mtime = 0, // dummy value
+ };
}
const std = @import("std");
const Allocator = std.mem.Allocator;
const build_options = @import("build_options");
+const Module = @import("Package/Module.zig");
+const assert = std.debug.assert;
+const AstGen = @import("AstGen.zig");
+const File = @import("Module.zig").File;
+const Compilation = @import("Compilation.zig");
src/Compilation.zig
@@ -37,6 +37,7 @@ const Zir = @import("Zir.zig");
const Autodoc = @import("Autodoc.zig");
const Color = @import("main.zig").Color;
const resinator = @import("resinator.zig");
+const Builtin = @import("Builtin.zig");
pub const Config = @import("Compilation/Config.zig");
@@ -59,7 +60,10 @@ root_mod: *Package.Module,
/// User-specified settings that have all the defaults resolved into concrete values.
config: Config,
-/// This is `null` when `-fno-emit-bin` is used.
+/// The main output file.
+/// In whole cache mode, this is null except for during the body of the update
+/// function. In incremental cache mode, this is a long-lived object.
+/// In both cases, this is `null` when `-fno-emit-bin` is used.
bin_file: ?*link.File,
/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
@@ -80,6 +84,8 @@ version: ?std.SemanticVersion,
libc_installation: ?*const LibCInstallation,
skip_linker_dependencies: bool,
no_builtin: bool,
+function_sections: bool,
+data_sections: bool,
c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
@@ -120,7 +126,6 @@ failed_win32_resources: if (build_options.only_core_functionality) void else std
/// Miscellaneous things that can fail.
misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
-keep_source_files_loaded: bool,
/// When this is `true` it means invoking clang as a sub-process is expected to inherit
/// stdin, stdout, stderr, and if it returns non success, to forward the exit code.
/// Otherwise we attempt to parse the error messages and expose them via the Compilation API.
@@ -144,6 +149,7 @@ debug_compiler_runtime_libs: bool,
debug_compile_errors: bool,
job_queued_compiler_rt_lib: bool = false,
job_queued_compiler_rt_obj: bool = false,
+job_queued_update_builtin_zig: bool,
alloc_failure_occurred: bool = false,
formatted_panics: bool = false,
last_update_was_cache_hit: bool = false,
@@ -814,13 +820,13 @@ pub const cache_helpers = struct {
addEmitLoc(hh, optional_emit_loc orelse return);
}
- pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?link.File.DebugFormat) void {
+ pub fn addOptionalDebugFormat(hh: *Cache.HashHelper, x: ?Config.DebugFormat) void {
hh.add(x != null);
addDebugFormat(hh, x orelse return);
}
- pub fn addDebugFormat(hh: *Cache.HashHelper, x: link.File.DebugFormat) void {
- const tag: @typeInfo(link.File.DebugFormat).Union.tag_type.? = x;
+ pub fn addDebugFormat(hh: *Cache.HashHelper, x: Config.DebugFormat) void {
+ const tag: @typeInfo(Config.DebugFormat).Union.tag_type.? = x;
hh.add(tag);
switch (x) {
.strip, .code_view => {},
@@ -860,11 +866,11 @@ pub const SystemLib = link.SystemLib;
pub const CacheMode = enum { incremental, whole };
-pub const CacheUse = union(CacheMode) {
+const CacheUse = union(CacheMode) {
incremental: *Incremental,
whole: *Whole,
- pub const Whole = struct {
+ const Whole = struct {
/// This is a pointer to a local variable inside `update()`.
cache_manifest: ?*Cache.Manifest = null,
cache_manifest_mutex: std.Thread.Mutex = .{},
@@ -873,12 +879,14 @@ pub const CacheUse = union(CacheMode) {
/// of exactly the correct size for "o/[digest]/[basename]".
/// The basename is of the outputted binary file in case we don't know the directory yet.
bin_sub_path: ?[]u8,
- /// Same as `whole_bin_sub_path` but for implibs.
+ /// Same as `bin_sub_path` but for implibs.
implib_sub_path: ?[]u8,
docs_sub_path: ?[]u8,
+ lf_open_opts: link.File.OpenOptions,
+ tmp_artifact_directory: ?Cache.Directory,
};
- pub const Incremental = struct {
+ const Incremental = struct {
/// Where build artifacts and incremental compilation metadata serialization go.
artifact_directory: Compilation.Directory,
};
@@ -937,7 +945,6 @@ pub const InitOptions = struct {
/// this flag would be set to disable this machinery to avoid false positives.
disable_lld_caching: bool = false,
cache_mode: CacheMode = .incremental,
- keep_source_files_loaded: bool = false,
lib_dirs: []const []const u8 = &[0][]const u8{},
rpath_list: []const []const u8 = &[0][]const u8{},
symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
@@ -1040,7 +1047,6 @@ pub const InitOptions = struct {
test_name_prefix: ?[]const u8 = null,
test_runner_path: ?[]const u8 = null,
subsystem: ?std.Target.SubSystem = null,
- debug_format: ?link.File.DebugFormat = null,
/// (Zig compiler development) Enable dumping linker's state as JSON.
enable_link_snapshots: bool = false,
/// (Darwin) Install name of the dylib
@@ -1327,7 +1333,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
cache.hash.add(options.config.link_libcpp);
cache.hash.add(options.config.link_libunwind);
cache.hash.add(output_mode);
- cache_helpers.addOptionalDebugFormat(&cache.hash, options.debug_format);
+ cache_helpers.addDebugFormat(&cache.hash, comp.config.debug_format);
cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
@@ -1380,7 +1386,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
};
errdefer if (opt_zcu) |zcu| zcu.deinit();
- const system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init(
+ var system_libs = try std.StringArrayHashMapUnmanaged(SystemLib).init(
gpa,
options.system_lib_names,
options.system_lib_infos,
@@ -1409,7 +1415,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),
.astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa),
.embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
- .keep_source_files_loaded = options.keep_source_files_loaded,
.c_source_files = options.c_source_files,
.rc_source_files = options.rc_source_files,
.cache_parent = cache,
@@ -1451,10 +1456,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
.skip_linker_dependencies = options.skip_linker_dependencies,
.no_builtin = options.no_builtin,
+ .job_queued_update_builtin_zig = have_zcu,
+ .function_sections = options.function_sections,
+ .data_sections = options.data_sections,
};
const lf_open_opts: link.File.OpenOptions = .{
- .comp = comp,
.linker_script = options.linker_script,
.z_nodelete = options.linker_z_nodelete,
.z_notext = options.linker_z_notext,
@@ -1471,8 +1478,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.lib_dirs = options.lib_dirs,
.rpath_list = options.rpath_list,
.symbol_wrap_set = options.symbol_wrap_set,
- .function_sections = options.function_sections,
- .data_sections = options.data_sections,
.allow_shlib_undefined = options.linker_allow_shlib_undefined,
.bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
.compress_debug_sections = options.linker_compress_debug_sections orelse .none,
@@ -1507,7 +1512,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.build_id = build_id,
.disable_lld_caching = options.disable_lld_caching or cache_mode == .whole,
.subsystem = options.subsystem,
- .debug_format = options.debug_format,
.hash_style = options.hash_style,
.enable_link_snapshots = options.enable_link_snapshots,
.install_name = options.install_name,
@@ -1572,17 +1576,17 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.directory = emit_bin.directory orelse artifact_directory,
.sub_path = emit_bin.basename,
};
- comp.bin_file = try link.File.open(arena, emit, lf_open_opts);
+ comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
}
- if (options.implib_emit) |emit_implib| {
+ if (options.emit_implib) |emit_implib| {
comp.implib_emit = .{
.directory = emit_implib.directory orelse artifact_directory,
.sub_path = emit_implib.basename,
};
}
- if (options.docs_emit) |emit_docs| {
+ if (options.emit_docs) |emit_docs| {
comp.docs_emit = .{
.directory = emit_docs.directory orelse artifact_directory,
.sub_path = emit_docs.basename,
@@ -1610,6 +1614,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.bin_sub_path = try prepareWholeEmitSubPath(arena, options.emit_bin),
.implib_sub_path = try prepareWholeEmitSubPath(arena, options.emit_implib),
.docs_sub_path = try prepareWholeEmitSubPath(arena, options.emit_docs),
+ .tmp_artifact_directory = null,
};
comp.cache_use = .{ .whole = whole };
},
@@ -1662,7 +1667,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
}
}
- const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null;
+ const have_bin_emit = switch (comp.cache_use) {
+ .whole => |whole| whole.bin_sub_path != null,
+ .incremental => comp.bin_file != null,
+ };
if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {
if (target.isDarwin()) {
@@ -1814,8 +1822,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
pub fn destroy(self: *Compilation) void {
if (self.bin_file) |lf| lf.destroy();
if (self.module) |zcu| zcu.deinit();
+ switch (self.cache_use) {
+ .incremental => |incremental| {
+ incremental.artifact_directory.handle.close();
+ },
+ .whole => {},
+ }
- const gpa = self.gpa;
self.work_queue.deinit();
self.anon_work_queue.deinit();
self.c_object_work_queue.deinit();
@@ -1825,6 +1838,9 @@ pub fn destroy(self: *Compilation) void {
self.astgen_work_queue.deinit();
self.embed_file_work_queue.deinit();
+ const gpa = self.gpa;
+ self.system_libs.deinit(gpa);
+
{
var it = self.crt_files.iterator();
while (it.next()) |entry| {
@@ -1914,7 +1930,7 @@ pub fn hotCodeSwap(comp: *Compilation, prog_node: *std.Progress.Node, pid: std.C
}
fn cleanupAfterUpdate(comp: *Compilation) void {
- switch (comp) {
+ switch (comp.cache_use) {
.incremental => return,
.whole => |whole| {
if (whole.cache_manifest) |man| {
@@ -1971,7 +1987,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
const digest = man.final();
- comp.wholeCacheModeSetBinFilePath(&digest);
+ comp.wholeCacheModeSetBinFilePath(whole, &digest);
assert(comp.bin_file.lock == null);
comp.bin_file.lock = man.toOwnedLock();
@@ -2001,21 +2017,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
// Now that the directory is known, it is time to create the Emit
// objects and call link.File.open.
- if (comp.whole_implib_sub_path) |sub_path| {
+ if (whole.implib_sub_path) |sub_path| {
comp.implib_emit = .{
.directory = tmp_artifact_directory,
.sub_path = std.fs.path.basename(sub_path),
};
}
- if (comp.whole_docs_sub_path) |sub_path| {
+ if (whole.docs_sub_path) |sub_path| {
comp.docs_emit = .{
.directory = tmp_artifact_directory,
.sub_path = std.fs.path.basename(sub_path),
};
}
- if (comp.whole_bin_sub_path) |sub_path| {
+ if (whole.bin_sub_path) |sub_path| {
const emit: Emit = .{
.directory = tmp_artifact_directory,
.sub_path = std.fs.path.basename(sub_path),
@@ -2024,7 +2040,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
// but in practice it won't leak much and usually whole cache mode
// will be combined with exactly one call to update().
const arena = comp.arena.allocator();
- comp.bin_file = try link.File.open(arena, emit, whole.lf_open_opts);
+ comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
}
},
.incremental => {},
@@ -2158,7 +2174,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
const o_sub_path = "o" ++ s ++ digest;
try renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path);
- comp.wholeCacheModeSetBinFilePath(&digest);
+ comp.wholeCacheModeSetBinFilePath(whole, &digest);
// Failure here only means an unnecessary cache miss.
man.writeManifest() catch |err| {
@@ -2170,19 +2186,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
},
.incremental => {},
}
-
- // Unload all source files to save memory.
- // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
- // to it, and (2) generic instantiations, comptime calls, inline calls will need
- // to reference the ZIR.
- if (!comp.keep_source_files_loaded) {
- if (comp.module) |module| {
- for (module.import_table.values()) |file| {
- file.unloadTree(comp.gpa);
- file.unloadSource(comp.gpa);
- }
- }
- }
}
/// This function is called by the frontend before flush(). It communicates that
@@ -2274,10 +2277,14 @@ fn flush(comp: *Compilation, prog_node: *std.Progress.Node) !void {
}
/// Communicate the output binary location to parent Compilations.
-fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_digest_len]u8) void {
+fn wholeCacheModeSetBinFilePath(
+ comp: *Compilation,
+ whole: *CacheUse.Whole,
+ digest: *const [Cache.hex_digest_len]u8,
+) void {
const digest_start = 2; // "o/[digest]/[basename]"
- if (comp.whole_bin_sub_path) |sub_path| {
+ if (whole.bin_sub_path) |sub_path| {
@memcpy(sub_path[digest_start..][0..digest.len], digest);
comp.bin_file.?.emit = .{
@@ -2286,7 +2293,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
};
}
- if (comp.whole_implib_sub_path) |sub_path| {
+ if (whole.implib_sub_path) |sub_path| {
@memcpy(sub_path[digest_start..][0..digest.len], digest);
comp.implib_emit = .{
@@ -2295,7 +2302,7 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
};
}
- if (comp.whole_docs_sub_path) |sub_path| {
+ if (whole.docs_sub_path) |sub_path| {
@memcpy(sub_path[digest_start..][0..digest.len], digest);
comp.docs_emit = .{
@@ -3232,13 +3239,25 @@ pub fn performAllTheWork(
// 1. to avoid race condition of zig processes truncating each other's builtin.zig files
// 2. optimization; in the hot path it only incurs a stat() syscall, which happens
// in the `astgen_wait_group`.
- if (comp.module) |mod| {
- if (mod.job_queued_update_builtin_zig) {
- mod.job_queued_update_builtin_zig = false;
+ if (comp.job_queued_update_builtin_zig) b: {
+ comp.job_queued_update_builtin_zig = false;
+ const zcu = comp.module orelse break :b;
+ _ = zcu;
+ // TODO put all the modules in a flat array to make them easy to iterate.
+ var seen: std.AutoArrayHashMapUnmanaged(*Package.Module, void) = .{};
+ defer seen.deinit(comp.gpa);
+ try seen.put(comp.gpa, comp.root_mod);
+ var i: usize = 0;
+ while (i < seen.count()) : (i += 1) {
+ const mod = seen.keys()[i];
+ for (mod.deps.values()) |dep|
+ try seen.put(comp.gpa, dep);
+
+ const file = mod.builtin_file orelse continue;
comp.astgen_wait_group.start();
try comp.thread_pool.spawn(workerUpdateBuiltinZigFile, .{
- comp, mod, &comp.astgen_wait_group,
+ comp, mod, file, &comp.astgen_wait_group,
});
}
}
@@ -3702,19 +3721,17 @@ fn workerAstGenFile(
fn workerUpdateBuiltinZigFile(
comp: *Compilation,
- mod: *Module,
+ mod: *Package.Module,
+ file: *Module.File,
wg: *WaitGroup,
) void {
defer wg.finish();
-
- mod.populateBuiltinFile() catch |err| {
- const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse ".";
-
+ Builtin.populateFile(comp, mod, file) catch |err| {
comp.mutex.lock();
defer comp.mutex.unlock();
- comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
- dir_path, @errorName(err),
+ comp.setMiscFailure(.write_builtin_zig, "unable to write '{}{s}': {s}", .{
+ mod.root, mod.root_src_path, @errorName(err),
});
};
}
@@ -3755,14 +3772,17 @@ fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !voi
@panic("TODO: handle embed file incremental update");
}
-pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {
+pub fn obtainCObjectCacheManifest(
+ comp: *const Compilation,
+ owner_mod: *Package.Module,
+) Cache.Manifest {
var man = comp.cache_parent.obtain();
// Only things that need to be added on top of the base hash, and only things
// that apply both to @cImport and compiling C objects. No linking stuff here!
// Also nothing that applies only to compiling .zig code.
- man.hash.add(comp.sanitize_c);
- man.hash.addListOfBytes(comp.clang_argv);
+ man.hash.add(owner_mod.sanitize_c);
+ man.hash.addListOfBytes(owner_mod.clang_argv);
man.hash.add(comp.config.link_libcpp);
// When libc_installation is null it means that Zig generated this dir list
@@ -3797,19 +3817,19 @@ pub const CImportResult = struct {
/// Caller owns returned memory.
/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
/// a bit when we want to start using it from self-hosted.
-pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
+pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {
if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build");
const tracy_trace = trace(@src());
defer tracy_trace.end();
const cimport_zig_basename = "cimport.zig";
- var man = comp.obtainCObjectCacheManifest();
+ var man = comp.obtainCObjectCacheManifest(owner_mod);
defer man.deinit();
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
man.hash.addBytes(c_src);
- man.hash.add(comp.c_frontend);
+ man.hash.add(comp.config.c_frontend);
// If the previous invocation resulted in clang errors, we will see a hit
// here with 0 files in the manifest, in which case it is actually a miss.
@@ -3846,15 +3866,15 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
var argv = std.ArrayList([]const u8).init(comp.gpa);
defer argv.deinit();
- try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
- try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path);
+ try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1]
+ try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod);
try argv.append(out_h_path);
if (comp.verbose_cc) {
dump_argv(argv.items);
}
- var tree = switch (comp.c_frontend) {
+ var tree = switch (comp.config.c_frontend) {
.aro => tree: {
const translate_c = @import("aro_translate_c.zig");
_ = translate_c;
@@ -4119,7 +4139,7 @@ fn reportRetryableEmbedFileError(
}
fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.Progress.Node) !void {
- if (comp.c_frontend == .aro) {
+ if (comp.config.c_frontend == .aro) {
return comp.failCObj(c_object, "aro does not support compiling C objects yet", .{});
}
if (!build_options.have_llvm) {
@@ -4142,7 +4162,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
_ = comp.failed_c_objects.swapRemove(c_object);
}
- var man = comp.obtainCObjectCacheManifest();
+ var man = comp.obtainCObjectCacheManifest(c_object.src.owner);
defer man.deinit();
man.hash.add(comp.clang_preprocessor_mode);
@@ -4219,7 +4239,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
if (std.process.can_execv and direct_o and
comp.disable_c_depfile and comp.clang_passthrough_mode)
{
- try comp.addCCArgs(arena, &argv, ext, null);
+ try comp.addCCArgs(arena, &argv, ext, null, c_object.src.owner);
try argv.appendSlice(c_object.src.extra_flags);
try argv.appendSlice(c_object.src.cache_exempt_flags);
@@ -4262,7 +4282,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
null
else
try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path});
- try comp.addCCArgs(arena, &argv, ext, out_dep_path);
+ try comp.addCCArgs(arena, &argv, ext, out_dep_path, c_object.src.owner);
try argv.appendSlice(c_object.src.extra_flags);
try argv.appendSlice(c_object.src.cache_exempt_flags);
@@ -4610,7 +4630,7 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32
// mode. While these defines are not normally present when calling rc.exe directly,
// them being defined matches the behavior of how MSVC calls rc.exe which is the more
// relevant behavior in this case.
- try comp.addCCArgs(arena, &argv, .rc, out_dep_path);
+ try comp.addCCArgs(arena, &argv, .rc, out_dep_path, rc_src.owner);
if (comp.verbose_cc) {
dump_argv(argv.items);
@@ -4788,11 +4808,12 @@ pub fn addTranslateCCArgs(
argv: *std.ArrayList([]const u8),
ext: FileExt,
out_dep_path: ?[]const u8,
+ owner_mod: *Package.Module,
) !void {
- try argv.appendSlice(&[_][]const u8{ "-x", "c" });
- try comp.addCCArgs(arena, argv, ext, out_dep_path);
+ try argv.appendSlice(&.{ "-x", "c" });
+ try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod);
// This gives us access to preprocessing entities, presumably at the cost of performance.
- try argv.appendSlice(&[_][]const u8{ "-Xclang", "-detailed-preprocessing-record" });
+ try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" });
}
/// Add common C compiler args between translate-c and C object compilation.
@@ -4825,11 +4846,11 @@ pub fn addCCArgs(
try argv.append("-fno-caret-diagnostics");
}
- if (comp.bin_file.function_sections) {
+ if (comp.function_sections) {
try argv.append("-ffunction-sections");
}
- if (comp.bin_file.data_sections) {
+ if (comp.data_sections) {
try argv.append("-fdata-sections");
}
@@ -5088,7 +5109,7 @@ pub fn addCCArgs(
try argv.append("-fPIC");
}
- if (comp.unwind_tables) {
+ if (mod.unwind_tables) {
try argv.append("-funwind-tables");
} else {
try argv.append("-fno-unwind-tables");
@@ -5174,7 +5195,7 @@ pub fn addCCArgs(
}
try argv.ensureUnusedCapacity(2);
- switch (comp.bin_file.debug_format) {
+ switch (comp.config.debug_format) {
.strip => {},
.code_view => {
// -g is required here because -gcodeview doesn't trigger debug info
@@ -5210,7 +5231,7 @@ pub fn addCCArgs(
try argv.append("-ffreestanding");
}
- try argv.appendSlice(comp.clang_argv);
+ try argv.appendSlice(mod.cc_argv);
}
fn failCObj(
@@ -6094,6 +6115,7 @@ fn buildOutputFromZig(
.have_zcu = true,
.emit_bin = true,
.root_optimize_mode = comp.compilerRtOptMode(),
+ .root_strip = comp.compilerRtStrip(),
.link_libc = comp.config.link_libc,
.any_unwind_tables = unwind_tables,
});
@@ -6198,6 +6220,7 @@ pub fn build_crt_file(
.have_zcu = false,
.emit_bin = true,
.root_optimize_mode = comp.compilerRtOptMode(),
+ .root_strip = comp.compilerRtStrip(),
.link_libc = false,
.lto = switch (output_mode) {
.Lib => comp.config.lto,
src/libunwind.zig
@@ -28,6 +28,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.have_zcu = false,
.emit_bin = true,
.root_optimize_mode = comp.compilerRtOptMode(),
+ .root_strip = comp.compilerRtStrip(),
.link_libc = true,
// Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825
.lto = false,
@@ -131,7 +132,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: *std.Progress.Node) !void {
.libc_installation = comp.libc_installation,
.emit_bin = emit_bin,
.link_mode = link_mode,
- .function_sections = comp.bin_file.function_sections,
+ .function_sections = comp.function_sections,
.c_source_files = &c_source_files,
.verbose_cc = comp.verbose_cc,
.verbose_link = comp.verbose_link,
src/link.zig
@@ -68,9 +68,6 @@ pub const File = struct {
force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
allow_shlib_undefined: bool,
stack_size: u64,
- debug_format: DebugFormat,
- function_sections: bool,
- data_sections: bool,
/// Prevents other processes from clobbering files in the output directory
/// of this linking operation.
@@ -78,16 +75,7 @@ pub const File = struct {
child_pid: ?std.ChildProcess.Id = null,
- pub const DebugFormat = union(enum) {
- strip,
- dwarf: std.dwarf.Format,
- code_view,
- };
-
pub const OpenOptions = struct {
- comp: *Compilation,
- emit: Compilation.Emit,
-
symbol_count_hint: u64 = 32,
program_code_size_hint: u64 = 256 * 1024,
@@ -95,8 +83,6 @@ pub const File = struct {
entry_addr: ?u64,
stack_size: ?u64,
image_base: ?u64,
- function_sections: bool,
- data_sections: bool,
eh_frame_hdr: bool,
emit_relocs: bool,
rdynamic: bool,
@@ -150,8 +136,6 @@ pub const File = struct {
compatibility_version: ?std.SemanticVersion,
- debug_format: ?DebugFormat,
-
// TODO: remove this. libraries are resolved by the frontend.
lib_dirs: []const []const u8,
rpath_list: []const []const u8,
@@ -190,10 +174,29 @@ pub const File = struct {
/// rewriting it. A malicious file is detected as incremental link failure
/// and does not cause Illegal Behavior. This operation is not atomic.
/// `arena` is used for allocations with the same lifetime as the created File.
- pub fn open(arena: Allocator, options: OpenOptions) !*File {
- switch (Tag.fromObjectFormat(options.comp.root_mod.resolved_target.result.ofmt)) {
+ pub fn open(
+ arena: Allocator,
+ comp: *Compilation,
+ 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);
+ return &ptr.base;
+ },
+ }
+ }
+
+ pub fn createEmpty(
+ arena: Allocator,
+ comp: *Compilation,
+ 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, options);
+ const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
return &ptr.base;
},
}
src/main.zig
@@ -892,7 +892,6 @@ fn buildOutputType(
var contains_res_file: bool = false;
var reference_trace: ?u32 = null;
var pdb_out_path: ?[]const u8 = null;
- var debug_format: ?link.File.DebugFormat = null;
var error_limit: ?Module.ErrorInt = null;
// These are before resolving sysroot.
var lib_dir_args: std.ArrayListUnmanaged([]const u8) = .{};
@@ -1054,6 +1053,8 @@ fn buildOutputType(
create_module.opts.any_sanitize_thread = true;
if (mod_opts.unwind_tables == true)
create_module.opts.any_unwind_tables = true;
+ if (mod_opts.strip == false)
+ create_module.opts.any_non_stripped = true;
const root_src = try introspect.resolvePath(arena, root_src_orig);
try create_module.modules.put(arena, mod_name, .{
@@ -1480,9 +1481,9 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "-fno-strip")) {
mod_opts.strip = false;
} else if (mem.eql(u8, arg, "-gdwarf32")) {
- debug_format = .{ .dwarf = .@"32" };
+ create_module.opts.debug_format = .{ .dwarf = .@"32" };
} else if (mem.eql(u8, arg, "-gdwarf64")) {
- debug_format = .{ .dwarf = .@"64" };
+ create_module.opts.debug_format = .{ .dwarf = .@"64" };
} else if (mem.eql(u8, arg, "-fformatted-panics")) {
formatted_panics = true;
} else if (mem.eql(u8, arg, "-fno-formatted-panics")) {
@@ -1989,11 +1990,11 @@ fn buildOutputType(
},
.gdwarf32 => {
mod_opts.strip = false;
- debug_format = .{ .dwarf = .@"32" };
+ create_module.opts.debug_format = .{ .dwarf = .@"32" };
},
.gdwarf64 => {
mod_opts.strip = false;
- debug_format = .{ .dwarf = .@"64" };
+ create_module.opts.debug_format = .{ .dwarf = .@"64" };
},
.sanitize => {
if (mem.eql(u8, it.only_arg, "undefined")) {
@@ -2532,6 +2533,8 @@ fn buildOutputType(
create_module.opts.any_sanitize_thread = true;
if (mod_opts.unwind_tables == true)
create_module.opts.any_unwind_tables = true;
+ if (mod_opts.strip == false)
+ create_module.opts.any_non_stripped = true;
const src_path = try introspect.resolvePath(arena, unresolved_src_path);
try create_module.modules.put(arena, "main", .{
@@ -3359,7 +3362,6 @@ fn buildOutputType(
.emit_docs = emit_docs_resolved.data,
.emit_implib = emit_implib_resolved.data,
.dll_export_fns = dll_export_fns,
- .keep_source_files_loaded = false,
.lib_dirs = lib_dirs.items,
.rpath_list = rpath_list.items,
.symbol_wrap_set = symbol_wrap_set,
@@ -3443,7 +3445,6 @@ fn buildOutputType(
.test_runner_path = test_runner_path,
.disable_lld_caching = !output_to_cache,
.subsystem = subsystem,
- .debug_format = debug_format,
.debug_compile_errors = debug_compile_errors,
.enable_link_snapshots = enable_link_snapshots,
.install_name = install_name,
@@ -3484,7 +3485,9 @@ fn buildOutputType(
defer if (!comp_destroyed) comp.destroy();
if (show_builtin) {
- return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
+ const builtin_mod = comp.root_mod.deps.get("builtin").?;
+ const source = builtin_mod.builtin_file.?.source;
+ return std.io.getStdOut().writeAll(source);
}
switch (listen) {
.none => {},
@@ -3737,6 +3740,7 @@ fn createModule(
const resolved_target = cli_mod.inherited.resolved_target.?;
create_module.opts.resolved_target = resolved_target;
create_module.opts.root_optimize_mode = cli_mod.inherited.optimize_mode;
+ create_module.opts.root_strip = cli_mod.inherited.strip;
const target = resolved_target.result;
// First, remove libc, libc++, and compiler_rt libraries from the system libraries list.
@@ -4366,12 +4370,12 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
const translated_zig_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});
- var man: Cache.Manifest = comp.obtainCObjectCacheManifest();
+ var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod);
man.want_shared_lock = false;
defer man.deinit();
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
- man.hash.add(comp.c_frontend);
+ man.hash.add(comp.config.c_frontend);
Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| {
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
};
@@ -4380,14 +4384,14 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
const digest = if (try man.hit()) man.final() else digest: {
if (fancy_output) |p| p.cache_hit = false;
var argv = std.ArrayList([]const u8).init(arena);
- try argv.append(@tagName(comp.c_frontend)); // argv[0] is program name, actual args start at [1]
+ try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1]
var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{});
defer zig_cache_tmp_dir.close();
const ext = Compilation.classifyFileExt(c_source_file.src_path);
const out_dep_path: ?[]const u8 = blk: {
- if (comp.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile())
+ if (comp.config.c_frontend == .aro or comp.disable_c_depfile or !ext.clangSupportsDepFile())
break :blk null;
const c_src_basename = fs.path.basename(c_source_file.src_path);
@@ -4397,14 +4401,15 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati
};
// TODO
- if (comp.c_frontend != .aro) try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path);
+ if (comp.config.c_frontend != .aro)
+ try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod);
try argv.append(c_source_file.src_path);
if (comp.verbose_cc) {
Compilation.dump_argv(argv.items);
}
- var tree = switch (comp.c_frontend) {
+ var tree = switch (comp.config.c_frontend) {
.aro => tree: {
const aro = @import("aro");
const translate_c = @import("aro_translate_c.zig");
src/Module.zig
@@ -152,8 +152,6 @@ stage1_flags: packed struct {
reserved: u2 = 0,
} = .{},
-job_queued_update_builtin_zig: bool = true,
-
compile_log_text: ArrayListUnmanaged(u8) = .{},
emit_h: ?*GlobalEmitH,
@@ -2490,7 +2488,6 @@ pub fn deinit(mod: *Module) void {
mod.compile_log_text.deinit(gpa);
- mod.zig_cache_artifact_directory.handle.close();
mod.local_zir_cache.handle.close();
mod.global_zir_cache.handle.close();
@@ -3075,72 +3072,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
}
}
-pub fn populateBuiltinFile(mod: *Module) !void {
- const tracy = trace(@src());
- defer tracy.end();
-
- const comp = mod.comp;
- const builtin_mod, const file = blk: {
- comp.mutex.lock();
- defer comp.mutex.unlock();
-
- const builtin_mod = mod.main_mod.deps.get("builtin").?;
- const result = try mod.importPkg(builtin_mod);
- break :blk .{ builtin_mod, result.file };
- };
- const gpa = mod.gpa;
- file.source = try comp.generateBuiltinZigSource(gpa);
- file.source_loaded = true;
-
- if (builtin_mod.root.statFile(builtin_mod.root_src_path)) |stat| {
- if (stat.size != file.source.len) {
- log.warn(
- "the cached file '{}{s}' had the wrong size. Expected {d}, found {d}. " ++
- "Overwriting with correct file contents now",
- .{ builtin_mod.root, builtin_mod.root_src_path, file.source.len, stat.size },
- );
-
- try writeBuiltinFile(file, builtin_mod);
- } else {
- file.stat = .{
- .size = stat.size,
- .inode = stat.inode,
- .mtime = stat.mtime,
- };
- }
- } else |err| switch (err) {
- error.BadPathName => unreachable, // it's always "builtin.zig"
- error.NameTooLong => unreachable, // it's always "builtin.zig"
- error.PipeBusy => unreachable, // it's not a pipe
- error.WouldBlock => unreachable, // not asking for non-blocking I/O
-
- error.FileNotFound => try writeBuiltinFile(file, builtin_mod),
-
- else => |e| return e,
- }
-
- file.tree = try Ast.parse(gpa, file.source, .zig);
- file.tree_loaded = true;
- assert(file.tree.errors.len == 0); // builtin.zig must parse
-
- file.zir = try AstGen.generate(gpa, file.tree);
- file.zir_loaded = true;
- file.status = .success_zir;
-}
-
-fn writeBuiltinFile(file: *File, builtin_mod: *Package.Module) !void {
- var af = try builtin_mod.root.atomicFile(builtin_mod.root_src_path, .{});
- defer af.deinit();
- try af.file.writeAll(file.source);
- try af.finish();
-
- file.stat = .{
- .size = file.source.len,
- .inode = 0, // dummy value
- .mtime = 0, // dummy value
- };
-}
-
pub fn mapOldZirToNew(
gpa: Allocator,
old_zir: Zir,
src/Sema.zig
@@ -784,6 +784,11 @@ pub const Block = struct {
}
}
+ pub fn ownerModule(block: Block) *Package.Module {
+ const zcu = block.sema.mod;
+ return zcu.namespacePtr(block.namespace).file_scope.mod;
+ }
+
pub fn startAnonDecl(block: *Block) !WipAnonDecl {
return WipAnonDecl{
.block = block,
@@ -5733,7 +5738,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
// Ignore the result, all the relevant operations have written to c_import_buf already.
_ = try sema.analyzeBodyBreak(&child_block, body);
- var c_import_res = comp.cImport(c_import_buf.items) catch |err|
+ var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err|
return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
defer c_import_res.deinit(gpa);