Author: David Malcolm <dmalc...@redhat.com>
Branch: libgccjit-backend
Changeset: r74979:cf027885030b
Date: 2014-12-16 10:12 -0500
http://bitbucket.org/pypy/pypy/changeset/cf027885030b/

Log:    Work-in-progress

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
@@ -1,8 +1,14 @@
+from rpython.jit.backend.llsupport import jitframe
 from rpython.jit.backend.llsupport.assembler import BaseAssembler
+from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
+from rpython.jit.backend.llsupport.regalloc import FrameManager
 from rpython.jit.backend.model import CompiledLoopToken
-from rpython.jit.backend.libgccjit.rffi_bindings import make_eci, Library, 
make_param_array
+from rpython.jit.backend.libgccjit.rffi_bindings import make_eci, Library, 
make_param_array, make_field_array, Context, Type
 from rpython.jit.metainterp.history import BoxInt, ConstInt
+from rpython.jit.metainterp.resoperation import *
+from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref, 
cast_object_to_ptr
 from rpython.rtyper.lltypesystem.rffi import *
+from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
 
 class AssemblerLibgccjit(BaseAssembler):
     _regalloc = None
@@ -30,29 +36,36 @@
         self.num_anon_loops = 0
 
         self.make_context()
-        print(self.ctxt)
-        self.t_int = self.lib.gcc_jit_context_get_type(self.ctxt,
-                                                       
self.lib.GCC_JIT_TYPE_INT)
+        self.t_int = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_INT)
+        self.t_void_ptr = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID_PTR)
 
     def make_context(self):
         eci = make_eci()
         self.lib = Library(eci)
-        self.ctxt = self.lib.gcc_jit_context_acquire()
-        self.lib.gcc_jit_context_set_bool_option(self.ctxt,
-                                            
self.lib.GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
-                                            r_int(1))
-        self.lib.gcc_jit_context_set_int_option(self.ctxt,
-                                           
self.lib.GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
-                                           r_int(3))
-        self.lib.gcc_jit_context_set_bool_option(self.ctxt,
-                                            
self.lib.GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
-                                            r_int(1))
-        self.lib.gcc_jit_context_set_bool_option(self.ctxt,
-                                            
self.lib.GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
-                                            r_int(1))
-        self.lib.gcc_jit_context_set_bool_option(self.ctxt,
-                                            
self.lib.GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
-                                            r_int(1))
+        self.ctxt = 
Context.acquire(self.lib)#self.lib.gcc_jit_context_acquire()
+        
self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
+                                  r_int(1))
+        self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DEBUGINFO,
+                                  r_int(1))
+        
self.ctxt.set_int_option(self.lib.GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
+                                 r_int(3))
+        
self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
+                                  r_int(1))
+        self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
+                                  r_int(1))
+        
self.ctxt.set_bool_option(self.lib.GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
+                                  r_int(1))
+        
+    def setup(self, looptoken):
+        allblocks = self.get_asmmemmgr_blocks(looptoken)
+        self.datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr,
+                                                        allblocks)
+
+    def get_asmmemmgr_blocks(self, looptoken):
+        clt = looptoken.compiled_loop_token
+        if clt.asmmemmgr_blocks is None:
+            clt.asmmemmgr_blocks = []
+        return clt.asmmemmgr_blocks
 
     def assemble_loop(self, inputargs, operations, looptoken, log,
                       loopname, logger):
@@ -62,10 +75,94 @@
         looptoken.compiled_loop_token = clt
         clt._debug_nbargs = len(inputargs)
 
+        self.setup(looptoken)
+
+        frame_info = self.datablockwrapper.malloc_aligned(
+            jitframe.JITFRAMEINFO_SIZE, alignment=64) #WORD)
+        clt.frame_info = rffi.cast(jitframe.JITFRAMEINFOPTR, frame_info)
+        clt.allgcrefs = []
+        clt.frame_info.clear() # for now
+
+        self.lvalue_for_box = {}
+
+        print(jitframe.JITFRAME)
+        print(dir(jitframe.JITFRAME))
+        print('jitframe.JITFRAME._flds: %r' % jitframe.JITFRAME._flds)
+
+        # For now, build a "struct jit_frame".
+        # This will have the fields of jitframe, but instead of 
+        # jf_frame, we'll have any input and output boxes:
+        visible_boxes = []
+        for arg in inputargs:
+            visible_boxes.append(arg)
+        for op in operations:
+            if op.getopname() == 'finish':
+                for arg in op._args:
+                    if arg not in visible_boxes:
+                        visible_boxes.append(arg)
+        print('visible_boxes: %r' % visible_boxes)
+
+        fields = []
+        def make_field(name, jit_type):
+            field = self.ctxt.new_field(jit_type,name)
+            fields.append(field)
+            return field
+        make_field('jfi_frame_depth', self.t_int)
+        make_field('jfi_frame_size', self.t_int)
+
+        t_JITFRAMEINFO = (
+            self.ctxt.new_struct_type ("JITFRAMEINFO",
+                                       fields).as_type())
+
+        t_JITFRAMEINFOPTR = t_JITFRAMEINFO.get_pointer()
+
+        struct_jit_frame = self.ctxt.new_opaque_struct ("JITFRAME")
+
+        t_jit_frame_ptr = struct_jit_frame.as_type().get_pointer()
+
+        fields = []
+        # FIXME: Does the GCStruct implicitly add any fields?
+        # If I put this here, then the arguments appear to be written to the
+        # place where I expect:
+        make_field('hack_rtti', self.t_void_ptr)
+        make_field('jf_frame_info', t_JITFRAMEINFOPTR)
+        self.field_jf_descr = make_field('jf_descr', self.t_void_ptr)
+        make_field('jf_force_descr', self.t_void_ptr)
+        make_field('jf_gcmap', self.t_void_ptr)
+        make_field('jf_extra_stack_depth', self.t_int)
+        make_field('jf_savedata', self.t_void_ptr)
+        make_field('jf_guard_exc', self.t_void_ptr)
+        make_field('jf_forward', t_jit_frame_ptr)
+        # jf_frame:
+        self.field_for_box = {}
+        locs = []
+        #loc = jitframe.getofs('jf_frame')
+        for loc, box in enumerate(visible_boxes):
+            field = make_field(str(box), self.t_int)
+            locs.append(loc) # hack!
+            self.field_for_box[box] = field
+
+        struct_jit_frame.set_fields (fields)
+
         # Make function:
-        self.lvalue_for_box = {}
         print('  inputargs: %r' % (inputargs, ))
+        #jitframe.JITFRAMEINFOPTR
         params = []
+
+        self.param_frame = self.ctxt.new_param(t_jit_frame_ptr, "jitframe")
+        params.append(self.param_frame)
+
+        self.param_addr = self.ctxt.new_param(self.t_void_ptr, "addr")
+        params.append(self.param_addr)
+
+        # For now, generate lvalues for the "visible boxes" directly as
+        # field lookups within the jit_frame:
+        for box in visible_boxes:
+            self.lvalue_for_box[box] = (
+                self.param_frame.as_rvalue().
+                  dereference_field (self.field_for_box[box]))
+
+        """
         for arg in inputargs:
             param_name = str2charp(str(arg))
             param = self.lib.gcc_jit_context_new_param(self.ctxt,
@@ -75,56 +172,44 @@
             self.lvalue_for_box[arg] = self.lib.gcc_jit_param_as_lvalue(param)
             free_charp(param_name)
             params.append(param)
+        """
         
         print("loopname: %r" % loopname)
         if not loopname:
             loopname = 'anonloop_%i' % self.num_anon_loops
             self.num_anon_loops += 1
-        fn_name = str2charp(loopname)
-        param_array = make_param_array(self.lib, params)
-        self.fn = self.lib.gcc_jit_context_new_function(self.ctxt,
-                                                        
self.lib.null_location_ptr,
-                                                        
self.lib.GCC_JIT_FUNCTION_EXPORTED,
-                                                        self.t_int,
-                                                        fn_name,
-                                                        r_int(len(params)),
-                                                        param_array,
-                                                        r_int(0))
-        lltype.free(param_array, flavor='raw')
-        free_charp(fn_name)
+        self.fn = self.ctxt.new_function(self.lib.GCC_JIT_FUNCTION_EXPORTED,
+                                         t_jit_frame_ptr, # self.t_int,
+                                         loopname,
+                                         params,
+                                         r_int(0))
 
-        self.b_current = self.lib.gcc_jit_function_new_block(self.fn, NULL)
+        self.b_current = self.fn.new_block()
 
         for op in operations:
-            """
             print(op)
             print(type(op))
             print(dir(op))
             print(repr(op.getopname()))
-            """
             # Add a comment describing this ResOperation
-            comment_text = str2charp(str(op))
-            self.lib.gcc_jit_block_add_comment(self.b_current,
-                                               self.lib.null_location_ptr,
-                                               comment_text)
-            free_charp(comment_text)
+            self.b_current.add_comment(str(op))
 
             # Compile the operation itself...
-            methname = '_on_%s' % op.getopname()
+            methname = '_emit_%s' % op.getopname()
             getattr(self, methname) (op)
 
-        jit_result = self.lib.gcc_jit_context_compile(self.ctxt)
-        self.lib.gcc_jit_context_release(self.ctxt)
-        if not jit_result:
-            # FIXME: get error from context
-            raise Exception("jit_result is NULL")
+        
+        self.ctxt.dump_to_file("/tmp/foo.c", r_int(1))
 
-        fn_name = str2charp(loopname)
-        fn_ptr = self.lib.gcc_jit_result_get_code(jit_result, fn_name)
-        free_charp(fn_name)
+        jit_result = self.ctxt.compile()
+        self.ctxt.release()
+
+        fn_ptr = jit_result.get_code(loopname)
 
         looptoken._ll_function_addr = fn_ptr
 
+        looptoken.compiled_loop_token._ll_initial_locs = locs
+        
         # FIXME: this leaks the gcc_jit_result
 
     def expr_to_rvalue(self, expr):
@@ -138,24 +223,20 @@
         """
 
         if isinstance(expr, BoxInt):
-            return 
self.lib.gcc_jit_lvalue_as_rvalue(self.get_box_as_lvalue(expr))
+            return self.get_box_as_lvalue(expr).as_rvalue()
         elif isinstance(expr, ConstInt):
             #print('value: %r' % expr.value)
             #print('type(value): %r' % type(expr.value))
-            return self.lib.gcc_jit_context_new_rvalue_from_int(self.ctxt,
-                                                                self.t_int,
-                                                                
r_int(expr.value))
+            return self.ctxt.new_rvalue_from_int(self.t_int,
+                                                 r_int(expr.value))
         raise ValueError('unhandled expr: %s' % expr)
 
     def get_box_as_lvalue(self, box):
         if box not in self.lvalue_for_box:
-            local_name = str2charp(str(box))
+            raise foo
             self.lvalue_for_box[box] = (
-                self.lib.gcc_jit_function_new_local(self.fn,
-                                                    self.lib.null_location_ptr,
-                                                    self.t_int, # FIXME: use 
correct type
-                                                    local_name))
-            free_charp(local_name)
+                self.fn.new_local(self.t_int, # FIXME: use correct type
+                                  local_name))
         return self.lvalue_for_box[box]
 
     def expr_to_lvalue(self, expr):
@@ -173,7 +254,7 @@
 
     # Handling of specific ResOperation subclasses
 
-    def _on_int_add(self, op):
+    def _emit_int_add(self, op):
         """
         print(op._arg0)
         print(op._arg1)
@@ -185,24 +266,21 @@
         lvalres = self.expr_to_lvalue(op.result)
 
         op_add = (
-            self.lib.gcc_jit_context_new_binary_op(self.ctxt,
-                                                   self.lib.null_location_ptr,
-                                                   
self.lib.GCC_JIT_BINARY_OP_PLUS,
-                                                   self.t_int,
-                                                   rval0, rval1))
-        
#self.lib.gcc_jit_object_get_debug_string(gcc_jit_rvalue_as_object(op_add))
-        self.lib.gcc_jit_block_add_assignment(self.b_current,
-                                              self.lib.null_location_ptr,
-                                              lvalres,
-                                              op_add)
+            self.ctxt.new_binary_op(self.lib.GCC_JIT_BINARY_OP_PLUS,
+                                    self.t_int,
+                                    rval0, rval1))
+        self.b_current.add_assignment(lvalres, op_add)
 
-    def _on_finish(self, op):
-        """
-        print(op.__dict__)
-        """
-        # FIXME: assume just 1-ary FINISH for now
-        assert len(op._args) == 1
-        result = op._args[0]
-        self.lib.gcc_jit_block_end_with_return(self.b_current,
-                                               self.lib.null_location_ptr,
-                                               self.expr_to_rvalue(result))
+    def _emit_finish(self, op):
+        # Write back to the jf_descr:
+        #  "jitframe->jf_descr = op.getdescr();"
+        descr = rffi.cast(lltype.Signed,
+                          cast_instance_to_gcref(op.getdescr()))
+
+        self.b_current.add_assignment(
+            self.param_frame.as_rvalue ().dereference_field (
+                self.field_jf_descr),
+            self.ctxt.new_rvalue_from_ptr (self.t_void_ptr,
+                                           rffi.cast(VOIDP, descr)))
+
+        self.b_current.end_with_return(self.param_frame.as_rvalue ())
diff --git a/rpython/jit/backend/libgccjit/rffi_bindings.py 
b/rpython/jit/backend/libgccjit/rffi_bindings.py
--- a/rpython/jit/backend/libgccjit/rffi_bindings.py
+++ b/rpython/jit/backend/libgccjit/rffi_bindings.py
@@ -351,6 +351,13 @@
             raise Exception("result is NULL")
         return Result(self.lib, inner_result)
 
+    def dump_to_file(self, path, update_locations):
+        path_charp = str2charp(path)
+        self.lib.gcc_jit_context_dump_to_file(self.inner_ctxt,
+                                              path_charp,
+                                              update_locations)
+        free_charp(path_charp)
+
     def get_type(self, r_enum):
         return Type(self.lib,
                     self.lib.gcc_jit_context_get_type(self.inner_ctxt,
@@ -364,13 +371,45 @@
                                                    name_charp)
         free_charp(name_charp)
         return Field(self.lib, field)
+
+    def new_struct_type(self, name, fields):
+        name_charp = str2charp(name)
+        field_array = lltype.malloc(self.lib.FIELD_P_P.TO,
+                                    len(fields),
+                                    flavor='raw') # of maybe gc?
+        for i in range(len(fields)):
+            field_array[i] = fields[i].inner_field
+        inner_struct = (
+            self.lib.gcc_jit_context_new_struct_type(self.inner_ctxt,
+                                                     
self.lib.null_location_ptr,
+                                                     name_charp,
+                                                     r_int(len(fields)),
+                                                     field_array))
+        lltype.free(field_array, flavor='raw')
+        free_charp(name_charp)
+        return Struct(self.lib, inner_struct)
     
+    def new_opaque_struct(self, name):
+        name_charp = str2charp(name)
+        inner_struct = (
+            self.lib.gcc_jit_context_new_opaque_struct(self.inner_ctxt,
+                                                       
self.lib.null_location_ptr,
+                                                       name_charp))
+        free_charp(name_charp)
+        return Struct(self.lib, inner_struct)
+
     def new_rvalue_from_int(self, type_, llvalue):
         return RValue(self.lib,
                       
self.lib.gcc_jit_context_new_rvalue_from_int(self.inner_ctxt,
                                                                    
type_.inner_type,
                                                                    llvalue))
 
+    def new_rvalue_from_ptr(self, type_, llvalue):
+        return RValue(self.lib,
+                      
self.lib.gcc_jit_context_new_rvalue_from_ptr(self.inner_ctxt,
+                                                                   
type_.inner_type,
+                                                                   llvalue))
+
     def new_binary_op(self, op, type_, a, b):
         return RValue(self.lib,
                       self.lib.gcc_jit_context_new_binary_op(self.inner_ctxt,
@@ -415,17 +454,48 @@
         Wrapper.__init__(self, lib)
         self.inner_type = inner_type
 
+    def get_pointer(self):
+        return Type(self.lib,
+                    self.lib.gcc_jit_type_get_pointer(self.inner_type))
 
 class Field(Wrapper):
     def __init__(self, lib, inner_field):
         Wrapper.__init__(self, lib)
         self.inner_field = inner_field
 
+class Struct(Wrapper):
+    def __init__(self, lib, inner_struct):
+        Wrapper.__init__(self, lib)
+        self.inner_struct = inner_struct
+
+    def as_type(self):
+        return Type(self.lib,
+                    self.lib.gcc_jit_struct_as_type(self.inner_struct))
+
+
+    def set_fields(self, fields):
+        field_array = lltype.malloc(self.lib.FIELD_P_P.TO,
+                                    len(fields),
+                                    flavor='raw') # of maybe gc?
+        for i in range(len(fields)):
+            field_array[i] = fields[i].inner_field
+        self.lib.gcc_jit_struct_set_fields(self.inner_struct,
+                                           self.lib.null_location_ptr,
+                                           r_int(len(fields)),
+                                           field_array)
+        lltype.free(field_array, flavor='raw')
+
 class RValue(Wrapper):
     def __init__(self, lib, inner_rvalue):
         Wrapper.__init__(self, lib)
         self.inner_rvalue = inner_rvalue
 
+    def dereference_field(self, field):
+        return LValue(self.lib,
+                      
self.lib.gcc_jit_rvalue_dereference_field(self.inner_rvalue,
+                                                                
self.lib.null_location_ptr,
+                                                                
field.inner_field))
+
 class LValue(Wrapper):
     def __init__(self, lib, inner_lvalue):
         Wrapper.__init__(self, lib)
@@ -458,11 +528,15 @@
         free_charp(name_charp)
         return LValue(self.lib, local)
 
-    def new_block(self, name):
-        name_charp = str2charp(name)
+    def new_block(self, name=None):
+        if name is not None:
+            name_charp = str2charp(name)
+        else:
+            name_charp = NULL
         block = self.lib.gcc_jit_function_new_block(self.inner_function,
                                                     name_charp)
-        free_charp(name_charp)
+        if name_charp:
+            free_charp(name_charp)
         return Block(self.lib, block)
 
 class Block(Wrapper):
@@ -476,6 +550,13 @@
                                               lvalue.inner_lvalue,
                                               rvalue.inner_rvalue)
 
+    def add_comment(self, text):
+        text_charp = str2charp(text)
+        self.lib.gcc_jit_block_add_comment(self.inner_block,
+                                           self.lib.null_location_ptr,
+                                           text_charp)
+        free_charp(text_charp)
+
     def end_with_return(self, rvalue):
         self.lib.gcc_jit_block_end_with_return(self.inner_block,
                                                self.lib.null_location_ptr,
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to