Incremental extensions to llpython to better support using the Python C-API.

This commit is contained in:
Jon Riehl 2013-07-12 19:38:50 -05:00
commit 9fe9e8eb39
2 changed files with 75 additions and 16 deletions

View file

@ -10,6 +10,7 @@ import opcode
import types
import logging
from llvm import LLVMException
import llvm.core as lc
from . import opcode_util
@ -40,6 +41,13 @@ _compare_mapping_sint = {'>':lc.ICMP_SGT,
'<=':lc.ICMP_SLE,
'!=':lc.ICMP_NE}
_compare_mapping_ptr = {'>':lc.ICMP_UGT,
'<':lc.ICMP_ULT,
'==':lc.ICMP_EQ,
'>=':lc.ICMP_UGE,
'<=':lc.ICMP_ULE,
'!=':lc.ICMP_NE}
# XXX Stolen from numba.llvm_types:
class LLVMCaster (object):
@ -120,6 +128,37 @@ class LLVMCaster (object):
raise NotImplementedError(lkind1, lkind2)
return ret_val
# ______________________________________________________________________
def _convert_const(py_val):
'''Convert a constant Python value into a comparable LLVM
constant. Preserves Python values and data structures such as
lists, tuples, and None.
'''
if isinstance(py_val, list):
ret_val = [_convert_const(child) for child in py_val]
elif isinstance(py_val, tuple):
ret_val = tuple(_convert_const(child) for child in py_val)
elif isinstance(py_val, int):
ret_val = lc.Constant.int(bytetype.lc_int, py_val)
elif isinstance(py_val, float):
ret_val = lc.Constant.double(py_val)
elif py_val == None:
ret_val = py_val
else:
raise NotImplementedError('Constant conversion for %r' % (py_val,))
return ret_val
# ______________________________________________________________________
def get_or_insert_global_variable(llvm_module, variable_ty, variable_name):
try:
ret_val = llvm_module.get_global_variable_named(variable_name)
# XXX Check LLVM value is of correct type?!
except LLVMException:
ret_val = llvm_module.add_global_variable(variable_ty, variable_name)
return ret_val
# ______________________________________________________________________
# Class definitions
@ -377,11 +416,12 @@ class LLVMTranslator (BytecodeFlowVisitor):
raise NotImplementedError("LLVMTranslator.op_BUILD_SLICE")
def op_BUILD_TUPLE (self, i, op, arg, *args, **kws):
return args
return [args]
def op_CALL_FUNCTION (self, i, op, arg, *args, **kws):
fn = args[0]
args = args[1:]
argcount = len(args)
fn_name = getattr(fn, '__name__', None)
if isinstance(fn, (types.FunctionType, types.MethodType)):
ret_val = [fn(self.builder, *args)]
@ -421,6 +461,9 @@ class LLVMTranslator (BytecodeFlowVisitor):
elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE):
ret_val = [self.builder.fcmp(_compare_mapping_float[cmp_kind],
arg1, arg2)]
elif isinstance(arg1.type, lc.PointerType):
ret_val = [self.builder.icmp(_compare_mapping_ptr[cmp_kind],
arg1, arg2)]
else:
raise NotImplementedError('Comparison of type %r' % (arg1.type,))
return ret_val
@ -480,17 +523,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
raise NotImplementedError("LLVMTranslator.op_LOAD_ATTR")
def op_LOAD_CONST (self, i, op, arg, *args, **kws):
py_val = self.code_obj.co_consts[arg]
if isinstance(py_val, int):
ret_val = [lc.Constant.int(bytetype.lc_int, py_val)]
elif isinstance(py_val, float):
ret_val = [lc.Constant.double(py_val)]
elif py_val == None:
ret_val = [None]
else:
raise NotImplementedError('Constant converstion for %r' %
(py_val,))
return ret_val
return [_convert_const(self.code_obj.co_consts[arg])]
def op_LOAD_DEREF (self, i, op, arg, *args, **kws):
name = self.code_obj.co_freevars[arg]
@ -546,7 +579,15 @@ class LLVMTranslator (BytecodeFlowVisitor):
return [self.builder.store(store_val, dest_addr)]
def op_UNARY_CONVERT (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT")
var_ty = args[0]
if isinstance(var_ty, lc.Type):
var_name = var_ty.__name__
ret_val = [get_or_insert_global_variable(self.llvm_module, var_ty,
var_name)]
else:
raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT: %r" %
(var_ty,))
return ret_val
def op_UNARY_INVERT (self, i, op, arg, *args, **kws):
raise NotImplementedError("LLVMTranslator.op_UNARY_INVERT")

View file

@ -1,4 +1,5 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# ______________________________________________________________________
import ctypes
@ -23,9 +24,10 @@ li8_ptr = lc.Type.pointer(li8)
lc_int = lc.Type.int(ctypes.sizeof(ctypes.c_int) * 8)
lc_long = lc.Type.int(ctypes.sizeof(ctypes.c_long) * 8)
l_pyobject_head = [lc_size_t, lc.Type.pointer(li32)]
l_pyobject_head = [lc_size_t, li8_ptr]
l_pyobject_head_struct = lc.Type.struct(l_pyobject_head)
l_pyobj_p = l_pyobject_head_struct_p = lc.Type.pointer(l_pyobject_head_struct)
l_pyobj_pp = lc.Type.pointer(l_pyobj_p)
l_pyfunc = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
strlen = lc.Type.function(lc_size_t, (li8_ptr,))
@ -34,10 +36,26 @@ strndup = lc.Type.function(li8_ptr, (li8_ptr, lc_size_t))
malloc = lc.Type.function(li8_ptr, (lc_size_t,))
free = lc.Type.function(lvoid, (li8_ptr,))
Py_BuildValue = lc.Type.function(l_pyobj_p, [li8_ptr], True)
PyArg_ParseTuple = lc.Type.function(lc_int, [l_pyobj_p, li8_ptr], True)
PyBool_FromLong = lc.Type.function(l_pyobj_p, [lc_long])
PyEval_SaveThread = lc.Type.function(li8_ptr, [])
PyEval_RestoreThread = lc.Type.function(lc.Type.void(), [li8_ptr])
PyEval_RestoreThread = lc.Type.function(lvoid, [li8_ptr])
PyInt_AsLong = lc.Type.function(lc_long, [l_pyobj_p])
PyInt_FromLong = lc.Type.function(l_pyobj_p, [lc_long])
PyNumber_Add = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyNumber_Divide = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyNumber_Multiply = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyNumber_Remainder = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyNumber_Subtract = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyNumber_TrueDivide = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
PyString_Check = lc.Type.function(lc_int, [l_pyobj_p])
PyString_CheckExact = lc.Type.function(lc_int, [l_pyobj_p])
PyString_Format = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
Py_BuildValue = lc.Type.function(l_pyobj_p, [li8_ptr], True)
Py_DecRef = lc.Type.function(lvoid, [l_pyobj_p])
Py_IncRef = lc.Type.function(lvoid, [l_pyobj_p])
PyInt_Type = li8
# ______________________________________________________________________
# End of bytetype.py