| ... | @@ -1119,13 +1119,14 @@ fn genFunc(func: *CodeGen) InnerError!void { | ... | @@ -1119,13 +1119,14 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1119 | try func.addTag(.dbg_prologue_end); | 1119 | try func.addTag(.dbg_prologue_end); |
| 1120 | | 1120 | |
| 1121 | try func.branches.append(func.gpa, .{}); | 1121 | try func.branches.append(func.gpa, .{}); |
| | 1122 | // clean up outer branch |
| | 1123 | defer { |
| | 1124 | var outer_branch = func.branches.pop(); |
| | 1125 | outer_branch.deinit(func.gpa); |
| | 1126 | } |
| 1122 | // Generate MIR for function body | 1127 | // Generate MIR for function body |
| 1123 | try func.genBody(func.air.getMainBody()); | 1128 | try func.genBody(func.air.getMainBody()); |
| 1124 | | 1129 | |
| 1125 | // clean up outer branch | | |
| 1126 | var outer_branch = func.branches.pop(); | | |
| 1127 | outer_branch.deinit(func.gpa); | | |
| 1128 | | | |
| 1129 | // In case we have a return value, but the last instruction is a noreturn (such as a while loop) | 1130 | // In case we have a return value, but the last instruction is a noreturn (such as a while loop) |
| 1130 | // we emit an unreachable instruction to tell the stack validator that part will never be reached. | 1131 | // we emit an unreachable instruction to tell the stack validator that part will never be reached. |
| 1131 | if (func_type.returns.len != 0 and func.air.instructions.len > 0) { | 1132 | if (func_type.returns.len != 0 and func.air.instructions.len > 0) { |
| ... | @@ -1607,10 +1608,18 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1607,10 +1608,18 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1607 | | 1608 | |
| 1608 | .Array, | 1609 | .Array, |
| 1609 | .Vector, | 1610 | .Vector, |
| 1610 | .Struct, | | |
| 1611 | .Frame, | 1611 | .Frame, |
| 1612 | .Union, | 1612 | .Union, |
| 1613 | => return ty.hasRuntimeBitsIgnoreComptime(), | 1613 | => return ty.hasRuntimeBitsIgnoreComptime(), |
| | 1614 | .Struct => { |
| | 1615 | if (ty.castTag(.@"struct")) |struct_ty| { |
| | 1616 | const struct_obj = struct_ty.data; |
| | 1617 | if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { |
| | 1618 | return isByRef(struct_obj.backing_int_ty, target); |
| | 1619 | } |
| | 1620 | } |
| | 1621 | return ty.hasRuntimeBitsIgnoreComptime(); |
| | 1622 | }, |
| 1614 | .Int => return ty.intInfo(target).bits > 64, | 1623 | .Int => return ty.intInfo(target).bits > 64, |
| 1615 | .Float => return ty.floatBits(target) > 64, | 1624 | .Float => return ty.floatBits(target) > 64, |
| 1616 | .ErrorUnion => { | 1625 | .ErrorUnion => { |
| ... | @@ -2134,7 +2143,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2134,7 +2143,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2134 | const len = @intCast(u32, ty.abiSize(func.target)); | 2143 | const len = @intCast(u32, ty.abiSize(func.target)); |
| 2135 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2144 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2136 | }, | 2145 | }, |
| 2137 | .Struct, .Array, .Union, .Vector => { | 2146 | .Struct, .Array, .Union, .Vector => if (isByRef(ty, func.target)) { |
| 2138 | const len = @intCast(u32, ty.abiSize(func.target)); | 2147 | const len = @intCast(u32, ty.abiSize(func.target)); |
| 2139 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); | 2148 | return func.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2140 | }, | 2149 | }, |
| ... | @@ -2689,6 +2698,18 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { | ... | @@ -2689,6 +2698,18 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { |
| 2689 | const is_pl = val.tag() == .opt_payload; | 2698 | const is_pl = val.tag() == .opt_payload; |
| 2690 | return WValue{ .imm32 = if (is_pl) @as(u32, 1) else 0 }; | 2699 | return WValue{ .imm32 = if (is_pl) @as(u32, 1) else 0 }; |
| 2691 | }, | 2700 | }, |
| | 2701 | .Struct => { |
| | 2702 | const struct_obj = ty.castTag(.@"struct").?.data; |
| | 2703 | assert(struct_obj.layout == .Packed); |
| | 2704 | var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer |
| | 2705 | val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0); |
| | 2706 | var payload: Value.Payload.U64 = .{ |
| | 2707 | .base = .{ .tag = .int_u64 }, |
| | 2708 | .data = std.mem.readIntLittle(u64, &buf), |
| | 2709 | }; |
| | 2710 | const int_val = Value.initPayload(&payload.base); |
| | 2711 | return func.lowerConstant(int_val, struct_obj.backing_int_ty); |
| | 2712 | }, |
| 2692 | else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}), | 2713 | else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}), |
| 2693 | } | 2714 | } |
| 2694 | } | 2715 | } |