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

'maximum recursion depth exceeded' while finalizing a large function #74

Open
eliben opened this Issue Apr 25, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@eliben
Copy link
Contributor

eliben commented Apr 25, 2017

I'm generating a fairly large function using PeachPy (compiling from another language). When the function has a large number of labels it seems that the finalization invoked when RETURN is called is blowing the Python style.

Part of the stack trace:

  File "function.py", line 549, in analyze_reachability
    output_block.analyze_reachability()
  File "function.py", line 549, in analyze_reachability
    output_block.analyze_reachability()
  File "function.py", line 549, in analyze_reachability
    output_block.analyze_reachability()
  File "function.py", line 549, in analyze_reachability
    output_block.analyze_reachability()

FWIW I'm not even using the register allocation features, all my registers are managed manually. A silly reproducer below:

import peachpy
import peachpy.x86_64

x = peachpy.Argument(peachpy.int64_t)
y = peachpy.Argument(peachpy.int64_t)

with peachpy.x86_64.Function("Times", (x, y), peachpy.int64_t) as asm_function:
    reg_x = peachpy.x86_64.rax
    reg_y = peachpy.x86_64.rbx
    reg_accum = peachpy.x86_64.rcx

    peachpy.x86_64.LOAD.ARGUMENT(reg_x, x)
    peachpy.x86_64.LOAD.ARGUMENT(reg_y, y)
    peachpy.x86_64.MOV(reg_accum, 0)

    for i in range(1000):
      loop_start_label = peachpy.x86_64.Label('loop_start{}'.format(i))
      loop_end_label = peachpy.x86_64.Label('loop_end{}'.format(i))

      peachpy.x86_64.CMP(reg_y, 0)
      peachpy.x86_64.JE(loop_end_label)
      peachpy.x86_64.LABEL(loop_start_label)      # bind the label
      peachpy.x86_64.ADD(reg_accum, reg_x)
      peachpy.x86_64.SUB(reg_y, 1)
      peachpy.x86_64.JG(loop_start_label)
      peachpy.x86_64.LABEL(loop_end_label)        # bind the label

    peachpy.x86_64.RETURN(reg_accum)

abi = peachpy.x86_64.abi.detect()
encoded_function = asm_function.finalize(abi).encode()
python_function = encoded_function.load()

print(encoded_function.format())
code = python_function.code_segment

fname = '/tmp/ppout.bin'
with open(fname, 'wb') as f:
    f.write(code)

print('Wrote code to file [{0}]: {1}'.format(fname, code))

# The JIT call
print(python_function(3, 4))
@Maratyszcza

This comment has been minimized.

Copy link
Owner

Maratyszcza commented Apr 27, 2017

PeachPy wasn't designed as a backend for other languages, and it doesn't scale to large number of instructions/branches/labels. In particular, most analysis passes are implemented as recursive functions, where recursion depth can be as high as the number of basic blocks. Rewriting these recursive functions as while loops would likely solve your problem, but its not a high-priority task for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment