| 114 | |
| 115 | private: |
| 116 | void printBlock(CFG::BasicBlock const& _block) |
| 117 | { |
| 118 | m_stream << "Block" << getBlockId(_block) << " [label=\"\\\n"; |
| 119 | |
| 120 | // Verify that the entries of this block exit into this block. |
| 121 | for (auto const& entry: _block.entries) |
| 122 | std::visit(util::GenericVisitor{ |
| 123 | [&](CFG::BasicBlock::Jump const& _jump) |
| 124 | { |
| 125 | soltestAssert(_jump.target == &_block, "Invalid control flow graph."); |
| 126 | }, |
| 127 | [&](CFG::BasicBlock::ConditionalJump const& _conditionalJump) |
| 128 | { |
| 129 | soltestAssert( |
| 130 | _conditionalJump.zero == &_block || _conditionalJump.nonZero == &_block, |
| 131 | "Invalid control flow graph." |
| 132 | ); |
| 133 | }, |
| 134 | [&](auto const&) |
| 135 | { |
| 136 | soltestAssert(false, "Invalid control flow graph."); |
| 137 | } |
| 138 | }, entry->exit); |
| 139 | |
| 140 | auto const& blockInfo = m_stackLayout.blockInfos.at(&_block); |
| 141 | m_stream << stackToString(blockInfo.entryLayout, m_dialect) << "\\l\\\n"; |
| 142 | for (auto const& operation: _block.operations) |
| 143 | { |
| 144 | auto entryLayout = m_stackLayout.operationEntryLayout.at(&operation); |
| 145 | m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_dialect) << "\\l\\\n"; |
| 146 | std::visit(util::GenericVisitor{ |
| 147 | [&](CFG::FunctionCall const& _call) { |
| 148 | m_stream << _call.function.get().name.str(); |
| 149 | }, |
| 150 | [&](CFG::BuiltinCall const& _call) { |
| 151 | m_stream << _call.builtin.get().name; |
| 152 | |
| 153 | }, |
| 154 | [&](CFG::Assignment const& _assignment) { |
| 155 | m_stream << "Assignment("; |
| 156 | m_stream << joinHumanReadable(_assignment.variables | ranges::views::transform(variableSlotToString)); |
| 157 | m_stream << ")"; |
| 158 | } |
| 159 | }, operation.operation); |
| 160 | m_stream << "\\l\\\n"; |
| 161 | soltestAssert(operation.input.size() <= entryLayout.size(), "Invalid Stack Layout."); |
| 162 | for (size_t i = 0; i < operation.input.size(); ++i) |
| 163 | entryLayout.pop_back(); |
| 164 | entryLayout += operation.output; |
| 165 | m_stream << stackToString(entryLayout, m_dialect) << "\\l\\\n"; |
| 166 | } |
| 167 | m_stream << stackToString(blockInfo.exitLayout, m_dialect) << "\\l\\\n"; |
| 168 | m_stream << "\"];\n"; |
| 169 | std::visit(util::GenericVisitor{ |
| 170 | [&](CFG::BasicBlock::MainExit const&) |
| 171 | { |
| 172 | m_stream << "Block" << getBlockId(_block) << "Exit [label=\"MainExit\"];\n"; |
| 173 | m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; |
nothing calls this directly
no test coverage detected