| ... | @@ -1014,6 +1014,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { | ... | @@ -1014,6 +1014,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype { |
| 1014 | .direct => wasm.Valtype.v128, | 1014 | .direct => wasm.Valtype.v128, |
| 1015 | .unrolled => wasm.Valtype.i32, | 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 | else => wasm.Valtype.i32, // all represented as reference/immediate | 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,33 +5085,61 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5074 | assert(!isByRef(union_ty, func.target)); | 5085 | assert(!isByRef(union_ty, func.target)); |
| 5075 | break :result tag_int; | 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) { | 5089 | if (isByRef(union_ty, func.target)) { |
| 5090 | try func.store(result_ptr, tag_int, union_obj.tag_ty, 0); | 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 | } else { | 5115 | } else { |
| 5093 | try func.store(result_ptr, payload, field.ty, 0); | 5116 | const operand = try func.resolveInst(extra.init); |
| 5094 | if (layout.tag_size > 0) { | 5117 | var payload: Type.Payload.Bits = .{ |
| 5095 | try func.store( | 5118 | .base = .{ .tag = .int_unsigned }, |
| 5096 | result_ptr, | 5119 | .data = @intCast(u16, union_ty.bitSize(func.target)), |
| 5097 | tag_int, | 5120 | }; |
| 5098 | union_obj.tag_ty, | 5121 | const union_int_type = Type.initPayload(&payload.base); |
| 5099 | @intCast(u32, layout.payload_size), | 5122 | if (field.ty.zigTypeTag() == .Float) { |
| 5100 | ); | 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 | return func.finishAir(inst, result, &.{extra.init}); | 5145 | return func.finishAir(inst, result, &.{extra.init}); |