| ... | @@ -1193,7 +1193,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1193,7 +1193,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1193 | /// Asserts that generating an instruction of that form is possible. | 1193 | /// Asserts that generating an instruction of that form is possible. |
| 1194 | fn binOpRegister( | 1194 | fn binOpRegister( |
| 1195 | self: *Self, | 1195 | self: *Self, |
| 1196 | tag: Air.Inst.Tag, | 1196 | mir_tag: Mir.Inst.Tag, |
| 1197 | maybe_inst: ?Air.Inst.Index, | 1197 | maybe_inst: ?Air.Inst.Index, |
| 1198 | lhs: MCValue, | 1198 | lhs: MCValue, |
| 1199 | rhs: MCValue, | 1199 | rhs: MCValue, |
| ... | @@ -1256,38 +1256,9 @@ fn binOpRegister( | ... | @@ -1256,38 +1256,9 @@ fn binOpRegister( |
| 1256 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); | 1256 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1257 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); | 1257 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 1258 | | 1258 | |
| 1259 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 1259 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 1260 | .add, | 1260 | .add_shifted_register, |
| 1261 | .ptr_add, | 1261 | .sub_shifted_register, |
| 1262 | => .add_shifted_register, | | |
| 1263 | .sub, | | |
| 1264 | .ptr_sub, | | |
| 1265 | => .sub_shifted_register, | | |
| 1266 | .cmp_eq => .cmp_shifted_register, | | |
| 1267 | .mul => .mul, | | |
| 1268 | .bit_and, | | |
| 1269 | .bool_and, | | |
| 1270 | => .and_shifted_register, | | |
| 1271 | .bit_or, | | |
| 1272 | .bool_or, | | |
| 1273 | => .orr_shifted_register, | | |
| 1274 | .shl, | | |
| 1275 | .shl_exact, | | |
| 1276 | => .lsl_register, | | |
| 1277 | .shr, | | |
| 1278 | .shr_exact, | | |
| 1279 | => switch (lhs_ty.intInfo(self.target.*).signedness) { | | |
| 1280 | .signed => Mir.Inst.Tag.asr_register, | | |
| 1281 | .unsigned => Mir.Inst.Tag.lsr_register, | | |
| 1282 | }, | | |
| 1283 | .xor => .eor_shifted_register, | | |
| 1284 | else => unreachable, | | |
| 1285 | }; | | |
| 1286 | const mir_data: Mir.Inst.Data = switch (tag) { | | |
| 1287 | .add, | | |
| 1288 | .sub, | | |
| 1289 | .ptr_add, | | |
| 1290 | .ptr_sub, | | |
| 1291 | => .{ .rrr_imm6_shift = .{ | 1262 | => .{ .rrr_imm6_shift = .{ |
| 1292 | .rd = dest_reg, | 1263 | .rd = dest_reg, |
| 1293 | .rn = lhs_reg, | 1264 | .rn = lhs_reg, |
| ... | @@ -1295,27 +1266,24 @@ fn binOpRegister( | ... | @@ -1295,27 +1266,24 @@ fn binOpRegister( |
| 1295 | .imm6 = 0, | 1266 | .imm6 = 0, |
| 1296 | .shift = .lsl, | 1267 | .shift = .lsl, |
| 1297 | } }, | 1268 | } }, |
| 1298 | .cmp_eq => .{ .rr_imm6_shift = .{ | 1269 | .cmp_shifted_register => .{ .rr_imm6_shift = .{ |
| 1299 | .rn = lhs_reg, | 1270 | .rn = lhs_reg, |
| 1300 | .rm = rhs_reg, | 1271 | .rm = rhs_reg, |
| 1301 | .imm6 = 0, | 1272 | .imm6 = 0, |
| 1302 | .shift = .lsl, | 1273 | .shift = .lsl, |
| 1303 | } }, | 1274 | } }, |
| 1304 | .mul, | 1275 | .mul, |
| 1305 | .shl, | 1276 | .lsl_register, |
| 1306 | .shl_exact, | 1277 | .asr_register, |
| 1307 | .shr, | 1278 | .lsr_register, |
| 1308 | .shr_exact, | | |
| 1309 | => .{ .rrr = .{ | 1279 | => .{ .rrr = .{ |
| 1310 | .rd = dest_reg, | 1280 | .rd = dest_reg, |
| 1311 | .rn = lhs_reg, | 1281 | .rn = lhs_reg, |
| 1312 | .rm = rhs_reg, | 1282 | .rm = rhs_reg, |
| 1313 | } }, | 1283 | } }, |
| 1314 | .bit_and, | 1284 | .and_shifted_register, |
| 1315 | .bool_and, | 1285 | .orr_shifted_register, |
| 1316 | .bit_or, | 1286 | .eor_shifted_register, |
| 1317 | .bool_or, | | |
| 1318 | .xor, | | |
| 1319 | => .{ .rrr_imm6_logical_shift = .{ | 1287 | => .{ .rrr_imm6_logical_shift = .{ |
| 1320 | .rd = dest_reg, | 1288 | .rd = dest_reg, |
| 1321 | .rn = lhs_reg, | 1289 | .rn = lhs_reg, |
| ... | @@ -1348,7 +1316,7 @@ fn binOpRegister( | ... | @@ -1348,7 +1316,7 @@ fn binOpRegister( |
| 1348 | /// Asserts that generating an instruction of that form is possible. | 1316 | /// Asserts that generating an instruction of that form is possible. |
| 1349 | fn binOpImmediate( | 1317 | fn binOpImmediate( |
| 1350 | self: *Self, | 1318 | self: *Self, |
| 1351 | tag: Air.Inst.Tag, | 1319 | mir_tag: Mir.Inst.Tag, |
| 1352 | maybe_inst: ?Air.Inst.Index, | 1320 | maybe_inst: ?Air.Inst.Index, |
| 1353 | lhs: MCValue, | 1321 | lhs: MCValue, |
| 1354 | rhs: MCValue, | 1322 | rhs: MCValue, |
| ... | @@ -1379,8 +1347,8 @@ fn binOpImmediate( | ... | @@ -1379,8 +1347,8 @@ fn binOpImmediate( |
| 1379 | }; | 1347 | }; |
| 1380 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); | 1348 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); |
| 1381 | | 1349 | |
| 1382 | const dest_reg = switch (tag) { | 1350 | const dest_reg = switch (mir_tag) { |
| 1383 | .cmp_eq => undefined, // cmp has no destination register | 1351 | .cmp_immediate => undefined, // cmp has no destination register |
| 1384 | else => if (maybe_inst) |inst| blk: { | 1352 | else => if (maybe_inst) |inst| blk: { |
| 1385 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1353 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1386 | | 1354 | |
| ... | @@ -1400,39 +1368,23 @@ fn binOpImmediate( | ... | @@ -1400,39 +1368,23 @@ fn binOpImmediate( |
| 1400 | | 1368 | |
| 1401 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); | 1369 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1402 | | 1370 | |
| 1403 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 1371 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 1404 | .add => .add_immediate, | 1372 | .add_immediate, |
| 1405 | .sub => .sub_immediate, | 1373 | .sub_immediate, |
| 1406 | .shl, | | |
| 1407 | .shl_exact, | | |
| 1408 | => .lsl_immediate, | | |
| 1409 | .shr, | | |
| 1410 | .shr_exact, | | |
| 1411 | => switch (lhs_ty.intInfo(self.target.*).signedness) { | | |
| 1412 | .signed => Mir.Inst.Tag.asr_immediate, | | |
| 1413 | .unsigned => Mir.Inst.Tag.lsr_immediate, | | |
| 1414 | }, | | |
| 1415 | .cmp_eq => .cmp_immediate, | | |
| 1416 | else => unreachable, | | |
| 1417 | }; | | |
| 1418 | const mir_data: Mir.Inst.Data = switch (tag) { | | |
| 1419 | .add, | | |
| 1420 | .sub, | | |
| 1421 | => .{ .rr_imm12_sh = .{ | 1374 | => .{ .rr_imm12_sh = .{ |
| 1422 | .rd = dest_reg, | 1375 | .rd = dest_reg, |
| 1423 | .rn = lhs_reg, | 1376 | .rn = lhs_reg, |
| 1424 | .imm12 = @intCast(u12, rhs.immediate), | 1377 | .imm12 = @intCast(u12, rhs.immediate), |
| 1425 | } }, | 1378 | } }, |
| 1426 | .shl, | 1379 | .lsl_immediate, |
| 1427 | .shl_exact, | 1380 | .asr_immediate, |
| 1428 | .shr, | 1381 | .lsr_immediate, |
| 1429 | .shr_exact, | | |
| 1430 | => .{ .rr_shift = .{ | 1382 | => .{ .rr_shift = .{ |
| 1431 | .rd = dest_reg, | 1383 | .rd = dest_reg, |
| 1432 | .rn = lhs_reg, | 1384 | .rn = lhs_reg, |
| 1433 | .shift = @intCast(u6, rhs.immediate), | 1385 | .shift = @intCast(u6, rhs.immediate), |
| 1434 | } }, | 1386 | } }, |
| 1435 | .cmp_eq => .{ .r_imm12_sh = .{ | 1387 | .cmp_immediate => .{ .r_imm12_sh = .{ |
| 1436 | .rn = lhs_reg, | 1388 | .rn = lhs_reg, |
| 1437 | .imm12 = @intCast(u12, rhs.immediate), | 1389 | .imm12 = @intCast(u12, rhs.immediate), |
| 1438 | } }, | 1390 | } }, |
| ... | @@ -1470,7 +1422,6 @@ fn binOp( | ... | @@ -1470,7 +1422,6 @@ fn binOp( |
| 1470 | ) InnerError!MCValue { | 1422 | ) InnerError!MCValue { |
| 1471 | const target = self.target.*; | 1423 | const target = self.target.*; |
| 1472 | switch (tag) { | 1424 | switch (tag) { |
| 1473 | // Arithmetic operations on integers and floats | | |
| 1474 | .add, | 1425 | .add, |
| 1475 | .sub, | 1426 | .sub, |
| 1476 | .cmp_eq, | 1427 | .cmp_eq, |
| ... | @@ -1498,13 +1449,26 @@ fn binOp( | ... | @@ -1498,13 +1449,26 @@ fn binOp( |
| 1498 | else => unreachable, | 1449 | else => unreachable, |
| 1499 | }; | 1450 | }; |
| 1500 | | 1451 | |
| | 1452 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| | 1453 | .add => .add_shifted_register, |
| | 1454 | .sub => .sub_shifted_register, |
| | 1455 | .cmp_eq => .cmp_shifted_register, |
| | 1456 | else => unreachable, |
| | 1457 | }; |
| | 1458 | const mir_tag_immediate: Mir.Inst.Tag = switch (tag) { |
| | 1459 | .add => .add_immediate, |
| | 1460 | .sub => .sub_immediate, |
| | 1461 | .cmp_eq => .cmp_immediate, |
| | 1462 | else => unreachable, |
| | 1463 | }; |
| | 1464 | |
| 1501 | if (rhs_immediate_ok) { | 1465 | if (rhs_immediate_ok) { |
| 1502 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 1466 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1503 | } else if (lhs_immediate_ok) { | 1467 | } else if (lhs_immediate_ok) { |
| 1504 | // swap lhs and rhs | 1468 | // swap lhs and rhs |
| 1505 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); | 1469 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, rhs, lhs, rhs_ty, true); |
| 1506 | } else { | 1470 | } else { |
| 1507 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1471 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1508 | } | 1472 | } |
| 1509 | } else { | 1473 | } else { |
| 1510 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 1474 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| ... | @@ -1523,7 +1487,7 @@ fn binOp( | ... | @@ -1523,7 +1487,7 @@ fn binOp( |
| 1523 | // TODO add optimisations for multiplication | 1487 | // TODO add optimisations for multiplication |
| 1524 | // with immediates, for example a * 2 can be | 1488 | // with immediates, for example a * 2 can be |
| 1525 | // lowered to a << 1 | 1489 | // lowered to a << 1 |
| 1526 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1490 | return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1527 | } else { | 1491 | } else { |
| 1528 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 1492 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1529 | } | 1493 | } |
| ... | @@ -1564,7 +1528,6 @@ fn binOp( | ... | @@ -1564,7 +1528,6 @@ fn binOp( |
| 1564 | else => unreachable, | 1528 | else => unreachable, |
| 1565 | } | 1529 | } |
| 1566 | }, | 1530 | }, |
| 1567 | // Bitwise operations on integers | | |
| 1568 | .bit_and, | 1531 | .bit_and, |
| 1569 | .bit_or, | 1532 | .bit_or, |
| 1570 | .xor, | 1533 | .xor, |
| ... | @@ -1576,7 +1539,14 @@ fn binOp( | ... | @@ -1576,7 +1539,14 @@ fn binOp( |
| 1576 | const int_info = lhs_ty.intInfo(self.target.*); | 1539 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1577 | if (int_info.bits <= 64) { | 1540 | if (int_info.bits <= 64) { |
| 1578 | // TODO implement bitwise operations with immediates | 1541 | // TODO implement bitwise operations with immediates |
| 1579 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1542 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 1543 | .bit_and => .and_shifted_register, |
| | 1544 | .bit_or => .orr_shifted_register, |
| | 1545 | .xor => .eor_shifted_register, |
| | 1546 | else => unreachable, |
| | 1547 | }; |
| | 1548 | |
| | 1549 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1580 | } else { | 1550 | } else { |
| 1581 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 1551 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1582 | } | 1552 | } |
| ... | @@ -1594,10 +1564,27 @@ fn binOp( | ... | @@ -1594,10 +1564,27 @@ fn binOp( |
| 1594 | if (int_info.bits <= 64) { | 1564 | if (int_info.bits <= 64) { |
| 1595 | const rhs_immediate_ok = rhs == .immediate; | 1565 | const rhs_immediate_ok = rhs == .immediate; |
| 1596 | | 1566 | |
| | 1567 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| | 1568 | .shl => .lsl_register, |
| | 1569 | .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| | 1570 | .signed => Mir.Inst.Tag.asr_register, |
| | 1571 | .unsigned => Mir.Inst.Tag.lsr_register, |
| | 1572 | }, |
| | 1573 | else => unreachable, |
| | 1574 | }; |
| | 1575 | const mir_tag_immediate: Mir.Inst.Tag = switch (tag) { |
| | 1576 | .shl => .lsl_immediate, |
| | 1577 | .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| | 1578 | .signed => Mir.Inst.Tag.asr_immediate, |
| | 1579 | .unsigned => Mir.Inst.Tag.lsr_immediate, |
| | 1580 | }, |
| | 1581 | else => unreachable, |
| | 1582 | }; |
| | 1583 | |
| 1597 | if (rhs_immediate_ok) { | 1584 | if (rhs_immediate_ok) { |
| 1598 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); | 1585 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1599 | } else { | 1586 | } else { |
| 1600 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1587 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1601 | } | 1588 | } |
| 1602 | } else { | 1589 | } else { |
| 1603 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 1590 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| ... | @@ -1614,7 +1601,13 @@ fn binOp( | ... | @@ -1614,7 +1601,13 @@ fn binOp( |
| 1614 | assert(lhs != .immediate); // should have been handled by Sema | 1601 | assert(lhs != .immediate); // should have been handled by Sema |
| 1615 | assert(rhs != .immediate); // should have been handled by Sema | 1602 | assert(rhs != .immediate); // should have been handled by Sema |
| 1616 | | 1603 | |
| 1617 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1604 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| | 1605 | .bool_and => .and_shifted_register, |
| | 1606 | .bool_or => .orr_shifted_register, |
| | 1607 | else => unreachable, |
| | 1608 | }; |
| | 1609 | |
| | 1610 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1618 | }, | 1611 | }, |
| 1619 | else => unreachable, | 1612 | else => unreachable, |
| 1620 | } | 1613 | } |
| ... | @@ -1632,9 +1625,9 @@ fn binOp( | ... | @@ -1632,9 +1625,9 @@ fn binOp( |
| 1632 | const elem_size = elem_ty.abiSize(self.target.*); | 1625 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1633 | | 1626 | |
| 1634 | if (elem_size == 1) { | 1627 | if (elem_size == 1) { |
| 1635 | const base_tag: Air.Inst.Tag = switch (tag) { | 1628 | const base_tag: Mir.Inst.Tag = switch (tag) { |
| 1636 | .ptr_add => .add, | 1629 | .ptr_add => .add_shifted_register, |
| 1637 | .ptr_sub => .sub, | 1630 | .ptr_sub => .sub_shifted_register, |
| 1638 | else => unreachable, | 1631 | else => unreachable, |
| 1639 | }; | 1632 | }; |
| 1640 | | 1633 | |