authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-06 18:18:53+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-06 23:29:36+01:00
logadc9a282d8b3cbe58e07c965fe40fb1dd8666bd7
treec5af1be6addc7065ab278f48511155fd3a9c6f71
parent4468abfc424ba645413ee076e5e2e370aa807bcc

stage2 ARM: fix load and store for abi_size < 4

Previously, in these cases, we would emit the ldr instruction even though ldrb oder ldrh are the correct instructions.

1 files changed, 98 insertions(+), 59 deletions(-)

src/arch/arm/CodeGen.zig+98-59
......@@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
647647 }
648648}
649649
650fn writeInt(self: *Self, comptime T: type, buf: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T) void {
651 const endian = self.target.cpu.arch.endian();
652 std.mem.writeInt(T, buf, value, endian);
653}
654
655650/// Asserts there is already capacity to insert into top branch inst_table.
656651fn processDeath(self: *Self, inst: Air.Inst.Index) void {
657652 const air_tags = self.air.instructions.items(.tag);
......@@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
906901 break :result r;
907902 },
908903 else => {
909 break :result try self.genArmBinOp(inst, ty_op.operand, .bool_true, .not);
904 break :result try self.genBinOp(inst, ty_op.operand, .bool_true, .not);
910905 },
911906 }
912907 };
......@@ -934,7 +929,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
934929
935930fn airAdd(self: *Self, inst: Air.Inst.Index) !void {
936931 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
937 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .add);
932 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .add);
938933 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
939934}
940935
......@@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
952947
953948fn airSub(self: *Self, inst: Air.Inst.Index) !void {
954949 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
955 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .sub);
950 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .sub);
956951 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
957952}
958953
......@@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
970965
971966fn airMul(self: *Self, inst: Air.Inst.Index) !void {
972967 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
973 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmMul(inst, bin_op.lhs, bin_op.rhs);
968 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genMul(inst, bin_op.lhs, bin_op.rhs);
974969 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
975970}
976971
......@@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
10261021
10271022fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
10281023 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1029 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and);
1024 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and);
10301025 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10311026}
10321027
10331028fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
10341029 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1035 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or);
1030 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or);
10361031 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10371032}
10381033
10391034fn airXor(self: *Self, inst: Air.Inst.Index) !void {
10401035 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1041 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .xor);
1036 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .xor);
10421037 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10431038}
10441039
10451040fn airShl(self: *Self, inst: Air.Inst.Index) !void {
10461041 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1047 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .shl);
1042 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl);
10481043 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10491044}
10501045
......@@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
10561051
10571052fn airShr(self: *Self, inst: Air.Inst.Index) !void {
10581053 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1059 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .shr);
1054 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shr);
10601055 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10611056}
10621057
......@@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
12961291 else => {
12971292 const dst_mcv = try self.allocRegOrMem(inst, true);
12981293
1299 const offset_mcv = try self.genArmMulConstant(bin_op.rhs, @intCast(u32, elem_size));
1294 const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size));
13001295 assert(offset_mcv == .register); // result of multiplication should always be register
13011296 self.register_manager.freezeRegs(&.{offset_mcv.register});
13021297
......@@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
13041299 self.register_manager.freezeRegs(&.{addr_reg});
13051300 defer self.register_manager.unfreezeRegs(&.{addr_reg});
13061301
1307 try self.genArmBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned);
1302 try self.genBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned);
13081303
13091304 // At this point in time, neither the base register
13101305 // nor the offset register contains any valuable data
......@@ -1415,6 +1410,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
14151410
14161411fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
14171412 const elem_ty = ptr_ty.elemType();
1413 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1414
14181415 switch (ptr) {
14191416 .none => unreachable,
14201417 .undef => unreachable,
......@@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
14401437 .compare_flags_signed, .compare_flags_unsigned => unreachable,
14411438 .embedded_in_code => unreachable,
14421439 .register => |dst_reg| {
1443 _ = try self.addInst(.{
1444 .tag = .ldr,
1445 .data = .{ .rr_offset = .{
1446 .rt = dst_reg,
1447 .rn = reg,
1448 .offset = .{ .offset = Instruction.Offset.none },
1449 } },
1450 });
1440 try self.genLdrRegister(dst_reg, reg, elem_size);
14511441 },
14521442 .stack_offset => |off| {
1453 if (elem_ty.abiSize(self.target.*) <= 4) {
1443 if (elem_size <= 4) {
14541444 const tmp_reg = try self.register_manager.allocReg(null);
14551445 self.register_manager.freezeRegs(&.{tmp_reg});
14561446 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
14571447
14581448 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
14591449 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1460 } else if (elem_ty.abiSize(self.target.*) == 8) {
1450 } else if (elem_size == 8) {
14611451 // TODO generalize this: maybe add a
14621452 // genArmMemcpy function which manually copies
14631453 // data if the size is below a certain
......@@ -1500,7 +1490,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
15001490 const tmp_reg = regs[3];
15011491
15021492 // sub dst_reg, fp, #off
1503 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
15041493 const adj_off = off + elem_size;
15051494 const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else {
15061495 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
......@@ -1528,7 +1517,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
15281517 });
15291518
15301519 // memcpy(src, dst, len)
1531 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
1520 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
15321521 }
15331522 },
15341523 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
......@@ -1600,14 +1589,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
16001589
16011590 switch (value) {
16021591 .register => |value_reg| {
1603 _ = try self.addInst(.{
1604 .tag = .str,
1605 .data = .{ .rr_offset = .{
1606 .rt = value_reg,
1607 .rn = addr_reg,
1608 .offset = .{ .offset = Instruction.Offset.none },
1609 } },
1610 });
1592 try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*)));
16111593 },
16121594 else => {
16131595 if (value_ty.abiSize(self.target.*) <= 4) {
......@@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool {
17231705 };
17241706}
17251707
1726fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue {
1708fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue {
17271709 // In the case of bitshifts, the type of rhs is different
17281710 // from the resulting type
17291711 const ty = self.air.typeOf(op_lhs);
......@@ -1732,17 +1714,17 @@ fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
17321714 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
17331715 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
17341716 .Bool => {
1735 return self.genArmBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned);
1717 return self.genBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned);
17361718 },
17371719 .Int => {
17381720 const int_info = ty.intInfo(self.target.*);
1739 return self.genArmBinIntOp(inst, op_lhs, op_rhs, op, int_info.bits, int_info.signedness);
1721 return self.genBinIntOp(inst, op_lhs, op_rhs, op, int_info.bits, int_info.signedness);
17401722 },
17411723 else => unreachable,
17421724 }
17431725}
17441726
1745fn genArmBinIntOp(
1727fn genBinIntOp(
17461728 self: *Self,
17471729 inst: Air.Inst.Index,
17481730 op_lhs: Air.Inst.Ref,
......@@ -1852,7 +1834,7 @@ fn genArmBinIntOp(
18521834 try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs);
18531835 }
18541836
1855 try self.genArmBinOpCode(
1837 try self.genBinOpCode(
18561838 dst_mcv.register,
18571839 lhs_mcv,
18581840 rhs_mcv,
......@@ -1863,7 +1845,7 @@ fn genArmBinIntOp(
18631845 return dst_mcv;
18641846}
18651847
1866fn genArmBinOpCode(
1848fn genBinOpCode(
18671849 self: *Self,
18681850 dst_reg: Register,
18691851 lhs_mcv: MCValue,
......@@ -1971,7 +1953,7 @@ fn genArmBinOpCode(
19711953 }
19721954}
19731955
1974fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
1956fn genMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
19751957 const lhs = try self.resolveInst(op_lhs);
19761958 const rhs = try self.resolveInst(op_rhs);
19771959
......@@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai
20502032 return dst_mcv;
20512033}
20522034
2053fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
2035fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
20542036 const lhs = try self.resolveInst(op);
20552037 const rhs = MCValue{ .immediate = imm };
20562038
......@@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue {
20972079 return dst_mcv;
20982080}
20992081
2100fn genArmInlineMemcpy(
2082fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, abi_size: u32) !void {
2083 switch (abi_size) {
2084 1, 3, 4 => {
2085 const tag: Mir.Inst.Tag = switch (abi_size) {
2086 1 => .ldrb,
2087 3, 4 => .ldr,
2088 else => unreachable,
2089 };
2090
2091 _ = try self.addInst(.{
2092 .tag = tag,
2093 .data = .{ .rr_offset = .{
2094 .rt = dest_reg,
2095 .rn = addr_reg,
2096 .offset = .{ .offset = Instruction.Offset.none },
2097 } },
2098 });
2099 },
2100 2 => {
2101 _ = try self.addInst(.{
2102 .tag = .ldrh,
2103 .data = .{ .rr_extra_offset = .{
2104 .rt = dest_reg,
2105 .rn = addr_reg,
2106 .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
2107 } },
2108 });
2109 },
2110 else => unreachable, // invalid abi_size for a register
2111 }
2112}
2113
2114fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, abi_size: u32) !void {
2115 switch (abi_size) {
2116 1, 3, 4 => {
2117 const tag: Mir.Inst.Tag = switch (abi_size) {
2118 1 => .strb,
2119 3, 4 => .str,
2120 else => unreachable,
2121 };
2122
2123 _ = try self.addInst(.{
2124 .tag = tag,
2125 .data = .{ .rr_offset = .{
2126 .rt = source_reg,
2127 .rn = addr_reg,
2128 .offset = .{ .offset = Instruction.Offset.none },
2129 } },
2130 });
2131 },
2132 2 => {
2133 _ = try self.addInst(.{
2134 .tag = .strh,
2135 .data = .{ .rr_extra_offset = .{
2136 .rt = source_reg,
2137 .rn = addr_reg,
2138 .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none },
2139 } },
2140 });
2141 },
2142 else => unreachable, // invalid abi_size for a register
2143 }
2144}
2145
2146fn genInlineMemcpy(
21012147 self: *Self,
21022148 src: Register,
21032149 dst: Register,
......@@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24692515
24702516 // The destination register is not present in the cmp instruction
24712517 // The signedness of the integer does not matter for the cmp instruction
2472 try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined);
2518 try self.genBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined);
24732519
24742520 break :result switch (signedness) {
24752521 .signed => MCValue{ .compare_flags_signed = op },
......@@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
27012747 else => .{ .register = try self.copyToTmpRegister(ty, operand) },
27022748 };
27032749
2704 try self.genArmBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
2750 try self.genBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
27052751
27062752 return MCValue{ .compare_flags_unsigned = .eq };
27072753 } else {
......@@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
27312777 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
27322778 };
27332779
2734 try self.genArmBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
2780 try self.genBinOpCode(undefined, reg_mcv, .{ .immediate = 0 }, false, .cmp_eq, undefined);
27352781
27362782 return MCValue{ .compare_flags_unsigned = .gt };
27372783 } else {
......@@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
29462992 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
29472993 const air_tags = self.air.instructions.items(.tag);
29482994 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) {
2949 .bool_and => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and),
2950 .bool_or => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or),
2995 .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and),
2996 .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or),
29512997 else => unreachable, // Not a boolean operation
29522998 };
29532999 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -3242,7 +3288,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
32423288 });
32433289
32443290 // memcpy(src, dst, len)
3245 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
3291 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
32463292 }
32473293 },
32483294 }
......@@ -3439,14 +3485,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
34393485 // The value is in memory at a hard-coded address.
34403486 // If the type is a pointer, it means the pointer address is at this memory location.
34413487 try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) });
3442 _ = try self.addInst(.{
3443 .tag = .ldr,
3444 .data = .{ .rr_offset = .{
3445 .rt = reg,
3446 .rn = reg,
3447 .offset = .{ .offset = Instruction.Offset.none },
3448 } },
3449 });
3488 try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*)));
34503489 },
34513490 .stack_offset => |unadjusted_off| {
34523491 // TODO: maybe addressing from sp instead of fp