Author: David Malcolm <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit