| 215 | } |
| 216 | |
| 217 | void ControlFlowGraph::gatherKnowledge() |
| 218 | { |
| 219 | // @todo actually we know that memory is filled with zeros at the beginning, |
| 220 | // we could make use of that. |
| 221 | KnownStatePointer emptyState = std::make_shared<KnownState>(); |
| 222 | bool unknownJumpEncountered = false; |
| 223 | |
| 224 | struct WorkQueueItem { |
| 225 | BlockId blockId; |
| 226 | KnownStatePointer state; |
| 227 | std::set<BlockId> blocksSeen; |
| 228 | }; |
| 229 | |
| 230 | std::vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), std::set<BlockId>()}}; |
| 231 | auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state) |
| 232 | { |
| 233 | WorkQueueItem item; |
| 234 | item.blockId = _to; |
| 235 | item.state = _state->copy(); |
| 236 | item.blocksSeen = _currentItem.blocksSeen; |
| 237 | item.blocksSeen.insert(_currentItem.blockId); |
| 238 | workQueue.push_back(std::move(item)); |
| 239 | }; |
| 240 | |
| 241 | while (!workQueue.empty()) |
| 242 | { |
| 243 | WorkQueueItem item = std::move(workQueue.back()); |
| 244 | workQueue.pop_back(); |
| 245 | //@todo we might have to do something like incrementing the sequence number for each JUMPDEST |
| 246 | assertThrow(!!item.blockId, OptimizerException, ""); |
| 247 | if (!m_blocks.count(item.blockId)) |
| 248 | continue; // too bad, we do not know the tag, probably an invalid jump |
| 249 | BasicBlock& block = m_blocks.at(item.blockId); |
| 250 | KnownStatePointer state = item.state; |
| 251 | if (block.startState) |
| 252 | { |
| 253 | // We call reduceToCommonKnowledge even in the non-join setting to get the correct |
| 254 | // sequence number |
| 255 | if (!m_joinKnowledge) |
| 256 | state->reset(); |
| 257 | state->reduceToCommonKnowledge(*block.startState, !item.blocksSeen.count(item.blockId)); |
| 258 | if (*state == *block.startState) |
| 259 | continue; |
| 260 | } |
| 261 | |
| 262 | block.startState = state->copy(); |
| 263 | |
| 264 | // Feed all items except for the final jump yet because it will erase the target tag. |
| 265 | unsigned pc = block.begin; |
| 266 | while (pc < block.end && !SemanticInformation::altersControlFlow(m_items.at(pc))) |
| 267 | state->feedItem(m_items.at(pc++)); |
| 268 | |
| 269 | if ( |
| 270 | block.endType == BasicBlock::EndType::JUMP || |
| 271 | block.endType == BasicBlock::EndType::JUMPI |
| 272 | ) |
| 273 | { |
| 274 | assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, ""); |
nothing calls this directly
no test coverage detected