[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