Added a support for indirect jumps within a function (Compiler) (#286)

This commit is contained in:
kobalicek
2020-05-09 00:14:52 +02:00
parent 80645e66a8
commit e78bba83da
51 changed files with 1590 additions and 661 deletions
+59 -9
View File
@@ -370,6 +370,21 @@ Cleared:
return kErrorOk;
}
Error RALocalAllocator::spillGpScratchRegsBeforeEntry(uint32_t scratchRegs) noexcept {
uint32_t group = BaseReg::kGroupGp;
Support::BitWordIterator<uint32_t> it(scratchRegs);
while (it.hasNext()) {
uint32_t physId = it.next();
if (_curAssignment.isPhysAssigned(group, physId)) {
uint32_t workId = _curAssignment.physToWorkId(group, physId);
ASMJIT_PROPAGATE(onSpillReg(group, workId, physId));
}
}
return kErrorOk;
}
// ============================================================================
// [asmjit::RALocalAllocator - Allocation]
// ============================================================================
@@ -847,7 +862,7 @@ Error RALocalAllocator::spillAfterAllocation(InstNode* node) noexcept {
Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* cont) noexcept {
// TODO: This should be used to make the branch allocation better.
ASMJIT_UNUSED(cont);
DebugUtils::unused(cont);
// The cursor must point to the previous instruction for a possible instruction insertion.
_cc->_setCursor(node->prev());
@@ -863,6 +878,7 @@ Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* co
}
ASMJIT_PROPAGATE(allocInst(node));
ASMJIT_PROPAGATE(spillRegsBeforeEntry(target));
if (target->hasEntryAssignment()) {
BaseNode* injectionPoint = _pass->extraBlock()->prev();
@@ -879,7 +895,7 @@ Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* co
BaseNode* curCursor = _cc->cursor();
if (curCursor != injectionPoint) {
// Additional instructions emitted to switch from the current state to
// the `target`s state. This means that we have to move these instructions
// the `target` state. This means that we have to move these instructions
// into an independent code block and patch the jump location.
Operand& targetOp(node->opType(node->opCount() - 1));
if (ASMJIT_UNLIKELY(!targetOp.isLabel()))
@@ -911,13 +927,50 @@ Error RALocalAllocator::allocBranch(InstNode* node, RABlock* target, RABlock* co
return kErrorOk;
}
Error RALocalAllocator::allocJumpTable(InstNode* node, const RABlocks& targets, RABlock* cont) noexcept {
if (targets.empty())
return DebugUtils::errored(kErrorInvalidState);
if (targets.size() == 1)
return allocBranch(node, targets[0], cont);
// The cursor must point to the previous instruction for a possible instruction insertion.
_cc->_setCursor(node->prev());
// All `targets` should have the same sharedAssignmentId, we just read the first.
RABlock* anyTarget = targets[0];
if (!anyTarget->hasSharedAssignmentId())
return DebugUtils::errored(kErrorInvalidState);
RASharedAssignment& sharedAssignment = _pass->_sharedAssignments[anyTarget->sharedAssignmentId()];
ASMJIT_PROPAGATE(allocInst(node));
if (!sharedAssignment.empty()) {
ASMJIT_PROPAGATE(switchToAssignment(
sharedAssignment.physToWorkMap(),
sharedAssignment.workToPhysMap(),
sharedAssignment.liveIn(),
true, // Read-only.
false // Try-mode.
));
}
ASMJIT_PROPAGATE(spillRegsBeforeEntry(anyTarget));
if (sharedAssignment.empty()) {
ASMJIT_PROPAGATE(_pass->setBlockEntryAssignment(anyTarget, block(), _curAssignment));
}
return kErrorOk;
}
// ============================================================================
// [asmjit::RALocalAllocator - Decision Making]
// ============================================================================
uint32_t RALocalAllocator::decideOnAssignment(uint32_t group, uint32_t workId, uint32_t physId, uint32_t allocableRegs) const noexcept {
ASMJIT_UNUSED(group);
ASMJIT_UNUSED(physId);
DebugUtils::unused(group, physId);
ASMJIT_ASSERT(allocableRegs != 0);
RAWorkReg* workReg = workRegById(workId);
@@ -945,10 +998,7 @@ uint32_t RALocalAllocator::decideOnUnassignment(uint32_t group, uint32_t workId,
ASMJIT_ASSERT(allocableRegs != 0);
// TODO:
ASMJIT_UNUSED(allocableRegs);
ASMJIT_UNUSED(group);
ASMJIT_UNUSED(workId);
ASMJIT_UNUSED(physId);
DebugUtils::unused(allocableRegs, group, workId, physId);
// if (!_curAssignment.isPhysDirty(group, physId)) {
// }
@@ -959,7 +1009,7 @@ uint32_t RALocalAllocator::decideOnUnassignment(uint32_t group, uint32_t workId,
uint32_t RALocalAllocator::decideOnSpillFor(uint32_t group, uint32_t workId, uint32_t spillableRegs, uint32_t* spillWorkId) const noexcept {
// May be used in the future to decide which register would be best to spill so `workId` can be assigned.
ASMJIT_UNUSED(workId);
DebugUtils::unused(workId);
ASMJIT_ASSERT(spillableRegs != 0);
Support::BitWordIterator<uint32_t> it(spillableRegs);