19
19
* Transformation of a Yul AST into a control flow graph.
20
20
*/
21
21
22
+ #include " SSAControlFlowGraph.h"
23
+
24
+
22
25
#include < libyul/backends/evm/SSAControlFlowGraphBuilder.h>
23
26
24
27
#include < libyul/backends/evm/ControlFlow.h>
@@ -52,28 +55,28 @@ SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder(
52
55
AsmAnalysisInfo const & _analysisInfo,
53
56
ControlFlowSideEffectsCollector const & _sideEffects,
54
57
Dialect const & _dialect,
55
- bool _keepLiteralAssignments
58
+ bool _literalsAsPushConstants
56
59
):
57
60
m_controlFlow (_controlFlow),
58
61
m_graph (_graph),
59
62
m_info (_analysisInfo),
60
63
m_sideEffects (_sideEffects),
61
64
m_dialect (_dialect),
62
- m_keepLiteralAssignments (_keepLiteralAssignments )
65
+ m_literalsAsPushConstants (_literalsAsPushConstants )
63
66
{
64
67
}
65
68
66
69
std::unique_ptr<ControlFlow> SSAControlFlowGraphBuilder::build (
67
70
AsmAnalysisInfo const & _analysisInfo,
68
71
Dialect const & _dialect,
69
72
Block const & _block,
70
- bool _keepLiteralAssignments
73
+ bool _literalsAsPushConstants
71
74
)
72
75
{
73
76
ControlFlowSideEffectsCollector sideEffects (_dialect, _block);
74
77
75
78
auto controlFlow = std::make_unique<ControlFlow>();
76
- SSAControlFlowGraphBuilder builder (*controlFlow, *controlFlow->mainGraph , _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments );
79
+ SSAControlFlowGraphBuilder builder (*controlFlow, *controlFlow->mainGraph , _analysisInfo, sideEffects, _dialect, _literalsAsPushConstants );
77
80
builder.m_currentBlock = controlFlow->mainGraph ->makeBlock (debugDataOf (_block));
78
81
builder.sealBlock (builder.m_currentBlock );
79
82
builder (_block);
@@ -211,10 +214,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable()
211
214
}
212
215
}
213
216
214
- void SSAControlFlowGraphBuilder::buildFunctionGraph (
215
- Scope::Function const * _function,
216
- FunctionDefinition const * _functionDefinition
217
- )
217
+ void SSAControlFlowGraphBuilder::buildFunctionGraph (Scope::Function const * _function, FunctionDefinition const * _functionDefinition)
218
218
{
219
219
m_controlFlow.functionGraphs .emplace_back (std::make_unique<SSACFG>());
220
220
auto & cfg = *m_controlFlow.functionGraphs .back ();
@@ -240,7 +240,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
240
240
cfg.arguments = arguments;
241
241
cfg.returns = returns;
242
242
243
- SSAControlFlowGraphBuilder builder (m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments );
243
+ SSAControlFlowGraphBuilder builder (m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_literalsAsPushConstants );
244
244
builder.m_currentBlock = cfg.entry ;
245
245
builder.m_functionDefinitions = m_functionDefinitions;
246
246
for (auto && [var, varId]: cfg.arguments )
@@ -255,6 +255,19 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
255
255
builder.cleanUnreachable ();
256
256
}
257
257
258
+ SSACFG::ValueId SSAControlFlowGraphBuilder::moveLiteralToVariable (SSACFG::ValueId const _value)
259
+ {
260
+ yulAssert (!m_literalsAsPushConstants);
261
+ yulAssert (m_graph.isLiteralValue (_value));
262
+ SSACFG::Operation assignment{
263
+ .outputs = {m_graph.newVariable (m_currentBlock)},
264
+ .kind = SSACFG::LiteralAssignment{},
265
+ .inputs = {_value}
266
+ };
267
+ currentBlock ().operations .emplace_back (assignment);
268
+ return assignment.outputs .back ();
269
+ }
270
+
258
271
void SSAControlFlowGraphBuilder::operator ()(ExpressionStatement const & _expressionStatement)
259
272
{
260
273
auto const * functionCall = std::get_if<FunctionCall>(&_expressionStatement.expression );
@@ -541,16 +554,8 @@ void SSAControlFlowGraphBuilder::assign(std::vector<std::reference_wrapper<Scope
541
554
542
555
for (auto const & [var, value]: ranges::zip_view (_variables, rhs))
543
556
{
544
- if (m_keepLiteralAssignments && m_graph.isLiteralValue (value))
545
- {
546
- SSACFG::Operation assignment{
547
- .outputs = {m_graph.newVariable (m_currentBlock)},
548
- .kind = SSACFG::LiteralAssignment{},
549
- .inputs = {value}
550
- };
551
- currentBlock ().operations .emplace_back (assignment);
552
- writeVariable (var, m_currentBlock, assignment.outputs .back ());
553
- }
557
+ if (!m_literalsAsPushConstants && m_graph.isLiteralValue (value))
558
+ writeVariable (var, m_currentBlock, moveLiteralToVariable (value));
554
559
else
555
560
writeVariable (var, m_currentBlock, value);
556
561
}
@@ -567,7 +572,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
567
572
SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData , builtin, _call}, {}};
568
573
for (auto && [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse)
569
574
if (!builtin.literalArgument (idx).has_value ())
570
- result.inputs .emplace_back (std::visit (*this , arg));
575
+ {
576
+ if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
577
+ {
578
+ auto const lit = m_graph.newLiteral (debugDataOf (currentBlock ()), std::get<Literal>(arg).value .value ());
579
+ result.inputs .emplace_back (moveLiteralToVariable (lit));
580
+ }
581
+ else
582
+ result.inputs .emplace_back (std::visit (*this , arg));
583
+ }
571
584
for (size_t i = 0 ; i < builtin.numReturns ; ++i)
572
585
result.outputs .emplace_back (m_graph.newVariable (m_currentBlock));
573
586
canContinue = builtin.controlFlowSideEffects .canContinue ;
@@ -582,7 +595,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
582
595
canContinue = m_sideEffects.functionSideEffects ().at (definition).canContinue ;
583
596
SSACFG::Operation result{{}, SSACFG::Call{debugDataOf (_call), function, _call, canContinue}, {}};
584
597
for (auto const & arg: _call.arguments | ranges::views::reverse)
585
- result.inputs .emplace_back (std::visit (*this , arg));
598
+ {
599
+ if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
600
+ {
601
+ auto const lit = m_graph.newLiteral (debugDataOf (currentBlock ()), std::get<Literal>(arg).value .value ());
602
+ result.inputs .emplace_back (moveLiteralToVariable (lit));
603
+ }
604
+ else
605
+ result.inputs .emplace_back (std::visit (*this , arg));
606
+ }
586
607
for (size_t i = 0 ; i < function.numReturns ; ++i)
587
608
result.outputs .emplace_back (m_graph.newVariable (m_currentBlock));
588
609
return result;
0 commit comments