def declare_intrinsic(self, intrinsic, tys=(), fnty=None): def _error(): raise NotImplementedError("unknown intrinsic %r with %d types" % (intrinsic, len(tys))) if intrinsic in {'llvm.cttz', 'llvm.ctlz', 'llvm.fma'}: suffixes = [tys[0].intrinsic_name] else: suffixes = [t.intrinsic_name for t in tys] name = '.'.join([intrinsic] + suffixes) if name in self.globals: return self.globals[name] if fnty is not None: # General case: function type is given pass # Compute function type if omitted for common cases elif len(tys) == 0 and intrinsic == 'llvm.assume': fnty = types.FunctionType(types.VoidType(), [types.IntType(1)]) elif len(tys) == 1: if intrinsic == 'llvm.powi': fnty = types.FunctionType(tys[0], [tys[0], types.IntType(32)]) elif intrinsic == 'llvm.pow': fnty = types.FunctionType(tys[0], tys * 2) elif intrinsic == 'llvm.convert.from.fp16': fnty = types.FunctionType(tys[0], [types.IntType(16)]) elif intrinsic == 'llvm.convert.to.fp16': fnty = types.FunctionType(types.IntType(16), tys) else: fnty = types.FunctionType(tys[0], tys) elif len(tys) == 2: if intrinsic == 'llvm.memset': tys = [tys[0], types.IntType(8), tys[1], types.IntType(1)] fnty = types.FunctionType(types.VoidType(), tys) elif intrinsic in {'llvm.cttz', 'llvm.ctlz'}: tys = [tys[0], types.IntType(1)] fnty = types.FunctionType(tys[0], tys) else: _error() elif len(tys) == 3: if intrinsic in ('llvm.memcpy', 'llvm.memmove'): tys = tys + [types.IntType(1)] fnty = types.FunctionType(types.VoidType(), tys) elif intrinsic == 'llvm.fma': tys = [tys[0]] * 3 fnty = types.FunctionType(tys[0], tys) else: _error() else: _error() return values.Function(self, fnty, name=name)
def load_reg(self, reg_type, reg_name, name=""): """ Load a register value into an LLVM value. Example: v = load_reg(IntType(32), "eax") """ ftype = types.FunctionType(reg_type, []) return self.asm(ftype, "", "={%s}" % reg_name, [], False, name)
def store_reg(self, value, reg_type, reg_name, name=""): """ Store an LLVM value inside a register Example: store_reg(Constant(IntType(32), 0xAAAAAAAA), IntType(32), "eax") """ ftype = types.FunctionType(types.VoidType(), [reg_type]) return self.asm(ftype, "", "{%s}" % reg_name, [value], True, name)
def wrapped(self, lhs, rhs, name=""): if lhs.type != rhs.type: raise ValueError( "Operands must be the same type, got (%s, %s)" % (lhs.type, rhs.type)) ty = lhs.type if not isinstance(ty, types.IntType): raise TypeError("expected an integer type, got %s" % (ty, )) bool_ty = types.IntType(1) mod = self.module fnty = types.FunctionType(types.LiteralStructType([ty, bool_ty]), [ty, ty]) fn = mod.declare_intrinsic("llvm.%s.with.overflow" % (opname, ), [ty], fnty) ret = self.call(fn, [lhs, rhs], name=name) return ret