diff options
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 397 |
1 files changed, 147 insertions, 250 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 93692b3996..fdda69e167 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -50,7 +56,6 @@ #include <cmath> #include <iostream> #include <cassert> -#include <algorithm> QT_USE_NAMESPACE @@ -81,120 +86,6 @@ static void showMeTheCode(IR::Function *function, const char *marker) } } -#if !defined(BROKEN_STD_VECTOR_BOOL_OR_BROKEN_STD_FIND) -// Sanity: -class BitVector -{ - std::vector<bool> bits; - -public: - BitVector(int size = 0, bool value = false) - : bits(size, value) - {} - - void reserve(int size) - { bits.reserve(size); } - - int size() const - { - Q_ASSERT(bits.size() < INT_MAX); - return static_cast<int>(bits.size()); - } - - void resize(int newSize) - { bits.resize(newSize); } - - void assign(int newSize, bool value) - { bits.assign(newSize, value); } - - int findNext(int start, bool value, bool wrapAround) const - { - // The ++operator of std::vector<bool>::iterator in libc++ has a bug when using it on an - // iterator pointing to the last element. It will not be set to ::end(), but beyond - // that. (It will be set to the first multiple of the native word size that is bigger - // than size().) - // - // See http://llvm.org/bugs/show_bug.cgi?id=19663 - // - // The work-around is to calculate the distance, and compare it to the size() to see if it's - // beyond the end, or take the minimum of the distance and the size. - - size_t pos = std::distance(bits.begin(), - std::find(bits.begin() + start, bits.end(), value)); - if (wrapAround && pos >= static_cast<size_t>(size())) - pos = std::distance(bits.begin(), - std::find(bits.begin(), bits.begin() + start, value)); - - pos = qMin(pos, static_cast<size_t>(size())); - - Q_ASSERT(pos <= static_cast<size_t>(size())); - Q_ASSERT(pos < INT_MAX); - - return static_cast<int>(pos); - } - - bool at(int idx) const - { return bits.at(idx); } - - void setBit(int idx) - { bits[idx] = true; } - - void clearBit(int idx) - { bits[idx] = false; } -}; -#else // Insanity: -class BitVector -{ - QBitArray bits; - -public: - BitVector(int size = 0, bool value = false) - : bits(size, value) - {} - - void reserve(int size) - { Q_UNUSED(size); } - - int size() const - { return bits.size(); } - - void resize(int newSize) - { bits.resize(newSize); } - - void assign(int newSize, bool value) - { - bits.resize(newSize); - bits.fill(value); - } - - int findNext(int start, bool value, bool wrapAround) const - { - for (int i = start, ei = size(); i < ei; ++i) { - if (at(i) == value) - return i; - } - - if (wrapAround) { - for (int i = 0, ei = start; i < ei; ++i) { - if (at(i) == value) - return i; - } - } - - return size(); - } - - bool at(int idx) const - { return bits.at(idx); } - - void setBit(int idx) - { bits[idx] = true; } - - void clearBit(int idx) - { bits[idx] = false; } -}; -#endif - class ProcessedBlocks { BitVector processed; @@ -551,7 +442,7 @@ class DominatorTree BasicBlockIndex p = d->parent[n]; BasicBlockIndex s = p; - foreach (BasicBlock *v, function->basicBlock(n)->in) { + for (BasicBlock *v : function->basicBlock(n)->in) { BasicBlockIndex ss = InvalidBasicBlockIndex; if (d->dfnum[v->index()] <= d->dfnum[n]) ss = v->index(); @@ -564,7 +455,7 @@ class DominatorTree bucket[s].push_back(n); link(p, n); if (bucket.contains(p)) { - foreach (BasicBlockIndex v, bucket[p]) { + for (BasicBlockIndex v : bucket[p]) { BasicBlockIndex y = ancestorWithLowestSemi(v, worklist); BasicBlockIndex semi_v = d->semi[v]; if (d->semi[y] == semi_v) @@ -611,7 +502,7 @@ public: // compute children of each node in the dominator tree std::vector<std::vector<BasicBlockIndex> > children; // BasicBlock index -> children children.resize(function->basicBlockCount()); - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; const BasicBlockIndex nodeIndex = n->index(); @@ -627,7 +518,7 @@ public: nodeStatus.resize(function->basicBlockCount()); std::vector<BasicBlockIndex> worklist; worklist.reserve(function->basicBlockCount()); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; BasicBlockIndex nodeIndex = bb->index(); @@ -661,10 +552,10 @@ public: if (np.todo.empty()) { BasicBlockSet &S = DF[node]; S.init(function); - foreach (BasicBlock *y, function->basicBlock(node)->out) + for (BasicBlock *y : function->basicBlock(node)->out) if (idom[y->index()] != node) S.insert(y); - foreach (BasicBlockIndex child, np.children) { + for (BasicBlockIndex child : np.children) { const BasicBlockSet &ws = DF[child]; for (BasicBlockSet::const_iterator it = ws.begin(), eit = ws.end(); it != eit; ++it) { BasicBlock *w = *it; @@ -683,7 +574,7 @@ public: buf.open(QIODevice::WriteOnly); QTextStream qout(&buf); qout << "Dominator Frontiers:" << endl; - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; @@ -700,7 +591,7 @@ public: } if (DebugDominatorFrontiers && DebugCodeCanUseLotsOfCpu) { - foreach (BasicBlock *n, function->basicBlocks()) { + for (BasicBlock *n : function->basicBlocks()) { if (n->isRemoved()) continue; const BasicBlockSet &fBlocks = DF[n->index()]; @@ -708,7 +599,7 @@ public: BasicBlock *fBlock = *it; Q_ASSERT(!dominates(n, fBlock) || fBlock == n); bool hasDominatedSucc = false; - foreach (BasicBlock *succ, fBlock->in) { + for (BasicBlock *succ : fBlock->in) { if (dominates(n, succ)) { hasDominatedSucc = true; break; @@ -741,7 +632,7 @@ public: buf.open(QIODevice::WriteOnly); QTextStream qout(&buf); qout << "Immediate dominators:" << endl; - foreach (BasicBlock *to, function->basicBlocks()) { + for (BasicBlock *to : function->basicBlocks()) { if (to->isRemoved()) continue; @@ -875,7 +766,7 @@ private: { std::vector<int> nodeDepths(size_t(function->basicBlockCount()), -1); nodeDepths[0] = 0; - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; @@ -939,8 +830,7 @@ private: std::vector<BasicBlockIndex> prefix; prefix.reserve(32); - for (int i = 0, ei = node->in.size(); i != ei; ++i) { - BasicBlock *in = node->in.at(i); + for (BasicBlock *in : node->in) { if (node == in) // back-edge to self continue; if (dominates(node->index(), in->index())) // a known back-edge @@ -1049,13 +939,13 @@ public: for (size_t i = 0; i != ei; ++i) A_orig[i].reserve(8); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; currentBB = bb; killed.assign(function->tempCount, false); - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); } } @@ -1375,16 +1265,15 @@ public: void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) { Phi *phiNode = f->NewStmt<Phi>(); - phiNode->d = new Phi::Data; phiNode->targetTemp = f->New<Temp>(); phiNode->targetTemp->init(a.kind, a.index); y->prependStatement(phiNode); - phiNode->d->incoming.resize(y->in.size()); + phiNode->incoming.resize(y->in.size()); for (int i = 0, ei = y->in.size(); i < ei; ++i) { Temp *t = f->New<Temp>(); t->init(a.kind, a.index); - phiNode->d->incoming[i] = t; + phiNode->incoming[i] = t; } } @@ -1559,7 +1448,7 @@ private: processed.markAsProcessed(bb); BasicBlock *next = 0; - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { if (processed.alreadyProcessed(out)) continue; if (!next) @@ -1575,17 +1464,17 @@ private: { currentBB = bb; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { currentStmt = s; s->accept(this); } - foreach (BasicBlock *Y, bb->out) { + for (BasicBlock *Y : bb->out) { const int j = Y->in.indexOf(bb); Q_ASSERT(j >= 0 && j < Y->in.size()); - foreach (Stmt *s, Y->statements()) { + for (Stmt *s : Y->statements()) { if (Phi *phi = s->asPhi()) { - Temp *t = phi->d->incoming[j]->asTemp(); + Temp *t = phi->incoming[j]->asTemp(); unsigned newTmp = currentNumber(*t); // qDebug()<<"I: replacing phi use"<<a<<"with"<<newTmp<<"in L"<<Y->index; t->index = newTmp; @@ -1727,7 +1616,7 @@ void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defU W.reserve(8); // Place phi functions: - foreach (const Temp &a, variables.allTemps()) { + for (const Temp &a : variables.allTemps()) { if (a.isInvalid()) continue; if (!variables.isNonLocal(a)) @@ -1785,7 +1674,7 @@ void cleanupPhis(DefUses &defUses) std::vector<Phi *> allPhis; allPhis.reserve(32); - foreach (const Temp *def, defUses.defs()) { + for (const Temp *def : defUses.defs()) { Stmt *defStmt = defUses.defStmt(*def); if (!defStmt) continue; @@ -1802,7 +1691,7 @@ void cleanupPhis(DefUses &defUses) toRemove |= collectedPhis; } - foreach (Phi *phi, allPhis) { + for (Phi *phi : allPhis) { if (!toRemove.at(phi->id())) continue; @@ -1839,11 +1728,11 @@ public: { grow(); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!s) continue; @@ -1899,7 +1788,7 @@ public: void applyToFunction() { - foreach (BasicBlock *bb, theFunction->basicBlocks()) { + for (BasicBlock *bb : theFunction->basicBlocks()) { if (bb->isRemoved()) continue; @@ -1968,6 +1857,11 @@ public: return *this; } + unsigned size() const + { + return worklistSize; + } + Stmt *takeNext(Stmt *last) { if (worklistSize == 0) @@ -2063,7 +1957,7 @@ protected: return; // TODO: maybe we can distinguish between built-ins of which we know that they do not have // a side-effect. - if (e->builtin == Name::builtin_invalid || (e->id && *e->id != QStringLiteral("this"))) + if (e->builtin == Name::builtin_invalid || (e->id && *e->id != QLatin1String("this"))) markAsSideEffect(); } @@ -2178,27 +2072,6 @@ protected: } }; -struct DiscoveredType { - int type; - MemberExpressionResolver *memberResolver; - - DiscoveredType() : type(UnknownType), memberResolver(0) {} - DiscoveredType(Type t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); } - explicit DiscoveredType(int t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); } - explicit DiscoveredType(MemberExpressionResolver *memberResolver) - : type(QObjectType) - , memberResolver(memberResolver) - { Q_ASSERT(memberResolver); } - - bool test(Type t) const { return type & t; } - bool isNumber() const { return (type & NumberType) && !(type & ~NumberType); } - - bool operator!=(Type other) const { return type != other; } - bool operator==(Type other) const { return type == other; } - bool operator==(const DiscoveredType &other) const { return type == other.type; } - bool operator!=(const DiscoveredType &other) const { return type != other.type; } -}; - class PropagateTempTypes: public StmtVisitor, ExprVisitor { const DefUses &defUses; @@ -2267,7 +2140,7 @@ protected: virtual void visitRet(Ret *s) { s->expr->accept(this); } virtual void visitPhi(Phi *s) { s->targetTemp->accept(this); - foreach (Expr *e, s->d->incoming) + foreach (Expr *e, s->incoming) e->accept(this); } }; @@ -2299,6 +2172,7 @@ class TypeInference: public StmtVisitor, public ExprVisitor {} }; TypingResult _ty; + Stmt *_currentStmt; public: TypeInference(QQmlEnginePrivate *qmlEngine, const DefUses &defUses) @@ -2307,6 +2181,7 @@ public: , _tempTypes(_defUses.tempCount()) , _worklist(0) , _ty(UnknownType) + , _currentStmt(nullptr) {} void run(StatementWorklist &w) { @@ -2323,7 +2198,10 @@ public: QTextStream qout(&buf); qout<<"Typing stmt "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); + + qDebug("%u left in the worklist", _worklist->size()); } if (!run(s)) { @@ -2334,6 +2212,7 @@ public: QTextStream qout(&buf); qout<<"Pushing back stmt: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } else { @@ -2343,6 +2222,7 @@ public: QTextStream qout(&buf); qout<<"Finished: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } @@ -2366,7 +2246,9 @@ private: bool run(Stmt *s) { TypingResult ty; std::swap(_ty, ty); - s->accept(this); + std::swap(_currentStmt, s); + _currentStmt->accept(this); + std::swap(_currentStmt, s); std::swap(_ty, ty); return ty.fullyTyped; } @@ -2400,11 +2282,16 @@ private: QTextStream qout(&buf); qout << "Pushing back dependent stmt: "; IRPrinter(&qout).print(s); + qout.flush(); qDebug("%s", buf.data().constData()); } } - *_worklist += _defUses.uses(*t); + for (Stmt *s : qAsConst(_defUses.uses(*t))) { + if (s != _currentStmt) { + *_worklist += s; + } + } } } else { e->type = (Type) ty.type; @@ -2540,20 +2427,29 @@ protected: if (_ty.fullyTyped && _ty.type.memberResolver && _ty.type.memberResolver->isValid()) { MemberExpressionResolver *resolver = _ty.type.memberResolver; - _ty.type.type = resolver->resolveMember(qmlEngine, resolver, e); + _ty.type = resolver->resolveMember(qmlEngine, resolver, e); } else _ty.type = VarType; } virtual void visitExp(Exp *s) { _ty = run(s->expr); } virtual void visitMove(Move *s) { - TypingResult sourceTy = run(s->source); if (Temp *t = s->target->asTemp()) { + if (Name *n = s->source->asName()) { + if (n->builtin == Name::builtin_qml_context) { + _ty = TypingResult(t->memberResolver); + setType(n, _ty.type); + setType(t, _ty.type); + return; + } + } + TypingResult sourceTy = run(s->source); setType(t, sourceTy.type); _ty = sourceTy; return; } + TypingResult sourceTy = run(s->source); _ty = run(s->target); _ty.fullyTyped &= sourceTy.fullyTyped; } @@ -2562,9 +2458,9 @@ protected: virtual void visitCJump(CJump *s) { _ty = run(s->cond); } virtual void visitRet(Ret *s) { _ty = run(s->expr); } virtual void visitPhi(Phi *s) { - _ty = run(s->d->incoming[0]); - for (int i = 1, ei = s->d->incoming.size(); i != ei; ++i) { - TypingResult ty = run(s->d->incoming[i]); + _ty = run(s->incoming[0]); + for (int i = 1, ei = s->incoming.size(); i != ei; ++i) { + TypingResult ty = run(s->incoming[i]); if (!ty.fullyTyped && _ty.fullyTyped) { // When one of the temps not fully typed, we already know that we cannot completely type this node. // So, pick the type we calculated upto this point, and wait until the unknown one will be typed. @@ -2770,7 +2666,7 @@ void convertConst(Const *c, Type targetType) break; case NullType: case UndefinedType: - c->value = qSNaN(); + c->value = qt_qnan(); c->type = targetType; default: Q_UNIMPLEMENTED(); @@ -2827,12 +2723,12 @@ public: void run(IR::Function *f, StatementWorklist &worklist) { _f = f; - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; _conversions.clear(); - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { _currStmt = s; s->accept(this); } @@ -2883,7 +2779,7 @@ public: _defUses.addUse(*source, conversion.stmt); if (Phi *phi = conversion.stmt->asPhi()) { - int idx = phi->d->incoming.indexOf(t); + int idx = phi->incoming.indexOf(t); Q_ASSERT(idx != -1); bb->in[idx]->insertStatementBeforeTerminator(convCall); } else { @@ -3035,14 +2931,15 @@ protected: virtual void visitRet(Ret *s) { run(s->expr); } virtual void visitPhi(Phi *s) { Type ty = s->targetTemp->type; - for (int i = 0, ei = s->d->incoming.size(); i != ei; ++i) - run(s->d->incoming[i], ty); + for (int i = 0, ei = s->incoming.size(); i != ei; ++i) + run(s->incoming[i], ty); } }; void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &worklist, DefUses &defUses) { - foreach (BasicBlock *toBB, f->basicBlocks()) { + const QVector<BasicBlock *> copy = f->basicBlocks(); + for (BasicBlock *toBB : copy) { if (toBB->isRemoved()) continue; if (toBB->in.size() < 2) @@ -3110,7 +3007,7 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &w df.setImmediateDominator(newBB, fromBB); bool toNeedsNewIdom = true; - foreach (BasicBlock *bb, toBB->in) { + for (BasicBlock *bb : toBB->in) { if (bb != newBB && !df.dominates(toBB, bb)) { toNeedsNewIdom = false; break; @@ -3220,7 +3117,7 @@ public: backedges.clear(); - foreach (BasicBlock *in, bb->in) + for (BasicBlock *in : bb->in) if (dt.dominates(bb, in)) backedges.push_back(in); @@ -3297,7 +3194,7 @@ private: // those predecessors are not in the current subloop. It might be the case // that they are in other loops, which we will then add as a subloop to the // current loop. - foreach (BasicBlock *predIn, predIt->in) + for (BasicBlock *predIn : predIt->in) if (predIn->containingGroup() != subloop) worklist.push_back(predIn); } else { @@ -3308,7 +3205,7 @@ private: predIt->setContainingGroup(loopHead); // Add all incoming edges to the worklist. - foreach (BasicBlock *bb, predIt->in) + for (BasicBlock *bb : predIt->in) worklist.push_back(bb); } } @@ -3320,7 +3217,7 @@ private: void createLoopInfos(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; if (BasicBlock *loopHeader = bb->containingGroup()) @@ -3393,7 +3290,7 @@ class BlockScheduler { Q_ASSERT(candidate->containingGroup() == currentGroup.group); - foreach (BasicBlock *in, candidate->in) { + for (BasicBlock *in : candidate->in) { if (emitted.alreadyProcessed(in)) continue; @@ -3503,7 +3400,7 @@ public: void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) { foreach (BasicBlock *bb, basicBlocks) { if (bb && bb->out.size() > 1) { - foreach (BasicBlock *bb2, bb->out) { + for (BasicBlock *bb2 : bb->out) { if (bb2 && bb2->in.size() > 1) { qDebug() << "found critical edge between block" << bb->index() << "and block" << bb2->index(); @@ -3538,28 +3435,28 @@ static void cleanupBasicBlocks(IR::Function *function) reachableBlocks.setBit(bb->index()); - foreach (BasicBlock *outBB, bb->out) { + for (BasicBlock *outBB : bb->out) { if (!reachableBlocks.at(outBB->index())) postponed.append(outBB); } } - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) // the block has already been removed, so ignore it continue; if (reachableBlocks.at(bb->index())) // the block is reachable, so ignore it continue; - foreach (BasicBlock *outBB, bb->out) { + for (BasicBlock *outBB : bb->out) { if (outBB->isRemoved() || !reachableBlocks.at(outBB->index())) continue; // We do not need to unlink from blocks that are scheduled to be removed. int idx = outBB->in.indexOf(bb); if (idx != -1) { outBB->in.remove(idx); - foreach (Stmt *s, outBB->statements()) { + for (Stmt *s : outBB->statements()) { if (Phi *phi = s->asPhi()) - phi->d->incoming.remove(idx); + phi->incoming.remove(idx); else break; } @@ -3574,9 +3471,9 @@ static void cleanupBasicBlocks(IR::Function *function) inline Const *isConstPhi(Phi *phi) { - if (Const *c = phi->d->incoming[0]->asConst()) { - for (int i = 1, ei = phi->d->incoming.size(); i != ei; ++i) { - if (Const *cc = phi->d->incoming[i]->asConst()) { + if (Const *c = phi->incoming[0]->asConst()) { + for (int i = 1, ei = phi->incoming.size(); i != ei; ++i) { + if (Const *cc = phi->incoming[i]->asConst()) { if (c->value != cc->value) return 0; if (!(c->type == cc->type || (c->type & NumberType && cc->type & NumberType))) @@ -3677,8 +3574,8 @@ protected: virtual void visitCJump(CJump *s) { check(s->cond); } virtual void visitRet(Ret *s) { check(s->expr); } virtual void visitPhi(Phi *s) { - for (int i = 0, ei = s->d->incoming.size(); i != ei; ++i) - check(s->d->incoming[i]); + for (int i = 0, ei = s->incoming.size(); i != ei; ++i) + check(s->incoming[i]); } private: @@ -3739,11 +3636,11 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs if (!outStmt) continue; if (Phi *phi = outStmt->asPhi()) { - if (Temp *t = phi->d->incoming[idx]->asTemp()) { + if (Temp *t = phi->incoming[idx]->asTemp()) { defUses.removeUse(phi, *t); W += defUses.defStmt(*t); } - phi->d->incoming.remove(idx); + phi->incoming.remove(idx); W += phi; } else { break; @@ -3793,14 +3690,14 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs continue; // unlink all incoming edges - foreach (BasicBlock *in, bb->in) { + for (BasicBlock *in : bb->in) { int idx = in->out.indexOf(bb); if (idx != -1) in->out.remove(idx); } // unlink all outgoing edges, including "arguments" to phi statements - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { if (out->isRemoved()) continue; @@ -3816,7 +3713,7 @@ void unlink(BasicBlock *from, BasicBlock *to, IR::Function *func, DefUses &defUs } // unlink all defs/uses from the statements in the basic block - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!s) continue; @@ -3931,7 +3828,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = Util(qout).genLoop(l); } - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; @@ -3942,7 +3839,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = else qout << ", shape=circle"; qout << "];\n"; - foreach (BasicBlock *out, bb->out) + for (BasicBlock *out : bb->out) qout << " L" << idx << " -> L" << out->index() << "\n"; } @@ -3978,9 +3875,9 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df) } // copy propagation: - if (phi->d->incoming.size() == 1) { + if (phi->incoming.size() == 1) { Temp *t = phi->targetTemp; - Expr *e = phi->d->incoming.first(); + Expr *e = phi->incoming.first(); QVector<Stmt *> newT2Uses; replaceUses(t, e, W, &newT2Uses); @@ -4411,14 +4308,14 @@ private: void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd) { LiveRegs live; - foreach (BasicBlock *successor, bb->out) { + for (BasicBlock *successor : bb->out) { live.unite(_liveIn[successor->index()]); const int bbIndex = successor->in.indexOf(bb); Q_ASSERT(bbIndex >= 0); - foreach (Stmt *s, successor->statements()) { + for (Stmt *s : successor->statements()) { if (Phi *phi = s->asPhi()) { - if (Temp *t = phi->d->incoming.at(bbIndex)->asTemp()) + if (Temp *t = phi->incoming.at(bbIndex)->asTemp()) live.insert(*t); } else { break; @@ -4426,7 +4323,7 @@ private: } } - QVector<Stmt *> statements = bb->statements(); + const QVector<Stmt *> &statements = bb->statements(); foreach (const Temp &opd, live) interval(&opd).addRange(start(bb), end(bb)); @@ -4474,7 +4371,7 @@ void removeUnreachleBlocks(IR::Function *function) { QVector<BasicBlock *> newSchedule; newSchedule.reserve(function->basicBlockCount()); - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) newSchedule.append(bb); function->setScheduledBlocks(newSchedule); @@ -4519,9 +4416,9 @@ public: } } - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); if (convertArgs && function->formals.size() > 0) @@ -4605,7 +4502,7 @@ public: { block = new BasicBlock(originalBlock->function, 0); - foreach (Stmt *s, originalBlock->statements()) { + for (Stmt *s : originalBlock->statements()) { s->accept(this); clonedStmt->location = s->location; } @@ -4635,9 +4532,8 @@ protected: clonedStmt = phi; phi->targetTemp = clone(stmt->targetTemp); - phi->d = new Phi::Data; - foreach (Expr *in, stmt->d->incoming) - phi->d->incoming.append(clone(in)); + foreach (Expr *in, stmt->incoming) + phi->incoming.append(clone(in)); block->appendStatement(phi); } @@ -4722,7 +4618,8 @@ private: // the terminators will automatically insert that edge). The blocks where the originals // pointed to will have an extra incoming edge from the copied blocks. - foreach (BasicBlock *in, loop->loopHeader->in) { + BasicBlock::IncomingEdges inCopy = loop->loopHeader->in; + for (BasicBlock *in : inCopy) { if (unpeeled.loopHeader != in // this can happen for really tight loops (where there are no body blocks). This is a back-edge in that case. && !unpeeled.loopBody.contains(in) // if the edge is not coming from within the copied set, leave it alone && !dt.dominates(loop->loopHeader, in)) // an edge coming from within the loop (so a back-edge): this is handled when rewiring all outgoing edges @@ -4796,7 +4693,7 @@ static void verifyCFG(IR::Function *function) if (!DoVerification) return; - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) { Q_ASSERT(bb->in.isEmpty()); Q_ASSERT(bb->out.isEmpty()); @@ -4828,14 +4725,14 @@ static void verifyCFG(IR::Function *function) } // Check the outgoing edges: - foreach (BasicBlock *out, bb->out) { + for (BasicBlock *out : bb->out) { Q_UNUSED(out); Q_ASSERT(!out->isRemoved()); Q_ASSERT(out->in.contains(bb)); } // Check the incoming edges: - foreach (BasicBlock *in, bb->in) { + for (BasicBlock *in : bb->in) { Q_UNUSED(in); Q_ASSERT(!in->isRemoved()); Q_ASSERT(in->out.contains(bb)); @@ -4852,7 +4749,7 @@ static void verifyImmediateDominators(const DominatorTree &dt, IR::Function *fun dt.dumpImmediateDominators(); DominatorTree referenceTree(function); - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; @@ -4873,11 +4770,11 @@ static void verifyNoPointerSharing(IR::Function *function) public: void operator()(IR::Function *f) { - foreach (BasicBlock *bb, f->basicBlocks()) { + for (BasicBlock *bb : f->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) + for (Stmt *s : bb->statements()) s->accept(this); } } @@ -4892,7 +4789,7 @@ static void verifyNoPointerSharing(IR::Function *function) { check(s); s->targetTemp->accept(this); - foreach (Expr *e, s->d->incoming) + foreach (Expr *e, s->incoming) e->accept(this); } @@ -4941,11 +4838,11 @@ class RemoveLineNumbers: public SideEffectsChecker, public StmtVisitor public: static void run(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (!hasSideEffects(s)) { s->location = QQmlJS::AST::SourceLocation(); } @@ -5157,13 +5054,13 @@ LifeTimeIntervals::LifeTimeIntervals(IR::Function *function) // basic-block. void LifeTimeIntervals::renumber(IR::Function *function) { - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { if (bb->isRemoved()) continue; _basicBlockPosition[bb->index()].start = _lastPosition + 1; - foreach (Stmt *s, bb->statements()) { + for (Stmt *s : bb->statements()) { if (s->asPhi()) continue; @@ -5193,7 +5090,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee function->removeSharedExpressions(); int statementCount = 0; - foreach (BasicBlock *bb, function->basicBlocks()) + for (BasicBlock *bb : function->basicBlocks()) if (!bb->isRemoved()) statementCount += bb->statementCount(); // showMeTheCode(function); @@ -5323,15 +5220,15 @@ void Optimizer::convertOutOfSSA() { // There should be no critical edges at this point. - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { MoveMapping moves; - foreach (BasicBlock *successor, bb->out) { + for (BasicBlock *successor : bb->out) { const int inIdx = successor->in.indexOf(bb); Q_ASSERT(inIdx >= 0); - foreach (Stmt *s, successor->statements()) { + for (Stmt *s : successor->statements()) { if (Phi *phi = s->asPhi()) { - moves.add(clone(phi->d->incoming[inIdx], function), + moves.add(clone(phi->incoming[inIdx], function), clone(phi->targetTemp, function)->asTemp()); } else { break; @@ -5359,7 +5256,7 @@ void Optimizer::convertOutOfSSA() { moves.insertMoves(bb, function, true); } - foreach (BasicBlock *bb, function->basicBlocks()) { + for (BasicBlock *bb : function->basicBlocks()) { while (!bb->isEmpty()) { if (bb->statements().first()->asPhi()) { bb->removeStatement(0); |