[pypy-svn] r12180 - in pypy/dist/pypy/translator/genc: . test

arigo at codespeak.net arigo at codespeak.net
Wed May 11 16:16:08 CEST 2005


Author: arigo
Date: Wed May 11 16:16:08 2005
New Revision: 12180

Added:
   pypy/dist/pypy/translator/genc/ll_include.h   (contents, props changed)
   pypy/dist/pypy/translator/genc/lltype.py   (contents, props changed)
   pypy/dist/pypy/translator/genc/test/test_lltyped.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/genc/ctyper.py
   pypy/dist/pypy/translator/genc/g_include.h
   pypy/dist/pypy/translator/genc/genc.py
   pypy/dist/pypy/translator/genc/inttype.py
Log:
Hackish draft of support of the LowLevelTypes in GenC.  Very partial and
without memory management.  It is also very much indirect because it plugs in
the existing CTyper, which was meant to support a much more indirect,
C-template-based approach than actually needed now.



Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py	(original)
+++ pypy/dist/pypy/translator/genc/ctyper.py	Wed May 11 16:16:08 2005
@@ -6,6 +6,7 @@
 from pypy.translator.typer import Specializer
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.annotation.model import SomeInteger, SomePBC, SomeTuple, SomeList
+from pypy.annotation.model import SomePtr
 from pypy.translator.genc.pyobjtype import CPyObjectType
 from pypy.translator.genc.inttype import CIntType
 from pypy.translator.genc.nonetype import CNoneType
@@ -14,6 +15,8 @@
 from pypy.translator.genc.listtype import CListType
 from pypy.translator.genc.classtype import CClassPtrType
 from pypy.translator.genc.instancetype import CInstanceType
+from pypy.translator.genc.lltype import CPtrType, CLiteralTypeName
+from pypy.rpython import lltypes
 import types
 from pypy.interpreter.pycode import CO_VARARGS
 
@@ -110,12 +113,28 @@
             #    besttype = self.annotator.translator.getconcretetype(
             #        CListType, item_ct)
 
+            elif isinstance(s_value, SomePtr):
+                besttype = self.annotator.translator.getconcretetype(
+                    CPtrType, s_value.ll_ptrtype)
+
         return besttype
 
     def specialized_op(self, op, bindings):
         if op.opname in ('newtuple', 'newlist'):
             # operations that are controlled by their return type
             s_binding = self.annotator.binding(op.result, True)
+        elif op.opname == 'simple_call' and isinstance(op.args[0], Constant):
+            # XXX move me elsewhere
+            func = op.args[0].value
+            if func is lltypes.malloc:
+                assert len(op.args) == 2   # for now
+                s_result = self.annotator.binding(op.result)
+                ct = self.annotator.translator.getconcretetype(CLiteralTypeName)
+                return [
+                    self.typed_op(SpaceOperation('malloc', [op.args[1]],
+                                                 op.result),
+                                  [ct], self.annotation2concretetype(s_result))
+                    ]
         elif bindings:
             # operations are by default controlled by their 1st arg
             s_binding = bindings[0]

Modified: pypy/dist/pypy/translator/genc/g_include.h
==============================================================================
--- pypy/dist/pypy/translator/genc/g_include.h	(original)
+++ pypy/dist/pypy/translator/genc/g_include.h	Wed May 11 16:16:08 2005
@@ -20,3 +20,4 @@
 #include "none_include.h"
 #include "pyobj_include.h"
 #include "tuple_include.h"
+#include "ll_include.h"

Modified: pypy/dist/pypy/translator/genc/genc.py
==============================================================================
--- pypy/dist/pypy/translator/genc/genc.py	(original)
+++ pypy/dist/pypy/translator/genc/genc.py	Wed May 11 16:16:08 2005
@@ -125,14 +125,20 @@
         # the footer proper: the module init function */
         print >> f, self.C_FOOTER % info
 
+    def need_typedecl_now(self, ct):
+        if ct not in self.ctypes_alreadyseen:
+            self.ctypes_alreadyseen[ct] = True
+            return ct.init_globals(self)
+        else:
+            return []
+
     def gen_global_declarations(self):
         # collect more of the latercode between the functions,
         # and produce the corresponding global declarations
         insert_first = []
         for ct in self.translator.ctlist:
             if ct not in self.ctypes_alreadyseen:
-                insert_first += list(ct.init_globals(self))
-                self.ctypes_alreadyseen[ct] = True
+                insert_first += list(self.need_typedecl_now(ct))
         self.globaldecl[:0] = insert_first
         for ct in self.translator.ctlist:
             self.globaldecl += list(ct.collect_globals(self))

Modified: pypy/dist/pypy/translator/genc/inttype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/inttype.py	(original)
+++ pypy/dist/pypy/translator/genc/inttype.py	Wed May 11 16:16:08 2005
@@ -10,3 +10,13 @@
 
     def nameof(self, v, debug=None):
         return '%d' % (v,)
+
+
+class CUnsignedType(CType):
+    typename      = 'unsigned'
+    error_return  = '-1'
+    s_annotation  = SomeInteger(nonneg=True, unsigned=True)
+
+    def nameof(self, v, debug=None):
+        assert v >= 0
+        return '%d' % (v,)

Added: pypy/dist/pypy/translator/genc/ll_include.h
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/ll_include.h	Wed May 11 16:16:08 2005
@@ -0,0 +1,15 @@
+
+/************************************************************/
+ /***  C header subsection: operations on LowLevelTypes    ***/
+
+
+/* XXX no reference counting */
+
+#define OP_MALLOC(typename, r, err)                     \
+    r = PyObject_Malloc(sizeof(typename));              \
+    if (r == NULL) { PyErr_NoMemory(); FAIL(err) }      \
+    memset((void*) r, 0, sizeof(typename));
+
+#define OP_GETFIELD(x, fieldname, r, err)         r = x->fieldname;
+#define OP_SETFIELD(x, fieldname, val, r, err)    x->fieldname = val;
+#define OP_GETSUBSTRUCT(x, fieldname, r, err)     r = &x->fieldname;

Added: pypy/dist/pypy/translator/genc/lltype.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/lltype.py	Wed May 11 16:16:08 2005
@@ -0,0 +1,150 @@
+from __future__ import generators
+from pypy.translator.genc.basetype import CType
+from pypy.translator.gensupp import C_IDENTIFIER
+from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
+from pypy.rpython import lltypes
+
+
+class CLiteral(CType):   # HACK! TEMPORARY
+    def nameof(self, obj, debug=None):
+        assert isinstance(obj, str)
+        return obj
+
+class CLiteralTypeName(CType):   # HACK! TEMPORARY
+    def nameof(self, obj, debug=None):
+        assert isinstance(obj, lltypes.LowLevelType)
+        ct = ll2concretetype(self.translator, obj)
+        return ct.typename
+
+
+class CLLType(CType):
+
+    def __init__(self, translator, lltype):
+        super(CLLType, self).__init__(translator)
+        self.lltype = lltype
+##        self.globaldecl = []
+
+    def debugname(self):
+        # a nice textual name for debugging...
+        return str(self.lltype)
+
+##    def collect_globals(self, genc):
+##        result = self.globaldecl
+##        self.globaldecl = []
+##        return result
+
+
+class CPtrType(CLLType):
+    error_return = 'NULL'
+    Counter = 0
+
+    def __init__(self, translator, lltype):
+        super(CPtrType, self).__init__(translator, lltype)
+        ct = ll2concretetype(translator, lltype.TO)
+        self.typename = 'ptr%d_%s' % (CPtrType.Counter,
+                                      ct.typename.translate(C_IDENTIFIER))
+        CPtrType.Counter += 1
+
+    def init_globals(self, genc):
+        ct = ll2concretetype(genc.translator, self.lltype.TO)
+        yield 'typedef %s* %s;' % (ct.typename, self.typename)
+        yield '#define OP_DECREF_%s(x)  /* XXX nothing for now */' % (
+            self.typename)
+
+    def spec_getattr(self, typer, op):
+        v_ptr, v_attrname = op.args
+        assert isinstance(v_attrname, Constant)
+        attrname = v_attrname.value
+        attrtype = self.lltype.TO._flds[attrname]
+        cliteral = typer.annotator.translator.getconcretetype(CLiteral)
+        s_result = typer.annotator.binding(op.result)
+        ctresult = typer.annotation2concretetype(s_result)
+        if isinstance(attrtype, lltypes.ContainerType):
+            yield typer.typed_op(op, [self, cliteral], ctresult,
+                                 newopname='getsubstruct')
+        else:
+            yield typer.typed_op(op, [self, cliteral], ctresult,
+                                 newopname='getfield')
+
+    def spec_setattr(self, typer, op):
+        v_ptr, v_attrname, v_value = op.args
+        assert isinstance(v_attrname, Constant)
+        attrname = v_attrname.value
+        attrtype = self.lltype.TO._flds[attrname]
+        cliteral = typer.annotator.translator.getconcretetype(CLiteral)
+        if isinstance(attrtype, lltypes.ContainerType):
+            raise AssertionError("cannot setattr to a substructure")
+        ctinput = ll2concretetype(typer.annotator.translator, attrtype)
+        yield typer.typed_op(op, [self, cliteral, ctinput], typer.TNone,
+                             newopname='setfield')
+
+
+class CStructType(CLLType):
+    Counter = 0
+
+    def __init__(self, translator, lltype):
+        super(CStructType, self).__init__(translator, lltype)
+        basename = lltype._name.translate(C_IDENTIFIER)
+        self.typename = 'struct ll_%s%d' % (basename, CStructType.Counter)
+        CStructType.Counter += 1
+
+    def init_globals(self, genc):
+        # make sure that the field types are defined before we use them
+        lines = ['%s {' % self.typename]
+        for fieldname in self.lltype._names:
+            T = self.lltype._flds[fieldname]
+            ct = ll2concretetype(genc.translator, T)
+            for line in genc.need_typedecl_now(ct):
+                yield line
+            lines.append('\t%s %s;' % (ct.typename, fieldname))
+        lines.append('};')
+        for line in lines:
+            yield line
+
+
+class CArrayType(CLLType):
+    Counter = 0
+
+    def __init__(self, translator, lltype):
+        super(CArrayType, self).__init__(translator, lltype)
+        self.typename = 'struct array%d ' % CArrayType.Counter
+        CArrayType.Counter += 1
+
+    def init_globals(self, genc):
+        # define first the struct containing one item of this array
+        ct = ll2concretetype(genc.translator, self.lltype.OF)
+        for line in genc.need_typedecl_now(ct):
+            yield line
+        # the array struct itself
+        yield '%s {' % self.typename
+        yield '\tlong size;'
+        yield '\t%s items[1];  /* variable-sized */' % ct.typename
+        yield '};'
+
+
+# ____________________________________________________________
+
+from pypy.translator.genc import inttype, nonetype
+
+primitivetypemap = {
+    lltypes.Signed: inttype.CIntType,
+    lltypes.Unsigned: inttype.CUnsignedType,
+    #lltypes.Char: ...
+    lltypes.Bool: inttype.CIntType,
+    lltypes.Void: nonetype.CNoneType,
+    }
+
+def get_primitive_type(translator, lltype):
+    cls = primitivetypemap[lltype]
+    return translator.getconcretetype(cls)
+
+ll2concretetypemap = {
+    lltypes.Struct: CStructType,
+    lltypes.Array: CArrayType,
+    lltypes._PtrType: CPtrType,
+    lltypes.Primitive: get_primitive_type,
+    }
+
+def ll2concretetype(translator, lltype):
+    cls = ll2concretetypemap[lltype.__class__]
+    return translator.getconcretetype(cls, lltype)

Added: pypy/dist/pypy/translator/genc/test/test_lltyped.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/test/test_lltyped.py	Wed May 11 16:16:08 2005
@@ -0,0 +1,37 @@
+from pypy.rpython.lltypes import *
+from pypy.translator.tool.buildpyxmodule import skip_missing_compiler
+from pypy.translator.translator import Translator
+from pypy.translator.genc.ctyper import GenCSpecializer
+
+
+class TestLowLevelType:
+    objspacename = 'flow'
+
+    def getcompiled(self, func, argstypelist=[]):
+        t = Translator(func, simplifying=True)
+        # builds starting-types from func_defs 
+        a = t.annotate(argstypelist)
+        a.simplify()
+        GenCSpecializer(a).specialize()
+        t.checkgraphs()
+        t.view()
+        return skip_missing_compiler(t.ccompile)
+
+    def test_simple(self):
+        S = Struct("s", ('v', Signed))
+        def llf():
+            s = malloc(S)
+            return s.v
+        fn = self.getcompiled(llf)
+        assert fn() == 0
+
+    def test_simple2(self):
+        S = Struct("s", ('v', Signed))
+        S2 = Struct("s2", ('a',S), ('b',S))
+        def llf():
+            s = malloc(S2)
+            s.a.v = 6
+            s.b.v = 12
+            return s.a.v+s.b.v
+        fn = self.getcompiled(llf)
+        assert fn() == 18



More information about the Pypy-commit mailing list