authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-11-29 21:34:40+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-11-30 17:56:02+01:00
logdf7ddb475e4c96bf44cc7e802c2c36efb8f38e89
treed9e3214655e100c2cfbc2a93d896b96dc103c77f
parent6924f21bbd81683b0889994ce86aa0ae22e5b317
signaturelock-open Commit is signed but in an unrecognized format.

wasm: Fix pointer to field of packed struct

When requesting a pointer to a field of a packed struct (of which is not byte-aligned), we simply provide the address of the packed struct itself.

1 files changed, 27 insertions(+), 9 deletions(-)

src/arch/wasm/CodeGen.zig+27-9
...@@ -2166,9 +2166,8 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2166,9 +2166,8 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2166 break :shifted try func.binOp(extended_value, shift_val, int_elem_ty, .shl);2166 break :shifted try func.binOp(extended_value, shift_val, int_elem_ty, .shl);
2167 } else extended_value;2167 } else extended_value;
2168 const result = try func.binOp(anded, shifted_value, int_elem_ty, .@"or");2168 const result = try func.binOp(anded, shifted_value, int_elem_ty, .@"or");
2169 std.debug.print("Host: {} ty {} ty {}\n", .{ ptr_info.host_size, int_elem_ty.fmtDebug(), ty.fmtDebug() });
2170 // lhs is still on the stack2169 // lhs is still on the stack
2171 try func.store(.stack, result, int_elem_ty, 0);2170 try func.store(.stack, result, int_elem_ty, lhs.offset());
2172 }2171 }
21732172
2174 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });2173 func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
...@@ -2284,8 +2283,10 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2284,8 +2283,10 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2284 const int_elem_ty = Type.initPayload(&int_ty_payload.base);2283 const int_elem_ty = Type.initPayload(&int_ty_payload.base);
2285 const shift_val = if (ptr_info.host_size <= 4)2284 const shift_val = if (ptr_info.host_size <= 4)
2286 WValue{ .imm32 = ptr_info.bit_offset }2285 WValue{ .imm32 = ptr_info.bit_offset }
2286 else if (ptr_info.host_size <= 8)
2287 WValue{ .imm64 = ptr_info.bit_offset }
2287 else2288 else
2288 WValue{ .imm64 = ptr_info.bit_offset };2289 return func.fail("TODO: airLoad where ptr to bitfield exceeds 64 bits", .{});
22892290
2290 const stack_loaded = try func.load(operand, int_elem_ty, 0);2291 const stack_loaded = try func.load(operand, int_elem_ty, 0);
2291 const shifted = try func.binOp(stack_loaded, shift_val, int_elem_ty, .shr);2292 const shifted = try func.binOp(stack_loaded, shift_val, int_elem_ty, .shr);
...@@ -3213,7 +3214,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3213,7 +3214,7 @@ fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
32133214
3214 const struct_ptr = try func.resolveInst(extra.data.struct_operand);3215 const struct_ptr = try func.resolveInst(extra.data.struct_operand);
3215 const struct_ty = func.air.typeOf(extra.data.struct_operand).childType();3216 const struct_ty = func.air.typeOf(extra.data.struct_operand).childType();
3216 const result = try func.structFieldPtr(extra.data.struct_operand, struct_ptr, struct_ty, extra.data.field_index);3217 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ty, extra.data.field_index);
3217 func.finishAir(inst, result, &.{extra.data.struct_operand});3218 func.finishAir(inst, result, &.{extra.data.struct_operand});
3218}3219}
32193220
...@@ -3223,14 +3224,27 @@ fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) Inne...@@ -3223,14 +3224,27 @@ fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) Inne
3223 const struct_ptr = try func.resolveInst(ty_op.operand);3224 const struct_ptr = try func.resolveInst(ty_op.operand);
3224 const struct_ty = func.air.typeOf(ty_op.operand).childType();3225 const struct_ty = func.air.typeOf(ty_op.operand).childType();
32253226
3226 const result = try func.structFieldPtr(ty_op.operand, struct_ptr, struct_ty, index);3227 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ty, index);
3227 func.finishAir(inst, result, &.{ty_op.operand});3228 func.finishAir(inst, result, &.{ty_op.operand});
3228}3229}
32293230
3230fn structFieldPtr(func: *CodeGen, ref: Air.Inst.Ref, struct_ptr: WValue, struct_ty: Type, index: u32) InnerError!WValue {3231fn structFieldPtr(
3232 func: *CodeGen,
3233 inst: Air.Inst.Index,
3234 ref: Air.Inst.Ref,
3235 struct_ptr: WValue,
3236 struct_ty: Type,
3237 index: u32,
3238) InnerError!WValue {
3239 const result_ty = func.air.typeOfIndex(inst);
3231 const offset = switch (struct_ty.containerLayout()) {3240 const offset = switch (struct_ty.containerLayout()) {
3232 .Packed => switch (struct_ty.zigTypeTag()) {3241 .Packed => switch (struct_ty.zigTypeTag()) {
3233 .Struct => struct_ty.packedStructFieldByteOffset(index, func.target),3242 .Struct => offset: {
3243 if (result_ty.ptrInfo().data.host_size != 0) {
3244 break :offset @as(u32, 0);
3245 }
3246 break :offset struct_ty.packedStructFieldByteOffset(index, func.target);
3247 },
3234 .Union => 0,3248 .Union => 0,
3235 else => unreachable,3249 else => unreachable,
3236 },3250 },
...@@ -3266,11 +3280,15 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3266,11 +3280,15 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3266 assert(struct_obj.layout == .Packed);3280 assert(struct_obj.layout == .Packed);
3267 const offset = struct_obj.packedFieldBitOffset(func.target, field_index);3281 const offset = struct_obj.packedFieldBitOffset(func.target, field_index);
3268 const backing_ty = struct_obj.backing_int_ty;3282 const backing_ty = struct_obj.backing_int_ty;
3269 const wasm_bits = toWasmBits(backing_ty.intInfo(func.target).bits).?;3283 const wasm_bits = toWasmBits(backing_ty.intInfo(func.target).bits) orelse {
3284 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});
3285 };
3270 const const_wvalue = if (wasm_bits == 32)3286 const const_wvalue = if (wasm_bits == 32)
3271 WValue{ .imm32 = offset }3287 WValue{ .imm32 = offset }
3288 else if (wasm_bits == 64)
3289 WValue{ .imm64 = offset }
3272 else3290 else
3273 WValue{ .imm64 = offset };3291 return func.fail("TODO: airStructFieldVal for packed structs larger than 64 bits", .{});
32743292
3275 // for first field we don't require any shifting3293 // for first field we don't require any shifting
3276 const shifted_value = if (offset == 0)3294 const shifted_value = if (offset == 0)