diff options
Diffstat (limited to 'ControlFlowGraph.cpp')
-rw-r--r-- | ControlFlowGraph.cpp | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/ControlFlowGraph.cpp b/ControlFlowGraph.cpp index 5adb951a..1ad54d8c 100644 --- a/ControlFlowGraph.cpp +++ b/ControlFlowGraph.cpp @@ -221,22 +221,36 @@ void ControlFlowGraph::gatherKnowledge() KnownStatePointer emptyState = make_shared<KnownState>(); bool unknownJumpEncountered = false; - vector<pair<BlockId, KnownStatePointer>> workQueue({make_pair(BlockId::initial(), emptyState->copy())}); + struct WorkQueueItem { + BlockId blockId; + KnownStatePointer state; + set<BlockId> blocksSeen; + }; + + vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), set<BlockId>()}}; + auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state) + { + WorkQueueItem item; + item.blockId = _to; + item.state = _state->copy(); + item.blocksSeen = _currentItem.blocksSeen; + item.blocksSeen.insert(_currentItem.blockId); + workQueue.push_back(move(item)); + }; + while (!workQueue.empty()) { + WorkQueueItem item = move(workQueue.back()); + workQueue.pop_back(); //@todo we might have to do something like incrementing the sequence number for each JUMPDEST - assertThrow(!!workQueue.back().first, OptimizerException, ""); - if (!m_blocks.count(workQueue.back().first)) - { - workQueue.pop_back(); + assertThrow(!!item.blockId, OptimizerException, ""); + if (!m_blocks.count(item.blockId)) continue; // too bad, we do not know the tag, probably an invalid jump - } - BasicBlock& block = m_blocks.at(workQueue.back().first); - KnownStatePointer state = workQueue.back().second; - workQueue.pop_back(); + BasicBlock& block = m_blocks.at(item.blockId); + KnownStatePointer state = item.state; if (block.startState) { - state->reduceToCommonKnowledge(*block.startState); + state->reduceToCommonKnowledge(*block.startState, !item.blocksSeen.count(item.blockId)); if (*state == *block.startState) continue; } @@ -270,12 +284,12 @@ void ControlFlowGraph::gatherKnowledge() unknownJumpEncountered = true; for (auto const& it: m_blocks) if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag) - workQueue.push_back(make_pair(it.first, emptyState->copy())); + workQueue.push_back(WorkQueueItem{it.first, emptyState, set<BlockId>()}); } } else for (auto tag: tags) - workQueue.push_back(make_pair(BlockId(tag), state->copy())); + addWorkQueueItem(item, BlockId(tag), state); } else if (block.begin <= pc && pc < block.end) state->feedItem(m_items.at(pc++)); @@ -287,7 +301,7 @@ void ControlFlowGraph::gatherKnowledge() block.endType == BasicBlock::EndType::HANDOVER || block.endType == BasicBlock::EndType::JUMPI ) - workQueue.push_back(make_pair(block.next, state->copy())); + addWorkQueueItem(item, block.next, state); } // Remove all blocks we never visited here. This might happen because a tag is pushed but |