[pypy-commit] pypy libgccjit-backend: Get test_compile_bridge to work
dmalcolm
noreply at buildbot.pypy.org
Mon Dec 22 22:35:09 CET 2014
Author: David Malcolm <dmalcolm at redhat.com>
Branch: libgccjit-backend
Changeset: r75071:c77c1f9355fd
Date: 2014-12-22 16:42 -0500
http://bitbucket.org/pypy/pypy/changeset/c77c1f9355fd/
Log: Get test_compile_bridge to work
diff --git a/rpython/jit/backend/libgccjit/assembler.py b/rpython/jit/backend/libgccjit/assembler.py
--- a/rpython/jit/backend/libgccjit/assembler.py
+++ b/rpython/jit/backend/libgccjit/assembler.py
@@ -23,6 +23,21 @@
self.paramtypes = [assembler.t_jit_frame_ptr,
assembler.t_void_ptr]
+class Function:
+ """
+ Wrapper around a rffi_bindings.Function, for a loop or bridge
+ """
+ def __init__(self, name, rffi_fn):
+ self.name = name
+ self.rffi_fn = rffi_fn
+ self.patchpoints = []
+
+ def new_block(self, name):
+ return self.rffi_fn.new_block(name)
+
+ def new_local(self, type_, name):
+ return self.rffi_fn.new_local(type_, name)
+
class Patchpoint:
"""
We need to be able to patch out the generated code that runs when a
@@ -91,7 +106,12 @@
# this is a:
# struct JITFRAME * (**guard_failure_fn) (struct JITFRAME *, void *)
# i.e. one extra level of indirection.
- fn_ptr_ptr = result.get_global(self.fn_ptr_name)
+ self.fn_ptr_ptr = result.get_global(self.fn_ptr_name)
+
+ self.set_handler(handler)
+
+ def set_handler(self, handler):
+ print('set_handler(%r)' % handler)
# We want to write the equivalent of:
# (*fn_ptr_ptr) = handler;
@@ -102,7 +122,7 @@
# We can't directly express the function ptr ptr in lltype,
# so instead pretend we have a (const char **) and a (const char *):
- fn_ptr_ptr = rffi.cast(rffi.CCHARPP, fn_ptr_ptr)
+ fn_ptr_ptr = rffi.cast(rffi.CCHARPP, self.fn_ptr_ptr)
handler = rffi.cast(rffi.CCHARP, handler)
# ...and write through the ptr:
@@ -133,13 +153,18 @@
self.num_anon_loops = 0
self.num_guard_failure_fns = 0
+ self.num_bridges = 0
self.sizeof_signed = rffi.sizeof(lltype.Signed)
- self.patchpoints = []
+ self.label_for_descr = {}
+ self.block_for_label_descr = {}
+ self.function_for_label_descr = {}
+ self.patchpoint_for_descr = {}
+
+ eci = make_eci()
+ self.lib = Library(eci)
def make_context(self):
- eci = make_eci()
- self.lib = Library(eci)
self.ctxt = Context.acquire(self.lib)#self.lib.gcc_jit_context_acquire()
if 0:
self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
@@ -162,7 +187,22 @@
if 0:
self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
r_int(1))
-
+
+ self.t_Signed = self.ctxt.get_int_type(r_int(self.sizeof_signed),
+ r_int(1))
+ self.t_UINT = self.ctxt.get_int_type(r_int(self.sizeof_signed),
+ r_int(0))
+ self.t_float = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_DOUBLE) # FIXME
+ self.t_bool = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_BOOL)
+ self.t_void_ptr = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID_PTR)
+ self.t_void = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID)
+
+ self.u_signed = self.ctxt.new_field(self.t_Signed, "u_signed")
+ self.u_float = self.ctxt.new_field(self.t_float, "u_float")
+ self.t_any = self.ctxt.new_union_type ("any",
+ [self.u_signed,
+ self.u_float])
+
def setup(self, looptoken):
allblocks = self.get_asmmemmgr_blocks(looptoken)
self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
@@ -191,22 +231,69 @@
clt.frame_info.clear() # for now
self.make_context()
- self.t_Signed = self.ctxt.get_int_type(r_int(self.sizeof_signed),
- r_int(1))
- self.t_UINT = self.ctxt.get_int_type(r_int(self.sizeof_signed),
- r_int(0))
- self.t_float = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_DOUBLE) # FIXME
- self.t_bool = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_BOOL)
- self.t_void_ptr = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID_PTR)
- self.t_void = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID)
-
- self.u_signed = self.ctxt.new_field(self.t_Signed, "u_signed")
- self.u_float = self.ctxt.new_field(self.t_float, "u_float")
- self.t_any = self.ctxt.new_union_type ("any",
- [self.u_signed,
- self.u_float])
+ max_args, initial_locs = self.make_JITFRAME_struct(inputargs,
+ operations)
self.lvalue_for_box = {}
+ if not loopname:
+ loopname = 'anonloop_%i' % self.num_anon_loops
+ self.num_anon_loops += 1
+ print(" loopname: %r" % loopname)
+ self.make_function(loopname, inputargs, operations)
+
+ # Ensure that the frame is large enough
+ baseofs = self.cpu.get_baseofs_of_frame_field()
+ clt.frame_info.update_frame_depth(baseofs,
+ max_args)
+
+ self.ctxt.dump_to_file("/tmp/%s.c" % loopname, r_int(1))
+
+ #raise foo
+
+ jit_result = self.ctxt.compile()
+ self.ctxt.release()
+
+ # Patch all patchpoints to their initial handlers:
+ for pp in self.fn.patchpoints:
+ pp.write_initial_handler(jit_result)
+
+ fn_ptr = jit_result.get_code(loopname)
+
+ looptoken._ll_function_addr = fn_ptr
+
+ looptoken.compiled_loop_token._ll_initial_locs = initial_locs
+
+ # FIXME: this leaks the gcc_jit_result
+
+ def assemble_bridge(self, logger, faildescr, inputargs, operations,
+ original_loop_token, log):
+ print('assemble_bridge(%r)' % locals())
+ if not we_are_translated():
+ # Arguments should be unique
+ assert len(set(inputargs)) == len(inputargs)
+
+ self.make_context()
+ max_args, initial_locs = self.make_JITFRAME_struct(inputargs,
+ operations)
+ self.lvalue_for_box = {}
+
+ name = "bridge_%i" % self.num_bridges
+ self.num_bridges += 1
+
+ self.make_function(name, inputargs, operations)
+ self.ctxt.dump_to_file("/tmp/%s.c" % name, r_int(1))
+ jit_result = self.ctxt.compile()
+ self.ctxt.release()
+
+ # Patch all patchpoints to their initial handlers:
+ for pp in self.fn.patchpoints:
+ pp.write_initial_handler(jit_result)
+
+ # Patch the patchpoint for "faildescr" to point to our new code
+ fn_ptr = jit_result.get_code(name)
+ self.patchpoint_for_descr[faildescr].set_handler(fn_ptr)
+
+ def make_JITFRAME_struct(self, inputargs, operations):
#print(jitframe.JITFRAME)
#print(dir(jitframe.JITFRAME))
#print('jitframe.JITFRAME._flds: %r' % jitframe.JITFRAME._flds)
@@ -274,26 +361,24 @@
struct_jit_frame.set_fields (fields)
+ return max_args, initial_locs
+
+ def make_function(self, name, inputargs, operations):
# Make function:
#print(' inputargs: %r' % (inputargs, ))
#jitframe.JITFRAMEINFOPTR
self.loop_params = Params(self)
- if not loopname:
- loopname = 'anonloop_%i' % self.num_anon_loops
- self.num_anon_loops += 1
- print(" loopname: %r" % loopname)
- self.fn = self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_EXPORTED,
- self.t_jit_frame_ptr,
- loopname,
- self.loop_params.paramlist,
- r_int(0))
+ self.fn = Function(name,
+ self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_EXPORTED,
+ self.t_jit_frame_ptr,
+ name,
+ self.loop_params.paramlist,
+ r_int(0)))
self.b_current = self.fn.new_block("initial")
- self.label_for_descr = {}
- self.block_for_label_descr = {}
- # Add an initial comment summarizing the loop
+ # Add an initial comment summarizing the loop or bridge:
text = '\n\tinputargs: %s\n\n' % inputargs
for op in operations:
#print(op)
@@ -302,7 +387,7 @@
#print(repr(op.getopname()))
text += '\t%s\n' % op
self.b_current.add_comment(str(text))
-
+
# Get initial values from input args:
for idx, arg in enumerate(inputargs):
self.b_current.add_comment("inputargs[%i]: %s" % (idx, arg))
@@ -334,39 +419,6 @@
methname = 'emit_%s' % op.getopname()
getattr(self, methname) (op)
- # Ensure that the frame is large enough
- baseofs = self.cpu.get_baseofs_of_frame_field()
- clt.frame_info.update_frame_depth(baseofs,
- max_args)
-
- self.ctxt.dump_to_file("/tmp/%s.c" % loopname, r_int(1))
-
- #raise foo
-
- jit_result = self.ctxt.compile()
- self.ctxt.release()
-
- # Patch all patchpoints to their initial handlers:
- for pp in self.patchpoints:
- pp.write_initial_handler(jit_result)
-
- fn_ptr = jit_result.get_code(loopname)
-
- looptoken._ll_function_addr = fn_ptr
-
- looptoken.compiled_loop_token._ll_initial_locs = initial_locs
-
- # FIXME: this leaks the gcc_jit_result
-
- def assemble_bridge(self, logger, faildescr, inputargs, operations,
- original_loop_token, log):
- print('assemble_bridge(%r)' % locals())
- if not we_are_translated():
- # Arguments should be unique
- assert len(set(inputargs)) == len(inputargs)
-
- raise foo
-
def expr_to_rvalue(self, expr):
"""
print('expr_to_rvalue')
@@ -466,8 +518,27 @@
self.b_current.add_assignment(
self.get_box_as_lvalue(label._args[i]),
tmps[i].as_rvalue())
-
- self.b_current.end_with_jump(self.block_for_label_descr[jumpop.getdescr()])
+
+ print('jumpop.getdescr(): %r' % jumpop.getdescr())
+ dest_fn = self.function_for_label_descr[jumpop.getdescr()]
+ print('dest_fn: %r' % dest_fn)
+ if dest_fn == self.fn:
+ b_dest = self.block_for_label_descr[jumpop.getdescr()]
+ self.b_current.end_with_jump(b_dest)
+ else:
+ # Implement as a tail-call:
+ # Sadly, we need to "import" the fn by name, since it was
+ # created on a different gcc_jit_context.
+ p = Params(self)
+ other_fn = self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_IMPORTED,
+ self.t_jit_frame_ptr,
+ dest_fn.name,
+ p.paramlist,
+ r_int(0))
+ args = [param.as_rvalue()
+ for param in self.loop_params.paramlist]
+ call = self.ctxt.new_call(other_fn, args)
+ self.b_current.end_with_return(call)
def emit_finish(self, resop):
self._impl_write_output_args(self.loop_params, resop._args)
@@ -483,6 +554,7 @@
b_new = self.fn.new_block(str(resop))
self.block_for_label_descr[resop.getdescr()] = b_new
self.label_for_descr[resop.getdescr()] = resop
+ self.function_for_label_descr[resop.getdescr()] = self.fn
self.b_current.end_with_jump(b_new)
self.b_current = b_new
@@ -511,7 +583,8 @@
# Implement it as a tail-call through a function ptr to
# a handler function, allowing patchability
pp = Patchpoint(self)
- self.patchpoints.append(pp)
+ self.fn.patchpoints.append(pp)
+ self.patchpoint_for_descr[resop.getdescr()] = pp
args = [param.as_rvalue()
for param in self.loop_params.paramlist]
call = self.ctxt.new_call_through_ptr (pp.failure_fn_ptr.as_rvalue(),
More information about the pypy-commit
mailing list