Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix[venom]: fix _stack_reorder() routine #4220

Merged
merged 13 commits into from
Oct 4, 2024
29 changes: 26 additions & 3 deletions vyper/venom/venom_to_assembly.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections import Counter
from bisect import insort
from collections import Counter, defaultdict
from typing import Any

from vyper.exceptions import CompilerPanic, StackTooDeep
Expand Down Expand Up @@ -210,11 +211,19 @@ def _stack_reorder(

counts = Counter(stack_ops)

positions: dict[IROperand, list[int]] = defaultdict(lambda: [])
for op in stack_ops:
positions[op] = []
for i in range(counts[op]):
positions[op].append(stack.get_depth(op, i + 1))

for i in range(stack_ops_count):
op = stack_ops[i]
final_stack_depth = -(stack_ops_count - i - 1)
depth = stack.get_depth(op, counts[op]) # type: ignore
counts[op] -= 1
depth = positions[op].pop() # type: ignore
assert depth not in range(
-stack_ops_count + 1, final_stack_depth
), f"{depth} : ({-stack_ops_count - 1}, {final_stack_depth})"

if depth == StackModel.NOT_IN_STACK:
raise CompilerPanic(f"Variable {op} not in stack")
Expand All @@ -225,9 +234,23 @@ def _stack_reorder(
if op == stack.peek(final_stack_depth):
continue

if len(positions[stack.peek(0)]) != 0:
positions[stack.peek(0)].remove(0)
insort(positions[stack.peek(0)], depth)

cost += self.swap(assembly, stack, depth)
if final_stack_depth in positions[stack.peek(final_stack_depth)]:
positions[stack.peek(final_stack_depth)].remove(final_stack_depth)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the positions[stack.peek(final_stack_depth)] can be factored out into a variable

positions[stack.peek(final_stack_depth)].insert(0, 0)
else:
positions[stack.peek(final_stack_depth)].insert(0, 0)

cost += self.swap(assembly, stack, final_stack_depth)

assert (
len(stack_ops) == 0 or stack._stack[-len(stack_ops) :] == stack_ops
), f"Wrong stack {stack} {stack_ops}"

return cost

def _emit_input_operands(
Expand Down
Loading