mirror of
https://github.com/ziglang/zig.git
synced 2026-02-01 20:23:38 +00:00
restore -fno-emit-bin -femit-llvm-ir functionality
Now, link.File will always be null when -fno-emit-bin is specified, and in the case that LLVM artifacts are still required, the Zcu instance has an LlvmObject.
This commit is contained in:
parent
92cc2f41e6
commit
b8674910d4
@ -39,6 +39,7 @@ const Zir = @import("Zir.zig");
|
||||
const Autodoc = @import("Autodoc.zig");
|
||||
const resinator = @import("resinator.zig");
|
||||
const Builtin = @import("Builtin.zig");
|
||||
const LlvmObject = @import("codegen/llvm.zig").Object;
|
||||
|
||||
pub const Config = @import("Compilation/Config.zig");
|
||||
|
||||
@ -1434,6 +1435,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation {
|
||||
.emit_h = emit_h,
|
||||
.tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
|
||||
.error_limit = error_limit,
|
||||
.llvm_object = null,
|
||||
};
|
||||
try zcu.init();
|
||||
break :blk zcu;
|
||||
@ -1683,6 +1685,17 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation {
|
||||
},
|
||||
}
|
||||
|
||||
// Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.
|
||||
if (options.emit_bin == null and (comp.verbose_llvm_ir != null or
|
||||
comp.verbose_llvm_bc != null or
|
||||
(use_llvm and comp.emit_asm != null) or
|
||||
comp.emit_llvm_ir != null or
|
||||
comp.emit_llvm_bc != null))
|
||||
{
|
||||
if (build_options.only_c) unreachable;
|
||||
if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
|
||||
}
|
||||
|
||||
comp.arena = arena_allocator;
|
||||
break :comp comp;
|
||||
};
|
||||
@ -2016,6 +2029,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
const tracy_trace = trace(@src());
|
||||
defer tracy_trace.end();
|
||||
|
||||
// This arena is scoped to this one update.
|
||||
const gpa = comp.gpa;
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
comp.clearMiscFailures();
|
||||
comp.last_update_was_cache_hit = false;
|
||||
|
||||
@ -2034,7 +2053,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
|
||||
man = comp.cache_parent.obtain();
|
||||
whole.cache_manifest = &man;
|
||||
try comp.addNonIncrementalStuffToCacheManifest(&man);
|
||||
try addNonIncrementalStuffToCacheManifest(comp, arena, &man);
|
||||
|
||||
const is_hit = man.hit() catch |err| {
|
||||
const i = man.failed_file_index orelse return err;
|
||||
@ -2065,8 +2084,8 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
tmp_dir_rand_int = std.crypto.random.int(u64);
|
||||
const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int);
|
||||
|
||||
const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path});
|
||||
errdefer comp.gpa.free(path);
|
||||
const path = try comp.local_cache_directory.join(gpa, &.{tmp_dir_sub_path});
|
||||
errdefer gpa.free(path);
|
||||
|
||||
const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
|
||||
errdefer handle.close();
|
||||
@ -2100,10 +2119,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
.directory = tmp_artifact_directory,
|
||||
.sub_path = std.fs.path.basename(sub_path),
|
||||
};
|
||||
// It's a bit strange to use the Compilation arena allocator here
|
||||
// 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.createEmpty(arena, comp, emit, whole.lf_open_opts);
|
||||
}
|
||||
},
|
||||
@ -2127,7 +2142,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
}
|
||||
|
||||
if (comp.module) |module| {
|
||||
module.compile_log_text.shrinkAndFree(module.gpa, 0);
|
||||
module.compile_log_text.shrinkAndFree(gpa, 0);
|
||||
module.generation += 1;
|
||||
|
||||
// Make sure std.zig is inside the import_table. We unconditionally need
|
||||
@ -2189,7 +2204,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
comp.root_name,
|
||||
@as(usize, @intFromPtr(module)),
|
||||
});
|
||||
module.intern_pool.dumpGenericInstances(comp.gpa);
|
||||
module.intern_pool.dumpGenericInstances(gpa);
|
||||
}
|
||||
|
||||
if (comp.config.is_test and comp.totalErrorCount() == 0) {
|
||||
@ -2222,8 +2237,23 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
};
|
||||
}
|
||||
|
||||
if (comp.module) |module| {
|
||||
try link.File.C.flushEmitH(module);
|
||||
if (comp.module) |zcu| {
|
||||
try link.File.C.flushEmitH(zcu);
|
||||
|
||||
if (zcu.llvm_object) |llvm_object| {
|
||||
if (build_options.only_c) unreachable;
|
||||
const default_emit = switch (comp.cache_use) {
|
||||
.whole => |whole| .{
|
||||
.directory = whole.tmp_artifact_directory.?,
|
||||
.sub_path = "dummy",
|
||||
},
|
||||
.incremental => |incremental| .{
|
||||
.directory = incremental.artifact_directory,
|
||||
.sub_path = "dummy",
|
||||
},
|
||||
};
|
||||
try emitLlvmObject(comp, arena, default_emit, null, llvm_object, main_progress_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2238,7 +2268,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
|
||||
// Close tmp dir and link.File to avoid open handle during rename.
|
||||
if (whole.tmp_artifact_directory) |*tmp_directory| {
|
||||
tmp_directory.handle.close();
|
||||
if (tmp_directory.path) |p| comp.gpa.free(p);
|
||||
if (tmp_directory.path) |p| gpa.free(p);
|
||||
whole.tmp_artifact_directory = null;
|
||||
} else unreachable;
|
||||
|
||||
@ -2389,13 +2419,13 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
|
||||
/// anything from the link cache manifest.
|
||||
pub const link_hash_implementation_version = 10;
|
||||
|
||||
fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
|
||||
fn addNonIncrementalStuffToCacheManifest(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
man: *Cache.Manifest,
|
||||
) !void {
|
||||
const gpa = comp.gpa;
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
comptime assert(link_hash_implementation_version == 10);
|
||||
|
||||
if (comp.module) |mod| {
|
||||
@ -2568,6 +2598,50 @@ fn emitOthers(comp: *Compilation) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emitLlvmObject(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
default_emit: Emit,
|
||||
bin_emit_loc: ?EmitLoc,
|
||||
llvm_object: *LlvmObject,
|
||||
prog_node: *std.Progress.Node,
|
||||
) !void {
|
||||
if (build_options.only_c) @compileError("unreachable");
|
||||
|
||||
var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
|
||||
sub_prog_node.activate();
|
||||
sub_prog_node.context.refresh();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
try llvm_object.emit(.{
|
||||
.pre_ir_path = comp.verbose_llvm_ir,
|
||||
.pre_bc_path = comp.verbose_llvm_bc,
|
||||
.bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc),
|
||||
.asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm),
|
||||
.post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir),
|
||||
.post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc),
|
||||
|
||||
.is_debug = comp.root_mod.optimize_mode == .Debug,
|
||||
.is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
|
||||
.time_report = comp.time_report,
|
||||
.sanitize_thread = comp.config.any_sanitize_thread,
|
||||
.lto = comp.config.lto,
|
||||
});
|
||||
}
|
||||
|
||||
fn resolveEmitLoc(
|
||||
arena: Allocator,
|
||||
default_emit: Emit,
|
||||
opt_loc: ?EmitLoc,
|
||||
) Allocator.Error!?[*:0]const u8 {
|
||||
const loc = opt_loc orelse return null;
|
||||
const slice = if (loc.directory) |directory|
|
||||
try directory.joinZ(arena, &.{loc.basename})
|
||||
else
|
||||
try default_emit.basenamePath(arena, loc.basename);
|
||||
return slice.ptr;
|
||||
}
|
||||
|
||||
fn reportMultiModuleErrors(mod: *Module) !void {
|
||||
// Some cases can give you a whole bunch of multi-module errors, which it's not helpful to
|
||||
// print all of, so we'll cap the number of these to emit.
|
||||
|
||||
251
src/Module.zig
251
src/Module.zig
@ -37,6 +37,7 @@ const clang = @import("clang.zig");
|
||||
const InternPool = @import("InternPool.zig");
|
||||
const Alignment = InternPool.Alignment;
|
||||
const BuiltinFn = std.zig.BuiltinFn;
|
||||
const LlvmObject = @import("codegen/llvm.zig").Object;
|
||||
|
||||
comptime {
|
||||
@setEvalBranchQuota(4000);
|
||||
@ -53,6 +54,10 @@ comptime {
|
||||
/// General-purpose allocator. Used for both temporary and long-term storage.
|
||||
gpa: Allocator,
|
||||
comp: *Compilation,
|
||||
/// Usually, the LlvmObject is managed by linker code, however, in the case
|
||||
/// that -fno-emit-bin is specified, the linker code never executes, so we
|
||||
/// store the LlvmObject here.
|
||||
llvm_object: ?*LlvmObject,
|
||||
|
||||
/// Pointer to externally managed resource.
|
||||
root_mod: *Package.Module,
|
||||
@ -2476,36 +2481,41 @@ pub fn init(mod: *Module) !void {
|
||||
try mod.global_error_set.put(gpa, .empty, {});
|
||||
}
|
||||
|
||||
pub fn deinit(mod: *Module) void {
|
||||
const gpa = mod.gpa;
|
||||
pub fn deinit(zcu: *Zcu) void {
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
for (mod.import_table.keys()) |key| {
|
||||
if (zcu.llvm_object) |llvm_object| {
|
||||
if (build_options.only_c) unreachable;
|
||||
llvm_object.deinit();
|
||||
}
|
||||
|
||||
for (zcu.import_table.keys()) |key| {
|
||||
gpa.free(key);
|
||||
}
|
||||
var failed_decls = mod.failed_decls;
|
||||
mod.failed_decls = .{};
|
||||
for (mod.import_table.values()) |value| {
|
||||
value.destroy(mod);
|
||||
var failed_decls = zcu.failed_decls;
|
||||
zcu.failed_decls = .{};
|
||||
for (zcu.import_table.values()) |value| {
|
||||
value.destroy(zcu);
|
||||
}
|
||||
mod.import_table.deinit(gpa);
|
||||
zcu.import_table.deinit(gpa);
|
||||
|
||||
for (mod.embed_table.keys(), mod.embed_table.values()) |path, embed_file| {
|
||||
for (zcu.embed_table.keys(), zcu.embed_table.values()) |path, embed_file| {
|
||||
gpa.free(path);
|
||||
gpa.destroy(embed_file);
|
||||
}
|
||||
mod.embed_table.deinit(gpa);
|
||||
zcu.embed_table.deinit(gpa);
|
||||
|
||||
mod.compile_log_text.deinit(gpa);
|
||||
zcu.compile_log_text.deinit(gpa);
|
||||
|
||||
mod.local_zir_cache.handle.close();
|
||||
mod.global_zir_cache.handle.close();
|
||||
zcu.local_zir_cache.handle.close();
|
||||
zcu.global_zir_cache.handle.close();
|
||||
|
||||
for (failed_decls.values()) |value| {
|
||||
value.destroy(gpa);
|
||||
}
|
||||
failed_decls.deinit(gpa);
|
||||
|
||||
if (mod.emit_h) |emit_h| {
|
||||
if (zcu.emit_h) |emit_h| {
|
||||
for (emit_h.failed_decls.values()) |value| {
|
||||
value.destroy(gpa);
|
||||
}
|
||||
@ -2514,68 +2524,68 @@ pub fn deinit(mod: *Module) void {
|
||||
emit_h.allocated_emit_h.deinit(gpa);
|
||||
}
|
||||
|
||||
for (mod.failed_files.values()) |value| {
|
||||
for (zcu.failed_files.values()) |value| {
|
||||
if (value) |msg| msg.destroy(gpa);
|
||||
}
|
||||
mod.failed_files.deinit(gpa);
|
||||
zcu.failed_files.deinit(gpa);
|
||||
|
||||
for (mod.failed_embed_files.values()) |msg| {
|
||||
for (zcu.failed_embed_files.values()) |msg| {
|
||||
msg.destroy(gpa);
|
||||
}
|
||||
mod.failed_embed_files.deinit(gpa);
|
||||
zcu.failed_embed_files.deinit(gpa);
|
||||
|
||||
for (mod.failed_exports.values()) |value| {
|
||||
for (zcu.failed_exports.values()) |value| {
|
||||
value.destroy(gpa);
|
||||
}
|
||||
mod.failed_exports.deinit(gpa);
|
||||
zcu.failed_exports.deinit(gpa);
|
||||
|
||||
for (mod.cimport_errors.values()) |*errs| {
|
||||
for (zcu.cimport_errors.values()) |*errs| {
|
||||
errs.deinit(gpa);
|
||||
}
|
||||
mod.cimport_errors.deinit(gpa);
|
||||
zcu.cimport_errors.deinit(gpa);
|
||||
|
||||
mod.compile_log_decls.deinit(gpa);
|
||||
zcu.compile_log_decls.deinit(gpa);
|
||||
|
||||
for (mod.decl_exports.values()) |*export_list| {
|
||||
for (zcu.decl_exports.values()) |*export_list| {
|
||||
export_list.deinit(gpa);
|
||||
}
|
||||
mod.decl_exports.deinit(gpa);
|
||||
zcu.decl_exports.deinit(gpa);
|
||||
|
||||
for (mod.value_exports.values()) |*export_list| {
|
||||
for (zcu.value_exports.values()) |*export_list| {
|
||||
export_list.deinit(gpa);
|
||||
}
|
||||
mod.value_exports.deinit(gpa);
|
||||
zcu.value_exports.deinit(gpa);
|
||||
|
||||
for (mod.export_owners.values()) |*value| {
|
||||
for (zcu.export_owners.values()) |*value| {
|
||||
freeExportList(gpa, value);
|
||||
}
|
||||
mod.export_owners.deinit(gpa);
|
||||
zcu.export_owners.deinit(gpa);
|
||||
|
||||
mod.global_error_set.deinit(gpa);
|
||||
zcu.global_error_set.deinit(gpa);
|
||||
|
||||
mod.test_functions.deinit(gpa);
|
||||
zcu.test_functions.deinit(gpa);
|
||||
|
||||
for (mod.global_assembly.values()) |s| {
|
||||
for (zcu.global_assembly.values()) |s| {
|
||||
gpa.free(s);
|
||||
}
|
||||
mod.global_assembly.deinit(gpa);
|
||||
zcu.global_assembly.deinit(gpa);
|
||||
|
||||
mod.reference_table.deinit(gpa);
|
||||
zcu.reference_table.deinit(gpa);
|
||||
|
||||
{
|
||||
var it = mod.intern_pool.allocated_namespaces.iterator(0);
|
||||
var it = zcu.intern_pool.allocated_namespaces.iterator(0);
|
||||
while (it.next()) |namespace| {
|
||||
namespace.decls.deinit(gpa);
|
||||
namespace.usingnamespace_set.deinit(gpa);
|
||||
}
|
||||
}
|
||||
|
||||
mod.intern_pool.deinit(gpa);
|
||||
mod.tmp_hack_arena.deinit();
|
||||
zcu.intern_pool.deinit(gpa);
|
||||
zcu.tmp_hack_arena.deinit();
|
||||
|
||||
mod.capture_scope_parents.deinit(gpa);
|
||||
mod.runtime_capture_scopes.deinit(gpa);
|
||||
mod.comptime_capture_scopes.deinit(gpa);
|
||||
zcu.capture_scope_parents.deinit(gpa);
|
||||
zcu.runtime_capture_scopes.deinit(gpa);
|
||||
zcu.comptime_capture_scopes.deinit(gpa);
|
||||
}
|
||||
|
||||
pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
|
||||
@ -3222,14 +3232,14 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
|
||||
pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const func = mod.funcInfo(func_index);
|
||||
const ip = &zcu.intern_pool;
|
||||
const func = zcu.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
|
||||
switch (decl.analysis) {
|
||||
.unreferenced => unreachable,
|
||||
@ -3253,13 +3263,13 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
|
||||
.success => return,
|
||||
}
|
||||
|
||||
const gpa = mod.gpa;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
var tmp_arena = std.heap.ArenaAllocator.init(gpa);
|
||||
defer tmp_arena.deinit();
|
||||
const sema_arena = tmp_arena.allocator();
|
||||
|
||||
var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
|
||||
var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
|
||||
error.AnalysisFail => {
|
||||
if (func.analysis(ip).state == .in_progress) {
|
||||
// If this decl caused the compile error, the analysis field would
|
||||
@ -3273,25 +3283,22 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
|
||||
};
|
||||
defer air.deinit(gpa);
|
||||
|
||||
const comp = mod.comp;
|
||||
|
||||
const no_bin_file = (comp.bin_file == null and
|
||||
comp.emit_asm == null and
|
||||
comp.emit_llvm_ir == null and
|
||||
comp.emit_llvm_bc == null);
|
||||
const comp = zcu.comp;
|
||||
|
||||
const dump_air = builtin.mode == .Debug and comp.verbose_air;
|
||||
const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
|
||||
|
||||
if (no_bin_file and !dump_air and !dump_llvm_ir) return;
|
||||
if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {
|
||||
return;
|
||||
}
|
||||
|
||||
var liveness = try Liveness.analyze(gpa, air, ip);
|
||||
defer liveness.deinit(gpa);
|
||||
|
||||
if (dump_air) {
|
||||
const fqn = try decl.getFullyQualifiedName(mod);
|
||||
const fqn = try decl.getFullyQualifiedName(zcu);
|
||||
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
|
||||
@import("print_air.zig").dump(mod, air, liveness);
|
||||
@import("print_air.zig").dump(zcu, air, liveness);
|
||||
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
|
||||
}
|
||||
|
||||
@ -3307,12 +3314,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
|
||||
verify.verify() catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => {
|
||||
try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
mod.failed_decls.putAssumeCapacityNoClobber(
|
||||
try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
zcu.failed_decls.putAssumeCapacityNoClobber(
|
||||
decl_index,
|
||||
try Module.ErrorMsg.create(
|
||||
gpa,
|
||||
decl.srcLoc(mod),
|
||||
decl.srcLoc(zcu),
|
||||
"invalid liveness: {s}",
|
||||
.{@errorName(err)},
|
||||
),
|
||||
@ -3323,28 +3330,32 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
|
||||
};
|
||||
}
|
||||
|
||||
if (no_bin_file and !dump_llvm_ir) return;
|
||||
|
||||
const lf = comp.bin_file.?;
|
||||
lf.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
return;
|
||||
},
|
||||
else => {
|
||||
try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
|
||||
gpa,
|
||||
decl.srcLoc(mod),
|
||||
"unable to codegen: {s}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
decl.analysis = .codegen_failure_retryable;
|
||||
return;
|
||||
},
|
||||
};
|
||||
return;
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
},
|
||||
else => {
|
||||
try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
|
||||
gpa,
|
||||
decl.srcLoc(zcu),
|
||||
"unable to codegen: {s}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
decl.analysis = .codegen_failure_retryable;
|
||||
},
|
||||
};
|
||||
} else if (zcu.llvm_object) |llvm_object| {
|
||||
if (build_options.only_c) unreachable;
|
||||
llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -5235,44 +5246,57 @@ pub fn processExports(mod: *Module) !void {
|
||||
const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export);
|
||||
|
||||
fn processExportsInner(
|
||||
mod: *Module,
|
||||
zcu: *Zcu,
|
||||
symbol_exports: *SymbolExports,
|
||||
exported: Exported,
|
||||
exports: []const *Export,
|
||||
) error{OutOfMemory}!void {
|
||||
const gpa = mod.gpa;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
for (exports) |new_export| {
|
||||
const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);
|
||||
if (gop.found_existing) {
|
||||
new_export.status = .failed_retryable;
|
||||
try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
|
||||
const src_loc = new_export.getSrcLoc(mod);
|
||||
try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
|
||||
const src_loc = new_export.getSrcLoc(zcu);
|
||||
const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{
|
||||
new_export.opts.name.fmt(&mod.intern_pool),
|
||||
new_export.opts.name.fmt(&zcu.intern_pool),
|
||||
});
|
||||
errdefer msg.destroy(gpa);
|
||||
const other_export = gop.value_ptr.*;
|
||||
const other_src_loc = other_export.getSrcLoc(mod);
|
||||
try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
|
||||
mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
|
||||
const other_src_loc = other_export.getSrcLoc(zcu);
|
||||
try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
|
||||
zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
|
||||
new_export.status = .failed;
|
||||
} else {
|
||||
gop.value_ptr.* = new_export;
|
||||
}
|
||||
}
|
||||
const lf = mod.comp.bin_file orelse return;
|
||||
lf.updateExports(mod, exported, exports) catch |err| switch (err) {
|
||||
if (zcu.comp.bin_file) |lf| {
|
||||
try handleUpdateExports(zcu, exports, lf.updateExports(zcu, exported, exports));
|
||||
} else if (zcu.llvm_object) |llvm_object| {
|
||||
if (build_options.only_c) unreachable;
|
||||
try handleUpdateExports(zcu, exports, llvm_object.updateExports(zcu, exported, exports));
|
||||
}
|
||||
}
|
||||
|
||||
fn handleUpdateExports(
|
||||
zcu: *Zcu,
|
||||
exports: []const *Export,
|
||||
result: link.File.UpdateExportsError!void,
|
||||
) Allocator.Error!void {
|
||||
const gpa = zcu.gpa;
|
||||
result catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => {
|
||||
error.AnalysisFail => {
|
||||
const new_export = exports[0];
|
||||
new_export.status = .failed_retryable;
|
||||
try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
|
||||
const src_loc = new_export.getSrcLoc(mod);
|
||||
try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
|
||||
const src_loc = new_export.getSrcLoc(zcu);
|
||||
const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{
|
||||
@errorName(err),
|
||||
});
|
||||
mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
|
||||
zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -5415,41 +5439,38 @@ pub fn populateTestFunctions(
|
||||
try mod.linkerUpdateDecl(decl_index);
|
||||
}
|
||||
|
||||
pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
|
||||
const comp = mod.comp;
|
||||
pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {
|
||||
const comp = zcu.comp;
|
||||
|
||||
if (comp.bin_file) |lf| {
|
||||
const decl = mod.declPtr(decl_index);
|
||||
lf.updateDecl(mod, decl_index) catch |err| switch (err) {
|
||||
lf.updateDecl(zcu, decl_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
decl.analysis = .codegen_failure;
|
||||
return;
|
||||
},
|
||||
else => {
|
||||
const gpa = mod.gpa;
|
||||
try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
const gpa = zcu.gpa;
|
||||
try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
|
||||
zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
|
||||
gpa,
|
||||
decl.srcLoc(mod),
|
||||
decl.srcLoc(zcu),
|
||||
"unable to codegen: {s}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
decl.analysis = .codegen_failure_retryable;
|
||||
return;
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const dump_llvm_ir = builtin.mode == .Debug and
|
||||
(comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
|
||||
|
||||
if (comp.emit_asm != null or
|
||||
comp.emit_llvm_ir != null or
|
||||
comp.emit_llvm_bc != null or
|
||||
dump_llvm_ir)
|
||||
{
|
||||
@panic("TODO handle emit_asm, emit_llvm_ir, and emit_llvm_bc along with -fno-emit-bin");
|
||||
}
|
||||
} else if (zcu.llvm_object) |llvm_object| {
|
||||
if (build_options.only_c) unreachable;
|
||||
llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.AnalysisFail => {
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
decl.analysis = .codegen_failure;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
41
src/link.zig
41
src/link.zig
@ -984,49 +984,16 @@ pub const File = struct {
|
||||
return output_mode == .Lib and !self.isStatic();
|
||||
}
|
||||
|
||||
pub fn resolveEmitLoc(
|
||||
base: File,
|
||||
arena: Allocator,
|
||||
opt_loc: ?Compilation.EmitLoc,
|
||||
) Allocator.Error!?[*:0]const u8 {
|
||||
const loc = opt_loc orelse return null;
|
||||
const slice = if (loc.directory) |directory|
|
||||
try directory.joinZ(arena, &.{loc.basename})
|
||||
else
|
||||
try base.emit.basenamePath(arena, loc.basename);
|
||||
return slice.ptr;
|
||||
}
|
||||
|
||||
pub fn emitLlvmObject(
|
||||
base: File,
|
||||
arena: Allocator,
|
||||
llvm_object: *LlvmObject,
|
||||
prog_node: *std.Progress.Node,
|
||||
) !void {
|
||||
const comp = base.comp;
|
||||
|
||||
var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
|
||||
sub_prog_node.activate();
|
||||
sub_prog_node.context.refresh();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
try llvm_object.emit(.{
|
||||
.pre_ir_path = comp.verbose_llvm_ir,
|
||||
.pre_bc_path = comp.verbose_llvm_bc,
|
||||
.bin_path = try base.resolveEmitLoc(arena, .{
|
||||
.directory = null,
|
||||
.basename = base.zcu_object_sub_path.?,
|
||||
}),
|
||||
.asm_path = try base.resolveEmitLoc(arena, comp.emit_asm),
|
||||
.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,
|
||||
.time_report = comp.time_report,
|
||||
.sanitize_thread = comp.config.any_sanitize_thread,
|
||||
.lto = comp.config.lto,
|
||||
});
|
||||
return base.comp.emitLlvmObject(arena, base.emit, .{
|
||||
.directory = null,
|
||||
.basename = base.zcu_object_sub_path.?,
|
||||
}, llvm_object, prog_node);
|
||||
}
|
||||
|
||||
pub const C = @import("link/C.zig");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user