void Forest::Color() { int nn, m; int c; int j, k = 17; int *p; CSet used; Tree *t; if (pass == 1) { for (c = 0; c < treecount; c++) { trees[c]->spill = false; trees[c]->color = k; if (trees[c]->var < 3) trees[c]->color = trees[c]->var; if (trees[c]->var >= regFirstArg && trees[c]->var <= regLastArg) { trees[c]->color = trees[c]->var - regFirstArg + 18; } if (trees[c]->var == regFP || trees[c]->var == regLR || trees[c]->var == regXLR || trees[c]->var == regSP) { trees[c]->color = trees[c]->var - regXLR + 28; } } } used.clear(); used.add(0); // reg0 is a constant 0 used.add(1); // these two are return value used.add(2); while (!stk->IsEmpty()) { t = trees[m=pop()]; if (pass == 1 && !t->infinite && t->cost < 0.0f) { // was <= 0.0f t->spill = true; } else { p = iGraph.GetNeighbours(m, &nn); for (j = 0; j < nn; j++) used.add(trees[p[j]]->color); for (c = 0; used.isMember(c) && c < k; c++); if (c < k && t->color == k) { // The tree may have been colored already t->color = c; used.add(c); } else if (t->color <= k) // Don't need to spill args t->spill = true; } } }
bool Forest::SpillCode() { int c, m, n; Var *v; Tree *t; BasicBlock *bb; int64_t spillOffset; OCODE *cd; CSet spilled; bool ret; ret = false; cd = currentFn->spAdjust; if (cd == nullptr) return (ret); spillOffset = cd->oper3->offset->i; spilled.clear(); for (c = 0; c < treecount; c++) { t = trees[c]; // convenience // Tree couldn't be colored that means there are no available registers. // So, spill one of the registers. The register to spill should be one // that isn't live at the same time as this tree. if (t->spill) { ret = true; v = Var::Find(t->var); v = v->GetVarToSpill(&spilled); if (v == nullptr) continue; // The var is spilled at the head of the tree, and restored later t->blocks->resetPtr(); m = t->blocks->nextMember(); if (m >= 0) { // should always be true, otherwise no code bb = basicBlocks[m]; if (!spilled.isMember(v->num)) { v->spillOffset = spillOffset; spillOffset += sizeOfWord; spilled.add(v->num); } bb->InsertSpillCode(v->num, -v->spillOffset); while(1) { n = m; m = t->blocks->nextMember(); if (m < 0) break; // Detect when a different branch is present. The node // number will jump by more than 1 between branches. // *** suspect this won't work, should just pick last block in tree if (m - n > 1) { bb = basicBlocks[n]; bb->InsertFillCode(v->num, -v->spillOffset); } } bb = basicBlocks[n]; bb->InsertFillCode(v->num, -v->spillOffset); } t->spill = false; } } cd->oper3->offset->i = spillOffset; return (ret); }