def __add__(self, other): """ Return the result of an addition. """ other = qy.value_from_any(other).cast_to(self.type_) value = RealValue(qy.get().builder.fadd(self._value, other._value)) if qy.get().test_for_nan: qy.assert_(~value.is_nan, "result of %s + %s is not a number", other, self) return value
def __eq__(self, other): """ Return the result of an equality comparison. """ return \ qy.Value.from_low( qy.get().builder.icmp( llvm.ICMP_EQ, qy.get().builder.ptrtoint(self._value, qy.iptr_type), qy.value_from_any(other).cast_to(qy.iptr_type)._value, ), )
def __mul__(self, other): """ Return the result of a multiplication. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.mul(self._value, other._value))
def __div__(self, other): """ Return the result of a division. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.sdiv(self._value, other._value))
def __or__(self, other): """ Return the result of a bitwise or. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.or_(self._value, other._value))
def __add__(self, other): """ Return the result of an addition. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.add(self._value, other._value))
def intrinsic(intrinsic_id, qualifiers=()): """ Return an intrinsic function. """ qualifiers = map(qy.type_from_any, qualifiers) return Function(llvm.Function.intrinsic(qy.get().module, intrinsic_id, qualifiers))
def named(name, return_type=llvm.Type.void(), argument_types=()): """ Look up or create a named function. """ type_ = llvm.Type.function(qy.type_from_any(return_type), map(qy.type_from_any, argument_types)) return Function(qy.get().module.get_or_insert_function(type_, name))
def __sub__(self, other): """ Return the result of a subtraction. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.sub(self._value, other._value))
def load(self, name = ""): """ Load the value pointed to by this pointer. """ return \ qy.Value.from_low( qy.get().builder.load(self._value, name = name), )
def __mod__(self, other): """ Return the remainder of a division. Note that this operation performs C-style, not Python-style, modulo. """ other = qy.value_from_any(other).cast_to(self.type_) return IntegerValue(qy.get().builder.srem(self._value, other._value))
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX support more casts type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_POINTER: low_value = qy.get().builder.bitcast(self._value, type_, name) elif type_.kind == llvm.TYPE_INTEGER: if type_.width == qy.iptr_type.width: low_value = qy.get().builder.ptrtoint(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_any(low_value)
def new_named(name, return_type=llvm.Type.void(), argument_types=(), internal=True): """ Create a named function. """ type_ = llvm.Type.function(qy.type_from_any(return_type), map(qy.type_from_any, argument_types)) function = qy.get().module.add_function(type_, name) if internal: function.linkage = llvm.LINKAGE_INTERNAL return Function(function)
def gep(self, *indices): """ Return a pointer to a component. """ return \ qy.Value.from_low( qy.get().builder.gep( self._value, [qy.Value.from_any(i)._value for i in indices], ), )
def __le__(self, other): """ Return the result of a less-than-or-equal comparison. """ return \ qy.Value.from_low( qy.get().builder.icmp( llvm.ICMP_SLE, self._value, qy.value_from_any(other).cast_to(self.type_)._value, ), )
def __eq__(self, other): """ Return the result of an equality comparison. """ return \ qy.Value.from_low( qy.get().builder.fcmp( llvm.FCMP_OEQ, self._value, qy.value_from_any(other)._value, ), )
def is_nan(self): """ Test for nan. """ return \ qy.Value.from_low( qy.get().builder.fcmp( llvm.FCMP_UNO, self._value, self._value, ), )
def __gt__(self, other): """ Return the result of a greater-than comparison. """ return \ qy.Value.from_low( qy.get().builder.icmp( llvm.ICMP_SGT, self._value, qy.value_from_any(other).cast_to(self.type_)._value, ), )
def __ge__(self, other): """ Return the result of a greater-than-or-equal comparison. """ return \ qy.Value.from_low( qy.get().builder.fcmp( llvm.FCMP_OGE, self._value, qy.value_from_any(other).cast_to(self.type_)._value, ), )
def __lt__(self, other): """ Return the result of a less-than comparison. """ return \ qy.Value.from_low( qy.get().builder.fcmp( llvm.FCMP_OLT, self._value, qy.value_from_any(other).cast_to(self.type_)._value, ), )
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX cleanly handle signedness somehow (explicit "signed" qy value?) type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_DOUBLE: low_value = qy.get().builder.sitofp(self._value, type_, name) elif type_.kind == llvm.TYPE_INTEGER: if self.type_.width == type_.width: low_value = self._value elif self.type_.width < type_.width: low_value = qy.get().builder.sext(self._value, type_, name) elif self.type_.width > type_.width: low_value = qy.get().builder.trunc(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_any(low_value)
def __call__(self, *arguments): """ Emit IR for a function call. """ # sanity if len(arguments) != len(self.argument_types): raise TypeError( "function %s expects %i arguments but received %i" % (self._value.name, len(self.argument_types), len(arguments)) ) # emit the call arguments = map(qy.value_from_any, arguments) coerced = [v.cast_to(a) for (v, a) in zip(arguments, self.argument_types)] return qy.Value.from_low(qy.get().builder.call(self._value, [c.low for c in coerced]))
def decorator(emit): """ Look up or emit the function. """ if name is None: if emit.__name__ == "_": function_name = "function" else: function_name = emit.__name__ else: function_name = name if function_name in qy.get().module.global_variables: return Function.get_named(function_name) else: define_decorator = Function.define( return_type=return_type, argument_types=argument_types, name=name, internal=internal ) return define_decorator(emit)
def cast_to(self, type_, name = ""): """ Cast this value to the specified type. """ # XXX support more casts type_ = qy.type_from_any(type_) low_value = None if type_.kind == llvm.TYPE_DOUBLE: if self.type_.kind == llvm.TYPE_DOUBLE: low_value = self._value if type_.kind == llvm.TYPE_INTEGER: low_value = qy.get().builder.fptosi(self._value, type_, name) if low_value is None: raise CoercionError(self.type_, type_) else: return qy.Value.from_low(low_value)
def store(self, pointer): """ Store this value to the specified pointer. """ return qy.get().builder.store(self._value, pointer._value)
def get_named(name): """ Look up a named function. """ return Function(qy.get().module.get_function_named(name))
def __invert__(self): """ Return the result of bitwise inversion. """ return qy.get().builder.xor(self._value, LLVM_Constant.int(self.type_, -1))