[pypy-svn] r64999 - in pypy/branch/pyjitpl5/pypy/jit/backend/llvm: . test

arigo at codespeak.net arigo at codespeak.net
Sun May 3 13:49:17 CEST 2009


Author: arigo
Date: Sun May  3 13:49:16 2009
New Revision: 64999

Modified:
   pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c
   pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py
   pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py
Log:
Work hard until the first example of 'llvm-py'is complete
and runs with a JIT.


Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/demo1.c	Sun May  3 13:49:16 2009
@@ -5,7 +5,7 @@
 
 /* The following list of functions seems to be necessary to force the
  * functions to be included in pypy_cache_llvm.so.  The list is never
- * used.
+ * used.  Actually, any single function seems to be enough...
  */
 void* llvm_c_functions[] = {
   (void*) LLVMModuleCreateWithName

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/llvm_rffi.py	Sun May  3 13:49:16 2009
@@ -30,10 +30,7 @@
     oname = os.path.join(dirname, 'demo1.o')
     do("gcc -c '%s' -o '%s'" % (cname, oname))
     do("g++ -shared '%s' -o '%s'" % (oname, libname) +
-       " `%s --libs jit`" % llvm_config +
-       " `%s --cflags`" % llvm_config +
-       " `%s --ldflags`" % llvm_config +
-       "")
+       " `%s --cflags --ldflags --libs jit engine`" % llvm_config)
 
 compilation_info = ExternalCompilationInfo(
     library_dirs = [dirname],
@@ -50,8 +47,87 @@
 def opaqueptr(name):
     return rffi.VOIDP  # lltype.Ptr(rffi.COpaque(name))
 
-LLVMModuleRef = opaqueptr('struct LLVMModuleOpaque')
+LLVMModuleRef = opaqueptr('struct LLVMOpaqueModule')
+LLVMTypeRef = opaqueptr('struct LLVMOpaqueType')
+LLVMValueRef = opaqueptr('struct LLVMOpaqueValue')
+LLVMBasicBlockRef = opaqueptr('struct LLVMOpaqueBasicBlock')
+LLVMBuilderRef = opaqueptr('struct LLVMOpaqueBuilder')
+LLVMModuleProviderRef = opaqueptr('struct LLVMOpaqueModuleProvider')
+LLVMGenericValueRef = opaqueptr('struct LLVMOpaqueGenericValue')
+LLVMExecutionEngineRef = opaqueptr('struct LLVMOpaqueExecutionEngine')
+
+# ____________________________________________________________
 
 LLVMModuleCreateWithName = llexternal('LLVMModuleCreateWithName',
                                       [rffi.CCHARP],
                                       LLVMModuleRef)
+LLVMDumpModule = llexternal('LLVMDumpModule', [LLVMModuleRef], lltype.Void)
+
+LLVMInt32Type = llexternal('LLVMInt32Type', [], LLVMTypeRef)
+LLVMFunctionType = llexternal('LLVMFunctionType',
+                              [LLVMTypeRef,                 # return type
+                               rffi.CArrayPtr(LLVMTypeRef), # param types
+                               rffi.UINT,                   # param count
+                               rffi.INT],                   # flag: is vararg
+                              LLVMTypeRef)
+
+LLVMAddFunction = llexternal('LLVMAddFunction',
+                             [LLVMModuleRef,                # module
+                              rffi.CCHARP,                  # name
+                              LLVMTypeRef],                 # function type
+                             LLVMValueRef)
+LLVMGetParam = llexternal('LLVMGetParam',
+                          [LLVMValueRef,                    # function
+                           rffi.UINT],                      # index
+                          LLVMValueRef)
+
+LLVMAppendBasicBlock = llexternal('LLVMAppendBasicBlock',
+                                  [LLVMValueRef,            # function
+                                   rffi.CCHARP],            # name
+                                  LLVMBasicBlockRef)
+
+LLVMCreateBuilder = llexternal('LLVMCreateBuilder', [], LLVMBuilderRef)
+LLVMPositionBuilderAtEnd = llexternal('LLVMPositionBuilderAtEnd',
+                                      [LLVMBuilderRef,      # builder
+                                       LLVMBasicBlockRef],  # block
+                                      lltype.Void)
+
+LLVMBuildRet = llexternal('LLVMBuildRet', [LLVMBuilderRef,  # builder,
+                                           LLVMValueRef],   # result
+                          LLVMValueRef)
+LLVMBuildAdd = llexternal('LLVMBuildAdd', [LLVMBuilderRef,  # builder
+                                           LLVMValueRef,    # left-hand side
+                                           LLVMValueRef,    # right-hand side
+                                           rffi.CCHARP],    # name of result
+                          LLVMValueRef)
+
+LLVMCreateModuleProviderForExistingModule = llexternal(
+    'LLVMCreateModuleProviderForExistingModule', [LLVMModuleRef],
+    LLVMModuleProviderRef)
+
+# ____________________________________________________________
+
+LLVMCreateGenericValueOfInt = llexternal('LLVMCreateGenericValueOfInt',
+                                         [LLVMTypeRef,      # type
+                                          rffi.ULONGLONG,   # value
+                                          rffi.INT],        # flag: is_signed
+                                         LLVMGenericValueRef)
+
+LLVMGenericValueToInt = llexternal('LLVMGenericValueToInt',
+                                   [LLVMGenericValueRef,
+                                    rffi.INT],              # flag: is_signed
+                                   rffi.ULONGLONG)
+
+LLVMCreateJITCompiler = llexternal('LLVMCreateJITCompiler',
+                                   [rffi.CArrayPtr(LLVMExecutionEngineRef),
+                                    LLVMModuleProviderRef,
+                                    rffi.INT,                      # "fast"
+                                    rffi.CArrayPtr(rffi.CCHARP)],  # -> error
+                                   rffi.INT)
+
+LLVMRunFunction = llexternal('LLVMRunFunction',
+                             [LLVMExecutionEngineRef,
+                              LLVMValueRef,                         # function
+                              rffi.UINT,                            # num args
+                              rffi.CArrayPtr(LLVMGenericValueRef)], # args
+                             LLVMGenericValueRef)   # return value

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llvm/test/test_llvm_rffi.py	Sun May  3 13:49:16 2009
@@ -1,5 +1,91 @@
 
 from pypy.jit.backend.llvm.llvm_rffi import *
 
-def test_basic():
-    LLVMModuleCreateWithName("hello")
+
+def test_from_llvm_py_example_1():
+    # NOTE: no GC so far!!!!!!!!!
+
+    # Create an (empty) module.
+    my_module = LLVMModuleCreateWithName("my_module")
+
+    # All the types involved here are "int"s. This type is represented
+    # by an object of type LLVMTypeRef:
+    ty_int = LLVMInt32Type()
+
+    # We need to represent the class of functions that accept two integers
+    # and return an integer. This is represented by another LLVMTypeRef:
+    arglist = lltype.malloc(rffi.CArray(LLVMTypeRef), 2, flavor='raw')
+    arglist[0] = ty_int
+    arglist[1] = ty_int
+    ty_func = LLVMFunctionType(ty_int, arglist, 2, False)
+    lltype.free(arglist, flavor='raw')
+
+    # Now we need a function named 'sum' of this type. Functions are not
+    # free-standing; it needs to be contained in a module.
+    f_sum = LLVMAddFunction(my_module, "sum", ty_func)
+    f_arg_0 = LLVMGetParam(f_sum, 0)
+    f_arg_1 = LLVMGetParam(f_sum, 1)
+
+    # Our function needs a "basic block" -- a set of instructions that
+    # end with a terminator (like return, branch etc.). By convention
+    # the first block is called "entry".
+    bb = LLVMAppendBasicBlock(f_sum, "entry")
+
+    # Let's add instructions into the block. For this, we need an
+    # instruction builder:
+    builder = LLVMCreateBuilder()
+    LLVMPositionBuilderAtEnd(builder, bb)
+
+    # OK, now for the instructions themselves. We'll create an add
+    # instruction that returns the sum as a value, which we'll use
+    # a ret instruction to return.
+    tmp = LLVMBuildAdd(builder, f_arg_0, f_arg_1, "tmp")
+    LLVMBuildRet(builder, tmp)
+
+    # We've completed the definition now! Let's see the LLVM assembly
+    # language representation of what we've created: (it goes to stderr)
+    LLVMDumpModule(my_module)
+    return locals()
+
+
+class LLVMException(Exception):
+    pass
+
+
+def test_from_llvm_py_example_2():
+    d = test_from_llvm_py_example_1()
+    my_module = d['my_module']
+    ty_int = d['ty_int']
+    f_sum = d['f_sum']
+
+    # Create a module provider object first. Modules can come from
+    # in-memory IRs like what we created now, or from bitcode (.bc)
+    # files. The module provider abstracts this detail.
+    mp = LLVMCreateModuleProviderForExistingModule(my_module)
+
+    # Create an execution engine object. This creates a JIT compiler,
+    # or complain on platforms that don't support it.
+    ee_out = lltype.malloc(rffi.CArray(LLVMExecutionEngineRef), 1, flavor='raw')
+    error_out = lltype.malloc(rffi.CArray(rffi.CCHARP), 1, flavor='raw')
+    try:
+        error = LLVMCreateJITCompiler(ee_out, mp, True, error_out)
+        if rffi.cast(lltype.Signed, error) != 0:
+            raise LLVMException(rffi.charp2str(error_out[0]))
+        ee = ee_out[0]
+    finally:
+        lltype.free(error_out, flavor='raw')
+        lltype.free(ee_out, flavor='raw')
+
+    # The arguments needs to be passed as "GenericValue" objects.
+    args = lltype.malloc(rffi.CArray(LLVMGenericValueRef), 2, flavor='raw')
+    args[0] = LLVMCreateGenericValueOfInt(ty_int, 100, True)
+    args[1] = LLVMCreateGenericValueOfInt(ty_int, 42, True)
+
+    # Now let's compile and run!
+    retval = LLVMRunFunction(ee, f_sum, 2, args)
+    lltype.free(args, flavor='raw')
+
+    # The return value is also GenericValue. Let's check it.
+    ulonglong = LLVMGenericValueToInt(retval, True)
+    res = rffi.cast(lltype.Signed, ulonglong)
+    assert res == 142



More information about the Pypy-commit mailing list