2424using namespace BinaryNinja ;
2525using namespace std ;
2626
27+ namespace {
28+
29+ // Memoizes the reverse (LLIL-SSA -> MLIL) expr lookups for one LLIL-SSA function.
30+ // The same LLIL-SSA expr is reached from many MLIL exprs, and a reverse query
31+ // derives its result by walking the LLIL-SSA use-def graph rather than reading a
32+ // stored table, so repeating it for each recurrence is what dominates a
33+ // whole-function map build.
34+ class ReverseExprMemo
35+ {
36+ Ref<LowLevelILFunction> m_llilSsa;
37+ std::unordered_map<size_t , std::pair<size_t , std::set<size_t >>> m_entries;
38+
39+ public:
40+ explicit ReverseExprMemo (Ref<LowLevelILFunction> llilSsa) : m_llilSsa(std::move(llilSsa)) {}
41+
42+ // The MLIL expr that `llilSsaExpr` maps to directly, paired with every MLIL expr it maps to.
43+ const std::pair<size_t , std::set<size_t >>& Get (size_t llilSsaExpr)
44+ {
45+ auto entry = m_entries.find (llilSsaExpr);
46+ if (entry == m_entries.end ())
47+ {
48+ entry = m_entries.emplace (llilSsaExpr,
49+ std::make_pair (m_llilSsa->GetMediumLevelILExprIndex (llilSsaExpr), m_llilSsa->GetMediumLevelILExprIndexes (llilSsaExpr))
50+ ).first ;
51+ }
52+ return entry->second ;
53+ }
54+ };
55+
56+ } // unnamed namespace
57+
2758
2859ILSourceLocation::ILSourceLocation (const struct MediumLevelILInstruction & instr):
2960 address(instr.address), sourceOperand(instr.sourceOperand), valid(true ),
@@ -117,12 +148,14 @@ std::unordered_map<size_t /* llil ssa */, size_t /* mlil */> MediumLevelILFuncti
117148std::vector<BNExprMapInfo> MediumLevelILFunction::GetLLILSSAToMLILExprMap (bool fromTranslation)
118149{
119150 std::vector<BNExprMapInfo> result;
151+
120152 if (fromTranslation)
121153 {
122154 // TODO: Handle LLIL SSA -> MLIL mappings in case someone is brave enough to try
123155 // lifting LLILSSA->MLIL themselves instead of an MLIL->MLIL translation
124156 // (which is the only one I've seen people do so far)
125157
158+ ReverseExprMemo reverse (m_translationData->copyingFunction ->GetLowLevelIL ()->GetSSAForm ());
126159 for (auto & [oldExprIndex, newExprIndices]: m_translationData->mlilToMlilExprMap )
127160 {
128161 // Look up the LLIL SSA expression for the old expr in its function
@@ -132,8 +165,7 @@ std::vector<BNExprMapInfo> MediumLevelILFunction::GetLLILSSAToMLILExprMap(bool f
132165 auto oldLLILSSAIndices = m_translationData->copyingFunction ->GetLowLevelILExprIndexes (oldExprIndex);
133166 for (auto & oldLLILSSAIndex: oldLLILSSAIndices)
134167 {
135- size_t oldReverseDirect = m_translationData->copyingFunction ->GetLowLevelIL ()->GetSSAForm ()->GetMediumLevelILExprIndex (oldLLILSSAIndex);
136- auto oldReverseAll = m_translationData->copyingFunction ->GetLowLevelIL ()->GetSSAForm ()->GetMediumLevelILExprIndexes (oldLLILSSAIndex);
168+ const auto & [oldReverseDirect, oldReverseAll] = reverse.Get (oldLLILSSAIndex);
137169 for (auto & [newExprIndex, newDirect]: newExprIndices)
138170 {
139171 BNExprMapInfo info;
@@ -150,6 +182,7 @@ std::vector<BNExprMapInfo> MediumLevelILFunction::GetLLILSSAToMLILExprMap(bool f
150182 }
151183 else
152184 {
185+ ReverseExprMemo reverse (GetLowLevelIL ()->GetSSAForm ());
153186 for (auto & block: GetBasicBlocks ())
154187 {
155188 for (size_t instrIndex = block->GetStart (); instrIndex < block->GetEnd (); instrIndex++)
@@ -160,8 +193,7 @@ std::vector<BNExprMapInfo> MediumLevelILFunction::GetLLILSSAToMLILExprMap(bool f
160193 auto llilSSAIndices = GetLowLevelILExprIndexes (expr.exprIndex );
161194 for (auto & llilSSAIndex: llilSSAIndices)
162195 {
163- size_t reverseDirect = GetLowLevelIL ()->GetSSAForm ()->GetMediumLevelILExprIndex (llilSSAIndex);
164- auto reverseAll = GetLowLevelIL ()->GetSSAForm ()->GetMediumLevelILExprIndexes (llilSSAIndex);
196+ const auto & [reverseDirect, reverseAll] = reverse.Get (llilSSAIndex);
165197
166198 BNExprMapInfo info;
167199 info.lowerIndex = llilSSAIndex;
0 commit comments