Commits

Manuel Jacob  committed e22c2e7

Rewrite main() in RPython. Add enough hacks to make translation of simple programs work. Remove some code in rpython/translator/c/extfunc.py that is unnecessary now.

  • Participants
  • Parent commits 9a92c5b
  • Branches refactor-translator

Comments (0)

Files changed (13)

File rpython/translator/c/extfunc.py

 import types
+from rpython.annotator import model as annmodel
 from rpython.flowspace.model import FunctionGraph
 from rpython.rtyper.lltypesystem import lltype
 from rpython.translator.c.support import cdecl
 
 #______________________________________________________
 
-def find_list_of_str(rtyper):
-    for r in rtyper.reprs.itervalues():
-        if isinstance(r, rlist.ListRepr) and r.item_repr is rstr.string_repr:
-            return r.lowleveltype.TO
-    return None
-
 def predeclare_common_types(db, rtyper):
     # Common types
     yield ('RPyString', STR)
-    LIST_OF_STR = find_list_of_str(rtyper)
-    if LIST_OF_STR is not None:
-        yield ('RPyListOfString', LIST_OF_STR)
-
-def predeclare_utility_functions(db, rtyper):
-    # Common utility functions
-    def RPyString_New(length=lltype.Signed):
-        return mallocstr(length)
-
-    # !!!
-    # be extremely careful passing a gc tracked object
-    # from such an helper result to another one
-    # as argument, this could result in leaks
-    # Such result should be only from C code
-    # returned directly as results
-
-    LIST_OF_STR = find_list_of_str(rtyper)
-    if LIST_OF_STR is not None:
-        p = lltype.Ptr(LIST_OF_STR)
-
-        def _RPyListOfString_New(length=lltype.Signed):
-            return LIST_OF_STR.ll_newlist(length)
-
-        def _RPyListOfString_SetItem(l=p,
-                                    index=lltype.Signed,
-                                    newstring=lltype.Ptr(STR)):
-            rlist.ll_setitem_nonneg(rlist.dum_nocheck, l, index, newstring)
-
-        def _RPyListOfString_GetItem(l=p,
-                                    index=lltype.Signed):
-            return rlist.ll_getitem_fast(l, index)
-
-        def _RPyListOfString_Length(l=p):
-            return rlist.ll_length(l)
-
-    for fname, f in locals().items():
-        if isinstance(f, types.FunctionType):
-            # XXX this is painful :(
-            if (LIST_OF_STR, fname) in db.helper2ptr:
-                yield (fname, db.helper2ptr[LIST_OF_STR, fname])
-            else:
-                # hack: the defaults give the type of the arguments
-                graph = rtyper.annotate_helper(f, f.func_defaults)
-                db.helper2ptr[LIST_OF_STR, fname] = graph
-                yield (fname, graph)
-
 
 def predeclare_extfuncs(db, rtyper):
     modules = {}
     for exccls in exceptiondata.standardexceptions:
         exc_llvalue = exceptiondata.get_standard_ll_exc_instance_by_class(
             exccls)
+        rtyper.getrepr(annmodel.lltype_to_annotation(lltype.typeOf(exc_llvalue)))
         # strange naming here because the macro name must be
         # a substring of PyExc_%s
         name = exccls.__name__
         if exccls.__module__ != 'exceptions':
             name = '%s_%s' % (exccls.__module__.replace('.', '__'), name)
         yield ('RPyExc_%s' % name, exc_llvalue)
+    rtyper.call_all_setups()
 
 
 def predeclare_all(db, rtyper):
     for fn in [predeclare_common_types,
-               predeclare_utility_functions,
                predeclare_exception_data,
                predeclare_extfuncs,
                ]:
 
 def get_all(db, rtyper):
     for fn in [predeclare_common_types,
-               predeclare_utility_functions,
                predeclare_exception_data,
                predeclare_extfuncs,
                ]:

File rpython/translator/c/genc.py

 
         if db is None:
             db = self.build_database()
-        pf = self.getentrypointptr()
         if self.modulename is None:
             self.modulename = uniquemodulename('testing')
         modulename = self.modulename
         if not self.standalone:
             assert not self.config.translation.instrument
         else:
-            defines['PYPY_STANDALONE'] = db.get(pf)
             if self.config.translation.instrument:
                 defines['PYPY_INSTRUMENT'] = 1
             if CBuilder.have___thread:
                 if not self.config.translation.no__thread:
                     defines['USE___THREAD'] = 1
             if self.config.translation.shared:
-                defines['PYPY_MAIN_FUNCTION'] = "pypy_main_startup"
                 self.eci = self.eci.merge(ExternalCompilationInfo(
-                    export_symbols=["pypy_main_startup", "pypy_debug_file"]))
+                    export_symbols=["rpython_main", "pypy_debug_file"]))
         self.eci, cfile, extra = gen_source(db, modulename, targetdir,
                                             self.eci, defines=defines,
                                             split=self.split)
                 and profbased[0] is ProfOpt)
 
     def getentrypointptr(self):
-        # XXX check that the entrypoint has the correct
-        # signature:  list-of-strings -> int
-        bk = self.translator.annotator.bookkeeper
-        return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph())
+        from rpython.translator.gensupp import make_main
+        # XXX: only framework for now
+        setup = self.db.gctransformer.frameworkgc_setup_ptr.value
+        graph = make_main(self.translator, setup, self.entrypoint)
+        return getfunctionptr(graph)
 
     def cmdexec(self, args='', env=None, err=False, expect_crash=False):
         assert self._compiled
 def add_extra_files(eci):
     srcdir = py.path.local(__file__).join('..', 'src')
     files = [
-        srcdir / 'entrypoint.c',       # ifdef PYPY_STANDALONE
-        srcdir / 'allocator.c',        # ifdef PYPY_STANDALONE
+        srcdir / 'main.c',
+        srcdir / 'allocator.c',
         srcdir / 'mem.c',
         srcdir / 'exception.c',
         srcdir / 'rtyper.c',

File rpython/translator/c/src/allocator.c

 /* allocation functions */
 #include "common_header.h"
-#ifdef PYPY_STANDALONE
 #include <stdlib.h>
 
 #if defined(PYPY_USE_TRIVIAL_MALLOC)
 #  include "src/obmalloc.c"
 
 #endif
-
-#endif  /* PYPY_STANDALONE */

File rpython/translator/c/src/entrypoint.c

-#include "common_header.h"
-#ifdef PYPY_STANDALONE
-#include "structdef.h"
-#include "forwarddecl.h"
-#include "preimpl.h"
-#include <src/entrypoint.h>
-#include <src/commondefs.h>
-#include <src/mem.h>
-#include <src/instrument.h>
-#include <src/rtyper.h>
-#include <src/exception.h>
-#include <src/debug_traceback.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef __GNUC__
-/* Hack to prevent this function from being inlined.  Helps asmgcc
-   because the main() function has often a different prologue/epilogue. */
-int pypy_main_function(int argc, char *argv[]) __attribute__((__noinline__));
-#endif
-
-# ifdef PYPY_USE_ASMGCC
-#  include "structdef.h"
-#  include "forwarddecl.h"
-# endif
-
-int pypy_main_function(int argc, char *argv[])
-{
-    char *errmsg;
-    int i, exitcode;
-    RPyListOfString *list;
-
-#ifdef PYPY_USE_ASMGCC
-    pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter++;
-#endif
-    pypy_asm_stack_bottom();
-#ifdef PYPY_X86_CHECK_SSE2_DEFINED
-    pypy_x86_check_sse2();
-#endif
-    instrument_setup();
-
-#ifndef MS_WINDOWS
-    /* this message does no longer apply to win64 :-) */
-    if (sizeof(void*) != SIZEOF_LONG) {
-        errmsg = "only support platforms where sizeof(void*) == sizeof(long),"
-                 " for now";
-        goto error;
-    }
-#endif
-
-    errmsg = RPython_StartupCode();
-    if (errmsg) goto error;
-
-    list = _RPyListOfString_New(argc);
-    if (RPyExceptionOccurred()) goto memory_out;
-    for (i=0; i<argc; i++) {
-        RPyString *s = RPyString_FromString(argv[i]);
-        if (RPyExceptionOccurred()) goto memory_out;
-        _RPyListOfString_SetItem(list, i, s);
-    }
-
-    exitcode = STANDALONE_ENTRY_POINT(list);
-
-    pypy_debug_alloc_results();
-
-    if (RPyExceptionOccurred()) {
-        /* print the RPython traceback */
-        pypy_debug_catch_fatal_exception();
-    }
-
-    pypy_malloc_counters_results();
-
-    return exitcode;
-
- memory_out:
-    errmsg = "out of memory";
- error:
-    fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
-    abort();
-    return 1;
-}
-
-int PYPY_MAIN_FUNCTION(int argc, char *argv[])
-{
-    return pypy_main_function(argc, argv);
-}
-
-#endif  /* PYPY_STANDALONE */

File rpython/translator/c/src/entrypoint.h

-#ifdef PYPY_STANDALONE
-
-#ifndef STANDALONE_ENTRY_POINT
-#  define STANDALONE_ENTRY_POINT   PYPY_STANDALONE
-#endif
-
-#ifndef PYPY_MAIN_FUNCTION
-#define PYPY_MAIN_FUNCTION main
-#endif
-
-char *RPython_StartupCode(void);
-int PYPY_MAIN_FUNCTION(int argc, char *argv[]);
-#endif  /* PYPY_STANDALONE */

File rpython/translator/c/src/g_include.h

 #  include "src/debug_traceback.h"
 
 #  include "src/allocator.h"
-#ifdef PYPY_STANDALONE
-#  include "src/entrypoint.h"
-#endif
 
 /* suppress a few warnings in the generated code */
 #ifdef MS_WINDOWS

File rpython/translator/c/src/main.c

+int rpython_main(int argc, char *argv[]);
+
+int main(int argc, char *argv[]) {
+  return rpython_main(argc, argv);
+}

File rpython/translator/c/src/rtyper.c

 		free(dump);
 	}
 }
-
-RPyString *RPyString_FromString(char *buf)
-{
-	int length = strlen(buf);
-	RPyString *rps = RPyString_New(length);
-	memcpy(rps->rs_chars.items, buf, length);
-	return rps;
-}

File rpython/translator/c/src/rtyper.h

 
 char *RPyString_AsCharP(RPyString *rps);
 void RPyString_FreeCache(void);
-RPyString *RPyString_FromString(char *buf);

File rpython/translator/c/src/support.c

 #include "common_header.h"
 #include <src/support.h>
+#include <src/commondefs.h>
+#include <src/mem.h>
+#include <src/instrument.h>
 
 /************************************************************/
 /***  C header subsection: support functions              ***/
   abort();
 }
 
+
+void rpython_special_startup()
+{
+#ifdef PYPY_X86_CHECK_SSE2_DEFINED
+    pypy_x86_check_sse2();
+#endif
+    instrument_setup();
+
+#ifndef MS_WINDOWS
+    /* this message does no longer apply to win64 :-) */
+    if (sizeof(void*) != SIZEOF_LONG) {
+        fprintf(stderr, "Only support platforms where sizeof(void*) == "
+                        "sizeof(long), for now\n");
+        abort();
+    }
+#endif
+}
+
+void rpython_special_shutdown()
+{
+    pypy_debug_alloc_results();
+    pypy_malloc_counters_results();
+}

File rpython/translator/c/src/support.h

 #  define RPyNLenItem(array, index)          ((array)->items[index])
 #  define RPyBareItem(array, index)          ((array)[index])
 #endif
+
+void rpython_special_startup();
+void rpython_special_shutdown();

File rpython/translator/gensupp.py

 Some support for genxxx implementations of source generators.
 Another name could be genEric, but well...
 """
+from os import write
+
+from rpython.annotator import model as annmodel
+from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.lltypesystem.lloperation import llop
+
 
 def uniquemodulename(name, SEEN=set()):
     # never reuse the same module name within a Python session!
         self.mapping[name] = ret
         return ret
 
+
+rpython_special_startup = rffi.llexternal(
+    'rpython_special_startup', [], lltype.Void, _nowrapper=True)
+rpython_special_shutdown = rffi.llexternal(
+    'rpython_special_shutdown', [], lltype.Void, _nowrapper=True)
+
+def make_main(translator, setup, entrypoint):
+    def rpython_main(argc, argv):
+        rffi.stackcounter.stacks_counter += 1
+        llop.gc_stack_bottom(lltype.Void)
+        rpython_special_startup()
+        try:
+            if setup is not None:
+                setup()
+            args = [rffi.charp2str(argv[i]) for i in range(argc)]
+            exitcode = entrypoint(args)
+        except Exception as e:
+            write(2, 'DEBUG: An uncaught exception was raised in entrypoint: '
+                      + str(e) + '\n')
+            return 1
+        rpython_special_shutdown();
+        return exitcode
+    rpython_main.c_name = 'rpython_main'
+
+    mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
+    arg1 = annmodel.lltype_to_annotation(rffi.INT)
+    arg2 = annmodel.lltype_to_annotation(rffi.CCHARPP)
+    res = annmodel.lltype_to_annotation(lltype.Signed)
+    graph = mixlevelannotator.getgraph(rpython_main, [arg1, arg2], res)
+    mixlevelannotator.finish()
+    mixlevelannotator.backend_optimize()
+    return graph

File rpython/translator/platform/posix.py

 
         if shared:
             m.definition('SHARED_IMPORT_LIB', libname),
-            m.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup")
-            m.rule('main.c', '',
-                   'echo "'
-                   'int $(PYPY_MAIN_FUNCTION)(int, char*[]); '
-                   'int main(int argc, char* argv[]) '
-                   '{ return $(PYPY_MAIN_FUNCTION)(argc, argv); }" > $@')
             m.rule('$(DEFAULT_TARGET)', ['$(TARGET)', 'main.o'],
                    '$(CC_LINK) $(LDFLAGS_LINK) main.o -L. -l$(SHARED_IMPORT_LIB) -o $@')