| ... | @@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -647,11 +647,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 647 | } | 647 | } |
| 648 | } | 648 | } |
| 649 | | 649 | |
| 650 | fn 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 | | | |
| 655 | /// Asserts there is already capacity to insert into top branch inst_table. | 650 | /// Asserts there is already capacity to insert into top branch inst_table. |
| 656 | fn processDeath(self: *Self, inst: Air.Inst.Index) void { | 651 | fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 657 | const air_tags = self.air.instructions.items(.tag); | 652 | const air_tags = self.air.instructions.items(.tag); |
| ... | @@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -906,7 +901,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 906 | break :result r; | 901 | break :result r; |
| 907 | }, | 902 | }, |
| 908 | else => { | 903 | 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); |
| 910 | }, | 905 | }, |
| 911 | } | 906 | } |
| 912 | }; | 907 | }; |
| ... | @@ -934,7 +929,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -934,7 +929,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 934 | | 929 | |
| 935 | fn airAdd(self: *Self, inst: Air.Inst.Index) !void { | 930 | fn airAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 936 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 931 | 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); |
| 938 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 933 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 939 | } | 934 | } |
| 940 | | 935 | |
| ... | @@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -952,7 +947,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 952 | | 947 | |
| 953 | fn airSub(self: *Self, inst: Air.Inst.Index) !void { | 948 | fn airSub(self: *Self, inst: Air.Inst.Index) !void { |
| 954 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 949 | 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); |
| 956 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 951 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 957 | } | 952 | } |
| 958 | | 953 | |
| ... | @@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -970,7 +965,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 970 | | 965 | |
| 971 | fn airMul(self: *Self, inst: Air.Inst.Index) !void { | 966 | fn airMul(self: *Self, inst: Air.Inst.Index) !void { |
| 972 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 967 | 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); |
| 974 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 969 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 975 | } | 970 | } |
| 976 | | 971 | |
| ... | @@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1026,25 +1021,25 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1026 | | 1021 | |
| 1027 | fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { | 1022 | fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { |
| 1028 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1023 | 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); |
| 1030 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1025 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1031 | } | 1026 | } |
| 1032 | | 1027 | |
| 1033 | fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { | 1028 | fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { |
| 1034 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1029 | 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); |
| 1036 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1031 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1037 | } | 1032 | } |
| 1038 | | 1033 | |
| 1039 | fn airXor(self: *Self, inst: Air.Inst.Index) !void { | 1034 | fn airXor(self: *Self, inst: Air.Inst.Index) !void { |
| 1040 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1035 | 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); |
| 1042 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1037 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1043 | } | 1038 | } |
| 1044 | | 1039 | |
| 1045 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { | 1040 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 1046 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1041 | 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); |
| 1048 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1043 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1049 | } | 1044 | } |
| 1050 | | 1045 | |
| ... | @@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1056,7 +1051,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1056 | | 1051 | |
| 1057 | fn airShr(self: *Self, inst: Air.Inst.Index) !void { | 1052 | fn airShr(self: *Self, inst: Air.Inst.Index) !void { |
| 1058 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1053 | 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); |
| 1060 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1055 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1061 | } | 1056 | } |
| 1062 | | 1057 | |
| ... | @@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1296,7 +1291,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1296 | else => { | 1291 | else => { |
| 1297 | const dst_mcv = try self.allocRegOrMem(inst, true); | 1292 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1298 | | 1293 | |
| 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)); |
| 1300 | assert(offset_mcv == .register); // result of multiplication should always be register | 1295 | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1301 | self.register_manager.freezeRegs(&.{offset_mcv.register}); | 1296 | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1302 | | 1297 | |
| ... | @@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1304,7 +1299,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1304 | self.register_manager.freezeRegs(&.{addr_reg}); | 1299 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1305 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1300 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1306 | | 1301 | |
| 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); |
| 1308 | | 1303 | |
| 1309 | // At this point in time, neither the base register | 1304 | // At this point in time, neither the base register |
| 1310 | // nor the offset register contains any valuable data | 1305 | // 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 | ... | @@ -1415,6 +1410,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind |
| 1415 | | 1410 | |
| 1416 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 1411 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1417 | const elem_ty = ptr_ty.elemType(); | 1412 | const elem_ty = ptr_ty.elemType(); |
| | 1413 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| | 1414 | |
| 1418 | switch (ptr) { | 1415 | switch (ptr) { |
| 1419 | .none => unreachable, | 1416 | .none => unreachable, |
| 1420 | .undef => unreachable, | 1417 | .undef => unreachable, |
| ... | @@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1440,24 +1437,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1440 | .compare_flags_signed, .compare_flags_unsigned => unreachable, | 1437 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1441 | .embedded_in_code => unreachable, | 1438 | .embedded_in_code => unreachable, |
| 1442 | .register => |dst_reg| { | 1439 | .register => |dst_reg| { |
| 1443 | _ = try self.addInst(.{ | 1440 | try self.genLdrRegister(dst_reg, reg, elem_size); |
| 1444 | .tag = .ldr, | | |
| 1445 | .data = .{ .rr_offset = .{ | | |
| 1446 | .rt = dst_reg, | | |
| 1447 | .rn = reg, | | |
| 1448 | .offset = .{ .offset = Instruction.Offset.none }, | | |
| 1449 | } }, | | |
| 1450 | }); | | |
| 1451 | }, | 1441 | }, |
| 1452 | .stack_offset => |off| { | 1442 | .stack_offset => |off| { |
| 1453 | if (elem_ty.abiSize(self.target.*) <= 4) { | 1443 | if (elem_size <= 4) { |
| 1454 | const tmp_reg = try self.register_manager.allocReg(null); | 1444 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1455 | self.register_manager.freezeRegs(&.{tmp_reg}); | 1445 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1456 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); | 1446 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| 1457 | | 1447 | |
| 1458 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); | 1448 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 1459 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); | 1449 | 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) { |
| 1461 | // TODO generalize this: maybe add a | 1451 | // TODO generalize this: maybe add a |
| 1462 | // genArmMemcpy function which manually copies | 1452 | // genArmMemcpy function which manually copies |
| 1463 | // data if the size is below a certain | 1453 | // 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 | ... | @@ -1500,7 +1490,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1500 | const tmp_reg = regs[3]; | 1490 | const tmp_reg = regs[3]; |
| 1501 | | 1491 | |
| 1502 | // sub dst_reg, fp, #off | 1492 | // sub dst_reg, fp, #off |
| 1503 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | | |
| 1504 | const adj_off = off + elem_size; | 1493 | const adj_off = off + elem_size; |
| 1505 | const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else { | 1494 | const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else { |
| 1506 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); | 1495 | 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 | ... | @@ -1528,7 +1517,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1528 | }); | 1517 | }); |
| 1529 | | 1518 | |
| 1530 | // memcpy(src, dst, len) | 1519 | // 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); |
| 1532 | } | 1521 | } |
| 1533 | }, | 1522 | }, |
| 1534 | else => return self.fail("TODO load from register into {}", .{dst_mcv}), | 1523 | 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 | ... | @@ -1600,14 +1589,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1600 | | 1589 | |
| 1601 | switch (value) { | 1590 | switch (value) { |
| 1602 | .register => |value_reg| { | 1591 | .register => |value_reg| { |
| 1603 | _ = try self.addInst(.{ | 1592 | try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*))); |
| 1604 | .tag = .str, | | |
| 1605 | .data = .{ .rr_offset = .{ | | |
| 1606 | .rt = value_reg, | | |
| 1607 | .rn = addr_reg, | | |
| 1608 | .offset = .{ .offset = Instruction.Offset.none }, | | |
| 1609 | } }, | | |
| 1610 | }); | | |
| 1611 | }, | 1593 | }, |
| 1612 | else => { | 1594 | else => { |
| 1613 | if (value_ty.abiSize(self.target.*) <= 4) { | 1595 | if (value_ty.abiSize(self.target.*) <= 4) { |
| ... | @@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { | ... | @@ -1723,7 +1705,7 @@ fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { |
| 1723 | }; | 1705 | }; |
| 1724 | } | 1706 | } |
| 1725 | | 1707 | |
| 1726 | fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue { | 1708 | fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref, op: Air.Inst.Tag) !MCValue { |
| 1727 | // In the case of bitshifts, the type of rhs is different | 1709 | // In the case of bitshifts, the type of rhs is different |
| 1728 | // from the resulting type | 1710 | // from the resulting type |
| 1729 | const ty = self.air.typeOf(op_lhs); | 1711 | 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: | ... | @@ -1732,17 +1714,17 @@ fn genArmBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: |
| 1732 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 1714 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| 1733 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | 1715 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 1734 | .Bool => { | 1716 | .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); |
| 1736 | }, | 1718 | }, |
| 1737 | .Int => { | 1719 | .Int => { |
| 1738 | const int_info = ty.intInfo(self.target.*); | 1720 | 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); |
| 1740 | }, | 1722 | }, |
| 1741 | else => unreachable, | 1723 | else => unreachable, |
| 1742 | } | 1724 | } |
| 1743 | } | 1725 | } |
| 1744 | | 1726 | |
| 1745 | fn genArmBinIntOp( | 1727 | fn genBinIntOp( |
| 1746 | self: *Self, | 1728 | self: *Self, |
| 1747 | inst: Air.Inst.Index, | 1729 | inst: Air.Inst.Index, |
| 1748 | op_lhs: Air.Inst.Ref, | 1730 | op_lhs: Air.Inst.Ref, |
| ... | @@ -1852,7 +1834,7 @@ fn genArmBinIntOp( | ... | @@ -1852,7 +1834,7 @@ fn genArmBinIntOp( |
| 1852 | try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs); | 1834 | try self.genSetReg(self.air.typeOf(op_rhs), rhs_mcv.register, rhs); |
| 1853 | } | 1835 | } |
| 1854 | | 1836 | |
| 1855 | try self.genArmBinOpCode( | 1837 | try self.genBinOpCode( |
| 1856 | dst_mcv.register, | 1838 | dst_mcv.register, |
| 1857 | lhs_mcv, | 1839 | lhs_mcv, |
| 1858 | rhs_mcv, | 1840 | rhs_mcv, |
| ... | @@ -1863,7 +1845,7 @@ fn genArmBinIntOp( | ... | @@ -1863,7 +1845,7 @@ fn genArmBinIntOp( |
| 1863 | return dst_mcv; | 1845 | return dst_mcv; |
| 1864 | } | 1846 | } |
| 1865 | | 1847 | |
| 1866 | fn genArmBinOpCode( | 1848 | fn genBinOpCode( |
| 1867 | self: *Self, | 1849 | self: *Self, |
| 1868 | dst_reg: Register, | 1850 | dst_reg: Register, |
| 1869 | lhs_mcv: MCValue, | 1851 | lhs_mcv: MCValue, |
| ... | @@ -1971,7 +1953,7 @@ fn genArmBinOpCode( | ... | @@ -1971,7 +1953,7 @@ fn genArmBinOpCode( |
| 1971 | } | 1953 | } |
| 1972 | } | 1954 | } |
| 1973 | | 1955 | |
| 1974 | fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { | 1956 | fn genMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 1975 | const lhs = try self.resolveInst(op_lhs); | 1957 | const lhs = try self.resolveInst(op_lhs); |
| 1976 | const rhs = try self.resolveInst(op_rhs); | 1958 | const rhs = try self.resolveInst(op_rhs); |
| 1977 | | 1959 | |
| ... | @@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai | ... | @@ -2050,7 +2032,7 @@ fn genArmMul(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Ai |
| 2050 | return dst_mcv; | 2032 | return dst_mcv; |
| 2051 | } | 2033 | } |
| 2052 | | 2034 | |
| 2053 | fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { | 2035 | fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 2054 | const lhs = try self.resolveInst(op); | 2036 | const lhs = try self.resolveInst(op); |
| 2055 | const rhs = MCValue{ .immediate = imm }; | 2037 | const rhs = MCValue{ .immediate = imm }; |
| 2056 | | 2038 | |
| ... | @@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { | ... | @@ -2097,7 +2079,71 @@ fn genArmMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 2097 | return dst_mcv; | 2079 | return dst_mcv; |
| 2098 | } | 2080 | } |
| 2099 | | 2081 | |
| 2100 | fn genArmInlineMemcpy( | 2082 | fn 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 | |
| | 2114 | fn 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 | |
| | 2146 | fn genInlineMemcpy( |
| 2101 | self: *Self, | 2147 | self: *Self, |
| 2102 | src: Register, | 2148 | src: Register, |
| 2103 | dst: Register, | 2149 | dst: Register, |
| ... | @@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -2469,7 +2515,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2469 | | 2515 | |
| 2470 | // The destination register is not present in the cmp instruction | 2516 | // The destination register is not present in the cmp instruction |
| 2471 | // The signedness of the integer does not matter for the cmp instruction | 2517 | // 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); |
| 2473 | | 2519 | |
| 2474 | break :result switch (signedness) { | 2520 | break :result switch (signedness) { |
| 2475 | .signed => MCValue{ .compare_flags_signed = op }, | 2521 | .signed => MCValue{ .compare_flags_signed = op }, |
| ... | @@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -2701,7 +2747,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2701 | else => .{ .register = try self.copyToTmpRegister(ty, operand) }, | 2747 | else => .{ .register = try self.copyToTmpRegister(ty, operand) }, |
| 2702 | }; | 2748 | }; |
| 2703 | | 2749 | |
| 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); |
| 2705 | | 2751 | |
| 2706 | return MCValue{ .compare_flags_unsigned = .eq }; | 2752 | return MCValue{ .compare_flags_unsigned = .eq }; |
| 2707 | } else { | 2753 | } else { |
| ... | @@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -2731,7 +2777,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2731 | else => .{ .register = try self.copyToTmpRegister(error_type, operand) }, | 2777 | else => .{ .register = try self.copyToTmpRegister(error_type, operand) }, |
| 2732 | }; | 2778 | }; |
| 2733 | | 2779 | |
| 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); |
| 2735 | | 2781 | |
| 2736 | return MCValue{ .compare_flags_unsigned = .gt }; | 2782 | return MCValue{ .compare_flags_unsigned = .gt }; |
| 2737 | } else { | 2783 | } else { |
| ... | @@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2946,8 +2992,8 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { |
| 2946 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2992 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2947 | const air_tags = self.air.instructions.items(.tag); | 2993 | const air_tags = self.air.instructions.items(.tag); |
| 2948 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) { | 2994 | 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), | 2995 | .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and), |
| 2950 | .bool_or => try self.genArmBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), | 2996 | .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), |
| 2951 | else => unreachable, // Not a boolean operation | 2997 | else => unreachable, // Not a boolean operation |
| 2952 | }; | 2998 | }; |
| 2953 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 2999 | 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 | ... | @@ -3242,7 +3288,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3242 | }); | 3288 | }); |
| 3243 | | 3289 | |
| 3244 | // memcpy(src, dst, len) | 3290 | // 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); |
| 3246 | } | 3292 | } |
| 3247 | }, | 3293 | }, |
| 3248 | } | 3294 | } |
| ... | @@ -3439,14 +3485,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3439,14 +3485,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3439 | // The value is in memory at a hard-coded address. | 3485 | // The value is in memory at a hard-coded address. |
| 3440 | // If the type is a pointer, it means the pointer address is at this memory location. | 3486 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3441 | try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) }); | 3487 | try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) }); |
| 3442 | _ = try self.addInst(.{ | 3488 | try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*))); |
| 3443 | .tag = .ldr, | | |
| 3444 | .data = .{ .rr_offset = .{ | | |
| 3445 | .rt = reg, | | |
| 3446 | .rn = reg, | | |
| 3447 | .offset = .{ .offset = Instruction.Offset.none }, | | |
| 3448 | } }, | | |
| 3449 | }); | | |
| 3450 | }, | 3489 | }, |
| 3451 | .stack_offset => |unadjusted_off| { | 3490 | .stack_offset => |unadjusted_off| { |
| 3452 | // TODO: maybe addressing from sp instead of fp | 3491 | // TODO: maybe addressing from sp instead of fp |