| ... | ... | @@ -1014,6 +1014,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 1014 | 1014 | .direct => wasm.Valtype.v128, |
| 1015 | 1015 | .unrolled => wasm.Valtype.i32, |
| 1016 | 1016 | }, |
| 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 | }, |
| 1017 | 1028 | else => wasm.Valtype.i32, // all represented as reference/immediate |
| 1018 | 1029 | }; |
| 1019 | 1030 | } |
| ... | ... | @@ -5074,33 +5085,61 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5074 | 5085 | assert(!isByRef(union_ty, func.target)); |
| 5075 | 5086 | break :result tag_int; |
| 5076 | 5087 | } |
| 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 | | } |
| 5088 | 5088 | |
| 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 | } |
| 5091 | 5113 | } |
| 5114 | break :result result_ptr; |
| 5092 | 5115 | } 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); |
| 5101 | 5139 | } |
| 5140 | const casted = try func.intcast(operand, field.ty, union_int_type); |
| 5141 | break :result try casted.toLocal(func, field.ty); |
| 5102 | 5142 | } |
| 5103 | | break :result result_ptr; |
| 5104 | 5143 | }; |
| 5105 | 5144 | |
| 5106 | 5145 | return func.finishAir(inst, result, &.{extra.init}); |