| ... | @@ -34,7 +34,10 @@ const Register = bits.Register; | ... | @@ -34,7 +34,10 @@ const Register = bits.Register; |
| 34 | const RegisterManager = abi.RegisterManager; | 34 | const RegisterManager = abi.RegisterManager; |
| 35 | const RegisterLock = RegisterManager.RegisterLock; | 35 | const RegisterLock = RegisterManager.RegisterLock; |
| 36 | const callee_preserved_regs = abi.callee_preserved_regs; | 36 | const callee_preserved_regs = abi.callee_preserved_regs; |
| | 37 | /// General Purpose |
| 37 | const gp = abi.RegisterClass.gp; | 38 | const gp = abi.RegisterClass.gp; |
| | 39 | /// Function Args |
| | 40 | const fa = abi.RegisterClass.fa; |
| 38 | | 41 | |
| 39 | const InnerError = CodeGenError || error{OutOfRegisters}; | 42 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 40 | | 43 | |
| ... | @@ -297,6 +300,7 @@ pub fn generate( | ... | @@ -297,6 +300,7 @@ pub fn generate( |
| 297 | .prev_di_pc = 0, | 300 | .prev_di_pc = 0, |
| 298 | .prev_di_line = func.lbrace_line, | 301 | .prev_di_line = func.lbrace_line, |
| 299 | .prev_di_column = func.lbrace_column, | 302 | .prev_di_column = func.lbrace_column, |
| | 303 | .stack_size = @max(32, function.max_end_stack), |
| 300 | }; | 304 | }; |
| 301 | defer emit.deinit(); | 305 | defer emit.deinit(); |
| 302 | | 306 | |
| ... | @@ -349,14 +353,9 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { | ... | @@ -349,14 +353,9 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 349 | } | 353 | } |
| 350 | | 354 | |
| 351 | fn gen(self: *Self) !void { | 355 | fn gen(self: *Self) !void { |
| 352 | const mod = self.bin_file.comp.module.?; | | |
| 353 | const cc = self.fn_type.fnCallingConvention(mod); | | |
| 354 | | | |
| 355 | if (cc == .Naked) return self.fail("TODO: gen support callconv(.{s})", .{@tagName(cc)}); | | |
| 356 | | | |
| 357 | _ = try self.addInst(.{ | 356 | _ = try self.addInst(.{ |
| 358 | .tag = .psuedo_prologue, | 357 | .tag = .psuedo_prologue, |
| 359 | .data = .{ .imm12 = 0 }, // Backpatched later. | 358 | .data = .{ .nop = {} }, // Backpatched later. |
| 360 | }); | 359 | }); |
| 361 | | 360 | |
| 362 | _ = try self.addInst(.{ | 361 | _ = try self.addInst(.{ |
| ... | @@ -366,32 +365,6 @@ fn gen(self: *Self) !void { | ... | @@ -366,32 +365,6 @@ fn gen(self: *Self) !void { |
| 366 | | 365 | |
| 367 | try self.genBody(self.air.getMainBody()); | 366 | try self.genBody(self.air.getMainBody()); |
| 368 | | 367 | |
| 369 | // Backpatch prologue stack size | | |
| 370 | if (math.cast(i12, self.max_end_stack)) |casted_stack_size| { | | |
| 371 | self.mir_instructions.items(.data)[0].imm12 = casted_stack_size; | | |
| 372 | } else return self.fail("TODO support larger stack sizes, got {}", .{self.max_end_stack}); | | |
| 373 | | | |
| 374 | _ = try self.addInst(.{ | | |
| 375 | .tag = .dbg_epilogue_begin, | | |
| 376 | .data = .{ .nop = {} }, | | |
| 377 | }); | | |
| 378 | | | |
| 379 | // exitlude jumps | | |
| 380 | if (self.exitlude_jump_relocs.items.len > 0 and | | |
| 381 | self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2) | | |
| 382 | { | | |
| 383 | // If the last Mir instruction (apart from the | | |
| 384 | // dbg_epilogue_begin) is the last exitlude jump | | |
| 385 | // relocation (which would just jump one instruction | | |
| 386 | // further), it can be safely removed | | |
| 387 | self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop()); | | |
| 388 | } | | |
| 389 | | | |
| 390 | for (self.exitlude_jump_relocs.items) |jmp_reloc| { | | |
| 391 | _ = jmp_reloc; | | |
| 392 | return self.fail("TODO add branches in RISCV64", .{}); | | |
| 393 | } | | |
| 394 | | | |
| 395 | // Drop them off at the rbrace. | 368 | // Drop them off at the rbrace. |
| 396 | _ = try self.addInst(.{ | 369 | _ = try self.addInst(.{ |
| 397 | .tag = .dbg_line, | 370 | .tag = .dbg_line, |
| ... | @@ -501,7 +474,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -501,7 +474,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 501 | .fpext => try self.airFpext(inst), | 474 | .fpext => try self.airFpext(inst), |
| 502 | .intcast => try self.airIntCast(inst), | 475 | .intcast => try self.airIntCast(inst), |
| 503 | .trunc => try self.airTrunc(inst), | 476 | .trunc => try self.airTrunc(inst), |
| 504 | .int_from_bool => try self.airIntFromBool(inst), | 477 | .int_from_bool => try self.airIntFromBool(inst), |
| 505 | .is_non_null => try self.airIsNonNull(inst), | 478 | .is_non_null => try self.airIsNonNull(inst), |
| 506 | .is_non_null_ptr => try self.airIsNonNullPtr(inst), | 479 | .is_non_null_ptr => try self.airIsNonNullPtr(inst), |
| 507 | .is_null => try self.airIsNull(inst), | 480 | .is_null => try self.airIsNull(inst), |
| ... | @@ -513,17 +486,17 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -513,17 +486,17 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 513 | .load => try self.airLoad(inst), | 486 | .load => try self.airLoad(inst), |
| 514 | .loop => try self.airLoop(inst), | 487 | .loop => try self.airLoop(inst), |
| 515 | .not => try self.airNot(inst), | 488 | .not => try self.airNot(inst), |
| 516 | .int_from_ptr => try self.airIntFromPtr(inst), | 489 | .int_from_ptr => try self.airIntFromPtr(inst), |
| 517 | .ret => try self.airRet(inst), | 490 | .ret => try self.airRet(inst, false), |
| 518 | .ret_safe => try self.airRet(inst), // TODO | 491 | .ret_safe => try self.airRet(inst, true), |
| 519 | .ret_load => try self.airRetLoad(inst), | 492 | .ret_load => try self.airRetLoad(inst), |
| 520 | .store => try self.airStore(inst, false), | 493 | .store => try self.airStore(inst, false), |
| 521 | .store_safe => try self.airStore(inst, true), | 494 | .store_safe => try self.airStore(inst, true), |
| 522 | .struct_field_ptr=> try self.airStructFieldPtr(inst), | 495 | .struct_field_ptr=> try self.airStructFieldPtr(inst), |
| 523 | .struct_field_val=> try self.airStructFieldVal(inst), | 496 | .struct_field_val=> try self.airStructFieldVal(inst), |
| 524 | .array_to_slice => try self.airArrayToSlice(inst), | 497 | .array_to_slice => try self.airArrayToSlice(inst), |
| 525 | .float_from_int => try self.airFloatFromInt(inst), | 498 | .float_from_int => try self.airFloatFromInt(inst), |
| 526 | .int_from_float => try self.airIntFromFloat(inst), | 499 | .int_from_float => try self.airIntFromFloat(inst), |
| 527 | .cmpxchg_strong => try self.airCmpxchg(inst), | 500 | .cmpxchg_strong => try self.airCmpxchg(inst), |
| 528 | .cmpxchg_weak => try self.airCmpxchg(inst), | 501 | .cmpxchg_weak => try self.airCmpxchg(inst), |
| 529 | .atomic_rmw => try self.airAtomicRmw(inst), | 502 | .atomic_rmw => try self.airAtomicRmw(inst), |
| ... | @@ -792,6 +765,7 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCVa | ... | @@ -792,6 +765,7 @@ fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCVa |
| 792 | | 765 | |
| 793 | fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { | 766 | fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { |
| 794 | const stack_offset = try self.allocMemPtr(inst); | 767 | const stack_offset = try self.allocMemPtr(inst); |
| | 768 | log.debug("airAlloc offset: {}", .{stack_offset}); |
| 795 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); | 769 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); |
| 796 | } | 770 | } |
| 797 | | 771 | |
| ... | @@ -1468,30 +1442,30 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind | ... | @@ -1468,30 +1442,30 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind |
| 1468 | return true; | 1442 | return true; |
| 1469 | } | 1443 | } |
| 1470 | | 1444 | |
| 1471 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { | 1445 | fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 1472 | const mod = self.bin_file.comp.module.?; | 1446 | const mod = self.bin_file.comp.module.?; |
| 1473 | const elem_ty = ptr_ty.childType(mod); | 1447 | const elem_ty = ptr_ty.childType(mod); |
| 1474 | | 1448 | |
| 1475 | switch (ptr) { | 1449 | switch (src_ptr) { |
| 1476 | .none => unreachable, | 1450 | .none => unreachable, |
| 1477 | .undef => unreachable, | 1451 | .undef => unreachable, |
| 1478 | .unreach => unreachable, | 1452 | .unreach => unreachable, |
| 1479 | .dead => unreachable, | 1453 | .dead => unreachable, |
| 1480 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), | 1454 | .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), |
| 1481 | .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }), | 1455 | .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }), |
| 1482 | .register => |src_reg| try self.setRegOrMem(elem_ty, dst_mcv, .{ .register = src_reg }), | 1456 | .register => try self.setValue(elem_ty, dst_mcv, src_ptr), |
| 1483 | .memory, | 1457 | .memory, |
| 1484 | .stack_offset, | 1458 | .stack_offset, |
| 1485 | => { | 1459 | => { |
| 1486 | const reg = try self.register_manager.allocReg(null, gp); | 1460 | const reg = try self.register_manager.allocReg(null, gp); |
| 1487 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); | 1461 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 1488 | defer self.register_manager.unlockReg(reg_lock); | 1462 | errdefer self.register_manager.unlockReg(reg_lock); |
| 1489 | | 1463 | |
| 1490 | try self.genSetReg(ptr_ty, reg, ptr); | 1464 | try self.genSetReg(ptr_ty, reg, src_ptr); |
| 1491 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); | 1465 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 1492 | }, | 1466 | }, |
| 1493 | .load_symbol => { | 1467 | .load_symbol => { |
| 1494 | const reg = try self.copyToTmpRegister(ptr_ty, ptr); | 1468 | const reg = try self.copyToTmpRegister(ptr_ty, src_ptr); |
| 1495 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); | 1469 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| 1496 | }, | 1470 | }, |
| 1497 | } | 1471 | } |
| ... | @@ -1524,34 +1498,18 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1524,34 +1498,18 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1524 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1498 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1525 | } | 1499 | } |
| 1526 | | 1500 | |
| 1527 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { | 1501 | fn store(self: *Self, dst_ptr: MCValue, src_val: MCValue, ptr_ty: Type, value_ty: Type) !void { |
| 1528 | _ = ptr_ty; | 1502 | _ = ptr_ty; |
| 1529 | | 1503 | |
| 1530 | log.debug("storing {s}", .{@tagName(ptr)}); | 1504 | log.debug("storing {s}", .{@tagName(dst_ptr)}); |
| 1531 | | 1505 | |
| 1532 | switch (ptr) { | 1506 | switch (dst_ptr) { |
| 1533 | .none => unreachable, | 1507 | .none => unreachable, |
| 1534 | .undef => unreachable, | 1508 | .undef => unreachable, |
| 1535 | .unreach => unreachable, | 1509 | .unreach => unreachable, |
| 1536 | .dead => unreachable, | 1510 | .dead => unreachable, |
| 1537 | .immediate => |imm| { | 1511 | .ptr_stack_offset => |off| try self.genSetStack(value_ty, off, src_val), |
| 1538 | try self.setRegOrMem(value_ty, .{ .memory = imm }, value); | 1512 | else => return self.fail("TODO implement storing to MCValue.{s}", .{@tagName(dst_ptr)}), |
| 1539 | }, | | |
| 1540 | .ptr_stack_offset => |off| { | | |
| 1541 | try self.genSetStack(value_ty, off, value); | | |
| 1542 | }, | | |
| 1543 | .register => { | | |
| 1544 | return self.fail("TODO implement storing to MCValue.register", .{}); | | |
| 1545 | }, | | |
| 1546 | .memory => { | | |
| 1547 | return self.fail("TODO implement storing to MCValue.memory", .{}); | | |
| 1548 | }, | | |
| 1549 | .stack_offset => { | | |
| 1550 | return self.fail("TODO implement storing to MCValue.stack_offset", .{}); | | |
| 1551 | }, | | |
| 1552 | .load_symbol => { | | |
| 1553 | return self.fail("TODO implement storing to MCValue.load_symbol", .{}); | | |
| 1554 | }, | | |
| 1555 | } | 1513 | } |
| 1556 | } | 1514 | } |
| 1557 | | 1515 | |
| ... | @@ -1629,29 +1587,32 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { | ... | @@ -1629,29 +1587,32 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 1629 | } | 1587 | } |
| 1630 | | 1588 | |
| 1631 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { | 1589 | fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1632 | const arg_index = self.arg_index; | 1590 | var arg_index = self.arg_index; |
| 1633 | self.arg_index += 1; | | |
| 1634 | | 1591 | |
| 1635 | const ty = self.typeOfIndex(inst); | 1592 | // we skip over args that have no bits |
| 1636 | _ = ty; | 1593 | while (self.args[arg_index] == .none) arg_index += 1; |
| | 1594 | self.arg_index = arg_index + 1; |
| 1637 | | 1595 | |
| 1638 | const result = self.args[arg_index]; | 1596 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 1639 | // TODO support stack-only arguments | 1597 | const arg_ty = self.typeOfIndex(inst); |
| 1640 | // TODO Copy registers to the stack | 1598 | _ = arg_ty; |
| 1641 | const mcv = result; | 1599 | const src_mcv = self.args[arg_index]; |
| 1642 | try self.genArgDbgInfo(inst, mcv); | | |
| 1643 | | 1600 | |
| 1644 | if (self.liveness.isUnused(inst)) | 1601 | const dst_mcv = switch (src_mcv) { |
| 1645 | return self.finishAirBookkeeping(); | 1602 | .register => |src_reg| dst: { |
| | 1603 | self.register_manager.getRegAssumeFree(src_reg, inst); |
| | 1604 | break :dst src_mcv; |
| | 1605 | }, |
| | 1606 | // don't need to allocate anything, can just be used immediately. |
| | 1607 | .stack_offset => src_mcv, |
| | 1608 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), |
| | 1609 | }; |
| 1646 | | 1610 | |
| 1647 | switch (mcv) { | 1611 | try self.genArgDbgInfo(inst, src_mcv); |
| 1648 | .register => |reg| { | 1612 | break :result dst_mcv; |
| 1649 | self.register_manager.getRegAssumeFree(reg, inst); | 1613 | }; |
| 1650 | }, | | |
| 1651 | else => {}, | | |
| 1652 | } | | |
| 1653 | | 1614 | |
| 1654 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); | 1615 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 1655 | } | 1616 | } |
| 1656 | | 1617 | |
| 1657 | fn airTrap(self: *Self) !void { | 1618 | fn airTrap(self: *Self) !void { |
| ... | @@ -1704,26 +1665,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1704,26 +1665,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1704 | const arg = args[arg_i]; | 1665 | const arg = args[arg_i]; |
| 1705 | const arg_ty = self.typeOf(arg); | 1666 | const arg_ty = self.typeOf(arg); |
| 1706 | const arg_mcv = try self.resolveInst(args[arg_i]); | 1667 | const arg_mcv = try self.resolveInst(args[arg_i]); |
| 1707 | | 1668 | try self.setValue(arg_ty, mc_arg, arg_mcv); |
| 1708 | switch (mc_arg) { | | |
| 1709 | .none => continue, | | |
| 1710 | .undef => unreachable, | | |
| 1711 | .immediate => unreachable, | | |
| 1712 | .unreach => unreachable, | | |
| 1713 | .dead => unreachable, | | |
| 1714 | .memory => unreachable, | | |
| 1715 | .register => |reg| { | | |
| 1716 | try self.register_manager.getReg(reg, null); | | |
| 1717 | try self.genSetReg(arg_ty, reg, arg_mcv); | | |
| 1718 | }, | | |
| 1719 | .stack_offset => |off| try self.genSetStack(arg_ty, off, arg_mcv), | | |
| 1720 | .ptr_stack_offset => { | | |
| 1721 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); | | |
| 1722 | }, | | |
| 1723 | .load_symbol => { | | |
| 1724 | return self.fail("TODO implement calling with MCValue.load_symbol", .{}); | | |
| 1725 | }, | | |
| 1726 | } | | |
| 1727 | } | 1669 | } |
| 1728 | | 1670 | |
| 1729 | if (try self.air.value(callee, mod)) |func_value| { | 1671 | if (try self.air.value(callee, mod)) |func_value| { |
| ... | @@ -1791,19 +1733,39 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -1791,19 +1733,39 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 1791 | fn ret(self: *Self, mcv: MCValue) !void { | 1733 | fn ret(self: *Self, mcv: MCValue) !void { |
| 1792 | const mod = self.bin_file.comp.module.?; | 1734 | const mod = self.bin_file.comp.module.?; |
| 1793 | const ret_ty = self.fn_type.fnReturnType(mod); | 1735 | const ret_ty = self.fn_type.fnReturnType(mod); |
| 1794 | try self.setRegOrMem(ret_ty, self.ret_mcv, mcv); | 1736 | try self.setValue(ret_ty, self.ret_mcv, mcv); |
| | 1737 | |
| 1795 | // Just add space for an instruction, patch this later | 1738 | // Just add space for an instruction, patch this later |
| 1796 | const index = try self.addInst(.{ | 1739 | const index = try self.addInst(.{ |
| 1797 | .tag = .nop, | 1740 | .tag = .ret, |
| 1798 | .data = .{ .nop = {} }, | 1741 | .data = .{ .nop = {} }, |
| 1799 | }); | 1742 | }); |
| | 1743 | |
| 1800 | try self.exitlude_jump_relocs.append(self.gpa, index); | 1744 | try self.exitlude_jump_relocs.append(self.gpa, index); |
| 1801 | } | 1745 | } |
| 1802 | | 1746 | |
| 1803 | fn airRet(self: *Self, inst: Air.Inst.Index) !void { | 1747 | fn airRet(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| | 1748 | if (safety) { |
| | 1749 | // safe |
| | 1750 | } else { |
| | 1751 | // not safe |
| | 1752 | } |
| | 1753 | |
| 1804 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 1754 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 1805 | const operand = try self.resolveInst(un_op); | 1755 | const operand = try self.resolveInst(un_op); |
| | 1756 | |
| | 1757 | _ = try self.addInst(.{ |
| | 1758 | .tag = .dbg_epilogue_begin, |
| | 1759 | .data = .{ .nop = {} }, |
| | 1760 | }); |
| | 1761 | |
| | 1762 | _ = try self.addInst(.{ |
| | 1763 | .tag = .psuedo_epilogue, |
| | 1764 | .data = .{ .nop = {} }, |
| | 1765 | }); |
| | 1766 | |
| 1806 | try self.ret(operand); | 1767 | try self.ret(operand); |
| | 1768 | |
| 1807 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | 1769 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 1808 | } | 1770 | } |
| 1809 | | 1771 | |
| ... | @@ -1983,7 +1945,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1983,7 +1945,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1983 | log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv }); | 1945 | log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv }); |
| 1984 | // TODO make sure the destination stack offset / register does not already have something | 1946 | // TODO make sure the destination stack offset / register does not already have something |
| 1985 | // going on there. | 1947 | // going on there. |
| 1986 | try self.setRegOrMem(self.typeOfIndex(else_key), canon_mcv, else_value); | 1948 | try self.setValue(self.typeOfIndex(else_key), canon_mcv, else_value); |
| 1987 | // TODO track the new register / stack allocation | 1949 | // TODO track the new register / stack allocation |
| 1988 | } | 1950 | } |
| 1989 | try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count()); | 1951 | try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count()); |
| ... | @@ -2010,7 +1972,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2010,7 +1972,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 2010 | log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value }); | 1972 | log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value }); |
| 2011 | // TODO make sure the destination stack offset / register does not already have something | 1973 | // TODO make sure the destination stack offset / register does not already have something |
| 2012 | // going on there. | 1974 | // going on there. |
| 2013 | try self.setRegOrMem(self.typeOfIndex(then_key), parent_mcv, then_value); | 1975 | try self.setValue(self.typeOfIndex(then_key), parent_mcv, then_value); |
| 2014 | // TODO track the new register / stack allocation | 1976 | // TODO track the new register / stack allocation |
| 2015 | } | 1977 | } |
| 2016 | | 1978 | |
| ... | @@ -2195,7 +2157,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2195,7 +2157,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 2195 | /// Send control flow to the `index` of `self.code`. | 2157 | /// Send control flow to the `index` of `self.code`. |
| 2196 | fn jump(self: *Self, index: Mir.Inst.Index) !void { | 2158 | fn jump(self: *Self, index: Mir.Inst.Index) !void { |
| 2197 | _ = try self.addInst(.{ | 2159 | _ = try self.addInst(.{ |
| 2198 | .tag = .psuedo_jump, | 2160 | .tag = .j, |
| 2199 | .data = .{ | 2161 | .data = .{ |
| 2200 | .inst = index, | 2162 | .inst = index, |
| 2201 | }, | 2163 | }, |
| ... | @@ -2270,7 +2232,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | ... | @@ -2270,7 +2232,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 2270 | if (block_mcv == .none) { | 2232 | if (block_mcv == .none) { |
| 2271 | block_data.mcv = operand_mcv; | 2233 | block_data.mcv = operand_mcv; |
| 2272 | } else { | 2234 | } else { |
| 2273 | try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv); | 2235 | try self.setValue(self.typeOfIndex(block), block_mcv, operand_mcv); |
| 2274 | } | 2236 | } |
| 2275 | } | 2237 | } |
| 2276 | return self.brVoid(block); | 2238 | return self.brVoid(block); |
| ... | @@ -2415,28 +2377,32 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT | ... | @@ -2415,28 +2377,32 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT |
| 2415 | } | 2377 | } |
| 2416 | | 2378 | |
| 2417 | /// Sets the value without any modifications to register allocation metadata or stack allocation metadata. | 2379 | /// Sets the value without any modifications to register allocation metadata or stack allocation metadata. |
| 2418 | fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | 2380 | fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void { |
| 2419 | if (!loc.isMutable()) { | 2381 | // There isn't anything to store |
| 2420 | return std.debug.panic("tried to setRegOrMem immutable: {s}", .{@tagName(loc)}); | 2382 | if (dst_val == .none) return; |
| | 2383 | |
| | 2384 | if (!dst_val.isMutable()) { |
| | 2385 | return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)}); |
| 2421 | } | 2386 | } |
| 2422 | | 2387 | |
| 2423 | switch (loc) { | 2388 | switch (dst_val) { |
| 2424 | .none => return, | 2389 | .register => |reg| return self.genSetReg(ty, reg, src_val), |
| 2425 | .register => |reg| return self.genSetReg(ty, reg, val), | 2390 | .stack_offset => |off| return self.genSetStack(ty, off, src_val), |
| 2426 | .stack_offset => |off| return self.genSetStack(ty, off, val), | 2391 | .memory => |addr| return self.genSetMem(ty, addr, src_val), |
| 2427 | else => return self.fail("TODO: setRegOrMem {s}", .{@tagName(loc)}), | 2392 | else => return self.fail("TODO: setValue {s}", .{@tagName(dst_val)}), |
| 2428 | } | 2393 | } |
| 2429 | } | 2394 | } |
| 2430 | | 2395 | |
| 2431 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 2396 | /// Sets the value of `src_val` into stack memory at `stack_offset`. |
| | 2397 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) InnerError!void { |
| 2432 | const mod = self.bin_file.comp.module.?; | 2398 | const mod = self.bin_file.comp.module.?; |
| 2433 | const abi_size: u32 = @intCast(ty.abiSize(mod)); | 2399 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 2434 | | 2400 | |
| 2435 | switch (mcv) { | 2401 | switch (src_val) { |
| 2436 | .none => return, | 2402 | .none => return, |
| 2437 | .dead => unreachable, | 2403 | .dead => unreachable, |
| 2438 | .immediate => { | 2404 | .immediate => { |
| 2439 | const reg = try self.copyToTmpRegister(ty, mcv); | 2405 | const reg = try self.copyToTmpRegister(ty, src_val); |
| 2440 | return self.genSetStack(ty, stack_offset, .{ .register = reg }); | 2406 | return self.genSetStack(ty, stack_offset, .{ .register = reg }); |
| 2441 | }, | 2407 | }, |
| 2442 | .register => |reg| { | 2408 | .register => |reg| { |
| ... | @@ -2456,8 +2422,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2456,8 +2422,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2456 | .tag = tag, | 2422 | .tag = tag, |
| 2457 | .data = .{ .i_type = .{ | 2423 | .data = .{ .i_type = .{ |
| 2458 | .rd = reg, | 2424 | .rd = reg, |
| 2459 | .rs1 = .sp, | 2425 | .rs1 = .s0, |
| 2460 | .imm12 = @intCast(stack_offset), | 2426 | .imm12 = math.cast(i12, stack_offset) orelse { |
| | 2427 | return self.fail("TODO: genSetStack bigger stack values", .{}); |
| | 2428 | }, |
| 2461 | } }, | 2429 | } }, |
| 2462 | }); | 2430 | }); |
| 2463 | }, | 2431 | }, |
| ... | @@ -2466,7 +2434,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2466,7 +2434,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2466 | }, | 2434 | }, |
| 2467 | .stack_offset, .load_symbol => { | 2435 | .stack_offset, .load_symbol => { |
| 2468 | if (abi_size <= 8) { | 2436 | if (abi_size <= 8) { |
| 2469 | const reg = try self.copyToTmpRegister(ty, mcv); | 2437 | const reg = try self.copyToTmpRegister(ty, src_val); |
| 2470 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 2438 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 2471 | } | 2439 | } |
| 2472 | | 2440 | |
| ... | @@ -2485,7 +2453,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2485,7 +2453,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2485 | const count_reg = regs[3]; | 2453 | const count_reg = regs[3]; |
| 2486 | const tmp_reg = regs[4]; | 2454 | const tmp_reg = regs[4]; |
| 2487 | | 2455 | |
| 2488 | switch (mcv) { | 2456 | switch (src_val) { |
| 2489 | .stack_offset => |offset| { | 2457 | .stack_offset => |offset| { |
| 2490 | if (offset == stack_offset) return; | 2458 | if (offset == stack_offset) return; |
| 2491 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); | 2459 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); |
| ... | @@ -2511,7 +2479,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2511,7 +2479,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2511 | }, | 2479 | }, |
| 2512 | }); | 2480 | }); |
| 2513 | }, | 2481 | }, |
| 2514 | else => return self.fail("TODO: genSetStack unreachable {s}", .{@tagName(mcv)}), | 2482 | else => return self.fail("TODO: genSetStack unreachable {s}", .{@tagName(src_val)}), |
| 2515 | } | 2483 | } |
| 2516 | | 2484 | |
| 2517 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); | 2485 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); |
| ... | @@ -2520,10 +2488,20 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2520,10 +2488,20 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2520 | // memcpy(src, dst, len) | 2488 | // memcpy(src, dst, len) |
| 2521 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); | 2489 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); |
| 2522 | }, | 2490 | }, |
| 2523 | else => return self.fail("TODO: genSetStack {s}", .{@tagName(mcv)}), | 2491 | else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}), |
| 2524 | } | 2492 | } |
| 2525 | } | 2493 | } |
| 2526 | | 2494 | |
| | 2495 | fn genSetMem(self: *Self, ty: Type, addr: u64, src_val: MCValue) InnerError!void { |
| | 2496 | const mod = self.bin_file.comp.module.?; |
| | 2497 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| | 2498 | _ = abi_size; |
| | 2499 | _ = addr; |
| | 2500 | _ = src_val; |
| | 2501 | |
| | 2502 | return self.fail("TODO: genSetMem", .{}); |
| | 2503 | } |
| | 2504 | |
| 2527 | fn genInlineMemcpy( | 2505 | fn genInlineMemcpy( |
| 2528 | self: *Self, | 2506 | self: *Self, |
| 2529 | src: Register, | 2507 | src: Register, |
| ... | @@ -2541,11 +2519,12 @@ fn genInlineMemcpy( | ... | @@ -2541,11 +2519,12 @@ fn genInlineMemcpy( |
| 2541 | return self.fail("TODO: genInlineMemcpy", .{}); | 2519 | return self.fail("TODO: genInlineMemcpy", .{}); |
| 2542 | } | 2520 | } |
| 2543 | | 2521 | |
| 2544 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 2522 | /// Sets the value of `src_val` into `reg`. Assumes you have a lock on it. |
| | 2523 | fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!void { |
| 2545 | const mod = self.bin_file.comp.module.?; | 2524 | const mod = self.bin_file.comp.module.?; |
| 2546 | const abi_size: u32 = @intCast(ty.abiSize(mod)); | 2525 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 2547 | | 2526 | |
| 2548 | switch (mcv) { | 2527 | switch (src_val) { |
| 2549 | .dead => unreachable, | 2528 | .dead => unreachable, |
| 2550 | .ptr_stack_offset => return self.fail("TODO genSetReg ptr_stack_offset", .{}), | 2529 | .ptr_stack_offset => return self.fail("TODO genSetReg ptr_stack_offset", .{}), |
| 2551 | .unreach, .none => return, // Nothing to do. | 2530 | .unreach, .none => return, // Nothing to do. |
| ... | @@ -2634,8 +2613,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -2634,8 +2613,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2634 | .tag = tag, | 2613 | .tag = tag, |
| 2635 | .data = .{ .i_type = .{ | 2614 | .data = .{ .i_type = .{ |
| 2636 | .rd = reg, | 2615 | .rd = reg, |
| 2637 | .rs1 = .sp, | 2616 | .rs1 = .s0, |
| 2638 | .imm12 = @intCast(off), | 2617 | .imm12 = math.cast(i12, off) orelse { |
| | 2618 | return self.fail("TODO: genSetReg support larger stack sizes", .{}); |
| | 2619 | }, |
| 2639 | } }, | 2620 | } }, |
| 2640 | }); | 2621 | }); |
| 2641 | }, | 2622 | }, |
| ... | @@ -2685,7 +2666,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2685,7 +2666,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2685 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | 2666 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 2686 | | 2667 | |
| 2687 | const dest = try self.allocRegOrMem(inst, true); | 2668 | const dest = try self.allocRegOrMem(inst, true); |
| 2688 | try self.setRegOrMem(self.typeOfIndex(inst), dest, operand); | 2669 | try self.setValue(self.typeOfIndex(inst), dest, operand); |
| 2689 | break :result dest; | 2670 | break :result dest; |
| 2690 | }; | 2671 | }; |
| 2691 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2672 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | @@ -2912,7 +2893,6 @@ const CallMCValues = struct { | ... | @@ -2912,7 +2893,6 @@ const CallMCValues = struct { |
| 2912 | /// Caller must call `CallMCValues.deinit`. | 2893 | /// Caller must call `CallMCValues.deinit`. |
| 2913 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | 2894 | fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2914 | const mod = self.bin_file.comp.module.?; | 2895 | const mod = self.bin_file.comp.module.?; |
| 2915 | const ip = &mod.intern_pool; | | |
| 2916 | const fn_info = mod.typeToFunc(fn_ty).?; | 2896 | const fn_info = mod.typeToFunc(fn_ty).?; |
| 2917 | const cc = fn_info.cc; | 2897 | const cc = fn_info.cc; |
| 2918 | var result: CallMCValues = .{ | 2898 | var result: CallMCValues = .{ |
| ... | @@ -2935,21 +2915,20 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -2935,21 +2915,20 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 2935 | return result; | 2915 | return result; |
| 2936 | }, | 2916 | }, |
| 2937 | .Unspecified, .C => { | 2917 | .Unspecified, .C => { |
| 2938 | // LP64D ABI | 2918 | if (result.args.len > 8) { |
| 2939 | // | 2919 | return self.fail("TODO: support more than 8 function args", .{}); |
| 2940 | // TODO make this generic with other ABIs, in particular | 2920 | } |
| 2941 | // with different hardware floating-point calling | | |
| 2942 | // conventions | | |
| 2943 | var stack_offset: u32 = 0; | | |
| 2944 | | | |
| 2945 | for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| { | | |
| 2946 | const param_type = Type.fromInterned(ty); | | |
| 2947 | const param_size: u32 = @intCast(param_type.abiSize(mod)); | | |
| 2948 | | 2921 | |
| 2949 | result_arg.* = .{ .stack_offset = stack_offset }; | 2922 | for (0..result.args.len) |i| { |
| 2950 | stack_offset += param_size; | 2923 | const arg_reg = try self.register_manager.allocReg(null, fa); |
| | 2924 | result.args[i] = .{ .register = arg_reg }; |
| 2951 | } | 2925 | } |
| 2952 | | 2926 | |
| | 2927 | // stack_offset = num s registers spilled + local var space |
| | 2928 | var stack_offset: u32 = 0; |
| | 2929 | _ = &stack_offset; |
| | 2930 | // TODO: spill used s registers here |
| | 2931 | |
| 2953 | result.stack_byte_count = stack_offset; | 2932 | result.stack_byte_count = stack_offset; |
| 2954 | result.stack_align = .@"16"; | 2933 | result.stack_align = .@"16"; |
| 2955 | }, | 2934 | }, |