Commits

Alexander Schremmer  committed 222168f

Prefix names by package name. Support for external_void, _external_reference,
containers with external linkage.
Add linkage information to generated C code.

  • Participants
  • Parent commits de9ec8e
  • Branches sepcomp

Comments (0)

Files changed (5)

File pypy/translator/c/database.py

         # assign to a constant object is something C doesn't think is
         # constant
         self.late_initializations = []
-        self.namespace = CNameManager()
+        pkgname = "pypy"
+        if translator and translator.config.translation.exportpackage:
+            pkgname = translator.config.translation.exportpackage
+        self.namespace = CNameManager(pkgname + "_")
+        self.from_other_namespace = lambda ns, name, **kwargs: CNameManager(ns + "_").uniquename(name, **kwargs)
 
         if translator is None or translator.rtyper is None:
             self.exctransformer = None
                     node = BareBoneArrayDefNode(self, T, varlength)
                 else:
                     node = ArrayDefNode(self, T, varlength)
-            elif isinstance(T, OpaqueType) and T.hints.get("render_structure", False):
+            elif isinstance(T, OpaqueType) and (T.hints.get("render_structure", False) or T.hints.get("external_void", False)):
                 node = ExtTypeOpaqueDefNode(self, T)
             elif T == WeakRef:
                 REALT = self.gcpolicy.get_real_weakref_type()
         elif isinstance(T, OpaqueType):
             if T == RuntimeTypeInfo:
                 return  self.gcpolicy.rtti_type()
+            elif T.hints.get("external_void", False):
+                return 'void @'
             elif T.hints.get("render_structure", False):
                 node = self.gettypedefnode(T, varlength=varlength)
                 if who_asks is not None:
         try:
             node = self.containernodes[container]
         except KeyError:
+            if isinstance(container, lltype._external_reference):
+                buildkwds.update(dict(external_name=container.name, external_component=container.component))
             T = typeOf(container)
             if isinstance(T, (lltype.Array, lltype.Struct)):
                 if hasattr(self.gctransformer, 'consider_constant'):

File pypy/translator/c/gc.py

         return []
 
     def implementation(self):
-        yield 'char %s  /* uninitialized */;' % self.name
+        yield '%schar %s  /* uninitialized */;' % (self.linkage(), self.name)
 
 class FrameworkGcRuntimeTypeInfo_OpaqueNode(BoehmGcRuntimeTypeInfo_OpaqueNode):
     nodekind = 'framework rtti'

File pypy/translator/c/node.py

         self.T = T
         self.dependencies = {}
         self.name = 'RPyOpaque_%s' % (T.tag,)
+        if T.hints.get("external_void", False):
+            self.typetag = "extern void*"
+            self.name = T.tag
 
     def setup(self):
         pass
     def definition(self):
         return []
 
+
 # ____________________________________________________________
 
 
 class ContainerNode(object):
     if USESLOTS:
-        __slots__ = """db T obj 
+        __slots__ = """db T obj inhibit_dependencies
                        typename implementationtypename
                         name ptrname
-                        globalcontainer""".split()
+                        globalcontainer external_name""".split()
 
-    def __init__(self, db, T, obj):
+    def __init__(self, db, T, obj, external_name=None, external_component=None):
         self.db = db
         self.T = T
         self.obj = obj
-        #self.dependencies = {}
+        self.external_name = external_name
         self.typename = db.gettype(T)  #, who_asks=self)
         self.implementationtypename = db.gettype(T, varlength=self.getlength())
+        self.inhibit_dependencies = False
+        if external_name:
+            self.inhibit_dependencies = True
+            self.globalcontainer = True
+            if not external_component:
+                self.name = external_name
+            else:
+                self.name = db.from_other_namespace(external_component, "g_" + external_name)
+            self.ptrname = '(&%s)' % (self.name, )
+            return
         parent, parentindex = parentlink(obj)
         if parent is None:
             self.name = db.namespace.uniquename('g_' + self.basename())
         return hasattr(self.T, "_hints") and self.T._hints.get('thread_local')
 
     def forward_declaration(self):
-        yield '%s;' % (
+        yield '%s%s;' % (self.linkage(),
             forward_cdecl(self.implementationtypename,
                 self.name, self.db.standalone, self.is_thread_local()))
 
+    def linkage(self):
+        linkage = "static "
+        if getattr(self.obj, "_exported", False):
+            linkage = ""
+        if getattr(self, "external_name", None):
+            linkage = "extern "
+        return linkage
+
+
     def implementation(self):
+        if self.external_name:
+            return []
+
         lines = list(self.initializationexpr())
-        lines[0] = '%s = %s' % (
+        lines[0] = '%s%s = %s' % (self.linkage(),
             cdecl(self.implementationtypename, self.name, self.is_thread_local()),
             lines[0])
         lines[-1] += ';'
         return self.T._name
 
     def enum_dependencies(self):
+        if self.inhibit_dependencies:
+            return
         for name in self.T._names:
             yield getattr(self.obj, name)
 
 
 assert not USESLOTS or '__dict__' not in dir(StructNode)
 
+
 class ArrayNode(ContainerNode):
     nodekind = 'array'
     if USESLOTS:
         __slots__ = ()
 
-    def __init__(self, db, T, obj):
-        ContainerNode.__init__(self, db, T, obj)
+    def __init__(self, db, T, obj, **kwargs):
+        ContainerNode.__init__(self, db, T, obj, **kwargs)
         if barebonearray(T):
             self.ptrname = self.name
 
         return 'array'
 
     def enum_dependencies(self):
+        if self.inhibit_dependencies:
+            return
         return self.obj.items
 
     def getlength(self):
         return self.T._name
 
     def enum_dependencies(self):
+        if self.inhibit_dependencies:
+            return
         for i in range(self.obj.getlength()):
             yield self.obj.getitem(i)
 
         self.T = T
         self.obj = obj
         if getattr(obj, 'external', None) == 'C' and not db.need_sandboxing(obj):
-            self.name = forcename or self.basename()
+            comp = getattr(obj, 'component', None)
+            if comp:
+                self.name = db.from_other_namespace(comp, self.basename())
+            else:
+                self.name = forcename or self.basename()
         else:
-            self.name = (forcename or
-                         db.namespace.uniquename('g_' + self.basename()))
+            if getattr(obj, '_extname', None):
+                self.name = db.namespace.uniquename(obj._extname)
+            else:
+                self.name = (forcename or
+                             db.namespace.uniquename('g_' + self.basename()))
         self.compilation_info = getattr(obj, 'compilation_info',
                                         ExternalCompilationInfo())
         self.make_funcgens()
 
     def forward_declaration(self):
         for funcgen in self.funcgens:
-            yield '%s;' % (
+            yield '%s%s;' % (self.linkage(),
                 forward_cdecl(self.implementationtypename,
                     funcgen.name(self.name), self.db.standalone))
 
         # recompute implementationtypename as the argnames may have changed
         argnames = funcgen.argnames()
         implementationtypename = self.db.gettype(self.T, argnames=argnames)
-        yield '%s {' % cdecl(implementationtypename, funcgen.name(self.name))
+        yield '%s%s {' % (self.linkage(), cdecl(implementationtypename, funcgen.name(self.name)))
         #
         # declare the local variables
         #

File pypy/translator/c/support.py

         __thread = "__thread "
 
     cdecl_str = __thread + cdecl(ctype, cname)
-    if standalone:
+    if standalone and False: # XXX why extern!?
         return 'extern ' + cdecl_str
     else:
         return cdecl_str

File pypy/translator/c/test/test_database.py

 import autopath, sys
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.lltypesystem import rffi
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.database import LowLevelDatabase
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
     print '/*********************************/'
     structdeflist = database.getstructdeflist()
     for node in structdeflist:
+        if hasattr(node, 'forward_decl'):
+            if node.forward_decl:
+                print node.forward_decl
+        else:
+            print '%s %s;' % (node.typetag, node.name)
+
+    for node in structdeflist:
         for line in node.definition():
             print line
     print
     db.complete()
     dump_on_stdout(db)
 
+def test_extdef():
+    db = LowLevelDatabase()
+    handle = "handle"
+    S2 = GcStruct("testing2")
+    val = externalptr(S2, "foo")
+    #typ = Ptr(OpaqueType(handle, hints=dict(external_void=True)))
+    #val = rffi.CConstant(handle, typ)
+    S = GcStruct('testing', ('x', Ptr(S2)), ('y', Signed))
+    s = malloc(S)
+    s.x = val
+    s.y = 1
+    db.get(s)
+    db.complete()
+    dump_on_stdout(db)
 
 def test_malloc():
     S = GcStruct('testing', ('x', Signed), ('y', Signed))