using namespace QQmlJS::MASM;
using namespace QV4;
+namespace {
+class ConvertTemps: protected V4IR::StmtVisitor, protected V4IR::ExprVisitor
+{
+ int _nextFreeStackSlot;
+ QHash<V4IR::Temp, int> _stackSlotForTemp;
+
+ void renumber(V4IR::Temp *t)
+ {
+ if (t->kind != V4IR::Temp::VirtualRegister)
+ return;
+
+ int stackSlot = _stackSlotForTemp.value(*t, -1);
+ if (stackSlot == -1) {
+ stackSlot = _nextFreeStackSlot++;
+ _stackSlotForTemp[*t] = stackSlot;
+ }
+
+ t->kind = V4IR::Temp::StackSlot;
+ t->index = stackSlot;
+ }
+
+public:
+ ConvertTemps()
+ : _nextFreeStackSlot(0)
+ {}
+
+ void toStackSlots(V4IR::Function *function)
+ {
+ _stackSlotForTemp.reserve(function->tempCount);
+
+ foreach (V4IR::BasicBlock *bb, function->basicBlocks)
+ foreach (V4IR::Stmt *s, bb->statements)
+ s->accept(this);
+
+ function->tempCount = _nextFreeStackSlot;
+ }
+
+protected:
+ virtual void visitConst(V4IR::Const *) {}
+ virtual void visitString(V4IR::String *) {}
+ virtual void visitRegExp(V4IR::RegExp *) {}
+ virtual void visitName(V4IR::Name *) {}
+ virtual void visitTemp(V4IR::Temp *e) { renumber(e); }
+ virtual void visitClosure(V4IR::Closure *) {}
+ virtual void visitConvert(V4IR::Convert *e) { e->expr->accept(this); }
+ virtual void visitUnop(V4IR::Unop *e) { e->expr->accept(this); }
+ virtual void visitBinop(V4IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
+ virtual void visitCall(V4IR::Call *e) {
+ e->base->accept(this);
+ for (V4IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitNew(V4IR::New *e) {
+ e->base->accept(this);
+ for (V4IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitSubscript(V4IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
+ virtual void visitMember(V4IR::Member *e) { e->base->accept(this); }
+ virtual void visitExp(V4IR::Exp *s) { s->expr->accept(this); }
+ virtual void visitMove(V4IR::Move *s) { s->target->accept(this); s->source->accept(this); }
+ virtual void visitJump(V4IR::Jump *) {}
+ virtual void visitCJump(V4IR::CJump *s) { s->cond->accept(this); }
+ virtual void visitRet(V4IR::Ret *s) { s->expr->accept(this); }
+ virtual void visitTry(V4IR::Try *s) { s->exceptionVar->accept(this); }
+ virtual void visitPhi(V4IR::Phi *) { Q_UNREACHABLE(); }
+};
+} // anonymous namespace
+
/* Platform/Calling convention/Architecture specific section */
#if CPU(X86_64)
loadPtr(Address(context, offsetof(CallContext, locals)), reg);
offset = t->index * sizeof(Value);
} break;
- case V4IR::Temp::VirtualRegister: {
+ case V4IR::Temp::StackSlot: {
assert(t->scope == 0);
const int arg = _function->maxNumberOfArguments + t->index + 1;
offset = - sizeof(Value) * (arg + 1);
, _function(0)
, _vmFunction(0)
, _as(0)
+ , _locals(0)
{
}
V4IR::Optimizer opt(_function);
opt.run();
- opt.convertOutOfSSA();
+ if (opt.isInSSA()) {
+#if CPU(X86_64) && (OS(MAC_OS_X) || OS(LINUX)) && 0
+ // TODO: add a register allocator here.
+#else
+ // No register allocator available for this platform, so:
+ opt.convertOutOfSSA();
+ ConvertTemps().toStackSlots(_function);
+#endif
+ } else {
+ ConvertTemps().toStackSlots(_function);
+ }
int locals = (_function->tempCount + _function->maxNumberOfArguments) + 1;
locals = (locals + 1) & ~1;