aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-07 17:08:33 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-07 20:13:29 +0100
commit7a9b9df80e9799421393f476ea10332ba35ec258 (patch)
treecac6f357f444b7c756226809979ea0d9d6a12d15 /src
parentac36fe71147a78e5f9299428eee776efcc9e4afb (diff)
downloadzig-7a9b9df80e9799421393f476ea10332ba35ec258.tar.gz
zig-7a9b9df80e9799421393f476ea10332ba35ec258.zip
stage2,x64: impl masking reg for struct_field_val
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 1aac404346..e2ae339bae 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2025,16 +2025,35 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const mcv = try self.resolveInst(operand);
const struct_ty = self.air.typeOf(operand);
- const struct_size = @intCast(i32, struct_ty.abiSize(self.target.*));
- const struct_field_offset = @intCast(i32, struct_ty.structFieldOffset(index, self.target.*));
+ const struct_size = struct_ty.abiSize(self.target.*);
+ const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*);
const struct_field_ty = struct_ty.structFieldType(index);
- const struct_field_size = @intCast(i32, struct_field_ty.abiSize(self.target.*));
+ const struct_field_size = struct_field_ty.abiSize(self.target.*);
switch (mcv) {
.stack_offset => |off| {
- const stack_offset = off + struct_size - struct_field_offset - struct_field_size;
+ const offset_to_field = struct_size - struct_field_offset - struct_field_size;
+ const stack_offset = off + @intCast(i32, offset_to_field);
break :result MCValue{ .stack_offset = stack_offset };
},
+ .register => |reg| {
+ // 1. Shift by struct_field_offset.
+ // 2. Mask with reg.size() - struct_field_size
+ // 3. Return in register
+
+ // TODO check if register can be re-used
+ self.register_manager.freezeRegs(&.{reg});
+ defer self.register_manager.unfreezeRegs(&.{reg});
+ const dst_mcv = try self.copyToNewRegister(inst, Type.usize, .{ .register = reg.to64() });
+
+ // TODO shift here
+
+ const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*)));
+ const mask = (~@as(u64, 0)) >> mask_shift;
+ try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .immediate = mask });
+
+ break :result dst_mcv;
+ },
else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}),
}
};