| ... | @@ -1716,7 +1716,14 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1716,7 +1716,14 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1716 | .Array, | 1716 | .Array, |
| 1717 | .Frame, | 1717 | .Frame, |
| 1718 | .Union, | 1718 | .Union, |
| 1719 | => return ty.hasRuntimeBitsIgnoreComptime(), | 1719 | => { |
| | 1720 | if (ty.castTag(.@"union")) |union_ty| { |
| | 1721 | if (union_ty.data.layout == .Packed) { |
| | 1722 | return ty.abiSize(target) > 8; |
| | 1723 | } |
| | 1724 | } |
| | 1725 | return ty.hasRuntimeBitsIgnoreComptime(); |
| | 1726 | }, |
| 1720 | .Struct => { | 1727 | .Struct => { |
| 1721 | if (ty.castTag(.@"struct")) |struct_ty| { | 1728 | if (ty.castTag(.@"struct")) |struct_ty| { |
| 1722 | const struct_obj = struct_ty.data; | 1729 | const struct_obj = struct_ty.data; |
| ... | @@ -3131,6 +3138,14 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -3131,6 +3138,14 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 3131 | val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable; | 3138 | val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable; |
| 3132 | return func.storeSimdImmd(buf); | 3139 | return func.storeSimdImmd(buf); |
| 3133 | }, | 3140 | }, |
| | 3141 | .Union => { |
| | 3142 | // in this case we have a packed union which will not be passed by reference. |
| | 3143 | const union_ty = ty.cast(Type.Payload.Union).?.data; |
| | 3144 | const union_obj = val.castTag(.@"union").?.data; |
| | 3145 | const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?; |
| | 3146 | const field_ty = union_ty.fields.values()[field_index].ty; |
| | 3147 | return func.lowerConstant(union_obj.val, field_ty); |
| | 3148 | }, |
| 3134 | else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}), | 3149 | else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}), |
| 3135 | } | 3150 | } |
| 3136 | } | 3151 | } |
| ... | @@ -3661,8 +3676,42 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3661,8 +3676,42 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3661 | break :result try truncated.toLocal(func, field_ty); | 3676 | break :result try truncated.toLocal(func, field_ty); |
| 3662 | }, | 3677 | }, |
| 3663 | .Union => result: { | 3678 | .Union => result: { |
| 3664 | const val = try func.load(operand, field_ty, 0); | 3679 | if (isByRef(struct_ty, func.target)) { |
| 3665 | break :result try val.toLocal(func, field_ty); | 3680 | if (!isByRef(field_ty, func.target)) { |
| | 3681 | const val = try func.load(operand, field_ty, 0); |
| | 3682 | break :result try val.toLocal(func, field_ty); |
| | 3683 | } else { |
| | 3684 | const new_stack_val = try func.allocStack(field_ty); |
| | 3685 | try func.store(new_stack_val, operand, field_ty, 0); |
| | 3686 | break :result new_stack_val; |
| | 3687 | } |
| | 3688 | } |
| | 3689 | |
| | 3690 | var payload: Type.Payload.Bits = .{ |
| | 3691 | .base = .{ .tag = .int_unsigned }, |
| | 3692 | .data = @intCast(u16, struct_ty.bitSize(func.target)), |
| | 3693 | }; |
| | 3694 | const union_int_type = Type.initPayload(&payload.base); |
| | 3695 | if (field_ty.zigTypeTag() == .Float) { |
| | 3696 | var int_payload: Type.Payload.Bits = .{ |
| | 3697 | .base = .{ .tag = .int_unsigned }, |
| | 3698 | .data = @intCast(u16, field_ty.bitSize(func.target)), |
| | 3699 | }; |
| | 3700 | const int_type = Type.initPayload(&int_payload.base); |
| | 3701 | const truncated = try func.trunc(operand, int_type, union_int_type); |
| | 3702 | const bitcasted = try func.bitcast(field_ty, int_type, truncated); |
| | 3703 | break :result try bitcasted.toLocal(func, field_ty); |
| | 3704 | } else if (field_ty.isPtrAtRuntime()) { |
| | 3705 | var int_payload: Type.Payload.Bits = .{ |
| | 3706 | .base = .{ .tag = .int_unsigned }, |
| | 3707 | .data = @intCast(u16, field_ty.bitSize(func.target)), |
| | 3708 | }; |
| | 3709 | const int_type = Type.initPayload(&int_payload.base); |
| | 3710 | const truncated = try func.trunc(operand, int_type, union_int_type); |
| | 3711 | break :result try truncated.toLocal(func, field_ty); |
| | 3712 | } |
| | 3713 | const truncated = try func.trunc(operand, field_ty, union_int_type); |
| | 3714 | break :result try truncated.toLocal(func, field_ty); |
| 3666 | }, | 3715 | }, |
| 3667 | else => unreachable, | 3716 | else => unreachable, |
| 3668 | }, | 3717 | }, |