void CodeEmitter::prepareEmission(BasicBlock *bb) { Instruction *i, *next; Function *func = bb->getFunction(); int j; unsigned int nShort; for (j = func->bbCount - 1; j >= 0 && !func->bbArray[j]->binSize; --j); for (; j >= 0; --j) { BasicBlock *in = func->bbArray[j]; Instruction *exit = in->getExit(); if (exit && exit->op == OP_BRA && exit->asFlow()->target.bb == bb) { in->binSize -= 8; func->binSize -= 8; for (++j; j < func->bbCount; ++j) func->bbArray[j]->binPos -= 8; in->remove(exit); } bb->binPos = in->binPos + in->binSize; if (in->binSize) // no more no-op branches to bb break; } func->bbArray[func->bbCount++] = bb; if (!bb->getExit()) return; // determine encoding size, try to group short instructions nShort = 0; for (i = bb->getEntry(); i; i = next) { next = i->next; if (i->op == OP_MEMBAR && !targ->isOpSupported(OP_MEMBAR, TYPE_NONE)) { bb->remove(i); continue; } i->encSize = getMinEncodingSize(i); if (next && i->encSize < 8) ++nShort; else if ((nShort & 1) && next && getMinEncodingSize(next) == 4) { if (i->isCommutationLegal(i->next)) { bb->permuteAdjacent(i, next); next->encSize = 4; next = i; i = i->prev; ++nShort; } else if (i->isCommutationLegal(i->prev) && next->next) { bb->permuteAdjacent(i->prev, i); next->encSize = 4; next = next->next; bb->binSize += 4; ++nShort; } else { i->encSize = 8; i->prev->encSize = 8; bb->binSize += 4; nShort = 0; } } else { i->encSize = 8; if (nShort & 1) { i->prev->encSize = 8; bb->binSize += 4; } nShort = 0; } bb->binSize += i->encSize; } if (bb->getExit()->encSize == 4) { assert(nShort); bb->getExit()->encSize = 8; bb->binSize += 4; if ((bb->getExit()->prev->encSize == 4) && !(nShort & 1)) { bb->binSize += 8; bb->getExit()->prev->encSize = 8; } } assert(!bb->getEntry() || (bb->getExit() && bb->getExit()->encSize == 8)); func->binSize += bb->binSize; }