[python-bindings] Added OpCode like support for all enumerations with unittests.
authorMichael Gottesman <mgottesman@apple.com>
Sat, 22 Feb 2014 05:39:35 +0000 (05:39 +0000)
committerMichael Gottesman <mgottesman@apple.com>
Sat, 22 Feb 2014 05:39:35 +0000 (05:39 +0000)
Also fixed some trailing whitespace issues.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201929 91177308-0d34-0410-b5e6-96231b3b80d8

bindings/python/llvm/core.py
bindings/python/llvm/tests/test_core.py

index ebf57d44438bf14f4657117b681fba0b0cb53c7a..e8bfab8445f7e0fc7aa2709b1f1b1020f854acb9 100644 (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
+
+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."""
@@ -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()
index 63f84c828bc8ac8eefbee45efa41799b3854ccf9..da7b635ec999b70020606db73e89c27b5742e748 100644 (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)
-
-        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()
@@ -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