mirror of
https://github.com/asmjit/asmjit
synced 2026-06-08 13:13:30 +00:00
Added a support for indirect jumps within a function (Compiler) (#286)
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user