From 4af5bbde53da7f6ac8acc630135e569885bd94c4 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Fri, 25 Nov 2022 19:14:24 +0100 Subject: [PATCH] wasm: airStructFieldPtr - Support packed structs Simplifies the airStructFieldPtr(index) functions to only obtain the correct struct type and field index, which is then passed into the structFieldPtr function. This function now calculates the byte-offset of the field's address and returns a new `WValue` with this offset. This means we only have to do this calculation in a single function, and no longer have to duplicate any logic. This also handles both regular (tagged) unions and packed unions. --- src/arch/wasm/CodeGen.zig | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index f872bb804f..5eadc5167f 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -3131,13 +3131,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const struct_ptr = try func.resolveInst(extra.data.struct_operand); const struct_ty = func.air.typeOf(extra.data.struct_operand).childType(); - const offset = std.math.cast(u32, struct_ty.structFieldOffset(extra.data.field_index, func.target)) orelse { - const module = func.bin_file.base.options.module.?; - return func.fail("Field type '{}' too big to fit into stack frame", .{ - struct_ty.structFieldType(extra.data.field_index).fmt(module), - }); - }; - const result = try func.structFieldPtr(struct_ptr, offset); + const result = try func.structFieldPtr(struct_ptr, struct_ty, extra.data.field_index); func.finishAir(inst, result, &.{extra.data.struct_operand}); } @@ -3146,21 +3140,23 @@ fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) Inne if (func.liveness.isUnused(inst)) return func.finishAir(inst, .none, &.{ty_op.operand}); const struct_ptr = try func.resolveInst(ty_op.operand); const struct_ty = func.air.typeOf(ty_op.operand).childType(); - const field_ty = struct_ty.structFieldType(index); - const offset = std.math.cast(u32, struct_ty.structFieldOffset(index, func.target)) orelse { - const module = func.bin_file.base.options.module.?; - return func.fail("Field type '{}' too big to fit into stack frame", .{ - field_ty.fmt(module), - }); - }; - const result = try func.structFieldPtr(struct_ptr, offset); + + const result = try func.structFieldPtr(struct_ptr, struct_ty, index); func.finishAir(inst, result, &.{ty_op.operand}); } -fn structFieldPtr(func: *CodeGen, struct_ptr: WValue, offset: u32) InnerError!WValue { +fn structFieldPtr(func: *CodeGen, struct_ptr: WValue, struct_ty: Type, index: u32) InnerError!WValue { + const offset = switch (struct_ty.containerLayout()) { + .Packed => switch (struct_ty.zigTypeTag()) { + .Struct => struct_ty.packedStructFieldByteOffset(index, func.target), + .Union => 0, + else => unreachable, + }, + else => struct_ty.structFieldOffset(index, func.target), + }; switch (struct_ptr) { .stack_offset => |stack_offset| { - return WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; + return WValue{ .stack_offset = .{ .value = stack_offset.value + @intCast(u32, offset), .references = 1 } }; }, else => return func.buildPointerOffset(struct_ptr, offset, .new), }