refactor llvm_cbuilder

This commit is contained in:
Siu Kwan Lam 2012-09-07 17:38:56 -07:00
commit 8a159b35f0

View file

@ -42,6 +42,9 @@ def _is_block_terminated(bb):
instrs = bb.instructions
return len(instrs) > 0 and instrs[-1].is_terminator
def _is_struct(ty):
return isinstance(ty, lc.StructType)
def _is_cstruct(ty):
try:
return issubclass(ty, CStruct)
@ -67,6 +70,10 @@ def _change_block_temporarily(builder, bb):
def _change_block_temporarily_dummy(*args):
yield
class CastError(TypeError):
def __init__(self, orig, to):
super(CastError, self).__init__("Cannot cast from %s to %s" % (orig, to))
class _IfElse(object):
'''if-else construct.
@ -399,7 +406,7 @@ class CBuilder(object):
def check_arg(x):
if isinstance(x, int):
return self.constant(types.int, x)
if not x.is_int:
if not isinstance(x, IntegerValue):
raise TypeError(x, "All args must be of integer type.")
return x
@ -675,7 +682,11 @@ class CBuilder(object):
def alignment(self, ty):
'''get minimum alignment of `ty`
'''
return self.target_data.abi_alignment(ty)
return self.abi.abi_alignment(ty)
@property
def abi(self):
return self.target_data
def unreachable(self):
'''insert instruction that causes segfault some platform (Intel),
@ -828,301 +839,335 @@ class CDefinition(CBuilder):
raise NotImplementedError
class CValue(object):
'''
Signedness
----------
Since LLVM type does not provide signedness attribute. This information
is provided in the CValue.unsigned attribute. The default value is
`None`, meaning that this attribute is not set.
def __init__(self, parent, handle):
self.__parent = parent
self.__handle = handle
In casting operation, signednss information is passed as an optional arg.
@property
def handle(self):
return self.__handle
In binary operation, signedness of the left operand is used.
'''
@property
def parent(self):
return self.__parent
unsigned = None # attribute for for integer values.
def _temp(self, val):
return CTemp(self.parent, val)
_BINOP_MAP = {
# op-name : (signed int, unsigned int, real)
'add' : (lc.Builder.add, lc.Builder.add, lc.Builder.fadd),
'sub' : (lc.Builder.sub, lc.Builder.sub, lc.Builder.fsub),
'mul' : (lc.Builder.mul, lc.Builder.mul, lc.Builder.fmul),
'div' : (lc.Builder.sdiv, lc.Builder.udiv, lc.Builder.fdiv),
'mod' : (lc.Builder.srem, lc.Builder.urem, lc.Builder.frem),
}
def _get_operator_provider(ty):
if _is_pointer(ty):
return PointerValue
elif _is_int(ty):
return IntegerValue
elif _is_real(ty):
return RealValue
elif _is_vector(ty):
inner = _get_operator_provider(ty.element)
return type(str(ty), (inner, VectorIndexing), {})
elif _is_struct(ty):
return StructValue
else:
assert False, (str(ty), type(ty))
_BITWISE_MAP = {
# op-name : (signed int, unsigned int)
'lshift' : (lc.Builder.shl, lc.Builder.shl),
'rshift' : (lc.Builder.lshr, lc.Builder.ashr),
'and' : (lc.Builder.and_, lc.Builder.and_),
'or' : (lc.Builder.or_, lc.Builder.or_),
'xor' : (lc.Builder.xor, lc.Builder.xor),
}
class CTemp(CValue):
def __new__(cls, parent, handle):
meta = _get_operator_provider(handle.type)
base = type(str('%s_%s' % (cls.__name__, handle.type)), (cls, meta), {})
return object.__new__(base)
_CMP_MAP = {
# op-name : (signed int, unsigned int, real)
'eq' : (lc.ICMP_EQ, lc.ICMP_EQ, lc.FCMP_OEQ),
'ne' : (lc.ICMP_NE, lc.ICMP_NE, lc.FCMP_ONE),
'lt' : (lc.ICMP_SLT, lc.ICMP_ULT, lc.FCMP_OLT),
'le' : (lc.ICMP_SLE, lc.ICMP_ULE, lc.FCMP_OLE),
'gt' : (lc.ICMP_SGT, lc.ICMP_UGT, lc.FCMP_OGT),
'ge' : (lc.ICMP_SGE, lc.ICMP_UGE, lc.FCMP_OGE),
}
def __init__(self, *args, **kws):
super(CTemp, self).__init__(*args, **kws)
self._init_mixin()
def __init__(self, parent):
self.parent = parent
@property
def value(self):
return self.handle
def _use_binop(self, op):
'''implements binary operations
'''
def wrapped(rhs):
self._ensure_same_type(rhs)
binop = self._BINOP_MAP[op]
if self.is_int:
if not self.unsigned:
idx = 0
else:
idx = 1
elif self.is_real:
idx = 2
else:
errmsg = "Binary operation %s does not support type %s"
raise TypeError(errmsg % (op, self.type))
res = binop[idx](self.parent.builder, self.value, rhs.value)
return CTemp(self.parent, res)
return wrapped
@property
def type(self):
return self.value.type
def _use_bitwise(self, op):
'''implements bitwise operations
'''
def wrapped(rhs):
self._ensure_same_type(rhs)
if not self.is_int:
errmsg = "Bitwise operation %s does not support type %s"
raise TypeError(op, self.type)
if not self.unsigned:
idx = 0
else:
idx = 1
res = self._BITWISE_MAP[idx](self.parent.builder,
self.value, rhs.value)
return CTemp(self.parent, res)
return wrapped
class CVar(CValue):
def __new__(cls, parent, ptr):
meta = _get_operator_provider(ptr.type.pointee)
base = type(str('%s_%s' % (cls.__name__, ptr.type.pointee)), (cls, meta), {})
return object.__new__(base)
def __init__(self, parent, ptr):
super(CVar, self).__init__(parent, ptr)
self._init_mixin()
self.invariant = False
def reference(self):
return self._temp(self.handle)
@property
def ref(self):
return self.reference()
@property
def value(self):
return self.parent.builder.load(self.ref.value,
invariant=self.invariant)
@property
def type(self):
return self.ref.type.pointee
def assign(self, val, **kws):
if self.invariant:
raise TypeError("Storing to invariant variable.")
self.parent.builder.store(val.value, self.ref.value, **kws)
return self
def __iadd__(self, rhs):
return self.assign(self.__add__(rhs))
def __isub__(self, rhs):
return self.assign(self.__sub__(rhs))
def __imul__(self, rhs):
return self.assign(self.__mul__(rhs))
def __idiv__(self, rhs):
return self.assign(self.__div__(rhs))
def __imod__(self, rhs):
return self.assign(self.__mod__(rhs))
def __ilshift__(self, rhs):
return self.assign(self.__lshift__(rhs))
def __irshift__(self, rhs):
return self.assign(self.__rshift__(rhs))
def __iand__(self, rhs):
return self.assign(self.__and__(rhs))
def __ior__(self, rhs):
return self.assign(self.__or__(rhs))
def __ixor__(self, rhs):
return self.assign(self.__xor__(rhs))
class OperatorMixin(object):
def _init_mixin(self):
pass
class IntegerValue(OperatorMixin):
def _init_mixin(self):
self._unsigned = False
def _get_unsigned(self):
return self._unsigned
def _set_unsigned(self, unsigned):
self._unsigned = bool(unsigned)
unsigned = property(_get_unsigned, _set_unsigned)
def __add__(self, rhs):
return self._use_binop('add')(rhs)
return self._temp(self.parent.builder.add(self.value, rhs.value))
def __sub__(self, rhs):
return self._use_binop('sub')(rhs)
return self._temp(self.parent.builder.sub(self.value, rhs.value))
def __mul__(self, rhs):
return self._use_binop('mul')(rhs)
return self._temp(self.parent.builder.mul(self.value, rhs.value))
def __div__(self, rhs):
return self._use_binop('div')(rhs)
def __truediv__(self, rhs):
return self.__div__(rhs)
if self.unsigned:
return self._temp(self.parent.builder.udiv(self.value, rhs.value))
else:
return self._temp(self.parent.builder.sdiv(self.value, rhs.value))
def __mod__(self, rhs):
return self._use_binop('mod')(rhs)
if self.unsigned:
return self._temp(self.parent.builder.urem(self.value, rhs.value))
else:
return self._temp(self.parent.builder.srem(self.value, rhs.value))
def __lshift__(self, rhs):
return self._use_bitwise('lshift')(rhs)
def __ilshift__(self, rhs):
return self._temp(self.parent.builder.shl(self.value, rhs.value))
def __rshift__(self, rhs):
return self._use_bitwise('rshift')(rhs)
def __irshift__(self, rhs):
if self.unsigned:
return self._temp(self.self.parent.builder.lshr(self.value, rhs.value))
else:
return self._temp(self.parent.builder.ashr(self.value, rhs.value))
def __and__(self, rhs):
return self._use_bitwise('and')(rhs)
def __iand__(self, rhs):
return self._temp(self.parent.builder.and_(self.value, rhs.value))
def __or__(self, rhs):
return self._use_bitwise('or')(rhs)
def __ior__(self, rhs):
return self._temp(self.parent.builder.or_(self.value, rhs.value))
def __xor__(self, rhs):
return self._use_bitwise('xor')(rhs)
def _ensure_same_type(self, val):
'''ensure that this instance has the same type as `val`
Raises TypeError if `self.type != val.type`
'''
if self.type != val.type:
errmsg = "Type mismatch: %s != %s"
raise TypeError(errmsg % (self.type, val.type))
@property
def is_int(self):
return _is_int(self.type) or _is_vector(self.type, _is_int)
@property
def is_real(self):
return _is_real(self.type) or _is_vector(self.type, _is_real)
def cast(self, ty, unsigned=False):
'''cast to another type
If `ty == self.type`, then pass thru
'''
make = lambda X: CTemp(self.parent, X)
if self.type == ty:
return self # pass thru
elif self.is_pointer and _is_pointer(ty):
builder = self.parent.builder
return make(builder.bitcast(self.value, ty))
elif self.is_int:
if _is_int(ty):
if self.type.width < ty.width:
if not unsigned:
return make(self.parent.builder.sext(self.value, ty))
else:
return make(self.parent.builder.zext(self.value, ty))
else:
return make(self.parent.builder.trunc(self.value, ty))
elif _is_real(ty):
if not unsigned:
return make(self.parent.builder.sitofp(self.value, ty))
else:
return make(self.parent.builder.uitofp(self.value, ty))
elif self.is_real:
if _is_int(ty):
if not unsigned:
return make(self.parent.builder.fptosi(self.value, ty))
else:
return make(self.parent.builder.fptoui(self.value, ty))
else:
if ty == types.double:
assert self.type == types.float
return make(self.parent.builder.fpext(self.value, ty))
else:
assert ty == types.float
assert self.type == types.double
return make(self.parent.builder.fptrunc(self.value, ty))
errmsg = "Cast from %s to %s is not possible."
raise TypeError(errmsg % (self.type, ty))
def ptrtoint(self):
self._ensure_is_pointer()
builder = self.parent.builder
return CTemp(self.parent, builder.ptrtoint(self.value, types.intp))
def inttoptr(self, ty):
if not self.is_int:
raise TypeError("Must be an integer")
builder = self.parent.builder
return CTemp(self.parent, builder.inttoptr(self.value, ty))
def _cmp_op(self, name):
'''implements comparison operations
'''
def wrapped(rhs):
make = lambda X: CTemp(self.parent, X)
self._ensure_same_type(rhs)
flag_bag = self._CMP_MAP[name]
if self.is_int:
comparator = self.parent.builder.icmp
if not self.unsigned:
flag = flag_bag[0]
else:
flag = flag_bag[1]
elif self.is_real:
comparator = self.parent.builder.fcmp
flag = flag_bag[2]
else:
errmsg = "Comparision between %s and %s is not supported."
raise TypeError(errmsg % (self.type, rhs.type))
return CTemp(self.parent, comparator(flag, self.value, rhs.value))
return wrapped
def __eq__(self, rhs):
return self._cmp_op('eq')(rhs)
def __ne__(self, rhs):
return self._cmp_op('ne')(rhs)
def __ixor__(self, rhs):
return self._temp(self.parent.builder.xor(self.value, rhs.value))
def __lt__(self, rhs):
return self._cmp_op('lt')(rhs)
if self.unsigned:
return self._temp(self.parent.builder.icmp(lc.ICMP_ULT, self.value, rhs.value))
else:
return self._temp(self.parent.builder.icmp(lc.ICMP_SLT, self.value, rhs.value))
def __le__(self, rhs):
return self._cmp_op('le')(rhs)
if self.unsigned:
return self._temp(self.parent.builder.icmp(lc.ICMP_ULE, self.value, rhs.value))
else:
return self._temp(self.parent.builder.icmp(lc.ICMP_SLE, self.value, rhs.value))
def __eq__(self, rhs):
return self._temp(self.parent.builder.icmp(lc.ICMP_EQ, self.value, rhs.value))
def __ne__(self, rhs):
return self._temp(self.parent.builder.icmp(lc.ICMP_NE, self.value, rhs.value))
def __gt__(self, rhs):
return self._cmp_op('gt')(rhs)
if self.unsigned:
return self._temp(self.parent.builder.icmp(lc.ICMP_UGT, self.value, rhs.value))
else:
return self._temp(self.parent.builder.icmp(lc.ICMP_SGT, self.value, rhs.value))
def __ge__(self, rhs):
return self._cmp_op('ge')(rhs)
if self.unsigned:
return self._temp(self.parent.builder.icmp(lc.ICMP_UGE, self.value, rhs.value))
else:
return self._temp(self.parent.builder.icmp(lc.ICMP_SGE, self.value, rhs.value))
def cast(self, ty, unsigned=False):
if ty == self.type:
return self._temp(self.value)
if _is_real(ty):
if self.unsigned or unsigned:
return self._temp(self.parent.builder.uitofp(self.value, ty))
else:
return self._temp(self.parent.builder.sitofp(self.value, ty))
elif _is_int(ty):
if self.parent.abi.size(self.type) < self.parent.abi.size(ty):
if self.unsigned or unsigned:
return self._temp(self.parent.builder.zext(self.value, ty))
else:
return self._temp(self.parent.builder.sext(self.value, ty))
else:
return self._temp(self.parent.builder.trunc(self.value, ty))
raise CastError(self.type, ty)
class RealValue(OperatorMixin):
def __add__(self, rhs):
return self._temp(self.parent.builder.fadd(self.value, rhs.value))
def __sub__(self, rhs):
return self._temp(self.parent.builder.fsub(self.value, rhs.value))
def __mul__(self, rhs):
return self._temp(self.parent.builder.fmul(self.value, rhs.value))
def __div__(self, rhs):
return self._temp(self.parent.builder.fdiv(self.value, rhs.value))
def __mod__(self, rhs):
return self._temp(self.parent.builder.frem(self.value, rhs.value))
def __lt__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_OLT, self.value, rhs.value))
def __le__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_OLE, self.value, rhs.value))
def __eq__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_OEQ, self.value, rhs.value))
def __ne__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_ONE, self.value, rhs.value))
def __gt__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_OGT, self.value, rhs.value))
def __ge__(self, rhs):
return self._temp(self.parent.builder.fcmp(lc.FCMP_OGE, self.value, rhs.value))
def cast(self, ty, unsigned=False):
if ty == self.type:
return self._temp(self.value)
if _is_int(ty):
if unsigned:
return self._temp(self.parent.builder.fptoui(self.value, ty))
else:
return self._temp(self.parent.builder.fptosi(self.value, ty))
if _is_real(ty):
if self.parent.abi.size(self.type) > self.parent.abi.size(ty):
return self._temp(self.parent.builder.fptrunc(self.value, ty))
else:
return self._temp(self.parent.builder.fpext(self.value, ty))
raise CastError(self.type, ty)
@property
def is_vector(self):
return _is_vector(self.type)
@property
def is_pointer(self):
return _is_pointer(self.type)
def _ensure_is_pointer(self):
if not self.is_pointer:
raise TypeError("Must be a pointer; got %s" % self.type)
def _ensure_is_vector(self):
if not self.is_vector:
raise TypeError("Must be a vector; got %s" % self.type)
class PointerIndexing(OperatorMixin):
def __getitem__(self, idx):
'''implement access indexing
Uses GEP.
'''
bldr = self.parent.builder
if self.is_pointer:
if type(idx) is slice:
# just handle case by case
# Case #1: A[idx:] get poointer offset by idx
if not idx.step and not idx.stop:
idx = _auto_coerce_index(self.parent, idx.start)
ptr = bldr.gep(self.value, [idx.value])
return CArray(self.parent, ptr)
else: # return an variable at idx
idx = _auto_coerce_index(self.parent, idx)
if type(idx) is slice:
# just handle case by case
# Case #1: A[idx:] get pointer offset by idx
if not idx.step and not idx.stop:
idx = _auto_coerce_index(self.parent, idx.start)
ptr = bldr.gep(self.value, [idx.value])
return CVar(self.parent, ptr)
elif self.is_vector:
return CArray(self.parent, ptr)
else: # return an variable at idx
idx = _auto_coerce_index(self.parent, idx)
val = bldr.extract_element(self.value, idx.value)
return CTemp(self.parent, val)
else:
raise TypeError("Must be a pointer or vector; got %s" % self.type)
ptr = bldr.gep(self.value, [idx.value])
return CVar(self.parent, ptr)
def __setitem__(self, idx, val):
idx = _auto_coerce_index(self.parent, idx)
bldr = self.parent.builder
if self.is_vector:
vec = bldr.insert_element(self.value, val.value, idx.value)
bldr.store(vec, self.ptr)
elif self.is_pointer:
self[idx].assign(val)
else:
raise TypeError("Must be a pointer or vector; got %s" % self.type)
self[idx].assign(val)
def load(self, volatile=False, invariant=False):
'''memory load for pointer types
'''
self._ensure_is_pointer()
loaded = self.parent.builder.load(self.value, volatile=volatile,
invariant=invariant)
return CTemp(self.parent, loaded)
class PointerCasting(OperatorMixin):
def cast(self, ty):
if ty == self.type:
return self._temp(self.value)
def store(self, val, volatile=False, nontemporal=False):
'''memory store for pointer types
if _is_pointer(ty):
return self._temp(self.parent.builder.bitcast(self.value, ty))
raise CastError(self.type, ty)
class VectorIndexing(OperatorMixin):
def __getitem__(self, idx):
'''implement access indexing
Uses GEP.
'''
self._ensure_is_pointer()
inst = self.parent.builder.store(val.value, self.value,
volatile=volatile)
bldr = self.parent.builder
idx = _auto_coerce_index(self.parent, idx)
val = bldr.extract_element(self.value, idx.value)
return CTemp(self.parent, val)
def __setitem__(self, idx, val):
idx = _auto_coerce_index(self.parent, idx)
bldr = self.parent.builder
vec = bldr.insert_element(self.value, val.value, idx.value)
bldr.store(vec, self.ref.value)
class PointerValue(PointerIndexing, PointerCasting):
def load(self, **kws):
return self._temp(self.parent.builder.load(self.value, **kws))
def store(self, val, nontemporal=False, **kws):
inst = self.parent.builder.store(val.value, self.value, **kws)
if nontemporal:
self.parent.set_memop_non_temporal(inst)
@ -1135,12 +1180,11 @@ class CValue(object):
Other parameters are the same as `CBuilder.atomic_load`
'''
self._ensure_is_pointer()
if align is None:
align = self.parent.alignment(self.type.pointee)
inst = self.parent.builder.atomic_load(self.value, ordering, align,
crossthread=crossthread)
return CTemp(self.parent, inst)
return self._temp(inst)
def atomic_store(self, value, ordering, align=None, crossthread=True):
'''atomic memory store for pointer types
@ -1150,7 +1194,6 @@ class CValue(object):
Other parameters are the same as `CBuilder.atomic_store`
'''
self._ensure_is_pointer()
if align is None:
align = self.parent.alignment(self.type.pointee)
self.parent.builder.atomic_store(value.ptr, self.value, ordering,
@ -1161,19 +1204,34 @@ class CValue(object):
Other parameters are the same as `CBuilder.atomic_cmpxchg`
'''
self._ensure_is_pointer()
inst = self.parent.builder.atomic_cmpxchg(self.value, old.value,
new.value, ordering,
crossthread=crossthread)
return CTemp(self.parent, inst)
return self._temp(inst)
def as_struct(self, cstruct_class, volatile=False):
'''load a pointer to a structure and assume a structure interface
'''
ptr = self.parent.builder.load(self.value, volatile=volatile)
return cstruct_class(self.parent, self.value)
class StructValue(OperatorMixin):
def as_struct(self, cstruct_class):
'''assume a structure interface
'''
return cstruct_class(self.parent, self.ref.value)
class CFunc(CValue):
class CFunc(CValue, PointerCasting):
'''Wraps function pointer
'''
def __init__(self, parent, func):
super(CFunc, self).__init__(parent)
self.function = func
super(CFunc, self).__init__(parent, func)
@property
def function(self):
return self.handle
def __call__(self, *args, **opts):
'''Call the function with the given arguments
@ -1188,13 +1246,15 @@ class CFunc(CValue):
"argument %d mismatch: %s != %s"
% (self.function.name, i, exp, got.type))
res = self.parent.builder.call(self.function, arg_values)
if hasattr(self.function, 'calling_convention'):
res.calling_convention = self.function.calling_convention
if opts.get('inline'):
self.parent.add_auto_inline(res)
return CTemp(self.parent, res)
if ftype.return_type != lc.Type.void():
return CTemp(self.parent, res)
@property
def value(self):
@ -1204,123 +1264,25 @@ class CFunc(CValue):
def type(self):
return self.function.type
class CTemp(CValue):
'''Wraps temporary values
'''
def __init__(self, parent, value):
super(CTemp, self).__init__(parent)
self.value = value
@property
def type(self):
return self.value.type
class CVar(CValue):
'''Wraps variables
Similar to C variables.
'''
def __init__(self, parent, ptr):
super(CVar, self).__init__(parent)
self.ptr = ptr
self.invariant = False
def _inplace_binop(self, op):
def wrapped(rhs):
res = self._use_binop(op)(rhs)
self.assign(res)
return self
return wrapped
def __iadd__(self, rhs):
return self._inplace_binop('add')(rhs)
def __isub__(self, rhs):
return self._inplace_binop('sub')(rhs)
def __imul__(self, rhs):
return self._inplace_binop('mul')(rhs)
def __idiv__(self, rhs):
return self._inplace_binop('div')(rhs)
def __imod__(self, rhs):
return self._inplace_binop('mod')(rhs)
def _inplace_bitwise(self, op):
def wrapped(rhs):
res = self._use_bitwise(op)(rhs)
self.assign(res)
return self
return wrapped
def __ilshift__(self, rhs):
return self._inplace_bitwise('lshift')(rhs)
def __irshift__(self, rhs):
return self._inplace_bitwise('rshift')(rhs)
def __iand__(self, rhs):
return self._inplace_bitwise('and')(rhs)
def __ior__(self, rhs):
return self._inplace_bitwise('or')(rhs)
def __ixor__(self, rhs):
return self._inplace_bitwise('xor')(rhs)
@property
def value(self):
return self.parent.builder.load(self.ptr, invariant=self.invariant)
def assign(self, val, nontemporal=False):
'''assign new value to the variable
'''
if self.invariant: raise TypeError("Assignment to invariant variable")
self._ensure_same_type(val)
inst = self.parent.builder.store(val.value, self.ptr)
if nontemporal:
self.parent.set_memop_non_temporal(inst)
@property
def type(self):
return self.ptr.type.pointee
def reference(self):
'''get a pointer reference of the variable
'''
return CTemp(self.parent, self.ptr)
def as_struct(self, cstruct_class, volatile=False):
'''load a pointer to a structure and assume a structure interface
'''
if _is_pointer(self.type):
ptr = self.parent.builder.load(self.ptr, volatile=volatile)
return cstruct_class(self.parent, ptr)
else:
return cstruct_class(self.parent, self.ptr)
class CArray(CValue):
class CArray(CValue, PointerIndexing, PointerCasting):
'''wraps a array
Similar to C arrays
'''
def __init__(self, parent, base):
super(CArray, self).__init__(parent)
self.base_ptr = base
super(CArray, self).__init__(parent, base)
@property
def value(self):
return self.base_ptr
return self.handle
def reference(self):
return CTemp(self.parent, self.base_ptr)
return self._temp(self.value)
@property
def type(self):
return self.base_ptr.type
return self.value.type
def vector_load(self, count, align=0):
parent = self.parent
@ -1328,9 +1290,9 @@ class CArray(CValue):
values = [self[i] for i in range(count)]
vecty = types.vector(self.type.pointee, count)
vec = builder.load(builder.bitcast(self.base_ptr, types.pointer(vecty)),
vec = builder.load(builder.bitcast(self.value, types.pointer(vecty)),
align=align)
return CTemp(parent, vec)
return self._temp(vec)
def vector_store(self, vec, align=0):
if vec.type.element != self.type.pointee:
@ -1338,10 +1300,11 @@ class CArray(CValue):
(vec.type.element, self.type.pointee))
parent = self.parent
builder = parent.builder
vecptr = builder.bitcast(self.base_ptr, types.pointer(vec.type))
vecptr = builder.bitcast(self.value, types.pointer(vec.type))
builder.store(vec.value, vecptr, align=align)
return self
class CStruct(CValue):
'''Wraps a structure
@ -1358,9 +1321,9 @@ class CStruct(CValue):
return lc.Type.struct([v for k, v in cls._fields_])
def __init__(self, parent, ptr):
super(CStruct, self).__init__(parent)
super(CStruct, self).__init__(parent, ptr)
makeind = lambda x: self.parent.constant(types.int, x).value
self.ptr = ptr
for i, (fd, _) in enumerate(self._fields_):
gep = self.parent.builder.gep(ptr, [makeind(0), makeind(i)])
gep.name = "%s.%s" % (type(self).__name__, fd)
@ -1369,7 +1332,7 @@ class CStruct(CValue):
setattr(self, fd, CVar(self.parent, gep))
def reference(self):
return CTemp(self.parent, self.ptr)
return self._temp(self.handle)
class CExternal(object):