Skip to content

Commit

Permalink
[python-bindings] Added OpCode like support for all enumerations with…
Browse files Browse the repository at this point in the history
… unittests.

Also fixed some trailing whitespace issues.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201929 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
gottesmm committed Feb 22, 2014
1 parent a6e734d commit 0ee9a84
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 37 deletions.
134 changes: 113 additions & 21 deletions bindings/python/llvm/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

__all__ = [
"lib",
"Enums",
"OpCode",
"MemoryBuffer",
"Module",
Expand All @@ -32,42 +33,116 @@
]

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

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."""

opcode = OpCode(name, value)
OpCode._value_map[value] = opcode
setattr(OpCode, name, opcode)
_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."""
Expand Down Expand Up @@ -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()
Expand All @@ -536,5 +628,5 @@ def initialize_llvm():
lib.LLVMInitializeTarget(p)

register_library(lib)
register_enumerations()
Enums = register_enumerations()
initialize_llvm()
42 changes: 26 additions & 16 deletions bindings/python/llvm/tests/test_core.py
Original file line number Diff line number Diff line change
@@ -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)

op = OpCode.from_value(1)
self.assertTrue(isinstance(op, OpCode))
self.assertEqual(op, OpCode.Ret)
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))

# 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()
Expand Down Expand Up @@ -61,7 +71,7 @@ def test_module_print_module_to_file(self):
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
Expand All @@ -81,19 +91,19 @@ def test_module_function_iteration(self):
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
Expand All @@ -103,12 +113,12 @@ def test_function_basicblock_iteration(self):
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
Expand Down

0 comments on commit 0ee9a84

Please sign in to comment.