authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-05-29 12:33:24+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-05-31 18:04:33+02:00
loge36cc0ce8f4c0ec7c1398149c5fa30f15d8dae9f
tree15c5787dde73bf473c8e79de3f03843db754ef59
parent128814f9bf89460232569ae3e47c52f90cdf4ffd
signaturelock-open Commit is signed but in an unrecognized format.

wasm: `union_init` support packed unions


1 files changed, 61 insertions(+), 22 deletions(-)

src/arch/wasm/CodeGen.zig+61-22
......@@ -1014,6 +1014,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
10141014 .direct => wasm.Valtype.v128,
10151015 .unrolled => wasm.Valtype.i32,
10161016 },
1017 .Union => switch (ty.containerLayout()) {
1018 .Packed => {
1019 var int_ty_payload: Type.Payload.Bits = .{
1020 .base = .{ .tag = .int_unsigned },
1021 .data = @intCast(u16, ty.bitSize(target)),
1022 };
1023 const int_ty = Type.initPayload(&int_ty_payload.base);
1024 return typeToValtype(int_ty, target);
1025 },
1026 else => wasm.Valtype.i32,
1027 },
10171028 else => wasm.Valtype.i32, // all represented as reference/immediate
10181029 };
10191030}
......@@ -5074,33 +5085,61 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50745085 assert(!isByRef(union_ty, func.target));
50755086 break :result tag_int;
50765087 }
5077 assert(isByRef(union_ty, func.target));
5078
5079 const result_ptr = try func.allocStack(union_ty);
5080 const payload = try func.resolveInst(extra.init);
5081 if (layout.tag_align >= layout.payload_align) {
5082 if (isByRef(field.ty, func.target)) {
5083 const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
5084 try func.store(payload_ptr, payload, field.ty, 0);
5085 } else {
5086 try func.store(result_ptr, payload, field.ty, @intCast(u32, layout.tag_size));
5087 }
50885088
5089 if (layout.tag_size > 0) {
5090 try func.store(result_ptr, tag_int, union_obj.tag_ty, 0);
5089 if (isByRef(union_ty, func.target)) {
5090 const result_ptr = try func.allocStack(union_ty);
5091 const payload = try func.resolveInst(extra.init);
5092 if (layout.tag_align >= layout.payload_align) {
5093 if (isByRef(field.ty, func.target)) {
5094 const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
5095 try func.store(payload_ptr, payload, field.ty, 0);
5096 } else {
5097 try func.store(result_ptr, payload, field.ty, @intCast(u32, layout.tag_size));
5098 }
5099
5100 if (layout.tag_size > 0) {
5101 try func.store(result_ptr, tag_int, union_obj.tag_ty, 0);
5102 }
5103 } else {
5104 try func.store(result_ptr, payload, field.ty, 0);
5105 if (layout.tag_size > 0) {
5106 try func.store(
5107 result_ptr,
5108 tag_int,
5109 union_obj.tag_ty,
5110 @intCast(u32, layout.payload_size),
5111 );
5112 }
50915113 }
5114 break :result result_ptr;
50925115 } else {
5093 try func.store(result_ptr, payload, field.ty, 0);
5094 if (layout.tag_size > 0) {
5095 try func.store(
5096 result_ptr,
5097 tag_int,
5098 union_obj.tag_ty,
5099 @intCast(u32, layout.payload_size),
5100 );
5116 const operand = try func.resolveInst(extra.init);
5117 var payload: Type.Payload.Bits = .{
5118 .base = .{ .tag = .int_unsigned },
5119 .data = @intCast(u16, union_ty.bitSize(func.target)),
5120 };
5121 const union_int_type = Type.initPayload(&payload.base);
5122 if (field.ty.zigTypeTag() == .Float) {
5123 var int_payload: Type.Payload.Bits = .{
5124 .base = .{ .tag = .int_unsigned },
5125 .data = @intCast(u16, field.ty.bitSize(func.target)),
5126 };
5127 const int_type = Type.initPayload(&int_payload.base);
5128 const bitcasted = try func.bitcast(field.ty, int_type, operand);
5129 const casted = try func.trunc(bitcasted, int_type, union_int_type);
5130 break :result try casted.toLocal(func, field.ty);
5131 } else if (field.ty.isPtrAtRuntime()) {
5132 var int_payload: Type.Payload.Bits = .{
5133 .base = .{ .tag = .int_unsigned },
5134 .data = @intCast(u16, field.ty.bitSize(func.target)),
5135 };
5136 const int_type = Type.initPayload(&int_payload.base);
5137 const casted = try func.intcast(operand, int_type, union_int_type);
5138 break :result try casted.toLocal(func, field.ty);
51015139 }
5140 const casted = try func.intcast(operand, field.ty, union_int_type);
5141 break :result try casted.toLocal(func, field.ty);
51025142 }
5103 break :result result_ptr;
51045143 };
51055144
51065145 return func.finishAir(inst, result, &.{extra.init});