| 137 | } |
| 138 | |
| 139 | AssemblyItems CSECodeGenerator::generateCode( |
| 140 | unsigned _initialSequenceNumber, |
| 141 | int _initialStackHeight, |
| 142 | std::map<int, Id> const& _initialStack, |
| 143 | std::map<int, Id> const& _targetStackContents |
| 144 | ) |
| 145 | { |
| 146 | m_stackHeight = _initialStackHeight; |
| 147 | m_stack = _initialStack; |
| 148 | m_targetStack = _targetStackContents; |
| 149 | for (auto const& item: m_stack) |
| 150 | m_classPositions[item.second].insert(item.first); |
| 151 | |
| 152 | // generate the dependency graph starting from final storage and memory writes and target stack contents |
| 153 | for (auto const& p: m_storeOperations) |
| 154 | addDependencies(p.second.back().expression); |
| 155 | for (auto const& targetItem: m_targetStack) |
| 156 | { |
| 157 | m_finalClasses.insert(targetItem.second); |
| 158 | addDependencies(targetItem.second); |
| 159 | } |
| 160 | |
| 161 | // store all needed sequenced expressions |
| 162 | std::set<std::pair<unsigned, Id>> sequencedExpressions; |
| 163 | for (auto const& p: m_neededBy) |
| 164 | for (auto id: {p.first, p.second}) |
| 165 | if (unsigned seqNr = m_expressionClasses.representative(id).sequenceNumber) |
| 166 | { |
| 167 | // Invalid sequenced operation. |
| 168 | // @todo quick fix for now. Proper fix needs to choose representative with higher |
| 169 | // sequence number during dependency analysis. |
| 170 | assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString); |
| 171 | sequencedExpressions.insert(std::make_pair(seqNr, id)); |
| 172 | } |
| 173 | |
| 174 | // Perform all operations on storage and memory in order, if they are needed. |
| 175 | for (auto const& seqAndId: sequencedExpressions) |
| 176 | if (!m_classPositions.count(seqAndId.second)) |
| 177 | generateClassElement(seqAndId.second, true); |
| 178 | |
| 179 | // generate the target stack elements |
| 180 | for (auto const& targetItem: m_targetStack) |
| 181 | { |
| 182 | if (m_stack.count(targetItem.first) && m_stack.at(targetItem.first) == targetItem.second) |
| 183 | continue; // already there |
| 184 | generateClassElement(targetItem.second); |
| 185 | assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, ""); |
| 186 | if (m_classPositions[targetItem.second].count(targetItem.first)) |
| 187 | continue; |
| 188 | langutil::DebugData::ConstPtr debugData; |
| 189 | if (m_expressionClasses.representative(targetItem.second).item) |
| 190 | debugData = m_expressionClasses.representative(targetItem.second).item->debugData(); |
| 191 | int position = classElementPosition(targetItem.second); |
| 192 | if (position < targetItem.first) |
| 193 | // it is already at its target, we need another copy |
| 194 | appendDup(position, debugData); |
| 195 | else |
| 196 | appendOrRemoveSwap(position, debugData); |
no test coverage detected