# # Copyright (c) 2008-10, Mahadevan R All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of this software, nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # """Core classes of LLVM. The llvm.core module contains classes and constants required to build the in-memory intermediate representation (IR) data structures.""" import llvm # top-level, for common stuff import llvm._core as _core # C wrappers import llvm._util as _util # utility functions #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== # type kinds (LLVMTypeKind enum) TYPE_VOID = 0 TYPE_HALF = 1 TYPE_FLOAT = 2 TYPE_DOUBLE = 3 TYPE_X86_FP80 = 4 TYPE_FP128 = 5 TYPE_PPC_FP128 = 6 TYPE_LABEL = 7 TYPE_INTEGER = 8 TYPE_FUNCTION = 9 TYPE_STRUCT = 10 TYPE_ARRAY = 11 TYPE_POINTER = 12 TYPE_VECTOR = 13 TYPE_METADATA = 14 TYPE_X86_MMX = 15 # value IDs (llvm::Value::ValueTy enum) VALUE_ARGUMENT = 0 VALUE_BASIC_BLOCK = 1 VALUE_FUNCTION = 2 VALUE_GLOBAL_ALIAS = 3 VALUE_GLOBAL_VARIABLE = 4 VALUE_UNDEF_VALUE = 5 VALUE_BLOCK_ADDRESS = 6 VALUE_CONSTANT_EXPR = 7 VALUE_CONSTANT_AGGREGATE_ZERO = 8 VALUE_CONSTANT_DATA_ARRAY = 9 VALUE_CONSTANT_DATA_VECTOR = 10 VALUE_CONSTANT_INT = 11 VALUE_CONSTANT_FP = 12 VALUE_CONSTANT_ARRAY = 13 VALUE_CONSTANT_STRUCT = 14 VALUE_CONSTANT_VECTOR = 15 VALUE_CONSTANT_POINTER_NULL = 16 VALUE_MD_NODE = 17 VALUE_MD_STRING = 18 VALUE_INLINE_ASM = 19 VALUE_PSEUDO_SOURCE_VALUE = 20 VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = 21 VALUE_INSTRUCTION = 22 # instruction opcodes (from include/llvm/Instruction.def) OPCODE_RET = 1 OPCODE_BR = 2 OPCODE_SWITCH = 3 OPCODE_INDIRECT_BR = 4 OPCODE_INVOKE = 5 OPCODE_RESUME = 6 OPCODE_UNREACHABLE = 7 OPCODE_ADD = 8 OPCODE_FADD = 9 OPCODE_SUB = 10 OPCODE_FSUB = 11 OPCODE_MUL = 12 OPCODE_FMUL = 13 OPCODE_UDIV = 14 OPCODE_SDIV = 15 OPCODE_FDIV = 16 OPCODE_UREM = 17 OPCODE_SREM = 18 OPCODE_FREM = 19 OPCODE_SHL = 20 OPCODE_LSHR = 21 OPCODE_ASHR = 22 OPCODE_AND = 23 OPCODE_OR = 24 OPCODE_XOR = 25 OPCODE_ALLOCA = 26 OPCODE_LOAD = 27 OPCODE_STORE = 28 OPCODE_GETELEMENTPTR = 29 OPCODE_FENCE = 30 OPCODE_ATOMICCMPXCHG = 31 OPCODE_ATOMICRMW = 32 OPCODE_TRUNC = 33 OPCODE_ZEXT = 34 OPCODE_SEXT = 35 OPCODE_FPTOUI = 36 OPCODE_FPTOSI = 37 OPCODE_UITOFP = 38 OPCODE_SITOFP = 39 OPCODE_FPTRUNC = 40 OPCODE_FPEXT = 41 OPCODE_PTRTOINT = 42 OPCODE_INTTOPTR = 43 OPCODE_BITCAST = 44 OPCODE_ICMP = 45 OPCODE_FCMP = 46 OPCODE_PHI = 47 OPCODE_CALL = 48 OPCODE_SELECT = 49 OPCODE_USEROP1 = 50 OPCODE_USEROP2 = 51 OPCODE_VAARG = 52 OPCODE_EXTRACTELEMENT = 53 OPCODE_INSERTELEMENT = 54 OPCODE_SHUFFLEVECTOR = 55 OPCODE_EXTRACTVALUE = 56 OPCODE_INSERTVALUE = 57 OPCODE_LANDINGPAD = 58 # calling conventions CC_C = 0 CC_FASTCALL = 8 CC_COLDCALL = 9 CC_GHC = 10 CC_X86_STDCALL = 64 CC_X86_FASTCALL = 65 CC_ARM_APCS = 66 CC_ARM_AAPCS = 67 CC_ARM_AAPCS_VFP = 68 CC_MSP430_INTR = 69 CC_X86_THISCALL = 70 CC_PTX_KERNEL = 71 CC_PTX_DEVICE = 72 CC_MBLAZE_INTR = 73 CC_MBLAZE_SVOL = 74 # int predicates ICMP_EQ = 32 ICMP_NE = 33 ICMP_UGT = 34 ICMP_UGE = 35 ICMP_ULT = 36 ICMP_ULE = 37 ICMP_SGT = 38 ICMP_SGE = 39 ICMP_SLT = 40 ICMP_SLE = 41 # same as ICMP_xx, for backward compatibility IPRED_EQ = ICMP_EQ IPRED_NE = ICMP_NE IPRED_UGT = ICMP_UGT IPRED_UGE = ICMP_UGE IPRED_ULT = ICMP_ULT IPRED_ULE = ICMP_ULE IPRED_SGT = ICMP_SGT IPRED_SGE = ICMP_SGE IPRED_SLT = ICMP_SLT IPRED_SLE = ICMP_SLE # real predicates FCMP_FALSE = 0 FCMP_OEQ = 1 FCMP_OGT = 2 FCMP_OGE = 3 FCMP_OLT = 4 FCMP_OLE = 5 FCMP_ONE = 6 FCMP_ORD = 7 FCMP_UNO = 8 FCMP_UEQ = 9 FCMP_UGT = 10 FCMP_UGE = 11 FCMP_ULT = 12 FCMP_ULE = 13 FCMP_UNE = 14 FCMP_TRUE = 15 # real predicates RPRED_FALSE = FCMP_FALSE RPRED_OEQ = FCMP_OEQ RPRED_OGT = FCMP_OGT RPRED_OGE = FCMP_OGE RPRED_OLT = FCMP_OLT RPRED_OLE = FCMP_OLE RPRED_ONE = FCMP_ONE RPRED_ORD = FCMP_ORD RPRED_UNO = FCMP_UNO RPRED_UEQ = FCMP_UEQ RPRED_UGT = FCMP_UGT RPRED_UGE = FCMP_UGE RPRED_ULT = FCMP_ULT RPRED_ULE = FCMP_ULE RPRED_UNE = FCMP_UNE RPRED_TRUE = FCMP_TRUE # linkages (see llvm-c/Core.h) LINKAGE_EXTERNAL = 0 LINKAGE_AVAILABLE_EXTERNALLY = 1 LINKAGE_LINKONCE_ANY = 2 LINKAGE_LINKONCE_ODR = 3 LINKAGE_WEAK_ANY = 4 LINKAGE_WEAK_ODR = 5 LINKAGE_APPENDING = 6 LINKAGE_INTERNAL = 7 LINKAGE_PRIVATE = 8 LINKAGE_DLLIMPORT = 9 LINKAGE_DLLEXPORT = 10 LINKAGE_EXTERNAL_WEAK = 11 LINKAGE_GHOST = 12 LINKAGE_COMMON = 13 LINKAGE_LINKER_PRIVATE = 14 LINKAGE_LINKER_PRIVATE_WEAK = 15 LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 # visibility (see llvm/GlobalValue.h) VISIBILITY_DEFAULT = 0 VISIBILITY_HIDDEN = 1 VISIBILITY_PROTECTED = 2 # parameter attributes (see llvm/Attributes.h) ATTR_NONE = 0 ATTR_ZEXT = 1 ATTR_SEXT = 2 ATTR_NO_RETURN = 4 ATTR_IN_REG = 8 ATTR_STRUCT_RET = 16 ATTR_NO_UNWIND = 32 ATTR_NO_ALIAS = 64 ATTR_BY_VAL = 128 ATTR_NEST = 256 ATTR_READ_NONE = 512 ATTR_READONLY = 1024 ATTR_NO_INLINE = 1<<11 ATTR_ALWAYS_INLINE = 1<<12 ATTR_OPTIMIZE_FOR_SIZE = 1<<13 ATTR_STACK_PROTECT = 1<<14 ATTR_STACK_PROTECT_REQ = 1<<15 ATTR_ALIGNMENT = 1<<16 ATTR_NO_CAPTURE = 1<<21 ATTR_NO_REDZONE = 1<<22 ATTR_NO_IMPLICIT_FLOAT = 1<<23 ATTR_NAKED = 1<<24 ATTR_INLINE_HINT = 1<<25 ATTR_STACK_ALIGNMENT = 7<<26 ATTR_HOTPATCH = 1<<29 # intrinsic IDs from llvm._intrinsic_ids import * #===----------------------------------------------------------------------=== # Helpers (for internal use) #===----------------------------------------------------------------------=== def check_is_type(obj): _util.check_gen(obj, Type) def check_is_type_struct(obj): _util.check_gen(obj, StructType) def check_is_value(obj): _util.check_gen(obj, Value) def check_is_constant(obj): _util.check_gen(obj, Constant) def check_is_function(obj): _util.check_gen(obj, Function) def check_is_global_value(obj): _util.check_gen(obj, GlobalValue) def check_is_basic_block(obj): _util.check_gen(obj, BasicBlock) def check_is_module(obj): _util.check_gen(obj, Module) def unpack_types(objlst): return _util.unpack_gen(objlst, check_is_type) def unpack_values(objlst): return _util.unpack_gen(objlst, check_is_value) def unpack_constants(objlst): return _util.unpack_gen(objlst, check_is_constant) def unpack_values_or_none(objlst): return _util.unpack_gen_allow_none(objlst, check_is_value) def check_is_callable(obj): if isinstance(obj, Function): return typ = obj.type if isinstance(typ, PointerType) and \ isinstance(typ.pointee, FunctionType): return raise TypeError("argument is neither a function nor a function pointer") def _to_int(v): if v: return 1 else: return 0 #===----------------------------------------------------------------------=== # Module #===----------------------------------------------------------------------=== class Module(llvm.Ownable, llvm.Cacheable): """A Module instance stores all the information related to an LLVM module. Modules are the top level container of all other LLVM Intermediate Representation (IR) objects. Each module directly contains a list of globals variables, a list of functions, a list of libraries (or other modules) this module depends on, a symbol table, and various data about the target's characteristics. Construct a Module only using the static methods defined below, *NOT* using the constructor. A correct usage is: module_obj = Module.new('my_module') """ @staticmethod def new(id): """Create a new Module instance. Creates an instance of Module, having the id `id'. """ return Module(_core.LLVMModuleCreateWithName(id)) @staticmethod def from_bitcode(fileobj_or_str): """Create a Module instance from the contents of a bitcode file. fileobj_or_str -- takes a file-like object or string that contains a module represented in bitcode. """ if isinstance(fileobj_or_str, _util.unicode_type): data = fileobj_or_str.encode('utf-8') elif isinstance(fileobj_or_str, bytes): data = fileobj_or_str else: data = fileobj_or_str.read() ret = _core.LLVMGetModuleFromBitcode(data) if not ret: raise llvm.LLVMException("Unable to create module from bitcode") elif _util.isstring(ret): raise llvm.LLVMException(ret) else: return Module(ret) @staticmethod def from_assembly(fileobj_or_str): """Create a Module instance from the contents of an LLVM assembly (.ll) file. fileobj_or_str -- takes a file-like object or string that contains a module represented in llvm-ir assembly. """ if isinstance(fileobj_or_str, _util.unicode_type): data = fileobj_or_str.encode('utf-8') elif isinstance(fileobj_or_str, bytes): data = fileobj_or_str else: data = fileobj_or_str.read() if isinstance(data, _util.unicode_type): data = data.encode() ret = _core.LLVMGetModuleFromAssembly(data) if not ret: raise llvm.LLVMException("Unable to create module from assembly") elif isinstance(ret, str): raise llvm.LLVMException(ret) else: return Module(ret) def __init__(self, ptr): """DO NOT CALL DIRECTLY. Use the static method `Module.new' instead. """ llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule) def __str__(self): """Text representation of a module. Returns the textual representation (`llvm assembly') of the module. Use it like this: ll = str(module_obj) print module_obj # same as `print ll' """ return _core.LLVMDumpModuleToString(self.ptr) def __eq__(self, rhs): if isinstance(rhs, Module): return str(self) == str(rhs) else: return False def __ne__(self, rhs): return not self == rhs def _get_target(self): return _core.LLVMGetTarget(self.ptr) def _set_target(self, value): return _core.LLVMSetTarget(self.ptr, value) target = property(_get_target, _set_target, """The target triple string describing the target host.""" ) def _get_data_layout(self): return _core.LLVMGetDataLayout(self.ptr) def _set_data_layout(self, value): _core.LLVMSetDataLayout(self.ptr, value) data_layout = property(_get_data_layout, _set_data_layout, """The data layout string for the module's target platform. The data layout strings is an encoded representation of the type sizes and alignments expected by this module. """ ) @property def pointer_size(self): """Pointer size of target platform. Can be 0, 32 or 64. Zero represents llvm::Module::AnyPointerSize.""" return _core.LLVMModuleGetPointerSize(self.ptr) def link_in(self, other, preserve=False): """Link the `other' module into this one. The `other' module is linked into this one such that types, global variables, function, etc. are matched and resolved. The `other' module is no longer valid after this method is invoked, all refs to it should be dropped. In the future, this API might be replaced with a full-fledged Linker class. """ check_is_module(other) if not preserve: other.forget() # remove it from object cache result = _core.LLVMLinkModules(self.ptr, other.ptr, int(bool(preserve))) if result is not None: raise llvm.LLVMException(result) if not preserve: # Prevent user from using the other module other.ptr = None # Use a dummy owner to prevent other.ptr to be deleted other._own(llvm.DummyOwner()) def get_type_named(self, name): """Return a Type object with the given name.""" ptr = _core.LLVMGetTypeByName(self.ptr, name) if ptr: kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) return None def add_global_variable(self, ty, name, addrspace=0): """Add a global variable of given type with given name.""" return GlobalVariable.new(self, ty, name, addrspace) def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" return GlobalVariable.get(self, name) @property def global_variables(self): """All global variables in this module.""" return _util.wrapiter(_core.LLVMGetFirstGlobal, _core.LLVMGetNextGlobal, self.ptr, _make_value) def add_function(self, ty, name): """Add a function of given type with given name.""" return Function.new(self, ty, name) def get_function_named(self, name): """Return a Function object representing function with given name.""" return Function.get(self, name) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" return Function.get_or_insert(self, ty, name) @property def functions(self): """All functions in this module.""" return _util.wrapiter(_core.LLVMGetFirstFunction, _core.LLVMGetNextFunction, self.ptr, _make_value) def verify(self): """Verify module. Checks module for errors. Raises `llvm.LLVMException' on any error.""" ret = _core.LLVMVerifyModule(self.ptr) # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. if ret != "": raise llvm.LLVMException(ret) def to_bitcode(self, fileobj=None): """Write bitcode representation of module to given file-like object. fileobj -- A file-like object to where the bitcode is written. If it is None, the bitcode is returned. Return value -- Returns None if fileobj is not None. Otherwise, return the bitcode as a bytestring. """ data = _core.LLVMGetBitcodeFromModule(self.ptr) if not data: raise llvm.LLVMException("Unable to create bitcode") if fileobj is not None: fileobj.write(data) else: return data def add_library(self, name): return _core.LLVMModuleAddLibrary(self.ptr, name) def _get_id(self): return _core.LLVMGetModuleIdentifier(self.ptr) def _set_id(self, string): _core.LLVMSetModuleIdentifier(self.ptr, string) id = property(_get_id, _set_id) def to_native_object(self, fileobj=None): '''Outputs the byte string of the module as native object code If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' data = _core.LLVMGetNativeCodeFromModule(self.ptr, 0) if fileobj is not None: fileobj.write(data) else: return data def to_native_assembly(self, fileobj=None): '''Outputs the byte string of the module as native assembly code If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' data = _core.LLVMGetNativeCodeFromModule(self.ptr, 1) if fileobj is not None: fileobj.write(data) else: return data def get_or_insert_named_metadata(self, name): ptr = _core.LLVMModuleGetOrInsertNamedMetaData(self.ptr, name) return NamedMetaData(ptr) def get_named_metadata(self, name): ptr = _core.LLVMModuleGetNamedMetaData(self.ptr, name) return NamedMetaData(ptr) def clone(self): return Module(_core.LLVMCloneModule(self.ptr)) #===----------------------------------------------------------------------=== # Types #===----------------------------------------------------------------------=== class Type(object): """Represents a type, like a 32-bit integer or an 80-bit x86 float. Use one of the static methods to create an instance. Example: ty = Type.double() """ @staticmethod def int(bits=32): """Create an integer type having the given bit width.""" if bits == 1: return _make_type(_core.LLVMInt1Type(), TYPE_INTEGER) elif bits == 8: return _make_type(_core.LLVMInt8Type(), TYPE_INTEGER) elif bits == 16: return _make_type(_core.LLVMInt16Type(), TYPE_INTEGER) elif bits == 32: return _make_type(_core.LLVMInt32Type(), TYPE_INTEGER) elif bits == 64: return _make_type(_core.LLVMInt64Type(), TYPE_INTEGER) else: bits = int(bits) # bits must be an int return _make_type(_core.LLVMIntType(bits), TYPE_INTEGER) @staticmethod def float(): """Create a 32-bit floating point type.""" return _make_type(_core.LLVMFloatType(), TYPE_FLOAT) @staticmethod def double(): """Create a 64-bit floating point type.""" return _make_type(_core.LLVMDoubleType(), TYPE_DOUBLE) @staticmethod def x86_fp80(): """Create a 80-bit x86 floating point type.""" return _make_type(_core.LLVMX86FP80Type(), TYPE_X86_FP80) @staticmethod def fp128(): """Create a 128-bit floating point type (with 112-bit mantissa).""" return _make_type(_core.LLVMFP128Type(), TYPE_FP128) @staticmethod def ppc_fp128(): """Create a 128-bit floating point type (two 64-bits).""" return _make_type(_core.LLVMPPCFP128Type(), TYPE_PPC_FP128) @staticmethod def function(return_ty, param_tys, var_arg=False): """Create a function type. Creates a function type that returns a value of type `return_ty', takes arguments of types as given in the iterable `param_tys'. Set `var_arg' to True (default is False) for a variadic function.""" check_is_type(return_ty) var_arg = _to_int(var_arg) # ensure int params = unpack_types(param_tys) return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, var_arg), TYPE_FUNCTION) @staticmethod def opaque(name): """Create a opaque StructType""" if not name: raise llvm.LLVMException("Must specify a name") objptr = _core.LLVMStructTypeIdentified(name) return _make_type(objptr, TYPE_STRUCT) @staticmethod def struct(element_tys, name=''): # not packed """Create a (unpacked) structure type. Creates a structure type with elements of types as given in the iterable `element_tys'. This method creates a unpacked structure. For a packed one, use the packed_struct() method. If name is not '', creates a identified type; otherwise, creates a literal type.""" return Type.__struct(element_tys, packed=False, name=name) @staticmethod def packed_struct(element_tys, name=''): """Create a (packed) structure type. Creates a structure type with elements of types as given in the iterable `element_tys'. This method creates a packed structure. For an unpacked one, use the struct() method. If name is not '', creates a identified type; otherwise, creates a literal type.""" return Type.__struct(element_tys, packed=True, name=name) @staticmethod def __struct(element_tys, packed, name): elems = unpack_types(element_tys) packed = int(bool(packed)) if name: # create Identified StructType objptr = _core.LLVMStructTypeIdentified(name) _core.LLVMSetStructBody(objptr, elems, packed) else: # create Literal StructType objptr = _core.LLVMStructType(elems, packed) return _make_type(objptr, TYPE_STRUCT) @staticmethod def array(element_ty, count): """Create an array type. Creates a type for an array of elements of type `element_ty', having 'count' elements.""" check_is_type(element_ty) count = int(count) # must be an int return _make_type(_core.LLVMArrayType(element_ty.ptr, count), TYPE_ARRAY) @staticmethod def pointer(pointee_ty, addr_space=0): """Create a pointer type. Creates a pointer type, which can point to values of type `pointee_ty', in the address space `addr_space'.""" check_is_type(pointee_ty) addr_space = int(addr_space) # must be an int return _make_type(_core.LLVMPointerType(pointee_ty.ptr, addr_space), TYPE_POINTER) @staticmethod def vector(element_ty, count): """Create a vector type. Creates a type for a vector of elements of type `element_ty', having `count' elements.""" check_is_type(element_ty) count = int(count) # must be an int return _make_type(_core.LLVMVectorType(element_ty.ptr, count), TYPE_VECTOR) @staticmethod def void(): """Create a void type. Represents the `void' type.""" return _make_type(_core.LLVMVoidType(), TYPE_VOID) @staticmethod def label(): """Create a label type.""" return _make_type(_core.LLVMLabelType(), TYPE_LABEL) def __init__(self, ptr, kind): """DO NOT CALL DIRECTLY. Use one of the static methods instead.""" self.ptr = ptr self.kind = kind """An enum (int) value denoting which type this is. Use the symbolic constants TYPE_* defined in llvm.core module.""" def __str__(self): """Text representation of a type. Returns the textual representation (`llvm assembly') of the type.""" return _core.LLVMDumpTypeToString(self.ptr) def __eq__(self, rhs): if isinstance(rhs, Type): return str(self) == str(rhs) else: return False def __ne__(self, rhs): return not self == rhs class IntegerType(Type): """Represents an integer type.""" @property def width(self): """The width of the integer type, in bits.""" return _core.LLVMGetIntTypeWidth(self.ptr) class FunctionType(Type): """Represents a function type.""" @property def return_type(self): """The type of the value returned by this function.""" ptr = _core.LLVMGetReturnType(self.ptr) kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) @property def vararg(self): """True if this function is variadic.""" return _core.LLVMIsFunctionVarArg(self.ptr) != 0 @property def args(self): """An iterable that yields Type objects, representing the types of the arguments accepted by this function, in order.""" pp = _core.LLVMGetFunctionTypeParams(self.ptr) return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] @property def arg_count(self): """Number of arguments accepted by this function. Same as len(obj.args), but faster.""" return _core.LLVMCountParamTypes(self.ptr) class StructType(Type): """Represents a structure type.""" @property def element_count(self): """Number of elements (members) in the structure. Same as len(obj.elements), but faster.""" return _core.LLVMCountStructElementTypes(self.ptr) @property def elements(self): """An iterable that yieldsd Type objects, representing the types of the elements (members) of the structure, in order.""" pp = _core.LLVMGetStructElementTypes(self.ptr) return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] def set_body(self, elems, packed=False): """Filled the body of a opaque type. """ # check if not self.is_opaque: raise llvm.LLVMException("Body is already defined.") # prepare arguments elems = unpack_types(elems) if packed: packed = 1 else: packed = 0 # call c API _core.LLVMSetStructBody(self.ptr, elems, packed) @property def packed(self): """True if the structure is packed, False otherwise.""" return _core.LLVMIsPackedStruct(self.ptr) != 0 def _set_name(self, name): _core.LLVMSetStructName(self.ptr, name) def _get_name(self): return _core.LLVMGetStructName(self.ptr) name = property(_get_name, _set_name) @property def is_literal(self): return bool(_core.LLVMIsLiteralStruct(self.ptr)) @property def is_identified(self): return not _core.LLVMIsLiteralStruct(self.ptr) @property def is_opaque(self): return bool(_core.LLVMIsOpaqueStruct(self.ptr)) class ArrayType(Type): """Represents an array type.""" @property def element(self): ptr = _core.LLVMGetElementType(self.ptr) kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) @property def count(self): return _core.LLVMGetArrayLength(self.ptr) class PointerType(Type): @property def pointee(self): ptr = _core.LLVMGetElementType(self.ptr) kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) @property def address_space(self): return _core.LLVMGetPointerAddressSpace(self.ptr) class VectorType(Type): @property def element(self): ptr = _core.LLVMGetElementType(self.ptr) kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) @property def count(self): return _core.LLVMGetVectorSize(self.ptr) #===----------------------------------------------------------------------=== # Type factory method #===----------------------------------------------------------------------=== # type ID -> class map __class_for_typeid = { TYPE_INTEGER : IntegerType, TYPE_FUNCTION : FunctionType, TYPE_STRUCT : StructType, TYPE_ARRAY : ArrayType, TYPE_POINTER : PointerType, TYPE_VECTOR : VectorType, } def _make_type(ptr, kind): class_obj = __class_for_typeid.get(kind) if class_obj: return class_obj(ptr, kind) else: # "generic" type return Type(ptr, kind) #===----------------------------------------------------------------------=== # Values #===----------------------------------------------------------------------=== class Value(llvm.Cacheable): def __init__(self, ptr): self.ptr = ptr def __str__(self): return _core.LLVMDumpValueToString(self.ptr) def __eq__(self, rhs): if isinstance(rhs, Value): return str(self) == str(rhs) else: return False def __ne__(self, rhs): return not self == rhs def _get_name(self): return _core.LLVMGetValueName(self.ptr) def _set_name(self, value): return _core.LLVMSetValueName(self.ptr, value) name = property(_get_name, _set_name) @property def value_id(self): return _core.LLVMValueGetID(self.ptr) @property def type(self): ptr = _core.LLVMTypeOf(self.ptr) kind = _core.LLVMGetTypeKind(ptr) return _make_type(ptr, kind) @property def use_count(self): return _core.LLVMValueGetNumUses(self.ptr) @property def uses(self): return [ _make_value(v) for v in _core.LLVMValueGetUses(self.ptr) ] class User(Value): @property def operand_count(self): return _core.LLVMUserGetNumOperands(self.ptr) @property def operands(self): """Yields operands of this instruction.""" return [self._get_operand(i) for i in range(self.operand_count)] def _get_operand(self, i): return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) class Constant(User): @staticmethod def null(ty): check_is_type(ty) return _make_value(_core.LLVMConstNull(ty.ptr)) @staticmethod def all_ones(ty): check_is_type(ty) return _make_value(_core.LLVMConstAllOnes(ty.ptr)) @staticmethod def undef(ty): check_is_type(ty) return _make_value(_core.LLVMGetUndef(ty.ptr)) @staticmethod def int(ty, value): check_is_type(ty) return _make_value(_core.LLVMConstInt(ty.ptr, value, 0)) @staticmethod def int_signextend(ty, value): check_is_type(ty) return _make_value(_core.LLVMConstInt(ty.ptr, value, 1)) @staticmethod def real(ty, value): check_is_type(ty) if isinstance(value, str): return _make_value(_core.LLVMConstRealOfString(ty.ptr, value)) else: return _make_value(_core.LLVMConstReal(ty.ptr, value)) @staticmethod def string(strval): # dont_null_terminate=True return _make_value(_core.LLVMConstString(strval, 1)) @staticmethod def stringz(strval): # dont_null_terminate=False return _make_value(_core.LLVMConstString(strval, 0)) @staticmethod def array(ty, consts): check_is_type(ty) const_ptrs = unpack_constants(consts) return _make_value(_core.LLVMConstArray(ty.ptr, const_ptrs)) @staticmethod def struct(consts): # not packed const_ptrs = unpack_constants(consts) return _make_value(_core.LLVMConstStruct(const_ptrs, 0)) @staticmethod def packed_struct(consts): const_ptrs = unpack_constants(consts) return _make_value(_core.LLVMConstStruct(const_ptrs, 1)) @staticmethod def vector(consts): const_ptrs = unpack_constants(consts) return _make_value(_core.LLVMConstVector(const_ptrs)) @staticmethod def sizeof(ty): check_is_type(ty) return _make_value(_core.LLVMSizeOf(ty.ptr)) def neg(self): return _make_value(_core.LLVMConstNeg(self.ptr)) def not_(self): return _make_value(_core.LLVMConstNot(self.ptr)) def add(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstAdd(self.ptr, rhs.ptr)) def fadd(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFAdd(self.ptr, rhs.ptr)) def sub(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstSub(self.ptr, rhs.ptr)) def fsub(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFSub(self.ptr, rhs.ptr)) def mul(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstMul(self.ptr, rhs.ptr)) def fmul(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFMul(self.ptr, rhs.ptr)) def udiv(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstUDiv(self.ptr, rhs.ptr)) def sdiv(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstSDiv(self.ptr, rhs.ptr)) def fdiv(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFDiv(self.ptr, rhs.ptr)) def urem(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstURem(self.ptr, rhs.ptr)) def srem(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstSRem(self.ptr, rhs.ptr)) def frem(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFRem(self.ptr, rhs.ptr)) def and_(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstAnd(self.ptr, rhs.ptr)) def or_(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstOr(self.ptr, rhs.ptr)) def xor(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstXor(self.ptr, rhs.ptr)) def icmp(self, int_pred, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstICmp(int_pred, self.ptr, rhs.ptr)) def fcmp(self, real_pred, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstFCmp(real_pred, self.ptr, rhs.ptr)) def shl(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstShl(self.ptr, rhs.ptr)) def lshr(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstLShr(self.ptr, rhs.ptr)) def ashr(self, rhs): check_is_constant(rhs) return _make_value(_core.LLVMConstAShr(self.ptr, rhs.ptr)) def gep(self, indices): index_ptrs = unpack_constants(indices) return _make_value(_core.LLVMConstGEP(self.ptr, index_ptrs)) def trunc(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstTrunc(self.ptr, ty.ptr)) def sext(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstSExt(self.ptr, ty.ptr)) def zext(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstZExt(self.ptr, ty.ptr)) def fptrunc(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstFPTrunc(self.ptr, ty.ptr)) def fpext(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstFPExt(self.ptr, ty.ptr)) def uitofp(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstUIToFP(self.ptr, ty.ptr)) def sitofp(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstSIToFP(self.ptr, ty.ptr)) def fptoui(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstFPToUI(self.ptr, ty.ptr)) def fptosi(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstFPToSI(self.ptr, ty.ptr)) def ptrtoint(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstPtrToInt(self.ptr, ty.ptr)) def inttoptr(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstIntToPtr(self.ptr, ty.ptr)) def bitcast(self, ty): check_is_type(ty) return _make_value(_core.LLVMConstBitCast(self.ptr, ty.ptr)) def select(self, true_const, false_const): check_is_constant(true_const) check_is_constant(false_const) return _make_value( _core.LLVMConstSelect(self.ptr, true_const.ptr, false_const.ptr)) def extract_element(self, index): # note: self must be a _vector_ constant check_is_constant(index) return _make_value( _core.LLVMConstExtractElement(self.ptr, index.ptr)) def insert_element(self, value, index): # note: self must be a _vector_ constant check_is_constant(value) check_is_constant(index) return _make_value( _core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr)) def shuffle_vector(self, vector_b, mask): # note: self must be a _vector_ constant check_is_constant(vector_b) # note: vector_b must be a _vector_ constant check_is_constant(mask) return _make_value( _core.LLVMConstShuffleVector(self.ptr, vector_b.ptr, mask.ptr)) class ConstantExpr(Constant): @property def opcode(self): return _core.LLVMGetConstExprOpcode(self.ptr) @property def opcode_name(self): return _core.LLVMGetConstExprOpcodeName(self.ptr) class ConstantAggregateZero(Constant): pass class ConstantDataArray(Constant): pass class ConstantDataVector(Constant): pass class ConstantInt(Constant): @property def z_ext_value(self): '''Obtain the zero extended value for an integer constant value.''' # Warning: assertion failure when value does not fit in 64 bits return _core.LLVMConstIntGetZExtValue(self.ptr) @property def s_ext_value(self): '''Obtain the sign extended value for an integer constant value.''' # Warning: assertion failure when value does not fit in 64 bits return _core.LLVMConstIntGetSExtValue(self.ptr) class ConstantFP(Constant): pass class ConstantArray(Constant): pass class ConstantStruct(Constant): pass class ConstantVector(Constant): pass class ConstantPointerNull(Constant): pass class UndefValue(Constant): pass class GlobalValue(Constant): def __init__(self, ptr): Constant.__init__(self, ptr) # Hang on to the module, don't let it die before we do. # It is nice to have just a map of functions without # retaining a ref to the owning module. self._module_obj = self.module def _delete(self): # Called in subclass delete() methods. self._module_obj = None def _get_linkage(self): return _core.LLVMGetLinkage(self.ptr) def _set_linkage(self, value): _core.LLVMSetLinkage(self.ptr, value) linkage = property(_get_linkage, _set_linkage) def _get_section(self): return _core.LLVMGetSection(self.ptr) def _set_section(self, value): return _core.LLVMSetSection(self.ptr, value) section = property(_get_section, _set_section) def _get_visibility(self): return _core.LLVMGetVisibility(self.ptr) def _set_visibility(self, value): return _core.LLVMSetVisibility(self.ptr, value) visibility = property(_get_visibility, _set_visibility) def _get_alignment(self): return _core.LLVMGetAlignment(self.ptr) def _set_alignment(self, value): return _core.LLVMSetAlignment(self.ptr, value) alignment = property(_get_alignment, _set_alignment) @property def is_declaration(self): return _core.LLVMIsDeclaration(self.ptr) != 0 @property def module(self): return Module(_core.LLVMGetGlobalParent(self.ptr)) class GlobalVariable(GlobalValue): @staticmethod def new(module, ty, name, addrspace=0): check_is_module(module) check_is_type(ty) return _make_value(_core.LLVMAddGlobalInAddressSpace(module.ptr, ty.ptr, name, addrspace)) @staticmethod def get(module, name): check_is_module(module) ptr = _core.LLVMGetNamedGlobal(module.ptr, name) if not ptr: raise llvm.LLVMException("no global named `%s`" % name) return _make_value(ptr) def delete(self): self._delete() _core.LLVMDeleteGlobal(self.ptr) self.forget() self.ptr = None def _get_initializer(self): if _core.LLVMHasInitializer(self.ptr): return _make_value(_core.LLVMGetInitializer(self.ptr)) else: return None def _set_initializer(self, const): check_is_constant(const) _core.LLVMSetInitializer(self.ptr, const.ptr) def _del_initializer(self): check_is_constant(const) initializer = property(_get_initializer, _set_initializer) def _get_is_global_constant(self): return _core.LLVMIsGlobalConstant(self.ptr) def _set_is_global_constant(self, value): value = _to_int(value) _core.LLVMSetGlobalConstant(self.ptr, value) global_constant = \ property(_get_is_global_constant, _set_is_global_constant) def _get_thread_local(self): return bool(_core.LLVMIsThreadLocal(self.ptr)) def _set_thread_local(self, value): value = _to_int(value) _core.LLVMSetThreadLocal(self.ptr, value) thread_local = property(_get_thread_local, _set_thread_local) class Argument(Value): def add_attribute(self, attr): _core.LLVMAddAttribute(self.ptr, attr) def remove_attribute(self, attr): _core.LLVMRemoveAttribute(self.ptr, attr) def _set_alignment(self, align): _core.LLVMSetParamAlignment(self.ptr, align) def _get_alignment(self): return _core.LLVMGetParamAlignment(self.ptr) alignment = \ property(_get_alignment, _set_alignment) class Function(GlobalValue): @staticmethod def new(module, func_ty, name): check_is_module(module) check_is_type(func_ty) return _make_value(_core.LLVMAddFunction(module.ptr, name, func_ty.ptr)) @staticmethod def get_or_insert(module, func_ty, name): check_is_module(module) check_is_type(func_ty) return _make_value(_core.LLVMModuleGetOrInsertFunction(module.ptr, name, func_ty.ptr)) @staticmethod def get(module, name): check_is_module(module) ptr = _core.LLVMGetNamedFunction(module.ptr, name) if not ptr: raise llvm.LLVMException("no function named `%s`" % name) return _make_value(ptr) @staticmethod def intrinsic(module, intrinsic_id, types): check_is_module(module) ptrs = unpack_types(types) return _make_value( _core.LLVMGetIntrinsic(module.ptr, intrinsic_id, ptrs)) def delete(self): self._delete() _core.LLVMDeleteFunction(self.ptr) self.forget() self.ptr = None @property def intrinsic_id(self): return _core.LLVMGetIntrinsicID(self.ptr) def _get_cc(self): return _core.LLVMGetFunctionCallConv(self.ptr) def _set_cc(self, value): _core.LLVMSetFunctionCallConv(self.ptr, value) calling_convention = property(_get_cc, _set_cc) def _get_coll(self): return _core.LLVMGetGC(self.ptr) def _set_coll(self, value): _core.LLVMSetGC(self.ptr, value) collector = property(_get_coll, _set_coll) # the nounwind attribute: def _get_does_not_throw(self): return _core.LLVMGetDoesNotThrow(self.ptr) def _set_does_not_throw(self,value): _core.LLVMSetDoesNotThrow(self.ptr, value) does_not_throw = property(_get_does_not_throw, _set_does_not_throw) @property def args(self): return _util.wrapiter(_core.LLVMGetFirstParam, _core.LLVMGetNextParam, self.ptr, _make_value) @property def basic_block_count(self): return _core.LLVMCountBasicBlocks(self.ptr) @property def entry_basic_block(self): if self.basic_block_count == 0: return None return _make_value(_core.LLVMGetEntryBasicBlock(self.ptr)) def get_entry_basic_block(self): """Deprecated, use entry_basic_block property.""" return self.entry_basic_block def append_basic_block(self, name): return _make_value(_core.LLVMAppendBasicBlock(self.ptr, name)) @property def basic_blocks(self): return _util.wrapiter(_core.LLVMGetFirstBasicBlock, _core.LLVMGetNextBasicBlock, self.ptr, _make_value) def viewCFG(self): return _core.LLVMViewFunctionCFG(self.ptr) def add_attribute(self, attr): _core.LLVMAddFunctionAttr(self.ptr, attr) def remove_attribute(self, attr): _core.LLVMRemoveFunctionAttr(self.ptr, attr) def viewCFGOnly(self): return _core.LLVMViewFunctionCFGOnly(self.ptr) def verify(self): # Although we're just asking LLVM to return the success or # failure, it appears to print result to stderr and abort. # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. return _core.LLVMVerifyFunction(self.ptr) != 0 #===----------------------------------------------------------------------=== # InlineAsm #===----------------------------------------------------------------------=== class InlineAsm(Value): @staticmethod def get(functype, asm, constrains, side_effect=False, align_stack=False, dialect=0): assert dialect == 0, "LLVM 3.1 does not implement dialect selection" check_is_type(functype) pycap = _core.LLVMGetFunctionFromInlineAsm(functype.ptr, asm, constrains, int(side_effect), int(align_stack), dialect) return _make_value(pycap) #===----------------------------------------------------------------------=== # MetaData #===----------------------------------------------------------------------=== class MetaData(Value): @staticmethod def get(module, values): ''' values -- must be an iterable of Constant or None. None is treated as "null". ''' vs = unpack_values_or_none(values) ptr = _core.LLVMMetaDataGet(module.ptr, vs) return MetaData(ptr) @staticmethod def get_named_operands(module, name): lst = _core.LLVMGetNamedMetadataOperands(module.ptr, name) return [MetaData(ptr) for ptr in lst] @staticmethod def add_named_operand(module, name, operand): _core.LLVMAddNamedMetadataOperand(module.ptr, name, operand.ptr) @property def operand_count(self): return _core.LLVMMetaDataGetNumOperands(self.ptr) @property def operands(self): """Yields operands of this metadata.""" return [self._get_operand(i) for i in range(self.operand_count)] def _get_operand(self, i): val = _core.LLVMMetaDataGetOperand(self.ptr, i) if val: # metadata operands can be None return _make_value(val) class MetaDataString(Value): @staticmethod def get(module, s): ptr = _core.LLVMMetaDataStringGet(module.ptr, s) return MetaDataString(ptr) @property def string(self): '''Same as MDString::getString''' return self.name class NamedMetaData(llvm.Cacheable): @staticmethod def get_or_insert(mod, name): return mod.get_or_insert_named_metadata(name) @staticmethod def get(mod, name): return mod.get_named_metadata(name) def __init__(self, ptr): self.ptr = ptr def delete(self): _core.LLVMEraseNamedMetaData(self.ptr) @property def name(self): return _core.LLVMNamedMetaDataGetName(self.ptr) def __str__(self): return _core.LLVMDumpNamedMDToString(self.ptr) def add(self, operand): _core.LLVMNamedMetaDataAddOperand(self.ptr, operand.ptr) #===----------------------------------------------------------------------=== # Instruction #===----------------------------------------------------------------------=== class Instruction(User): @property def basic_block(self): return _make_value(_core.LLVMGetInstructionParent(self.ptr)) @property def is_terminator(self): return _core.LLVMInstIsTerminator(self.ptr) != 0 @property def is_binary_op(self): return _core.LLVMInstIsBinaryOp(self.ptr) != 0 @property def is_shift(self): return _core.LLVMInstIsShift(self.ptr) != 0 @property def is_cast(self): return _core.LLVMInstIsCast(self.ptr) != 0 @property def is_logical_shift(self): return _core.LLVMInstIsLogicalShift(self.ptr) != 0 @property def is_arithmetic_shift(self): return _core.LLVMInstIsArithmeticShift(self.ptr) != 0 @property def is_associative(self): return _core.LLVMInstIsAssociative(self.ptr) != 0 @property def is_commutative(self): return _core.LLVMInstIsCommutative(self.ptr) != 0 @property def is_volatile(self): """True if this is a volatile load or store.""" return _core.LLVMInstIsVolatile(self.ptr) != 0 def set_volatile(self, flag): return _core.LLVMSetVolatile(self.ptr, int(bool(flag))) def set_metadata(self, kind, metadata): return _core.LLVMInstSetMetaData(self.ptr, kind, metadata.ptr) @property def opcode(self): return _core.LLVMInstGetOpcode(self.ptr) @property def opcode_name(self): return _core.LLVMInstGetOpcodeName(self.ptr) def erase_from_parent(self): return _core.LLVMInstructionEraseFromParent(self.ptr) class CallOrInvokeInstruction(Instruction): def _get_cc(self): return _core.LLVMGetInstructionCallConv(self.ptr) def _set_cc(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value) calling_convention = property(_get_cc, _set_cc) def add_parameter_attribute(self, idx, attr): _core.LLVMAddInstrAttribute(self.ptr, idx, attr) def remove_parameter_attribute(self, idx, attr): _core.LLVMRemoveInstrAttribute(self.ptr, idx, attr) def set_parameter_alignment(self, idx, align): _core.LLVMSetInstrParamAlignment(self.ptr, idx, align) def _get_called_function(self): function = _core.LLVMInstGetCalledFunction(self.ptr) if function: # Return value can be None on indirect call/invoke return _make_value(function) def _set_called_function(self, function): _core.LLVMInstSetCalledFunction(self.ptr, function.ptr) called_function = property(_get_called_function, _set_called_function) # tail call is valid only for 'call', not 'invoke' # disabled for now #def _get_tc(self): return _core.LLVMIsTailCall(self.ptr) #def _set_tc(self, value): _core.LLVMSetTailCall(self.ptr, value) #tail_call = property(_get_tc, _set_tc) class PHINode(Instruction): @property def incoming_count(self): return _core.LLVMCountIncoming(self.ptr) def add_incoming(self, value, block): check_is_value(value) check_is_basic_block(block) _core.LLVMAddIncoming1(self.ptr, value.ptr, block.ptr) def get_incoming_value(self, idx): return _make_value(_core.LLVMGetIncomingValue(self.ptr, idx)) def get_incoming_block(self, idx): return _make_value(_core.LLVMGetIncomingBlock(self.ptr, idx)) class SwitchInstruction(Instruction): def add_case(self, const, bblk): check_is_constant(const) # and has to be an int too check_is_basic_block(bblk) _core.LLVMAddCase(self.ptr, const.ptr, bblk.ptr) class CompareInstruction(Instruction): @property def predicate(self): return _core.LLVMCmpInstGetPredicate(self.ptr) #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== class BasicBlock(Value): def insert_before(self, name): return _make_value(_core.LLVMInsertBasicBlock(self.ptr, name)) def delete(self): _core.LLVMDeleteBasicBlock(self.ptr) self.forget() self.ptr = None @property def function(self): func_ptr = _core.LLVMGetBasicBlockParent(self.ptr) return _make_value(func_ptr) @property def instructions(self): return _util.wrapiter(_core.LLVMGetFirstInstruction, _core.LLVMGetNextInstruction, self.ptr, _make_value) #===----------------------------------------------------------------------=== # Value factory method #===----------------------------------------------------------------------=== # value ID -> class map __class_for_valueid = { VALUE_ARGUMENT : Argument, VALUE_BASIC_BLOCK : BasicBlock, VALUE_FUNCTION : Function, VALUE_GLOBAL_ALIAS : GlobalValue, VALUE_GLOBAL_VARIABLE : GlobalVariable, VALUE_UNDEF_VALUE : UndefValue, VALUE_CONSTANT_EXPR : ConstantExpr, VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, VALUE_CONSTANT_INT : ConstantInt, VALUE_CONSTANT_FP : ConstantFP, VALUE_CONSTANT_ARRAY : ConstantArray, VALUE_CONSTANT_STRUCT : ConstantStruct, VALUE_CONSTANT_VECTOR : ConstantVector, VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, VALUE_MD_NODE : MetaData, VALUE_MD_STRING : MetaDataString, VALUE_INLINE_ASM : InlineAsm, VALUE_INSTRUCTION + OPCODE_PHI : PHINode, VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction } def _make_value(ptr): kind = _core.LLVMValueGetID(ptr) # based on kind, create one of the Value subclasses class_obj = __class_for_valueid.get(kind) if class_obj: return class_obj(ptr) elif kind > VALUE_INSTRUCTION: # "generic" instruction return Instruction(ptr) else: # "generic" value return Value(ptr) #===----------------------------------------------------------------------=== # Builder #===----------------------------------------------------------------------=== class Builder(object): @staticmethod def new(basic_block): check_is_basic_block(basic_block) b = Builder(_core.LLVMCreateBuilder()) b.position_at_end(basic_block) return b def __init__(self, ptr): self.ptr = ptr def __del__(self): _core.LLVMDisposeBuilder(self.ptr) def position_at_beginning(self, bblk): """Position the builder at the beginning of the given block. Next instruction inserted will be first one in the block.""" check_is_basic_block(bblk) # Avoids using "blk.instructions", which will fetch all the # instructions into a list. Don't try this at home, though. inst_ptr = _core.LLVMGetFirstInstruction(bblk.ptr) if inst_ptr: # Issue #10: inst_ptr can be None if b/b has no insts. inst = _make_value(inst_ptr) self.position_before(inst) def position_at_end(self, bblk): """Position the builder at the end of the given block. Next instruction inserted will be last one in the block.""" _core.LLVMPositionBuilderAtEnd(self.ptr, bblk.ptr) def position_before(self, instr): """Position the builder before the given instruction. The instruction can belong to a basic block other than the current one.""" _core.LLVMPositionBuilderBefore(self.ptr, instr.ptr) @property def block(self): """Deprecated, use basic_block property instead.""" return _make_value(_core.LLVMGetInsertBlock(self.ptr)) @property def basic_block(self): """The basic block where the builder is positioned.""" return _make_value(_core.LLVMGetInsertBlock(self.ptr)) # terminator instructions def ret_void(self): return _make_value(_core.LLVMBuildRetVoid(self.ptr)) def ret(self, value): check_is_value(value) return _make_value(_core.LLVMBuildRet(self.ptr, value.ptr)) def ret_many(self, values): vs = unpack_values(values) return _make_value(_core.LLVMBuildRetMultiple(self.ptr, vs)) def branch(self, bblk): check_is_basic_block(bblk) if __debug__: for instr in self.basic_block.instructions: assert not instr.is_terminator, "BasicBlock can only have one terminator" return _make_value(_core.LLVMBuildBr(self.ptr, bblk.ptr)) def cbranch(self, if_value, then_blk, else_blk): check_is_value(if_value) check_is_basic_block(then_blk) check_is_basic_block(else_blk) return _make_value( _core.LLVMBuildCondBr(self.ptr, if_value.ptr, then_blk.ptr, else_blk.ptr)) def switch(self, value, else_blk, n=10): check_is_value(value) # value has to be of any 'int' type check_is_basic_block(else_blk) return _make_value( _core.LLVMBuildSwitch(self.ptr, value.ptr, else_blk.ptr, n)) def invoke(self, func, args, then_blk, catch_blk, name=""): check_is_callable(func) check_is_basic_block(then_blk) check_is_basic_block(catch_blk) args2 = unpack_values(args) return _make_value( _core.LLVMBuildInvoke(self.ptr, func.ptr, args2, then_blk.ptr, catch_blk.ptr, name)) def unreachable(self): return _make_value(_core.LLVMBuildUnreachable(self.ptr)) # arithmethic, bitwise and logical def add(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildAdd(self.ptr, lhs.ptr, rhs.ptr, name)) def fadd(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildFAdd(self.ptr, lhs.ptr, rhs.ptr, name)) def sub(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildSub(self.ptr, lhs.ptr, rhs.ptr, name)) def fsub(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildFSub(self.ptr, lhs.ptr, rhs.ptr, name)) def mul(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildMul(self.ptr, lhs.ptr, rhs.ptr, name)) def fmul(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value(_core.LLVMBuildFMul(self.ptr, lhs.ptr, rhs.ptr, name)) def udiv(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildUDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def sdiv(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildSDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def fdiv(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildFDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def urem(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildURem(self.ptr, lhs.ptr, rhs.ptr, name)) def srem(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildSRem(self.ptr, lhs.ptr, rhs.ptr, name)) def frem(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildFRem(self.ptr, lhs.ptr, rhs.ptr, name)) def shl(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildShl(self.ptr, lhs.ptr, rhs.ptr, name)) def lshr(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildLShr(self.ptr, lhs.ptr, rhs.ptr, name)) def ashr(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildAShr(self.ptr, lhs.ptr, rhs.ptr, name)) def and_(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildAnd(self.ptr, lhs.ptr, rhs.ptr, name)) def or_(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildOr(self.ptr, lhs.ptr, rhs.ptr, name)) def xor(self, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildXor(self.ptr, lhs.ptr, rhs.ptr, name)) def neg(self, val, name=""): check_is_value(val) return _make_value(_core.LLVMBuildNeg(self.ptr, val.ptr, name)) def not_(self, val, name=""): check_is_value(val) return _make_value(_core.LLVMBuildNot(self.ptr, val.ptr, name)) # memory def malloc(self, ty, name=""): check_is_type(ty) return _make_value(_core.LLVMBuildMalloc(self.ptr, ty.ptr, name)) def malloc_array(self, ty, size, name=""): check_is_type(ty) check_is_value(size) return _make_value( _core.LLVMBuildArrayMalloc(self.ptr, ty.ptr, size.ptr, name)) def alloca(self, ty, name=""): check_is_type(ty) return _make_value(_core.LLVMBuildAlloca(self.ptr, ty.ptr, name)) def alloca_array(self, ty, size, name=""): check_is_type(ty) check_is_value(size) return _make_value( _core.LLVMBuildArrayAlloca(self.ptr, ty.ptr, size.ptr, name)) def free(self, ptr): check_is_value(ptr) return _make_value(_core.LLVMBuildFree(self.ptr, ptr.ptr)) def load(self, ptr, name="", align=0, volatile=False, invariant=False): check_is_value(ptr) inst = _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name)) if align: _core.LLVMLdSetAlignment(inst.ptr, align) if volatile: inst.set_volatile(volatile) if invariant: mod = self.basic_block.function.module md = MetaData.get(mod, []) # empty metadata node inst.set_metadata('invariant.load', md) return inst def store(self, value, ptr, align=0, volatile=False): check_is_value(value) check_is_value(ptr) inst = _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr)) if align: _core.LLVMStSetAlignment(inst.ptr, align) if volatile: inst.set_volatile(volatile) return inst def gep(self, ptr, indices, name="", inbounds=False): check_is_value(ptr) index_ptrs = unpack_values(indices) if inbounds: ret = _core.LLVMBuildInBoundsGEP(self.ptr, ptr.ptr, index_ptrs, name) else: ret = _core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name) return _make_value(ret) # casts and extensions def trunc(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) def zext(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildZExt(self.ptr, value.ptr, dest_ty.ptr, name)) def sext(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildSExt(self.ptr, value.ptr, dest_ty.ptr, name)) def fptoui(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildFPToUI(self.ptr, value.ptr, dest_ty.ptr, name)) def fptosi(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildFPToSI(self.ptr, value.ptr, dest_ty.ptr, name)) def uitofp(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildUIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) def sitofp(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildSIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) def fptrunc(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildFPTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) def fpext(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildFPExt(self.ptr, value.ptr, dest_ty.ptr, name)) def ptrtoint(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildPtrToInt(self.ptr, value.ptr, dest_ty.ptr, name)) def inttoptr(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildIntToPtr(self.ptr, value.ptr, dest_ty.ptr, name)) def bitcast(self, value, dest_ty, name=""): check_is_value(value) check_is_type(dest_ty) return _make_value( _core.LLVMBuildBitCast(self.ptr, value.ptr, dest_ty.ptr, name)) # comparisons def icmp(self, ipred, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildICmp(self.ptr, ipred, lhs.ptr, rhs.ptr, name)) def fcmp(self, rpred, lhs, rhs, name=""): check_is_value(lhs) check_is_value(rhs) return _make_value( _core.LLVMBuildFCmp(self.ptr, rpred, lhs.ptr, rhs.ptr, name)) # misc def extract_value(self, retval, idx, name=""): check_is_value(retval) return _make_value( _core.LLVMBuildGetResult(self.ptr, retval.ptr, idx, name)) # obsolete synonym for extract_value getresult = extract_value def insert_value(self, retval, rhs, idx, name=""): check_is_value(retval) check_is_value(rhs) return _make_value( _core.LLVMBuildInsertValue(self.ptr, retval.ptr, rhs.ptr, idx, name)) def phi(self, ty, name=""): check_is_type(ty) return _make_value(_core.LLVMBuildPhi(self.ptr, ty.ptr, name)) def call(self, fn, args, name=""): check_is_callable(fn) err_template = 'Argument type mismatch: expected %s but got %s' for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): if t != v.type: raise TypeError(err_template % (t, v.type)) arg_ptrs = unpack_values(args) return _make_value( _core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name)) def select(self, cond, then_value, else_value, name=""): check_is_value(cond) check_is_value(then_value) check_is_value(else_value) return _make_value( _core.LLVMBuildSelect(self.ptr, cond.ptr, then_value.ptr, else_value.ptr, name)) def vaarg(self, list_val, ty, name=""): check_is_value(list_val) check_is_type(ty) return _make_value( _core.LLVMBuildVAArg(self.ptr, list_val.ptr, ty.ptr, name)) def extract_element(self, vec_val, idx_val, name=""): check_is_value(vec_val) check_is_value(idx_val) return _make_value( _core.LLVMBuildExtractElement(self.ptr, vec_val.ptr, idx_val.ptr, name)) def insert_element(self, vec_val, elt_val, idx_val, name=""): check_is_value(vec_val) check_is_value(elt_val) check_is_value(idx_val) return _make_value( _core.LLVMBuildInsertElement(self.ptr, vec_val.ptr, elt_val.ptr, idx_val.ptr, name)) def shuffle_vector(self, vecA, vecB, mask, name=""): check_is_value(vecA) check_is_value(vecB) check_is_value(mask) return _make_value( _core.LLVMBuildShuffleVector(self.ptr, vecA.ptr, vecB.ptr, mask.ptr, name)) # atomics def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): check_is_value(ptr) check_is_value(old) check_is_value(new) inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr, ordering.lower(), int(bool(crossthread))) return _make_value(inst) def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): check_is_value(ptr) check_is_value(val) inst = _core.LLVMBuildAtomicRMW(self.ptr, op.lower(), ptr.ptr, val.ptr, ordering.lower(), int(bool(crossthread))) return _make_value(inst) def atomic_xchg(self, *args, **kwargs): return self.atomic_rmw('xchg', *args, **kwargs) def atomic_add(self, *args, **kwargs): return self.atomic_rmw('add', *args, **kwargs) def atomic_sub(self, *args, **kwargs): return self.atomic_rmw('sub', *args, **kwargs) def atomic_and(self, *args, **kwargs): return self.atomic_rmw('and', *args, **kwargs) def atomic_nand(self, *args, **kwargs): return self.atomic_rmw('nand', *args, **kwargs) def atomic_or(self, *args, **kwargs): return self.atomic_rmw('or', *args, **kwargs) def atomic_xor(self, *args, **kwargs): return self.atomic_rmw('xor', *args, **kwargs) def atomic_max(self, *args, **kwargs): return self.atomic_rmw('max', *args, **kwargs) def atomic_min(self, *args, **kwargs): return self.atomic_rmw('min', *args, **kwargs) def atomic_umax(self, *args, **kwargs): return self.atomic_rmw('umax', *args, **kwargs) def atomic_umin(self, *args, **kwargs): return self.atomic_rmw('umin', *args, **kwargs) def atomic_load(self, ptr, ordering, align=1, crossthread=True, volatile=False, name=""): check_is_value(ptr) inst = _make_value(_core.LLVMBuildAtomicLoad( self.ptr, ptr.ptr, int(align), ordering.lower(), int(bool(crossthread)))) if volatile: inst.set_volatile(volatile) if inst: inst.name = name return inst def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, volatile=False): check_is_value(value) check_is_value(ptr) inst = _make_value(_core.LLVMBuildAtomicStore( self.ptr, ptr.ptr, value.ptr, int(align), ordering.lower(), int(bool(crossthread)))) if volatile: inst.set_volatile(volatile) return inst def fence(self, ordering, crossthread=True): inst = _make_value(_core.LLVMBuildFence(self.ptr, ordering.lower(), int(bool(crossthread)))) return inst #===----------------------------------------------------------------------=== # Memory buffer #===----------------------------------------------------------------------=== class MemoryBuffer(object): @staticmethod def from_file(fname): ret = _core.LLVMCreateMemoryBufferWithContentsOfFile(fname) if isinstance(ret, str): return (None, ret) else: obj = MemoryBuffer(ret) return (obj, "") @staticmethod def from_stdin(): ret = _core.LLVMCreateMemoryBufferWithSTDIN() if isinstance(ret, str): return (None, ret) else: obj = MemoryBuffer(ret) return (obj, "") def __init__(self, ptr): self.ptr = ptr def __del__(self): _core.LLVMDisposeMemoryBuffer(self.ptr) #===----------------------------------------------------------------------=== # Misc #===----------------------------------------------------------------------=== def load_library_permanently(filename): """Load a shared library. Load the given shared library (filename argument specifies the full path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" ret = _core.LLVMLoadLibraryPermanently(filename) if isinstance(ret, str): raise llvm.LLVMException(ret) def inline_function(call): check_is_value(call) return bool(_core.LLVMInlineFunction(call.ptr)) def parse_environment_options(progname, envname): _core.LLVMParseEnvOpts(progname, envname) #===----------------------------------------------------------------------=== # Initialization #===----------------------------------------------------------------------=== if _core.LLVMInitializeNativeTarget(): raise llvm.LLVMException("No native target!?") if _core.LLVMInitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") HAS_PTX = HAS_NVPTX = False if True: # use PTX? try: _core.LLVMInitializePTXTarget() _core.LLVMInitializePTXTargetInfo() _core.LLVMInitializePTXTargetMC() _core.LLVMInitializePTXAsmPrinter() HAS_PTX = True except AttributeError: try: _core.LLVMInitializeNVPTXTarget() _core.LLVMInitializeNVPTXTargetInfo() _core.LLVMInitializeNVPTXTargetMC() _core.LLVMInitializeNVPTXAsmPrinter() HAS_NVPTX = True except AttributeError: pass