authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-04 23:22:09-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
log943dac3e8558712096d55a30897057d75444178c
tree71642efb143c8811cd59c407479dfacbc9723942
parent9bf715de74a7d5badeae932afb594b7c6b33afa3

compiler: add type safety for export indices


18 files changed, 213 insertions(+), 126 deletions(-)

src/Sema.zig+5-5
...@@ -38298,7 +38298,7 @@ pub fn flushExports(sema: *Sema) !void {...@@ -38298,7 +38298,7 @@ pub fn flushExports(sema: *Sema) !void {
38298 // So, pick up and delete any existing exports. This strategy performs38298 // So, pick up and delete any existing exports. This strategy performs
38299 // redundant work, but that's okay, because this case is exceedingly rare.38299 // redundant work, but that's okay, because this case is exceedingly rare.
38300 if (zcu.single_exports.get(sema.owner)) |export_idx| {38300 if (zcu.single_exports.get(sema.owner)) |export_idx| {
38301 try sema.exports.append(gpa, zcu.all_exports.items[export_idx]);38301 try sema.exports.append(gpa, export_idx.ptr(zcu).*);
38302 } else if (zcu.multi_exports.get(sema.owner)) |info| {38302 } else if (zcu.multi_exports.get(sema.owner)) |info| {
38303 try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]);38303 try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]);
38304 }38304 }
...@@ -38307,12 +38307,12 @@ pub fn flushExports(sema: *Sema) !void {...@@ -38307,12 +38307,12 @@ pub fn flushExports(sema: *Sema) !void {
38307 // `sema.exports` is completed; store the data into the `Zcu`.38307 // `sema.exports` is completed; store the data into the `Zcu`.
38308 if (sema.exports.items.len == 1) {38308 if (sema.exports.items.len == 1) {
38309 try zcu.single_exports.ensureUnusedCapacity(gpa, 1);38309 try zcu.single_exports.ensureUnusedCapacity(gpa, 1);
38310 const export_idx = zcu.free_exports.popOrNull() orelse idx: {38310 const export_idx: Zcu.Export.Index = zcu.free_exports.popOrNull() orelse idx: {
38311 _ = try zcu.all_exports.addOne(gpa);38311 _ = try zcu.all_exports.addOne(gpa);
38312 break :idx zcu.all_exports.items.len - 1;38312 break :idx @enumFromInt(zcu.all_exports.items.len - 1);
38313 };38313 };
38314 zcu.all_exports.items[export_idx] = sema.exports.items[0];38314 export_idx.ptr(zcu).* = sema.exports.items[0];
38315 zcu.single_exports.putAssumeCapacityNoClobber(sema.owner, @intCast(export_idx));38315 zcu.single_exports.putAssumeCapacityNoClobber(sema.owner, export_idx);
38316 } else {38316 } else {
38317 try zcu.multi_exports.ensureUnusedCapacity(gpa, 1);38317 try zcu.multi_exports.ensureUnusedCapacity(gpa, 1);
38318 const exports_base = zcu.all_exports.items.len;38318 const exports_base = zcu.all_exports.items.len;
src/Zcu.zig+11-13
...@@ -79,11 +79,11 @@ local_zir_cache: Compilation.Directory,...@@ -79,11 +79,11 @@ local_zir_cache: Compilation.Directory,
79all_exports: std.ArrayListUnmanaged(Export) = .empty,79all_exports: std.ArrayListUnmanaged(Export) = .empty,
80/// This is a list of free indices in `all_exports`. These indices may be reused by exports from80/// This is a list of free indices in `all_exports`. These indices may be reused by exports from
81/// future semantic analysis.81/// future semantic analysis.
82free_exports: std.ArrayListUnmanaged(u32) = .empty,82free_exports: std.ArrayListUnmanaged(Export.Index) = .empty,
83/// Maps from an `AnalUnit` which performs a single export, to the index into `all_exports` of83/// Maps from an `AnalUnit` which performs a single export, to the index into `all_exports` of
84/// the export it performs. Note that the key is not the `Decl` being exported, but the `AnalUnit`84/// the export it performs. Note that the key is not the `Decl` being exported, but the `AnalUnit`
85/// whose analysis triggered the export.85/// whose analysis triggered the export.
86single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty,86single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, Export.Index) = .empty,
87/// Like `single_exports`, but for `AnalUnit`s which perform multiple exports.87/// Like `single_exports`, but for `AnalUnit`s which perform multiple exports.
88/// The exports are `all_exports.items[index..][0..len]`.88/// The exports are `all_exports.items[index..][0..len]`.
89multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {89multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
...@@ -145,8 +145,7 @@ compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {...@@ -145,8 +145,7 @@ compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
145failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .empty,145failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .empty,
146/// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator.146/// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator.
147failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .empty,147failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .empty,
148/// Key is index into `all_exports`.148failed_exports: std.AutoArrayHashMapUnmanaged(Export.Index, *ErrorMsg) = .empty,
149failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .empty,
150/// If analysis failed due to a cimport error, the corresponding Clang errors149/// If analysis failed due to a cimport error, the corresponding Clang errors
151/// are stored here.150/// are stored here.
152cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .empty,151cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .empty,
...@@ -3101,7 +3100,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3101,7 +3100,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
3101 const gpa = zcu.gpa;3100 const gpa = zcu.gpa;
31023101
3103 const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv|3102 const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv|
3104 .{ kv.value, 1 }3103 .{ @intFromEnum(kv.value), 1 }
3105 else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info|3104 else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info|
3106 .{ info.value.index, info.value.len }3105 .{ info.value.index, info.value.len }
3107 else3106 else
...@@ -3115,11 +3114,12 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3115,11 +3114,12 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
3115 // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports3114 // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports
3116 // within a single update.3115 // within a single update.
3117 if (dev.env.supports(.incremental)) {3116 if (dev.env.supports(.incremental)) {
3118 for (exports, exports_base..) |exp, export_idx| {3117 for (exports, exports_base..) |exp, export_index_usize| {
3118 const export_idx: Export.Index = @enumFromInt(export_index_usize);
3119 if (zcu.comp.bin_file) |lf| {3119 if (zcu.comp.bin_file) |lf| {
3120 lf.deleteExport(exp.exported, exp.opts.name);3120 lf.deleteExport(exp.exported, exp.opts.name);
3121 }3121 }
3122 if (zcu.failed_exports.fetchSwapRemove(@intCast(export_idx))) |failed_kv| {3122 if (zcu.failed_exports.fetchSwapRemove(export_idx)) |failed_kv| {
3123 failed_kv.value.destroy(gpa);3123 failed_kv.value.destroy(gpa);
3124 }3124 }
3125 }3125 }
...@@ -3131,7 +3131,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3131,7 +3131,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
3131 return;3131 return;
3132 };3132 };
3133 for (exports_base..exports_base + exports_len) |export_idx| {3133 for (exports_base..exports_base + exports_len) |export_idx| {
3134 zcu.free_exports.appendAssumeCapacity(@intCast(export_idx));3134 zcu.free_exports.appendAssumeCapacity(@enumFromInt(export_idx));
3135 }3135 }
3136}3136}
31373137
...@@ -3277,7 +3277,7 @@ fn lockAndClearFileCompileError(zcu: *Zcu, file: *File) void {...@@ -3277,7 +3277,7 @@ fn lockAndClearFileCompileError(zcu: *Zcu, file: *File) void {
32773277
3278pub fn handleUpdateExports(3278pub fn handleUpdateExports(
3279 zcu: *Zcu,3279 zcu: *Zcu,
3280 export_indices: []const u32,3280 export_indices: []const Export.Index,
3281 result: link.File.UpdateExportsError!void,3281 result: link.File.UpdateExportsError!void,
3282) Allocator.Error!void {3282) Allocator.Error!void {
3283 const gpa = zcu.gpa;3283 const gpa = zcu.gpa;
...@@ -3285,12 +3285,10 @@ pub fn handleUpdateExports(...@@ -3285,12 +3285,10 @@ pub fn handleUpdateExports(
3285 error.OutOfMemory => return error.OutOfMemory,3285 error.OutOfMemory => return error.OutOfMemory,
3286 error.AnalysisFail => {3286 error.AnalysisFail => {
3287 const export_idx = export_indices[0];3287 const export_idx = export_indices[0];
3288 const new_export = &zcu.all_exports.items[export_idx];3288 const new_export = export_idx.ptr(zcu);
3289 new_export.status = .failed_retryable;3289 new_export.status = .failed_retryable;
3290 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);3290 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
3291 const msg = try ErrorMsg.create(gpa, new_export.src, "unable to export: {s}", .{3291 const msg = try ErrorMsg.create(gpa, new_export.src, "unable to export: {s}", .{@errorName(err)});
3292 @errorName(err),
3293 });
3294 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);3292 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);
3295 },3293 },
3296 };3294 };
src/Zcu/PerThread.zig+8-8
...@@ -2815,8 +2815,8 @@ pub fn processExports(pt: Zcu.PerThread) !void {...@@ -2815,8 +2815,8 @@ pub fn processExports(pt: Zcu.PerThread) !void {
2815 const gpa = zcu.gpa;2815 const gpa = zcu.gpa;
28162816
2817 // First, construct a mapping of every exported value and Nav to the indices of all its different exports.2817 // First, construct a mapping of every exported value and Nav to the indices of all its different exports.
2818 var nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, std.ArrayListUnmanaged(u32)) = .empty;2818 var nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, std.ArrayListUnmanaged(Zcu.Export.Index)) = .empty;
2819 var uav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, std.ArrayListUnmanaged(u32)) = .empty;2819 var uav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, std.ArrayListUnmanaged(Zcu.Export.Index)) = .empty;
2820 defer {2820 defer {
2821 for (nav_exports.values()) |*exports| {2821 for (nav_exports.values()) |*exports| {
2822 exports.deinit(gpa);2822 exports.deinit(gpa);
...@@ -2835,7 +2835,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {...@@ -2835,7 +2835,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
2835 try nav_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count());2835 try nav_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count());
28362836
2837 for (zcu.single_exports.values()) |export_idx| {2837 for (zcu.single_exports.values()) |export_idx| {
2838 const exp = zcu.all_exports.items[export_idx];2838 const exp = export_idx.ptr(zcu);
2839 const value_ptr, const found_existing = switch (exp.exported) {2839 const value_ptr, const found_existing = switch (exp.exported) {
2840 .nav => |nav| gop: {2840 .nav => |nav| gop: {
2841 const gop = try nav_exports.getOrPut(gpa, nav);2841 const gop = try nav_exports.getOrPut(gpa, nav);
...@@ -2863,7 +2863,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {...@@ -2863,7 +2863,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
2863 },2863 },
2864 };2864 };
2865 if (!found_existing) value_ptr.* = .{};2865 if (!found_existing) value_ptr.* = .{};
2866 try value_ptr.append(gpa, @intCast(export_idx));2866 try value_ptr.append(gpa, @enumFromInt(export_idx));
2867 }2867 }
2868 }2868 }
28692869
...@@ -2882,20 +2882,20 @@ pub fn processExports(pt: Zcu.PerThread) !void {...@@ -2882,20 +2882,20 @@ pub fn processExports(pt: Zcu.PerThread) !void {
2882 }2882 }
2883}2883}
28842884
2885const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, u32);2885const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, Zcu.Export.Index);
28862886
2887fn processExportsInner(2887fn processExportsInner(
2888 pt: Zcu.PerThread,2888 pt: Zcu.PerThread,
2889 symbol_exports: *SymbolExports,2889 symbol_exports: *SymbolExports,
2890 exported: Zcu.Exported,2890 exported: Zcu.Exported,
2891 export_indices: []const u32,2891 export_indices: []const Zcu.Export.Index,
2892) error{OutOfMemory}!void {2892) error{OutOfMemory}!void {
2893 const zcu = pt.zcu;2893 const zcu = pt.zcu;
2894 const gpa = zcu.gpa;2894 const gpa = zcu.gpa;
2895 const ip = &zcu.intern_pool;2895 const ip = &zcu.intern_pool;
28962896
2897 for (export_indices) |export_idx| {2897 for (export_indices) |export_idx| {
2898 const new_export = &zcu.all_exports.items[export_idx];2898 const new_export = export_idx.ptr(zcu);
2899 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);2899 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);
2900 if (gop.found_existing) {2900 if (gop.found_existing) {
2901 new_export.status = .failed_retryable;2901 new_export.status = .failed_retryable;
...@@ -2904,7 +2904,7 @@ fn processExportsInner(...@@ -2904,7 +2904,7 @@ fn processExportsInner(
2904 new_export.opts.name.fmt(ip),2904 new_export.opts.name.fmt(ip),
2905 });2905 });
2906 errdefer msg.destroy(gpa);2906 errdefer msg.destroy(gpa);
2907 const other_export = zcu.all_exports.items[gop.value_ptr.*];2907 const other_export = gop.value_ptr.ptr(zcu);
2908 try zcu.errNote(other_export.src, msg, "other symbol here", .{});2908 try zcu.errNote(other_export.src, msg, "other symbol here", .{});
2909 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);2909 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);
2910 new_export.status = .failed;2910 new_export.status = .failed;
src/arch/wasm/CodeGen.zig+8-15
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const ArrayList = std.ArrayList;
5const assert = std.debug.assert;4const assert = std.debug.assert;
6const testing = std.testing;5const testing = std.testing;
7const leb = std.leb;6const leb = std.leb;
...@@ -631,7 +630,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {...@@ -631,7 +630,7 @@ blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, struct {
631/// Maps `loop` instructions to their label. `br` to here repeats the loop.630/// Maps `loop` instructions to their label. `br` to here repeats the loop.
632loops: std.AutoHashMapUnmanaged(Air.Inst.Index, u32) = .empty,631loops: std.AutoHashMapUnmanaged(Air.Inst.Index, u32) = .empty,
633/// `bytes` contains the wasm bytecode belonging to the 'code' section.632/// `bytes` contains the wasm bytecode belonging to the 'code' section.
634code: *ArrayList(u8),633code: *std.ArrayListUnmanaged(u8),
635/// The index the next local generated will have634/// The index the next local generated will have
636/// NOTE: arguments share the index with locals therefore the first variable635/// NOTE: arguments share the index with locals therefore the first variable
637/// will have the index that comes after the last argument's index636/// will have the index that comes after the last argument's index
...@@ -639,8 +638,6 @@ local_index: u32 = 0,...@@ -639,8 +638,6 @@ local_index: u32 = 0,
639/// The index of the current argument.638/// The index of the current argument.
640/// Used to track which argument is being referenced in `airArg`.639/// Used to track which argument is being referenced in `airArg`.
641arg_index: u32 = 0,640arg_index: u32 = 0,
642/// If codegen fails, an error messages will be allocated and saved in `err_msg`
643err_msg: *Zcu.ErrorMsg,
644/// List of all locals' types generated throughout this declaration641/// List of all locals' types generated throughout this declaration
645/// used to emit locals count at start of 'code' section.642/// used to emit locals count at start of 'code' section.
646locals: std.ArrayListUnmanaged(u8),643locals: std.ArrayListUnmanaged(u8),
...@@ -732,10 +729,9 @@ pub fn deinit(func: *CodeGen) void {...@@ -732,10 +729,9 @@ pub fn deinit(func: *CodeGen) void {
732 func.* = undefined;729 func.* = undefined;
733}730}
734731
735/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig732fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
736fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {733 const msg = try Zcu.ErrorMsg.create(func.gpa, func.src_loc, fmt, args);
737 func.err_msg = try Zcu.ErrorMsg.create(func.gpa, func.src_loc, fmt, args);734 return func.pt.zcu.codegenFailMsg(func.owner_nav, msg);
738 return error.CodegenFail;
739}735}
740736
741/// Resolves the `WValue` for the given instruction `inst`737/// Resolves the `WValue` for the given instruction `inst`
...@@ -1173,9 +1169,9 @@ pub fn generate(...@@ -1173,9 +1169,9 @@ pub fn generate(
1173 func_index: InternPool.Index,1169 func_index: InternPool.Index,
1174 air: Air,1170 air: Air,
1175 liveness: Liveness,1171 liveness: Liveness,
1176 code: *std.ArrayList(u8),1172 code: *std.ArrayListUnmanaged(u8),
1177 debug_output: link.File.DebugInfoOutput,1173 debug_output: link.File.DebugInfoOutput,
1178) codegen.CodeGenError!codegen.Result {1174) codegen.CodeGenError!void {
1179 const zcu = pt.zcu;1175 const zcu = pt.zcu;
1180 const gpa = zcu.gpa;1176 const gpa = zcu.gpa;
1181 const func = zcu.funcInfo(func_index);1177 const func = zcu.funcInfo(func_index);
...@@ -1189,7 +1185,6 @@ pub fn generate(...@@ -1189,7 +1185,6 @@ pub fn generate(
1189 .code = code,1185 .code = code,
1190 .owner_nav = func.owner_nav,1186 .owner_nav = func.owner_nav,
1191 .src_loc = src_loc,1187 .src_loc = src_loc,
1192 .err_msg = undefined,
1193 .locals = .{},1188 .locals = .{},
1194 .target = target,1189 .target = target,
1195 .bin_file = bin_file.cast(.wasm).?,1190 .bin_file = bin_file.cast(.wasm).?,
...@@ -1199,11 +1194,9 @@ pub fn generate(...@@ -1199,11 +1194,9 @@ pub fn generate(
1199 defer code_gen.deinit();1194 defer code_gen.deinit();
12001195
1201 genFunc(&code_gen) catch |err| switch (err) {1196 genFunc(&code_gen) catch |err| switch (err) {
1202 error.CodegenFail => return codegen.Result{ .fail = code_gen.err_msg },1197 error.CodegenFail => return error.CodegenFail,
1203 else => |e| return e,1198 else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),
1204 };1199 };
1205
1206 return codegen.Result.ok;
1207}1200}
12081201
1209fn genFunc(func: *CodeGen) InnerError!void {1202fn genFunc(func: *CodeGen) InnerError!void {
src/arch/wasm/Mir.zig+4-4
...@@ -80,15 +80,15 @@ pub const Inst = struct {...@@ -80,15 +80,15 @@ pub const Inst = struct {
80 ///80 ///
81 /// Uses `nop`81 /// Uses `nop`
82 @"return" = 0x0F,82 @"return" = 0x0F,
83 /// Calls a function using `nav_index`.
84 call_nav,
85 /// Calls a function using `func_index`.
86 call_func,
87 /// Calls a function pointer by its function signature83 /// Calls a function pointer by its function signature
88 /// and index into the function table.84 /// and index into the function table.
89 ///85 ///
90 /// Uses `label`86 /// Uses `label`
91 call_indirect = 0x11,87 call_indirect = 0x11,
88 /// Calls a function using `nav_index`.
89 call_nav,
90 /// Calls a function using `func_index`.
91 call_func,
92 /// Calls a function by its index.92 /// Calls a function by its index.
93 ///93 ///
94 /// The function is the auto-generated tag name function for the type94 /// The function is the auto-generated tag name function for the type
src/codegen/c.zig+4-4
...@@ -3052,12 +3052,12 @@ pub fn genDeclValue(...@@ -3052,12 +3052,12 @@ pub fn genDeclValue(
3052 try w.writeAll(";\n");3052 try w.writeAll(";\n");
3053}3053}
30543054
3055pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const u32) !void {3055pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void {
3056 const zcu = dg.pt.zcu;3056 const zcu = dg.pt.zcu;
3057 const ip = &zcu.intern_pool;3057 const ip = &zcu.intern_pool;
3058 const fwd = dg.fwdDeclWriter();3058 const fwd = dg.fwdDeclWriter();
30593059
3060 const main_name = zcu.all_exports.items[export_indices[0]].opts.name;3060 const main_name = export_indices[0].ptr(zcu).opts.name;
3061 try fwd.writeAll("#define ");3061 try fwd.writeAll("#define ");
3062 switch (exported) {3062 switch (exported) {
3063 .nav => |nav| try dg.renderNavName(fwd, nav),3063 .nav => |nav| try dg.renderNavName(fwd, nav),
...@@ -3069,7 +3069,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3069,7 +3069,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
30693069
3070 const exported_val = exported.getValue(zcu);3070 const exported_val = exported.getValue(zcu);
3071 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {3071 if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| {
3072 const @"export" = &zcu.all_exports.items[export_index];3072 const @"export" = export_index.ptr(zcu);
3073 try fwd.writeAll("zig_extern ");3073 try fwd.writeAll("zig_extern ");
3074 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");3074 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
3075 try dg.renderFunctionSignature(3075 try dg.renderFunctionSignature(
...@@ -3091,7 +3091,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const...@@ -3091,7 +3091,7 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const
3091 else => true,3091 else => true,
3092 };3092 };
3093 for (export_indices) |export_index| {3093 for (export_indices) |export_index| {
3094 const @"export" = &zcu.all_exports.items[export_index];3094 const @"export" = export_index.ptr(zcu);
3095 try fwd.writeAll("zig_extern ");3095 try fwd.writeAll("zig_extern ");
3096 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");3096 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
3097 const extern_name = @"export".opts.name.toSlice(ip);3097 const extern_name = @"export".opts.name.toSlice(ip);
src/codegen/llvm.zig+1-1
...@@ -1810,7 +1810,7 @@ pub const Object = struct {...@@ -1810,7 +1810,7 @@ pub const Object = struct {
1810 self: *Object,1810 self: *Object,
1811 pt: Zcu.PerThread,1811 pt: Zcu.PerThread,
1812 exported: Zcu.Exported,1812 exported: Zcu.Exported,
1813 export_indices: []const u32,1813 export_indices: []const Zcu.Export.Index,
1814 ) link.File.UpdateExportsError!void {1814 ) link.File.UpdateExportsError!void {
1815 assert(std.meta.eql(pt, self.pt));1815 assert(std.meta.eql(pt, self.pt));
1816 const zcu = pt.zcu;1816 const zcu = pt.zcu;
src/link.zig+1-1
...@@ -817,7 +817,7 @@ pub const File = struct {...@@ -817,7 +817,7 @@ pub const File = struct {
817 base: *File,817 base: *File,
818 pt: Zcu.PerThread,818 pt: Zcu.PerThread,
819 exported: Zcu.Exported,819 exported: Zcu.Exported,
820 export_indices: []const u32,820 export_indices: []const Zcu.Export.Index,
821 ) UpdateExportsError!void {821 ) UpdateExportsError!void {
822 switch (base.tag) {822 switch (base.tag) {
823 inline else => |tag| {823 inline else => |tag| {
src/link/C.zig+1-1
...@@ -840,7 +840,7 @@ pub fn updateExports(...@@ -840,7 +840,7 @@ pub fn updateExports(
840 self: *C,840 self: *C,
841 pt: Zcu.PerThread,841 pt: Zcu.PerThread,
842 exported: Zcu.Exported,842 exported: Zcu.Exported,
843 export_indices: []const u32,843 export_indices: []const Zcu.Export.Index,
844) !void {844) !void {
845 const zcu = pt.zcu;845 const zcu = pt.zcu;
846 const gpa = zcu.gpa;846 const gpa = zcu.gpa;
src/link/Elf.zig+1-1
...@@ -2393,7 +2393,7 @@ pub fn updateExports(...@@ -2393,7 +2393,7 @@ pub fn updateExports(
2393 self: *Elf,2393 self: *Elf,
2394 pt: Zcu.PerThread,2394 pt: Zcu.PerThread,
2395 exported: Zcu.Exported,2395 exported: Zcu.Exported,
2396 export_indices: []const u32,2396 export_indices: []const Zcu.Export.Index,
2397) link.File.UpdateExportsError!void {2397) link.File.UpdateExportsError!void {
2398 if (build_options.skip_non_native and builtin.object_format != .elf) {2398 if (build_options.skip_non_native and builtin.object_format != .elf) {
2399 @panic("Attempted to compile for object format that was disabled by build configuration");2399 @panic("Attempted to compile for object format that was disabled by build configuration");
src/link/Elf/ZigObject.zig+1-1
...@@ -1745,7 +1745,7 @@ pub fn updateExports(...@@ -1745,7 +1745,7 @@ pub fn updateExports(
1745 elf_file: *Elf,1745 elf_file: *Elf,
1746 pt: Zcu.PerThread,1746 pt: Zcu.PerThread,
1747 exported: Zcu.Exported,1747 exported: Zcu.Exported,
1748 export_indices: []const u32,1748 export_indices: []const Zcu.Export.Index,
1749) link.File.UpdateExportsError!void {1749) link.File.UpdateExportsError!void {
1750 const tracy = trace(@src());1750 const tracy = trace(@src());
1751 defer tracy.end();1751 defer tracy.end();
src/link/MachO.zig+1-1
...@@ -3056,7 +3056,7 @@ pub fn updateExports(...@@ -3056,7 +3056,7 @@ pub fn updateExports(
3056 self: *MachO,3056 self: *MachO,
3057 pt: Zcu.PerThread,3057 pt: Zcu.PerThread,
3058 exported: Zcu.Exported,3058 exported: Zcu.Exported,
3059 export_indices: []const u32,3059 export_indices: []const Zcu.Export.Index,
3060) link.File.UpdateExportsError!void {3060) link.File.UpdateExportsError!void {
3061 if (build_options.skip_non_native and builtin.object_format != .macho) {3061 if (build_options.skip_non_native and builtin.object_format != .macho) {
3062 @panic("Attempted to compile for object format that was disabled by build configuration");3062 @panic("Attempted to compile for object format that was disabled by build configuration");
src/link/MachO/ZigObject.zig+1-1
...@@ -1246,7 +1246,7 @@ pub fn updateExports(...@@ -1246,7 +1246,7 @@ pub fn updateExports(
1246 macho_file: *MachO,1246 macho_file: *MachO,
1247 pt: Zcu.PerThread,1247 pt: Zcu.PerThread,
1248 exported: Zcu.Exported,1248 exported: Zcu.Exported,
1249 export_indices: []const u32,1249 export_indices: []const Zcu.Export.Index,
1250) link.File.UpdateExportsError!void {1250) link.File.UpdateExportsError!void {
1251 const tracy = trace(@src());1251 const tracy = trace(@src());
1252 defer tracy.end();1252 defer tracy.end();
src/link/NvPtx.zig+1-1
...@@ -100,7 +100,7 @@ pub fn updateExports(...@@ -100,7 +100,7 @@ pub fn updateExports(
100 self: *NvPtx,100 self: *NvPtx,
101 pt: Zcu.PerThread,101 pt: Zcu.PerThread,
102 exported: Zcu.Exported,102 exported: Zcu.Exported,
103 export_indices: []const u32,103 export_indices: []const Zcu.Export.Index,
104) !void {104) !void {
105 if (build_options.skip_non_native and builtin.object_format != .nvptx)105 if (build_options.skip_non_native and builtin.object_format != .nvptx)
106 @panic("Attempted to compile for object format that was disabled by build configuration");106 @panic("Attempted to compile for object format that was disabled by build configuration");
src/link/Plan9.zig+3-3
...@@ -60,7 +60,7 @@ fn_nav_table: std.AutoArrayHashMapUnmanaged(...@@ -60,7 +60,7 @@ fn_nav_table: std.AutoArrayHashMapUnmanaged(
60data_nav_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u8) = .empty,60data_nav_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u8) = .empty,
61/// When `updateExports` is called, we store the export indices here, to be used61/// When `updateExports` is called, we store the export indices here, to be used
62/// during flush.62/// during flush.
63nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []u32) = .empty,63nav_exports: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, []Zcu.Export.Index) = .empty,
6464
65lazy_syms: LazySymbolTable = .{},65lazy_syms: LazySymbolTable = .{},
6666
...@@ -1007,7 +1007,7 @@ pub fn updateExports(...@@ -1007,7 +1007,7 @@ pub fn updateExports(
1007 self: *Plan9,1007 self: *Plan9,
1008 pt: Zcu.PerThread,1008 pt: Zcu.PerThread,
1009 exported: Zcu.Exported,1009 exported: Zcu.Exported,
1010 export_indices: []const u32,1010 export_indices: []const Zcu.Export.Index,
1011) !void {1011) !void {
1012 const gpa = self.base.comp.gpa;1012 const gpa = self.base.comp.gpa;
1013 switch (exported) {1013 switch (exported) {
...@@ -1018,7 +1018,7 @@ pub fn updateExports(...@@ -1018,7 +1018,7 @@ pub fn updateExports(
1018 gpa.free(kv.value);1018 gpa.free(kv.value);
1019 }1019 }
1020 try self.nav_exports.ensureUnusedCapacity(gpa, 1);1020 try self.nav_exports.ensureUnusedCapacity(gpa, 1);
1021 const duped_indices = try gpa.dupe(u32, export_indices);1021 const duped_indices = try gpa.dupe(Zcu.Export.Index, export_indices);
1022 self.nav_exports.putAssumeCapacityNoClobber(nav, duped_indices);1022 self.nav_exports.putAssumeCapacityNoClobber(nav, duped_indices);
1023 },1023 },
1024 }1024 }
src/link/SpirV.zig+2-2
...@@ -155,7 +155,7 @@ pub fn updateExports(...@@ -155,7 +155,7 @@ pub fn updateExports(
155 self: *SpirV,155 self: *SpirV,
156 pt: Zcu.PerThread,156 pt: Zcu.PerThread,
157 exported: Zcu.Exported,157 exported: Zcu.Exported,
158 export_indices: []const u32,158 export_indices: []const Zcu.Export.Index,
159) !void {159) !void {
160 const zcu = pt.zcu;160 const zcu = pt.zcu;
161 const ip = &zcu.intern_pool;161 const ip = &zcu.intern_pool;
...@@ -190,7 +190,7 @@ pub fn updateExports(...@@ -190,7 +190,7 @@ pub fn updateExports(
190 };190 };
191191
192 for (export_indices) |export_idx| {192 for (export_indices) |export_idx| {
193 const exp = zcu.all_exports.items[export_idx];193 const exp = export_idx.ptr(zcu);
194 try self.object.spv.declareEntryPoint(194 try self.object.spv.declareEntryPoint(
195 spv_decl_index,195 spv_decl_index,
196 exp.opts.name.toSlice(ip),196 exp.opts.name.toSlice(ip),
src/link/Wasm.zig+155-58
...@@ -56,6 +56,10 @@ base: link.File,...@@ -56,6 +56,10 @@ base: link.File,
56/// string_table entries for them. Alternately those sites could be moved to56/// string_table entries for them. Alternately those sites could be moved to
57/// use a different byte array for this purpose.57/// use a different byte array for this purpose.
58string_bytes: std.ArrayListUnmanaged(u8),58string_bytes: std.ArrayListUnmanaged(u8),
59/// Sometimes we have logic that wants to borrow string bytes to store
60/// arbitrary things in there. In this case it is not allowed to intern new
61/// strings during this time. This safety lock is used to detect misuses.
62string_bytes_lock: std.debug.SafetyLock = .{},
59/// Omitted when serializing linker state.63/// Omitted when serializing linker state.
60string_table: String.Table,64string_table: String.Table,
61/// Symbol name of the entry function to export65/// Symbol name of the entry function to export
...@@ -202,6 +206,10 @@ any_exports_updated: bool = true,...@@ -202,6 +206,10 @@ any_exports_updated: bool = true,
202/// Index into `objects`.206/// Index into `objects`.
203pub const ObjectIndex = enum(u32) {207pub const ObjectIndex = enum(u32) {
204 _,208 _,
209
210 pub fn ptr(index: ObjectIndex, wasm: *const Wasm) *Object {
211 return &wasm.objects.items[@intFromEnum(index)];
212 }
205};213};
206214
207/// Index into `functions`.215/// Index into `functions`.
...@@ -269,12 +277,26 @@ pub const SourceLocation = enum(u32) {...@@ -269,12 +277,26 @@ pub const SourceLocation = enum(u32) {
269 };277 };
270 }278 }
271279
280 pub fn unpack(sl: SourceLocation, wasm: *const Wasm) Unpacked {
281 return switch (sl) {
282 .zig_object_nofile => .zig_object_nofile,
283 .none => .none,
284 _ => {
285 const i = @intFromEnum(sl);
286 if (i < wasm.objects.items.len) return .{ .object_index = @enumFromInt(i) };
287 const sl_index = i - wasm.objects.items.len;
288 _ = sl_index;
289 @panic("TODO");
290 },
291 };
292 }
293
272 pub fn addError(sl: SourceLocation, wasm: *Wasm, comptime f: []const u8, args: anytype) void {294 pub fn addError(sl: SourceLocation, wasm: *Wasm, comptime f: []const u8, args: anytype) void {
273 const diags = &wasm.base.comp.link_diags;295 const diags = &wasm.base.comp.link_diags;
274 switch (sl.unpack(wasm)) {296 switch (sl.unpack(wasm)) {
275 .none => unreachable,297 .none => unreachable,
276 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),298 .zig_object_nofile => diags.addError("zig compilation unit: " ++ f, args),
277 .object_index => |i| diags.addError("{}: " ++ f, .{wasm.objects.items[i].path} ++ args),299 .object_index => |i| diags.addError("{}: " ++ f, .{i.ptr(wasm).path} ++ args),
278 .source_location_index => @panic("TODO"),300 .source_location_index => @panic("TODO"),
279 }301 }
280 }302 }
...@@ -520,6 +542,10 @@ pub const FunctionImport = extern struct {...@@ -520,6 +542,10 @@ pub const FunctionImport = extern struct {
520 /// Index into `object_function_imports`.542 /// Index into `object_function_imports`.
521 pub const Index = enum(u32) {543 pub const Index = enum(u32) {
522 _,544 _,
545
546 pub fn ptr(index: FunctionImport.Index, wasm: *const Wasm) *FunctionImport {
547 return &wasm.object_function_imports.items[@intFromEnum(index)];
548 }
523 };549 };
524};550};
525551
...@@ -543,7 +569,8 @@ pub const GlobalImport = extern struct {...@@ -543,7 +569,8 @@ pub const GlobalImport = extern struct {
543 source_location: SourceLocation,569 source_location: SourceLocation,
544 resolution: Resolution,570 resolution: Resolution,
545571
546 /// Represents a synthetic global, or a global from an object.572 /// Represents a synthetic global, a global from an object, or a global
573 /// from the Zcu.
547 pub const Resolution = enum(u32) {574 pub const Resolution = enum(u32) {
548 unresolved,575 unresolved,
549 __heap_base,576 __heap_base,
...@@ -556,6 +583,68 @@ pub const GlobalImport = extern struct {...@@ -556,6 +583,68 @@ pub const GlobalImport = extern struct {
556 // Next, index into `object_globals`.583 // Next, index into `object_globals`.
557 // Next, index into `navs`.584 // Next, index into `navs`.
558 _,585 _,
586
587 const first_object_global = @intFromEnum(Resolution.__zig_error_name_table) + 1;
588
589 pub const Unpacked = union(enum) {
590 unresolved,
591 __heap_base,
592 __heap_end,
593 __stack_pointer,
594 __tls_align,
595 __tls_base,
596 __tls_size,
597 __zig_error_name_table,
598 object_global: ObjectGlobalIndex,
599 nav: Nav.Index,
600 };
601
602 pub fn unpack(r: Resolution, wasm: *const Wasm) Unpacked {
603 return switch (r) {
604 .unresolved => .unresolved,
605 .__wasm_apply_global_tls_relocs => .__wasm_apply_global_tls_relocs,
606 .__wasm_call_ctors => .__wasm_call_ctors,
607 .__wasm_init_memory => .__wasm_init_memory,
608 .__wasm_init_tls => .__wasm_init_tls,
609 .__zig_error_names => .__zig_error_names,
610 _ => {
611 const i: u32 = @intFromEnum(r);
612 const object_global_index = i - first_object_global;
613 if (object_global_index < wasm.object_globals.items.len)
614 return .{ .object_global = @enumFromInt(object_global_index) };
615 const nav_index = object_global_index - wasm.object_globals.items.len;
616 return .{ .nav = @enumFromInt(nav_index) };
617 },
618 };
619 }
620
621 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Resolution {
622 return switch (unpacked) {
623 .unresolved => .unresolved,
624 .__heap_base => .__heap_base,
625 .__heap_end => .__heap_end,
626 .__stack_pointer => .__stack_pointer,
627 .__tls_align => .__tls_align,
628 .__tls_base => .__tls_base,
629 .__tls_size => .__tls_size,
630 .__zig_error_name_table => .__zig_error_name_table,
631 .object_global => |i| @enumFromInt(first_object_global + @intFromEnum(i)),
632 .nav => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)),
633 };
634 }
635
636 pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution {
637 return pack(wasm, .{ .nav = @enumFromInt(wasm.navs.getIndex(ip_nav).?) });
638 }
639 };
640
641 /// Index into `object_global_imports`.
642 pub const Index = enum(u32) {
643 _,
644
645 pub fn ptr(index: Index, wasm: *const Wasm) *GlobalImport {
646 return &wasm.object_global_imports.items[@intFromEnum(index)];
647 }
559 };648 };
560};649};
561650
...@@ -634,20 +723,6 @@ pub const ObjectSectionIndex = enum(u32) {...@@ -634,20 +723,6 @@ pub const ObjectSectionIndex = enum(u32) {
634 _,723 _,
635};724};
636725
637/// Index into `object_function_imports`.
638pub const ObjectFunctionImportIndex = enum(u32) {
639 _,
640
641 pub fn ptr(index: ObjectFunctionImportIndex, wasm: *const Wasm) *FunctionImport {
642 return &wasm.object_function_imports.items[@intFromEnum(index)];
643 }
644};
645
646/// Index into `object_global_imports`.
647pub const ObjectGlobalImportIndex = enum(u32) {
648 _,
649};
650
651/// Index into `object_table_imports`.726/// Index into `object_table_imports`.
652pub const ObjectTableImportIndex = enum(u32) {727pub const ObjectTableImportIndex = enum(u32) {
653 _,728 _,
...@@ -861,11 +936,35 @@ pub const ValtypeList = enum(u32) {...@@ -861,11 +936,35 @@ pub const ValtypeList = enum(u32) {
861 }936 }
862};937};
863938
939/// Index into `imports`.
940pub const ZcuImportIndex = enum(u32) {
941 _,
942};
943
864/// 0. Index into `object_function_imports`.944/// 0. Index into `object_function_imports`.
865/// 1. Index into `imports`.945/// 1. Index into `imports`.
866pub const FunctionImportId = enum(u32) {946pub const FunctionImportId = enum(u32) {
867 _,947 _,
868948
949 pub const Unpacked = union(enum) {
950 object_function_import: FunctionImport.Index,
951 zcu_import: ZcuImportIndex,
952 };
953
954 pub fn pack(unpacked: Unpacked, wasm: *const Wasm) FunctionImportId {
955 return switch (unpacked) {
956 .object_function_import => |i| @enumFromInt(@intFromEnum(i)),
957 .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_function_imports.entries.len),
958 };
959 }
960
961 pub fn unpack(id: FunctionImportId, wasm: *const Wasm) Unpacked {
962 const i = @intFromEnum(id);
963 if (i < wasm.object_function_imports.entries.len) return .{ .object_function_import = @enumFromInt(i) };
964 const zcu_import_i = i - wasm.object_function_imports.entries.len;
965 return .{ .zcu_import = @enumFromInt(zcu_import_i) };
966 }
967
869 /// This function is allowed O(N) lookup because it is only called during968 /// This function is allowed O(N) lookup because it is only called during
870 /// diagnostic generation.969 /// diagnostic generation.
871 pub fn sourceLocation(id: FunctionImportId, wasm: *const Wasm) SourceLocation {970 pub fn sourceLocation(id: FunctionImportId, wasm: *const Wasm) SourceLocation {
...@@ -873,10 +972,10 @@ pub const FunctionImportId = enum(u32) {...@@ -873,10 +972,10 @@ pub const FunctionImportId = enum(u32) {
873 .object_function_import => |obj_func_index| {972 .object_function_import => |obj_func_index| {
874 // TODO binary search973 // TODO binary search
875 for (wasm.objects.items, 0..) |o, i| {974 for (wasm.objects.items, 0..) |o, i| {
876 if (o.function_imports.off <= obj_func_index and975 if (o.function_imports.off <= @intFromEnum(obj_func_index) and
877 o.function_imports.off + o.function_imports.len > obj_func_index)976 o.function_imports.off + o.function_imports.len > @intFromEnum(obj_func_index))
878 {977 {
879 return .pack(wasm, .{ .object_index = @enumFromInt(i) });978 return .pack(.{ .object_index = @enumFromInt(i) }, wasm);
880 }979 }
881 } else unreachable;980 } else unreachable;
882 },981 },
...@@ -890,17 +989,36 @@ pub const FunctionImportId = enum(u32) {...@@ -890,17 +989,36 @@ pub const FunctionImportId = enum(u32) {
890pub const GlobalImportId = enum(u32) {989pub const GlobalImportId = enum(u32) {
891 _,990 _,
892991
992 pub const Unpacked = union(enum) {
993 object_global_import: GlobalImport.Index,
994 zcu_import: ZcuImportIndex,
995 };
996
997 pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId {
998 return switch (unpacked) {
999 .object_global_import => |i| @enumFromInt(@intFromEnum(i)),
1000 .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_global_imports.entries.len),
1001 };
1002 }
1003
1004 pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked {
1005 const i = @intFromEnum(id);
1006 if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @enumFromInt(i) };
1007 const zcu_import_i = i - wasm.object_global_imports.entries.len;
1008 return .{ .zcu_import = @enumFromInt(zcu_import_i) };
1009 }
1010
893 /// This function is allowed O(N) lookup because it is only called during1011 /// This function is allowed O(N) lookup because it is only called during
894 /// diagnostic generation.1012 /// diagnostic generation.
895 pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation {1013 pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation {
896 switch (id.unpack(wasm)) {1014 switch (id.unpack(wasm)) {
897 .object_global_import => |obj_func_index| {1015 .object_global_import => |obj_global_index| {
898 // TODO binary search1016 // TODO binary search
899 for (wasm.objects.items, 0..) |o, i| {1017 for (wasm.objects.items, 0..) |o, i| {
900 if (o.global_imports.off <= obj_func_index and1018 if (o.global_imports.off <= @intFromEnum(obj_global_index) and
901 o.global_imports.off + o.global_imports.len > obj_func_index)1019 o.global_imports.off + o.global_imports.len > @intFromEnum(obj_global_index))
902 {1020 {
903 return .pack(wasm, .{ .object_index = @enumFromInt(i) });1021 return .pack(.{ .object_index = @enumFromInt(i) }, wasm);
904 }1022 }
905 } else unreachable;1023 } else unreachable;
906 },1024 },
...@@ -1330,23 +1448,13 @@ pub fn deinit(wasm: *Wasm) void {...@@ -1330,23 +1448,13 @@ pub fn deinit(wasm: *Wasm) void {
1330 wasm.object_memories.deinit(gpa);1448 wasm.object_memories.deinit(gpa);
13311449
1332 wasm.object_data_segments.deinit(gpa);1450 wasm.object_data_segments.deinit(gpa);
1333 wasm.object_relocatable_codes.deinit(gpa);
1334 wasm.object_custom_segments.deinit(gpa);1451 wasm.object_custom_segments.deinit(gpa);
1335 wasm.object_symbols.deinit(gpa);
1336 wasm.object_named_segments.deinit(gpa);
1337 wasm.object_init_funcs.deinit(gpa);1452 wasm.object_init_funcs.deinit(gpa);
1338 wasm.object_comdats.deinit(gpa);1453 wasm.object_comdats.deinit(gpa);
1339 wasm.object_relocations.deinit(gpa);
1340 wasm.object_relocations_table.deinit(gpa);1454 wasm.object_relocations_table.deinit(gpa);
1341 wasm.object_comdat_symbols.deinit(gpa);1455 wasm.object_comdat_symbols.deinit(gpa);
1342 wasm.objects.deinit(gpa);1456 wasm.objects.deinit(gpa);
13431457
1344 wasm.synthetic_symbols.deinit(gpa);
1345 wasm.undefs.deinit(gpa);
1346 wasm.discarded.deinit(gpa);
1347 wasm.segments.deinit(gpa);
1348 wasm.segment_info.deinit(gpa);
1349
1350 wasm.func_types.deinit(gpa);1458 wasm.func_types.deinit(gpa);
1351 wasm.function_exports.deinit(gpa);1459 wasm.function_exports.deinit(gpa);
1352 wasm.function_imports.deinit(gpa);1460 wasm.function_imports.deinit(gpa);
...@@ -1354,8 +1462,6 @@ pub fn deinit(wasm: *Wasm) void {...@@ -1354,8 +1462,6 @@ pub fn deinit(wasm: *Wasm) void {
1354 wasm.globals.deinit(gpa);1462 wasm.globals.deinit(gpa);
1355 wasm.global_imports.deinit(gpa);1463 wasm.global_imports.deinit(gpa);
1356 wasm.table_imports.deinit(gpa);1464 wasm.table_imports.deinit(gpa);
1357 wasm.output_globals.deinit(gpa);
1358 wasm.exports.deinit(gpa);
13591465
1360 wasm.string_bytes.deinit(gpa);1466 wasm.string_bytes.deinit(gpa);
1361 wasm.string_table.deinit(gpa);1467 wasm.string_table.deinit(gpa);
...@@ -1374,12 +1480,11 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -1374,12 +1480,11 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
1374 const nav_index = func.owner_nav;1480 const nav_index = func.owner_nav;
13751481
1376 const code_start: u32 = @intCast(wasm.string_bytes.items.len);1482 const code_start: u32 = @intCast(wasm.string_bytes.items.len);
1377 const relocs_start: u32 = @intCast(wasm.relocations.items.len);1483 const relocs_start: u32 = @intCast(wasm.relocations.len);
1378 wasm.string_bytes_lock.lock();1484 wasm.string_bytes_lock.lock();
13791485
1380 const wasm_codegen = @import("../../arch/wasm/CodeGen.zig");
1381 dev.check(.wasm_backend);1486 dev.check(.wasm_backend);
1382 const result = try wasm_codegen.generate(1487 try CodeGen.generate(
1383 &wasm.base,1488 &wasm.base,
1384 pt,1489 pt,
1385 zcu.navSrcLoc(nav_index),1490 zcu.navSrcLoc(nav_index),
...@@ -1391,18 +1496,12 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -1391,18 +1496,12 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
1391 );1496 );
13921497
1393 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);1498 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);
1394 const relocs_len: u32 = @intCast(wasm.relocations.items.len - relocs_start);1499 const relocs_len: u32 = @intCast(wasm.relocations.len - relocs_start);
1395 wasm.string_bytes_lock.unlock();1500 wasm.string_bytes_lock.unlock();
13961501
1397 const code: Nav.Code = switch (result) {1502 const code: Nav.Code = .{
1398 .ok => .{1503 .off = code_start,
1399 .off = code_start,1504 .len = code_len,
1400 .len = code_len,
1401 },
1402 .fail => |em| {
1403 try pt.zcu.failed_codegen.put(gpa, nav_index, em);
1404 return;
1405 },
1406 };1505 };
14071506
1408 const gop = try wasm.navs.getOrPut(gpa, nav_index);1507 const gop = try wasm.navs.getOrPut(gpa, nav_index);
...@@ -1445,24 +1544,22 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -1445,24 +1544,22 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
14451544
1446 if (!nav_init.typeOf(zcu).hasRuntimeBits(zcu)) {1545 if (!nav_init.typeOf(zcu).hasRuntimeBits(zcu)) {
1447 _ = wasm.imports.swapRemove(nav_index);1546 _ = wasm.imports.swapRemove(nav_index);
1448 if (wasm.navs.swapRemove(nav_index)) |old| {1547 if (wasm.navs.swapRemove(nav_index)) {
1449 _ = old;
1450 @panic("TODO reclaim resources");1548 @panic("TODO reclaim resources");
1451 }1549 }
1452 return;1550 return;
1453 }1551 }
14541552
1455 if (is_extern) {1553 if (is_extern) {
1456 try wasm.imports.put(nav_index, {});1554 try wasm.imports.put(gpa, nav_index, {});
1457 if (wasm.navs.swapRemove(nav_index)) |old| {1555 if (wasm.navs.swapRemove(nav_index)) {
1458 _ = old;
1459 @panic("TODO reclaim resources");1556 @panic("TODO reclaim resources");
1460 }1557 }
1461 return;1558 return;
1462 }1559 }
14631560
1464 const code_start: u32 = @intCast(wasm.string_bytes.items.len);1561 const code_start: u32 = @intCast(wasm.string_bytes.items.len);
1465 const relocs_start: u32 = @intCast(wasm.relocations.items.len);1562 const relocs_start: u32 = @intCast(wasm.relocations.len);
1466 wasm.string_bytes_lock.lock();1563 wasm.string_bytes_lock.lock();
14671564
1468 const res = try codegen.generateSymbol(1565 const res = try codegen.generateSymbol(
...@@ -1475,7 +1572,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -1475,7 +1572,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
1475 );1572 );
14761573
1477 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);1574 const code_len: u32 = @intCast(wasm.string_bytes.items.len - code_start);
1478 const relocs_len: u32 = @intCast(wasm.relocations.items.len - relocs_start);1575 const relocs_len: u32 = @intCast(wasm.relocations.len - relocs_start);
1479 wasm.string_bytes_lock.unlock();1576 wasm.string_bytes_lock.unlock();
14801577
1481 const code: Nav.Code = switch (res) {1578 const code: Nav.Code = switch (res) {
...@@ -1531,7 +1628,7 @@ pub fn updateExports(...@@ -1531,7 +1628,7 @@ pub fn updateExports(
1531 wasm: *Wasm,1628 wasm: *Wasm,
1532 pt: Zcu.PerThread,1629 pt: Zcu.PerThread,
1533 exported: Zcu.Exported,1630 exported: Zcu.Exported,
1534 export_indices: []const u32,1631 export_indices: []const Zcu.Export.Index,
1535) !void {1632) !void {
1536 if (build_options.skip_non_native and builtin.object_format != .wasm) {1633 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1537 @panic("Attempted to compile for object format that was disabled by build configuration");1634 @panic("Attempted to compile for object format that was disabled by build configuration");
...@@ -1668,7 +1765,7 @@ fn markFunction(...@@ -1668,7 +1765,7 @@ fn markFunction(
1668 wasm: *Wasm,1765 wasm: *Wasm,
1669 name: String,1766 name: String,
1670 import: *FunctionImport,1767 import: *FunctionImport,
1671 func_index: ObjectFunctionImportIndex,1768 func_index: FunctionImport.Index,
1672) error{OutOfMemory}!void {1769) error{OutOfMemory}!void {
1673 if (import.flags.alive) return;1770 if (import.flags.alive) return;
1674 import.flags.alive = true;1771 import.flags.alive = true;
...@@ -1712,7 +1809,7 @@ fn markGlobal(...@@ -1712,7 +1809,7 @@ fn markGlobal(
1712 wasm: *Wasm,1809 wasm: *Wasm,
1713 name: String,1810 name: String,
1714 import: *GlobalImport,1811 import: *GlobalImport,
1715 global_index: ObjectGlobalImportIndex,1812 global_index: GlobalImport.Index,
1716) !void {1813) !void {
1717 if (import.flags.alive) return;1814 if (import.flags.alive) return;
1718 import.flags.alive = true;1815 import.flags.alive = true;
src/link/Wasm/Flush.zig+5-6
...@@ -137,13 +137,12 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void {...@@ -137,13 +137,12 @@ pub fn finish(f: *Flush, wasm: *Wasm, arena: Allocator) anyerror!void {
137137
138 // Merge and order the data segments. Depends on garbage collection so that138 // Merge and order the data segments. Depends on garbage collection so that
139 // unused segments can be omitted.139 // unused segments can be omitted.
140 try f.ensureUnusedCapacity(gpa, wasm.object_data_segments.items.len);140 try f.data_segments.ensureUnusedCapacity(gpa, wasm.object_data_segments.items.len);
141 for (wasm.object_data_segments.items, 0..) |*ds, i| {141 for (wasm.object_data_segments.items, 0..) |*ds, i| {
142 if (!ds.flags.alive) continue;142 if (!ds.flags.alive) continue;
143 const data_segment_index: Wasm.DataSegment.Index = @enumFromInt(i);
143 any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !isBss(wasm, ds.name));144 any_passive_inits = any_passive_inits or ds.flags.is_passive or (import_memory and !isBss(wasm, ds.name));
144 f.data_segments.putAssumeCapacityNoClobber(@intCast(i), .{145 f.data_segments.putAssumeCapacityNoClobber(data_segment_index, .{ .offset = undefined });
145 .offset = undefined,
146 });
147 }146 }
148147
149 try wasm.functions.ensureUnusedCapacity(gpa, 3);148 try wasm.functions.ensureUnusedCapacity(gpa, 3);
...@@ -1082,8 +1081,8 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8)...@@ -1082,8 +1081,8 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *std.ArrayListUnmanaged(u8)
1082// try writeCustomSectionHeader(binary_bytes.items, header_offset, size);1081// try writeCustomSectionHeader(binary_bytes.items, header_offset, size);
1083//}1082//}
10841083
1085fn isBss(wasm: *Wasm, name: String) bool {1084fn isBss(wasm: *Wasm, optional_name: Wasm.OptionalString) bool {
1086 const s = name.slice(wasm);1085 const s = optional_name.slice(wasm) orelse return false;
1087 return mem.eql(u8, s, ".bss") or mem.startsWith(u8, s, ".bss.");1086 return mem.eql(u8, s, ".bss") or mem.startsWith(u8, s, ".bss.");
1088}1087}
10891088