This is strange bug - because this seems to be caused by 2 bugs at once. One problem is here:
void CompilerContext::allocGPVar(VarData* vdata, uint32_t regMask, uint32_t vflags) ASMJIT_NOTHROW
...
// If regMask contains restricted registers which may be used then everything
// is handled in this block.
if (regMask != Util::maskUpToIndex(REG_NUM_GP))
{
// Try to find unallocated register first.
mask = regMask & ~_state.usedGP;
if (mask != 0)
{
idx = Util::findFirstBit(
(nonPreservedFirst && (mask & ~preservedGP) != 0) ? (mask & ~preservedGP) : mask);
ASMJIT_ASSERT(idx != INVALID_VALUE);
}
// Then find the allocated and later spill.
else
{
idx = Util::findFirstBit(regMask & _state.usedGP);
ASMJIT_ASSERT(idx != INVALID_VALUE);
// Spill register we need.
ASMJIT_ASSERT(spillCandidate->workOffset != _currentOffset); <-- ADDED LINE
// Jump to spill part of allocation.
goto L_Spill;
}
}
This branch of code seems to miss check whether spilled variable is needed in the current instruction. I have patched that - it will scan for register where spillCandidate->workOffset != _currentOffset instead of using just Util::findFirstBit(regMask & _state.usedGP). Now my code works OK.
But there seems to be some other bug in play here: SETcc instruction has just one operand, so how it can happen that during allocation of this operand, there is some other variable marked as used by this instruction (workOffset==currentOffest)?
As this second bug is not causing any crashes, I will leave it as it is for now. But if you have some idea how this can happen, please let me know ;-)
Palo