Author: Manuel Jacob
Branch: llvm-translation-backend
Changeset: r66466:8835602e0b39
Date: 2012-03-04 16:38 +0100
http://bitbucket.org/pypy/pypy/changeset/8835602e0b39/

Log:    Improve LLVM assembly output and add tests for it.

diff --git a/pypy/translator/llvm/genllvm.py b/pypy/translator/llvm/genllvm.py
--- a/pypy/translator/llvm/genllvm.py
+++ b/pypy/translator/llvm/genllvm.py
@@ -20,7 +20,6 @@
         self.f = f
         self.names_counter = {}
         self.types = {}
-        self.globals_counter = count()
         self.globals_ = {None: 'null'}
         self.delayed_ptrs = []
 
@@ -59,8 +58,13 @@
             self.types[type_] = '[%s x %s]' % (type_.length, _T(type_.OF))
         elif isinstance(type_, lltype.Struct):
             self.types[type_] = name = self._unique('%struct.' + type_._name)
-            self.f.write('%s = type { %s }\n' % (
-                    name, _Tm(type_._flds[fld] for fld in type_._names)))
+            tmp = ('    %s%s%s ; %s' % (
+                           ';' if type_._flds[fld] is lltype.Void else '',
+                           _T(type_._flds[fld]),
+                           ',' if fld != type_._names[-1] else '',
+                           fld)
+                   for fld in type_._names)
+            self.f.write('%s = type {\n%s\n}\n' % (name, '\n'.join(tmp)))
         elif isinstance(type_, lltype.Array):
             of = _T(type_.OF)
             name = '%array_of_' + of.strip('%').replace('*', '_ptr')
@@ -93,7 +97,11 @@
                 self.f.writelines(writer.lines)
             return
 
-        name = '@global_%s' % next(self.globals_counter)
+        if isinstance(type_, lltype.FixedSizeArray):
+            tmp = 'array'
+        else:
+            tmp = _T(type_).strip('%').replace('*', '_ptr')
+        name = self._unique('@global_' + tmp)
         if isinstance(type_, lltype.Array):
             typedef = '{ i64, [%s x %s] }' % (len(obj.items), _T(type_.OF))
             self.globals_[obj] = 'bitcast(%s* %s to %s*)' % (
@@ -105,24 +113,53 @@
         self.f.write('%s = global %s %s\n' % (
                 name, typedef, self.repr_obj(type_, obj)))
 
-    def _repr_array(self, flds):
-        if all(_V(t, i) == 'null' for t, i in flds):
-            return 'zeroinitializer'
-        return '[ %s ]' % _TVm(flds)
+    def _zeroinitialized(self, type_, obj):
+        if isinstance(type_, lltype.Primitive):
+            return obj == type_._defl()
+        elif isinstance(type_, lltype.Ptr):
+            return not obj
+        elif isinstance(type_, lltype.Struct):
+            return all(self._zeroinitialized(type_._flds[na], getattr(obj, na))
+                                             for na in type_._names)
+        elif isinstance(type_, lltype.Array):
+            return len(obj.items) == 0
+        elif isinstance(type_, lltype.OpaqueType):
+            return True
+        elif isinstance(type_, llgroup.GroupType):
+            return True
+        else:
+            raise TypeError('type_ is %r' % type_)
+
+    def _repr_array(self, of, items):
+        if of is lltype.Char:
+            return 'c"%s"' % ''.join(items).replace('\00', r'\00')
+        tmp = (_TVm(of, items[i:i+16]) for i in xrange(0, len(items), 16))
+        cmms = [','] * (len(items) // 16) + ['']
+        return '[\n%s]' % (''.join('    %s%s\n' % i for i in zip(tmp, cmms)))
 
     def repr_obj(self, type_, obj):
-        if isinstance(type_, lltype.FixedSizeArray):
-            flds = [(type_.OF, getattr(obj, na)) for na in type_._names]
-            return self._repr_array(flds)
+        if self._zeroinitialized(type_, obj):
+            return 'zeroinitializer'
+        elif isinstance(type_, lltype.FixedSizeArray):
+            return self._repr_array(type_.OF, map(obj._getattr, type_._names))
         elif isinstance(type_, lltype.Struct):
-            flds = [(type_._flds[na], getattr(obj, na)) for na in type_._names]
-            if all(_V(t, i) == 'null' for t, i in flds):
-                return 'zeroinitializer'
-            return '{ %s }' % _TVm(flds)
+            tmp = ('    %s%s %s%s ; %s' % (
+                           ';' if type_._flds[fld] is lltype.Void else '',
+                           _T(type_._flds[fld]),
+                           _V(type_._flds[fld], getattr(obj, fld))
+                                   .replace('\n', '\n    '),
+                           ',' if fld != type_._names[-1] else '',
+                           fld)
+                   for fld in type_._names)
+            return '{\n%s\n}' % ('\n'.join(tmp))
+
         elif isinstance(type_, lltype.Array):
-            return '{ i64 %s, [%s x %s ] %s }' % (
-                    len(obj.items), len(obj.items), _T(type_.OF),
-                    self._repr_array([(type_.OF, i) for i in obj.items]))
+            if all(self._zeroinitialized(type_.OF, i) for i in obj.items):
+                data = 'zeroinitializer'
+            else:
+                data = self._repr_array(type_.OF, obj.items)
+            return '{ i64 %s, [%s x %s] %s }' % (
+                    len(obj.items), len(obj.items), _T(type_.OF), data)
         elif isinstance(type_, lltype.OpaqueType):
             return 'null'
         elif isinstance(type_, llgroup.GroupType):
@@ -141,7 +178,7 @@
         return str(value)
 
     if isinstance(value, ComputedIntSymbolic):
-        return value.compute_fn()
+        return str(value.compute_fn())
     elif isinstance(value, llmemory.AddressOffset):
         return '0' # XXX
         raise NotImplementedError
@@ -216,13 +253,10 @@
     """Represent multiple values. `vals` is an iterable of LLValues."""
     return ', '.join(V(val) for val in vals)
 
-def _TVm(vocs):
-    """
-    Represent multiple types and values. `vocs` is an iterable of
-    (LLType, LLValue) pairs.
-    """
-    return ', '.join('%s %s' % (_T(type_), _V(type_, val))
-                     for type_, val in vocs if type_ is not lltype.Void)
+def _TVm(type_, values):
+    """Represent multiple `values` of type `type_`."""
+    tstr = _T(type_)
+    return ', '.join('%s %s' % (tstr, _V(type_, value)) for value in values)
 
 def TVm(vocs):
     """
diff --git a/pypy/translator/llvm/test/test_genllvm.py 
b/pypy/translator/llvm/test/test_genllvm.py
--- a/pypy/translator/llvm/test/test_genllvm.py
+++ b/pypy/translator/llvm/test/test_genllvm.py
@@ -1,4 +1,7 @@
+from cStringIO import StringIO
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.interactive import Translation
+from pypy.translator.llvm import genllvm
 
 
 def compile(func, argtypes=None, gc=False):
@@ -16,6 +19,141 @@
     return translation.compile_llvm()
 
 
+class TestPrimitives(object):
+    def setup(self):
+        genllvm.database = None
+
+    def test_repr_signed(self):
+        assert genllvm.TV(genllvm.C(rffi.r_long(-1))) == 'i64 -1'
+
+    def test_repr_unsigned(self):
+        assert genllvm.TV(genllvm.C(rffi.r_ulong(1))) == 'i64 1'
+
+    def test_repr_char(self):
+        assert genllvm.TV(genllvm.C(chr(123))) == 'i8 123'
+
+    def test_repr_bool(self):
+        assert genllvm.TV(genllvm.C(True)) == 'i1 true'
+        assert genllvm.TV(genllvm.C(False)) == 'i1 false'
+
+    def test_repr_float(self):
+        assert genllvm.TV(genllvm.C(0.3)) == 'double 0.3'
+
+
+class TestDatabase(object):
+    def setup_method(self, meth):
+        self.f = StringIO()
+        genllvm.database = genllvm.Database(None, self.f)
+
+    def test_repr_fixed_size_array(self):
+        array = lltype.FixedSizeArray(lltype.Signed, 2)._container_example()
+        assert genllvm.TV(genllvm.C(array)) == '[2 x i64] zeroinitializer'
+        array.setitem(0, 1)
+        array.setitem(1, 2)
+        assert genllvm.TV(genllvm.C(array)) == ('[2 x i64] [\n'
+                                                '    i64 1, i64 2\n'
+                                                ']')
+        assert self.f.getvalue() == ''
+
+    def test_repr_string(self):
+        array = lltype.FixedSizeArray(lltype.Char, 7)._container_example()
+        for i, c in enumerate("string\00"):
+            array.setitem(i, c)
+        assert genllvm.TV(genllvm.C(array)) == r'[7 x i8] c"string\00"'
+        assert self.f.getvalue() == ''
+
+    def test_repr_struct(self):
+        struct = lltype.Struct(
+                'spam', ('eggs', lltype.Signed))._container_example()
+        assert genllvm.TV(genllvm.C(struct)) == '%struct.spam zeroinitializer'
+        struct.eggs = 1
+        assert genllvm.TV(genllvm.C(struct)) == ('%struct.spam {\n'
+                                                 '    i64 1 ; eggs\n'
+                                                 '}')
+        assert self.f.getvalue() == ('%struct.spam = type {\n'
+                                     '    i64 ; eggs\n'
+                                     '}\n')
+
+    def test_repr_struct_nested(self):
+        struct = lltype.Struct(
+                'spam', ('eggs', lltype.Struct(
+                        'foo', ('bar', lltype.Signed))))._container_example()
+        assert genllvm.TV(genllvm.C(struct)) == '%struct.spam zeroinitializer'
+        struct.eggs.bar = 1
+        assert genllvm.TV(genllvm.C(struct)) == ('%struct.spam {\n'
+                                                 '    %struct.foo {\n'
+                                                 '        i64 1 ; bar\n'
+                                                 '    } ; eggs\n'
+                                                 '}')
+        assert self.f.getvalue() == ('%struct.foo = type {\n'
+                                     '    i64 ; bar\n'
+                                     '}\n'
+                                     '%struct.spam = type {\n'
+                                     '    %struct.foo ; eggs\n'
+                                     '}\n')
+
+    def test_repr_array(self):
+        array = lltype.Array(lltype.Signed)._container_example()
+        assert genllvm.TV(genllvm.C(array)) == (
+                '%array_of_i64 { i64 1, [1 x i64] zeroinitializer }')
+        array.setitem(0, 1)
+        assert genllvm.TV(genllvm.C(array)) == (
+                '%array_of_i64 { i64 1, [1 x i64] [\n'
+                '    i64 1\n'
+                '] }')
+        assert self.f.getvalue() == '%array_of_i64 = type { i64, [0 x i64] }\n'
+
+    def test_repr_array_of_ptr(self):
+        struct_ptr_type = lltype.Ptr(lltype.Struct('x', ('y', lltype.Signed)))
+        array = lltype.Array(struct_ptr_type)._container_example()
+        assert genllvm.TV(genllvm.C(array)) == (
+                '%array_of_struct.x_ptr '
+                '{ i64 1, [1 x %struct.x*] zeroinitializer }')
+        array.setitem(0, struct_ptr_type._example())
+        assert genllvm.TV(genllvm.C(array)) == (
+                '%array_of_struct.x_ptr { i64 1, [1 x %struct.x*] [\n'
+                '    %struct.x* @global_struct.x\n'
+                '] }')
+        assert self.f.getvalue() == (
+                '%struct.x = type {\n'
+                '    i64 ; y\n'
+                '}\n'
+                '%array_of_struct.x_ptr = type { i64, [0 x %struct.x*] }\n'
+                '@global_struct.x = global %struct.x zeroinitializer\n')
+
+    def test_repr_func_type(self):
+        func_type = lltype.FuncType([lltype.Signed], lltype.Void)
+        assert genllvm._T(func_type) == 'void (i64)'
+
+    def test_repr_fixed_size_array_ptr(self):
+        array_ptr = lltype.Ptr(
+                lltype.FixedSizeArray(lltype.Signed, 2))._example()
+        assert genllvm.TV(genllvm.C(array_ptr)) == '[2 x i64]* @global_array'
+        assert self.f.getvalue() == (
+                '@global_array = global [2 x i64] zeroinitializer\n')
+
+    def test_repr_struct_ptr(self):
+        struct_ptr = lltype.Ptr(
+                lltype.Struct('spam', ('eggs', lltype.Signed)))._example()
+        assert genllvm.TV(genllvm.C(struct_ptr)) == (
+                '%struct.spam* @global_struct.spam')
+        assert self.f.getvalue() == (
+                '%struct.spam = type {\n'
+                '    i64 ; eggs\n'
+                '}\n'
+                '@global_struct.spam = global %struct.spam zeroinitializer\n')
+
+    def test_repr_array_ptr(self):
+        array_ptr = lltype.Ptr(lltype.Array(lltype.Signed))._example()
+        assert genllvm.TV(genllvm.C(array_ptr)) == (
+                '%array_of_i64* bitcast({ i64, [1 x i64] }* '
+                '@global_array_of_i64 to %array_of_i64*)')
+        assert self.f.getvalue() == (
+                '%array_of_i64 = type { i64, [0 x i64] }\n'
+                '@global_array_of_i64 = global { i64, [1 x i64] } '
+                '{ i64 1, [1 x i64] zeroinitializer }\n')
+
+
 class TestSimple(object):
     def test_pass(self):
         def f():
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to