Incremental extensions to llpython to better support using the Python C-API.
This commit is contained in:
parent
e4f4d56fe6
commit
9fe9e8eb39
2 changed files with 75 additions and 16 deletions
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue