diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-11-21 20:31:58 +0100 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-11-30 17:56:01 +0100 |
| commit | 2be0d5bbca5a261533b96dbc0e7bc400000e6e07 (patch) | |
| tree | 5af7e57d44eda6510e37848eb4ae8f6d886e0c7d /src | |
| parent | 71038c42f554da86ee23c9c448d39e457d5818eb (diff) | |
| download | zig-2be0d5bbca5a261533b96dbc0e7bc400000e6e07.tar.gz zig-2be0d5bbca5a261533b96dbc0e7bc400000e6e07.zip | |
wasm: add support packed structs in lowerConstant
When lowering constants of packed structs, which are smaller than 65
bits, we lower the value to an integer rather than store it in the
constant data section. This allows us to use an immediate value,
for quick loads and stores.
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 7dca38b619..f89eb938ee 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1119,13 +1119,14 @@ fn genFunc(func: *CodeGen) InnerError!void { try func.addTag(.dbg_prologue_end); try func.branches.append(func.gpa, .{}); + // clean up outer branch + defer { + var outer_branch = func.branches.pop(); + outer_branch.deinit(func.gpa); + } // Generate MIR for function body try func.genBody(func.air.getMainBody()); - // clean up outer branch - var outer_branch = func.branches.pop(); - outer_branch.deinit(func.gpa); - // In case we have a return value, but the last instruction is a noreturn (such as a while loop) // we emit an unreachable instruction to tell the stack validator that part will never be reached. if (func_type.returns.len != 0 and func.air.instructions.len > 0) { @@ -1607,10 +1608,18 @@ fn isByRef(ty: Type, target: std.Target) bool { .Array, .Vector, - .Struct, .Frame, .Union, => return ty.hasRuntimeBitsIgnoreComptime(), + .Struct => { + if (ty.castTag(.@"struct")) |struct_ty| { + const struct_obj = struct_ty.data; + if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { + return isByRef(struct_obj.backing_int_ty, target); + } + } + return ty.hasRuntimeBitsIgnoreComptime(); + }, .Int => return ty.intInfo(target).bits > 64, .Float => return ty.floatBits(target) > 64, .ErrorUnion => { @@ -2134,7 +2143,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE const len = @intCast(u32, ty.abiSize(func.target)); return func.memcpy(lhs, rhs, .{ .imm32 = len }); }, - .Struct, .Array, .Union, .Vector => { + .Struct, .Array, .Union, .Vector => if (isByRef(ty, func.target)) { const len = @intCast(u32, ty.abiSize(func.target)); return func.memcpy(lhs, rhs, .{ .imm32 = len }); }, @@ -2689,6 +2698,18 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { const is_pl = val.tag() == .opt_payload; return WValue{ .imm32 = if (is_pl) @as(u32, 1) else 0 }; }, + .Struct => { + const struct_obj = ty.castTag(.@"struct").?.data; + assert(struct_obj.layout == .Packed); + var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer + val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0); + var payload: Value.Payload.U64 = .{ + .base = .{ .tag = .int_u64 }, + .data = std.mem.readIntLittle(u64, &buf), + }; + const int_val = Value.initPayload(&payload.base); + return func.lowerConstant(int_val, struct_obj.backing_int_ty); + }, else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}), } } |
