authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-19 22:39:21-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
logee999d5a14c925b71d4b8c216bf1bd7c1b55e00f
tree9fe8c4e215a6bfa179135d807069a2d7cec601dc
parent7bf53d236d29776b524a3abb65e3f042237e0141

implement error table and error names data segments


2 files changed, 74 insertions(+), 19 deletions(-)

src/link/Wasm.zig+25-13
...@@ -253,6 +253,13 @@ all_zcu_locals: std.ArrayListUnmanaged(u8) = .empty,...@@ -253,6 +253,13 @@ all_zcu_locals: std.ArrayListUnmanaged(u8) = .empty,
253params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,253params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
254returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,254returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
255255
256/// All Zcu error names in order, null-terminated, concatenated. No need to
257/// serialize; trivially reconstructed.
258error_name_bytes: std.ArrayListUnmanaged(u8) = .empty,
259/// For each Zcu error, in order, offset into `error_name_bytes` where the name
260/// is stored. No need to serialize; trivially reconstructed.
261error_name_offs: std.ArrayListUnmanaged(u32) = .empty,
262
256pub const UavFixup = extern struct {263pub const UavFixup = extern struct {
257 uavs_exe_index: UavsExeIndex,264 uavs_exe_index: UavsExeIndex,
258 /// Index into `string_bytes`.265 /// Index into `string_bytes`.
...@@ -979,12 +986,11 @@ pub const GlobalImport = extern struct {...@@ -979,12 +986,11 @@ pub const GlobalImport = extern struct {
979 __tls_align,986 __tls_align,
980 __tls_base,987 __tls_base,
981 __tls_size,988 __tls_size,
982 __zig_error_name_table,
983 // Next, index into `object_globals`.989 // Next, index into `object_globals`.
984 // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.990 // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
985 _,991 _,
986992
987 const first_object_global = @intFromEnum(Resolution.__zig_error_name_table) + 1;993 const first_object_global = @intFromEnum(Resolution.__tls_size) + 1;
988994
989 pub const Unpacked = union(enum) {995 pub const Unpacked = union(enum) {
990 unresolved,996 unresolved,
...@@ -994,7 +1000,6 @@ pub const GlobalImport = extern struct {...@@ -994,7 +1000,6 @@ pub const GlobalImport = extern struct {
994 __tls_align,1000 __tls_align,
995 __tls_base,1001 __tls_base,
996 __tls_size,1002 __tls_size,
997 __zig_error_name_table,
998 object_global: ObjectGlobalIndex,1003 object_global: ObjectGlobalIndex,
999 nav_exe: NavsExeIndex,1004 nav_exe: NavsExeIndex,
1000 nav_obj: NavsObjIndex,1005 nav_obj: NavsObjIndex,
...@@ -1009,7 +1014,6 @@ pub const GlobalImport = extern struct {...@@ -1009,7 +1014,6 @@ pub const GlobalImport = extern struct {
1009 .__tls_align => .__tls_align,1014 .__tls_align => .__tls_align,
1010 .__tls_base => .__tls_base,1015 .__tls_base => .__tls_base,
1011 .__tls_size => .__tls_size,1016 .__tls_size => .__tls_size,
1012 .__zig_error_name_table => .__zig_error_name_table,
1013 _ => {1017 _ => {
1014 const i: u32 = @intFromEnum(r);1018 const i: u32 = @intFromEnum(r);
1015 const object_global_index = i - first_object_global;1019 const object_global_index = i - first_object_global;
...@@ -1036,7 +1040,6 @@ pub const GlobalImport = extern struct {...@@ -1036,7 +1040,6 @@ pub const GlobalImport = extern struct {
1036 .__tls_align => .__tls_align,1040 .__tls_align => .__tls_align,
1037 .__tls_base => .__tls_base,1041 .__tls_base => .__tls_base,
1038 .__tls_size => .__tls_size,1042 .__tls_size => .__tls_size,
1039 .__zig_error_name_table => .__zig_error_name_table,
1040 .object_global => |i| @enumFromInt(first_object_global + @intFromEnum(i)),1043 .object_global => |i| @enumFromInt(first_object_global + @intFromEnum(i)),
1041 .nav_obj => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)),1044 .nav_obj => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)),
1042 .nav_exe => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)),1045 .nav_exe => |i| @enumFromInt(first_object_global + wasm.object_globals.items.len + @intFromEnum(i)),
...@@ -1062,7 +1065,6 @@ pub const GlobalImport = extern struct {...@@ -1062,7 +1065,6 @@ pub const GlobalImport = extern struct {
1062 .__tls_align => @tagName(Unpacked.__tls_align),1065 .__tls_align => @tagName(Unpacked.__tls_align),
1063 .__tls_base => @tagName(Unpacked.__tls_base),1066 .__tls_base => @tagName(Unpacked.__tls_base),
1064 .__tls_size => @tagName(Unpacked.__tls_size),1067 .__tls_size => @tagName(Unpacked.__tls_size),
1065 .__zig_error_name_table => @tagName(Unpacked.__zig_error_name_table),
1066 .object_global => |i| i.name(wasm).slice(wasm),1068 .object_global => |i| i.name(wasm).slice(wasm),
1067 .nav_obj => |i| i.name(wasm),1069 .nav_obj => |i| i.name(wasm),
1068 .nav_exe => |i| i.name(wasm),1070 .nav_exe => |i| i.name(wasm),
...@@ -1332,6 +1334,7 @@ pub const DataSegment = extern struct {...@@ -1332,6 +1334,7 @@ pub const DataSegment = extern struct {
1332 };1334 };
13331335
1334 pub const Id = enum(u32) {1336 pub const Id = enum(u32) {
1337 __zig_error_names,
1335 __zig_error_name_table,1338 __zig_error_name_table,
1336 /// First, an `ObjectDataSegmentIndex`.1339 /// First, an `ObjectDataSegmentIndex`.
1337 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.1340 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
...@@ -1341,6 +1344,7 @@ pub const DataSegment = extern struct {...@@ -1341,6 +1344,7 @@ pub const DataSegment = extern struct {
1341 const first_object = @intFromEnum(Id.__zig_error_name_table) + 1;1344 const first_object = @intFromEnum(Id.__zig_error_name_table) + 1;
13421345
1343 pub const Unpacked = union(enum) {1346 pub const Unpacked = union(enum) {
1347 __zig_error_names,
1344 __zig_error_name_table,1348 __zig_error_name_table,
1345 object: ObjectDataSegmentIndex,1349 object: ObjectDataSegmentIndex,
1346 uav_exe: UavsExeIndex,1350 uav_exe: UavsExeIndex,
...@@ -1351,6 +1355,7 @@ pub const DataSegment = extern struct {...@@ -1351,6 +1355,7 @@ pub const DataSegment = extern struct {
13511355
1352 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Id {1356 pub fn pack(wasm: *const Wasm, unpacked: Unpacked) Id {
1353 return switch (unpacked) {1357 return switch (unpacked) {
1358 .__zig_error_names => .__zig_error_names,
1354 .__zig_error_name_table => .__zig_error_name_table,1359 .__zig_error_name_table => .__zig_error_name_table,
1355 .object => |i| @enumFromInt(first_object + @intFromEnum(i)),1360 .object => |i| @enumFromInt(first_object + @intFromEnum(i)),
1356 inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)),1361 inline .uav_exe, .uav_obj => |i| @enumFromInt(first_object + wasm.object_data_segments.items.len + @intFromEnum(i)),
...@@ -1361,6 +1366,7 @@ pub const DataSegment = extern struct {...@@ -1361,6 +1366,7 @@ pub const DataSegment = extern struct {
13611366
1362 pub fn unpack(id: Id, wasm: *const Wasm) Unpacked {1367 pub fn unpack(id: Id, wasm: *const Wasm) Unpacked {
1363 return switch (id) {1368 return switch (id) {
1369 .__zig_error_names => .__zig_error_names,
1364 .__zig_error_name_table => .__zig_error_name_table,1370 .__zig_error_name_table => .__zig_error_name_table,
1365 _ => {1371 _ => {
1366 const object_index = @intFromEnum(id) - first_object;1372 const object_index = @intFromEnum(id) - first_object;
...@@ -1393,7 +1399,7 @@ pub const DataSegment = extern struct {...@@ -1393,7 +1399,7 @@ pub const DataSegment = extern struct {
13931399
1394 pub fn category(id: Id, wasm: *const Wasm) Category {1400 pub fn category(id: Id, wasm: *const Wasm) Category {
1395 return switch (unpack(id, wasm)) {1401 return switch (unpack(id, wasm)) {
1396 .__zig_error_name_table => .data,1402 .__zig_error_names, .__zig_error_name_table => .data,
1397 .object => |i| {1403 .object => |i| {
1398 const ptr = i.ptr(wasm);1404 const ptr = i.ptr(wasm);
1399 if (ptr.flags.tls) return .tls;1405 if (ptr.flags.tls) return .tls;
...@@ -1414,7 +1420,7 @@ pub const DataSegment = extern struct {...@@ -1414,7 +1420,7 @@ pub const DataSegment = extern struct {
14141420
1415 pub fn isTls(id: Id, wasm: *const Wasm) bool {1421 pub fn isTls(id: Id, wasm: *const Wasm) bool {
1416 return switch (unpack(id, wasm)) {1422 return switch (unpack(id, wasm)) {
1417 .__zig_error_name_table => false,1423 .__zig_error_names, .__zig_error_name_table => false,
1418 .object => |i| i.ptr(wasm).flags.tls,1424 .object => |i| i.ptr(wasm).flags.tls,
1419 .uav_exe, .uav_obj => false,1425 .uav_exe, .uav_obj => false,
1420 inline .nav_exe, .nav_obj => |i| {1426 inline .nav_exe, .nav_obj => |i| {
...@@ -1432,7 +1438,7 @@ pub const DataSegment = extern struct {...@@ -1432,7 +1438,7 @@ pub const DataSegment = extern struct {
14321438
1433 pub fn name(id: Id, wasm: *const Wasm) []const u8 {1439 pub fn name(id: Id, wasm: *const Wasm) []const u8 {
1434 return switch (unpack(id, wasm)) {1440 return switch (unpack(id, wasm)) {
1435 .__zig_error_name_table, .uav_exe, .uav_obj => ".data",1441 .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj => ".data",
1436 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),1442 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),
1437 inline .nav_exe, .nav_obj => |i| {1443 inline .nav_exe, .nav_obj => |i| {
1438 const zcu = wasm.base.comp.zcu.?;1444 const zcu = wasm.base.comp.zcu.?;
...@@ -1445,6 +1451,7 @@ pub const DataSegment = extern struct {...@@ -1445,6 +1451,7 @@ pub const DataSegment = extern struct {
14451451
1446 pub fn alignment(id: Id, wasm: *const Wasm) Alignment {1452 pub fn alignment(id: Id, wasm: *const Wasm) Alignment {
1447 return switch (unpack(id, wasm)) {1453 return switch (unpack(id, wasm)) {
1454 .__zig_error_names => .@"1",
1448 .__zig_error_name_table => wasm.pointerAlignment(),1455 .__zig_error_name_table => wasm.pointerAlignment(),
1449 .object => |i| i.ptr(wasm).flags.alignment,1456 .object => |i| i.ptr(wasm).flags.alignment,
1450 inline .uav_exe, .uav_obj => |i| {1457 inline .uav_exe, .uav_obj => |i| {
...@@ -1472,6 +1479,7 @@ pub const DataSegment = extern struct {...@@ -1472,6 +1479,7 @@ pub const DataSegment = extern struct {
14721479
1473 pub fn refCount(id: Id, wasm: *const Wasm) u32 {1480 pub fn refCount(id: Id, wasm: *const Wasm) u32 {
1474 return switch (unpack(id, wasm)) {1481 return switch (unpack(id, wasm)) {
1482 .__zig_error_names => @intCast(wasm.error_name_offs.items.len),
1475 .__zig_error_name_table => wasm.error_name_table_ref_count,1483 .__zig_error_name_table => wasm.error_name_table_ref_count,
1476 .object, .uav_obj, .nav_obj => 0,1484 .object, .uav_obj, .nav_obj => 0,
1477 inline .uav_exe, .nav_exe => |i| i.value(wasm).count,1485 inline .uav_exe, .nav_exe => |i| i.value(wasm).count,
...@@ -1481,7 +1489,7 @@ pub const DataSegment = extern struct {...@@ -1481,7 +1489,7 @@ pub const DataSegment = extern struct {
1481 pub fn isPassive(id: Id, wasm: *const Wasm) bool {1489 pub fn isPassive(id: Id, wasm: *const Wasm) bool {
1482 if (wasm.base.comp.config.import_memory and !id.isBss(wasm)) return true;1490 if (wasm.base.comp.config.import_memory and !id.isBss(wasm)) return true;
1483 return switch (unpack(id, wasm)) {1491 return switch (unpack(id, wasm)) {
1484 .__zig_error_name_table => false,1492 .__zig_error_names, .__zig_error_name_table => false,
1485 .object => |i| i.ptr(wasm).flags.is_passive,1493 .object => |i| i.ptr(wasm).flags.is_passive,
1486 .uav_exe, .uav_obj, .nav_exe, .nav_obj => false,1494 .uav_exe, .uav_obj, .nav_exe, .nav_obj => false,
1487 };1495 };
...@@ -1489,7 +1497,7 @@ pub const DataSegment = extern struct {...@@ -1489,7 +1497,7 @@ pub const DataSegment = extern struct {
14891497
1490 pub fn isEmpty(id: Id, wasm: *const Wasm) bool {1498 pub fn isEmpty(id: Id, wasm: *const Wasm) bool {
1491 return switch (unpack(id, wasm)) {1499 return switch (unpack(id, wasm)) {
1492 .__zig_error_name_table => false,1500 .__zig_error_names, .__zig_error_name_table => false,
1493 .object => |i| i.ptr(wasm).payload.off == .none,1501 .object => |i| i.ptr(wasm).payload.off == .none,
1494 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none,1502 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none,
1495 };1503 };
...@@ -1497,10 +1505,11 @@ pub const DataSegment = extern struct {...@@ -1497,10 +1505,11 @@ pub const DataSegment = extern struct {
14971505
1498 pub fn size(id: Id, wasm: *const Wasm) u32 {1506 pub fn size(id: Id, wasm: *const Wasm) u32 {
1499 return switch (unpack(id, wasm)) {1507 return switch (unpack(id, wasm)) {
1508 .__zig_error_names => @intCast(wasm.error_name_bytes.items.len),
1500 .__zig_error_name_table => {1509 .__zig_error_name_table => {
1501 const comp = wasm.base.comp;1510 const comp = wasm.base.comp;
1502 const zcu = comp.zcu.?;1511 const zcu = comp.zcu.?;
1503 const errors_len = 1 + zcu.intern_pool.global_error_set.getNamesFromMainThread().len;1512 const errors_len = wasm.error_name_offs.items.len;
1504 const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu);1513 const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu);
1505 return @intCast(errors_len * elem_size);1514 return @intCast(errors_len * elem_size);
1506 },1515 },
...@@ -1589,8 +1598,8 @@ const PreloadedStrings = struct {...@@ -1589,8 +1598,8 @@ const PreloadedStrings = struct {
1589 __wasm_init_memory: String,1598 __wasm_init_memory: String,
1590 __wasm_init_memory_flag: String,1599 __wasm_init_memory_flag: String,
1591 __wasm_init_tls: String,1600 __wasm_init_tls: String,
1592 __zig_error_name_table: String,
1593 __zig_error_names: String,1601 __zig_error_names: String,
1602 __zig_error_name_table: String,
1594 __zig_errors_len: String,1603 __zig_errors_len: String,
1595 _initialize: String,1604 _initialize: String,
1596 _start: String,1605 _start: String,
...@@ -2367,6 +2376,9 @@ pub fn deinit(wasm: *Wasm) void {...@@ -2367,6 +2376,9 @@ pub fn deinit(wasm: *Wasm) void {
2367 wasm.params_scratch.deinit(gpa);2376 wasm.params_scratch.deinit(gpa);
2368 wasm.returns_scratch.deinit(gpa);2377 wasm.returns_scratch.deinit(gpa);
23692378
2379 wasm.error_name_bytes.deinit(gpa);
2380 wasm.error_name_offs.deinit(gpa);
2381
2370 wasm.missing_exports.deinit(gpa);2382 wasm.missing_exports.deinit(gpa);
2371}2383}
23722384
src/link/Wasm/Flush.zig+49-6
...@@ -71,10 +71,26 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -71,10 +71,26 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
71 };71 };
72 const is_obj = comp.config.output_mode == .Obj;72 const is_obj = comp.config.output_mode == .Obj;
73 const allow_undefined = is_obj or wasm.import_symbols;73 const allow_undefined = is_obj or wasm.import_symbols;
74 const zcu = wasm.base.comp.zcu.?;
75 const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!
7674
77 {75 if (comp.zcu) |zcu| {
76 const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!
77
78 if (wasm.error_name_table_ref_count > 0) {
79 // Ensure Zcu error name structures are populated.
80 const full_error_names = ip.global_error_set.getNamesFromMainThread();
81 try wasm.error_name_offs.ensureTotalCapacity(gpa, full_error_names.len + 1);
82 if (wasm.error_name_offs.items.len == 0) {
83 // Dummy entry at index 0 to avoid a sub instruction at `@errorName` sites.
84 wasm.error_name_offs.appendAssumeCapacity(0);
85 }
86 const new_error_names = full_error_names[wasm.error_name_offs.items.len - 1 ..];
87 for (new_error_names) |error_name| {
88 wasm.error_name_offs.appendAssumeCapacity(@intCast(wasm.error_name_bytes.items.len));
89 const s: [:0]const u8 = error_name.toSlice(ip);
90 try wasm.error_name_bytes.appendSlice(gpa, s[0 .. s.len + 1]);
91 }
92 }
93
78 const entry_name = if (wasm.entry_resolution.isNavOrUnresolved(wasm)) wasm.entry_name else .none;94 const entry_name = if (wasm.entry_resolution.isNavOrUnresolved(wasm)) wasm.entry_name else .none;
7995
80 for (wasm.nav_exports.keys()) |*nav_export| {96 for (wasm.nav_exports.keys()) |*nav_export| {
...@@ -144,7 +160,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -144,7 +160,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
144 // unused segments can be omitted.160 // unused segments can be omitted.
145 try f.data_segments.ensureUnusedCapacity(gpa, wasm.object_data_segments.items.len +161 try f.data_segments.ensureUnusedCapacity(gpa, wasm.object_data_segments.items.len +
146 wasm.uavs_obj.entries.len + wasm.navs_obj.entries.len +162 wasm.uavs_obj.entries.len + wasm.navs_obj.entries.len +
147 wasm.uavs_exe.entries.len + wasm.navs_exe.entries.len + 1);163 wasm.uavs_exe.entries.len + wasm.navs_exe.entries.len + 2);
148 if (is_obj) assert(wasm.uavs_exe.entries.len == 0);164 if (is_obj) assert(wasm.uavs_exe.entries.len == 0);
149 if (is_obj) assert(wasm.navs_exe.entries.len == 0);165 if (is_obj) assert(wasm.navs_exe.entries.len == 0);
150 if (!is_obj) assert(wasm.uavs_obj.entries.len == 0);166 if (!is_obj) assert(wasm.uavs_obj.entries.len == 0);
...@@ -170,6 +186,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -170,6 +186,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
170 }), @as(u32, undefined));186 }), @as(u32, undefined));
171 }187 }
172 if (wasm.error_name_table_ref_count > 0) {188 if (wasm.error_name_table_ref_count > 0) {
189 f.data_segments.putAssumeCapacity(.__zig_error_names, @as(u32, undefined));
173 f.data_segments.putAssumeCapacity(.__zig_error_name_table, @as(u32, undefined));190 f.data_segments.putAssumeCapacity(.__zig_error_name_table, @as(u32, undefined));
174 }191 }
175192
...@@ -546,7 +563,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -546,7 +563,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
546 .__tls_align => @panic("TODO"),563 .__tls_align => @panic("TODO"),
547 .__tls_base => @panic("TODO"),564 .__tls_base => @panic("TODO"),
548 .__tls_size => @panic("TODO"),565 .__tls_size => @panic("TODO"),
549 .__zig_error_name_table => @panic("TODO"),
550 .object_global => |i| {566 .object_global => |i| {
551 const global = i.ptr(wasm);567 const global = i.ptr(wasm);
552 try binary_writer.writeByte(@intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())));568 try binary_writer.writeByte(@intFromEnum(@as(std.wasm.Valtype, global.flags.global_type.valtype.to())));
...@@ -730,8 +746,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -730,8 +746,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
730 const code_start = binary_bytes.items.len;746 const code_start = binary_bytes.items.len;
731 append: {747 append: {
732 const code = switch (segment_id.unpack(wasm)) {748 const code = switch (segment_id.unpack(wasm)) {
749 .__zig_error_names => {
750 try binary_bytes.appendSlice(gpa, wasm.error_name_bytes.items);
751 break :append;
752 },
733 .__zig_error_name_table => {753 .__zig_error_name_table => {
734 if (true) @panic("TODO lower zig error name table");754 if (is_obj) @panic("TODO error name table reloc");
755 const base = f.data_segments.get(.__zig_error_names).?;
756 if (!is64) {
757 try emitErrorNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32);
758 } else {
759 try emitErrorNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u64);
760 }
735 break :append;761 break :append;
736 },762 },
737 .object => |i| c: {763 .object => |i| c: {
...@@ -1491,3 +1517,20 @@ fn uleb128size(x: u32) u32 {...@@ -1491,3 +1517,20 @@ fn uleb128size(x: u32) u32 {
1491 while (value != 0) : (size += 1) value >>= 7;1517 while (value != 0) : (size += 1) value >>= 7;
1492 return size;1518 return size;
1493}1519}
1520
1521fn emitErrorNameTable(
1522 gpa: Allocator,
1523 code: *std.ArrayListUnmanaged(u8),
1524 error_name_offs: []const u32,
1525 error_name_bytes: []const u8,
1526 base: u32,
1527 comptime Int: type,
1528) error{OutOfMemory}!void {
1529 const ptr_size_bytes = @divExact(@bitSizeOf(Int), 8);
1530 try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * error_name_offs.len);
1531 for (error_name_offs) |off| {
1532 const name_len: u32 = @intCast(mem.indexOfScalar(u8, error_name_bytes[off..], 0).?);
1533 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little);
1534 mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little);
1535 }
1536}