2397 lines
75 KiB
Python
2397 lines
75 KiB
Python
#
|
|
# 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
|
|
|
|
|