authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-28 16:42:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 19:49:08-07:00
logb8674910d45f0b87f82376abbd7a705ad77fe79a
treed4f5034d521dd0a54366860b7a1b0a862d877519
parent92cc2f41e6027a1e3bec7b3daa01da8dc90a9370

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.

3 files changed, 231 insertions(+), 169 deletions(-)

src/Compilation.zig+91-17
......@@ -39,6 +39,7 @@ const Zir = @import("Zir.zig");
3939const Autodoc = @import("Autodoc.zig");
4040const resinator = @import("resinator.zig");
4141const Builtin = @import("Builtin.zig");
42const LlvmObject = @import("codegen/llvm.zig").Object;
4243
4344pub const Config = @import("Compilation/Config.zig");
4445
......@@ -1434,6 +1435,7 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation {
14341435 .emit_h = emit_h,
14351436 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
14361437 .error_limit = error_limit,
1438 .llvm_object = null,
14371439 };
14381440 try zcu.init();
14391441 break :blk zcu;
......@@ -1683,6 +1685,17 @@ pub fn create(gpa: Allocator, options: CreateOptions) !*Compilation {
16831685 },
16841686 }
16851687
1688 // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.
1689 if (options.emit_bin == null and (comp.verbose_llvm_ir != null or
1690 comp.verbose_llvm_bc != null or
1691 (use_llvm and comp.emit_asm != null) or
1692 comp.emit_llvm_ir != null or
1693 comp.emit_llvm_bc != null))
1694 {
1695 if (build_options.only_c) unreachable;
1696 if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
1697 }
1698
16861699 comp.arena = arena_allocator;
16871700 break :comp comp;
16881701 };
......@@ -2016,6 +2029,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20162029 const tracy_trace = trace(@src());
20172030 defer tracy_trace.end();
20182031
2032 // This arena is scoped to this one update.
2033 const gpa = comp.gpa;
2034 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
2035 defer arena_allocator.deinit();
2036 const arena = arena_allocator.allocator();
2037
20192038 comp.clearMiscFailures();
20202039 comp.last_update_was_cache_hit = false;
20212040
......@@ -2034,7 +2053,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20342053
20352054 man = comp.cache_parent.obtain();
20362055 whole.cache_manifest = &man;
2037 try comp.addNonIncrementalStuffToCacheManifest(&man);
2056 try addNonIncrementalStuffToCacheManifest(comp, arena, &man);
20382057
20392058 const is_hit = man.hit() catch |err| {
20402059 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
20652084 tmp_dir_rand_int = std.crypto.random.int(u64);
20662085 const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int);
20672086
2068 const path = try comp.local_cache_directory.join(comp.gpa, &.{tmp_dir_sub_path});
2069 errdefer comp.gpa.free(path);
2087 const path = try comp.local_cache_directory.join(gpa, &.{tmp_dir_sub_path});
2088 errdefer gpa.free(path);
20702089
20712090 const handle = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
20722091 errdefer handle.close();
......@@ -2100,10 +2119,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21002119 .directory = tmp_artifact_directory,
21012120 .sub_path = std.fs.path.basename(sub_path),
21022121 };
2103 // It's a bit strange to use the Compilation arena allocator here
2104 // but in practice it won't leak much and usually whole cache mode
2105 // will be combined with exactly one call to update().
2106 const arena = comp.arena.allocator();
21072122 comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
21082123 }
21092124 },
......@@ -2127,7 +2142,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21272142 }
21282143
21292144 if (comp.module) |module| {
2130 module.compile_log_text.shrinkAndFree(module.gpa, 0);
2145 module.compile_log_text.shrinkAndFree(gpa, 0);
21312146 module.generation += 1;
21322147
21332148 // 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
21892204 comp.root_name,
21902205 @as(usize, @intFromPtr(module)),
21912206 });
2192 module.intern_pool.dumpGenericInstances(comp.gpa);
2207 module.intern_pool.dumpGenericInstances(gpa);
21932208 }
21942209
21952210 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
22222237 };
22232238 }
22242239
2225 if (comp.module) |module| {
2226 try link.File.C.flushEmitH(module);
2240 if (comp.module) |zcu| {
2241 try link.File.C.flushEmitH(zcu);
2242
2243 if (zcu.llvm_object) |llvm_object| {
2244 if (build_options.only_c) unreachable;
2245 const default_emit = switch (comp.cache_use) {
2246 .whole => |whole| .{
2247 .directory = whole.tmp_artifact_directory.?,
2248 .sub_path = "dummy",
2249 },
2250 .incremental => |incremental| .{
2251 .directory = incremental.artifact_directory,
2252 .sub_path = "dummy",
2253 },
2254 };
2255 try emitLlvmObject(comp, arena, default_emit, null, llvm_object, main_progress_node);
2256 }
22272257 }
22282258 }
22292259
......@@ -2238,7 +2268,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
22382268 // Close tmp dir and link.File to avoid open handle during rename.
22392269 if (whole.tmp_artifact_directory) |*tmp_directory| {
22402270 tmp_directory.handle.close();
2241 if (tmp_directory.path) |p| comp.gpa.free(p);
2271 if (tmp_directory.path) |p| gpa.free(p);
22422272 whole.tmp_artifact_directory = null;
22432273 } else unreachable;
22442274
......@@ -2389,13 +2419,13 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
23892419/// anything from the link cache manifest.
23902420pub const link_hash_implementation_version = 10;
23912421
2392fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
2422fn addNonIncrementalStuffToCacheManifest(
2423 comp: *Compilation,
2424 arena: Allocator,
2425 man: *Cache.Manifest,
2426) !void {
23932427 const gpa = comp.gpa;
23942428
2395 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
2396 defer arena_allocator.deinit();
2397 const arena = arena_allocator.allocator();
2398
23992429 comptime assert(link_hash_implementation_version == 10);
24002430
24012431 if (comp.module) |mod| {
......@@ -2568,6 +2598,50 @@ fn emitOthers(comp: *Compilation) void {
25682598 }
25692599}
25702600
2601pub fn emitLlvmObject(
2602 comp: *Compilation,
2603 arena: Allocator,
2604 default_emit: Emit,
2605 bin_emit_loc: ?EmitLoc,
2606 llvm_object: *LlvmObject,
2607 prog_node: *std.Progress.Node,
2608) !void {
2609 if (build_options.only_c) @compileError("unreachable");
2610
2611 var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
2612 sub_prog_node.activate();
2613 sub_prog_node.context.refresh();
2614 defer sub_prog_node.end();
2615
2616 try llvm_object.emit(.{
2617 .pre_ir_path = comp.verbose_llvm_ir,
2618 .pre_bc_path = comp.verbose_llvm_bc,
2619 .bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc),
2620 .asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm),
2621 .post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir),
2622 .post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc),
2623
2624 .is_debug = comp.root_mod.optimize_mode == .Debug,
2625 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
2626 .time_report = comp.time_report,
2627 .sanitize_thread = comp.config.any_sanitize_thread,
2628 .lto = comp.config.lto,
2629 });
2630}
2631
2632fn resolveEmitLoc(
2633 arena: Allocator,
2634 default_emit: Emit,
2635 opt_loc: ?EmitLoc,
2636) Allocator.Error!?[*:0]const u8 {
2637 const loc = opt_loc orelse return null;
2638 const slice = if (loc.directory) |directory|
2639 try directory.joinZ(arena, &.{loc.basename})
2640 else
2641 try default_emit.basenamePath(arena, loc.basename);
2642 return slice.ptr;
2643}
2644
25712645fn reportMultiModuleErrors(mod: *Module) !void {
25722646 // Some cases can give you a whole bunch of multi-module errors, which it's not helpful to
25732647 // print all of, so we'll cap the number of these to emit.
src/Module.zig+136-115
......@@ -37,6 +37,7 @@ const clang = @import("clang.zig");
3737const InternPool = @import("InternPool.zig");
3838const Alignment = InternPool.Alignment;
3939const BuiltinFn = std.zig.BuiltinFn;
40const LlvmObject = @import("codegen/llvm.zig").Object;
4041
4142comptime {
4243 @setEvalBranchQuota(4000);
......@@ -53,6 +54,10 @@ comptime {
5354/// General-purpose allocator. Used for both temporary and long-term storage.
5455gpa: Allocator,
5556comp: *Compilation,
57/// Usually, the LlvmObject is managed by linker code, however, in the case
58/// that -fno-emit-bin is specified, the linker code never executes, so we
59/// store the LlvmObject here.
60llvm_object: ?*LlvmObject,
5661
5762/// Pointer to externally managed resource.
5863root_mod: *Package.Module,
......@@ -2476,36 +2481,41 @@ pub fn init(mod: *Module) !void {
24762481 try mod.global_error_set.put(gpa, .empty, {});
24772482}
24782483
2479pub fn deinit(mod: *Module) void {
2480 const gpa = mod.gpa;
2484pub fn deinit(zcu: *Zcu) void {
2485 const gpa = zcu.gpa;
2486
2487 if (zcu.llvm_object) |llvm_object| {
2488 if (build_options.only_c) unreachable;
2489 llvm_object.deinit();
2490 }
24812491
2482 for (mod.import_table.keys()) |key| {
2492 for (zcu.import_table.keys()) |key| {
24832493 gpa.free(key);
24842494 }
2485 var failed_decls = mod.failed_decls;
2486 mod.failed_decls = .{};
2487 for (mod.import_table.values()) |value| {
2488 value.destroy(mod);
2495 var failed_decls = zcu.failed_decls;
2496 zcu.failed_decls = .{};
2497 for (zcu.import_table.values()) |value| {
2498 value.destroy(zcu);
24892499 }
2490 mod.import_table.deinit(gpa);
2500 zcu.import_table.deinit(gpa);
24912501
2492 for (mod.embed_table.keys(), mod.embed_table.values()) |path, embed_file| {
2502 for (zcu.embed_table.keys(), zcu.embed_table.values()) |path, embed_file| {
24932503 gpa.free(path);
24942504 gpa.destroy(embed_file);
24952505 }
2496 mod.embed_table.deinit(gpa);
2506 zcu.embed_table.deinit(gpa);
24972507
2498 mod.compile_log_text.deinit(gpa);
2508 zcu.compile_log_text.deinit(gpa);
24992509
2500 mod.local_zir_cache.handle.close();
2501 mod.global_zir_cache.handle.close();
2510 zcu.local_zir_cache.handle.close();
2511 zcu.global_zir_cache.handle.close();
25022512
25032513 for (failed_decls.values()) |value| {
25042514 value.destroy(gpa);
25052515 }
25062516 failed_decls.deinit(gpa);
25072517
2508 if (mod.emit_h) |emit_h| {
2518 if (zcu.emit_h) |emit_h| {
25092519 for (emit_h.failed_decls.values()) |value| {
25102520 value.destroy(gpa);
25112521 }
......@@ -2514,68 +2524,68 @@ pub fn deinit(mod: *Module) void {
25142524 emit_h.allocated_emit_h.deinit(gpa);
25152525 }
25162526
2517 for (mod.failed_files.values()) |value| {
2527 for (zcu.failed_files.values()) |value| {
25182528 if (value) |msg| msg.destroy(gpa);
25192529 }
2520 mod.failed_files.deinit(gpa);
2530 zcu.failed_files.deinit(gpa);
25212531
2522 for (mod.failed_embed_files.values()) |msg| {
2532 for (zcu.failed_embed_files.values()) |msg| {
25232533 msg.destroy(gpa);
25242534 }
2525 mod.failed_embed_files.deinit(gpa);
2535 zcu.failed_embed_files.deinit(gpa);
25262536
2527 for (mod.failed_exports.values()) |value| {
2537 for (zcu.failed_exports.values()) |value| {
25282538 value.destroy(gpa);
25292539 }
2530 mod.failed_exports.deinit(gpa);
2540 zcu.failed_exports.deinit(gpa);
25312541
2532 for (mod.cimport_errors.values()) |*errs| {
2542 for (zcu.cimport_errors.values()) |*errs| {
25332543 errs.deinit(gpa);
25342544 }
2535 mod.cimport_errors.deinit(gpa);
2545 zcu.cimport_errors.deinit(gpa);
25362546
2537 mod.compile_log_decls.deinit(gpa);
2547 zcu.compile_log_decls.deinit(gpa);
25382548
2539 for (mod.decl_exports.values()) |*export_list| {
2549 for (zcu.decl_exports.values()) |*export_list| {
25402550 export_list.deinit(gpa);
25412551 }
2542 mod.decl_exports.deinit(gpa);
2552 zcu.decl_exports.deinit(gpa);
25432553
2544 for (mod.value_exports.values()) |*export_list| {
2554 for (zcu.value_exports.values()) |*export_list| {
25452555 export_list.deinit(gpa);
25462556 }
2547 mod.value_exports.deinit(gpa);
2557 zcu.value_exports.deinit(gpa);
25482558
2549 for (mod.export_owners.values()) |*value| {
2559 for (zcu.export_owners.values()) |*value| {
25502560 freeExportList(gpa, value);
25512561 }
2552 mod.export_owners.deinit(gpa);
2562 zcu.export_owners.deinit(gpa);
25532563
2554 mod.global_error_set.deinit(gpa);
2564 zcu.global_error_set.deinit(gpa);
25552565
2556 mod.test_functions.deinit(gpa);
2566 zcu.test_functions.deinit(gpa);
25572567
2558 for (mod.global_assembly.values()) |s| {
2568 for (zcu.global_assembly.values()) |s| {
25592569 gpa.free(s);
25602570 }
2561 mod.global_assembly.deinit(gpa);
2571 zcu.global_assembly.deinit(gpa);
25622572
2563 mod.reference_table.deinit(gpa);
2573 zcu.reference_table.deinit(gpa);
25642574
25652575 {
2566 var it = mod.intern_pool.allocated_namespaces.iterator(0);
2576 var it = zcu.intern_pool.allocated_namespaces.iterator(0);
25672577 while (it.next()) |namespace| {
25682578 namespace.decls.deinit(gpa);
25692579 namespace.usingnamespace_set.deinit(gpa);
25702580 }
25712581 }
25722582
2573 mod.intern_pool.deinit(gpa);
2574 mod.tmp_hack_arena.deinit();
2583 zcu.intern_pool.deinit(gpa);
2584 zcu.tmp_hack_arena.deinit();
25752585
2576 mod.capture_scope_parents.deinit(gpa);
2577 mod.runtime_capture_scopes.deinit(gpa);
2578 mod.comptime_capture_scopes.deinit(gpa);
2586 zcu.capture_scope_parents.deinit(gpa);
2587 zcu.runtime_capture_scopes.deinit(gpa);
2588 zcu.comptime_capture_scopes.deinit(gpa);
25792589}
25802590
25812591pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
......@@ -3222,14 +3232,14 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
32223232 }
32233233}
32243234
3225pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
3235pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, func_index: InternPool.Index) SemaError!void {
32263236 const tracy = trace(@src());
32273237 defer tracy.end();
32283238
3229 const ip = &mod.intern_pool;
3230 const func = mod.funcInfo(func_index);
3239 const ip = &zcu.intern_pool;
3240 const func = zcu.funcInfo(func_index);
32313241 const decl_index = func.owner_decl;
3232 const decl = mod.declPtr(decl_index);
3242 const decl = zcu.declPtr(decl_index);
32333243
32343244 switch (decl.analysis) {
32353245 .unreferenced => unreachable,
......@@ -3253,13 +3263,13 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
32533263 .success => return,
32543264 }
32553265
3256 const gpa = mod.gpa;
3266 const gpa = zcu.gpa;
32573267
32583268 var tmp_arena = std.heap.ArenaAllocator.init(gpa);
32593269 defer tmp_arena.deinit();
32603270 const sema_arena = tmp_arena.allocator();
32613271
3262 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
3272 var air = zcu.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
32633273 error.AnalysisFail => {
32643274 if (func.analysis(ip).state == .in_progress) {
32653275 // 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
32733283 };
32743284 defer air.deinit(gpa);
32753285
3276 const comp = mod.comp;
3277
3278 const no_bin_file = (comp.bin_file == null and
3279 comp.emit_asm == null and
3280 comp.emit_llvm_ir == null and
3281 comp.emit_llvm_bc == null);
3286 const comp = zcu.comp;
32823287
32833288 const dump_air = builtin.mode == .Debug and comp.verbose_air;
32843289 const dump_llvm_ir = builtin.mode == .Debug and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
32853290
3286 if (no_bin_file and !dump_air and !dump_llvm_ir) return;
3291 if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {
3292 return;
3293 }
32873294
32883295 var liveness = try Liveness.analyze(gpa, air, ip);
32893296 defer liveness.deinit(gpa);
32903297
32913298 if (dump_air) {
3292 const fqn = try decl.getFullyQualifiedName(mod);
3299 const fqn = try decl.getFullyQualifiedName(zcu);
32933300 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
3294 @import("print_air.zig").dump(mod, air, liveness);
3301 @import("print_air.zig").dump(zcu, air, liveness);
32953302 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
32963303 }
32973304
......@@ -3307,12 +3314,12 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
33073314 verify.verify() catch |err| switch (err) {
33083315 error.OutOfMemory => return error.OutOfMemory,
33093316 else => {
3310 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
3311 mod.failed_decls.putAssumeCapacityNoClobber(
3317 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
3318 zcu.failed_decls.putAssumeCapacityNoClobber(
33123319 decl_index,
33133320 try Module.ErrorMsg.create(
33143321 gpa,
3315 decl.srcLoc(mod),
3322 decl.srcLoc(zcu),
33163323 "invalid liveness: {s}",
33173324 .{@errorName(err)},
33183325 ),
......@@ -3323,28 +3330,32 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaEr
33233330 };
33243331 }
33253332
3326 if (no_bin_file and !dump_llvm_ir) return;
3327
3328 const lf = comp.bin_file.?;
3329 lf.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) {
3330 error.OutOfMemory => return error.OutOfMemory,
3331 error.AnalysisFail => {
3332 decl.analysis = .codegen_failure;
3333 return;
3334 },
3335 else => {
3336 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
3337 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
3338 gpa,
3339 decl.srcLoc(mod),
3340 "unable to codegen: {s}",
3341 .{@errorName(err)},
3342 ));
3343 decl.analysis = .codegen_failure_retryable;
3344 return;
3345 },
3346 };
3347 return;
3333 if (comp.bin_file) |lf| {
3334 lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3335 error.OutOfMemory => return error.OutOfMemory,
3336 error.AnalysisFail => {
3337 decl.analysis = .codegen_failure;
3338 },
3339 else => {
3340 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
3341 zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
3342 gpa,
3343 decl.srcLoc(zcu),
3344 "unable to codegen: {s}",
3345 .{@errorName(err)},
3346 ));
3347 decl.analysis = .codegen_failure_retryable;
3348 },
3349 };
3350 } else if (zcu.llvm_object) |llvm_object| {
3351 if (build_options.only_c) unreachable;
3352 llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3353 error.OutOfMemory => return error.OutOfMemory,
3354 error.AnalysisFail => {
3355 decl.analysis = .codegen_failure;
3356 },
3357 };
3358 }
33483359 },
33493360 }
33503361}
......@@ -5235,44 +5246,57 @@ pub fn processExports(mod: *Module) !void {
52355246const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export);
52365247
52375248fn processExportsInner(
5238 mod: *Module,
5249 zcu: *Zcu,
52395250 symbol_exports: *SymbolExports,
52405251 exported: Exported,
52415252 exports: []const *Export,
52425253) error{OutOfMemory}!void {
5243 const gpa = mod.gpa;
5254 const gpa = zcu.gpa;
52445255
52455256 for (exports) |new_export| {
52465257 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);
52475258 if (gop.found_existing) {
52485259 new_export.status = .failed_retryable;
5249 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
5250 const src_loc = new_export.getSrcLoc(mod);
5260 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
5261 const src_loc = new_export.getSrcLoc(zcu);
52515262 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{
5252 new_export.opts.name.fmt(&mod.intern_pool),
5263 new_export.opts.name.fmt(&zcu.intern_pool),
52535264 });
52545265 errdefer msg.destroy(gpa);
52555266 const other_export = gop.value_ptr.*;
5256 const other_src_loc = other_export.getSrcLoc(mod);
5257 try mod.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
5258 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
5267 const other_src_loc = other_export.getSrcLoc(zcu);
5268 try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});
5269 zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
52595270 new_export.status = .failed;
52605271 } else {
52615272 gop.value_ptr.* = new_export;
52625273 }
52635274 }
5264 const lf = mod.comp.bin_file orelse return;
5265 lf.updateExports(mod, exported, exports) catch |err| switch (err) {
5275 if (zcu.comp.bin_file) |lf| {
5276 try handleUpdateExports(zcu, exports, lf.updateExports(zcu, exported, exports));
5277 } else if (zcu.llvm_object) |llvm_object| {
5278 if (build_options.only_c) unreachable;
5279 try handleUpdateExports(zcu, exports, llvm_object.updateExports(zcu, exported, exports));
5280 }
5281}
5282
5283fn handleUpdateExports(
5284 zcu: *Zcu,
5285 exports: []const *Export,
5286 result: link.File.UpdateExportsError!void,
5287) Allocator.Error!void {
5288 const gpa = zcu.gpa;
5289 result catch |err| switch (err) {
52665290 error.OutOfMemory => return error.OutOfMemory,
5267 else => {
5291 error.AnalysisFail => {
52685292 const new_export = exports[0];
52695293 new_export.status = .failed_retryable;
5270 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
5271 const src_loc = new_export.getSrcLoc(mod);
5294 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
5295 const src_loc = new_export.getSrcLoc(zcu);
52725296 const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{
52735297 @errorName(err),
52745298 });
5275 mod.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
5299 zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
52765300 },
52775301 };
52785302}
......@@ -5415,41 +5439,38 @@ pub fn populateTestFunctions(
54155439 try mod.linkerUpdateDecl(decl_index);
54165440}
54175441
5418pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
5419 const comp = mod.comp;
5442pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {
5443 const comp = zcu.comp;
54205444
54215445 if (comp.bin_file) |lf| {
5422 const decl = mod.declPtr(decl_index);
5423 lf.updateDecl(mod, decl_index) catch |err| switch (err) {
5446 lf.updateDecl(zcu, decl_index) catch |err| switch (err) {
54245447 error.OutOfMemory => return error.OutOfMemory,
54255448 error.AnalysisFail => {
5449 const decl = zcu.declPtr(decl_index);
54265450 decl.analysis = .codegen_failure;
5427 return;
54285451 },
54295452 else => {
5430 const gpa = mod.gpa;
5431 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
5432 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
5453 const decl = zcu.declPtr(decl_index);
5454 const gpa = zcu.gpa;
5455 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);
5456 zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
54335457 gpa,
5434 decl.srcLoc(mod),
5458 decl.srcLoc(zcu),
54355459 "unable to codegen: {s}",
54365460 .{@errorName(err)},
54375461 ));
54385462 decl.analysis = .codegen_failure_retryable;
5439 return;
54405463 },
54415464 };
5442 } else {
5443 const dump_llvm_ir = builtin.mode == .Debug and
5444 (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
5445
5446 if (comp.emit_asm != null or
5447 comp.emit_llvm_ir != null or
5448 comp.emit_llvm_bc != null or
5449 dump_llvm_ir)
5450 {
5451 @panic("TODO handle emit_asm, emit_llvm_ir, and emit_llvm_bc along with -fno-emit-bin");
5452 }
5465 } else if (zcu.llvm_object) |llvm_object| {
5466 if (build_options.only_c) unreachable;
5467 llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) {
5468 error.OutOfMemory => return error.OutOfMemory,
5469 error.AnalysisFail => {
5470 const decl = zcu.declPtr(decl_index);
5471 decl.analysis = .codegen_failure;
5472 },
5473 };
54535474 }
54545475}
54555476
src/link.zig+4-37
......@@ -984,49 +984,16 @@ pub const File = struct {
984984 return output_mode == .Lib and !self.isStatic();
985985 }
986986
987 pub fn resolveEmitLoc(
988 base: File,
989 arena: Allocator,
990 opt_loc: ?Compilation.EmitLoc,
991 ) Allocator.Error!?[*:0]const u8 {
992 const loc = opt_loc orelse return null;
993 const slice = if (loc.directory) |directory|
994 try directory.joinZ(arena, &.{loc.basename})
995 else
996 try base.emit.basenamePath(arena, loc.basename);
997 return slice.ptr;
998 }
999
1000987 pub fn emitLlvmObject(
1001988 base: File,
1002989 arena: Allocator,
1003990 llvm_object: *LlvmObject,
1004991 prog_node: *std.Progress.Node,
1005992 ) !void {
1006 const comp = base.comp;
1007
1008 var sub_prog_node = prog_node.start("LLVM Emit Object", 0);
1009 sub_prog_node.activate();
1010 sub_prog_node.context.refresh();
1011 defer sub_prog_node.end();
1012
1013 try llvm_object.emit(.{
1014 .pre_ir_path = comp.verbose_llvm_ir,
1015 .pre_bc_path = comp.verbose_llvm_bc,
1016 .bin_path = try base.resolveEmitLoc(arena, .{
1017 .directory = null,
1018 .basename = base.zcu_object_sub_path.?,
1019 }),
1020 .asm_path = try base.resolveEmitLoc(arena, comp.emit_asm),
1021 .post_ir_path = try base.resolveEmitLoc(arena, comp.emit_llvm_ir),
1022 .post_bc_path = try base.resolveEmitLoc(arena, comp.emit_llvm_bc),
1023
1024 .is_debug = comp.root_mod.optimize_mode == .Debug,
1025 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
1026 .time_report = comp.time_report,
1027 .sanitize_thread = comp.config.any_sanitize_thread,
1028 .lto = comp.config.lto,
1029 });
993 return base.comp.emitLlvmObject(arena, base.emit, .{
994 .directory = null,
995 .basename = base.zcu_object_sub_path.?,
996 }, llvm_object, prog_node);
1030997 }
1031998
1032999 pub const C = @import("link/C.zig");