[python-bindings] Added OpCode like support for all enumerations with unittests.

Also fixed some trailing whitespace issues.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201929 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2014-02-22 05:39:35 +00:00
parent a6e734d2ed
commit 0ee9a84cac
2 changed files with 138 additions and 36 deletions

View File

@ -20,6 +20,7 @@ from ctypes import c_uint
__all__ = [
"lib",
"Enums",
"OpCode",
"MemoryBuffer",
"Module",
@ -32,42 +33,116 @@ __all__ = [
]
lib = get_library()
Enums = []
class OpCode(object):
"""Represents an individual OpCode enumeration."""
_value_map = {}
class LLVMEnumeration(object):
"""Represents an individual LLVM enumeration."""
def __init__(self, name, value):
self.name = name
self.value = value
def __repr__(self):
return 'OpCode.%s' % self.name
return '%s.%s' % (self.__class__.__name__,
self.name)
@staticmethod
def from_value(value):
"""Obtain an OpCode instance from a numeric value."""
result = OpCode._value_map.get(value, None)
@classmethod
def from_value(cls, value):
"""Obtain an enumeration instance from a numeric value."""
result = cls._value_map.get(value, None)
if result is None:
raise ValueError('Unknown OpCode: %d' % value)
raise ValueError('Unknown %s: %d' % (cls.__name__,
value))
return result
@staticmethod
def register(name, value):
"""Registers a new OpCode enumeration.
@classmethod
def register(cls, name, value):
"""Registers a new enumeration.
This is called by this module for each enumeration defined in
enumerations. You should not need to call this outside this module.
"""
if value in OpCode._value_map:
raise ValueError('OpCode value already registered: %d' % value)
if value in cls._value_map:
raise ValueError('%s value already registered: %d' % (cls.__name__,
value))
enum = cls(name, value)
cls._value_map[value] = enum
setattr(cls, name, enum)
#print cls, name, value
opcode = OpCode(name, value)
OpCode._value_map[value] = opcode
setattr(OpCode, name, opcode)
class Attribute(LLVMEnumeration):
"""Represents an individual Attribute enumeration."""
_value_map = {}
def __init__(self, name, value):
super(Attribute, self).__init__(name, value)
class OpCode(LLVMEnumeration):
"""Represents an individual OpCode enumeration."""
_value_map = {}
def __init__(self, name, value):
super(OpCode, self).__init__(name, value)
class TypeKind(LLVMEnumeration):
"""Represents an individual TypeKind enumeration."""
_value_map = {}
def __init__(self, name, value):
super(TypeKind, self).__init__(name, value)
class Linkage(LLVMEnumeration):
"""Represents an individual Linkage enumeration."""
_value_map = {}
def __init__(self, name, value):
super(Linkage, self).__init__(name, value)
class Visibility(LLVMEnumeration):
"""Represents an individual visibility enumeration."""
_value_map = {}
def __init__(self, name, value):
super(Visibility, self).__init__(name, value)
class CallConv(LLVMEnumeration):
"""Represents an individual calling convention enumeration."""
_value_map = {}
def __init__(self, name, value):
super(CallConv, self).__init__(name, value)
class IntPredicate(LLVMEnumeration):
"""Represents an individual IntPredicate enumeration."""
_value_map = {}
def __init__(self, name, value):
super(IntPredicate, self).__init__(name, value)
class RealPredicate(LLVMEnumeration):
"""Represents an individual RealPredicate enumeration."""
_value_map = {}
def __init__(self, name, value):
super(RealPredicate, self).__init__(name, value)
class LandingPadClauseTy(LLVMEnumeration):
"""Represents an individual LandingPadClauseTy enumeration."""
_value_map = {}
def __init__(self, name, value):
super(LandingPadClauseTy, self).__init__(name, value)
class MemoryBuffer(LLVMObject):
"""Represents an opaque memory buffer."""
@ -516,8 +591,25 @@ def register_library(library):
library.LLVMGetInstructionOpcode.restype = c_uint
def register_enumerations():
for name, value in enumerations.OpCodes:
OpCode.register(name, value)
if Enums:
return None
enums = [
(Attribute, enumerations.Attributes),
(OpCode, enumerations.OpCodes),
(TypeKind, enumerations.TypeKinds),
(Linkage, enumerations.Linkages),
(Visibility, enumerations.Visibility),
(CallConv, enumerations.CallConv),
(IntPredicate, enumerations.IntPredicate),
(RealPredicate, enumerations.RealPredicate),
(LandingPadClauseTy, enumerations.LandingPadClauseTy),
]
s = set([])
for enum_class, enum_spec in enums:
for name, value in enum_spec:
print name, value
enum_class.register(name, value)
return enums
def initialize_llvm():
c = Context.GetGlobalContext()
@ -536,5 +628,5 @@ def initialize_llvm():
lib.LLVMInitializeTarget(p)
register_library(lib)
register_enumerations()
Enums = register_enumerations()
initialize_llvm()

View File

@ -1,20 +1,30 @@
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 ..core import Enums
from ..core import OpCode
from ..bit_reader import parse_bitcode
class TestCore(TestBase):
def test_opcode(self):
self.assertTrue(hasattr(OpCode, 'Ret'))
self.assertTrue(isinstance(OpCode.Ret, OpCode))
self.assertEqual(OpCode.Ret.value, 1)
def test_enumerations(self):
for enum_cls, enum_spec in Enums:
for enum_name, enum_value in enum_spec:
# First make sure that enum_cls has the name of the enum as an
# attribute. People will access these values as
# EnumCls.EnumName.
self.assertTrue(hasattr(enum_cls, enum_name))
v_attr = getattr(enum_cls, enum_name)
self.assertTrue(isinstance(v_attr, enum_cls))
op = OpCode.from_value(1)
self.assertTrue(isinstance(op, OpCode))
self.assertEqual(op, OpCode.Ret)
# Then make sure that the value returned for this attribute is
# correct in both ways.
self.assertEqual(v_attr.value, enum_value)
e = enum_cls.from_value(enum_value)
self.assertTrue(isinstance(e, enum_cls))
self.assertEqual(e, v_attr)
def test_memory_buffer_create_from_file(self):
source = self.get_test_file()
@ -61,7 +71,7 @@ class TestCore(TestBase):
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
@ -81,19 +91,19 @@ class TestCore(TestBase):
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
@ -103,12 +113,12 @@ class TestCore(TestBase):
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