| author | |
| committer | |
| log | 7e552dc1e9a8388f71cc32083deb9dd848e79808 |
| tree | b1c1086002c91be0e6c1195cc18966906a171ce3 |
| parent | bc8cd135987c7dc7419d034ba31178331d606cfa |
| signature |
This commit reworks our representation of exported Decls and values in
Zcu to be memory-optimized and trivially serialized.
All exports are now stored in the `all_exports` array on `Zcu`. An
`AnalUnit` which performs an export (either through an `export`
annotation or by containing an analyzed `@export`) gains an entry into
`single_exports` if it performs only one export, or `multi_exports` if
it performs multiple.
We no longer store a persistent mapping from a `Decl`/value to all
exports of that entity; this state is not necessary for the majority of
the pipeline. Instead, we construct it in `Zcu.processExports`, just
before flush. This does not affect the algorithmic complexity of
`processExports`, since this function already iterates all exports in
the `Zcu`.
The elimination of `decl_exports` and `value_exports` led to a few
non-trivial backend changes. The LLVM backend has been wrangled into a
more reasonable state in general regarding exports and externs. The C
backend is currently disabled in this commit, because its support for
`export` was quite broken, and that was exposed by this work -- I'm
hoping @jacobly0 will be able to pick this up!16 files changed, 498 insertions(+), 450 deletions(-)
src/Sema.zig+72-42| ... | @@ -117,6 +117,10 @@ maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAll | ... | @@ -117,6 +117,10 @@ maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAll |
| 117 | /// Backed by gpa. | 117 | /// Backed by gpa. |
| 118 | comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{}, | 118 | comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{}, |
| 119 | 119 | ||
| 120 | /// A list of exports performed by this analysis. After this `Sema` terminates, | ||
| 121 | /// these are flushed to `Zcu.single_exports` or `Zcu.multi_exports`. | ||
| 122 | exports: std.ArrayListUnmanaged(Zcu.Export) = .{}, | ||
| 123 | |||
| 120 | const MaybeComptimeAlloc = struct { | 124 | const MaybeComptimeAlloc = struct { |
| 121 | /// The runtime index of the `alloc` instruction. | 125 | /// The runtime index of the `alloc` instruction. |
| 122 | runtime_index: Value.RuntimeIndex, | 126 | runtime_index: Value.RuntimeIndex, |
| ... | @@ -186,6 +190,7 @@ const build_options = @import("build_options"); | ... | @@ -186,6 +190,7 @@ const build_options = @import("build_options"); |
| 186 | const Compilation = @import("Compilation.zig"); | 190 | const Compilation = @import("Compilation.zig"); |
| 187 | const InternPool = @import("InternPool.zig"); | 191 | const InternPool = @import("InternPool.zig"); |
| 188 | const Alignment = InternPool.Alignment; | 192 | const Alignment = InternPool.Alignment; |
| 193 | const AnalUnit = InternPool.AnalUnit; | ||
| 189 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; | 194 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; |
| 190 | 195 | ||
| 191 | pub const default_branch_quota = 1000; | 196 | pub const default_branch_quota = 1000; |
| ... | @@ -875,6 +880,7 @@ pub fn deinit(sema: *Sema) void { | ... | @@ -875,6 +880,7 @@ pub fn deinit(sema: *Sema) void { |
| 875 | sema.base_allocs.deinit(gpa); | 880 | sema.base_allocs.deinit(gpa); |
| 876 | sema.maybe_comptime_allocs.deinit(gpa); | 881 | sema.maybe_comptime_allocs.deinit(gpa); |
| 877 | sema.comptime_allocs.deinit(gpa); | 882 | sema.comptime_allocs.deinit(gpa); |
| 883 | sema.exports.deinit(gpa); | ||
| 878 | sema.* = undefined; | 884 | sema.* = undefined; |
| 879 | } | 885 | } |
| 880 | 886 | ||
| ... | @@ -2735,12 +2741,12 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool { | ... | @@ -2735,12 +2741,12 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool { |
| 2735 | if (!zcu.comp.debug_incremental) return false; | 2741 | if (!zcu.comp.debug_incremental) return false; |
| 2736 | 2742 | ||
| 2737 | const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu); | 2743 | const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu); |
| 2738 | const decl_as_depender = InternPool.AnalUnit.wrap(.{ .decl = decl_index }); | 2744 | const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index }); |
| 2739 | const was_outdated = zcu.outdated.swapRemove(decl_as_depender) or | 2745 | const was_outdated = zcu.outdated.swapRemove(decl_as_depender) or |
| 2740 | zcu.potentially_outdated.swapRemove(decl_as_depender); | 2746 | zcu.potentially_outdated.swapRemove(decl_as_depender); |
| 2741 | if (!was_outdated) return false; | 2747 | if (!was_outdated) return false; |
| 2742 | _ = zcu.outdated_ready.swapRemove(decl_as_depender); | 2748 | _ = zcu.outdated_ready.swapRemove(decl_as_depender); |
| 2743 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | 2749 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 2744 | zcu.intern_pool.remove(ty); | 2750 | zcu.intern_pool.remove(ty); |
| 2745 | zcu.declPtr(decl_index).analysis = .dependency_failure; | 2751 | zcu.declPtr(decl_index).analysis = .dependency_failure; |
| 2746 | try zcu.markDependeeOutdated(.{ .decl_val = decl_index }); | 2752 | try zcu.markDependeeOutdated(.{ .decl_val = decl_index }); |
| ... | @@ -2834,7 +2840,7 @@ fn zirStructDecl( | ... | @@ -2834,7 +2840,7 @@ fn zirStructDecl( |
| 2834 | if (sema.mod.comp.debug_incremental) { | 2840 | if (sema.mod.comp.debug_incremental) { |
| 2835 | try ip.addDependency( | 2841 | try ip.addDependency( |
| 2836 | sema.gpa, | 2842 | sema.gpa, |
| 2837 | InternPool.AnalUnit.wrap(.{ .decl = new_decl_index }), | 2843 | AnalUnit.wrap(.{ .decl = new_decl_index }), |
| 2838 | .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | 2844 | .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) }, |
| 2839 | ); | 2845 | ); |
| 2840 | } | 2846 | } |
| ... | @@ -3068,7 +3074,7 @@ fn zirEnumDecl( | ... | @@ -3068,7 +3074,7 @@ fn zirEnumDecl( |
| 3068 | if (sema.mod.comp.debug_incremental) { | 3074 | if (sema.mod.comp.debug_incremental) { |
| 3069 | try mod.intern_pool.addDependency( | 3075 | try mod.intern_pool.addDependency( |
| 3070 | sema.gpa, | 3076 | sema.gpa, |
| 3071 | InternPool.AnalUnit.wrap(.{ .decl = new_decl_index }), | 3077 | AnalUnit.wrap(.{ .decl = new_decl_index }), |
| 3072 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | 3078 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, |
| 3073 | ); | 3079 | ); |
| 3074 | } | 3080 | } |
| ... | @@ -3334,7 +3340,7 @@ fn zirUnionDecl( | ... | @@ -3334,7 +3340,7 @@ fn zirUnionDecl( |
| 3334 | if (sema.mod.comp.debug_incremental) { | 3340 | if (sema.mod.comp.debug_incremental) { |
| 3335 | try mod.intern_pool.addDependency( | 3341 | try mod.intern_pool.addDependency( |
| 3336 | sema.gpa, | 3342 | sema.gpa, |
| 3337 | InternPool.AnalUnit.wrap(.{ .decl = new_decl_index }), | 3343 | AnalUnit.wrap(.{ .decl = new_decl_index }), |
| 3338 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | 3344 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, |
| 3339 | ); | 3345 | ); |
| 3340 | } | 3346 | } |
| ... | @@ -3422,7 +3428,7 @@ fn zirOpaqueDecl( | ... | @@ -3422,7 +3428,7 @@ fn zirOpaqueDecl( |
| 3422 | if (sema.mod.comp.debug_incremental) { | 3428 | if (sema.mod.comp.debug_incremental) { |
| 3423 | try ip.addDependency( | 3429 | try ip.addDependency( |
| 3424 | gpa, | 3430 | gpa, |
| 3425 | InternPool.AnalUnit.wrap(.{ .decl = new_decl_index }), | 3431 | AnalUnit.wrap(.{ .decl = new_decl_index }), |
| 3426 | .{ .src_hash = try ip.trackZir(gpa, block.getFileScope(mod), inst) }, | 3432 | .{ .src_hash = try ip.trackZir(gpa, block.getFileScope(mod), inst) }, |
| 3427 | ); | 3433 | ); |
| 3428 | } | 3434 | } |
| ... | @@ -6423,10 +6429,9 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -6423,10 +6429,9 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 6423 | return sema.analyzeExport(block, src, options, decl_index); | 6429 | return sema.analyzeExport(block, src, options, decl_index); |
| 6424 | } | 6430 | } |
| 6425 | 6431 | ||
| 6426 | try addExport(mod, .{ | 6432 | try sema.exports.append(mod.gpa, .{ |
| 6427 | .opts = options, | 6433 | .opts = options, |
| 6428 | .src = src, | 6434 | .src = src, |
| 6429 | .owner_decl = sema.owner_decl_index, | ||
| 6430 | .exported = .{ .value = operand.toIntern() }, | 6435 | .exported = .{ .value = operand.toIntern() }, |
| 6431 | .status = .in_progress, | 6436 | .status = .in_progress, |
| 6432 | }); | 6437 | }); |
| ... | @@ -6469,46 +6474,14 @@ pub fn analyzeExport( | ... | @@ -6469,46 +6474,14 @@ pub fn analyzeExport( |
| 6469 | 6474 | ||
| 6470 | try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); | 6475 | try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); |
| 6471 | 6476 | ||
| 6472 | try addExport(mod, .{ | 6477 | try sema.exports.append(gpa, .{ |
| 6473 | .opts = options, | 6478 | .opts = options, |
| 6474 | .src = src, | 6479 | .src = src, |
| 6475 | .owner_decl = sema.owner_decl_index, | ||
| 6476 | .exported = .{ .decl_index = exported_decl_index }, | 6480 | .exported = .{ .decl_index = exported_decl_index }, |
| 6477 | .status = .in_progress, | 6481 | .status = .in_progress, |
| 6478 | }); | 6482 | }); |
| 6479 | } | 6483 | } |
| 6480 | 6484 | ||
| 6481 | fn addExport(mod: *Module, export_init: Module.Export) error{OutOfMemory}!void { | ||
| 6482 | const gpa = mod.gpa; | ||
| 6483 | |||
| 6484 | try mod.decl_exports.ensureUnusedCapacity(gpa, 1); | ||
| 6485 | try mod.value_exports.ensureUnusedCapacity(gpa, 1); | ||
| 6486 | try mod.export_owners.ensureUnusedCapacity(gpa, 1); | ||
| 6487 | |||
| 6488 | const new_export = try gpa.create(Module.Export); | ||
| 6489 | errdefer gpa.destroy(new_export); | ||
| 6490 | |||
| 6491 | new_export.* = export_init; | ||
| 6492 | |||
| 6493 | const eo_gop = mod.export_owners.getOrPutAssumeCapacity(export_init.owner_decl); | ||
| 6494 | if (!eo_gop.found_existing) eo_gop.value_ptr.* = .{}; | ||
| 6495 | try eo_gop.value_ptr.append(gpa, new_export); | ||
| 6496 | errdefer _ = eo_gop.value_ptr.pop(); | ||
| 6497 | |||
| 6498 | switch (export_init.exported) { | ||
| 6499 | .decl_index => |decl_index| { | ||
| 6500 | const de_gop = mod.decl_exports.getOrPutAssumeCapacity(decl_index); | ||
| 6501 | if (!de_gop.found_existing) de_gop.value_ptr.* = .{}; | ||
| 6502 | try de_gop.value_ptr.append(gpa, new_export); | ||
| 6503 | }, | ||
| 6504 | .value => |value| { | ||
| 6505 | const ve_gop = mod.value_exports.getOrPutAssumeCapacity(value); | ||
| 6506 | if (!ve_gop.found_existing) ve_gop.value_ptr.* = .{}; | ||
| 6507 | try ve_gop.value_ptr.append(gpa, new_export); | ||
| 6508 | }, | ||
| 6509 | } | ||
| 6510 | } | ||
| 6511 | |||
| 6512 | fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 6485 | fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { |
| 6513 | const mod = sema.mod; | 6486 | const mod = sema.mod; |
| 6514 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; | 6487 | const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; |
| ... | @@ -8411,6 +8384,9 @@ fn instantiateGenericCall( | ... | @@ -8411,6 +8384,9 @@ fn instantiateGenericCall( |
| 8411 | }); | 8384 | }); |
| 8412 | sema.appendRefsAssumeCapacity(runtime_args.items); | 8385 | sema.appendRefsAssumeCapacity(runtime_args.items); |
| 8413 | 8386 | ||
| 8387 | // `child_sema` is owned by us, so just take its exports. | ||
| 8388 | try sema.exports.appendSlice(sema.gpa, child_sema.exports.items); | ||
| 8389 | |||
| 8414 | if (ensure_result_used) { | 8390 | if (ensure_result_used) { |
| 8415 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); | 8391 | try sema.ensureResultUsed(block, sema.typeOf(result), call_src); |
| 8416 | } | 8392 | } |
| ... | @@ -35263,6 +35239,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co | ... | @@ -35263,6 +35239,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co |
| 35263 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); | 35239 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); |
| 35264 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); | 35240 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); |
| 35265 | } | 35241 | } |
| 35242 | |||
| 35243 | try sema.flushExports(); | ||
| 35266 | } | 35244 | } |
| 35267 | 35245 | ||
| 35268 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | 35246 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { |
| ... | @@ -36225,6 +36203,8 @@ fn semaStructFields( | ... | @@ -36225,6 +36203,8 @@ fn semaStructFields( |
| 36225 | 36203 | ||
| 36226 | struct_type.clearTypesWip(ip); | 36204 | struct_type.clearTypesWip(ip); |
| 36227 | if (!any_inits) struct_type.setHaveFieldInits(ip); | 36205 | if (!any_inits) struct_type.setHaveFieldInits(ip); |
| 36206 | |||
| 36207 | try sema.flushExports(); | ||
| 36228 | } | 36208 | } |
| 36229 | 36209 | ||
| 36230 | // This logic must be kept in sync with `semaStructFields` | 36210 | // This logic must be kept in sync with `semaStructFields` |
| ... | @@ -36365,6 +36345,8 @@ fn semaStructFieldInits( | ... | @@ -36365,6 +36345,8 @@ fn semaStructFieldInits( |
| 36365 | struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); | 36345 | struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); |
| 36366 | } | 36346 | } |
| 36367 | } | 36347 | } |
| 36348 | |||
| 36349 | try sema.flushExports(); | ||
| 36368 | } | 36350 | } |
| 36369 | 36351 | ||
| 36370 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { | 36352 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { |
| ... | @@ -36738,6 +36720,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded | ... | @@ -36738,6 +36720,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded |
| 36738 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl)); | 36720 | const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl)); |
| 36739 | union_type.tagTypePtr(ip).* = enum_ty; | 36721 | union_type.tagTypePtr(ip).* = enum_ty; |
| 36740 | } | 36722 | } |
| 36723 | |||
| 36724 | try sema.flushExports(); | ||
| 36741 | } | 36725 | } |
| 36742 | 36726 | ||
| 36743 | fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value { | 36727 | fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value { |
| ... | @@ -38362,7 +38346,7 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | ... | @@ -38362,7 +38346,7 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 38362 | return; | 38346 | return; |
| 38363 | } | 38347 | } |
| 38364 | 38348 | ||
| 38365 | const depender = InternPool.AnalUnit.wrap( | 38349 | const depender = AnalUnit.wrap( |
| 38366 | if (sema.owner_func_index != .none) | 38350 | if (sema.owner_func_index != .none) |
| 38367 | .{ .func = sema.owner_func_index } | 38351 | .{ .func = sema.owner_func_index } |
| 38368 | else | 38352 | else |
| ... | @@ -38494,6 +38478,52 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: | ... | @@ -38494,6 +38478,52 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: |
| 38494 | } | 38478 | } |
| 38495 | } | 38479 | } |
| 38496 | 38480 | ||
| 38481 | /// This should be called exactly once, at the end of a `Sema`'s lifetime. | ||
| 38482 | /// It takes the exports stored in `sema.export` and flushes them to the `Zcu` | ||
| 38483 | /// to be processed by the linker after the update. | ||
| 38484 | pub fn flushExports(sema: *Sema) !void { | ||
| 38485 | if (sema.exports.items.len == 0) return; | ||
| 38486 | |||
| 38487 | const zcu = sema.mod; | ||
| 38488 | const gpa = zcu.gpa; | ||
| 38489 | |||
| 38490 | const unit: AnalUnit = if (sema.owner_func_index != .none) | ||
| 38491 | AnalUnit.wrap(.{ .func = sema.owner_func_index }) | ||
| 38492 | else | ||
| 38493 | AnalUnit.wrap(.{ .decl = sema.owner_decl_index }); | ||
| 38494 | |||
| 38495 | // There may be existing exports. For instance, a struct may export | ||
| 38496 | // things during both field type resolution and field default resolution. | ||
| 38497 | // | ||
| 38498 | // So, pick up and delete any existing exports. This strategy performs | ||
| 38499 | // redundant work, but that's okay, because this case is exceedingly rare. | ||
| 38500 | if (zcu.single_exports.get(unit)) |export_idx| { | ||
| 38501 | try sema.exports.append(gpa, zcu.all_exports.items[export_idx]); | ||
| 38502 | } else if (zcu.multi_exports.get(unit)) |info| { | ||
| 38503 | try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]); | ||
| 38504 | } | ||
| 38505 | zcu.deleteUnitExports(unit); | ||
| 38506 | |||
| 38507 | // `sema.exports` is completed; store the data into the `Zcu`. | ||
| 38508 | if (sema.exports.items.len == 1) { | ||
| 38509 | try zcu.single_exports.ensureUnusedCapacity(gpa, 1); | ||
| 38510 | const export_idx = zcu.free_exports.popOrNull() orelse idx: { | ||
| 38511 | _ = try zcu.all_exports.addOne(gpa); | ||
| 38512 | break :idx zcu.all_exports.items.len - 1; | ||
| 38513 | }; | ||
| 38514 | zcu.all_exports.items[export_idx] = sema.exports.items[0]; | ||
| 38515 | zcu.single_exports.putAssumeCapacityNoClobber(unit, @intCast(export_idx)); | ||
| 38516 | } else { | ||
| 38517 | try zcu.multi_exports.ensureUnusedCapacity(gpa, 1); | ||
| 38518 | const exports_base = zcu.all_exports.items.len; | ||
| 38519 | try zcu.all_exports.appendSlice(gpa, sema.exports.items); | ||
| 38520 | zcu.multi_exports.putAssumeCapacityNoClobber(unit, .{ | ||
| 38521 | .index = @intCast(exports_base), | ||
| 38522 | .len = @intCast(sema.exports.items.len), | ||
| 38523 | }); | ||
| 38524 | } | ||
| 38525 | } | ||
| 38526 | |||
| 38497 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; | 38527 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; |
| 38498 | pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; | 38528 | pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; |
| 38499 | 38529 |
src/Zcu.zig+160-143| ... | @@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir; | ... | @@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir; |
| 35 | const clang = @import("clang.zig"); | 35 | const clang = @import("clang.zig"); |
| 36 | const InternPool = @import("InternPool.zig"); | 36 | const InternPool = @import("InternPool.zig"); |
| 37 | const Alignment = InternPool.Alignment; | 37 | const Alignment = InternPool.Alignment; |
| 38 | const AnalUnit = InternPool.AnalUnit; | ||
| 38 | const BuiltinFn = std.zig.BuiltinFn; | 39 | const BuiltinFn = std.zig.BuiltinFn; |
| 39 | const LlvmObject = @import("codegen/llvm.zig").Object; | 40 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 40 | 41 | ||
| ... | @@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined, | ... | @@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined, |
| 71 | global_zir_cache: Compilation.Directory, | 72 | global_zir_cache: Compilation.Directory, |
| 72 | /// Used by AstGen worker to load and store ZIR cache. | 73 | /// Used by AstGen worker to load and store ZIR cache. |
| 73 | local_zir_cache: Compilation.Directory, | 74 | local_zir_cache: Compilation.Directory, |
| 74 | /// It's rare for a decl to be exported, so we save memory by having a sparse | 75 | /// This is where all `Export` values are stored. Not all values here are necessarily valid exports; |
| 75 | /// map of Decl indexes to details about them being exported. | 76 | /// to enumerate all exports, `single_exports` and `multi_exports` must be consulted. |
| 76 | /// The Export memory is owned by the `export_owners` table; the slice itself | 77 | all_exports: ArrayListUnmanaged(Export) = .{}, |
| 77 | /// is owned by this table. The slice is guaranteed to not be empty. | 78 | /// This is a list of free indices in `all_exports`. These indices may be reused by exports from |
| 78 | decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{}, | 79 | /// future semantic analysis. |
| 79 | /// Same as `decl_exports` but for exported constant values. | 80 | free_exports: ArrayListUnmanaged(u32) = .{}, |
| 80 | value_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, ArrayListUnmanaged(*Export)) = .{}, | 81 | /// Maps from an `AnalUnit` which performs a single export, to the index into `all_exports` of |
| 81 | /// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl | 82 | /// the export it performs. Note that the key is not the `Decl` being exported, but the `AnalUnit` |
| 82 | /// is modified. Note that the key of this table is not the Decl being exported, but the Decl that | 83 | /// whose analysis triggered the export. |
| 83 | /// is performing the export of another Decl. | 84 | single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, |
| 84 | /// This table owns the Export memory. | 85 | /// Like `single_exports`, but for `AnalUnit`s which perform multiple exports. |
| 85 | export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{}, | 86 | /// The exports are `all_exports.items[index..][0..len]`. |
| 87 | multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { | ||
| 88 | index: u32, | ||
| 89 | len: u32, | ||
| 90 | }) = .{}, | ||
| 86 | /// The set of all the Zig source files in the Module. We keep track of this in order | 91 | /// The set of all the Zig source files in the Module. We keep track of this in order |
| 87 | /// to iterate over it and check which source files have been modified on the file system when | 92 | /// to iterate over it and check which source files have been modified on the file system when |
| 88 | /// an update is requested, as well as to cache `@import` results. | 93 | /// an update is requested, as well as to cache `@import` results. |
| ... | @@ -126,9 +131,8 @@ compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct { | ... | @@ -126,9 +131,8 @@ compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct { |
| 126 | failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, | 131 | failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, |
| 127 | /// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator. | 132 | /// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator. |
| 128 | failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{}, | 133 | failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{}, |
| 129 | /// Using a map here for consistency with the other fields here. | 134 | /// Key is index into `all_exports`. |
| 130 | /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator. | 135 | failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{}, |
| 131 | failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, | ||
| 132 | /// If a decl failed due to a cimport error, the corresponding Clang errors | 136 | /// If a decl failed due to a cimport error, the corresponding Clang errors |
| 133 | /// are stored here. | 137 | /// are stored here. |
| 134 | cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{}, | 138 | cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{}, |
| ... | @@ -140,14 +144,14 @@ global_error_set: GlobalErrorSet = .{}, | ... | @@ -140,14 +144,14 @@ global_error_set: GlobalErrorSet = .{}, |
| 140 | error_limit: ErrorInt, | 144 | error_limit: ErrorInt, |
| 141 | 145 | ||
| 142 | /// Value is the number of PO or outdated Decls which this AnalUnit depends on. | 146 | /// Value is the number of PO or outdated Decls which this AnalUnit depends on. |
| 143 | potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, u32) = .{}, | 147 | potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, |
| 144 | /// Value is the number of PO or outdated Decls which this AnalUnit depends on. | 148 | /// Value is the number of PO or outdated Decls which this AnalUnit depends on. |
| 145 | /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. | 149 | /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. |
| 146 | outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, u32) = .{}, | 150 | outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, |
| 147 | /// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0. | 151 | /// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0. |
| 148 | /// Such `AnalUnit`s are ready for immediate re-analysis. | 152 | /// Such `AnalUnit`s are ready for immediate re-analysis. |
| 149 | /// See `findOutdatedToAnalyze` for details. | 153 | /// See `findOutdatedToAnalyze` for details. |
| 150 | outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, void) = .{}, | 154 | outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, |
| 151 | /// This contains a set of Decls which may not be in `outdated`, but are the | 155 | /// This contains a set of Decls which may not be in `outdated`, but are the |
| 152 | /// root Decls of files which have updated source and thus must be re-analyzed. | 156 | /// root Decls of files which have updated source and thus must be re-analyzed. |
| 153 | /// If such a Decl is only in this set, the struct type index may be preserved | 157 | /// If such a Decl is only in this set, the struct type index may be preserved |
| ... | @@ -158,7 +162,7 @@ outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | ... | @@ -158,7 +162,7 @@ outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 158 | /// failure was something like running out of disk space, and trying again may | 162 | /// failure was something like running out of disk space, and trying again may |
| 159 | /// succeed. On the next update, we will flush this list, marking all members of | 163 | /// succeed. On the next update, we will flush this list, marking all members of |
| 160 | /// it as outdated. | 164 | /// it as outdated. |
| 161 | retryable_failures: std.ArrayListUnmanaged(InternPool.AnalUnit) = .{}, | 165 | retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .{}, |
| 162 | 166 | ||
| 163 | stage1_flags: packed struct { | 167 | stage1_flags: packed struct { |
| 164 | have_winmain: bool = false, | 168 | have_winmain: bool = false, |
| ... | @@ -267,8 +271,6 @@ pub const Exported = union(enum) { | ... | @@ -267,8 +271,6 @@ pub const Exported = union(enum) { |
| 267 | pub const Export = struct { | 271 | pub const Export = struct { |
| 268 | opts: Options, | 272 | opts: Options, |
| 269 | src: LazySrcLoc, | 273 | src: LazySrcLoc, |
| 270 | /// The Decl that performs the export. Note that this is *not* the Decl being exported. | ||
| 271 | owner_decl: Decl.Index, | ||
| 272 | exported: Exported, | 274 | exported: Exported, |
| 273 | status: enum { | 275 | status: enum { |
| 274 | in_progress, | 276 | in_progress, |
| ... | @@ -2507,20 +2509,10 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2507,20 +2509,10 @@ pub fn deinit(zcu: *Zcu) void { |
| 2507 | 2509 | ||
| 2508 | zcu.compile_log_decls.deinit(gpa); | 2510 | zcu.compile_log_decls.deinit(gpa); |
| 2509 | 2511 | ||
| 2510 | for (zcu.decl_exports.values()) |*export_list| { | 2512 | zcu.all_exports.deinit(gpa); |
| 2511 | export_list.deinit(gpa); | 2513 | zcu.free_exports.deinit(gpa); |
| 2512 | } | 2514 | zcu.single_exports.deinit(gpa); |
| 2513 | zcu.decl_exports.deinit(gpa); | 2515 | zcu.multi_exports.deinit(gpa); |
| 2514 | |||
| 2515 | for (zcu.value_exports.values()) |*export_list| { | ||
| 2516 | export_list.deinit(gpa); | ||
| 2517 | } | ||
| 2518 | zcu.value_exports.deinit(gpa); | ||
| 2519 | |||
| 2520 | for (zcu.export_owners.values()) |*value| { | ||
| 2521 | freeExportList(gpa, value); | ||
| 2522 | } | ||
| 2523 | zcu.export_owners.deinit(gpa); | ||
| 2524 | 2516 | ||
| 2525 | zcu.global_error_set.deinit(gpa); | 2517 | zcu.global_error_set.deinit(gpa); |
| 2526 | 2518 | ||
| ... | @@ -2590,11 +2582,6 @@ pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { | ... | @@ -2590,11 +2582,6 @@ pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { |
| 2590 | return decl_index == namespace.decl_index; | 2582 | return decl_index == namespace.decl_index; |
| 2591 | } | 2583 | } |
| 2592 | 2584 | ||
| 2593 | fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void { | ||
| 2594 | for (export_list.items) |exp| gpa.destroy(exp); | ||
| 2595 | export_list.deinit(gpa); | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | // TODO https://github.com/ziglang/zig/issues/8643 | 2585 | // TODO https://github.com/ziglang/zig/issues/8643 |
| 2599 | const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; | 2586 | const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; |
| 2600 | const HackDataLayout = extern struct { | 2587 | const HackDataLayout = extern struct { |
| ... | @@ -3139,7 +3126,7 @@ fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { | ... | @@ -3139,7 +3126,7 @@ fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { |
| 3139 | 3126 | ||
| 3140 | /// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may | 3127 | /// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may |
| 3141 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. | 3128 | /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. |
| 3142 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternPool.AnalUnit) !void { | 3129 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { |
| 3143 | var it = zcu.intern_pool.dependencyIterator(switch (maybe_outdated.unwrap()) { | 3130 | var it = zcu.intern_pool.dependencyIterator(switch (maybe_outdated.unwrap()) { |
| 3144 | .decl => |decl_index| .{ .decl_val = decl_index }, // TODO: also `decl_ref` deps when introduced | 3131 | .decl => |decl_index| .{ .decl_val = decl_index }, // TODO: also `decl_ref` deps when introduced |
| 3145 | .func => |func_index| .{ .func_ies = func_index }, | 3132 | .func => |func_index| .{ .func_ies = func_index }, |
| ... | @@ -3166,7 +3153,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternP | ... | @@ -3166,7 +3153,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternP |
| 3166 | } | 3153 | } |
| 3167 | } | 3154 | } |
| 3168 | 3155 | ||
| 3169 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalUnit { | 3156 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3170 | if (!zcu.comp.debug_incremental) return null; | 3157 | if (!zcu.comp.debug_incremental) return null; |
| 3171 | 3158 | ||
| 3172 | if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) { | 3159 | if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) { |
| ... | @@ -3197,7 +3184,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalUnit { | ... | @@ -3197,7 +3184,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalUnit { |
| 3197 | // `outdated`. This set will be small (number of files changed in this | 3184 | // `outdated`. This set will be small (number of files changed in this |
| 3198 | // update), so it's alright for us to just iterate here. | 3185 | // update), so it's alright for us to just iterate here. |
| 3199 | for (zcu.outdated_file_root.keys()) |file_decl| { | 3186 | for (zcu.outdated_file_root.keys()) |file_decl| { |
| 3200 | const decl_depender = InternPool.AnalUnit.wrap(.{ .decl = file_decl }); | 3187 | const decl_depender = AnalUnit.wrap(.{ .decl = file_decl }); |
| 3201 | if (zcu.outdated.contains(decl_depender)) { | 3188 | if (zcu.outdated.contains(decl_depender)) { |
| 3202 | // Since we didn't hit this in the first loop, this Decl must have | 3189 | // Since we didn't hit this in the first loop, this Decl must have |
| 3203 | // pending dependencies, so is ineligible. | 3190 | // pending dependencies, so is ineligible. |
| ... | @@ -3271,7 +3258,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalUnit { | ... | @@ -3271,7 +3258,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalUnit { |
| 3271 | chosen_decl_dependers, | 3258 | chosen_decl_dependers, |
| 3272 | }); | 3259 | }); |
| 3273 | 3260 | ||
| 3274 | return InternPool.AnalUnit.wrap(.{ .decl = chosen_decl_idx.? }); | 3261 | return AnalUnit.wrap(.{ .decl = chosen_decl_idx.? }); |
| 3275 | } | 3262 | } |
| 3276 | 3263 | ||
| 3277 | /// During an incremental update, before semantic analysis, call this to flush all values from | 3264 | /// During an incremental update, before semantic analysis, call this to flush all values from |
| ... | @@ -3456,7 +3443,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3456,7 +3443,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3456 | // which tries to limit re-analysis to Decls whose previously listed | 3443 | // which tries to limit re-analysis to Decls whose previously listed |
| 3457 | // dependencies are all up-to-date. | 3444 | // dependencies are all up-to-date. |
| 3458 | 3445 | ||
| 3459 | const decl_as_depender = InternPool.AnalUnit.wrap(.{ .decl = decl_index }); | 3446 | const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index }); |
| 3460 | const decl_was_outdated = mod.outdated.swapRemove(decl_as_depender) or | 3447 | const decl_was_outdated = mod.outdated.swapRemove(decl_as_depender) or |
| 3461 | mod.potentially_outdated.swapRemove(decl_as_depender); | 3448 | mod.potentially_outdated.swapRemove(decl_as_depender); |
| 3462 | 3449 | ||
| ... | @@ -3485,7 +3472,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3485,7 +3472,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3485 | // The exports this Decl performs will be re-discovered, so we remove them here | 3472 | // The exports this Decl performs will be re-discovered, so we remove them here |
| 3486 | // prior to re-analysis. | 3473 | // prior to re-analysis. |
| 3487 | if (build_options.only_c) unreachable; | 3474 | if (build_options.only_c) unreachable; |
| 3488 | try mod.deleteDeclExports(decl_index); | 3475 | mod.deleteUnitExports(AnalUnit.wrap(.{ .decl = decl_index })); |
| 3489 | } | 3476 | } |
| 3490 | 3477 | ||
| 3491 | const sema_result: SemaDeclResult = blk: { | 3478 | const sema_result: SemaDeclResult = blk: { |
| ... | @@ -3522,7 +3509,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { | ... | @@ -3522,7 +3509,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { |
| 3522 | else => |e| { | 3509 | else => |e| { |
| 3523 | decl.analysis = .sema_failure; | 3510 | decl.analysis = .sema_failure; |
| 3524 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); | 3511 | try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); |
| 3525 | try mod.retryable_failures.append(mod.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | 3512 | try mod.retryable_failures.append(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 3526 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( | 3513 | mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( |
| 3527 | mod.gpa, | 3514 | mod.gpa, |
| 3528 | decl.navSrcLoc(mod).upgrade(mod), | 3515 | decl.navSrcLoc(mod).upgrade(mod), |
| ... | @@ -3581,7 +3568,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In | ... | @@ -3581,7 +3568,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In |
| 3581 | // that's the case, we should remove this function from the binary. | 3568 | // that's the case, we should remove this function from the binary. |
| 3582 | if (decl.val.ip_index != func_index) { | 3569 | if (decl.val.ip_index != func_index) { |
| 3583 | try zcu.markDependeeOutdated(.{ .func_ies = func_index }); | 3570 | try zcu.markDependeeOutdated(.{ .func_ies = func_index }); |
| 3584 | ip.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); | 3571 | ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index })); |
| 3585 | ip.remove(func_index); | 3572 | ip.remove(func_index); |
| 3586 | @panic("TODO: remove orphaned function from binary"); | 3573 | @panic("TODO: remove orphaned function from binary"); |
| 3587 | } | 3574 | } |
| ... | @@ -3607,12 +3594,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In | ... | @@ -3607,12 +3594,14 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In |
| 3607 | .complete => {}, | 3594 | .complete => {}, |
| 3608 | } | 3595 | } |
| 3609 | 3596 | ||
| 3610 | const func_as_depender = InternPool.AnalUnit.wrap(.{ .func = func_index }); | 3597 | const func_as_depender = AnalUnit.wrap(.{ .func = func_index }); |
| 3611 | const was_outdated = zcu.outdated.swapRemove(func_as_depender) or | 3598 | const was_outdated = zcu.outdated.swapRemove(func_as_depender) or |
| 3612 | zcu.potentially_outdated.swapRemove(func_as_depender); | 3599 | zcu.potentially_outdated.swapRemove(func_as_depender); |
| 3613 | 3600 | ||
| 3614 | if (was_outdated) { | 3601 | if (was_outdated) { |
| 3602 | if (build_options.only_c) unreachable; | ||
| 3615 | _ = zcu.outdated_ready.swapRemove(func_as_depender); | 3603 | _ = zcu.outdated_ready.swapRemove(func_as_depender); |
| 3604 | zcu.deleteUnitExports(AnalUnit.wrap(.{ .func = func_index })); | ||
| 3616 | } | 3605 | } |
| 3617 | 3606 | ||
| 3618 | switch (func.analysis(ip).state) { | 3607 | switch (func.analysis(ip).state) { |
| ... | @@ -3728,16 +3717,13 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In | ... | @@ -3728,16 +3717,13 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In |
| 3728 | .{@errorName(err)}, | 3717 | .{@errorName(err)}, |
| 3729 | )); | 3718 | )); |
| 3730 | func.analysis(ip).state = .codegen_failure; | 3719 | func.analysis(ip).state = .codegen_failure; |
| 3731 | try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); | 3720 | try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index })); |
| 3732 | }, | 3721 | }, |
| 3733 | }; | 3722 | }; |
| 3734 | } else if (zcu.llvm_object) |llvm_object| { | 3723 | } else if (zcu.llvm_object) |llvm_object| { |
| 3735 | if (build_options.only_c) unreachable; | 3724 | if (build_options.only_c) unreachable; |
| 3736 | llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { | 3725 | llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) { |
| 3737 | error.OutOfMemory => return error.OutOfMemory, | 3726 | error.OutOfMemory => return error.OutOfMemory, |
| 3738 | error.AnalysisFail => { | ||
| 3739 | func.analysis(ip).state = .codegen_failure; | ||
| 3740 | }, | ||
| 3741 | }; | 3727 | }; |
| 3742 | } | 3728 | } |
| 3743 | } | 3729 | } |
| ... | @@ -3773,7 +3759,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) | ... | @@ -3773,7 +3759,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) |
| 3773 | 3759 | ||
| 3774 | assert(decl.has_tv); | 3760 | assert(decl.has_tv); |
| 3775 | 3761 | ||
| 3776 | const func_as_depender = InternPool.AnalUnit.wrap(.{ .func = func_index }); | 3762 | const func_as_depender = AnalUnit.wrap(.{ .func = func_index }); |
| 3777 | const is_outdated = mod.outdated.contains(func_as_depender) or | 3763 | const is_outdated = mod.outdated.contains(func_as_depender) or |
| 3778 | mod.potentially_outdated.contains(func_as_depender); | 3764 | mod.potentially_outdated.contains(func_as_depender); |
| 3779 | 3765 | ||
| ... | @@ -3857,7 +3843,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa | ... | @@ -3857,7 +3843,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa |
| 3857 | if (zcu.comp.debug_incremental) { | 3843 | if (zcu.comp.debug_incremental) { |
| 3858 | try ip.addDependency( | 3844 | try ip.addDependency( |
| 3859 | gpa, | 3845 | gpa, |
| 3860 | InternPool.AnalUnit.wrap(.{ .decl = decl_index }), | 3846 | AnalUnit.wrap(.{ .decl = decl_index }), |
| 3861 | .{ .src_hash = tracked_inst }, | 3847 | .{ .src_hash = tracked_inst }, |
| 3862 | ); | 3848 | ); |
| 3863 | } | 3849 | } |
| ... | @@ -3906,7 +3892,7 @@ fn semaFileUpdate(zcu: *Zcu, file: *File, type_outdated: bool) SemaError!bool { | ... | @@ -3906,7 +3892,7 @@ fn semaFileUpdate(zcu: *Zcu, file: *File, type_outdated: bool) SemaError!bool { |
| 3906 | 3892 | ||
| 3907 | if (type_outdated) { | 3893 | if (type_outdated) { |
| 3908 | // Invalidate the existing type, reusing the decl and namespace. | 3894 | // Invalidate the existing type, reusing the decl and namespace. |
| 3909 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = file.root_decl.unwrap().? })); | 3895 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = file.root_decl.unwrap().? })); |
| 3910 | zcu.intern_pool.remove(decl.val.toIntern()); | 3896 | zcu.intern_pool.remove(decl.val.toIntern()); |
| 3911 | decl.val = undefined; | 3897 | decl.val = undefined; |
| 3912 | _ = try zcu.getFileRootStruct(file.root_decl.unwrap().?, decl.src_namespace, file); | 3898 | _ = try zcu.getFileRootStruct(file.root_decl.unwrap().?, decl.src_namespace, file); |
| ... | @@ -4097,7 +4083,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { | ... | @@ -4097,7 +4083,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 4097 | break :ip_index .none; | 4083 | break :ip_index .none; |
| 4098 | }; | 4084 | }; |
| 4099 | 4085 | ||
| 4100 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | 4086 | mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 4101 | 4087 | ||
| 4102 | decl.analysis = .in_progress; | 4088 | decl.analysis = .in_progress; |
| 4103 | 4089 | ||
| ... | @@ -4293,6 +4279,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { | ... | @@ -4293,6 +4279,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { |
| 4293 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); | 4279 | try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index); |
| 4294 | } | 4280 | } |
| 4295 | 4281 | ||
| 4282 | try sema.flushExports(); | ||
| 4283 | |||
| 4296 | return result; | 4284 | return result; |
| 4297 | } | 4285 | } |
| 4298 | 4286 | ||
| ... | @@ -4323,7 +4311,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult { | ... | @@ -4323,7 +4311,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult { |
| 4323 | // with a new Decl. | 4311 | // with a new Decl. |
| 4324 | // | 4312 | // |
| 4325 | // Yes, this does mean that any type owner Decl has a constant value for its entire lifetime. | 4313 | // Yes, this does mean that any type owner Decl has a constant value for its entire lifetime. |
| 4326 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | 4314 | zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 4327 | zcu.intern_pool.remove(decl.val.toIntern()); | 4315 | zcu.intern_pool.remove(decl.val.toIntern()); |
| 4328 | decl.analysis = .dependency_failure; | 4316 | decl.analysis = .dependency_failure; |
| 4329 | return .{ | 4317 | return .{ |
| ... | @@ -4949,63 +4937,44 @@ pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!vo | ... | @@ -4949,63 +4937,44 @@ pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!vo |
| 4949 | } | 4937 | } |
| 4950 | } | 4938 | } |
| 4951 | 4939 | ||
| 4952 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of | 4940 | /// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of |
| 4953 | /// this Decl will cause them to be re-created (or not). | 4941 | /// this `AnalUnit` will cause them to be re-created (or not). |
| 4954 | fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { | 4942 | pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 4955 | var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value; | 4943 | const gpa = zcu.gpa; |
| 4956 | 4944 | ||
| 4957 | for (export_owners.items) |exp| { | 4945 | const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv| |
| 4958 | switch (exp.exported) { | 4946 | .{ kv.value, 1 } |
| 4959 | .decl_index => |exported_decl_index| { | 4947 | else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info| |
| 4960 | if (mod.decl_exports.getPtr(exported_decl_index)) |export_list| { | 4948 | .{ info.value.index, info.value.len } |
| 4961 | // Remove exports with owner_decl matching the regenerating decl. | 4949 | else |
| 4962 | const list = export_list.items; | 4950 | return; |
| 4963 | var i: usize = 0; | 4951 | |
| 4964 | var new_len = list.len; | 4952 | const exports = zcu.all_exports.items[exports_base..][0..exports_len]; |
| 4965 | while (i < new_len) { | 4953 | |
| 4966 | if (list[i].owner_decl == decl_index) { | 4954 | // In an only-c build, we're guaranteed to never use incremental compilation, so there are |
| 4967 | mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]); | 4955 | // guaranteed not to be any exports in the output file that need deleting (since we only call |
| 4968 | new_len -= 1; | 4956 | // `updateExports` on flush). |
| 4969 | } else { | 4957 | // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports |
| 4970 | i += 1; | 4958 | // within a single update. |
| 4971 | } | 4959 | if (!build_options.only_c) { |
| 4972 | } | 4960 | for (exports, exports_base..) |exp, export_idx| { |
| 4973 | export_list.shrinkAndFree(mod.gpa, new_len); | 4961 | if (zcu.comp.bin_file) |lf| { |
| 4974 | if (new_len == 0) { | 4962 | lf.deleteExport(exp.exported, exp.opts.name); |
| 4975 | assert(mod.decl_exports.swapRemove(exported_decl_index)); | 4963 | } |
| 4976 | } | 4964 | if (zcu.failed_exports.fetchSwapRemove(@intCast(export_idx))) |failed_kv| { |
| 4977 | } | 4965 | failed_kv.value.destroy(gpa); |
| 4978 | }, | 4966 | } |
| 4979 | .value => |value| { | ||
| 4980 | if (mod.value_exports.getPtr(value)) |export_list| { | ||
| 4981 | // Remove exports with owner_decl matching the regenerating decl. | ||
| 4982 | const list = export_list.items; | ||
| 4983 | var i: usize = 0; | ||
| 4984 | var new_len = list.len; | ||
| 4985 | while (i < new_len) { | ||
| 4986 | if (list[i].owner_decl == decl_index) { | ||
| 4987 | mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]); | ||
| 4988 | new_len -= 1; | ||
| 4989 | } else { | ||
| 4990 | i += 1; | ||
| 4991 | } | ||
| 4992 | } | ||
| 4993 | export_list.shrinkAndFree(mod.gpa, new_len); | ||
| 4994 | if (new_len == 0) { | ||
| 4995 | assert(mod.value_exports.swapRemove(value)); | ||
| 4996 | } | ||
| 4997 | } | ||
| 4998 | }, | ||
| 4999 | } | ||
| 5000 | if (mod.comp.bin_file) |lf| { | ||
| 5001 | try lf.deleteDeclExport(decl_index, exp.opts.name); | ||
| 5002 | } | ||
| 5003 | if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| { | ||
| 5004 | failed_kv.value.destroy(mod.gpa); | ||
| 5005 | } | 4967 | } |
| 5006 | mod.gpa.destroy(exp); | ||
| 5007 | } | 4968 | } |
| 5008 | export_owners.deinit(mod.gpa); | 4969 | |
| 4970 | zcu.free_exports.ensureUnusedCapacity(gpa, exports_len) catch { | ||
| 4971 | // This space will be reused eventually, so we need not propagate this error. | ||
| 4972 | // Just leak it for now, and let GC reclaim it later on. | ||
| 4973 | return; | ||
| 4974 | }; | ||
| 4975 | for (exports_base..exports_base + exports_len) |export_idx| { | ||
| 4976 | zcu.free_exports.appendAssumeCapacity(@intCast(export_idx)); | ||
| 4977 | } | ||
| 5009 | } | 4978 | } |
| 5010 | 4979 | ||
| 5011 | pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air { | 4980 | pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air { |
| ... | @@ -5026,7 +4995,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -5026,7 +4995,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 5026 | const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0); | 4995 | const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0); |
| 5027 | defer decl_prog_node.end(); | 4996 | defer decl_prog_node.end(); |
| 5028 | 4997 | ||
| 5029 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index })); | 4998 | mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index })); |
| 5030 | 4999 | ||
| 5031 | var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); | 5000 | var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa); |
| 5032 | defer comptime_err_ret_trace.deinit(); | 5001 | defer comptime_err_ret_trace.deinit(); |
| ... | @@ -5262,6 +5231,8 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato | ... | @@ -5262,6 +5231,8 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 5262 | }; | 5231 | }; |
| 5263 | } | 5232 | } |
| 5264 | 5233 | ||
| 5234 | try sema.flushExports(); | ||
| 5235 | |||
| 5265 | return .{ | 5236 | return .{ |
| 5266 | .instructions = sema.air_instructions.toOwnedSlice(), | 5237 | .instructions = sema.air_instructions.toOwnedSlice(), |
| 5267 | .extra = try sema.air_extra.toOwnedSlice(gpa), | 5238 | .extra = try sema.air_extra.toOwnedSlice(gpa), |
| ... | @@ -5392,33 +5363,89 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void { | ... | @@ -5392,33 +5363,89 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void { |
| 5392 | /// Called from `Compilation.update`, after everything is done, just before | 5363 | /// Called from `Compilation.update`, after everything is done, just before |
| 5393 | /// reporting compile errors. In this function we emit exported symbol collision | 5364 | /// reporting compile errors. In this function we emit exported symbol collision |
| 5394 | /// errors and communicate exported symbols to the linker backend. | 5365 | /// errors and communicate exported symbols to the linker backend. |
| 5395 | pub fn processExports(mod: *Module) !void { | 5366 | pub fn processExports(zcu: *Zcu) !void { |
| 5367 | const gpa = zcu.gpa; | ||
| 5368 | |||
| 5369 | // First, construct a mapping of every exported value and Decl to the indices of all its different exports. | ||
| 5370 | var decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(u32)) = .{}; | ||
| 5371 | var value_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, ArrayListUnmanaged(u32)) = .{}; | ||
| 5372 | defer { | ||
| 5373 | for (decl_exports.values()) |*exports| { | ||
| 5374 | exports.deinit(gpa); | ||
| 5375 | } | ||
| 5376 | decl_exports.deinit(gpa); | ||
| 5377 | for (value_exports.values()) |*exports| { | ||
| 5378 | exports.deinit(gpa); | ||
| 5379 | } | ||
| 5380 | value_exports.deinit(gpa); | ||
| 5381 | } | ||
| 5382 | |||
| 5383 | // We note as a heuristic: | ||
| 5384 | // * It is rare to export a value. | ||
| 5385 | // * It is rare for one Decl to be exported multiple times. | ||
| 5386 | // So, this ensureTotalCapacity serves as a reasonable (albeit very approximate) optimization. | ||
| 5387 | try decl_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count()); | ||
| 5388 | |||
| 5389 | for (zcu.single_exports.values()) |export_idx| { | ||
| 5390 | const exp = zcu.all_exports.items[export_idx]; | ||
| 5391 | const value_ptr, const found_existing = switch (exp.exported) { | ||
| 5392 | .decl_index => |i| gop: { | ||
| 5393 | const gop = try decl_exports.getOrPut(gpa, i); | ||
| 5394 | break :gop .{ gop.value_ptr, gop.found_existing }; | ||
| 5395 | }, | ||
| 5396 | .value => |i| gop: { | ||
| 5397 | const gop = try value_exports.getOrPut(gpa, i); | ||
| 5398 | break :gop .{ gop.value_ptr, gop.found_existing }; | ||
| 5399 | }, | ||
| 5400 | }; | ||
| 5401 | if (!found_existing) value_ptr.* = .{}; | ||
| 5402 | try value_ptr.append(gpa, export_idx); | ||
| 5403 | } | ||
| 5404 | |||
| 5405 | for (zcu.multi_exports.values()) |info| { | ||
| 5406 | for (zcu.all_exports.items[info.index..][0..info.len], info.index..) |exp, export_idx| { | ||
| 5407 | const value_ptr, const found_existing = switch (exp.exported) { | ||
| 5408 | .decl_index => |i| gop: { | ||
| 5409 | const gop = try decl_exports.getOrPut(gpa, i); | ||
| 5410 | break :gop .{ gop.value_ptr, gop.found_existing }; | ||
| 5411 | }, | ||
| 5412 | .value => |i| gop: { | ||
| 5413 | const gop = try value_exports.getOrPut(gpa, i); | ||
| 5414 | break :gop .{ gop.value_ptr, gop.found_existing }; | ||
| 5415 | }, | ||
| 5416 | }; | ||
| 5417 | if (!found_existing) value_ptr.* = .{}; | ||
| 5418 | try value_ptr.append(gpa, @intCast(export_idx)); | ||
| 5419 | } | ||
| 5420 | } | ||
| 5421 | |||
| 5396 | // Map symbol names to `Export` for name collision detection. | 5422 | // Map symbol names to `Export` for name collision detection. |
| 5397 | var symbol_exports: SymbolExports = .{}; | 5423 | var symbol_exports: SymbolExports = .{}; |
| 5398 | defer symbol_exports.deinit(mod.gpa); | 5424 | defer symbol_exports.deinit(gpa); |
| 5399 | 5425 | ||
| 5400 | for (mod.decl_exports.keys(), mod.decl_exports.values()) |exported_decl, exports_list| { | 5426 | for (decl_exports.keys(), decl_exports.values()) |exported_decl, exports_list| { |
| 5401 | const exported: Exported = .{ .decl_index = exported_decl }; | 5427 | const exported: Exported = .{ .decl_index = exported_decl }; |
| 5402 | try processExportsInner(mod, &symbol_exports, exported, exports_list.items); | 5428 | try processExportsInner(zcu, &symbol_exports, exported, exports_list.items); |
| 5403 | } | 5429 | } |
| 5404 | 5430 | ||
| 5405 | for (mod.value_exports.keys(), mod.value_exports.values()) |exported_value, exports_list| { | 5431 | for (value_exports.keys(), value_exports.values()) |exported_value, exports_list| { |
| 5406 | const exported: Exported = .{ .value = exported_value }; | 5432 | const exported: Exported = .{ .value = exported_value }; |
| 5407 | try processExportsInner(mod, &symbol_exports, exported, exports_list.items); | 5433 | try processExportsInner(zcu, &symbol_exports, exported, exports_list.items); |
| 5408 | } | 5434 | } |
| 5409 | } | 5435 | } |
| 5410 | 5436 | ||
| 5411 | const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export); | 5437 | const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, u32); |
| 5412 | 5438 | ||
| 5413 | fn processExportsInner( | 5439 | fn processExportsInner( |
| 5414 | zcu: *Zcu, | 5440 | zcu: *Zcu, |
| 5415 | symbol_exports: *SymbolExports, | 5441 | symbol_exports: *SymbolExports, |
| 5416 | exported: Exported, | 5442 | exported: Exported, |
| 5417 | exports: []const *Export, | 5443 | export_indices: []const u32, |
| 5418 | ) error{OutOfMemory}!void { | 5444 | ) error{OutOfMemory}!void { |
| 5419 | const gpa = zcu.gpa; | 5445 | const gpa = zcu.gpa; |
| 5420 | 5446 | ||
| 5421 | for (exports) |new_export| { | 5447 | for (export_indices) |export_idx| { |
| 5448 | const new_export = &zcu.all_exports.items[export_idx]; | ||
| 5422 | const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name); | 5449 | const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name); |
| 5423 | if (gop.found_existing) { | 5450 | if (gop.found_existing) { |
| 5424 | new_export.status = .failed_retryable; | 5451 | new_export.status = .failed_retryable; |
| ... | @@ -5428,40 +5455,41 @@ fn processExportsInner( | ... | @@ -5428,40 +5455,41 @@ fn processExportsInner( |
| 5428 | new_export.opts.name.fmt(&zcu.intern_pool), | 5455 | new_export.opts.name.fmt(&zcu.intern_pool), |
| 5429 | }); | 5456 | }); |
| 5430 | errdefer msg.destroy(gpa); | 5457 | errdefer msg.destroy(gpa); |
| 5431 | const other_export = gop.value_ptr.*; | 5458 | const other_export = zcu.all_exports.items[gop.value_ptr.*]; |
| 5432 | const other_src_loc = other_export.getSrcLoc(zcu); | 5459 | const other_src_loc = other_export.getSrcLoc(zcu); |
| 5433 | try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{}); | 5460 | try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{}); |
| 5434 | zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg); | 5461 | zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg); |
| 5435 | new_export.status = .failed; | 5462 | new_export.status = .failed; |
| 5436 | } else { | 5463 | } else { |
| 5437 | gop.value_ptr.* = new_export; | 5464 | gop.value_ptr.* = export_idx; |
| 5438 | } | 5465 | } |
| 5439 | } | 5466 | } |
| 5440 | if (zcu.comp.bin_file) |lf| { | 5467 | if (zcu.comp.bin_file) |lf| { |
| 5441 | try handleUpdateExports(zcu, exports, lf.updateExports(zcu, exported, exports)); | 5468 | try handleUpdateExports(zcu, export_indices, lf.updateExports(zcu, exported, export_indices)); |
| 5442 | } else if (zcu.llvm_object) |llvm_object| { | 5469 | } else if (zcu.llvm_object) |llvm_object| { |
| 5443 | if (build_options.only_c) unreachable; | 5470 | if (build_options.only_c) unreachable; |
| 5444 | try handleUpdateExports(zcu, exports, llvm_object.updateExports(zcu, exported, exports)); | 5471 | try handleUpdateExports(zcu, export_indices, llvm_object.updateExports(zcu, exported, export_indices)); |
| 5445 | } | 5472 | } |
| 5446 | } | 5473 | } |
| 5447 | 5474 | ||
| 5448 | fn handleUpdateExports( | 5475 | fn handleUpdateExports( |
| 5449 | zcu: *Zcu, | 5476 | zcu: *Zcu, |
| 5450 | exports: []const *Export, | 5477 | export_indices: []const u32, |
| 5451 | result: link.File.UpdateExportsError!void, | 5478 | result: link.File.UpdateExportsError!void, |
| 5452 | ) Allocator.Error!void { | 5479 | ) Allocator.Error!void { |
| 5453 | const gpa = zcu.gpa; | 5480 | const gpa = zcu.gpa; |
| 5454 | result catch |err| switch (err) { | 5481 | result catch |err| switch (err) { |
| 5455 | error.OutOfMemory => return error.OutOfMemory, | 5482 | error.OutOfMemory => return error.OutOfMemory, |
| 5456 | error.AnalysisFail => { | 5483 | error.AnalysisFail => { |
| 5457 | const new_export = exports[0]; | 5484 | const export_idx = export_indices[0]; |
| 5485 | const new_export = &zcu.all_exports.items[export_idx]; | ||
| 5458 | new_export.status = .failed_retryable; | 5486 | new_export.status = .failed_retryable; |
| 5459 | try zcu.failed_exports.ensureUnusedCapacity(gpa, 1); | 5487 | try zcu.failed_exports.ensureUnusedCapacity(gpa, 1); |
| 5460 | const src_loc = new_export.getSrcLoc(zcu); | 5488 | const src_loc = new_export.getSrcLoc(zcu); |
| 5461 | const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{ | 5489 | const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{ |
| 5462 | @errorName(err), | 5490 | @errorName(err), |
| 5463 | }); | 5491 | }); |
| 5464 | zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg); | 5492 | zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg); |
| 5465 | }, | 5493 | }, |
| 5466 | }; | 5494 | }; |
| 5467 | } | 5495 | } |
| ... | @@ -5627,16 +5655,13 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { | ... | @@ -5627,16 +5655,13 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void { |
| 5627 | .{@errorName(err)}, | 5655 | .{@errorName(err)}, |
| 5628 | )); | 5656 | )); |
| 5629 | decl.analysis = .codegen_failure; | 5657 | decl.analysis = .codegen_failure; |
| 5630 | try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index })); | 5658 | try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 5631 | }, | 5659 | }, |
| 5632 | }; | 5660 | }; |
| 5633 | } else if (zcu.llvm_object) |llvm_object| { | 5661 | } else if (zcu.llvm_object) |llvm_object| { |
| 5634 | if (build_options.only_c) unreachable; | 5662 | if (build_options.only_c) unreachable; |
| 5635 | llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) { | 5663 | llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) { |
| 5636 | error.OutOfMemory => return error.OutOfMemory, | 5664 | error.OutOfMemory => return error.OutOfMemory, |
| 5637 | error.AnalysisFail => { | ||
| 5638 | decl.analysis = .codegen_failure; | ||
| 5639 | }, | ||
| 5640 | }; | 5665 | }; |
| 5641 | } | 5666 | } |
| 5642 | } | 5667 | } |
| ... | @@ -5684,14 +5709,6 @@ pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u | ... | @@ -5684,14 +5709,6 @@ pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u |
| 5684 | } | 5709 | } |
| 5685 | } | 5710 | } |
| 5686 | 5711 | ||
| 5687 | pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export { | ||
| 5688 | if (mod.decl_exports.get(decl_index)) |l| { | ||
| 5689 | return l.items; | ||
| 5690 | } else { | ||
| 5691 | return &[0]*Export{}; | ||
| 5692 | } | ||
| 5693 | } | ||
| 5694 | |||
| 5695 | pub const Feature = enum { | 5712 | pub const Feature = enum { |
| 5696 | panic_fn, | 5713 | panic_fn, |
| 5697 | panic_unwrap_error, | 5714 | panic_unwrap_error, |
src/codegen/c.zig+2| ... | @@ -3081,6 +3081,8 @@ pub fn genDeclValue( | ... | @@ -3081,6 +3081,8 @@ pub fn genDeclValue( |
| 3081 | } | 3081 | } |
| 3082 | 3082 | ||
| 3083 | pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | 3083 | pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 3084 | if (true) @panic("TODO jacobly"); | ||
| 3085 | |||
| 3084 | const tracy = trace(@src()); | 3086 | const tracy = trace(@src()); |
| 3085 | defer tracy.end(); | 3087 | defer tracy.end(); |
| 3086 | 3088 |
src/codegen/llvm.zig+109-154| ... | @@ -848,10 +848,6 @@ pub const Object = struct { | ... | @@ -848,10 +848,6 @@ pub const Object = struct { |
| 848 | /// Note that the values are not added until `emit`, when all errors in | 848 | /// Note that the values are not added until `emit`, when all errors in |
| 849 | /// the compilation are known. | 849 | /// the compilation are known. |
| 850 | error_name_table: Builder.Variable.Index, | 850 | error_name_table: Builder.Variable.Index, |
| 851 | /// This map is usually very close to empty. It tracks only the cases when a | ||
| 852 | /// second extern Decl could not be emitted with the correct name due to a | ||
| 853 | /// name collision. | ||
| 854 | extern_collisions: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, void), | ||
| 855 | 851 | ||
| 856 | /// Memoizes a null `?usize` value. | 852 | /// Memoizes a null `?usize` value. |
| 857 | null_opt_usize: Builder.Constant, | 853 | null_opt_usize: Builder.Constant, |
| ... | @@ -1011,7 +1007,6 @@ pub const Object = struct { | ... | @@ -1011,7 +1007,6 @@ pub const Object = struct { |
| 1011 | .named_enum_map = .{}, | 1007 | .named_enum_map = .{}, |
| 1012 | .type_map = .{}, | 1008 | .type_map = .{}, |
| 1013 | .error_name_table = .none, | 1009 | .error_name_table = .none, |
| 1014 | .extern_collisions = .{}, | ||
| 1015 | .null_opt_usize = .no_init, | 1010 | .null_opt_usize = .no_init, |
| 1016 | .struct_field_map = .{}, | 1011 | .struct_field_map = .{}, |
| 1017 | }; | 1012 | }; |
| ... | @@ -1029,7 +1024,6 @@ pub const Object = struct { | ... | @@ -1029,7 +1024,6 @@ pub const Object = struct { |
| 1029 | self.anon_decl_map.deinit(gpa); | 1024 | self.anon_decl_map.deinit(gpa); |
| 1030 | self.named_enum_map.deinit(gpa); | 1025 | self.named_enum_map.deinit(gpa); |
| 1031 | self.type_map.deinit(gpa); | 1026 | self.type_map.deinit(gpa); |
| 1032 | self.extern_collisions.deinit(gpa); | ||
| 1033 | self.builder.deinit(); | 1027 | self.builder.deinit(); |
| 1034 | self.struct_field_map.deinit(gpa); | 1028 | self.struct_field_map.deinit(gpa); |
| 1035 | self.* = undefined; | 1029 | self.* = undefined; |
| ... | @@ -1121,61 +1115,6 @@ pub const Object = struct { | ... | @@ -1121,61 +1115,6 @@ pub const Object = struct { |
| 1121 | try object.builder.finishModuleAsm(); | 1115 | try object.builder.finishModuleAsm(); |
| 1122 | } | 1116 | } |
| 1123 | 1117 | ||
| 1124 | fn resolveExportExternCollisions(object: *Object) !void { | ||
| 1125 | const mod = object.module; | ||
| 1126 | |||
| 1127 | // This map has externs with incorrect symbol names. | ||
| 1128 | for (object.extern_collisions.keys()) |decl_index| { | ||
| 1129 | const global = object.decl_map.get(decl_index) orelse continue; | ||
| 1130 | // Same logic as below but for externs instead of exports. | ||
| 1131 | const decl_name = object.builder.strtabStringIfExists(mod.declPtr(decl_index).name.toSlice(&mod.intern_pool)) orelse continue; | ||
| 1132 | const other_global = object.builder.getGlobal(decl_name) orelse continue; | ||
| 1133 | if (other_global.toConst().getBase(&object.builder) == | ||
| 1134 | global.toConst().getBase(&object.builder)) continue; | ||
| 1135 | |||
| 1136 | try global.replace(other_global, &object.builder); | ||
| 1137 | } | ||
| 1138 | object.extern_collisions.clearRetainingCapacity(); | ||
| 1139 | |||
| 1140 | for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| { | ||
| 1141 | const global = object.decl_map.get(decl_index) orelse continue; | ||
| 1142 | try resolveGlobalCollisions(object, global, export_list.items); | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | for (mod.value_exports.keys(), mod.value_exports.values()) |val, export_list| { | ||
| 1146 | const global = object.anon_decl_map.get(val) orelse continue; | ||
| 1147 | try resolveGlobalCollisions(object, global, export_list.items); | ||
| 1148 | } | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | fn resolveGlobalCollisions( | ||
| 1152 | object: *Object, | ||
| 1153 | global: Builder.Global.Index, | ||
| 1154 | export_list: []const *Module.Export, | ||
| 1155 | ) !void { | ||
| 1156 | const mod = object.module; | ||
| 1157 | const global_base = global.toConst().getBase(&object.builder); | ||
| 1158 | for (export_list) |exp| { | ||
| 1159 | // Detect if the LLVM global has already been created as an extern. In such | ||
| 1160 | // case, we need to replace all uses of it with this exported global. | ||
| 1161 | const exp_name = object.builder.strtabStringIfExists(exp.opts.name.toSlice(&mod.intern_pool)) orelse continue; | ||
| 1162 | |||
| 1163 | const other_global = object.builder.getGlobal(exp_name) orelse continue; | ||
| 1164 | if (other_global.toConst().getBase(&object.builder) == global_base) continue; | ||
| 1165 | |||
| 1166 | try global.takeName(other_global, &object.builder); | ||
| 1167 | try other_global.replace(global, &object.builder); | ||
| 1168 | // Problem: now we need to replace in the decl_map that | ||
| 1169 | // the extern decl index points to this new global. However we don't | ||
| 1170 | // know the decl index. | ||
| 1171 | // Even if we did, a future incremental update to the extern would then | ||
| 1172 | // treat the LLVM global as an extern rather than an export, so it would | ||
| 1173 | // need a way to check that. | ||
| 1174 | // This is a TODO that needs to be solved when making | ||
| 1175 | // the LLVM backend support incremental compilation. | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | pub const EmitOptions = struct { | 1118 | pub const EmitOptions = struct { |
| 1180 | pre_ir_path: ?[]const u8, | 1119 | pre_ir_path: ?[]const u8, |
| 1181 | pre_bc_path: ?[]const u8, | 1120 | pre_bc_path: ?[]const u8, |
| ... | @@ -1193,7 +1132,6 @@ pub const Object = struct { | ... | @@ -1193,7 +1132,6 @@ pub const Object = struct { |
| 1193 | 1132 | ||
| 1194 | pub fn emit(self: *Object, options: EmitOptions) !void { | 1133 | pub fn emit(self: *Object, options: EmitOptions) !void { |
| 1195 | { | 1134 | { |
| 1196 | try self.resolveExportExternCollisions(); | ||
| 1197 | try self.genErrorNameTable(); | 1135 | try self.genErrorNameTable(); |
| 1198 | try self.genCmpLtErrorsLenFunction(); | 1136 | try self.genCmpLtErrorsLenFunction(); |
| 1199 | try self.genModuleLevelAssembly(); | 1137 | try self.genModuleLevelAssembly(); |
| ... | @@ -1698,8 +1636,7 @@ pub const Object = struct { | ... | @@ -1698,8 +1636,7 @@ pub const Object = struct { |
| 1698 | const file = try o.getDebugFile(namespace.file_scope); | 1636 | const file = try o.getDebugFile(namespace.file_scope); |
| 1699 | 1637 | ||
| 1700 | const line_number = decl.navSrcLine(zcu) + 1; | 1638 | const line_number = decl.navSrcLine(zcu) + 1; |
| 1701 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null and | 1639 | const is_internal_linkage = decl.val.getExternFunc(zcu) == null; |
| 1702 | !zcu.decl_exports.contains(decl_index); | ||
| 1703 | const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu)); | 1640 | const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu)); |
| 1704 | 1641 | ||
| 1705 | const subprogram = try o.builder.debugSubprogram( | 1642 | const subprogram = try o.builder.debugSubprogram( |
| ... | @@ -1760,8 +1697,6 @@ pub const Object = struct { | ... | @@ -1760,8 +1697,6 @@ pub const Object = struct { |
| 1760 | }; | 1697 | }; |
| 1761 | 1698 | ||
| 1762 | try fg.wip.finish(); | 1699 | try fg.wip.finish(); |
| 1763 | |||
| 1764 | try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index)); | ||
| 1765 | } | 1700 | } |
| 1766 | 1701 | ||
| 1767 | pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { | 1702 | pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void { |
| ... | @@ -1781,66 +1716,25 @@ pub const Object = struct { | ... | @@ -1781,66 +1716,25 @@ pub const Object = struct { |
| 1781 | }, | 1716 | }, |
| 1782 | else => |e| return e, | 1717 | else => |e| return e, |
| 1783 | }; | 1718 | }; |
| 1784 | try self.updateExports(module, .{ .decl_index = decl_index }, module.getDeclExports(decl_index)); | ||
| 1785 | } | 1719 | } |
| 1786 | 1720 | ||
| 1787 | pub fn updateExports( | 1721 | pub fn updateExports( |
| 1788 | self: *Object, | 1722 | self: *Object, |
| 1789 | mod: *Module, | 1723 | mod: *Module, |
| 1790 | exported: Module.Exported, | 1724 | exported: Module.Exported, |
| 1791 | exports: []const *Module.Export, | 1725 | export_indices: []const u32, |
| 1792 | ) link.File.UpdateExportsError!void { | 1726 | ) link.File.UpdateExportsError!void { |
| 1793 | const decl_index = switch (exported) { | 1727 | const decl_index = switch (exported) { |
| 1794 | .decl_index => |i| i, | 1728 | .decl_index => |i| i, |
| 1795 | .value => |val| return updateExportedValue(self, mod, val, exports), | 1729 | .value => |val| return updateExportedValue(self, mod, val, export_indices), |
| 1796 | }; | 1730 | }; |
| 1797 | const gpa = mod.gpa; | ||
| 1798 | const ip = &mod.intern_pool; | 1731 | const ip = &mod.intern_pool; |
| 1799 | // If the module does not already have the function, we ignore this function call | 1732 | const global_index = self.decl_map.get(decl_index).?; |
| 1800 | // because we call `updateExports` at the end of `updateFunc` and `updateDecl`. | ||
| 1801 | const global_index = self.decl_map.get(decl_index) orelse return; | ||
| 1802 | const decl = mod.declPtr(decl_index); | 1733 | const decl = mod.declPtr(decl_index); |
| 1803 | const comp = mod.comp; | 1734 | const comp = mod.comp; |
| 1804 | if (decl.isExtern(mod)) { | ||
| 1805 | const decl_name = decl_name: { | ||
| 1806 | if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) { | ||
| 1807 | if (decl.getOwnedExternFunc(mod).?.lib_name.toSlice(ip)) |lib_name| { | ||
| 1808 | if (!std.mem.eql(u8, lib_name, "c")) { | ||
| 1809 | break :decl_name try self.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name }); | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | } | ||
| 1813 | break :decl_name try self.builder.strtabString(decl.name.toSlice(ip)); | ||
| 1814 | }; | ||
| 1815 | 1735 | ||
| 1816 | if (self.builder.getGlobal(decl_name)) |other_global| { | 1736 | if (export_indices.len != 0) { |
| 1817 | if (other_global != global_index) { | 1737 | return updateExportedGlobal(self, mod, global_index, export_indices); |
| 1818 | try self.extern_collisions.put(gpa, decl_index, {}); | ||
| 1819 | } | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | try global_index.rename(decl_name, &self.builder); | ||
| 1823 | global_index.setLinkage(.external, &self.builder); | ||
| 1824 | global_index.setUnnamedAddr(.default, &self.builder); | ||
| 1825 | if (comp.config.dll_export_fns) | ||
| 1826 | global_index.setDllStorageClass(.default, &self.builder); | ||
| 1827 | |||
| 1828 | if (decl.val.getVariable(mod)) |decl_var| { | ||
| 1829 | global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( | ||
| 1830 | if (decl_var.is_threadlocal) .generaldynamic else .default, | ||
| 1831 | &self.builder, | ||
| 1832 | ); | ||
| 1833 | if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder); | ||
| 1834 | } | ||
| 1835 | } else if (exports.len != 0) { | ||
| 1836 | const main_exp_name = try self.builder.strtabString(exports[0].opts.name.toSlice(ip)); | ||
| 1837 | try global_index.rename(main_exp_name, &self.builder); | ||
| 1838 | |||
| 1839 | if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal) | ||
| 1840 | global_index.ptrConst(&self.builder).kind | ||
| 1841 | .variable.setThreadLocal(.generaldynamic, &self.builder); | ||
| 1842 | |||
| 1843 | return updateExportedGlobal(self, mod, global_index, exports); | ||
| 1844 | } else { | 1738 | } else { |
| 1845 | const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip)); | 1739 | const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip)); |
| 1846 | try global_index.rename(fqn, &self.builder); | 1740 | try global_index.rename(fqn, &self.builder); |
| ... | @@ -1848,17 +1742,6 @@ pub const Object = struct { | ... | @@ -1848,17 +1742,6 @@ pub const Object = struct { |
| 1848 | if (comp.config.dll_export_fns) | 1742 | if (comp.config.dll_export_fns) |
| 1849 | global_index.setDllStorageClass(.default, &self.builder); | 1743 | global_index.setDllStorageClass(.default, &self.builder); |
| 1850 | global_index.setUnnamedAddr(.unnamed_addr, &self.builder); | 1744 | global_index.setUnnamedAddr(.unnamed_addr, &self.builder); |
| 1851 | if (decl.val.getVariable(mod)) |decl_var| { | ||
| 1852 | const decl_namespace = mod.namespacePtr(decl.src_namespace); | ||
| 1853 | const single_threaded = decl_namespace.file_scope.mod.single_threaded; | ||
| 1854 | global_index.ptrConst(&self.builder).kind.variable.setThreadLocal( | ||
| 1855 | if (decl_var.is_threadlocal and !single_threaded) | ||
| 1856 | .generaldynamic | ||
| 1857 | else | ||
| 1858 | .default, | ||
| 1859 | &self.builder, | ||
| 1860 | ); | ||
| 1861 | } | ||
| 1862 | } | 1745 | } |
| 1863 | } | 1746 | } |
| 1864 | 1747 | ||
| ... | @@ -1866,11 +1749,11 @@ pub const Object = struct { | ... | @@ -1866,11 +1749,11 @@ pub const Object = struct { |
| 1866 | o: *Object, | 1749 | o: *Object, |
| 1867 | mod: *Module, | 1750 | mod: *Module, |
| 1868 | exported_value: InternPool.Index, | 1751 | exported_value: InternPool.Index, |
| 1869 | exports: []const *Module.Export, | 1752 | export_indices: []const u32, |
| 1870 | ) link.File.UpdateExportsError!void { | 1753 | ) link.File.UpdateExportsError!void { |
| 1871 | const gpa = mod.gpa; | 1754 | const gpa = mod.gpa; |
| 1872 | const ip = &mod.intern_pool; | 1755 | const ip = &mod.intern_pool; |
| 1873 | const main_exp_name = try o.builder.strtabString(exports[0].opts.name.toSlice(ip)); | 1756 | const main_exp_name = try o.builder.strtabString(mod.all_exports.items[export_indices[0]].opts.name.toSlice(ip)); |
| 1874 | const global_index = i: { | 1757 | const global_index = i: { |
| 1875 | const gop = try o.anon_decl_map.getOrPut(gpa, exported_value); | 1758 | const gop = try o.anon_decl_map.getOrPut(gpa, exported_value); |
| 1876 | if (gop.found_existing) { | 1759 | if (gop.found_existing) { |
| ... | @@ -1894,32 +1777,57 @@ pub const Object = struct { | ... | @@ -1894,32 +1777,57 @@ pub const Object = struct { |
| 1894 | try variable_index.setInitializer(init_val, &o.builder); | 1777 | try variable_index.setInitializer(init_val, &o.builder); |
| 1895 | break :i global_index; | 1778 | break :i global_index; |
| 1896 | }; | 1779 | }; |
| 1897 | return updateExportedGlobal(o, mod, global_index, exports); | 1780 | return updateExportedGlobal(o, mod, global_index, export_indices); |
| 1898 | } | 1781 | } |
| 1899 | 1782 | ||
| 1900 | fn updateExportedGlobal( | 1783 | fn updateExportedGlobal( |
| 1901 | o: *Object, | 1784 | o: *Object, |
| 1902 | mod: *Module, | 1785 | mod: *Module, |
| 1903 | global_index: Builder.Global.Index, | 1786 | global_index: Builder.Global.Index, |
| 1904 | exports: []const *Module.Export, | 1787 | export_indices: []const u32, |
| 1905 | ) link.File.UpdateExportsError!void { | 1788 | ) link.File.UpdateExportsError!void { |
| 1906 | const comp = mod.comp; | 1789 | const comp = mod.comp; |
| 1907 | const ip = &mod.intern_pool; | 1790 | const ip = &mod.intern_pool; |
| 1791 | const first_export = mod.all_exports.items[export_indices[0]]; | ||
| 1792 | |||
| 1793 | // We will rename this global to have a name matching `first_export`. | ||
| 1794 | // Successive exports become aliases. | ||
| 1795 | // If the first export name already exists, then there is a corresponding | ||
| 1796 | // extern global - we replace it with this global. | ||
| 1797 | const first_exp_name = try o.builder.strtabString(first_export.opts.name.toSlice(ip)); | ||
| 1798 | if (o.builder.getGlobal(first_exp_name)) |other_global| replace: { | ||
| 1799 | if (other_global.toConst().getBase(&o.builder) == global_index.toConst().getBase(&o.builder)) { | ||
| 1800 | break :replace; // this global already has the name we want | ||
| 1801 | } | ||
| 1802 | try global_index.takeName(other_global, &o.builder); | ||
| 1803 | try other_global.replace(global_index, &o.builder); | ||
| 1804 | // Problem: now we need to replace in the decl_map that | ||
| 1805 | // the extern decl index points to this new global. However we don't | ||
| 1806 | // know the decl index. | ||
| 1807 | // Even if we did, a future incremental update to the extern would then | ||
| 1808 | // treat the LLVM global as an extern rather than an export, so it would | ||
| 1809 | // need a way to check that. | ||
| 1810 | // This is a TODO that needs to be solved when making | ||
| 1811 | // the LLVM backend support incremental compilation. | ||
| 1812 | } else { | ||
| 1813 | try global_index.rename(first_exp_name, &o.builder); | ||
| 1814 | } | ||
| 1815 | |||
| 1908 | global_index.setUnnamedAddr(.default, &o.builder); | 1816 | global_index.setUnnamedAddr(.default, &o.builder); |
| 1909 | if (comp.config.dll_export_fns) | 1817 | if (comp.config.dll_export_fns) |
| 1910 | global_index.setDllStorageClass(.dllexport, &o.builder); | 1818 | global_index.setDllStorageClass(.dllexport, &o.builder); |
| 1911 | global_index.setLinkage(switch (exports[0].opts.linkage) { | 1819 | global_index.setLinkage(switch (first_export.opts.linkage) { |
| 1912 | .internal => unreachable, | 1820 | .internal => unreachable, |
| 1913 | .strong => .external, | 1821 | .strong => .external, |
| 1914 | .weak => .weak_odr, | 1822 | .weak => .weak_odr, |
| 1915 | .link_once => .linkonce_odr, | 1823 | .link_once => .linkonce_odr, |
| 1916 | }, &o.builder); | 1824 | }, &o.builder); |
| 1917 | global_index.setVisibility(switch (exports[0].opts.visibility) { | 1825 | global_index.setVisibility(switch (first_export.opts.visibility) { |
| 1918 | .default => .default, | 1826 | .default => .default, |
| 1919 | .hidden => .hidden, | 1827 | .hidden => .hidden, |
| 1920 | .protected => .protected, | 1828 | .protected => .protected, |
| 1921 | }, &o.builder); | 1829 | }, &o.builder); |
| 1922 | if (exports[0].opts.section.toSlice(ip)) |section| | 1830 | if (first_export.opts.section.toSlice(ip)) |section| |
| 1923 | switch (global_index.ptrConst(&o.builder).kind) { | 1831 | switch (global_index.ptrConst(&o.builder).kind) { |
| 1924 | .variable => |impl_index| impl_index.setSection( | 1832 | .variable => |impl_index| impl_index.setSection( |
| 1925 | try o.builder.string(section), | 1833 | try o.builder.string(section), |
| ... | @@ -1936,7 +1844,8 @@ pub const Object = struct { | ... | @@ -1936,7 +1844,8 @@ pub const Object = struct { |
| 1936 | // The planned solution to this is https://github.com/ziglang/zig/issues/13265 | 1844 | // The planned solution to this is https://github.com/ziglang/zig/issues/13265 |
| 1937 | // Until then we iterate over existing aliases and make them point | 1845 | // Until then we iterate over existing aliases and make them point |
| 1938 | // to the correct decl, or otherwise add a new alias. Old aliases are leaked. | 1846 | // to the correct decl, or otherwise add a new alias. Old aliases are leaked. |
| 1939 | for (exports[1..]) |exp| { | 1847 | for (export_indices[1..]) |export_idx| { |
| 1848 | const exp = mod.all_exports.items[export_idx]; | ||
| 1940 | const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip)); | 1849 | const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip)); |
| 1941 | if (o.builder.getGlobal(exp_name)) |global| { | 1850 | if (o.builder.getGlobal(exp_name)) |global| { |
| 1942 | switch (global.ptrConst(&o.builder).kind) { | 1851 | switch (global.ptrConst(&o.builder).kind) { |
| ... | @@ -1944,7 +1853,13 @@ pub const Object = struct { | ... | @@ -1944,7 +1853,13 @@ pub const Object = struct { |
| 1944 | alias.setAliasee(global_index.toConst(), &o.builder); | 1853 | alias.setAliasee(global_index.toConst(), &o.builder); |
| 1945 | continue; | 1854 | continue; |
| 1946 | }, | 1855 | }, |
| 1947 | .variable, .function => {}, | 1856 | .variable, .function => { |
| 1857 | // This existing global is an `extern` corresponding to this export. | ||
| 1858 | // Replace it with the global being exported. | ||
| 1859 | // This existing global must be replaced with the alias. | ||
| 1860 | try global.rename(.empty, &o.builder); | ||
| 1861 | try global.replace(global_index, &o.builder); | ||
| 1862 | }, | ||
| 1948 | .replaced => unreachable, | 1863 | .replaced => unreachable, |
| 1949 | } | 1864 | } |
| 1950 | } | 1865 | } |
| ... | @@ -4762,36 +4677,77 @@ pub const DeclGen = struct { | ... | @@ -4762,36 +4677,77 @@ pub const DeclGen = struct { |
| 4762 | else => try o.lowerValue(init_val), | 4677 | else => try o.lowerValue(init_val), |
| 4763 | }, &o.builder); | 4678 | }, &o.builder); |
| 4764 | 4679 | ||
| 4680 | if (decl.val.getVariable(zcu)) |decl_var| { | ||
| 4681 | const decl_namespace = zcu.namespacePtr(decl.src_namespace); | ||
| 4682 | const single_threaded = decl_namespace.file_scope.mod.single_threaded; | ||
| 4683 | variable_index.setThreadLocal( | ||
| 4684 | if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default, | ||
| 4685 | &o.builder, | ||
| 4686 | ); | ||
| 4687 | } | ||
| 4688 | |||
| 4765 | const line_number = decl.navSrcLine(zcu) + 1; | 4689 | const line_number = decl.navSrcLine(zcu) + 1; |
| 4766 | const is_internal_linkage = !o.module.decl_exports.contains(decl_index); | ||
| 4767 | 4690 | ||
| 4768 | const namespace = zcu.namespacePtr(decl.src_namespace); | 4691 | const namespace = zcu.namespacePtr(decl.src_namespace); |
| 4769 | const owner_mod = namespace.file_scope.mod; | 4692 | const owner_mod = namespace.file_scope.mod; |
| 4770 | 4693 | ||
| 4771 | if (owner_mod.strip) return; | 4694 | if (!owner_mod.strip) { |
| 4695 | const debug_file = try o.getDebugFile(namespace.file_scope); | ||
| 4696 | |||
| 4697 | const debug_global_var = try o.builder.debugGlobalVar( | ||
| 4698 | try o.builder.metadataString(decl.name.toSlice(ip)), // Name | ||
| 4699 | try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name | ||
| 4700 | debug_file, // File | ||
| 4701 | debug_file, // Scope | ||
| 4702 | line_number, | ||
| 4703 | try o.lowerDebugType(decl.typeOf(zcu)), | ||
| 4704 | variable_index, | ||
| 4705 | .{ .local = !decl.isExtern(zcu) }, | ||
| 4706 | ); | ||
| 4772 | 4707 | ||
| 4773 | const debug_file = try o.getDebugFile(namespace.file_scope); | 4708 | const debug_expression = try o.builder.debugExpression(&.{}); |
| 4774 | 4709 | ||
| 4775 | const debug_global_var = try o.builder.debugGlobalVar( | 4710 | const debug_global_var_expression = try o.builder.debugGlobalVarExpression( |
| 4776 | try o.builder.metadataString(decl.name.toSlice(ip)), // Name | 4711 | debug_global_var, |
| 4777 | try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name | 4712 | debug_expression, |
| 4778 | debug_file, // File | 4713 | ); |
| 4779 | debug_file, // Scope | ||
| 4780 | line_number, | ||
| 4781 | try o.lowerDebugType(decl.typeOf(zcu)), | ||
| 4782 | variable_index, | ||
| 4783 | .{ .local = is_internal_linkage }, | ||
| 4784 | ); | ||
| 4785 | 4714 | ||
| 4786 | const debug_expression = try o.builder.debugExpression(&.{}); | 4715 | variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder); |
| 4716 | try o.debug_globals.append(o.gpa, debug_global_var_expression); | ||
| 4717 | } | ||
| 4718 | } | ||
| 4787 | 4719 | ||
| 4788 | const debug_global_var_expression = try o.builder.debugGlobalVarExpression( | 4720 | if (decl.isExtern(zcu)) { |
| 4789 | debug_global_var, | 4721 | const global_index = o.decl_map.get(decl_index).?; |
| 4790 | debug_expression, | ||
| 4791 | ); | ||
| 4792 | 4722 | ||
| 4793 | variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder); | 4723 | const decl_name = decl_name: { |
| 4794 | try o.debug_globals.append(o.gpa, debug_global_var_expression); | 4724 | if (zcu.getTarget().isWasm() and decl.typeOf(zcu).zigTypeTag(zcu) == .Fn) { |
| 4725 | if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| { | ||
| 4726 | if (!std.mem.eql(u8, lib_name, "c")) { | ||
| 4727 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name }); | ||
| 4728 | } | ||
| 4729 | } | ||
| 4730 | } | ||
| 4731 | break :decl_name try o.builder.strtabString(decl.name.toSlice(ip)); | ||
| 4732 | }; | ||
| 4733 | |||
| 4734 | if (o.builder.getGlobal(decl_name)) |other_global| { | ||
| 4735 | if (other_global != global_index) { | ||
| 4736 | // Another global already has this name; just use it in place of this global. | ||
| 4737 | try global_index.replace(other_global, &o.builder); | ||
| 4738 | return; | ||
| 4739 | } | ||
| 4740 | } | ||
| 4741 | |||
| 4742 | try global_index.rename(decl_name, &o.builder); | ||
| 4743 | global_index.setLinkage(.external, &o.builder); | ||
| 4744 | global_index.setUnnamedAddr(.default, &o.builder); | ||
| 4745 | if (zcu.comp.config.dll_export_fns) | ||
| 4746 | global_index.setDllStorageClass(.default, &o.builder); | ||
| 4747 | |||
| 4748 | if (decl.val.getVariable(zcu)) |decl_var| { | ||
| 4749 | if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder); | ||
| 4750 | } | ||
| 4795 | } | 4751 | } |
| 4796 | } | 4752 | } |
| 4797 | }; | 4753 | }; |
| ... | @@ -5193,7 +5149,6 @@ pub const FuncGen = struct { | ... | @@ -5193,7 +5149,6 @@ pub const FuncGen = struct { |
| 5193 | 5149 | ||
| 5194 | const fqn = try decl.fullyQualifiedName(zcu); | 5150 | const fqn = try decl.fullyQualifiedName(zcu); |
| 5195 | 5151 | ||
| 5196 | const is_internal_linkage = !zcu.decl_exports.contains(decl_index); | ||
| 5197 | const fn_ty = try zcu.funcType(.{ | 5152 | const fn_ty = try zcu.funcType(.{ |
| 5198 | .param_types = &.{}, | 5153 | .param_types = &.{}, |
| 5199 | .return_type = .void_type, | 5154 | .return_type = .void_type, |
| ... | @@ -5211,7 +5166,7 @@ pub const FuncGen = struct { | ... | @@ -5211,7 +5166,7 @@ pub const FuncGen = struct { |
| 5211 | .sp_flags = .{ | 5166 | .sp_flags = .{ |
| 5212 | .Optimized = owner_mod.optimize_mode != .Debug, | 5167 | .Optimized = owner_mod.optimize_mode != .Debug, |
| 5213 | .Definition = true, | 5168 | .Definition = true, |
| 5214 | .LocalToUnit = is_internal_linkage, | 5169 | .LocalToUnit = true, // TODO: we can't know this at this point, since the function could be exported later! |
| 5215 | }, | 5170 | }, |
| 5216 | }, | 5171 | }, |
| 5217 | o.debug_compile_unit, | 5172 | o.debug_compile_unit, |
src/link.zig+6-6| ... | @@ -606,12 +606,12 @@ pub const File = struct { | ... | @@ -606,12 +606,12 @@ pub const File = struct { |
| 606 | base: *File, | 606 | base: *File, |
| 607 | module: *Module, | 607 | module: *Module, |
| 608 | exported: Module.Exported, | 608 | exported: Module.Exported, |
| 609 | exports: []const *Module.Export, | 609 | export_indices: []const u32, |
| 610 | ) UpdateExportsError!void { | 610 | ) UpdateExportsError!void { |
| 611 | switch (base.tag) { | 611 | switch (base.tag) { |
| 612 | inline else => |tag| { | 612 | inline else => |tag| { |
| 613 | if (tag != .c and build_options.only_c) unreachable; | 613 | if (tag != .c and build_options.only_c) unreachable; |
| 614 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, exports); | 614 | return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, export_indices); |
| 615 | }, | 615 | }, |
| 616 | } | 616 | } |
| 617 | } | 617 | } |
| ... | @@ -671,11 +671,11 @@ pub const File = struct { | ... | @@ -671,11 +671,11 @@ pub const File = struct { |
| 671 | } | 671 | } |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | pub fn deleteDeclExport( | 674 | pub fn deleteExport( |
| 675 | base: *File, | 675 | base: *File, |
| 676 | decl_index: InternPool.DeclIndex, | 676 | exported: Zcu.Exported, |
| 677 | name: InternPool.NullTerminatedString, | 677 | name: InternPool.NullTerminatedString, |
| 678 | ) !void { | 678 | ) void { |
| 679 | if (build_options.only_c) @compileError("unreachable"); | 679 | if (build_options.only_c) @compileError("unreachable"); |
| 680 | switch (base.tag) { | 680 | switch (base.tag) { |
| 681 | .plan9, | 681 | .plan9, |
| ... | @@ -685,7 +685,7 @@ pub const File = struct { | ... | @@ -685,7 +685,7 @@ pub const File = struct { |
| 685 | => {}, | 685 | => {}, |
| 686 | 686 | ||
| 687 | inline else => |tag| { | 687 | inline else => |tag| { |
| 688 | return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteDeclExport(decl_index, name); | 688 | return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteExport(exported, name); |
| 689 | }, | 689 | }, |
| 690 | } | 690 | } |
| 691 | } | 691 | } |
src/link/C.zig+22-7| ... | @@ -183,6 +183,8 @@ pub fn updateFunc( | ... | @@ -183,6 +183,8 @@ pub fn updateFunc( |
| 183 | air: Air, | 183 | air: Air, |
| 184 | liveness: Liveness, | 184 | liveness: Liveness, |
| 185 | ) !void { | 185 | ) !void { |
| 186 | if (true) @panic("TODO jacobly"); | ||
| 187 | |||
| 186 | const gpa = self.base.comp.gpa; | 188 | const gpa = self.base.comp.gpa; |
| 187 | 189 | ||
| 188 | const func = zcu.funcInfo(func_index); | 190 | const func = zcu.funcInfo(func_index); |
| ... | @@ -250,6 +252,8 @@ pub fn updateFunc( | ... | @@ -250,6 +252,8 @@ pub fn updateFunc( |
| 250 | } | 252 | } |
| 251 | 253 | ||
| 252 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | 254 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 255 | if (true) @panic("TODO jacobly"); | ||
| 256 | |||
| 253 | const gpa = self.base.comp.gpa; | 257 | const gpa = self.base.comp.gpa; |
| 254 | const anon_decl = self.anon_decls.keys()[i]; | 258 | const anon_decl = self.anon_decls.keys()[i]; |
| 255 | 259 | ||
| ... | @@ -306,6 +310,8 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | ... | @@ -306,6 +310,8 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 306 | } | 310 | } |
| 307 | 311 | ||
| 308 | pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | 312 | pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 313 | if (true) @panic("TODO jacobly"); | ||
| 314 | |||
| 309 | const tracy = trace(@src()); | 315 | const tracy = trace(@src()); |
| 310 | defer tracy.end(); | 316 | defer tracy.end(); |
| 311 | 317 | ||
| ... | @@ -390,6 +396,8 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { | ... | @@ -390,6 +396,8 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { |
| 390 | } | 396 | } |
| 391 | 397 | ||
| 392 | pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !void { | 398 | pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !void { |
| 399 | if (true) @panic("TODO jacobly"); | ||
| 400 | |||
| 393 | _ = arena; // Has the same lifetime as the call to Compilation.update. | 401 | _ = arena; // Has the same lifetime as the call to Compilation.update. |
| 394 | 402 | ||
| 395 | const tracy = trace(@src()); | 403 | const tracy = trace(@src()); |
| ... | @@ -451,9 +459,16 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo | ... | @@ -451,9 +459,16 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo |
| 451 | { | 459 | { |
| 452 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | 460 | var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; |
| 453 | defer export_names.deinit(gpa); | 461 | defer export_names.deinit(gpa); |
| 454 | try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len)); | 462 | try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count())); |
| 455 | for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"| | 463 | for (zcu.single_exports.values()) |export_idx| { |
| 456 | try export_names.put(gpa, @"export".opts.name, {}); | 464 | export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {}); |
| 465 | } | ||
| 466 | for (zcu.multi_exports.values()) |info| { | ||
| 467 | try export_names.ensureUnusedCapacity(info.len); | ||
| 468 | for (zcu.all_exports.items[info.index..][0..info.len]) |export_idx| { | ||
| 469 | export_names.putAssumeCapacity(gpa, zcu.all_exports.items[export_idx].opts.name, {}); | ||
| 470 | } | ||
| 471 | } | ||
| 457 | 472 | ||
| 458 | for (self.anon_decls.values()) |*decl_block| { | 473 | for (self.anon_decls.values()) |*decl_block| { |
| 459 | try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none); | 474 | try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none); |
| ... | @@ -781,10 +796,10 @@ pub fn updateExports( | ... | @@ -781,10 +796,10 @@ pub fn updateExports( |
| 781 | self: *C, | 796 | self: *C, |
| 782 | zcu: *Zcu, | 797 | zcu: *Zcu, |
| 783 | exported: Zcu.Exported, | 798 | exported: Zcu.Exported, |
| 784 | exports: []const *Zcu.Export, | 799 | export_indices: []const u32, |
| 785 | ) !void { | 800 | ) !void { |
| 786 | _ = exports; | ||
| 787 | _ = exported; | ||
| 788 | _ = zcu; | ||
| 789 | _ = self; | 801 | _ = self; |
| 802 | _ = zcu; | ||
| 803 | _ = exported; | ||
| 804 | _ = export_indices; | ||
| 790 | } | 805 | } |
src/link/Coff.zig+18-17| ... | @@ -1162,9 +1162,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: | ... | @@ -1162,9 +1162,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: |
| 1162 | 1162 | ||
| 1163 | try self.updateDeclCode(decl_index, code, .FUNCTION); | 1163 | try self.updateDeclCode(decl_index, code, .FUNCTION); |
| 1164 | 1164 | ||
| 1165 | // Since we updated the vaddr and the size, each corresponding export | 1165 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1166 | // symbol also needs to be updated. | ||
| 1167 | return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 1168 | } | 1166 | } |
| 1169 | 1167 | ||
| 1170 | pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 { | 1168 | pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 { |
| ... | @@ -1286,9 +1284,7 @@ pub fn updateDecl( | ... | @@ -1286,9 +1284,7 @@ pub fn updateDecl( |
| 1286 | 1284 | ||
| 1287 | try self.updateDeclCode(decl_index, code, .NULL); | 1285 | try self.updateDeclCode(decl_index, code, .NULL); |
| 1288 | 1286 | ||
| 1289 | // Since we updated the vaddr and the size, each corresponding export | 1287 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1290 | // symbol also needs to be updated. | ||
| 1291 | return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 1292 | } | 1288 | } |
| 1293 | 1289 | ||
| 1294 | fn updateLazySymbolAtom( | 1290 | fn updateLazySymbolAtom( |
| ... | @@ -1509,7 +1505,7 @@ pub fn updateExports( | ... | @@ -1509,7 +1505,7 @@ pub fn updateExports( |
| 1509 | self: *Coff, | 1505 | self: *Coff, |
| 1510 | mod: *Module, | 1506 | mod: *Module, |
| 1511 | exported: Module.Exported, | 1507 | exported: Module.Exported, |
| 1512 | exports: []const *Module.Export, | 1508 | export_indices: []const u32, |
| 1513 | ) link.File.UpdateExportsError!void { | 1509 | ) link.File.UpdateExportsError!void { |
| 1514 | if (build_options.skip_non_native and builtin.object_format != .coff) { | 1510 | if (build_options.skip_non_native and builtin.object_format != .coff) { |
| 1515 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1511 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| ... | @@ -1522,7 +1518,8 @@ pub fn updateExports( | ... | @@ -1522,7 +1518,8 @@ pub fn updateExports( |
| 1522 | if (comp.config.use_llvm) { | 1518 | if (comp.config.use_llvm) { |
| 1523 | // Even in the case of LLVM, we need to notice certain exported symbols in order to | 1519 | // Even in the case of LLVM, we need to notice certain exported symbols in order to |
| 1524 | // detect the default subsystem. | 1520 | // detect the default subsystem. |
| 1525 | for (exports) |exp| { | 1521 | for (export_indices) |export_idx| { |
| 1522 | const exp = mod.all_exports.items[export_idx]; | ||
| 1526 | const exported_decl_index = switch (exp.exported) { | 1523 | const exported_decl_index = switch (exp.exported) { |
| 1527 | .decl_index => |i| i, | 1524 | .decl_index => |i| i, |
| 1528 | .value => continue, | 1525 | .value => continue, |
| ... | @@ -1552,7 +1549,7 @@ pub fn updateExports( | ... | @@ -1552,7 +1549,7 @@ pub fn updateExports( |
| 1552 | } | 1549 | } |
| 1553 | } | 1550 | } |
| 1554 | 1551 | ||
| 1555 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); | 1552 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices); |
| 1556 | 1553 | ||
| 1557 | const gpa = comp.gpa; | 1554 | const gpa = comp.gpa; |
| 1558 | 1555 | ||
| ... | @@ -1562,7 +1559,7 @@ pub fn updateExports( | ... | @@ -1562,7 +1559,7 @@ pub fn updateExports( |
| 1562 | break :blk self.decls.getPtr(decl_index).?; | 1559 | break :blk self.decls.getPtr(decl_index).?; |
| 1563 | }, | 1560 | }, |
| 1564 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | 1561 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { |
| 1565 | const first_exp = exports[0]; | 1562 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1566 | const res = try self.lowerAnonDecl(value, .none, first_exp.getSrcLoc(mod)); | 1563 | const res = try self.lowerAnonDecl(value, .none, first_exp.getSrcLoc(mod)); |
| 1567 | switch (res) { | 1564 | switch (res) { |
| 1568 | .ok => {}, | 1565 | .ok => {}, |
| ... | @@ -1570,7 +1567,7 @@ pub fn updateExports( | ... | @@ -1570,7 +1567,7 @@ pub fn updateExports( |
| 1570 | // TODO maybe it's enough to return an error here and let Module.processExportsInner | 1567 | // TODO maybe it's enough to return an error here and let Module.processExportsInner |
| 1571 | // handle the error? | 1568 | // handle the error? |
| 1572 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1569 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1573 | mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em); | 1570 | mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em); |
| 1574 | return; | 1571 | return; |
| 1575 | }, | 1572 | }, |
| 1576 | } | 1573 | } |
| ... | @@ -1580,12 +1577,13 @@ pub fn updateExports( | ... | @@ -1580,12 +1577,13 @@ pub fn updateExports( |
| 1580 | const atom_index = metadata.atom; | 1577 | const atom_index = metadata.atom; |
| 1581 | const atom = self.getAtom(atom_index); | 1578 | const atom = self.getAtom(atom_index); |
| 1582 | 1579 | ||
| 1583 | for (exports) |exp| { | 1580 | for (export_indices) |export_idx| { |
| 1581 | const exp = mod.all_exports.items[export_idx]; | ||
| 1584 | log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)}); | 1582 | log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)}); |
| 1585 | 1583 | ||
| 1586 | if (exp.opts.section.toSlice(&mod.intern_pool)) |section_name| { | 1584 | if (exp.opts.section.toSlice(&mod.intern_pool)) |section_name| { |
| 1587 | if (!mem.eql(u8, section_name, ".text")) { | 1585 | if (!mem.eql(u8, section_name, ".text")) { |
| 1588 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | 1586 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create( |
| 1589 | gpa, | 1587 | gpa, |
| 1590 | exp.getSrcLoc(mod), | 1588 | exp.getSrcLoc(mod), |
| 1591 | "Unimplemented: ExportOptions.section", | 1589 | "Unimplemented: ExportOptions.section", |
| ... | @@ -1596,7 +1594,7 @@ pub fn updateExports( | ... | @@ -1596,7 +1594,7 @@ pub fn updateExports( |
| 1596 | } | 1594 | } |
| 1597 | 1595 | ||
| 1598 | if (exp.opts.linkage == .link_once) { | 1596 | if (exp.opts.linkage == .link_once) { |
| 1599 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | 1597 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create( |
| 1600 | gpa, | 1598 | gpa, |
| 1601 | exp.getSrcLoc(mod), | 1599 | exp.getSrcLoc(mod), |
| 1602 | "Unimplemented: GlobalLinkage.link_once", | 1600 | "Unimplemented: GlobalLinkage.link_once", |
| ... | @@ -1641,13 +1639,16 @@ pub fn updateExports( | ... | @@ -1641,13 +1639,16 @@ pub fn updateExports( |
| 1641 | } | 1639 | } |
| 1642 | } | 1640 | } |
| 1643 | 1641 | ||
| 1644 | pub fn deleteDeclExport( | 1642 | pub fn deleteExport( |
| 1645 | self: *Coff, | 1643 | self: *Coff, |
| 1646 | decl_index: InternPool.DeclIndex, | 1644 | exported: Zcu.Exported, |
| 1647 | name: InternPool.NullTerminatedString, | 1645 | name: InternPool.NullTerminatedString, |
| 1648 | ) void { | 1646 | ) void { |
| 1649 | if (self.llvm_object) |_| return; | 1647 | if (self.llvm_object) |_| return; |
| 1650 | const metadata = self.decls.getPtr(decl_index) orelse return; | 1648 | const metadata = switch (exported) { |
| 1649 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | ||
| 1650 | .value => |value| self.anon_decls.getPtr(value) orelse return, | ||
| 1651 | }; | ||
| 1651 | const mod = self.base.comp.module.?; | 1652 | const mod = self.base.comp.module.?; |
| 1652 | const name_slice = name.toSlice(&mod.intern_pool); | 1653 | const name_slice = name.toSlice(&mod.intern_pool); |
| 1653 | const sym_index = metadata.getExportPtr(self, name_slice) orelse return; | 1654 | const sym_index = metadata.getExportPtr(self, name_slice) orelse return; |
src/link/Elf.zig+6-6| ... | @@ -3011,13 +3011,13 @@ pub fn updateExports( | ... | @@ -3011,13 +3011,13 @@ pub fn updateExports( |
| 3011 | self: *Elf, | 3011 | self: *Elf, |
| 3012 | mod: *Module, | 3012 | mod: *Module, |
| 3013 | exported: Module.Exported, | 3013 | exported: Module.Exported, |
| 3014 | exports: []const *Module.Export, | 3014 | export_indices: []const u32, |
| 3015 | ) link.File.UpdateExportsError!void { | 3015 | ) link.File.UpdateExportsError!void { |
| 3016 | if (build_options.skip_non_native and builtin.object_format != .elf) { | 3016 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 3017 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 3017 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 3018 | } | 3018 | } |
| 3019 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); | 3019 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices); |
| 3020 | return self.zigObjectPtr().?.updateExports(self, mod, exported, exports); | 3020 | return self.zigObjectPtr().?.updateExports(self, mod, exported, export_indices); |
| 3021 | } | 3021 | } |
| 3022 | 3022 | ||
| 3023 | pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void { | 3023 | pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void { |
| ... | @@ -3025,13 +3025,13 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.Dec | ... | @@ -3025,13 +3025,13 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.Dec |
| 3025 | return self.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index); | 3025 | return self.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index); |
| 3026 | } | 3026 | } |
| 3027 | 3027 | ||
| 3028 | pub fn deleteDeclExport( | 3028 | pub fn deleteExport( |
| 3029 | self: *Elf, | 3029 | self: *Elf, |
| 3030 | decl_index: InternPool.DeclIndex, | 3030 | exported: Zcu.Exported, |
| 3031 | name: InternPool.NullTerminatedString, | 3031 | name: InternPool.NullTerminatedString, |
| 3032 | ) void { | 3032 | ) void { |
| 3033 | if (self.llvm_object) |_| return; | 3033 | if (self.llvm_object) |_| return; |
| 3034 | return self.zigObjectPtr().?.deleteDeclExport(self, decl_index, name); | 3034 | return self.zigObjectPtr().?.deleteExport(self, exported, name); |
| 3035 | } | 3035 | } |
| 3036 | 3036 | ||
| 3037 | fn addLinkerDefinedSymbols(self: *Elf) !void { | 3037 | fn addLinkerDefinedSymbols(self: *Elf) !void { |
src/link/Elf/ZigObject.zig+15-15| ... | @@ -1115,9 +1115,7 @@ pub fn updateFunc( | ... | @@ -1115,9 +1115,7 @@ pub fn updateFunc( |
| 1115 | ); | 1115 | ); |
| 1116 | } | 1116 | } |
| 1117 | 1117 | ||
| 1118 | // Since we updated the vaddr and the size, each corresponding export | 1118 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1119 | // symbol also needs to be updated. | ||
| 1120 | return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 1121 | } | 1119 | } |
| 1122 | 1120 | ||
| 1123 | pub fn updateDecl( | 1121 | pub fn updateDecl( |
| ... | @@ -1194,9 +1192,7 @@ pub fn updateDecl( | ... | @@ -1194,9 +1192,7 @@ pub fn updateDecl( |
| 1194 | ); | 1192 | ); |
| 1195 | } | 1193 | } |
| 1196 | 1194 | ||
| 1197 | // Since we updated the vaddr and the size, each corresponding export | 1195 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1198 | // symbol also needs to be updated. | ||
| 1199 | return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 1200 | } | 1196 | } |
| 1201 | 1197 | ||
| 1202 | fn updateLazySymbol( | 1198 | fn updateLazySymbol( |
| ... | @@ -1386,7 +1382,7 @@ pub fn updateExports( | ... | @@ -1386,7 +1382,7 @@ pub fn updateExports( |
| 1386 | elf_file: *Elf, | 1382 | elf_file: *Elf, |
| 1387 | mod: *Module, | 1383 | mod: *Module, |
| 1388 | exported: Module.Exported, | 1384 | exported: Module.Exported, |
| 1389 | exports: []const *Module.Export, | 1385 | export_indices: []const u32, |
| 1390 | ) link.File.UpdateExportsError!void { | 1386 | ) link.File.UpdateExportsError!void { |
| 1391 | const tracy = trace(@src()); | 1387 | const tracy = trace(@src()); |
| 1392 | defer tracy.end(); | 1388 | defer tracy.end(); |
| ... | @@ -1398,7 +1394,7 @@ pub fn updateExports( | ... | @@ -1398,7 +1394,7 @@ pub fn updateExports( |
| 1398 | break :blk self.decls.getPtr(decl_index).?; | 1394 | break :blk self.decls.getPtr(decl_index).?; |
| 1399 | }, | 1395 | }, |
| 1400 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | 1396 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { |
| 1401 | const first_exp = exports[0]; | 1397 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1402 | const res = try self.lowerAnonDecl(elf_file, value, .none, first_exp.getSrcLoc(mod)); | 1398 | const res = try self.lowerAnonDecl(elf_file, value, .none, first_exp.getSrcLoc(mod)); |
| 1403 | switch (res) { | 1399 | switch (res) { |
| 1404 | .ok => {}, | 1400 | .ok => {}, |
| ... | @@ -1406,7 +1402,7 @@ pub fn updateExports( | ... | @@ -1406,7 +1402,7 @@ pub fn updateExports( |
| 1406 | // TODO maybe it's enough to return an error here and let Module.processExportsInner | 1402 | // TODO maybe it's enough to return an error here and let Module.processExportsInner |
| 1407 | // handle the error? | 1403 | // handle the error? |
| 1408 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1404 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1409 | mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em); | 1405 | mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em); |
| 1410 | return; | 1406 | return; |
| 1411 | }, | 1407 | }, |
| 1412 | } | 1408 | } |
| ... | @@ -1418,11 +1414,12 @@ pub fn updateExports( | ... | @@ -1418,11 +1414,12 @@ pub fn updateExports( |
| 1418 | const esym = self.local_esyms.items(.elf_sym)[esym_index]; | 1414 | const esym = self.local_esyms.items(.elf_sym)[esym_index]; |
| 1419 | const esym_shndx = self.local_esyms.items(.shndx)[esym_index]; | 1415 | const esym_shndx = self.local_esyms.items(.shndx)[esym_index]; |
| 1420 | 1416 | ||
| 1421 | for (exports) |exp| { | 1417 | for (export_indices) |export_idx| { |
| 1418 | const exp = mod.all_exports.items[export_idx]; | ||
| 1422 | if (exp.opts.section.unwrap()) |section_name| { | 1419 | if (exp.opts.section.unwrap()) |section_name| { |
| 1423 | if (!section_name.eqlSlice(".text", &mod.intern_pool)) { | 1420 | if (!section_name.eqlSlice(".text", &mod.intern_pool)) { |
| 1424 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1421 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1425 | mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( | 1422 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( |
| 1426 | gpa, | 1423 | gpa, |
| 1427 | exp.getSrcLoc(mod), | 1424 | exp.getSrcLoc(mod), |
| 1428 | "Unimplemented: ExportOptions.section", | 1425 | "Unimplemented: ExportOptions.section", |
| ... | @@ -1437,7 +1434,7 @@ pub fn updateExports( | ... | @@ -1437,7 +1434,7 @@ pub fn updateExports( |
| 1437 | .weak => elf.STB_WEAK, | 1434 | .weak => elf.STB_WEAK, |
| 1438 | .link_once => { | 1435 | .link_once => { |
| 1439 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1436 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1440 | mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( | 1437 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( |
| 1441 | gpa, | 1438 | gpa, |
| 1442 | exp.getSrcLoc(mod), | 1439 | exp.getSrcLoc(mod), |
| 1443 | "Unimplemented: GlobalLinkage.LinkOnce", | 1440 | "Unimplemented: GlobalLinkage.LinkOnce", |
| ... | @@ -1487,13 +1484,16 @@ pub fn updateDeclLineNumber( | ... | @@ -1487,13 +1484,16 @@ pub fn updateDeclLineNumber( |
| 1487 | } | 1484 | } |
| 1488 | } | 1485 | } |
| 1489 | 1486 | ||
| 1490 | pub fn deleteDeclExport( | 1487 | pub fn deleteExport( |
| 1491 | self: *ZigObject, | 1488 | self: *ZigObject, |
| 1492 | elf_file: *Elf, | 1489 | elf_file: *Elf, |
| 1493 | decl_index: InternPool.DeclIndex, | 1490 | exported: Zcu.Exported, |
| 1494 | name: InternPool.NullTerminatedString, | 1491 | name: InternPool.NullTerminatedString, |
| 1495 | ) void { | 1492 | ) void { |
| 1496 | const metadata = self.decls.getPtr(decl_index) orelse return; | 1493 | const metadata = switch (exported) { |
| 1494 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | ||
| 1495 | .value => |value| self.anon_decls.getPtr(value) orelse return, | ||
| 1496 | }; | ||
| 1497 | const mod = elf_file.base.comp.module.?; | 1497 | const mod = elf_file.base.comp.module.?; |
| 1498 | const exp_name = name.toSlice(&mod.intern_pool); | 1498 | const exp_name = name.toSlice(&mod.intern_pool); |
| 1499 | const esym_index = metadata.@"export"(self, exp_name) orelse return; | 1499 | const esym_index = metadata.@"export"(self, exp_name) orelse return; |
src/link/MachO.zig+7-7| ... | @@ -3196,22 +3196,22 @@ pub fn updateExports( | ... | @@ -3196,22 +3196,22 @@ pub fn updateExports( |
| 3196 | self: *MachO, | 3196 | self: *MachO, |
| 3197 | mod: *Module, | 3197 | mod: *Module, |
| 3198 | exported: Module.Exported, | 3198 | exported: Module.Exported, |
| 3199 | exports: []const *Module.Export, | 3199 | export_indices: []const u32, |
| 3200 | ) link.File.UpdateExportsError!void { | 3200 | ) link.File.UpdateExportsError!void { |
| 3201 | if (build_options.skip_non_native and builtin.object_format != .macho) { | 3201 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 3202 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 3202 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 3203 | } | 3203 | } |
| 3204 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); | 3204 | if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices); |
| 3205 | return self.getZigObject().?.updateExports(self, mod, exported, exports); | 3205 | return self.getZigObject().?.updateExports(self, mod, exported, export_indices); |
| 3206 | } | 3206 | } |
| 3207 | 3207 | ||
| 3208 | pub fn deleteDeclExport( | 3208 | pub fn deleteExport( |
| 3209 | self: *MachO, | 3209 | self: *MachO, |
| 3210 | decl_index: InternPool.DeclIndex, | 3210 | exported: Zcu.Exported, |
| 3211 | name: InternPool.NullTerminatedString, | 3211 | name: InternPool.NullTerminatedString, |
| 3212 | ) Allocator.Error!void { | 3212 | ) void { |
| 3213 | if (self.llvm_object) |_| return; | 3213 | if (self.llvm_object) |_| return; |
| 3214 | return self.getZigObject().?.deleteDeclExport(self, decl_index, name); | 3214 | return self.getZigObject().?.deleteExport(self, exported, name); |
| 3215 | } | 3215 | } |
| 3216 | 3216 | ||
| 3217 | pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { | 3217 | pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { |
src/link/MachO/ZigObject.zig+15-15| ... | @@ -713,9 +713,7 @@ pub fn updateFunc( | ... | @@ -713,9 +713,7 @@ pub fn updateFunc( |
| 713 | ); | 713 | ); |
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | // Since we updated the vaddr and the size, each corresponding export | 716 | // Exports will be updated by `Zcu.processExports` after the update. |
| 717 | // symbol also needs to be updated. | ||
| 718 | return self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 719 | } | 717 | } |
| 720 | 718 | ||
| 721 | pub fn updateDecl( | 719 | pub fn updateDecl( |
| ... | @@ -790,9 +788,7 @@ pub fn updateDecl( | ... | @@ -790,9 +788,7 @@ pub fn updateDecl( |
| 790 | ); | 788 | ); |
| 791 | } | 789 | } |
| 792 | 790 | ||
| 793 | // Since we updated the vaddr and the size, each corresponding export symbol also | 791 | // Exports will be updated by `Zcu.processExports` after the update. |
| 794 | // needs to be updated. | ||
| 795 | try self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); | ||
| 796 | } | 792 | } |
| 797 | 793 | ||
| 798 | fn updateDeclCode( | 794 | fn updateDeclCode( |
| ... | @@ -1187,7 +1183,7 @@ pub fn updateExports( | ... | @@ -1187,7 +1183,7 @@ pub fn updateExports( |
| 1187 | macho_file: *MachO, | 1183 | macho_file: *MachO, |
| 1188 | mod: *Module, | 1184 | mod: *Module, |
| 1189 | exported: Module.Exported, | 1185 | exported: Module.Exported, |
| 1190 | exports: []const *Module.Export, | 1186 | export_indices: []const u32, |
| 1191 | ) link.File.UpdateExportsError!void { | 1187 | ) link.File.UpdateExportsError!void { |
| 1192 | const tracy = trace(@src()); | 1188 | const tracy = trace(@src()); |
| 1193 | defer tracy.end(); | 1189 | defer tracy.end(); |
| ... | @@ -1199,7 +1195,7 @@ pub fn updateExports( | ... | @@ -1199,7 +1195,7 @@ pub fn updateExports( |
| 1199 | break :blk self.decls.getPtr(decl_index).?; | 1195 | break :blk self.decls.getPtr(decl_index).?; |
| 1200 | }, | 1196 | }, |
| 1201 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { | 1197 | .value => |value| self.anon_decls.getPtr(value) orelse blk: { |
| 1202 | const first_exp = exports[0]; | 1198 | const first_exp = mod.all_exports.items[export_indices[0]]; |
| 1203 | const res = try self.lowerAnonDecl(macho_file, value, .none, first_exp.getSrcLoc(mod)); | 1199 | const res = try self.lowerAnonDecl(macho_file, value, .none, first_exp.getSrcLoc(mod)); |
| 1204 | switch (res) { | 1200 | switch (res) { |
| 1205 | .ok => {}, | 1201 | .ok => {}, |
| ... | @@ -1207,7 +1203,7 @@ pub fn updateExports( | ... | @@ -1207,7 +1203,7 @@ pub fn updateExports( |
| 1207 | // TODO maybe it's enough to return an error here and let Module.processExportsInner | 1203 | // TODO maybe it's enough to return an error here and let Module.processExportsInner |
| 1208 | // handle the error? | 1204 | // handle the error? |
| 1209 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1205 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1210 | mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em); | 1206 | mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em); |
| 1211 | return; | 1207 | return; |
| 1212 | }, | 1208 | }, |
| 1213 | } | 1209 | } |
| ... | @@ -1218,11 +1214,12 @@ pub fn updateExports( | ... | @@ -1218,11 +1214,12 @@ pub fn updateExports( |
| 1218 | const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx; | 1214 | const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx; |
| 1219 | const nlist = self.symtab.items(.nlist)[nlist_idx]; | 1215 | const nlist = self.symtab.items(.nlist)[nlist_idx]; |
| 1220 | 1216 | ||
| 1221 | for (exports) |exp| { | 1217 | for (export_indices) |export_idx| { |
| 1218 | const exp = mod.all_exports.items[export_idx]; | ||
| 1222 | if (exp.opts.section.unwrap()) |section_name| { | 1219 | if (exp.opts.section.unwrap()) |section_name| { |
| 1223 | if (!section_name.eqlSlice("__text", &mod.intern_pool)) { | 1220 | if (!section_name.eqlSlice("__text", &mod.intern_pool)) { |
| 1224 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); | 1221 | try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1); |
| 1225 | mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create( | 1222 | mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create( |
| 1226 | gpa, | 1223 | gpa, |
| 1227 | exp.getSrcLoc(mod), | 1224 | exp.getSrcLoc(mod), |
| 1228 | "Unimplemented: ExportOptions.section", | 1225 | "Unimplemented: ExportOptions.section", |
| ... | @@ -1232,7 +1229,7 @@ pub fn updateExports( | ... | @@ -1232,7 +1229,7 @@ pub fn updateExports( |
| 1232 | } | 1229 | } |
| 1233 | } | 1230 | } |
| 1234 | if (exp.opts.linkage == .link_once) { | 1231 | if (exp.opts.linkage == .link_once) { |
| 1235 | try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create( | 1232 | try mod.failed_exports.putNoClobber(mod.gpa, export_idx, try Module.ErrorMsg.create( |
| 1236 | gpa, | 1233 | gpa, |
| 1237 | exp.getSrcLoc(mod), | 1234 | exp.getSrcLoc(mod), |
| 1238 | "Unimplemented: GlobalLinkage.link_once", | 1235 | "Unimplemented: GlobalLinkage.link_once", |
| ... | @@ -1364,15 +1361,18 @@ pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPo | ... | @@ -1364,15 +1361,18 @@ pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPo |
| 1364 | } | 1361 | } |
| 1365 | } | 1362 | } |
| 1366 | 1363 | ||
| 1367 | pub fn deleteDeclExport( | 1364 | pub fn deleteExport( |
| 1368 | self: *ZigObject, | 1365 | self: *ZigObject, |
| 1369 | macho_file: *MachO, | 1366 | macho_file: *MachO, |
| 1370 | decl_index: InternPool.DeclIndex, | 1367 | exported: Zcu.Exported, |
| 1371 | name: InternPool.NullTerminatedString, | 1368 | name: InternPool.NullTerminatedString, |
| 1372 | ) void { | 1369 | ) void { |
| 1373 | const mod = macho_file.base.comp.module.?; | 1370 | const mod = macho_file.base.comp.module.?; |
| 1374 | 1371 | ||
| 1375 | const metadata = self.decls.getPtr(decl_index) orelse return; | 1372 | const metadata = switch (exported) { |
| 1373 | .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return, | ||
| 1374 | .value => |value| self.anon_decls.getPtr(value) orelse return, | ||
| 1375 | }; | ||
| 1376 | const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return; | 1376 | const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return; |
| 1377 | 1377 | ||
| 1378 | log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)}); | 1378 | log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)}); |
src/link/NvPtx.zig+2-2| ... | @@ -96,12 +96,12 @@ pub fn updateExports( | ... | @@ -96,12 +96,12 @@ pub fn updateExports( |
| 96 | self: *NvPtx, | 96 | self: *NvPtx, |
| 97 | module: *Module, | 97 | module: *Module, |
| 98 | exported: Module.Exported, | 98 | exported: Module.Exported, |
| 99 | exports: []const *Module.Export, | 99 | export_indices: []const u32, |
| 100 | ) !void { | 100 | ) !void { |
| 101 | if (build_options.skip_non_native and builtin.object_format != .nvptx) | 101 | if (build_options.skip_non_native and builtin.object_format != .nvptx) |
| 102 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 102 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 103 | 103 | ||
| 104 | return self.llvm_object.updateExports(module, exported, exports); | 104 | return self.llvm_object.updateExports(module, exported, export_indices); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void { | 107 | pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void { |
src/link/Plan9.zig+44-22| ... | @@ -60,6 +60,9 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged( | ... | @@ -60,6 +60,9 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged( |
| 60 | ) = .{}, | 60 | ) = .{}, |
| 61 | /// the code is modified when relocated, so that is why it is mutable | 61 | /// the code is modified when relocated, so that is why it is mutable |
| 62 | data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{}, | 62 | data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{}, |
| 63 | /// When `updateExports` is called, we store the export indices here, to be used | ||
| 64 | /// during flush. | ||
| 65 | decl_exports: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u32) = .{}, | ||
| 63 | 66 | ||
| 64 | /// Table of unnamed constants associated with a parent `Decl`. | 67 | /// Table of unnamed constants associated with a parent `Decl`. |
| 65 | /// We store them here so that we can free the constants whenever the `Decl` | 68 | /// We store them here so that we can free the constants whenever the `Decl` |
| ... | @@ -770,8 +773,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node) | ... | @@ -770,8 +773,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node) |
| 770 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); | 773 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); |
| 771 | } | 774 | } |
| 772 | self.syms.items[atom.sym_index.?].value = off; | 775 | self.syms.items[atom.sym_index.?].value = off; |
| 773 | if (mod.decl_exports.get(decl_index)) |exports| { | 776 | if (self.decl_exports.get(decl_index)) |export_indices| { |
| 774 | try self.addDeclExports(mod, decl_index, exports.items); | 777 | try self.addDeclExports(mod, decl_index, export_indices); |
| 775 | } | 778 | } |
| 776 | } | 779 | } |
| 777 | } | 780 | } |
| ... | @@ -836,8 +839,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node) | ... | @@ -836,8 +839,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node) |
| 836 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); | 839 | mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian()); |
| 837 | } | 840 | } |
| 838 | self.syms.items[atom.sym_index.?].value = off; | 841 | self.syms.items[atom.sym_index.?].value = off; |
| 839 | if (mod.decl_exports.get(decl_index)) |exports| { | 842 | if (self.decl_exports.get(decl_index)) |export_indices| { |
| 840 | try self.addDeclExports(mod, decl_index, exports.items); | 843 | try self.addDeclExports(mod, decl_index, export_indices); |
| 841 | } | 844 | } |
| 842 | } | 845 | } |
| 843 | // write the unnamed constants after the other data decls | 846 | // write the unnamed constants after the other data decls |
| ... | @@ -1007,20 +1010,21 @@ fn addDeclExports( | ... | @@ -1007,20 +1010,21 @@ fn addDeclExports( |
| 1007 | self: *Plan9, | 1010 | self: *Plan9, |
| 1008 | mod: *Module, | 1011 | mod: *Module, |
| 1009 | decl_index: InternPool.DeclIndex, | 1012 | decl_index: InternPool.DeclIndex, |
| 1010 | exports: []const *Module.Export, | 1013 | export_indices: []const u32, |
| 1011 | ) !void { | 1014 | ) !void { |
| 1012 | const gpa = self.base.comp.gpa; | 1015 | const gpa = self.base.comp.gpa; |
| 1013 | const metadata = self.decls.getPtr(decl_index).?; | 1016 | const metadata = self.decls.getPtr(decl_index).?; |
| 1014 | const atom = self.getAtom(metadata.index); | 1017 | const atom = self.getAtom(metadata.index); |
| 1015 | 1018 | ||
| 1016 | for (exports) |exp| { | 1019 | for (export_indices) |export_idx| { |
| 1020 | const exp = mod.all_exports.items[export_idx]; | ||
| 1017 | const exp_name = exp.opts.name.toSlice(&mod.intern_pool); | 1021 | const exp_name = exp.opts.name.toSlice(&mod.intern_pool); |
| 1018 | // plan9 does not support custom sections | 1022 | // plan9 does not support custom sections |
| 1019 | if (exp.opts.section.unwrap()) |section_name| { | 1023 | if (exp.opts.section.unwrap()) |section_name| { |
| 1020 | if (!section_name.eqlSlice(".text", &mod.intern_pool) and | 1024 | if (!section_name.eqlSlice(".text", &mod.intern_pool) and |
| 1021 | !section_name.eqlSlice(".data", &mod.intern_pool)) | 1025 | !section_name.eqlSlice(".data", &mod.intern_pool)) |
| 1022 | { | 1026 | { |
| 1023 | try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create( | 1027 | try mod.failed_exports.put(mod.gpa, export_idx, try Module.ErrorMsg.create( |
| 1024 | gpa, | 1028 | gpa, |
| 1025 | mod.declPtr(decl_index).navSrcLoc(mod).upgrade(mod), | 1029 | mod.declPtr(decl_index).navSrcLoc(mod).upgrade(mod), |
| 1026 | "plan9 does not support extra sections", | 1030 | "plan9 does not support extra sections", |
| ... | @@ -1152,15 +1156,23 @@ pub fn updateExports( | ... | @@ -1152,15 +1156,23 @@ pub fn updateExports( |
| 1152 | self: *Plan9, | 1156 | self: *Plan9, |
| 1153 | module: *Module, | 1157 | module: *Module, |
| 1154 | exported: Module.Exported, | 1158 | exported: Module.Exported, |
| 1155 | exports: []const *Module.Export, | 1159 | export_indices: []const u32, |
| 1156 | ) !void { | 1160 | ) !void { |
| 1161 | const gpa = self.base.comp.gpa; | ||
| 1157 | switch (exported) { | 1162 | switch (exported) { |
| 1158 | .value => @panic("TODO: plan9 updateExports handling values"), | 1163 | .value => @panic("TODO: plan9 updateExports handling values"), |
| 1159 | .decl_index => |decl_index| _ = try self.seeDecl(decl_index), | 1164 | .decl_index => |decl_index| { |
| 1165 | _ = try self.seeDecl(decl_index); | ||
| 1166 | if (self.decl_exports.fetchSwapRemove(decl_index)) |kv| { | ||
| 1167 | gpa.free(kv.value); | ||
| 1168 | } | ||
| 1169 | try self.decl_exports.ensureUnusedCapacity(gpa, 1); | ||
| 1170 | const duped_indices = try gpa.dupe(u32, export_indices); | ||
| 1171 | self.decl_exports.putAssumeCapacityNoClobber(decl_index, duped_indices); | ||
| 1172 | }, | ||
| 1160 | } | 1173 | } |
| 1161 | // we do all the things in flush | 1174 | // all proper work is done in flush |
| 1162 | _ = module; | 1175 | _ = module; |
| 1163 | _ = exports; | ||
| 1164 | } | 1176 | } |
| 1165 | 1177 | ||
| 1166 | pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index { | 1178 | pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index { |
| ... | @@ -1290,6 +1302,10 @@ pub fn deinit(self: *Plan9) void { | ... | @@ -1290,6 +1302,10 @@ pub fn deinit(self: *Plan9) void { |
| 1290 | gpa.free(self.syms.items[sym_index].name); | 1302 | gpa.free(self.syms.items[sym_index].name); |
| 1291 | } | 1303 | } |
| 1292 | self.data_decl_table.deinit(gpa); | 1304 | self.data_decl_table.deinit(gpa); |
| 1305 | for (self.decl_exports.values()) |export_indices| { | ||
| 1306 | gpa.free(export_indices); | ||
| 1307 | } | ||
| 1308 | self.decl_exports.deinit(gpa); | ||
| 1293 | self.syms.deinit(gpa); | 1309 | self.syms.deinit(gpa); |
| 1294 | self.got_index_free_list.deinit(gpa); | 1310 | self.got_index_free_list.deinit(gpa); |
| 1295 | self.syms_index_free_list.deinit(gpa); | 1311 | self.syms_index_free_list.deinit(gpa); |
| ... | @@ -1395,10 +1411,13 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -1395,10 +1411,13 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 1395 | const atom = self.getAtom(decl_metadata.index); | 1411 | const atom = self.getAtom(decl_metadata.index); |
| 1396 | const sym = self.syms.items[atom.sym_index.?]; | 1412 | const sym = self.syms.items[atom.sym_index.?]; |
| 1397 | try self.writeSym(writer, sym); | 1413 | try self.writeSym(writer, sym); |
| 1398 | if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { | 1414 | if (self.decl_exports.get(decl_index)) |export_indices| { |
| 1399 | for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| { | 1415 | for (export_indices) |export_idx| { |
| 1400 | try self.writeSym(writer, self.syms.items[exp_i]); | 1416 | const exp = mod.all_exports.items[export_idx]; |
| 1401 | }; | 1417 | if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { |
| 1418 | try self.writeSym(writer, self.syms.items[exp_i]); | ||
| 1419 | } | ||
| 1420 | } | ||
| 1402 | } | 1421 | } |
| 1403 | } | 1422 | } |
| 1404 | } | 1423 | } |
| ... | @@ -1442,13 +1461,16 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -1442,13 +1461,16 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 1442 | const atom = self.getAtom(decl_metadata.index); | 1461 | const atom = self.getAtom(decl_metadata.index); |
| 1443 | const sym = self.syms.items[atom.sym_index.?]; | 1462 | const sym = self.syms.items[atom.sym_index.?]; |
| 1444 | try self.writeSym(writer, sym); | 1463 | try self.writeSym(writer, sym); |
| 1445 | if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| { | 1464 | if (self.decl_exports.get(decl_index)) |export_indices| { |
| 1446 | for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| { | 1465 | for (export_indices) |export_idx| { |
| 1447 | const s = self.syms.items[exp_i]; | 1466 | const exp = mod.all_exports.items[export_idx]; |
| 1448 | if (mem.eql(u8, s.name, "_start")) | 1467 | if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| { |
| 1449 | self.entry_val = s.value; | 1468 | const s = self.syms.items[exp_i]; |
| 1450 | try self.writeSym(writer, s); | 1469 | if (mem.eql(u8, s.name, "_start")) |
| 1451 | }; | 1470 | self.entry_val = s.value; |
| 1471 | try self.writeSym(writer, s); | ||
| 1472 | } | ||
| 1473 | } | ||
| 1452 | } | 1474 | } |
| 1453 | } | 1475 | } |
| 1454 | } | 1476 | } |
src/link/SpirV.zig+3-2| ... | @@ -152,7 +152,7 @@ pub fn updateExports( | ... | @@ -152,7 +152,7 @@ pub fn updateExports( |
| 152 | self: *SpirV, | 152 | self: *SpirV, |
| 153 | mod: *Module, | 153 | mod: *Module, |
| 154 | exported: Module.Exported, | 154 | exported: Module.Exported, |
| 155 | exports: []const *Module.Export, | 155 | export_indices: []const u32, |
| 156 | ) !void { | 156 | ) !void { |
| 157 | const decl_index = switch (exported) { | 157 | const decl_index = switch (exported) { |
| 158 | .decl_index => |i| i, | 158 | .decl_index => |i| i, |
| ... | @@ -177,7 +177,8 @@ pub fn updateExports( | ... | @@ -177,7 +177,8 @@ pub fn updateExports( |
| 177 | if ((!is_vulkan and execution_model == .Kernel) or | 177 | if ((!is_vulkan and execution_model == .Kernel) or |
| 178 | (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex))) | 178 | (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex))) |
| 179 | { | 179 | { |
| 180 | for (exports) |exp| { | 180 | for (export_indices) |export_idx| { |
| 181 | const exp = mod.all_exports.items[export_idx]; | ||
| 181 | try self.object.spv.declareEntryPoint( | 182 | try self.object.spv.declareEntryPoint( |
| 182 | spv_decl_index, | 183 | spv_decl_index, |
| 183 | exp.opts.name.toSlice(&mod.intern_pool), | 184 | exp.opts.name.toSlice(&mod.intern_pool), |
src/link/Wasm.zig+6-6| ... | @@ -1542,26 +1542,26 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin | ... | @@ -1542,26 +1542,26 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin |
| 1542 | return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info); | 1542 | return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info); |
| 1543 | } | 1543 | } |
| 1544 | 1544 | ||
| 1545 | pub fn deleteDeclExport( | 1545 | pub fn deleteExport( |
| 1546 | wasm: *Wasm, | 1546 | wasm: *Wasm, |
| 1547 | decl_index: InternPool.DeclIndex, | 1547 | exported: Zcu.Exported, |
| 1548 | name: InternPool.NullTerminatedString, | 1548 | name: InternPool.NullTerminatedString, |
| 1549 | ) void { | 1549 | ) void { |
| 1550 | if (wasm.llvm_object) |_| return; | 1550 | if (wasm.llvm_object) |_| return; |
| 1551 | return wasm.zigObjectPtr().?.deleteDeclExport(wasm, decl_index, name); | 1551 | return wasm.zigObjectPtr().?.deleteExport(wasm, exported, name); |
| 1552 | } | 1552 | } |
| 1553 | 1553 | ||
| 1554 | pub fn updateExports( | 1554 | pub fn updateExports( |
| 1555 | wasm: *Wasm, | 1555 | wasm: *Wasm, |
| 1556 | mod: *Module, | 1556 | mod: *Module, |
| 1557 | exported: Module.Exported, | 1557 | exported: Module.Exported, |
| 1558 | exports: []const *Module.Export, | 1558 | export_indices: []const u32, |
| 1559 | ) !void { | 1559 | ) !void { |
| 1560 | if (build_options.skip_non_native and builtin.object_format != .wasm) { | 1560 | if (build_options.skip_non_native and builtin.object_format != .wasm) { |
| 1561 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 1561 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 1562 | } | 1562 | } |
| 1563 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); | 1563 | if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices); |
| 1564 | return wasm.zigObjectPtr().?.updateExports(wasm, mod, exported, exports); | 1564 | return wasm.zigObjectPtr().?.updateExports(wasm, mod, exported, export_indices); |
| 1565 | } | 1565 | } |
| 1566 | 1566 | ||
| 1567 | pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { | 1567 | pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { |
src/link/Wasm/ZigObject.zig+11-6| ... | @@ -833,13 +833,17 @@ pub fn getAnonDeclVAddr( | ... | @@ -833,13 +833,17 @@ pub fn getAnonDeclVAddr( |
| 833 | return target_symbol_index; | 833 | return target_symbol_index; |
| 834 | } | 834 | } |
| 835 | 835 | ||
| 836 | pub fn deleteDeclExport( | 836 | pub fn deleteExport( |
| 837 | zig_object: *ZigObject, | 837 | zig_object: *ZigObject, |
| 838 | wasm_file: *Wasm, | 838 | wasm_file: *Wasm, |
| 839 | decl_index: InternPool.DeclIndex, | 839 | exported: Zcu.Exported, |
| 840 | name: InternPool.NullTerminatedString, | 840 | name: InternPool.NullTerminatedString, |
| 841 | ) void { | 841 | ) void { |
| 842 | const mod = wasm_file.base.comp.module.?; | 842 | const mod = wasm_file.base.comp.module.?; |
| 843 | const decl_index = switch (exported) { | ||
| 844 | .decl_index => |decl_index| decl_index, | ||
| 845 | .value => @panic("TODO: implement Wasm linker code for exporting a constant value"), | ||
| 846 | }; | ||
| 843 | const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return; | 847 | const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return; |
| 844 | if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| { | 848 | if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| { |
| 845 | const sym = zig_object.symbol(sym_index); | 849 | const sym = zig_object.symbol(sym_index); |
| ... | @@ -856,7 +860,7 @@ pub fn updateExports( | ... | @@ -856,7 +860,7 @@ pub fn updateExports( |
| 856 | wasm_file: *Wasm, | 860 | wasm_file: *Wasm, |
| 857 | mod: *Module, | 861 | mod: *Module, |
| 858 | exported: Module.Exported, | 862 | exported: Module.Exported, |
| 859 | exports: []const *Module.Export, | 863 | export_indices: []const u32, |
| 860 | ) !void { | 864 | ) !void { |
| 861 | const decl_index = switch (exported) { | 865 | const decl_index = switch (exported) { |
| 862 | .decl_index => |i| i, | 866 | .decl_index => |i| i, |
| ... | @@ -873,9 +877,10 @@ pub fn updateExports( | ... | @@ -873,9 +877,10 @@ pub fn updateExports( |
| 873 | const gpa = mod.gpa; | 877 | const gpa = mod.gpa; |
| 874 | log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)}); | 878 | log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)}); |
| 875 | 879 | ||
| 876 | for (exports) |exp| { | 880 | for (export_indices) |export_idx| { |
| 881 | const exp = mod.all_exports.items[export_idx]; | ||
| 877 | if (exp.opts.section.toSlice(&mod.intern_pool)) |section| { | 882 | if (exp.opts.section.toSlice(&mod.intern_pool)) |section| { |
| 878 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | 883 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create( |
| 879 | gpa, | 884 | gpa, |
| 880 | decl.navSrcLoc(mod).upgrade(mod), | 885 | decl.navSrcLoc(mod).upgrade(mod), |
| 881 | "Unimplemented: ExportOptions.section '{s}'", | 886 | "Unimplemented: ExportOptions.section '{s}'", |
| ... | @@ -908,7 +913,7 @@ pub fn updateExports( | ... | @@ -908,7 +913,7 @@ pub fn updateExports( |
| 908 | }, | 913 | }, |
| 909 | .strong => {}, // symbols are strong by default | 914 | .strong => {}, // symbols are strong by default |
| 910 | .link_once => { | 915 | .link_once => { |
| 911 | try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create( | 916 | try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create( |
| 912 | gpa, | 917 | gpa, |
| 913 | decl.navSrcLoc(mod).upgrade(mod), | 918 | decl.navSrcLoc(mod).upgrade(mod), |
| 914 | "Unimplemented: LinkOnce", | 919 | "Unimplemented: LinkOnce", |