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