authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-04 17:51:15+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:51+02:00
logdcb236acf432c1d772b2f7d65074735eeae4c4c2
tree67442af970ef392ea315b5e5c92f5ff8cf316163
parent02738228f24b807c45f9ae7b3b1f3657668aed27
signature Commit is signed but in an unrecognized format.

stage2 AArch64: memcpy support in store and more complete intcast


1 files changed, 70 insertions(+), 10 deletions(-)

src/arch/aarch64/CodeGen.zig+70-10
......@@ -1029,17 +1029,37 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
10291029 if (self.liveness.isUnused(inst))
10301030 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
10311031
1032 const operand_ty = self.air.typeOf(ty_op.operand);
1033 const operand = try self.resolveInst(ty_op.operand);
1034 const info_a = operand_ty.intInfo(self.target.*);
1035 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);
1036 if (info_a.signedness != info_b.signedness)
1037 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
1032 const operand = ty_op.operand;
1033 const operand_mcv = try self.resolveInst(operand);
1034 const operand_ty = self.air.typeOf(operand);
1035 const operand_info = operand_ty.intInfo(self.target.*);
1036
1037 const dest_ty = self.air.typeOfIndex(inst);
1038 const dest_info = dest_ty.intInfo(self.target.*);
10381039
1039 if (info_a.bits == info_b.bits)
1040 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
1040 const result: MCValue = result: {
1041 const operand_lock: ?RegisterLock = switch (operand_mcv) {
1042 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1043 else => null,
1044 };
1045 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
1046
1047 if (dest_info.bits > operand_info.bits) {
1048 const dest_mcv = try self.allocRegOrMem(inst, true);
1049 try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, operand_mcv);
1050 break :result dest_mcv;
1051 } else {
1052 if (self.reuseOperand(inst, operand, 0, operand_mcv)) {
1053 break :result operand_mcv;
1054 } else {
1055 const dest_mcv = try self.allocRegOrMem(inst, true);
1056 try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, operand_mcv);
1057 break :result dest_mcv;
1058 }
1059 }
1060 };
10411061
1042 return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});
1062 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
10431063}
10441064
10451065fn truncRegister(
......@@ -1065,6 +1085,8 @@ fn truncRegister(
10651085 });
10661086 },
10671087 32, 64 => {
1088 assert(dest_reg.size() == operand_reg.size());
1089
10681090 _ = try self.addInst(.{
10691091 .tag = .mov_register,
10701092 .data = .{ .rr = .{
......@@ -2955,6 +2977,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
29552977 defer if (addr_reg_lock) |reg| self.register_manager.unlockReg(reg);
29562978
29572979 switch (value) {
2980 .dead => unreachable,
2981 .undef => unreachable,
29582982 .register => |value_reg| {
29592983 try self.genStrRegister(value_reg, addr_reg, value_ty);
29602984 },
......@@ -2968,7 +2992,41 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
29682992 try self.genSetReg(value_ty, tmp_reg, value);
29692993 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
29702994 } else {
2971 return self.fail("TODO implement memcpy", .{});
2995 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, gp);
2996 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
2997 defer for (regs_locks) |reg| {
2998 self.register_manager.unlockReg(reg);
2999 };
3000
3001 const src_reg = addr_reg;
3002 const dst_reg = regs[0];
3003 const len_reg = regs[1];
3004 const count_reg = regs[2];
3005 const tmp_reg = regs[3];
3006
3007 switch (value) {
3008 .stack_offset => |off| {
3009 // sub src_reg, fp, #off
3010 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
3011 },
3012 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
3013 .stack_argument_offset => |off| {
3014 _ = try self.addInst(.{
3015 .tag = .ldr_ptr_stack_argument,
3016 .data = .{ .load_store_stack = .{
3017 .rt = src_reg,
3018 .offset = off,
3019 } },
3020 });
3021 },
3022 else => return self.fail("TODO store {} to register", .{value}),
3023 }
3024
3025 // mov len, #abi_size
3026 try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size });
3027
3028 // memcpy(src, dst, len)
3029 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
29723030 }
29733031 },
29743032 }
......@@ -4359,6 +4417,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
43594417 }
43604418 },
43614419 .register => |src_reg| {
4420 assert(src_reg.size() == reg.size());
4421
43624422 // If the registers are the same, nothing to do.
43634423 if (src_reg.id() == reg.id())
43644424 return;