authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-06 18:27:00-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
logbffa14860078fe466e9f005dfc56869e195281b5
tree43e22f8708b784ea5d1f5f2e7415761ff56014c4
parente521879e4730fd85a92081c0040db7dc5daad8a3

wasm codegen: fix some compilation errors


5 files changed, 161 insertions(+), 106 deletions(-)

src/Zcu.zig+11
...@@ -4120,3 +4120,14 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)...@@ -4120,3 +4120,14 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
4120 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4120 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4121 return error.CodegenFail;4121 return error.CodegenFail;
4122}4122}
4123
4124/// Check if nav is an alias to a function, in which case we want to lower the
4125/// actual nav, rather than the alias itself.
4126pub fn chaseNav(zcu: *const Zcu, nav: InternPool.Nav.Index) InternPool.Nav.Index {
4127 return switch (zcu.intern_pool.indexToKey(zcu.navValue(nav).toIntern())) {
4128 .func => |f| f.owner_nav,
4129 .variable => |variable| variable.owner_nav,
4130 .@"extern" => |@"extern"| @"extern".owner_nav,
4131 else => nav,
4132 };
4133}
src/arch/wasm/CodeGen.zig+44-77
...@@ -146,19 +146,14 @@ const WValue = union(enum) {...@@ -146,19 +146,14 @@ const WValue = union(enum) {
146 float32: f32,146 float32: f32,
147 /// A constant 64bit float value147 /// A constant 64bit float value
148 float64: f64,148 float64: f64,
149 /// A value that represents a pointer to the data section.149 nav_ref: struct {
150 memory: InternPool.Index,150 nav_index: InternPool.Nav.Index,
151 /// A value that represents a parent pointer and an offset151 offset: i32 = 0,
152 /// from that pointer. i.e. when slicing with constant values.152 },
153 memory_offset: struct {153 uav_ref: struct {
154 pointer: InternPool.Index,154 ip_index: InternPool.Index,
155 /// Offset will be set as addend when relocating155 offset: i32 = 0,
156 offset: u32,
157 },156 },
158 /// Represents a function pointer
159 /// In wasm function pointers are indexes into a function table,
160 /// rather than an address in the data section.
161 function_index: InternPool.Index,
162 /// Offset from the bottom of the virtual stack, with the offset157 /// Offset from the bottom of the virtual stack, with the offset
163 /// pointing to where the value lives.158 /// pointing to where the value lives.
164 stack_offset: struct {159 stack_offset: struct {
...@@ -752,7 +747,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -752,7 +747,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
752 const ty = func.typeOf(ref);747 const ty = func.typeOf(ref);
753 if (!ty.hasRuntimeBitsIgnoreComptime(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) {748 if (!ty.hasRuntimeBitsIgnoreComptime(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) {
754 gop.value_ptr.* = .none;749 gop.value_ptr.* = .none;
755 return gop.value_ptr.*;750 return .none;
756 }751 }
757752
758 // When we need to pass the value by reference (such as a struct), we will753 // When we need to pass the value by reference (such as a struct), we will
...@@ -762,7 +757,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {...@@ -762,7 +757,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
762 // In the other cases, we will simply lower the constant to a value that fits757 // In the other cases, we will simply lower the constant to a value that fits
763 // into a single local (such as a pointer, integer, bool, etc).758 // into a single local (such as a pointer, integer, bool, etc).
764 const result: WValue = if (isByRef(ty, pt, func.target))759 const result: WValue = if (isByRef(ty, pt, func.target))
765 .{ .memory = val.toIntern() }760 .{ .uav_ref = .{ .ip_index = val.toIntern() } }
766 else761 else
767 try func.lowerConstant(val, ty);762 try func.lowerConstant(val, ty);
768763
...@@ -956,6 +951,7 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32...@@ -956,6 +951,7 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32
956 u32 => @field(extra, field.name),951 u32 => @field(extra, field.name),
957 i32 => @bitCast(@field(extra, field.name)),952 i32 => @bitCast(@field(extra, field.name)),
958 InternPool.Index => @intFromEnum(@field(extra, field.name)),953 InternPool.Index => @intFromEnum(@field(extra, field.name)),
954 InternPool.Nav.Index => @intFromEnum(@field(extra, field.name)),
959 else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),955 else => |field_type| @compileError("Unsupported field type " ++ @typeName(field_type)),
960 });956 });
961 }957 }
...@@ -1028,17 +1024,36 @@ fn emitWValue(func: *CodeGen, value: WValue) InnerError!void {...@@ -1028,17 +1024,36 @@ fn emitWValue(func: *CodeGen, value: WValue) InnerError!void {
1028 .imm128 => |val| try func.addImm128(val),1024 .imm128 => |val| try func.addImm128(val),
1029 .float32 => |val| try func.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }),1025 .float32 => |val| try func.addInst(.{ .tag = .f32_const, .data = .{ .float32 = val } }),
1030 .float64 => |val| try func.addFloat64(val),1026 .float64 => |val| try func.addFloat64(val),
1031 .memory => |ptr| try func.addInst(.{ .tag = .uav_ref, .data = .{ .ip_index = ptr } }),1027 .nav_ref => |nav_ref| {
1032 .memory_offset => |mo| try func.addInst(.{1028 if (nav_ref.offset == 0) {
1033 .tag = .uav_ref_off,1029 try func.addInst(.{ .tag = .nav_ref, .data = .{ .nav_index = nav_ref.nav_index } });
1034 .data = .{1030 } else {
1035 .payload = try func.addExtra(Mir.UavRefOff{1031 try func.addInst(.{
1036 .ip_index = mo.pointer,1032 .tag = .nav_ref_off,
1037 .offset = @intCast(mo.offset), // TODO should not be an assert1033 .data = .{
1038 }),1034 .payload = try func.addExtra(Mir.NavRefOff{
1039 },1035 .nav_index = nav_ref.nav_index,
1040 }),1036 .offset = nav_ref.offset,
1041 .function_index => |index| try func.addIpIndex(.function_index, index),1037 }),
1038 },
1039 });
1040 }
1041 },
1042 .uav_ref => |uav| {
1043 if (uav.offset == 0) {
1044 try func.addInst(.{ .tag = .uav_ref, .data = .{ .ip_index = uav.ip_index } });
1045 } else {
1046 try func.addInst(.{
1047 .tag = .uav_ref_off,
1048 .data = .{
1049 .payload = try func.addExtra(Mir.UavRefOff{
1050 .ip_index = uav.ip_index,
1051 .offset = uav.offset,
1052 }),
1053 },
1054 });
1055 }
1056 },
1042 .stack_offset => try func.addLabel(.local_get, func.bottom_stack_value.local.value), // caller must ensure to address the offset1057 .stack_offset => try func.addLabel(.local_get, func.bottom_stack_value.local.value), // caller must ensure to address the offset
1043 }1058 }
1044}1059}
...@@ -1466,10 +1481,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:...@@ -1466,10 +1481,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
1466 assert(ty_classes[0] == .direct);1481 assert(ty_classes[0] == .direct);
1467 const scalar_type = abi.scalarType(ty, zcu);1482 const scalar_type = abi.scalarType(ty, zcu);
1468 switch (value) {1483 switch (value) {
1469 .memory,1484 .nav_ref, .stack_offset => _ = try func.load(value, scalar_type, 0),
1470 .memory_offset,
1471 .stack_offset,
1472 => _ = try func.load(value, scalar_type, 0),
1473 .dead => unreachable,1485 .dead => unreachable,
1474 else => try func.emitWValue(value),1486 else => try func.emitWValue(value),
1475 }1487 }
...@@ -3117,8 +3129,8 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr...@@ -3117,8 +3129,8 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr
3117 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;3129 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
3118 const offset: u64 = prev_offset + ptr.byte_offset;3130 const offset: u64 = prev_offset + ptr.byte_offset;
3119 return switch (ptr.base_addr) {3131 return switch (ptr.base_addr) {
3120 .nav => |nav| return func.lowerNavRef(nav, @intCast(offset)),3132 .nav => |nav| return .{ .nav_ref = .{ .nav_index = zcu.chaseNav(nav), .offset = @intCast(offset) } },
3121 .uav => |uav| return func.lowerUavRef(uav, @intCast(offset)),3133 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },
3122 .int => return func.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),3134 .int => return func.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),
3123 .eu_payload => return func.fail("Wasm TODO: lower error union payload pointer", .{}),3135 .eu_payload => return func.fail("Wasm TODO: lower error union payload pointer", .{}),
3124 .opt_payload => |opt_ptr| return func.lowerPtr(opt_ptr, offset),3136 .opt_payload => |opt_ptr| return func.lowerPtr(opt_ptr, offset),
...@@ -3162,51 +3174,6 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr...@@ -3162,51 +3174,6 @@ fn lowerPtr(func: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerEr
3162 };3174 };
3163}3175}
31643176
3165fn lowerUavRef(
3166 func: *CodeGen,
3167 uav: InternPool.Key.Ptr.BaseAddr.Uav,
3168 offset: u32,
3169) InnerError!WValue {
3170 const pt = func.pt;
3171 const zcu = pt.zcu;
3172 const ty = Type.fromInterned(zcu.intern_pool.typeOf(uav.val));
3173
3174 const is_fn_body = ty.zigTypeTag(zcu) == .@"fn";
3175 if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(zcu)) {
3176 return .{ .imm32 = 0xaaaaaaaa };
3177 }
3178
3179 return if (is_fn_body) .{
3180 .function_index = uav.val,
3181 } else if (offset == 0) .{
3182 .memory = uav.val,
3183 } else .{ .memory_offset = .{
3184 .pointer = uav.val,
3185 .offset = offset,
3186 } };
3187}
3188
3189fn lowerNavRef(func: *CodeGen, nav_index: InternPool.Nav.Index, offset: u32) InnerError!WValue {
3190 const pt = func.pt;
3191 const zcu = pt.zcu;
3192 const ip = &zcu.intern_pool;
3193
3194 const nav_ty = ip.getNav(nav_index).typeOf(ip);
3195 if (!ip.isFunctionType(nav_ty) and !Type.fromInterned(nav_ty).hasRuntimeBitsIgnoreComptime(zcu)) {
3196 return .{ .imm32 = 0xaaaaaaaa };
3197 }
3198
3199 const atom_index = try func.wasm.getOrCreateAtomForNav(pt, nav_index);
3200 const atom = func.wasm.getAtom(atom_index);
3201
3202 const target_sym_index = @intFromEnum(atom.sym_index);
3203 if (ip.isFunctionType(nav_ty)) {
3204 return .{ .function_index = target_sym_index };
3205 } else if (offset == 0) {
3206 return .{ .memory = target_sym_index };
3207 } else return .{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } };
3208}
3209
3210/// Asserts that `isByRef` returns `false` for `ty`.3177/// Asserts that `isByRef` returns `false` for `ty`.
3211fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {3178fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3212 const pt = func.pt;3179 const pt = func.pt;
...@@ -3307,7 +3274,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3307,7 +3274,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3307 .f64 => |f64_val| return .{ .float64 = f64_val },3274 .f64 => |f64_val| return .{ .float64 = f64_val },
3308 else => unreachable,3275 else => unreachable,
3309 },3276 },
3310 .slice => return .{ .memory = val.toIntern() },3277 .slice => unreachable, // isByRef == true
3311 .ptr => return func.lowerPtr(val.toIntern(), 0),3278 .ptr => return func.lowerPtr(val.toIntern(), 0),
3312 .opt => if (ty.optionalReprIsPayload(zcu)) {3279 .opt => if (ty.optionalReprIsPayload(zcu)) {
3313 const pl_ty = ty.optionalChild(zcu);3280 const pl_ty = ty.optionalChild(zcu);
src/arch/wasm/Emit.zig+63-12
...@@ -33,6 +33,9 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -33,6 +33,9 @@ pub fn lowerToCode(emit: *Emit) Error!void {
33 var inst: u32 = 0;33 var inst: u32 = 0;
3434
35 loop: switch (tags[inst]) {35 loop: switch (tags[inst]) {
36 .dbg_epilogue_begin => {
37 return;
38 },
36 .block, .loop => {39 .block, .loop => {
37 const block_type = datas[inst].block_type;40 const block_type = datas[inst].block_type;
38 try code.ensureUnusedCapacity(gpa, 2);41 try code.ensureUnusedCapacity(gpa, 2);
...@@ -42,28 +45,31 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -42,28 +45,31 @@ pub fn lowerToCode(emit: *Emit) Error!void {
42 inst += 1;45 inst += 1;
43 continue :loop tags[inst];46 continue :loop tags[inst];
44 },47 },
45
46 .uav_ref => {48 .uav_ref => {
47 try uavRefOff(wasm, code, .{ .ip_index = datas[inst].ip_index, .offset = 0 });49 try uavRefOff(wasm, code, .{ .ip_index = datas[inst].ip_index, .offset = 0 });
48
49 inst += 1;50 inst += 1;
50 continue :loop tags[inst];51 continue :loop tags[inst];
51 },52 },
52 .uav_ref_off => {53 .uav_ref_off => {
53 try uavRefOff(wasm, code, mir.extraData(Mir.UavRefOff, datas[inst].payload).data);54 try uavRefOff(wasm, code, mir.extraData(Mir.UavRefOff, datas[inst].payload).data);
54
55 inst += 1;55 inst += 1;
56 continue :loop tags[inst];56 continue :loop tags[inst];
57 },57 },
5858 .nav_ref => {
59 .dbg_line => {59 try navRefOff(wasm, code, .{ .ip_index = datas[inst].ip_index, .offset = 0 });
60 inst += 1;60 inst += 1;
61 continue :loop tags[inst];61 continue :loop tags[inst];
62 },62 },
63 .dbg_epilogue_begin => {63 .nav_ref_off => {
64 return;64 try navRefOff(wasm, code, mir.extraData(Mir.NavRefOff, datas[inst].payload).data);
65 inst += 1;
66 continue :loop tags[inst];
65 },67 },
6668
69 .dbg_line => {
70 inst += 1;
71 continue :loop tags[inst];
72 },
67 .br_if, .br, .memory_grow, .memory_size => {73 .br_if, .br, .memory_grow, .memory_size => {
68 try code.ensureUnusedCapacity(gpa, 11);74 try code.ensureUnusedCapacity(gpa, 11);
69 code.appendAssumeCapacity(@intFromEnum(tags[inst]));75 code.appendAssumeCapacity(@intFromEnum(tags[inst]));
...@@ -431,7 +437,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -431,7 +437,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
431437
432 _ => unreachable,438 _ => unreachable,
433 }439 }
434 unreachable;440 comptime unreachable;
435 },441 },
436 .simd_prefix => {442 .simd_prefix => {
437 try code.ensureUnusedCapacity(gpa, 6 + 20);443 try code.ensureUnusedCapacity(gpa, 6 + 20);
...@@ -487,7 +493,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -487,7 +493,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
487 },493 },
488 _ => unreachable,494 _ => unreachable,
489 }495 }
490 unreachable;496 comptime unreachable;
491 },497 },
492 .atomics_prefix => {498 .atomics_prefix => {
493 try code.ensureUnusedCapacity(gpa, 6 + 20);499 try code.ensureUnusedCapacity(gpa, 6 + 20);
...@@ -576,13 +582,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -576,13 +582,13 @@ pub fn lowerToCode(emit: *Emit) Error!void {
576 continue :loop tags[inst];582 continue :loop tags[inst];
577 },583 },
578 }584 }
579 unreachable;585 comptime unreachable;
580 },586 },
581 }587 }
582 unreachable;588 comptime unreachable;
583}589}
584590
585/// Assert 20 unused capacity.591/// Asserts 20 unused capacity.
586fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void {592fn encodeMemArg(code: *std.ArrayListUnmanaged(u8), mem_arg: Mir.MemArg) void {
587 assert(code.unusedCapacitySlice().len >= 20);593 assert(code.unusedCapacitySlice().len >= 20);
588 // Wasm encodes alignment as power of 2, rather than natural alignment.594 // Wasm encodes alignment as power of 2, rather than natural alignment.
...@@ -619,3 +625,48 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir...@@ -619,3 +625,48 @@ fn uavRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir
619 const addr: i64 = try wasm.uavAddr(data.ip_index);625 const addr: i64 = try wasm.uavAddr(data.ip_index);
620 leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable;626 leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable;
621}627}
628
629fn navRefOff(wasm: *link.File.Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff) !void {
630 const comp = wasm.base.comp;
631 const zcu = comp.zcu.?;
632 const ip = &zcu.intern_pool;
633 const gpa = comp.gpa;
634 const is_obj = comp.config.output_mode == .Obj;
635 const target = &comp.root_mod.resolved_target.result;
636 const nav_ty = ip.getNav(data.nav_index).typeOf(ip);
637
638 try code.ensureUnusedCapacity(gpa, 11);
639
640 if (ip.isFunctionType(nav_ty)) {
641 code.appendAssumeCapacity(std.wasm.Opcode.i32_const);
642 assert(data.offset == 0);
643 if (is_obj) {
644 try wasm.out_relocs.append(gpa, .{
645 .offset = @intCast(code.items.len),
646 .index = try wasm.navSymbolIndex(data.nav_index),
647 .tag = .TABLE_INDEX_SLEB,
648 .addend = data.offset,
649 });
650 code.appendNTimesAssumeCapacity(0, 5);
651 } else {
652 const addr: i64 = try wasm.navAddr(data.nav_index);
653 leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable;
654 }
655 } else {
656 const is_wasm32 = target.cpu.arch == .wasm32;
657 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
658 code.appendAssumeCapacity(@intFromEnum(opcode));
659 if (is_obj) {
660 try wasm.out_relocs.append(gpa, .{
661 .offset = @intCast(code.items.len),
662 .index = try wasm.navSymbolIndex(data.nav_index),
663 .tag = if (is_wasm32) .MEMORY_ADDR_LEB else .MEMORY_ADDR_LEB64,
664 .addend = data.offset,
665 });
666 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
667 } else {
668 const addr: i64 = try wasm.navAddr(data.nav_index);
669 leb.writeUleb128(code.fixedWriter(), addr + data.offset) catch unreachable;
670 }
671 }
672}
src/arch/wasm/Mir.zig+38-16
...@@ -32,8 +32,12 @@ pub const Inst = struct {...@@ -32,8 +32,12 @@ pub const Inst = struct {
3232
33 /// Some tags match wasm opcode values to facilitate trivial lowering.33 /// Some tags match wasm opcode values to facilitate trivial lowering.
34 pub const Tag = enum(u8) {34 pub const Tag = enum(u8) {
35 /// Uses `nop`35 /// Uses `tag`.
36 @"unreachable" = 0x00,36 @"unreachable" = 0x00,
37 /// Emits epilogue begin debug information. Marks the end of the function.
38 ///
39 /// Uses `tag` (no additional data).
40 dbg_epilogue_begin,
37 /// Creates a new block that can be jump from.41 /// Creates a new block that can be jump from.
38 ///42 ///
39 /// Type of the block is given in data `block_type`43 /// Type of the block is given in data `block_type`
...@@ -46,34 +50,51 @@ pub const Inst = struct {...@@ -46,34 +50,51 @@ pub const Inst = struct {
46 /// memory address of an unnamed constant. When emitting an object50 /// memory address of an unnamed constant. When emitting an object
47 /// file, this adds a relocation.51 /// file, this adds a relocation.
48 ///52 ///
49 /// Data is `ip_index`.53 /// This may not refer to a function.
54 ///
55 /// Uses `ip_index`.
50 uav_ref,56 uav_ref,
51 /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the57 /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the
52 /// memory address of an unnamed constant, offset by an integer value.58 /// memory address of an unnamed constant, offset by an integer value.
53 /// When emitting an object file, this adds a relocation.59 /// When emitting an object file, this adds a relocation.
54 ///60 ///
55 /// Data is `payload` pointing to a `UavRefOff`.61 /// This may not refer to a function.
62 ///
63 /// Uses `payload` pointing to a `UavRefOff`.
56 uav_ref_off,64 uav_ref_off,
65 /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the
66 /// memory address of a named constant.
67 ///
68 /// When this refers to a function, this always lowers to an i32_const
69 /// which is the function index. When emitting an object file, this
70 /// adds a `Wasm.Relocation.Tag.TABLE_INDEX_SLEB` relocation.
71 ///
72 /// Uses `nav_index`.
73 nav_ref,
74 /// Lowers to an i32_const (wasm32) or i64_const (wasm64) which is the
75 /// memory address of named constant, offset by an integer value.
76 /// When emitting an object file, this adds a relocation.
77 ///
78 /// This may not refer to a function.
79 ///
80 /// Uses `payload` pointing to a `NavRefOff`.
81 nav_ref_off,
57 /// Inserts debug information about the current line and column82 /// Inserts debug information about the current line and column
58 /// of the source code83 /// of the source code
59 ///84 ///
60 /// Uses `payload` of which the payload type is `DbgLineColumn`85 /// Uses `payload` of which the payload type is `DbgLineColumn`
61 dbg_line = 0x06,86 dbg_line,
62 /// Emits epilogue begin debug information. Marks the end of the function.
63 ///
64 /// Uses `nop`
65 dbg_epilogue_begin = 0x07,
66 /// Represents the end of a function body or an initialization expression87 /// Represents the end of a function body or an initialization expression
67 ///88 ///
68 /// Payload is `nop`89 /// Uses `tag` (no additional data).
69 end = 0x0B,90 end = 0x0B,
70 /// Breaks from the current block to a label91 /// Breaks from the current block to a label
71 ///92 ///
72 /// Data is `label` where index represents the label to jump to93 /// Uses `label` where index represents the label to jump to
73 br = 0x0C,94 br = 0x0C,
74 /// Breaks from the current block if the stack value is non-zero95 /// Breaks from the current block if the stack value is non-zero
75 ///96 ///
76 /// Data is `label` where index represents the label to jump to97 /// Uses `label` where index represents the label to jump to
77 br_if = 0x0D,98 br_if = 0x0D,
78 /// Jump table that takes the stack value as an index where each value99 /// Jump table that takes the stack value as an index where each value
79 /// represents the label to jump to.100 /// represents the label to jump to.
...@@ -82,7 +103,7 @@ pub const Inst = struct {...@@ -82,7 +103,7 @@ pub const Inst = struct {
82 br_table = 0x0E,103 br_table = 0x0E,
83 /// Returns from the function104 /// Returns from the function
84 ///105 ///
85 /// Uses `nop`106 /// Uses `tag`.
86 @"return" = 0x0F,107 @"return" = 0x0F,
87 /// Calls a function using `nav_index`.108 /// Calls a function using `nav_index`.
88 call_nav,109 call_nav,
...@@ -98,10 +119,6 @@ pub const Inst = struct {...@@ -98,10 +119,6 @@ pub const Inst = struct {
98 /// The function is the auto-generated tag name function for the type119 /// The function is the auto-generated tag name function for the type
99 /// provided in `ip_index`.120 /// provided in `ip_index`.
100 call_tag_name,121 call_tag_name,
101 /// Lowers to an i32_const containing the index of a function.
102 /// When emitting an object file, this adds a relocation.
103 /// Uses `ip_index`.
104 function_index,
105122
106 /// Pops three values from the stack and pushes123 /// Pops three values from the stack and pushes
107 /// the first or second value dependent on the third value.124 /// the first or second value dependent on the third value.
...@@ -663,6 +680,11 @@ pub const UavRefOff = struct {...@@ -663,6 +680,11 @@ pub const UavRefOff = struct {
663 offset: i32,680 offset: i32,
664};681};
665682
683pub const NavRefOff = struct {
684 nav_index: InternPool.Nav.Index,
685 offset: i32,
686};
687
666/// Maps a source line with wasm bytecode688/// Maps a source line with wasm bytecode
667pub const DbgLineColumn = struct {689pub const DbgLineColumn = struct {
668 line: u32,690 line: u32,
src/link/Wasm.zig+5-1
...@@ -1508,6 +1508,10 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -1508,6 +1508,10 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
15081508
1509 dev.check(.wasm_backend);1509 dev.check(.wasm_backend);
15101510
1511 // This converts AIR to MIR but does not yet lower to wasm code.
1512 // That lowering happens during `flush`, after garbage collection, which
1513 // can affect function and global indexes, which affects the LEB integer
1514 // encoding, which affects the output binary size.
1511 try wasm.zcu_funcs.put(pt.zcu.gpa, func_index, .{1515 try wasm.zcu_funcs.put(pt.zcu.gpa, func_index, .{
1512 .function = try CodeGen.function(wasm, pt, func_index, air, liveness),1516 .function = try CodeGen.function(wasm, pt, func_index, air, liveness),
1513 });1517 });
...@@ -1729,7 +1733,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v...@@ -1729,7 +1733,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
1729 continue;1733 continue;
1730 }1734 }
1731 }1735 }
1732 wasm.functions_len = @intCast(wasm.functions.items.len);1736 wasm.functions_len = @intCast(wasm.functions.entries.len);
1733 wasm.function_imports_init_keys = try gpa.dupe(String, wasm.function_imports.keys());1737 wasm.function_imports_init_keys = try gpa.dupe(String, wasm.function_imports.keys());
1734 wasm.function_imports_init_vals = try gpa.dupe(FunctionImportId, wasm.function_imports.vals());1738 wasm.function_imports_init_vals = try gpa.dupe(FunctionImportId, wasm.function_imports.vals());
1735 wasm.function_exports_len = @intCast(wasm.function_exports.items.len);1739 wasm.function_exports_len = @intCast(wasm.function_exports.items.len);