[pypy-commit] pypy libgccjit-backend: WIP, sent as https://mail.python.org/pipermail/pypy-dev/2014-December/012947.html
dmalcolm
noreply at buildbot.pypy.org
Wed Dec 17 17:48:26 CET 2014
Author: David Malcolm <dmalcolm at redhat.com>
Branch: libgccjit-backend
Changeset: r74973:2ae9fa4283cd
Date: 2014-12-15 09:57 -0500
http://bitbucket.org/pypy/pypy/changeset/2ae9fa4283cd/
Log: WIP, sent as https://mail.python.org/pipermail/pypy-
dev/2014-December/012947.html
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -99,6 +99,9 @@
def getcpuclassname(backend_name="auto"):
+ # FIXME:
+ return 'rpython.jit.backend.libgccjit.runner', 'CPU'
+
if backend_name == "auto":
backend_name = autodetect()
backend_name = backend_name.replace('_', '-')
diff --git a/rpython/jit/backend/libgccjit/__init__.py b/rpython/jit/backend/libgccjit/__init__.py
new file mode 100644
diff --git a/rpython/jit/backend/libgccjit/cffi_bindings.py b/rpython/jit/backend/libgccjit/cffi_bindings.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/libgccjit/cffi_bindings.py
@@ -0,0 +1,149 @@
+import os
+import re
+from collections import namedtuple
+
+# Hacks:
+INSTALL_PATH = '/home/david/coding-3/gcc-git-jit-pypy/install'
+INCLUDE_DIR = os.path.join(INSTALL_PATH, 'include')
+LIB_DIR = os.path.join(INSTALL_PATH, 'lib')
+BIN_DIR = os.path.join(INSTALL_PATH, 'bin')
+
+def append_to_envvar_path(envvar, path):
+ if envvar in os.environ:
+ os.environ[envvar] = path + ':' + os.environ[envvar]
+ else:
+ os.environ[envvar] = path
+ print('%s=%s' % (envvar, os.environ[envvar]))
+
+# It appears that we need to override os.environ['LD_LIBRARY_PATH']
+# before importing cffi for it to take account of this.
+append_to_envvar_path('LD_LIBRARY_PATH', LIB_DIR)
+# actually, for some reason I get:
+# File "/usr/lib64/python2.7/site-packages/cffi/vengine_cpy.py", line 124, in load_library
+# raise ffiplatform.VerificationError(error)
+# cffi.ffiplatform.VerificationError: importing '/home/david/coding-3/pypy-libgccjit/rpython/jit/backend/libgccjit/__pycache__/_cffi__x5c2f8978xf4274cdc.so': libgccjit.so.0: cannot open shared object file: No such file or directory
+# if LD_LIBRARY_PATH isn't set up before python starts up; issue with imp.load_dynamic ?
+
+# The library requires the correct driver to be in the PATH:
+append_to_envvar_path('PATH', BIN_DIR)
+
+os.system('env')
+
+import cffi
+
+ffi = cffi.FFI()
+
+with open(os.path.join(INCLUDE_DIR, 'libgccjit.h')) as f:
+ libgccjit_h_content = f.read()
+
+def toy_preprocessor(content):
+ """
+ ffi.cdef can't handle preprocessor directives.
+ We only have the idempotency guards and ifdef __cplusplus;
+ strip them out.
+ """
+ State = namedtuple('State', ('line', 'accepting_text'))
+ macros = {}
+ result = [] # list of lines
+ states = [State('default', accepting_text=True)]
+ for line in content.splitlines():
+ if 0:
+ print(repr(line))
+
+ m = re.match('#ifndef\s+(\S+)', line)
+ if m:
+ states.append(State(line,
+ accepting_text=(m.group(1) not in macros)) )
+ continue
+ m = re.match('#ifdef\s+(\S+)', line)
+
+ if m:
+ states.append(State(line,
+ accepting_text=(m.group(1) in macros)) )
+ continue
+
+ m = re.match('#define\s+(\S+)', line)
+ if m:
+ macros[m.group(1)] = ''
+ continue
+
+ m = re.match('#endif\s*', line)
+ if m:
+ states.pop()
+ continue
+
+ if states[-1].accepting_text:
+ result.append(line)
+
+ return '\n'.join(result)
+
+libgccjit_h_content = toy_preprocessor(libgccjit_h_content)
+
+# print(libgccjit_h_content)
+
+ffi.cdef(libgccjit_h_content)
+
+lib = ffi.verify('#include "libgccjit.h"',
+ libraries=['gccjit'],
+ library_dirs=[LIB_DIR],
+ include_dirs=[INCLUDE_DIR])
+
+ctxt = lib.gcc_jit_context_acquire()
+print ctxt
+
+lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
+ 1)
+lib.gcc_jit_context_set_int_option(ctxt,
+ lib.GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
+ 3)
+lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
+ 1)
+lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
+ 1)
+lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
+ 1)
+
+int_type = lib.gcc_jit_context_get_type(ctxt, lib.GCC_JIT_TYPE_INT)
+param = lib.gcc_jit_context_new_param(ctxt, ffi.NULL, int_type, "input")
+fn = lib.gcc_jit_context_new_function(ctxt,
+ ffi.NULL,
+ lib.GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "add_one_to",
+ 1, [param], 0)
+v_res = lib.gcc_jit_function_new_local(fn, ffi.NULL, int_type, "v_res")
+
+b_initial = lib.gcc_jit_function_new_block(fn, "initial")
+
+c_one = lib.gcc_jit_context_new_rvalue_from_int(ctxt, int_type, 1)
+
+op_add = lib.gcc_jit_context_new_binary_op(ctxt, ffi.NULL,
+ lib.GCC_JIT_BINARY_OP_PLUS,
+ int_type,
+ lib.gcc_jit_param_as_rvalue(param),
+ c_one)
+lib.gcc_jit_block_add_assignment(b_initial, ffi.NULL,
+ v_res,
+ op_add)
+
+lib.gcc_jit_block_end_with_return(b_initial, ffi.NULL,
+ lib.gcc_jit_lvalue_as_rvalue(v_res))
+
+jit_result = lib.gcc_jit_context_compile(ctxt)
+
+lib.gcc_jit_context_release(ctxt)
+
+fn_ptr = lib.gcc_jit_result_get_code(jit_result, "add_one_to")
+if not fn_ptr:
+ raise Exception("fn_ptr is NULL")
+print('fn_ptr: %r' % fn_ptr)
+
+fn_result = ffi.cast("int(*)(int)", fn_ptr)(41)
+print('fn_result: %r' % fn_result)
+assert fn_result == 42
+
+lib.gcc_jit_result_release(jit_result)
diff --git a/rpython/jit/backend/libgccjit/rffi_bindings.py b/rpython/jit/backend/libgccjit/rffi_bindings.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/libgccjit/rffi_bindings.py
@@ -0,0 +1,249 @@
+import os
+
+# Hacks:
+INSTALL_PATH = '/home/david/coding-3/gcc-git-jit-pypy/install'
+INCLUDE_DIR = os.path.join(INSTALL_PATH, 'include')
+LIB_DIR = os.path.join(INSTALL_PATH, 'lib')
+BIN_DIR = os.path.join(INSTALL_PATH, 'bin')
+
+def append_to_envvar_path(envvar, path):
+ if envvar in os.environ:
+ os.environ[envvar] = path + ':' + os.environ[envvar]
+ else:
+ os.environ[envvar] = path
+ print('%s=%s' % (envvar, os.environ[envvar]))
+
+# It appears that we need to override os.environ['LD_LIBRARY_PATH']
+# before importing cffi for it to take account of this.
+append_to_envvar_path('LD_LIBRARY_PATH', LIB_DIR)
+# actually, for some reason I get:
+# File "/usr/lib64/python2.7/site-packages/cffi/vengine_cpy.py", line 124, in load_library
+# raise ffiplatform.VerificationError(error)
+# cffi.ffiplatform.VerificationError: importing '/home/david/coding-3/pypy-libgccjit/rpython/jit/backend/libgccjit/__pycache__/_cffi__x5c2f8978xf4274cdc.so': libgccjit.so.0: cannot open shared object file: No such file or directory
+# if LD_LIBRARY_PATH isn't set up before python starts up; issue with imp.load_dynamic ?
+
+# The library requires the correct driver to be in the PATH:
+append_to_envvar_path('PATH', BIN_DIR)
+
+from rpython.rtyper.lltypesystem import rffi
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.lltypesystem.rffi import *
+from rpython.rtyper.lltypesystem import lltype
+
+def make_eci():
+ eci = ExternalCompilationInfo(includes=['libgccjit.h'],
+ include_dirs=[INCLUDE_DIR],
+ libraries=['gccjit'],
+ library_dirs=[LIB_DIR])
+ return eci
+
+class Library:
+ def __init__(self, eci):
+ self.eci = eci
+
+ # Opaque types:
+ self.GCC_JIT_CONTEXT_P = lltype.Ptr(COpaque(name='gcc_jit_context',
+ compilation_info=eci))
+ self.GCC_JIT_RESULT_P = lltype.Ptr(COpaque(name='gcc_jit_result',
+ compilation_info=eci))
+ self.GCC_JIT_TYPE_P = lltype.Ptr(COpaque(name='gcc_jit_type',
+ compilation_info=eci))
+ self.GCC_JIT_LOCATION_P = lltype.Ptr(COpaque(name='gcc_jit_location',
+ compilation_info=eci))
+ self.GCC_JIT_PARAM_P = lltype.Ptr(COpaque(name='gcc_jit_param',
+ compilation_info=eci))
+ self.GCC_JIT_LVALUE_P = lltype.Ptr(COpaque(name='gcc_jit_lvalue',
+ compilation_info=eci))
+ self.GCC_JIT_RVALUE_P = lltype.Ptr(COpaque(name='gcc_jit_rvalue',
+ compilation_info=eci))
+ self.GCC_JIT_FUNCTION_P = lltype.Ptr(COpaque(name='gcc_jit_function',
+ compilation_info=eci))
+ self.GCC_JIT_BLOCK_P = lltype.Ptr(COpaque(name='gcc_jit_block',
+ compilation_info=eci))
+
+ self.PARAM_P_P = lltype.Ptr(lltype.Array(self.GCC_JIT_PARAM_P,
+ hints={'nolength': True}))
+
+ # Entrypoints:
+ for returntype, name, paramtypes in [
+ (self.GCC_JIT_CONTEXT_P,
+ 'gcc_jit_context_acquire', []),
+
+ (lltype.Void,
+ 'gcc_jit_context_release', [self.GCC_JIT_CONTEXT_P]),
+
+ (lltype.Void,
+ 'gcc_jit_context_set_int_option', [self.GCC_JIT_CONTEXT_P,
+ INT, # FIXME: enum gcc_jit_int_option opt,
+ INT]),
+ (lltype.Void,
+ 'gcc_jit_context_set_bool_option', [self.GCC_JIT_CONTEXT_P,
+ INT, # FIXME: enum gcc_jit_bool_option opt,
+ INT]),
+
+ (self.GCC_JIT_RESULT_P,
+ 'gcc_jit_context_compile', [self.GCC_JIT_CONTEXT_P]),
+
+
+ (VOIDP,
+ 'gcc_jit_result_get_code', [self.GCC_JIT_RESULT_P,
+ CCHARP]),
+
+ (lltype.Void,
+ 'gcc_jit_result_release', [self.GCC_JIT_RESULT_P]),
+
+ ############################################################
+ # Types
+ ############################################################
+ (self.GCC_JIT_TYPE_P,
+ 'gcc_jit_context_get_type', [self.GCC_JIT_CONTEXT_P,
+ INT]),
+
+ ############################################################
+ # Constructing functions.
+ ############################################################
+ (self.GCC_JIT_PARAM_P,
+ 'gcc_jit_context_new_param', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_LOCATION_P,
+ self.GCC_JIT_TYPE_P,
+ CCHARP]),
+ (self.GCC_JIT_LVALUE_P,
+ 'gcc_jit_param_as_lvalue', [self.GCC_JIT_PARAM_P]),
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_param_as_rvalue', [self.GCC_JIT_PARAM_P]),
+
+ (self.GCC_JIT_FUNCTION_P,
+ 'gcc_jit_context_new_function', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_LOCATION_P,
+ INT, # enum gcc_jit_function_kind kind,
+ self.GCC_JIT_TYPE_P,
+ CCHARP,
+ INT,
+ self.PARAM_P_P,
+ INT]),
+ (self.GCC_JIT_LVALUE_P,
+ 'gcc_jit_function_new_local', [self.GCC_JIT_FUNCTION_P,
+ self.GCC_JIT_LOCATION_P,
+ self.GCC_JIT_TYPE_P,
+ CCHARP]),
+
+ (self.GCC_JIT_BLOCK_P,
+ 'gcc_jit_function_new_block', [self.GCC_JIT_FUNCTION_P,
+ CCHARP]),
+
+ ############################################################
+ # lvalues, rvalues and expressions.
+ ############################################################
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_lvalue_as_rvalue', [self.GCC_JIT_LVALUE_P]),
+
+ # Integer constants.
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_context_new_rvalue_from_int', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_TYPE_P,
+ INT]),
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_context_zero', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_TYPE_P]),
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_context_one', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_TYPE_P]),
+
+ (self.GCC_JIT_RVALUE_P,
+ 'gcc_jit_context_new_binary_op', [self.GCC_JIT_CONTEXT_P,
+ self.GCC_JIT_LOCATION_P,
+ INT, # enum gcc_jit_binary_op op,
+ self.GCC_JIT_TYPE_P,
+ self.GCC_JIT_RVALUE_P,
+ self.GCC_JIT_RVALUE_P]),
+
+ ############################################################
+ # Statement-creation.
+ ############################################################
+ (lltype.Void,
+ 'gcc_jit_block_add_assignment', [self.GCC_JIT_BLOCK_P,
+ self.GCC_JIT_LOCATION_P,
+ self.GCC_JIT_LVALUE_P,
+ self.GCC_JIT_RVALUE_P]),
+ (lltype.Void,
+ 'gcc_jit_block_end_with_return', [self.GCC_JIT_BLOCK_P,
+ self.GCC_JIT_LOCATION_P,
+ self.GCC_JIT_RVALUE_P]),
+ ]:
+ self.add_entrypoint(returntype, name, paramtypes)
+
+ # Enum values:
+ self.make_enum_values("""GCC_JIT_STR_OPTION_PROGNAME""")
+
+ self.make_enum_values("""GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL""")
+
+ self.make_enum_values("""GCC_JIT_BOOL_OPTION_DEBUGINFO,
+ GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE,
+ GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
+ GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
+ GCC_JIT_BOOL_OPTION_DUMP_SUMMARY,
+ GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
+ GCC_JIT_BOOL_OPTION_SELFCHECK_GC,
+ GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
+ """)
+
+ self.make_enum_values("""GCC_JIT_TYPE_VOID,
+ GCC_JIT_TYPE_VOID_PTR,
+ GCC_JIT_TYPE_BOOL,
+ GCC_JIT_TYPE_CHAR,
+ GCC_JIT_TYPE_SIGNED_CHAR,
+ GCC_JIT_TYPE_UNSIGNED_CHAR,
+ GCC_JIT_TYPE_SHORT,
+ GCC_JIT_TYPE_UNSIGNED_SHORT,
+ GCC_JIT_TYPE_INT,
+ GCC_JIT_TYPE_UNSIGNED_INT,
+ GCC_JIT_TYPE_LONG,
+ GCC_JIT_TYPE_UNSIGNED_LONG,
+ GCC_JIT_TYPE_LONG_LONG,
+ GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
+ GCC_JIT_TYPE_FLOAT,
+ GCC_JIT_TYPE_DOUBLE,
+ GCC_JIT_TYPE_LONG_DOUBLE,
+ GCC_JIT_TYPE_CONST_CHAR_PTR,
+ GCC_JIT_TYPE_SIZE_T,
+ GCC_JIT_TYPE_FILE_PTR,
+ GCC_JIT_TYPE_COMPLEX_FLOAT,
+ GCC_JIT_TYPE_COMPLEX_DOUBLE,
+ GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE""")
+
+ self.make_enum_values("""GCC_JIT_FUNCTION_EXPORTED,
+ GCC_JIT_FUNCTION_INTERNAL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ GCC_JIT_FUNCTION_ALWAYS_INLINE""")
+
+ self.make_enum_values(
+ """
+ GCC_JIT_BINARY_OP_PLUS,
+ GCC_JIT_BINARY_OP_MINUS,
+ GCC_JIT_BINARY_OP_MULT,
+ GCC_JIT_BINARY_OP_DIVIDE,
+ GCC_JIT_BINARY_OP_MODULO,
+ GCC_JIT_BINARY_OP_BITWISE_AND,
+ GCC_JIT_BINARY_OP_BITWISE_XOR,
+ GCC_JIT_BINARY_OP_BITWISE_OR,
+ GCC_JIT_BINARY_OP_LOGICAL_AND,
+ GCC_JIT_BINARY_OP_LOGICAL_OR,
+ GCC_JIT_BINARY_OP_LSHIFT,
+ GCC_JIT_BINARY_OP_RSHIFT
+ """)
+
+ self.null_location_ptr = lltype.nullptr(self.GCC_JIT_LOCATION_P.TO)
+
+
+ def add_entrypoint(self, returntype, name, paramtypes):
+ setattr(self, name,
+ llexternal(name, paramtypes, returntype,
+ compilation_info=self.eci))
+
+ def make_enum_values(self, lines):
+ for value, name in enumerate(lines.split(',')):
+ name = name.strip()
+ if name:
+ setattr(self, name, value)
+
+
diff --git a/rpython/jit/backend/libgccjit/runner.py b/rpython/jit/backend/libgccjit/runner.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/libgccjit/runner.py
@@ -0,0 +1,32 @@
+#from rpython.jit.backend import model
+from rpython.jit.backend.libgccjit.assembler import AssemblerLibgccjit
+from rpython.jit.backend.llsupport.llmodel import AbstractLLCPU
+
+#class CPU(model.AbstractCPU):
+class CPU(AbstractLLCPU):
+ def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
+ gcdescr=None):
+ AbstractLLCPU.__init__(self, rtyper, stats, opts,
+ translate_support_code, gcdescr)
+
+ def setup(self):
+ self.assembler = AssemblerLibgccjit(self)
+
+ def compile_loop(self, inputargs, operations, looptoken,
+ log=True, name='', logger=None):
+ import sys
+ sys.stderr.write('compile_loop:\n')
+ for i, arg in enumerate(inputargs):
+ sys.stderr.write(' arg[%i] = %r\n' % (i, arg))
+ sys.stderr.write(' type(arg[%i]) = %r\n' % (i, type(arg)))
+ for i, op in enumerate(operations):
+ sys.stderr.write(' op[%i] = %r\n' % (i, op))
+ sys.stderr.write(' type(op[%i]) = %r\n' % (i, type(op)))
+ sys.stderr.write(' looptoken: %r\n' % (looptoken, ))
+ sys.stderr.write(' log: %r\n' % (log, ))
+ sys.stderr.write(' name: %r\n' % (name, ))
+ sys.stderr.write(' logger: %r\n' % (logger, ))
+ sys.stderr.write('compile_loop: %r\n' % locals ())
+ #raise NotImplementedError
+ return self.assembler.assemble_loop(inputargs, operations, looptoken, log,
+ name, logger)
diff --git a/rpython/jit/backend/libgccjit/test/__init__.py b/rpython/jit/backend/libgccjit/test/__init__.py
new file mode 100644
diff --git a/rpython/jit/backend/libgccjit/test/test_basic.py b/rpython/jit/backend/libgccjit/test/test_basic.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/libgccjit/test/test_basic.py
@@ -0,0 +1,15 @@
+import py
+from rpython.jit.backend.detect_cpu import getcpuclass
+from rpython.jit.metainterp.test import support, test_ajit
+
+class JitLibgccjitMixin(support.LLJitMixin):
+ type_system = 'lltype'
+ CPUClass = getcpuclass()
+
+ def check_jumps(self, maxcount):
+ pass
+
+class TestBasic(JitLibgccjitMixin, test_ajit.BaseLLtypeTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_basic.py
+ pass
diff --git a/rpython/jit/backend/libgccjit/test/test_rffi_bindings.py b/rpython/jit/backend/libgccjit/test/test_rffi_bindings.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/libgccjit/test/test_rffi_bindings.py
@@ -0,0 +1,160 @@
+
+import py
+import sys
+from rpython.rtyper.lltypesystem.rffi import *
+from rpython.rtyper.lltypesystem.rffi import _keeper_for_type # crap
+from rpython.rlib.rposix import get_errno, set_errno
+from rpython.translator.c.test.test_genc import compile as compile_c
+from rpython.rtyper.lltypesystem.lltype import Signed, Ptr, Char, malloc
+from rpython.rtyper.lltypesystem import lltype
+from rpython.translator import cdir
+from rpython.tool.udir import udir
+from rpython.rtyper.test.test_llinterp import interpret
+from rpython.annotator.annrpython import RPythonAnnotator
+from rpython.rtyper.rtyper import RPythonTyper
+from rpython.translator.backendopt.all import backend_optimizations
+from rpython.translator.translator import graphof
+from rpython.conftest import option
+from rpython.flowspace.model import summary
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rlib.rarithmetic import r_singlefloat
+
+"""
+def test_string():
+ eci = ExternalCompilationInfo(includes=['string.h'])
+ z = llexternal('strlen', [CCHARP], Signed, compilation_info=eci)
+
+ def f():
+ s = str2charp("xxx")
+ res = z(s)
+ free_charp(s)
+ return res
+
+ xf = compile_c(f, [], backendopt=False)
+ assert xf() == 3
+"""
+
+from rpython.jit.backend.libgccjit.rffi_bindings import make_eci, Library
+
+def test_compile_empty_context():
+ eci = make_eci()
+
+ lib = Library(eci)
+
+ def f():
+ ctxt = lib.gcc_jit_context_acquire()
+ result = lib.gcc_jit_context_compile(ctxt)
+ lib.gcc_jit_context_release(ctxt)
+ lib.gcc_jit_result_release(result)
+
+ f1 = compile_c(f, [], backendopt=False)
+ f1 ()
+ #assert False # to see stderr
+
+def make_param_array(lib, l):
+ array = lltype.malloc(lib.PARAM_P_P.TO,
+ len(l),
+ flavor='raw') # of maybe gc?
+ for i in range(len(l)):
+ array[i] = l[i]
+ return array
+ # FIXME: don't leak!
+
+def test_compile_add_one_to():
+ eci = make_eci()
+
+ lib = Library(eci)
+
+ ft = lltype.FuncType([INT], INT)#, abi="C")
+ ftp = lltype.Ptr(ft)
+
+ def f():
+ ctxt = lib.gcc_jit_context_acquire()
+
+ lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
+ 1)
+ lib.gcc_jit_context_set_int_option(ctxt,
+ lib.GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
+ 3)
+ lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
+ 1)
+ lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
+ 1)
+ lib.gcc_jit_context_set_bool_option(ctxt,
+ lib.GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
+ 1)
+ t_int = lib.gcc_jit_context_get_type(ctxt, lib.GCC_JIT_TYPE_INT)
+ param = lib.gcc_jit_context_new_param(ctxt,
+ lib.null_location_ptr,
+ t_int,
+ "input")
+ # FIXME: how to build an array of params at this level?
+ # see liststr2charpp in rffi.py
+
+ param_array = make_param_array(lib, [param])
+ fn = lib.gcc_jit_context_new_function(ctxt,
+ lib.null_location_ptr,
+ lib.GCC_JIT_FUNCTION_EXPORTED,
+ t_int,
+ "add_one_to",
+ 1, param_array, 0)
+ lltype.free(param_array, flavor='raw')
+
+ v_res = lib.gcc_jit_function_new_local(fn,
+ lib.null_location_ptr,
+ t_int,
+ "v_res")
+ b_initial = lib.gcc_jit_function_new_block(fn, "initial")
+ c_one = lib.gcc_jit_context_new_rvalue_from_int(ctxt, t_int, 1)
+ op_add = lib.gcc_jit_context_new_binary_op(ctxt,
+ lib.null_location_ptr,
+ lib.GCC_JIT_BINARY_OP_PLUS,
+ t_int,
+ lib.gcc_jit_param_as_rvalue(param),
+ c_one)
+ lib.gcc_jit_block_add_assignment(b_initial, lib.null_location_ptr,
+ v_res,
+ op_add)
+ lib.gcc_jit_block_end_with_return(b_initial, lib.null_location_ptr,
+ lib.gcc_jit_lvalue_as_rvalue(v_res))
+
+ jit_result = lib.gcc_jit_context_compile(ctxt)
+ lib.gcc_jit_context_release(ctxt)
+ if not jit_result:
+ # FIXME: get error from context
+ raise Exception("jit_result is NULL")
+
+ fn_ptr = lib.gcc_jit_result_get_code(jit_result, "add_one_to")
+ if not fn_ptr:
+ raise Exception("fn_ptr is NULL")
+ print('fn_ptr: %s' % fn_ptr)
+
+ #ft = lltype.FuncType([INT], INT)#, abi="C")
+ # looks like we can't build a FuncType inside RPython
+ # but we can use one built outside:
+ print(ft)
+ print(ftp)
+
+ typed_fn_ptr = cast(ftp, fn_ptr)
+ print(typed_fn_ptr)
+ fn_result = typed_fn_ptr (r_int(41))
+ #print('fn_result: %d' % fn_result)
+ #assert fn_result == r_int(42)
+
+ # and it looks like we can't create a functionptr from this
+ # FuncType:
+ #funcptr = lltype.functionptr(ft)
+
+ lib.gcc_jit_result_release(jit_result)
+
+ return int(fn_result)
+
+ f1 = compile_c(f, [], backendopt=False)
+ assert f1() == 42
+ #assert False # to see stderr
+
+# TODO: test of an error
+# should turn it into an exception, and capture the error
More information about the pypy-commit
mailing list