@@ -72,21 +72,21 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement)
72
72
if (auto vars = isSimpleStore (StoreLoadLocation::Storage, _statement))
73
73
{
74
74
ASTModifier::operator ()(_statement);
75
- cxx20::erase_if (m_state.storage , mapTuple ([&](auto && key, auto && value) {
75
+ cxx20::erase_if (m_state.environment . storage , mapTuple ([&](auto && key, auto && value) {
76
76
return
77
77
!m_knowledgeBase.knownToBeDifferent (vars->first , key) &&
78
78
!m_knowledgeBase.knownToBeEqual (vars->second , value);
79
79
}));
80
- m_state.storage [vars->first ] = vars->second ;
80
+ m_state.environment . storage [vars->first ] = vars->second ;
81
81
return ;
82
82
}
83
83
else if (auto vars = isSimpleStore (StoreLoadLocation::Memory, _statement))
84
84
{
85
85
ASTModifier::operator ()(_statement);
86
- cxx20::erase_if (m_state.memory , mapTuple ([&](auto && key, auto && /* value */ ) {
86
+ cxx20::erase_if (m_state.environment . memory , mapTuple ([&](auto && key, auto && /* value */ ) {
87
87
return !m_knowledgeBase.knownToBeDifferentByAtLeast32 (vars->first , key);
88
88
}));
89
- m_state.memory [vars->first ] = vars->second ;
89
+ m_state.environment . memory [vars->first ] = vars->second ;
90
90
return ;
91
91
}
92
92
}
@@ -124,12 +124,11 @@ void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl)
124
124
void DataFlowAnalyzer::operator ()(If& _if)
125
125
{
126
126
clearKnowledgeIfInvalidated (*_if.condition );
127
- unordered_map<YulString, YulString> storage = m_state.storage ;
128
- unordered_map<YulString, YulString> memory = m_state.memory ;
127
+ Environment preEnvironment = m_state.environment ;
129
128
130
129
ASTModifier::operator ()(_if);
131
130
132
- joinKnowledge (storage, memory );
131
+ joinKnowledge (preEnvironment );
133
132
134
133
clearValues (assignedVariableNames (_if.body ));
135
134
}
@@ -141,10 +140,9 @@ void DataFlowAnalyzer::operator()(Switch& _switch)
141
140
set<YulString> assignedVariables;
142
141
for (auto & _case: _switch.cases )
143
142
{
144
- unordered_map<YulString, YulString> storage = m_state.storage ;
145
- unordered_map<YulString, YulString> memory = m_state.memory ;
143
+ Environment preEnvironment = m_state.environment ;
146
144
(*this )(_case.body );
147
- joinKnowledge (storage, memory );
145
+ joinKnowledge (preEnvironment );
148
146
149
147
set<YulString> variables = assignedVariableNames (_case.body );
150
148
assignedVariables += variables;
@@ -225,15 +223,15 @@ void DataFlowAnalyzer::operator()(Block& _block)
225
223
226
224
optional<YulString> DataFlowAnalyzer::storageValue (YulString _key) const
227
225
{
228
- if (YulString const * value = util::valueOrNullptr (m_state.storage , _key))
226
+ if (YulString const * value = util::valueOrNullptr (m_state.environment . storage , _key))
229
227
return *value;
230
228
else
231
229
return nullopt;
232
230
}
233
231
234
232
optional<YulString> DataFlowAnalyzer::memoryValue (YulString _key) const
235
233
{
236
- if (YulString const * value = util::valueOrNullptr (m_state.memory , _key))
234
+ if (YulString const * value = util::valueOrNullptr (m_state.environment . memory , _key))
237
235
return *value;
238
236
else
239
237
return nullopt;
@@ -267,13 +265,13 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
267
265
if (!_isDeclaration)
268
266
{
269
267
// assignment to slot denoted by "name"
270
- m_state.storage .erase (name);
268
+ m_state.environment . storage .erase (name);
271
269
// assignment to slot contents denoted by "name"
272
- cxx20::erase_if (m_state.storage , mapTuple ([&name](auto && /* key */ , auto && value) { return value == name; }));
270
+ cxx20::erase_if (m_state.environment . storage , mapTuple ([&name](auto && /* key */ , auto && value) { return value == name; }));
273
271
// assignment to slot denoted by "name"
274
- m_state.memory .erase (name);
272
+ m_state.environment . memory .erase (name);
275
273
// assignment to slot contents denoted by "name"
276
- cxx20::erase_if (m_state.memory , mapTuple ([&name](auto && /* key */ , auto && value) { return value == name; }));
274
+ cxx20::erase_if (m_state.environment . memory , mapTuple ([&name](auto && /* key */ , auto && value) { return value == name; }));
277
275
}
278
276
}
279
277
@@ -286,9 +284,9 @@ void DataFlowAnalyzer::handleAssignment(set<YulString> const& _variables, Expres
286
284
// On the other hand, if we knew the value in the slot
287
285
// already, then the sload() / mload() would have been replaced by a variable anyway.
288
286
if (auto key = isSimpleLoad (StoreLoadLocation::Memory, *_value))
289
- m_state.memory [*key] = variable;
287
+ m_state.environment . memory [*key] = variable;
290
288
else if (auto key = isSimpleLoad (StoreLoadLocation::Storage, *_value))
291
- m_state.storage [*key] = variable;
289
+ m_state.environment . storage [*key] = variable;
292
290
}
293
291
}
294
292
}
@@ -329,8 +327,8 @@ void DataFlowAnalyzer::clearValues(set<YulString> _variables)
329
327
auto eraseCondition = mapTuple ([&_variables](auto && key, auto && value) {
330
328
return _variables.count (key) || _variables.count (value);
331
329
});
332
- cxx20::erase_if (m_state.storage , eraseCondition);
333
- cxx20::erase_if (m_state.memory , eraseCondition);
330
+ cxx20::erase_if (m_state.environment . storage , eraseCondition);
331
+ cxx20::erase_if (m_state.environment . memory , eraseCondition);
334
332
335
333
// Also clear variables that reference variables to be cleared.
336
334
for (auto const & variableToClear: _variables)
@@ -357,9 +355,9 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block)
357
355
return ;
358
356
SideEffectsCollector sideEffects (m_dialect, _block, &m_functionSideEffects);
359
357
if (sideEffects.invalidatesStorage ())
360
- m_state.storage .clear ();
358
+ m_state.environment . storage .clear ();
361
359
if (sideEffects.invalidatesMemory ())
362
- m_state.memory .clear ();
360
+ m_state.environment . memory .clear ();
363
361
}
364
362
365
363
void DataFlowAnalyzer::clearKnowledgeIfInvalidated (Expression const & _expr)
@@ -368,35 +366,9 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr)
368
366
return ;
369
367
SideEffectsCollector sideEffects (m_dialect, _expr, &m_functionSideEffects);
370
368
if (sideEffects.invalidatesStorage ())
371
- m_state.storage .clear ();
369
+ m_state.environment . storage .clear ();
372
370
if (sideEffects.invalidatesMemory ())
373
- m_state.memory .clear ();
374
- }
375
-
376
- void DataFlowAnalyzer::joinKnowledge (
377
- unordered_map<YulString, YulString> const & _olderStorage,
378
- unordered_map<YulString, YulString> const & _olderMemory
379
- )
380
- {
381
- if (!m_analyzeStores)
382
- return ;
383
- joinKnowledgeHelper (m_state.storage , _olderStorage);
384
- joinKnowledgeHelper (m_state.memory , _olderMemory);
385
- }
386
-
387
- void DataFlowAnalyzer::joinKnowledgeHelper (
388
- std::unordered_map<YulString, YulString>& _this,
389
- std::unordered_map<YulString, YulString> const & _older
390
- )
391
- {
392
- // We clear if the key does not exist in the older map or if the value is different.
393
- // This also works for memory because _older is an "older version"
394
- // of m_state.memory and thus any overlapping write would have cleared the keys
395
- // that are not known to be different inside m_state.memory already.
396
- cxx20::erase_if (_this, mapTuple ([&_older](auto && key, auto && currentValue){
397
- YulString const * oldValue = util::valueOrNullptr (_older, key);
398
- return !oldValue || *oldValue != currentValue;
399
- }));
371
+ m_state.environment .memory .clear ();
400
372
}
401
373
402
374
bool DataFlowAnalyzer::inScope (YulString _variableName) const
@@ -443,3 +415,26 @@ std::optional<YulString> DataFlowAnalyzer::isSimpleLoad(
443
415
return key->name ;
444
416
return {};
445
417
}
418
+
419
+ void DataFlowAnalyzer::joinKnowledge (Environment const & _olderEnvironment)
420
+ {
421
+ if (!m_analyzeStores)
422
+ return ;
423
+ joinKnowledgeHelper (m_state.environment .storage , _olderEnvironment.storage );
424
+ joinKnowledgeHelper (m_state.environment .memory , _olderEnvironment.memory );
425
+ }
426
+
427
+ void DataFlowAnalyzer::joinKnowledgeHelper (
428
+ std::unordered_map<YulString, YulString>& _this,
429
+ std::unordered_map<YulString, YulString> const & _older
430
+ )
431
+ {
432
+ // We clear if the key does not exist in the older map or if the value is different.
433
+ // This also works for memory because _older is an "older version"
434
+ // of m_state.environment.memory and thus any overlapping write would have cleared the keys
435
+ // that are not known to be different inside m_state.environment.memory already.
436
+ cxx20::erase_if (_this, mapTuple ([&_older](auto && key, auto && currentValue){
437
+ YulString const * oldValue = util::valueOrNullptr (_older, key);
438
+ return !oldValue || *oldValue != currentValue;
439
+ }));
440
+ }
0 commit comments