aboutsummaryrefslogtreecommitdiffstats
path: root/bindings/python
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/python')
-rw-r--r--bindings/python/llvm/bit_reader.py31
-rw-r--r--bindings/python/llvm/core.py442
-rw-r--r--bindings/python/llvm/disassembler.py29
-rw-r--r--bindings/python/llvm/tests/base.py6
-rw-r--r--bindings/python/llvm/tests/test.bcbin0 -> 1344 bytes
-rw-r--r--bindings/python/llvm/tests/test_bitreader.py15
-rw-r--r--bindings/python/llvm/tests/test_core.py109
-rw-r--r--bindings/python/llvm/tests/test_disassembler.py4
-rw-r--r--bindings/python/llvm/tests/test_file1
9 files changed, 634 insertions, 3 deletions
diff --git a/bindings/python/llvm/bit_reader.py b/bindings/python/llvm/bit_reader.py
new file mode 100644
index 0000000..5bf5e22
--- /dev/null
+++ b/bindings/python/llvm/bit_reader.py
@@ -0,0 +1,31 @@
+
+from .common import LLVMObject
+from .common import c_object_p
+from .common import get_library
+from . import enumerations
+from .core import MemoryBuffer
+from .core import Module
+from .core import OpCode
+from ctypes import POINTER
+from ctypes import byref
+from ctypes import c_char_p
+from ctypes import cast
+__all__ = ['parse_bitcode']
+lib = get_library()
+
+def parse_bitcode(mem_buffer):
+ """Input is .core.MemoryBuffer"""
+ module = c_object_p()
+ out = c_char_p(None)
+ result = lib.LLVMParseBitcode(mem_buffer, byref(module), byref(out))
+ if result:
+ raise RuntimeError('LLVM Error: %s' % out.value)
+ m = Module(module)
+ m.take_ownership(mem_buffer)
+ return m
+
+def register_library(library):
+ library.LLVMParseBitcode.argtypes = [MemoryBuffer, POINTER(c_object_p), POINTER(c_char_p)]
+ library.LLVMParseBitcode.restype = bool
+
+register_library(lib)
diff --git a/bindings/python/llvm/core.py b/bindings/python/llvm/core.py
index 6756637..ebf57d4 100644
--- a/bindings/python/llvm/core.py
+++ b/bindings/python/llvm/core.py
@@ -16,10 +16,19 @@ from . import enumerations
from ctypes import POINTER
from ctypes import byref
from ctypes import c_char_p
+from ctypes import c_uint
__all__ = [
"lib",
+ "OpCode",
"MemoryBuffer",
+ "Module",
+ "Value",
+ "Function",
+ "BasicBlock",
+ "Instruction",
+ "Context",
+ "PassRegistry"
]
lib = get_library()
@@ -83,16 +92,449 @@ class MemoryBuffer(LLVMObject):
LLVMObject.__init__(self, memory, disposer=lib.LLVMDisposeMemoryBuffer)
+ def __len__(self):
+ return lib.LLVMGetBufferSize(self)
+
+class Value(LLVMObject):
+
+ def __init__(self, value):
+ LLVMObject.__init__(self, value)
+
+ @property
+ def name(self):
+ return lib.LLVMGetValueName(self)
+
+ def dump(self):
+ lib.LLVMDumpValue(self)
+
+ def get_operand(self, i):
+ return Value(lib.LLVMGetOperand(self, i))
+
+ def set_operand(self, i, v):
+ return lib.LLVMSetOperand(self, i, v)
+
+ def __len__(self):
+ return lib.LLVMGetNumOperands(self)
+
+class Module(LLVMObject):
+ """Represents the top-level structure of an llvm program in an opaque object."""
+
+ def __init__(self, module, name=None, context=None):
+ LLVMObject.__init__(self, module, disposer=lib.LLVMDisposeModule)
+
+ @classmethod
+ def CreateWithName(cls, module_id):
+ m = Module(lib.LLVMModuleCreateWithName(module_id))
+ c = Context.GetGlobalContext().take_ownership(m)
+ return m
+
+ @property
+ def datalayout(self):
+ return lib.LLVMGetDataLayout(self)
+
+ @datalayout.setter
+ def datalayout(self, new_data_layout):
+ """new_data_layout is a string."""
+ lib.LLVMSetDataLayout(self, new_data_layout)
+
+ @property
+ def target(self):
+ return lib.LLVMGetTarget(self)
+
+ @target.setter
+ def target(self, new_target):
+ """new_target is a string."""
+ lib.LLVMSetTarget(self, new_target)
+
+ def dump(self):
+ lib.LLVMDumpModule(self)
+
+ class __function_iterator(object):
+ def __init__(self, module, reverse=False):
+ self.module = module
+ self.reverse = reverse
+ if self.reverse:
+ self.function = self.module.last
+ else:
+ self.function = self.module.first
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not isinstance(self.function, Function):
+ raise StopIteration("")
+ result = self.function
+ if self.reverse:
+ self.function = self.function.prev
+ else:
+ self.function = self.function.next
+ return result
+
+ def __iter__(self):
+ return Module.__function_iterator(self)
+
+ def __reversed__(self):
+ return Module.__function_iterator(self, reverse=True)
+
+ @property
+ def first(self):
+ return Function(lib.LLVMGetFirstFunction(self))
+
+ @property
+ def last(self):
+ return Function(lib.LLVMGetLastFunction(self))
+
+ def print_module_to_file(self, filename):
+ out = c_char_p(None)
+ # Result is inverted so 0 means everything was ok.
+ result = lib.LLVMPrintModuleToFile(self, filename, byref(out))
+ if result:
+ raise RuntimeError("LLVM Error: %s" % out.value)
+
+class Function(Value):
+
+ def __init__(self, value):
+ Value.__init__(self, value)
+
+ @property
+ def next(self):
+ f = lib.LLVMGetNextFunction(self)
+ return f and Function(f)
+
+ @property
+ def prev(self):
+ f = lib.LLVMGetPreviousFunction(self)
+ return f and Function(f)
+
+ @property
+ def first(self):
+ b = lib.LLVMGetFirstBasicBlock(self)
+ return b and BasicBlock(b)
+
+ @property
+ def last(self):
+ b = lib.LLVMGetLastBasicBlock(self)
+ return b and BasicBlock(b)
+
+ class __bb_iterator(object):
+ def __init__(self, function, reverse=False):
+ self.function = function
+ self.reverse = reverse
+ if self.reverse:
+ self.bb = function.last
+ else:
+ self.bb = function.first
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not isinstance(self.bb, BasicBlock):
+ raise StopIteration("")
+ result = self.bb
+ if self.reverse:
+ self.bb = self.bb.prev
+ else:
+ self.bb = self.bb.next
+ return result
+
+ def __iter__(self):
+ return Function.__bb_iterator(self)
+
+ def __reversed__(self):
+ return Function.__bb_iterator(self, reverse=True)
+
+ def __len__(self):
+ return lib.LLVMCountBasicBlocks(self)
+
+class BasicBlock(LLVMObject):
+
+ def __init__(self, value):
+ LLVMObject.__init__(self, value)
+
+ @property
+ def next(self):
+ b = lib.LLVMGetNextBasicBlock(self)
+ return b and BasicBlock(b)
+
+ @property
+ def prev(self):
+ b = lib.LLVMGetPreviousBasicBlock(self)
+ return b and BasicBlock(b)
+
+ @property
+ def first(self):
+ i = lib.LLVMGetFirstInstruction(self)
+ return i and Instruction(i)
+
+ @property
+ def last(self):
+ i = lib.LLVMGetLastInstruction(self)
+ return i and Instruction(i)
+
+ def __as_value(self):
+ return Value(lib.LLVMBasicBlockAsValue(self))
+
+ @property
+ def name(self):
+ return lib.LLVMGetValueName(self.__as_value())
+
+ def dump(self):
+ lib.LLVMDumpValue(self.__as_value())
+
+ def get_operand(self, i):
+ return Value(lib.LLVMGetOperand(self.__as_value(),
+ i))
+
+ def set_operand(self, i, v):
+ return lib.LLVMSetOperand(self.__as_value(),
+ i, v)
+
+ def __len__(self):
+ return lib.LLVMGetNumOperands(self.__as_value())
+
+ class __inst_iterator(object):
+ def __init__(self, bb, reverse=False):
+ self.bb = bb
+ self.reverse = reverse
+ if self.reverse:
+ self.inst = self.bb.last
+ else:
+ self.inst = self.bb.first
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if not isinstance(self.inst, Instruction):
+ raise StopIteration("")
+ result = self.inst
+ if self.reverse:
+ self.inst = self.inst.prev
+ else:
+ self.inst = self.inst.next
+ return result
+
+ def __iter__(self):
+ return BasicBlock.__inst_iterator(self)
+
+ def __reversed__(self):
+ return BasicBlock.__inst_iterator(self, reverse=True)
+
+
+class Instruction(Value):
+
+ def __init__(self, value):
+ Value.__init__(self, value)
+
+ @property
+ def next(self):
+ i = lib.LLVMGetNextInstruction(self)
+ return i and Instruction(i)
+
+ @property
+ def prev(self):
+ i = lib.LLVMGetPreviousInstruction(self)
+ return i and Instruction(i)
+
+ @property
+ def opcode(self):
+ return OpCode.from_value(lib.LLVMGetInstructionOpcode(self))
+
+class Context(LLVMObject):
+
+ def __init__(self, context=None):
+ if context is None:
+ context = lib.LLVMContextCreate()
+ LLVMObject.__init__(self, context, disposer=lib.LLVMContextDispose)
+ else:
+ LLVMObject.__init__(self, context)
+
+ @classmethod
+ def GetGlobalContext(cls):
+ return Context(lib.LLVMGetGlobalContext())
+
+class PassRegistry(LLVMObject):
+ """Represents an opaque pass registry object."""
+
+ def __init__(self):
+ LLVMObject.__init__(self,
+ lib.LLVMGetGlobalPassRegistry())
+
def register_library(library):
+ # Initialization/Shutdown declarations.
+ library.LLVMInitializeCore.argtypes = [PassRegistry]
+ library.LLVMInitializeCore.restype = None
+
+ library.LLVMInitializeTransformUtils.argtypes = [PassRegistry]
+ library.LLVMInitializeTransformUtils.restype = None
+
+ library.LLVMInitializeScalarOpts.argtypes = [PassRegistry]
+ library.LLVMInitializeScalarOpts.restype = None
+
+ library.LLVMInitializeObjCARCOpts.argtypes = [PassRegistry]
+ library.LLVMInitializeObjCARCOpts.restype = None
+
+ library.LLVMInitializeVectorization.argtypes = [PassRegistry]
+ library.LLVMInitializeVectorization.restype = None
+
+ library.LLVMInitializeInstCombine.argtypes = [PassRegistry]
+ library.LLVMInitializeInstCombine.restype = None
+
+ library.LLVMInitializeIPO.argtypes = [PassRegistry]
+ library.LLVMInitializeIPO.restype = None
+
+ library.LLVMInitializeInstrumentation.argtypes = [PassRegistry]
+ library.LLVMInitializeInstrumentation.restype = None
+
+ library.LLVMInitializeAnalysis.argtypes = [PassRegistry]
+ library.LLVMInitializeAnalysis.restype = None
+
+ library.LLVMInitializeIPA.argtypes = [PassRegistry]
+ library.LLVMInitializeIPA.restype = None
+
+ library.LLVMInitializeCodeGen.argtypes = [PassRegistry]
+ library.LLVMInitializeCodeGen.restype = None
+
+ library.LLVMInitializeTarget.argtypes = [PassRegistry]
+ library.LLVMInitializeTarget.restype = None
+
+ library.LLVMShutdown.argtypes = []
+ library.LLVMShutdown.restype = None
+
+ # Pass Registry declarations.
+ library.LLVMGetGlobalPassRegistry.argtypes = []
+ library.LLVMGetGlobalPassRegistry.restype = c_object_p
+
+ # Context declarations.
+ library.LLVMContextCreate.argtypes = []
+ library.LLVMContextCreate.restype = c_object_p
+
+ library.LLVMContextDispose.argtypes = [Context]
+ library.LLVMContextDispose.restype = None
+
+ library.LLVMGetGlobalContext.argtypes = []
+ library.LLVMGetGlobalContext.restype = c_object_p
+
+ # Memory buffer declarations
library.LLVMCreateMemoryBufferWithContentsOfFile.argtypes = [c_char_p,
POINTER(c_object_p), POINTER(c_char_p)]
library.LLVMCreateMemoryBufferWithContentsOfFile.restype = bool
+ library.LLVMGetBufferSize.argtypes = [MemoryBuffer]
+
library.LLVMDisposeMemoryBuffer.argtypes = [MemoryBuffer]
+ # Module declarations
+ library.LLVMModuleCreateWithName.argtypes = [c_char_p]
+ library.LLVMModuleCreateWithName.restype = c_object_p
+
+ library.LLVMDisposeModule.argtypes = [Module]
+ library.LLVMDisposeModule.restype = None
+
+ library.LLVMGetDataLayout.argtypes = [Module]
+ library.LLVMGetDataLayout.restype = c_char_p
+
+ library.LLVMSetDataLayout.argtypes = [Module, c_char_p]
+ library.LLVMSetDataLayout.restype = None
+
+ library.LLVMGetTarget.argtypes = [Module]
+ library.LLVMGetTarget.restype = c_char_p
+
+ library.LLVMSetTarget.argtypes = [Module, c_char_p]
+ library.LLVMSetTarget.restype = None
+
+ library.LLVMDumpModule.argtypes = [Module]
+ library.LLVMDumpModule.restype = None
+
+ library.LLVMPrintModuleToFile.argtypes = [Module, c_char_p,
+ POINTER(c_char_p)]
+ library.LLVMPrintModuleToFile.restype = bool
+
+ library.LLVMGetFirstFunction.argtypes = [Module]
+ library.LLVMGetFirstFunction.restype = c_object_p
+
+ library.LLVMGetLastFunction.argtypes = [Module]
+ library.LLVMGetLastFunction.restype = c_object_p
+
+ library.LLVMGetNextFunction.argtypes = [Function]
+ library.LLVMGetNextFunction.restype = c_object_p
+
+ library.LLVMGetPreviousFunction.argtypes = [Function]
+ library.LLVMGetPreviousFunction.restype = c_object_p
+
+ # Value declarations.
+ library.LLVMGetValueName.argtypes = [Value]
+ library.LLVMGetValueName.restype = c_char_p
+
+ library.LLVMDumpValue.argtypes = [Value]
+ library.LLVMDumpValue.restype = None
+
+ library.LLVMGetOperand.argtypes = [Value, c_uint]
+ library.LLVMGetOperand.restype = c_object_p
+
+ library.LLVMSetOperand.argtypes = [Value, Value, c_uint]
+ library.LLVMSetOperand.restype = None
+
+ library.LLVMGetNumOperands.argtypes = [Value]
+ library.LLVMGetNumOperands.restype = c_uint
+
+ # Basic Block Declarations.
+ library.LLVMGetFirstBasicBlock.argtypes = [Function]
+ library.LLVMGetFirstBasicBlock.restype = c_object_p
+
+ library.LLVMGetLastBasicBlock.argtypes = [Function]
+ library.LLVMGetLastBasicBlock.restype = c_object_p
+
+ library.LLVMGetNextBasicBlock.argtypes = [BasicBlock]
+ library.LLVMGetNextBasicBlock.restype = c_object_p
+
+ library.LLVMGetPreviousBasicBlock.argtypes = [BasicBlock]
+ library.LLVMGetPreviousBasicBlock.restype = c_object_p
+
+ library.LLVMGetFirstInstruction.argtypes = [BasicBlock]
+ library.LLVMGetFirstInstruction.restype = c_object_p
+
+ library.LLVMGetLastInstruction.argtypes = [BasicBlock]
+ library.LLVMGetLastInstruction.restype = c_object_p
+
+ library.LLVMBasicBlockAsValue.argtypes = [BasicBlock]
+ library.LLVMBasicBlockAsValue.restype = c_object_p
+
+ library.LLVMCountBasicBlocks.argtypes = [Function]
+ library.LLVMCountBasicBlocks.restype = c_uint
+
+ # Instruction Declarations.
+ library.LLVMGetNextInstruction.argtypes = [Instruction]
+ library.LLVMGetNextInstruction.restype = c_object_p
+
+ library.LLVMGetPreviousInstruction.argtypes = [Instruction]
+ library.LLVMGetPreviousInstruction.restype = c_object_p
+
+ library.LLVMGetInstructionOpcode.argtypes = [Instruction]
+ library.LLVMGetInstructionOpcode.restype = c_uint
+
def register_enumerations():
for name, value in enumerations.OpCodes:
OpCode.register(name, value)
+def initialize_llvm():
+ c = Context.GetGlobalContext()
+ p = PassRegistry()
+ lib.LLVMInitializeCore(p)
+ lib.LLVMInitializeTransformUtils(p)
+ lib.LLVMInitializeScalarOpts(p)
+ lib.LLVMInitializeObjCARCOpts(p)
+ lib.LLVMInitializeVectorization(p)
+ lib.LLVMInitializeInstCombine(p)
+ lib.LLVMInitializeIPO(p)
+ lib.LLVMInitializeInstrumentation(p)
+ lib.LLVMInitializeAnalysis(p)
+ lib.LLVMInitializeIPA(p)
+ lib.LLVMInitializeCodeGen(p)
+ lib.LLVMInitializeTarget(p)
+
register_library(lib)
register_enumerations()
+initialize_llvm()
diff --git a/bindings/python/llvm/disassembler.py b/bindings/python/llvm/disassembler.py
index dcef9ac..f2df275 100644
--- a/bindings/python/llvm/disassembler.py
+++ b/bindings/python/llvm/disassembler.py
@@ -10,7 +10,6 @@
from ctypes import CFUNCTYPE
from ctypes import POINTER
from ctypes import addressof
-from ctypes import byref
from ctypes import c_byte
from ctypes import c_char_p
from ctypes import c_int
@@ -34,6 +33,29 @@ callbacks = {}
# Constants for set_options
Option_UseMarkup = 1
+
+
+_initialized = False
+_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore']
+def _ensure_initialized():
+ global _initialized
+ if not _initialized:
+ # Here one would want to call the functions
+ # LLVMInitializeAll{TargetInfo,TargetMC,Disassembler}s, but
+ # unfortunately they are only defined as static inline
+ # functions in the header files of llvm-c, so they don't exist
+ # as symbols in the shared library.
+ # So until that is fixed use this hack to initialize them all
+ for tgt in _targets:
+ for initializer in ("TargetInfo", "TargetMC", "Disassembler"):
+ try:
+ f = getattr(lib, "LLVMInitialize" + tgt + initializer)
+ except AttributeError:
+ continue
+ f()
+ _initialized = True
+
+
class Disassembler(LLVMObject):
"""Represents a disassembler instance.
@@ -48,9 +70,12 @@ class Disassembler(LLVMObject):
The triple argument is the triple to create the disassembler for. This
is something like 'i386-apple-darwin9'.
"""
+
+ _ensure_initialized()
+
ptr = lib.LLVMCreateDisasm(c_char_p(triple), c_void_p(None), c_int(0),
callbacks['op_info'](0), callbacks['symbol_lookup'](0))
- if not ptr.contents:
+ if not ptr:
raise Exception('Could not obtain disassembler for triple: %s' %
triple)
diff --git a/bindings/python/llvm/tests/base.py b/bindings/python/llvm/tests/base.py
index ff9eb2f..194f1a4 100644
--- a/bindings/python/llvm/tests/base.py
+++ b/bindings/python/llvm/tests/base.py
@@ -30,3 +30,9 @@ class TestBase(unittest.TestCase):
raise Exception('No suitable test binaries available!')
get_test_binary.__test__ = False
+
+ def get_test_file(self):
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_file")
+
+ def get_test_bc(self):
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.bc")
diff --git a/bindings/python/llvm/tests/test.bc b/bindings/python/llvm/tests/test.bc
new file mode 100644
index 0000000..8d3d28f
--- /dev/null
+++ b/bindings/python/llvm/tests/test.bc
Binary files differ
diff --git a/bindings/python/llvm/tests/test_bitreader.py b/bindings/python/llvm/tests/test_bitreader.py
new file mode 100644
index 0000000..d585009
--- /dev/null
+++ b/bindings/python/llvm/tests/test_bitreader.py
@@ -0,0 +1,15 @@
+from .base import TestBase
+from ..core import OpCode
+from ..core import MemoryBuffer
+from ..core import PassRegistry
+from ..core import Context
+from ..core import Module
+from ..bit_reader import parse_bitcode
+
+class TestBitReader(TestBase):
+
+ def test_parse_bitcode(self):
+ source = self.get_test_bc()
+ m = parse_bitcode(MemoryBuffer(filename=source))
+ print m.target
+ print m.datalayout
diff --git a/bindings/python/llvm/tests/test_core.py b/bindings/python/llvm/tests/test_core.py
index 545abc8..63f84c8 100644
--- a/bindings/python/llvm/tests/test_core.py
+++ b/bindings/python/llvm/tests/test_core.py
@@ -1,6 +1,10 @@
from .base import TestBase
from ..core import OpCode
from ..core import MemoryBuffer
+from ..core import PassRegistry
+from ..core import Context
+from ..core import Module
+from ..bit_reader import parse_bitcode
class TestCore(TestBase):
def test_opcode(self):
@@ -13,7 +17,7 @@ class TestCore(TestBase):
self.assertEqual(op, OpCode.Ret)
def test_memory_buffer_create_from_file(self):
- source = self.get_test_binary()
+ source = self.get_test_file()
MemoryBuffer(filename=source)
@@ -21,3 +25,106 @@ class TestCore(TestBase):
with self.assertRaises(Exception):
MemoryBuffer(filename="/hopefully/this/path/doesnt/exist")
+ def test_memory_buffer_len(self):
+ source = self.get_test_file()
+ m = MemoryBuffer(filename=source)
+ self.assertEqual(len(m), 50)
+
+ def test_create_passregistry(self):
+ PassRegistry()
+
+ def test_create_context(self):
+ Context.GetGlobalContext()
+
+ def test_create_module_with_name(self):
+ # Make sure we can not create a module without a LLVMModuleRef.
+ with self.assertRaises(TypeError):
+ m = Module()
+ m = Module.CreateWithName("test-module")
+
+ def test_module_getset_datalayout(self):
+ m = Module.CreateWithName("test-module")
+ dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
+ m.datalayout = dl
+ self.assertEqual(m.datalayout, dl)
+
+ def test_module_getset_target(self):
+ m = Module.CreateWithName("test-module")
+ target = "thumbv7-apple-ios5.0.0"
+ m.target = target
+ self.assertEqual(m.target, target)
+
+ def test_module_print_module_to_file(self):
+ m = Module.CreateWithName("test")
+ dl = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
+ m.datalayout = dl
+ target = "thumbv7-apple-ios5.0.0"
+ m.target = target
+ m.print_module_to_file("test2.ll")
+
+ def test_module_function_iteration(self):
+ m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
+ i = 0
+ functions = ["f", "f2", "f3", "f4", "f5", "f6", "g1", "g2", "h1", "h2",
+ "h3"]
+ # Forward
+ for f in m:
+ self.assertEqual(f.name, functions[i])
+ f.dump()
+ i += 1
+ # Backwards
+ for f in reversed(m):
+ i -= 1
+ self.assertEqual(f.name, functions[i])
+ f.dump()
+
+ def test_function_basicblock_iteration(self):
+ m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
+ i = 0
+
+ bb_list = ['b1', 'b2', 'end']
+
+ f = m.first
+ while f.name != "f6":
+ f = f.next
+
+ # Forward
+ for bb in f:
+ self.assertEqual(bb.name, bb_list[i])
+ bb.dump()
+ i += 1
+
+ # Backwards
+ for bb in reversed(f):
+ i -= 1
+ self.assertEqual(bb.name, bb_list[i])
+ bb.dump()
+
+ def test_basicblock_instruction_iteration(self):
+ m = parse_bitcode(MemoryBuffer(filename=self.get_test_bc()))
+ i = 0
+
+ inst_list = [('arg1', OpCode.ExtractValue),
+ ('arg2', OpCode.ExtractValue),
+ ('', OpCode.Call),
+ ('', OpCode.Ret)]
+
+ bb = m.first.first
+
+ # Forward
+ for inst in bb:
+ self.assertEqual(inst.name, inst_list[i][0])
+ self.assertEqual(inst.opcode, inst_list[i][1])
+ for op in range(len(inst)):
+ o = inst.get_operand(op)
+ print o.name
+ o.dump()
+ inst.dump()
+ i += 1
+
+ # Backwards
+ for inst in reversed(bb):
+ i -= 1
+ self.assertEqual(inst.name, inst_list[i][0])
+ self.assertEqual(inst.opcode, inst_list[i][1])
+ inst.dump()
diff --git a/bindings/python/llvm/tests/test_disassembler.py b/bindings/python/llvm/tests/test_disassembler.py
index 46d12f7..e960dc0 100644
--- a/bindings/python/llvm/tests/test_disassembler.py
+++ b/bindings/python/llvm/tests/test_disassembler.py
@@ -16,6 +16,10 @@ class TestDisassembler(TestBase):
self.assertEqual(count, 3)
self.assertEqual(s, '\tjcxz\t-127')
+ def test_nonexistant_triple(self):
+ with self.assertRaisesRegexp(Exception, "Could not obtain disassembler for triple"):
+ Disassembler("nonexistant-triple-raises")
+
def test_get_instructions(self):
sequence = '\x67\xe3\x81\x01\xc7' # jcxz -127; addl %eax, %edi
diff --git a/bindings/python/llvm/tests/test_file b/bindings/python/llvm/tests/test_file
new file mode 100644
index 0000000..6c9b038
--- /dev/null
+++ b/bindings/python/llvm/tests/test_file
@@ -0,0 +1 @@
+I,"cAGxqԐdvl\L>g>``wɩ \ No newline at end of file