authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-13 19:37:18-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log4cc9cfa7e88b0dd4b47bedba9f190f6731422da6
treeb17b2defe99d9f67469843e450ee82cf309a9953
parentba4521ac85bbfc7cf6e6ea8d36e75907d94878c3

wasm linker: track overaligned uavs


3 files changed, 38 insertions(+), 8 deletions(-)

src/arch/wasm/CodeGen.zig+6-5
...@@ -161,6 +161,7 @@ const WValue = union(enum) {...@@ -161,6 +161,7 @@ const WValue = union(enum) {
161 uav_ref: struct {161 uav_ref: struct {
162 ip_index: InternPool.Index,162 ip_index: InternPool.Index,
163 offset: i32 = 0,163 offset: i32 = 0,
164 orig_ptr_ty: InternPool.Index = .none,
164 },165 },
165 /// Offset from the bottom of the virtual stack, with the offset166 /// Offset from the bottom of the virtual stack, with the offset
166 /// pointing to where the value lives.167 /// pointing to where the value lives.
...@@ -1062,9 +1063,9 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {...@@ -1062,9 +1063,9 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1062 try cg.addInst(.{1063 try cg.addInst(.{
1063 .tag = .uav_ref,1064 .tag = .uav_ref,
1064 .data = if (is_obj) .{1065 .data = if (is_obj) .{
1065 .uav_obj = try wasm.refUavObj(uav.ip_index),1066 .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
1066 } else .{1067 } else .{
1067 .uav_exe = try wasm.refUavExe(uav.ip_index),1068 .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
1068 },1069 },
1069 });1070 });
1070 } else {1071 } else {
...@@ -1072,10 +1073,10 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {...@@ -1072,10 +1073,10 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1072 .tag = .uav_ref_off,1073 .tag = .uav_ref_off,
1073 .data = .{1074 .data = .{
1074 .payload = if (is_obj) try cg.addExtra(Mir.UavRefOffObj{1075 .payload = if (is_obj) try cg.addExtra(Mir.UavRefOffObj{
1075 .uav_obj = try wasm.refUavObj(uav.ip_index),1076 .uav_obj = try wasm.refUavObj(uav.ip_index, uav.orig_ptr_ty),
1076 .offset = uav.offset,1077 .offset = uav.offset,
1077 }) else try cg.addExtra(Mir.UavRefOffExe{1078 }) else try cg.addExtra(Mir.UavRefOffExe{
1078 .uav_exe = try wasm.refUavExe(uav.ip_index),1079 .uav_exe = try wasm.refUavExe(uav.ip_index, uav.orig_ptr_ty),
1079 .offset = uav.offset,1080 .offset = uav.offset,
1080 }),1081 }),
1081 },1082 },
...@@ -3093,7 +3094,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro...@@ -3093,7 +3094,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
3093 const offset: u64 = prev_offset + ptr.byte_offset;3094 const offset: u64 = prev_offset + ptr.byte_offset;
3094 return switch (ptr.base_addr) {3095 return switch (ptr.base_addr) {
3095 .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } },3096 .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } },
3096 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },3097 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset), .orig_ptr_ty = uav.orig_ty } },
3097 .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),3098 .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),
3098 .eu_payload => return cg.fail("Wasm TODO: lower error union payload pointer", .{}),3099 .eu_payload => return cg.fail("Wasm TODO: lower error union payload pointer", .{}),
3099 .opt_payload => |opt_ptr| return cg.lowerPtr(opt_ptr, offset),3100 .opt_payload => |opt_ptr| return cg.lowerPtr(opt_ptr, offset),
src/codegen.zig+1-1
...@@ -675,7 +675,7 @@ fn lowerUavRef(...@@ -675,7 +675,7 @@ fn lowerUavRef(
675 } else {675 } else {
676 try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);676 try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);
677 wasm.uav_fixups.appendAssumeCapacity(.{677 wasm.uav_fixups.appendAssumeCapacity(.{
678 .uavs_exe_index = try wasm.refUavExe(uav.val),678 .uavs_exe_index = try wasm.refUavExe(uav.val, uav.orig_ty),
679 .offset = @intCast(code.items.len),679 .offset = @intCast(code.items.len),
680 .addend = @intCast(offset),680 .addend = @intCast(offset),
681 });681 });
src/link/Wasm.zig+31-2
...@@ -189,6 +189,9 @@ navs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ZcuDataExe) = .emp...@@ -189,6 +189,9 @@ navs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ZcuDataExe) = .emp
189uavs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataObj) = .empty,189uavs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataObj) = .empty,
190/// Tracks ref count to optimize LEB encodings for UAV references.190/// Tracks ref count to optimize LEB encodings for UAV references.
191uavs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataExe) = .empty,191uavs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataExe) = .empty,
192/// Sparse table of uavs that need to be emitted with greater alignment than
193/// the default for the type.
194overaligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty,
192/// When the key is an enum type, this represents a `@tagName` function.195/// When the key is an enum type, this represents a `@tagName` function.
193zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty,196zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty,
194nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty,197nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty,
...@@ -1945,6 +1948,7 @@ pub const DataSegmentId = enum(u32) {...@@ -1945,6 +1948,7 @@ pub const DataSegmentId = enum(u32) {
1945 const zcu = wasm.base.comp.zcu.?;1948 const zcu = wasm.base.comp.zcu.?;
1946 const ip = &zcu.intern_pool;1949 const ip = &zcu.intern_pool;
1947 const ip_index = i.key(wasm).*;1950 const ip_index = i.key(wasm).*;
1951 if (wasm.overaligned_uavs.get(ip_index)) |a| return a;
1948 const ty: Zcu.Type = .fromInterned(ip.typeOf(ip_index));1952 const ty: Zcu.Type = .fromInterned(ip.typeOf(ip_index));
1949 const result = ty.abiAlignment(zcu);1953 const result = ty.abiAlignment(zcu);
1950 assert(result != .none);1954 assert(result != .none);
...@@ -3085,6 +3089,7 @@ pub fn deinit(wasm: *Wasm) void {...@@ -3085,6 +3089,7 @@ pub fn deinit(wasm: *Wasm) void {
3085 wasm.navs_obj.deinit(gpa);3089 wasm.navs_obj.deinit(gpa);
3086 wasm.uavs_exe.deinit(gpa);3090 wasm.uavs_exe.deinit(gpa);
3087 wasm.uavs_obj.deinit(gpa);3091 wasm.uavs_obj.deinit(gpa);
3092 wasm.overaligned_uavs.deinit(gpa);
3088 wasm.zcu_funcs.deinit(gpa);3093 wasm.zcu_funcs.deinit(gpa);
3089 wasm.nav_exports.deinit(gpa);3094 wasm.nav_exports.deinit(gpa);
3090 wasm.uav_exports.deinit(gpa);3095 wasm.uav_exports.deinit(gpa);
...@@ -4397,10 +4402,22 @@ pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableInd...@@ -4397,10 +4402,22 @@ pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableInd
4397 return @enumFromInt(gop.index);4402 return @enumFromInt(gop.index);
4398}4403}
43994404
4400pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index) !UavsObjIndex {4405pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsObjIndex {
4401 const comp = wasm.base.comp;4406 const comp = wasm.base.comp;
4407 const zcu = comp.zcu.?;
4408 const ip = &zcu.intern_pool;
4402 const gpa = comp.gpa;4409 const gpa = comp.gpa;
4403 assert(comp.config.output_mode == .Obj);4410 assert(comp.config.output_mode == .Obj);
4411
4412 if (orig_ptr_ty != .none) {
4413 const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
4414 const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
4415 if (explicit_alignment.compare(.gt, abi_alignment)) {
4416 const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
4417 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
4418 }
4419 }
4420
4404 const gop = try wasm.uavs_obj.getOrPut(gpa, ip_index);4421 const gop = try wasm.uavs_obj.getOrPut(gpa, ip_index);
4405 if (!gop.found_existing) gop.value_ptr.* = .{4422 if (!gop.found_existing) gop.value_ptr.* = .{
4406 // Lowering the value is delayed to avoid recursion.4423 // Lowering the value is delayed to avoid recursion.
...@@ -4410,10 +4427,22 @@ pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index) !UavsObjIndex {...@@ -4410,10 +4427,22 @@ pub fn refUavObj(wasm: *Wasm, ip_index: InternPool.Index) !UavsObjIndex {
4410 return @enumFromInt(gop.index);4427 return @enumFromInt(gop.index);
4411}4428}
44124429
4413pub fn refUavExe(wasm: *Wasm, ip_index: InternPool.Index) !UavsExeIndex {4430pub fn refUavExe(wasm: *Wasm, ip_index: InternPool.Index, orig_ptr_ty: InternPool.Index) !UavsExeIndex {
4414 const comp = wasm.base.comp;4431 const comp = wasm.base.comp;
4432 const zcu = comp.zcu.?;
4433 const ip = &zcu.intern_pool;
4415 const gpa = comp.gpa;4434 const gpa = comp.gpa;
4416 assert(comp.config.output_mode != .Obj);4435 assert(comp.config.output_mode != .Obj);
4436
4437 if (orig_ptr_ty != .none) {
4438 const abi_alignment = Zcu.Type.fromInterned(ip.typeOf(ip_index)).abiAlignment(zcu);
4439 const explicit_alignment = ip.indexToKey(orig_ptr_ty).ptr_type.flags.alignment;
4440 if (explicit_alignment.compare(.gt, abi_alignment)) {
4441 const gop = try wasm.overaligned_uavs.getOrPut(gpa, ip_index);
4442 gop.value_ptr.* = if (gop.found_existing) gop.value_ptr.maxStrict(explicit_alignment) else explicit_alignment;
4443 }
4444 }
4445
4417 const gop = try wasm.uavs_exe.getOrPut(gpa, ip_index);4446 const gop = try wasm.uavs_exe.getOrPut(gpa, ip_index);
4418 if (gop.found_existing) {4447 if (gop.found_existing) {
4419 gop.value_ptr.count += 1;4448 gop.value_ptr.count += 1;