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.
This commit is contained in:
Luuk de Gram 2022-11-21 20:31:58 +01:00
parent 71038c42f5
commit 2be0d5bbca
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664

View File

@ -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}),
}
}