- Implemented intersectStates()

- Minor changes in logging (logger now prints liveness analysis related to labels)
- Removed some TODOs.
This commit is contained in:
kobalicek
2015-02-14 15:33:38 +01:00
parent f289d83e5e
commit a587fc94d0
5 changed files with 284 additions and 181 deletions

View File

@@ -199,8 +199,17 @@ Error Assembler::bind(const Label& label) {
return setError(kErrorLabelAlreadyBound);
#if !defined(ASMJIT_DISABLE_LOGGER)
if (_logger)
_logger->logFormat(kLoggerStyleLabel, "L%u:\n", index);
if (_logger) {
StringBuilderT<256> sb;
sb.setFormat("L%u:", index);
size_t binSize = 0;
if ((_logger->getOptions() & (1 << kLoggerOptionBinaryForm)) == 0)
binSize = kInvalidIndex;
LogUtil::formatLine(sb, NULL, binSize, 0, 0, _comment);
_logger->logString(kLoggerStyleLabel, sb.getData(), sb.getLength());
}
#endif // !ASMJIT_DISABLE_LOGGER
Error error = kErrorOk;
@@ -260,6 +269,7 @@ Error Assembler::bind(const Label& label) {
if (error != kErrorOk)
return setError(error);
_comment = NULL;
return error;
}

View File

@@ -24,6 +24,60 @@
namespace asmjit {
// ============================================================================
// [asmjit::LogUtil]
// ============================================================================
bool LogUtil::formatLine(StringBuilder& sb, const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment) {
size_t currentLen = sb.getLength();
size_t commentLen = comment ? StringUtil::nlen(comment, kMaxCommentLength) : 0;
ASMJIT_ASSERT(binLen >= dispLen);
if ((binLen != 0 && binLen != kInvalidIndex) || commentLen) {
size_t align = kMaxInstLength;
char sep = ';';
for (size_t i = (binLen == kInvalidIndex); i < 2; i++) {
size_t begin = sb.getLength();
// Append align.
if (currentLen < align) {
if (!sb.appendChars(' ', align - currentLen))
return false;
}
// Append separator.
if (sep) {
if (!(sb.appendChar(sep) & sb.appendChar(' ')))
return false;
}
// Append binary data or comment.
if (i == 0) {
if (!sb.appendHex(binData, binLen - dispLen - imLen))
return false;
if (!sb.appendChars('.', dispLen * 2))
return false;
if (!sb.appendHex(binData + binLen - imLen, imLen))
return false;
if (commentLen == 0)
break;
}
else {
if (!sb.appendString(comment, commentLen))
return false;
}
currentLen += sb.getLength() - begin;
align += kMaxBinaryLength;
sep = '|';
}
}
return sb.appendChar('\n');
}
// ============================================================================
// [asmjit::Logger - Construction / Destruction]
// ============================================================================

View File

@@ -58,6 +58,23 @@ ASMJIT_ENUM(LoggerStyle) {
kLoggerStyleCount = 5
};
// ============================================================================
// [asmjit::LogUtil]
// ============================================================================
// Only used by asmjit internals, not available to consumers.
#if defined(ASMJIT_EXPORTS)
struct LogUtil {
enum {
kMaxCommentLength = 80,
kMaxInstLength = 36,
kMaxBinaryLength = 22
};
static bool formatLine(StringBuilder& sb, const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment);
};
#endif // ASMJIT_EXPORTS
// ============================================================================
// [asmjit::Logger]
// ============================================================================

View File

@@ -29,7 +29,6 @@ namespace asmjit {
// [Constants]
// ============================================================================
enum { kMaxCommentLength = 80 };
enum { kX86RexNoRexMask = kX86InstOptionRex | _kX86InstOptionNoRex };
//! \internal
@@ -912,56 +911,6 @@ static bool X86Assembler_dumpInstruction(StringBuilder& sb,
return true;
}
static bool X86Assembler_dumpComment(StringBuilder& sb, size_t len, const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment) {
size_t currentLen = len;
size_t commentLen = comment ? StringUtil::nlen(comment, kMaxCommentLength) : 0;
ASMJIT_ASSERT(binLen >= dispLen);
if (binLen || commentLen) {
size_t align = 36;
char sep = ';';
for (size_t i = (binLen == 0); i < 2; i++) {
size_t begin = sb.getLength();
// Append align.
if (currentLen < align) {
if (!sb.appendChars(' ', align - currentLen))
return false;
}
// Append separator.
if (sep) {
if (!(sb.appendChar(sep) & sb.appendChar(' ')))
return false;
}
// Append binary data or comment.
if (i == 0) {
if (!sb.appendHex(binData, binLen - dispLen - imLen))
return false;
if (!sb.appendChars('.', dispLen * 2))
return false;
if (!sb.appendHex(binData + binLen - imLen, imLen))
return false;
if (commentLen == 0)
break;
}
else {
if (!sb.appendString(comment, commentLen))
return false;
}
currentLen += sb.getLength() - begin;
align += 22;
sep = '|';
}
}
return sb.appendChar('\n');
}
#endif // !ASMJIT_DISABLE_LOGGER
// ============================================================================
@@ -4186,9 +4135,9 @@ _EmitDone:
X86Assembler_dumpInstruction(sb, Arch, code, options, o0, o1, o2, o3, loggerOptions);
if ((loggerOptions & (1 << kLoggerOptionBinaryForm)) != 0)
X86Assembler_dumpComment(sb, sb.getLength(), self->_cursor, (intptr_t)(cursor - self->_cursor), dispSize, imLen, self->_comment);
LogUtil::formatLine(sb, self->_cursor, (intptr_t)(cursor - self->_cursor), dispSize, imLen, self->_comment);
else
X86Assembler_dumpComment(sb, sb.getLength(), NULL, 0, 0, 0, self->_comment);
LogUtil::formatLine(sb, NULL, kInvalidIndex, 0, 0, self->_comment);
# if defined(ASMJIT_DEBUG)
if (self->_logger)

View File

@@ -648,73 +648,64 @@ void X86Context::emitLoad(VarData* vd, uint32_t regIndex, const char* reason) {
X86Mem m = getVarMem(vd);
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
case kVarTypeInt8:
case kVarTypeUInt8:
node = compiler->emit(kX86InstIdMov, x86::gpb_lo(regIndex), m);
if (comment) goto _Comment;
break;
case kVarTypeInt16:
case kVarTypeUInt16:
node = compiler->emit(kX86InstIdMov, x86::gpw(regIndex), m);
if (comment) goto _Comment;
break;
case kVarTypeInt32:
case kVarTypeUInt32:
node = compiler->emit(kX86InstIdMov, x86::gpd(regIndex), m);
if (comment) goto _Comment;
break;
#if defined(ASMJIT_BUILD_X64)
case kVarTypeInt64:
case kVarTypeUInt64:
ASMJIT_ASSERT(_compiler->getArch() != kArchX86);
node = compiler->emit(kX86InstIdMov, x86::gpq(regIndex), m);
if (comment) goto _Comment;
break;
#endif // ASMJIT_BUILD_X64
case kVarTypeFp32:
case kVarTypeFp64:
// TODO: [COMPILER] FPU.
// Compiler doesn't manage FPU stack.
ASMJIT_ASSERT(!"Reached");
break;
case kX86VarTypeMm:
node = compiler->emit(kX86InstIdMovq, x86::mm(regIndex), m);
if (comment) goto _Comment;
break;
case kX86VarTypeXmm:
node = compiler->emit(kX86InstIdMovdqa, x86::xmm(regIndex), m);
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSs:
node = compiler->emit(kX86InstIdMovss, x86::xmm(regIndex), m);
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSd:
node = compiler->emit(kX86InstIdMovsd, x86::xmm(regIndex), m);
if (comment) goto _Comment;
break;
case kX86VarTypeXmmPs:
node = compiler->emit(kX86InstIdMovaps, x86::xmm(regIndex), m);
if (comment) goto _Comment;
break;
case kX86VarTypeXmmPd:
node = compiler->emit(kX86InstIdMovapd, x86::xmm(regIndex), m);
if (comment) goto _Comment;
break;
}
return;
_Comment:
if (!_emitComments)
return;
node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName()));
}
@@ -729,73 +720,63 @@ void X86Context::emitSave(VarData* vd, uint32_t regIndex, const char* reason) {
X86Mem m = getVarMem(vd);
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
case kVarTypeInt8:
case kVarTypeUInt8:
node = compiler->emit(kX86InstIdMov, m, x86::gpb_lo(regIndex));
if (comment) goto _Comment;
break;
case kVarTypeInt16:
case kVarTypeUInt16:
node = compiler->emit(kX86InstIdMov, m, x86::gpw(regIndex));
if (comment) goto _Comment;
break;
case kVarTypeInt32:
case kVarTypeUInt32:
node = compiler->emit(kX86InstIdMov, m, x86::gpd(regIndex));
if (comment) goto _Comment;
break;
#if defined(ASMJIT_BUILD_X64)
case kVarTypeInt64:
case kVarTypeUInt64:
node = compiler->emit(kX86InstIdMov, m, x86::gpq(regIndex));
if (comment) goto _Comment;
break;
#endif // ASMJIT_BUILD_X64
case kVarTypeFp32:
case kVarTypeFp64:
// TODO: [COMPILER] FPU.
// Compiler doesn't manage FPU stack.
ASMJIT_ASSERT(!"Reached");
break;
case kX86VarTypeMm:
node = compiler->emit(kX86InstIdMovq, m, x86::mm(regIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmm:
node = compiler->emit(kX86InstIdMovdqa, m, x86::xmm(regIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSs:
node = compiler->emit(kX86InstIdMovss, m, x86::xmm(regIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSd:
node = compiler->emit(kX86InstIdMovsd, m, x86::xmm(regIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmPs:
node = compiler->emit(kX86InstIdMovaps, m, x86::xmm(regIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmPd:
node = compiler->emit(kX86InstIdMovapd, m, x86::xmm(regIndex));
if (comment) goto _Comment;
break;
}
return;
_Comment:
if (!_emitComments)
return;
node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName()));
}
@@ -808,9 +789,7 @@ void X86Context::emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegInde
ASMJIT_ASSERT(fromRegIndex != kInvalidReg);
X86Compiler* compiler = getCompiler();
Node* node = NULL;
bool comment = _emitComments;
switch (vd->getType()) {
case kVarTypeInt8:
@@ -820,51 +799,45 @@ void X86Context::emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegInde
case kVarTypeInt32:
case kVarTypeUInt32:
node = compiler->emit(kX86InstIdMov, x86::gpd(toRegIndex), x86::gpd(fromRegIndex));
if (comment) goto _Comment;
break;
#if defined(ASMJIT_BUILD_X64)
case kVarTypeInt64:
case kVarTypeUInt64:
node = compiler->emit(kX86InstIdMov, x86::gpq(toRegIndex), x86::gpq(fromRegIndex));
if (comment) goto _Comment;
break;
#endif // ASMJIT_BUILD_X64
case kVarTypeFp32:
case kVarTypeFp64:
// TODO: [COMPILER] FPU.
// Compiler doesn't manage FPU stack.
ASMJIT_ASSERT(!"Reached");
break;
case kX86VarTypeMm:
node = compiler->emit(kX86InstIdMovq, x86::mm(toRegIndex), x86::mm(fromRegIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmm:
node = compiler->emit(kX86InstIdMovaps, x86::xmm(toRegIndex), x86::xmm(fromRegIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSs:
node = compiler->emit(kX86InstIdMovss, x86::xmm(toRegIndex), x86::xmm(fromRegIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmSd:
node = compiler->emit(kX86InstIdMovsd, x86::xmm(toRegIndex), x86::xmm(fromRegIndex));
if (comment) goto _Comment;
break;
case kX86VarTypeXmmPs:
case kX86VarTypeXmmPd:
node = compiler->emit(kX86InstIdMovaps, x86::xmm(toRegIndex), x86::xmm(fromRegIndex));
if (comment) goto _Comment;
break;
}
return;
_Comment:
if (!_emitComments)
return;
node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName()));
}
@@ -877,25 +850,22 @@ void X86Context::emitSwapGp(VarData* aVd, VarData* bVd, uint32_t aIndex, uint32_
ASMJIT_ASSERT(bIndex != kInvalidReg);
X86Compiler* compiler = getCompiler();
Node* node = NULL;
bool comment = _emitComments;
#if defined(ASMJIT_BUILD_X64)
uint32_t vType = IntUtil::iMax(aVd->getType(), bVd->getType());
if (vType == kVarTypeInt64 || vType == kVarTypeUInt64) {
node = compiler->emit(kX86InstIdXchg, x86::gpq(aIndex), x86::gpq(bIndex));
if (comment) goto _Comment;
return;
}
else {
#endif // ASMJIT_BUILD_X64
node = compiler->emit(kX86InstIdXchg, x86::gpd(aIndex), x86::gpd(bIndex));
#if defined(ASMJIT_BUILD_X64)
}
#endif // ASMJIT_BUILD_X64
node = compiler->emit(kX86InstIdXchg, x86::gpd(aIndex), x86::gpd(bIndex));
if (comment) goto _Comment;
if (!_emitComments)
return;
_Comment:
node->setComment(compiler->_stringZone.sformat("[%s] %s, %s", reason, aVd->getName(), bVd->getName()));
}
@@ -967,7 +937,7 @@ void X86Context::emitConvertVarToVar(uint32_t dstType, uint32_t dstIndex, uint32
}
if (IntUtil::inInterval<uint32_t>(srcType, _kVarTypeIntStart, _kVarTypeIntEnd)) {
// TODO:
// TODO: [COMPILER] Variable conversion not supported.
ASMJIT_ASSERT(!"Reached");
}
break;
@@ -986,7 +956,7 @@ void X86Context::emitConvertVarToVar(uint32_t dstType, uint32_t dstIndex, uint32
}
if (IntUtil::inInterval<uint32_t>(srcType, _kVarTypeIntStart, _kVarTypeIntEnd)) {
// TODO:
// TODO: [COMPILER] Variable conversion not supported.
ASMJIT_ASSERT(!"Reached");
}
break;
@@ -1427,7 +1397,8 @@ _Move32:
case kVarTypeFp32:
case kVarTypeFp64:
// TODO: [COMPILER] EmitMoveImmToReg.
// Compiler doesn't manage FPU stack.
ASMJIT_ASSERT(!"Reached");
break;
case kX86VarTypeMm:
@@ -1595,28 +1566,25 @@ template<int C>
static ASMJIT_INLINE void X86Context_switchStateVars(X86Context* self, X86VarState* src) {
X86VarState* dst = self->getState();
VarData** dstVars = dst->getListByClass(C);
VarData** srcVars = src->getListByClass(C);
uint32_t regIndex;
uint32_t regMask;
uint32_t regCount = self->_regCount.get(C);
VarData** dVars = dst->getListByClass(C);
VarData** sVars = src->getListByClass(C);
X86StateCell* cells = src->_cells;
uint32_t regCount = self->_regCount.get(C);
bool didWork;
do {
didWork = false;
for (regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* dVd = dstVars[regIndex];
VarData* sVd = srcVars[regIndex];
for (uint32_t regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* dVd = dVars[regIndex];
VarData* sVd = sVars[regIndex];
if (dVd == sVd)
continue;
if (dVd != NULL) {
X86StateCell& cell = cells[dVd->getContextId()];
const X86StateCell& cell = cells[dVd->getContextId()];
if (cell.getState() != kVarStateReg) {
if (cell.getState() == kVarStateMem)
@@ -1643,8 +1611,9 @@ _MoveOrLoad:
continue;
}
if (dVd != NULL && sVd == NULL) {
X86StateCell& cell = cells[dVd->getContextId()];
if (dVd != NULL) {
const X86StateCell& cell = cells[dVd->getContextId()];
if (sVd == NULL) {
if (cell.getState() == kVarStateReg)
continue;
@@ -1657,8 +1626,6 @@ _MoveOrLoad:
continue;
}
else {
X86StateCell& cell = cells[dVd->getContextId()];
if (cell.getState() == kVarStateReg) {
if (dVd->getRegIndex() != kInvalidReg && sVd->getRegIndex() != kInvalidReg) {
if (C == kX86RegClassGp) {
@@ -1685,24 +1652,25 @@ _MoveOrLoad:
goto _MoveOrLoad;
}
}
}
} while (didWork);
uint32_t dstModified = dst->_modified.get(C);
uint32_t srcModified = src->_modified.get(C);
uint32_t dModified = dst->_modified.get(C);
uint32_t sModified = src->_modified.get(C);
if (dstModified != srcModified) {
for (regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* vd = dstVars[regIndex];
if (dModified != sModified) {
for (uint32_t regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* vd = dVars[regIndex];
if (vd == NULL)
continue;
if ((dstModified & regMask) && !(srcModified & regMask)) {
if ((dModified & regMask) && !(sModified & regMask)) {
self->save<C>(vd);
continue;
}
if (!(dstModified & regMask) && (srcModified & regMask)) {
if (!(dModified & regMask) && (sModified & regMask)) {
self->modify<C>(vd);
continue;
}
@@ -1732,9 +1700,9 @@ void X86Context::switchState(VarState* src_) {
X86StateCell* cells = src->_cells;
for (uint32_t i = 0; i < vdCount; i++) {
VarData* vd = static_cast<VarData*>(vdArray[i]);
X86StateCell& cell = cells[i];
const X86StateCell& cell = cells[i];
uint32_t vState = cell.getState();
if (vState != kVarStateReg) {
vd->setState(vState);
vd->setModified(false);
@@ -1748,11 +1716,125 @@ void X86Context::switchState(VarState* src_) {
// [asmjit::X86Context - State - Intersect]
// ============================================================================
void X86Context::intersectStates(VarState* a_, VarState* b_) {
X86VarState* aState = static_cast<X86VarState*>(a_);
X86VarState* bState = static_cast<X86VarState*>(b_);
// The algorithm is actually not so smart, but tries to find an intersection od
// `a` and `b` and tries to move/alloc a variable into that location if it's
// possible. It also finds out which variables will be spilled/unused by `a`
// and `b` and performs that action here. It may improve the switch state code
// in certain cases, but doesn't necessarily do the best job possible.
template<int C>
static ASMJIT_INLINE void X86Context_intersectStateVars(X86Context* self, X86VarState* a, X86VarState* b) {
X86VarState* dst = self->getState();
VarData** dVars = dst->getListByClass(C);
VarData** aVars = a->getListByClass(C);
VarData** bVars = b->getListByClass(C);
X86StateCell* aCells = a->_cells;
X86StateCell* bCells = b->_cells;
uint32_t regCount = self->_regCount.get(C);
bool didWork;
// Similar to `switchStateVars()`, we iterate over and over until there is
// no work to be done.
do {
didWork = false;
for (uint32_t regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* dVd = dVars[regIndex];
VarData* aVd = aVars[regIndex];
VarData* bVd = bVars[regIndex];
if (dVd == aVd)
continue;
if (dVd != NULL) {
const X86StateCell& aCell = aCells[dVd->getContextId()];
const X86StateCell& bCell = bCells[dVd->getContextId()];
if (aCell.getState() != kVarStateReg && bCell.getState() != kVarStateReg) {
if (aCell.getState() == kVarStateMem || bCell.getState() == kVarStateMem)
self->spill<C>(dVd);
else
self->unuse<C>(dVd);
dVd = NULL;
didWork = true;
if (aVd == NULL)
continue;
}
}
if (dVd == NULL && aVd != NULL) {
if (aVd->getRegIndex() != kInvalidReg)
self->move<C>(aVd, regIndex);
else
self->load<C>(aVd, regIndex);
didWork = true;
continue;
}
if (dVd != NULL) {
const X86StateCell& aCell = aCells[dVd->getContextId()];
const X86StateCell& bCell = bCells[dVd->getContextId()];
if (aVd == NULL) {
if (aCell.getState() == kVarStateReg || bCell.getState() == kVarStateReg)
continue;
if (aCell.getState() == kVarStateMem || bCell.getState() == kVarStateMem)
self->spill<C>(dVd);
else
self->unuse<C>(dVd);
didWork = true;
continue;
}
else if (C == kX86RegClassGp) {
if (aCell.getState() == kVarStateReg) {
if (dVd->getRegIndex() != kInvalidReg && aVd->getRegIndex() != kInvalidReg) {
self->swapGp(dVd, aVd);
didWork = true;
continue;
}
}
}
}
}
} while (didWork);
uint32_t dModified = dst->_modified.get(C);
uint32_t aModified = a->_modified.get(C);
if (dModified != aModified) {
for (uint32_t regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) {
VarData* vd = dVars[regIndex];
if (vd == NULL)
continue;
const X86StateCell& aCell = aCells[vd->getContextId()];
if ((dModified & regMask) && !(aModified & regMask) && aCell.getState() == kVarStateReg)
self->save<C>(vd);
}
}
}
void X86Context::intersectStates(VarState* a_, VarState* b_) {
X86VarState* a = static_cast<X86VarState*>(a_);
X86VarState* b = static_cast<X86VarState*>(b_);
ASMJIT_ASSERT(a != NULL);
ASMJIT_ASSERT(b != NULL);
X86Context_intersectStateVars<kX86RegClassGp >(this, a, b);
X86Context_intersectStateVars<kX86RegClassMm >(this, a, b);
X86Context_intersectStateVars<kX86RegClassXyz>(this, a, b);
// TODO: [COMPILER] Intersect states.
ASMJIT_X86_CHECK_STATE
}
@@ -4414,24 +4496,18 @@ ASMJIT_INLINE void X86CallAlloc::ret() {
uint32_t vf = _x86VarInfo[vd->getType()].getDesc();
uint32_t regIndex = ret.getRegIndex();
// TODO: Is it necessary to check for kInvalidReg when unusing if it's
// checked by unuse<> as well?
switch (vd->getClass()) {
case kX86RegClassGp:
ASMJIT_ASSERT(x86VarTypeToClass(ret.getVarType()) == vd->getClass());
if (vd->getRegIndex() != kInvalidReg)
_context->unuse<kX86RegClassGp>(vd);
_context->attach<kX86RegClassGp>(vd, regIndex, true);
break;
case kX86RegClassMm:
ASMJIT_ASSERT(x86VarTypeToClass(ret.getVarType()) == vd->getClass());
if (vd->getRegIndex() != kInvalidReg)
_context->unuse<kX86RegClassMm>(vd);
_context->attach<kX86RegClassMm>(vd, regIndex, true);
break;
@@ -4449,9 +4525,7 @@ ASMJIT_INLINE void X86CallAlloc::ret() {
else {
ASMJIT_ASSERT(x86VarTypeToClass(ret.getVarType()) == vd->getClass());
if (vd->getRegIndex() != kInvalidReg)
_context->unuse<kX86RegClassXyz>(vd);
_context->attach<kX86RegClassXyz>(vd, regIndex, true);
}
break;
@@ -5017,7 +5091,6 @@ static void X86Context_translateJump(X86Context* self, JumpNode* jNode, TargetNo
X86Compiler* compiler = self->getCompiler();
Node* extNode = self->getExtraBlock();
// TODO: [COMPILER] State Change.
compiler->_setCursor(extNode);
self->switchState(jTarget->getState());
@@ -5039,7 +5112,7 @@ static void X86Context_translateJump(X86Context* self, JumpNode* jNode, TargetNo
jNode->_target = jTrampolineTarget;
}
// Store the extNode and load the state back.
// Store the `extNode` and load the state back.
self->setExtraBlock(extNode);
self->loadState(jNode->_state);
}
@@ -5261,7 +5334,8 @@ _NextGroup:
if (jTarget->isTranslated()) {
if (jNext->isTranslated()) {
ASMJIT_ASSERT(jNext->getType() == kNodeTypeTarget);
// TODO: [COMPILER] State - Do intersection of two states if possible.
compiler->_setCursor(node->getPrev());
intersectStates(jTarget->getState(), jNext->getState());
}
VarState* savedState = saveState();
@@ -5278,7 +5352,6 @@ _NextGroup:
compiler->_setCursor(node);
switchState(static_cast<TargetNode*>(jNext)->getState());
next = jTarget;
}
else {