authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-04 18:57:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-06 09:54:33+01:00
logf4aa276a0c665633980ea49bccb29da9d02d2ae1
tree6a04dd73df6fb3e24fa37e88bd1a929c40919506
parentf01e6eec562e31445e940c5664c793ff443c35aa

stage2: fix inline memcpy


1 files changed, 63 insertions(+), 19 deletions(-)

src/arch/x86_64/CodeGen.zig+63-19
...@@ -1260,7 +1260,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1260,7 +1260,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1260 const dst_mcv: MCValue = blk: {1260 const dst_mcv: MCValue = blk: {
1261 switch (operand) {1261 switch (operand) {
1262 .stack_offset => |off| {1262 .stack_offset => |off| {
1263 break :blk MCValue{ .stack_offset = off };1263 break :blk MCValue{ .stack_offset = off + 8 };
1264 },1264 },
1265 else => return self.fail("TODO implement slice_ptr for {}", .{operand}),1265 else => return self.fail("TODO implement slice_ptr for {}", .{operand}),
1266 }1266 }
...@@ -1277,7 +1277,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1277,7 +1277,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1277 const dst_mcv: MCValue = blk: {1277 const dst_mcv: MCValue = blk: {
1278 switch (operand) {1278 switch (operand) {
1279 .stack_offset => |off| {1279 .stack_offset => |off| {
1280 break :blk MCValue{ .stack_offset = off + 8 };1280 break :blk MCValue{ .stack_offset = off };
1281 },1281 },
1282 else => return self.fail("TODO implement slice_len for {}", .{operand}),1282 else => return self.fail("TODO implement slice_len for {}", .{operand}),
1283 }1283 }
...@@ -1515,18 +1515,22 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1515,18 +1515,22 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1515 .data = .{ .imm = 0 },1515 .data = .{ .imm = 0 },
1516 });1516 });
1517 },1517 },
1518 .stack_offset => |unadjusted_off| {1518 .stack_offset => |off| {
1519 if (abi_size <= 8) {1519 if (abi_size <= 8) {
1520 const tmp_reg = try self.register_manager.allocReg(null, &.{reg});1520 const tmp_reg = try self.register_manager.allocReg(null, &.{reg});
1521 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);1521 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1522 return self.genSetStack(elem_ty, unadjusted_off, MCValue{ .register = tmp_reg });1522 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1523 }1523 }
15241524
1525 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ reg, .rax, .rcx });1525 const regs = try self.register_manager.allocRegs(
1526 3,
1527 .{ null, null, null },
1528 &.{ reg, .rax, .rcx },
1529 );
1526 const addr_reg = regs[0];1530 const addr_reg = regs[0];
1527 const len_reg = regs[1];1531 const len_reg = regs[1];
1532 const tmp_reg = regs[2];
15281533
1529 const off = unadjusted_off + abi_size;
1530 _ = try self.addInst(.{1534 _ = try self.addInst(.{
1531 .tag = .mov,1535 .tag = .mov,
1532 .ops = (Mir.Ops{1536 .ops = (Mir.Ops{
...@@ -1536,13 +1540,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1536,13 +1540,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1536 .data = undefined,1540 .data = undefined,
1537 });1541 });
15381542
1543 try self.register_manager.getReg(.rax, null);
1544 try self.register_manager.getReg(.rcx, null);
1545
1539 // TODO allow for abi size to be u641546 // TODO allow for abi size to be u64
1540 try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) });1547 try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) });
15411548
1542 return self.genInlineMemcpy(1549 return self.genInlineMemcpy(
1543 -@intCast(i32, off),1550 -@intCast(i32, off + abi_size),
1544 registerAlias(addr_reg, @divExact(reg.size(), 8)),1551 registerAlias(addr_reg, @divExact(reg.size(), 8)),
1545 len_reg.to64(),1552 len_reg.to64(),
1553 tmp_reg.to8(),
1546 );1554 );
1547 },1555 },
1548 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),1556 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
...@@ -2148,6 +2156,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2148,6 +2156,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2148 assert(ty.zigTypeTag() == .Pointer);2156 assert(ty.zigTypeTag() == .Pointer);
2149 const mcv = try self.resolveInst(callee);2157 const mcv = try self.resolveInst(callee);
2150 try self.genSetReg(Type.initTag(.usize), .rax, mcv);2158 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
2159 _ = try self.addInst(.{
2160 .tag = .call,
2161 .ops = (Mir.Ops{
2162 .reg1 = .rax,
2163 .flags = 0b01,
2164 }).encode(),
2165 .data = undefined,
2166 });
2151 }2167 }
2152 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {2168 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
2153 for (info.args) |mc_arg, arg_i| {2169 for (info.args) |mc_arg, arg_i| {
...@@ -2217,6 +2233,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2217,6 +2233,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2217 assert(ty.zigTypeTag() == .Pointer);2233 assert(ty.zigTypeTag() == .Pointer);
2218 const mcv = try self.resolveInst(callee);2234 const mcv = try self.resolveInst(callee);
2219 try self.genSetReg(Type.initTag(.usize), .rax, mcv);2235 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
2236 _ = try self.addInst(.{
2237 .tag = .call,
2238 .ops = (Mir.Ops{
2239 .reg1 = .rax,
2240 .flags = 0b01,
2241 }).encode(),
2242 .data = undefined,
2243 });
2220 }2244 }
2221 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {2245 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2222 for (info.args) |mc_arg, arg_i| {2246 for (info.args) |mc_arg, arg_i| {
...@@ -2269,7 +2293,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2269,7 +2293,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2269 });2293 });
2270 } else return self.fail("TODO implement calling extern fn on plan9", .{});2294 } else return self.fail("TODO implement calling extern fn on plan9", .{});
2271 } else {2295 } else {
2272 return self.fail("TODO implement calling runtime known function pointer", .{});2296 assert(ty.zigTypeTag() == .Pointer);
2297 const mcv = try self.resolveInst(callee);
2298 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
2299 _ = try self.addInst(.{
2300 .tag = .call,
2301 .ops = (Mir.Ops{
2302 .reg1 = .rax,
2303 .flags = 0b01,
2304 }).encode(),
2305 .data = undefined,
2306 });
2273 }2307 }
2274 } else unreachable;2308 } else unreachable;
22752309
...@@ -3118,8 +3152,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3118,8 +3152,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3118 }3152 }
3119 return self.fail("TODO implement memcpy for setting stack from {}", .{mcv});3153 return self.fail("TODO implement memcpy for setting stack from {}", .{mcv});
3120 },3154 },
3121 .stack_offset => |unadjusted_off| {3155 .stack_offset => |off| {
3122 if (stack_offset == unadjusted_off) {3156 if (stack_offset == off) {
3123 // Copy stack variable to itself; nothing to do.3157 // Copy stack variable to itself; nothing to do.
3124 return;3158 return;
3125 }3159 }
...@@ -3130,33 +3164,43 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3130,33 +3164,43 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3130 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });3164 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
3131 }3165 }
31323166
3133 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{ .rax, .rcx });3167 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, &.{ .rax, .rcx });
3134 const addr_reg = regs[0];3168 const addr_reg = regs[0];
3135 const len_reg = regs[1];3169 const len_reg = regs[1];
3170 const tmp_reg = regs[2];
3171
3172 try self.register_manager.getReg(.rax, null);
3173 try self.register_manager.getReg(.rcx, null);
31363174
3137 const off = unadjusted_off + abi_size;
3138 _ = try self.addInst(.{3175 _ = try self.addInst(.{
3139 .tag = .lea,3176 .tag = .lea,
3140 .ops = (Mir.Ops{3177 .ops = (Mir.Ops{
3141 .reg1 = addr_reg.to64(),3178 .reg1 = addr_reg.to64(),
3142 .reg2 = .rbp,3179 .reg2 = .rbp,
3143 }).encode(),3180 }).encode(),
3144 .data = .{ .imm = -@intCast(i32, off) },3181 .data = .{ .imm = -@intCast(i32, off + abi_size) },
3145 });3182 });
31463183
3147 // TODO allow for abi_size to be u643184 // TODO allow for abi_size to be u64
3148 try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) });3185 try self.genSetReg(Type.initTag(.u32), len_reg, .{ .immediate = @intCast(u32, abi_size) });
31493186
3150 return self.genInlineMemcpy(-@intCast(i32, off), addr_reg.to64(), len_reg.to64());3187 return self.genInlineMemcpy(
3188 -@intCast(i32, stack_offset + abi_size),
3189 addr_reg.to64(),
3190 len_reg.to64(),
3191 tmp_reg.to8(),
3192 );
3151 },3193 },
3152 }3194 }
3153}3195}
31543196
3155fn genInlineMemcpy(self: *Self, stack_offset: i32, addr_reg: Register, len_reg: Register) InnerError!void {3197fn genInlineMemcpy(
3156 try self.register_manager.getReg(.rax, null);3198 self: *Self,
3157 try self.register_manager.getReg(.rcx, null);3199 stack_offset: i32,
3158 const tmp_reg = try self.register_manager.allocReg(null, &.{ addr_reg, len_reg, .rax, .rcx });3200 addr_reg: Register,
31593201 len_reg: Register,
3202 tmp_reg: Register,
3203) InnerError!void {
3160 // mov rcx, 03204 // mov rcx, 0
3161 _ = try self.addInst(.{3205 _ = try self.addInst(.{
3162 .tag = .mov,3206 .tag = .mov,