@@ -63,8 +63,8 @@ std::vector<StackTooDeepError> SSACFGEVMCodeTransform::run(
6363 _assembly,
6464 _builtinContext,
6565 functionLabels,
66- *controlFlow.mainGraph ,
67- *_liveness.mainLiveness
66+ *controlFlow.mainGraph () ,
67+ *_liveness.cfgLiveness . front ()
6868 );
6969 if constexpr (debugOutput)
7070 {
@@ -76,17 +76,17 @@ std::vector<StackTooDeepError> SSACFGEVMCodeTransform::run(
7676 std::fflush (nullptr );
7777 }
7878
79- mainCodeTransform (controlFlow.mainGraph ->entry );
79+ mainCodeTransform (controlFlow.mainGraph () ->entry );
8080
8181 std::vector<StackTooDeepError> stackErrors;
8282 if (!mainCodeTransform.m_stackErrors .empty ())
8383 stackErrors = std::move (mainCodeTransform.m_stackErrors );
8484
85- yulAssert (controlFlow.functionGraphMapping .size () == _liveness.functionLiveness .size ());
86- for (size_t functionIndex = 0 ; functionIndex < controlFlow.functionGraphMapping .size (); ++functionIndex)
85+ yulAssert (controlFlow.functionGraphMapping .size () == _liveness.cfgLiveness .size ());
86+ for (size_t functionIndex = 1 ; functionIndex < controlFlow.functionGraphMapping .size (); ++functionIndex)
8787 {
8888 auto const & functionAndGraph = controlFlow.functionGraphMapping [functionIndex];
89- auto const & functionLiveness = _liveness.functionLiveness [functionIndex];
89+ auto const & functionLiveness = _liveness.cfgLiveness [functionIndex];
9090 auto const & [function, functionGraph] = functionAndGraph;
9191 SSACFGEVMCodeTransform functionCodeTransform (
9292 _assembly,
@@ -113,6 +113,8 @@ SSACFGEVMCodeTransform::FunctionLabels SSACFGEVMCodeTransform::registerFunctionL
113113
114114 for (auto const & [_function, _functionGraph]: _controlFlow.functionGraphMapping )
115115 {
116+ if (!_function)
117+ continue ;
116118 std::set<YulString> assignedFunctionNames;
117119 bool nameAlreadySeen = !assignedFunctionNames.insert (_function->name ).second ;
118120 if (_useNamedLabelsForFunctions == UseNamedLabels::YesAndForceUnique)
@@ -147,6 +149,7 @@ SSACFGEVMCodeTransform::SSACFGEVMCodeTransform
147149 m_assemblyCallbacks{
148150 .cfg = &_cfg,
149151 .assembly = &_assembly,
152+ .callSites = &m_stackLayout.callSites ,
150153 .returnLabels = &m_returnLabels
151154 },
152155 m_stackData (m_stackLayout.blockLayouts[m_cfg.entry.value].stackIn),
@@ -183,7 +186,7 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
183186 auto const & blockLayout = m_stackLayout[_block];
184187 assertLayoutCompatibility (m_stack.data (), blockLayout.stackIn );
185188 m_stackData = blockLayout.stackIn ;
186- m_stack = SSACFGStack (m_stackData, m_assemblyCallbacks, {&m_cfg}); // this can set some stuff to junk
189+ m_stack = Stack (m_stackData, m_assemblyCallbacks, {&m_cfg}); // this can set some stuff to junk
187190 // todo assert on all exits that the stack height is fine
188191 yulAssert (static_cast <int >(m_stack.size ()) == m_assembly.stackHeight ());
189192
@@ -196,7 +199,9 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
196199 bool const hasReturnLabel = std::holds_alternative<SSACFG::Call>(operation.kind )
197200 && std::get<SSACFG::Call>(operation.kind ).canContinue ;
198201 if (hasReturnLabel)
202+ {
199203 m_returnLabels[&std::get<SSACFG::Call>(operation.kind ).call .get ()] = m_assembly.newLabelId ();
204+ }
200205
201206 yulAssert (static_cast <int >(m_stack.size ()) == m_assembly.stackHeight ());
202207 // Create required layout for entering the operation.
@@ -209,35 +214,37 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
209214 }, operation.kind );
210215 std::cout << " \t\t " << operationName << " : " << stackToString (m_stack.data (), m_cfg) << " -> " << stackToString (operationStackIn, m_cfg) << std::endl;
211216 }
212- if (false )
217+ /* if (false)
213218 {
214219 std::vector<Slot> requiredStackTop;
215220 if (auto const* call = std::get_if<SSACFG::Call>(&operation.kind))
216221 if (call->canContinue)
222+ {
217223 requiredStackTop.emplace_back(FunctionReturnLabel{&call->call.get()});
224+ }
218225 LivenessAnalysis::LivenessData opLiveOut = m_liveness.operationsLiveOut(_block)[operationIndex];
219226 auto opLiveOutWithoutOutputs = opLiveOut;
220227 for (auto const& output: operation.outputs)
221228 opLiveOutWithoutOutputs.erase(output);
222229 requiredStackTop += operation.inputs;
223230 OperationForwardShuffler<SSACFGStack>::shuffle(m_stack, requiredStackTop, opLiveOutWithoutOutputs, m_junkBlockFinder.blockAllowsAdditionOfJunk(_block));
224-
225231 }
226- else
227- DanielShuffler<SSACFGStack >::shuffle (m_stack, {}, operationStackIn);
232+ else*/
233+ DanielShuffler<Stack<AssemblyCallbacks> >::shuffle (m_stack, {}, operationStackIn);
228234
229235 // Assert that we have the inputs of the operation on stack top.
230236 yulAssert (m_stack.size () >= operation.inputs .size () + (hasReturnLabel ? 1 : 0 ));
231237 for (auto const & [stackEntry, input]: ranges::zip_view (
232238 m_stack | ranges::views::take_last (operation.inputs .size ()),
233239 operation.inputs
234240 ))
235- yulAssert (stackEntry == Slot{ input} );
241+ yulAssert (stackEntry. isValueID () && stackEntry. valueID () == input);
236242 if (hasReturnLabel)
237243 {
238244 auto const returnLabelSlot = *(ranges::rbegin (m_stack.data ()) + static_cast <std::ptrdiff_t >(operation.inputs .size ()));
239245 yulAssert (std::holds_alternative<SSACFG::Call>(operation.kind ));
240- yulAssert (returnLabelSlot == Slot{FunctionReturnLabel{&std::get<SSACFG::Call>(operation.kind ).call .get ()}});
246+ // todo
247+ // yulAssert(returnLabelSlot == Slot{FunctionReturnLabel{&std::get<SSACFG::Call>(operation.kind).call.get()}});
241248 }
242249
243250 yulAssert (
@@ -257,7 +264,7 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
257264 m_stack.data () | ranges::views::take_last (operation.outputs .size ()),
258265 operation.outputs
259266 ))
260- yulAssert (stackEntry == Slot{ output} );
267+ yulAssert (stackEntry. isValueID () && stackEntry. valueID () == output);
261268 yulAssert (
262269 static_cast <int >(m_stack.size ()) == m_assembly.stackHeight (),
263270 fmt::format (" symbolic stack size = {} =/= {} = assembly stack height" , m_stack.size (), m_assembly.stackHeight ())
@@ -285,7 +292,7 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
285292 [&](SSACFG::BasicBlock::ConditionalJump const & _conditionalJump)
286293 {
287294 {
288- yulAssert (m_stack.top () == Slot{ _conditionalJump.condition } );
295+ yulAssert (m_stack.top (). isValueID () && m_stack. top (). valueID () == _conditionalJump.condition );
289296 m_assembly.appendJumpToIf (m_blockLabels[_conditionalJump.nonZero .value ]);
290297 // update symbolic stack by popping the condition
291298 m_stack.pop <false >();
@@ -330,13 +337,20 @@ void SSACFGEVMCodeTransform::operator()(SSACFG::BlockId const _block)
330337 // Need to be able to also swap up return label!
331338 yulAssert (static_cast <size_t >(m_assembly.stackHeight ()) == m_stack.size ());
332339 m_assembly.setStackHeight (m_assembly.stackHeight ()+1 );
333- std::vector<SSACFGStackLayout::Slot> returnSlots;
340+ std::vector<Slot> returnSlots;
341+
342+ // [label, ret1, ret2, ..., retn]
334343 if (!_return.returnValues .empty ())
335344 {
336- returnSlots.assign (_return.returnValues .begin ()+1 , _return.returnValues .end ());
337- returnSlots.emplace_back (_return.returnValues .front ());
345+ returnSlots.reserve (_return.returnValues .size ());
346+ for (std::size_t i = 1 ; i < _return.returnValues .size (); ++i)
347+ returnSlots.emplace_back (Slot::makeValueID (_return.returnValues [i]));
348+ returnSlots.emplace_back (Slot::makeValueID (_return.returnValues .front ()));
349+
338350 shuffleStack (returnSlots);
351+ // stack = [..., label, ret2, ..., retn, ret1]
339352 m_assembly.appendInstruction (evmasm::swapInstruction (static_cast <unsigned >(_return.returnValues .size ())));
353+ // swapN -> stack = [..., ret1, ret2, ..., retn, label]
340354 }
341355 else
342356 shuffleStack (returnSlots);
@@ -400,7 +414,7 @@ void SSACFGEVMCodeTransform::performOperation(SSACFG::Operation const& _operatio
400414 for (size_t i = 0 ; i < _operation.inputs .size (); ++i)
401415 m_stack.pop <false >();
402416 for (auto value: _operation.outputs )
403- m_stack.push <false >(value);
417+ m_stack.push <false >(Slot::makeValueID ( value) );
404418
405419 if constexpr (debugOutput)
406420 std::cout << " -> " << stackToString (m_stack.data (), m_cfg) << std::endl;
@@ -414,7 +428,7 @@ void SSACFGEVMCodeTransform::assertLayoutCompatibility(StackData const& _current
414428 );
415429 for (auto && [index, currentSlot, desiredSlot]: ranges::zip_view (ranges::views::iota (0 ), _current, _desired))
416430 yulAssert (
417- std::holds_alternative<JunkSlot>( desiredSlot) || currentSlot == desiredSlot,
431+ desiredSlot. isJunk ( ) || currentSlot == desiredSlot,
418432 fmt::format (
419433 " stack element mismatch: {} = {}[{}] =/= {}[{}] = {}" ,
420434 slotToString (currentSlot, m_cfg),
0 commit comments