[pypy-svn] r70543 - in pypy/branch/c-traceback/pypy: rpython/lltypesystem translator translator/c translator/c/src translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Tue Jan 12 19:02:21 CET 2010
Author: arigo
Date: Tue Jan 12 19:02:21 2010
New Revision: 70543
Added:
pypy/branch/c-traceback/pypy/translator/c/src/debug_traceback.h (contents, props changed)
Modified:
pypy/branch/c-traceback/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/c-traceback/pypy/translator/c/funcgen.py
pypy/branch/c-traceback/pypy/translator/c/genc.py
pypy/branch/c-traceback/pypy/translator/c/src/g_include.h
pypy/branch/c-traceback/pypy/translator/c/src/main.h
pypy/branch/c-traceback/pypy/translator/c/test/test_standalone.py
pypy/branch/c-traceback/pypy/translator/exceptiontransform.py
Log:
Pass the first 2 tests.
Modified: pypy/branch/c-traceback/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/c-traceback/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/c-traceback/pypy/rpython/lltypesystem/lloperation.py Tue Jan 12 19:02:21 2010
@@ -87,6 +87,7 @@
def is_pure(self, args_v):
return (self.canfold or # canfold => pure operation
self is llop.debug_assert or # debug_assert is pure enough
+ self is llop.debug_assert_with_tb or
# reading from immutable
(self in (llop.getfield, llop.getarrayitem) and
args_v[0].concretetype.TO._hints.get('immutable')) or
@@ -536,6 +537,8 @@
'debug_fatalerror': LLOp(),
'debug_llinterpcall': LLOp(), # Python func call 'res=arg[0](*arg[1:])'
# in backends, abort() or whatever is fine
+ 'debug_start_traceback':LLOp(),
+ 'debug_catch_exception':LLOp(),
# __________ instrumentation _________
'instrument_count': LLOp(),
Modified: pypy/branch/c-traceback/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/c/funcgen.py (original)
+++ pypy/branch/c-traceback/pypy/translator/c/funcgen.py Tue Jan 12 19:02:21 2010
@@ -817,5 +817,19 @@
self.expr(op.args[1]),
self.expr(op.args[2]))
+ def OP_DEBUG_RECORD_TRACEBACK(self, op):
+ if self.functionname is None:
+ return '/* debug_record_traceback skipped: no functionname */'
+ return 'PYPY_DEBUG_RECORD_TRACEBACK("%s");' % self.functionname
+
+ def OP_DEBUG_CATCH_EXCEPTION(self, op):
+ gottype = self.expr(op.args[0])
+ exprs = []
+ for c_limited_type in op.args[1:]:
+ exprs.append('%s == %s' % (gottype, self.expr(c_limited_type)))
+ return (self.OP_DEBUG_RECORD_TRACEBACK(None) +
+ ' if (%s) { pypy_debug_catch_exception(); }' % (
+ ' || '.join(exprs),))
+
assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)
Modified: pypy/branch/c-traceback/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/c/genc.py (original)
+++ pypy/branch/c-traceback/pypy/translator/c/genc.py Tue Jan 12 19:02:21 2010
@@ -715,6 +715,7 @@
print >> fc, '/*** Implementations ***/'
print >> fc
print >> fc, '#define PYPY_NOT_MAIN_FILE'
+ print >> fc, '#define PYPY_FILE_NAME "%s"' % name
print >> fc, '#include "common_header.h"'
print >> fc, '#include "structdef.h"'
print >> fc, '#include "forwarddecl.h"'
@@ -787,6 +788,7 @@
print >> f, '/***********************************************************/'
print >> f, '/*** Implementations ***/'
print >> f
+ print >> f, '#define PYPY_FILE_NAME "%s"' % os.path.basename(f.name)
for line in preimplementationlines:
print >> f, line
print >> f, '#include "src/g_include.h"'
Added: pypy/branch/c-traceback/pypy/translator/c/src/debug_traceback.h
==============================================================================
--- (empty file)
+++ pypy/branch/c-traceback/pypy/translator/c/src/debug_traceback.h Tue Jan 12 19:02:21 2010
@@ -0,0 +1,66 @@
+/**************************************************************/
+ /*** C header subsection: RPython tracebacks for debugging ***/
+
+
+#define PYPY_DEBUG_TRACEBACK_DEPTH 8
+
+#define OP_DEBUG_START_TRACEBACK() \
+ pypy_debug_traceback_count = PYPY_DEBUG_TRACEBACK_DEPTH
+
+#define PYPY_DEBUG_RECORD_TRACEBACK(funcname) \
+ if ((--pypy_debug_traceback_count) >= 0) { \
+ static struct pydtentry_s entry = { PYPY_FILE_NAME, funcname, __LINE__ }; \
+ pypy_debug_tracebacks[pypy_debug_traceback_count] = &entry; \
+ }
+
+/* Format of the data: to represent a location in the source code, we
+ use for now just a pointer to a 'pypy_debug_traceback_entry_s'.
+*/
+struct pydtentry_s {
+ const char *filename;
+ const char *funcname;
+ int lineno;
+};
+
+extern int pypy_debug_traceback_count;
+extern struct pydtentry_s *pypy_debug_tracebacks[PYPY_DEBUG_TRACEBACK_DEPTH];
+
+void pypy_debug_catch_exception(void);
+
+
+/************************************************************/
+
+
+#ifndef PYPY_NOT_MAIN_FILE
+
+int pypy_debug_traceback_count = PYPY_DEBUG_TRACEBACK_DEPTH;
+struct pydtentry_s *pypy_debug_tracebacks[PYPY_DEBUG_TRACEBACK_DEPTH];
+
+void pypy_debug_traceback_print(void)
+{
+ int i, lineno;
+ const char *filename;
+ const char *funcname;
+
+ fprintf(stderr, "RPython traceback:\n");
+ for (i=PYPY_DEBUG_TRACEBACK_DEPTH-1; i>=0; i--)
+ {
+ if (i < pypy_debug_traceback_count)
+ break;
+ filename = pypy_debug_tracebacks[i]->filename;
+ funcname = pypy_debug_tracebacks[i]->funcname;
+ lineno = pypy_debug_tracebacks[i]->lineno;
+ fprintf(stderr, " File \"%s\", line %d, in %s\n",
+ filename, lineno, funcname);
+ }
+}
+
+void pypy_debug_catch_exception(void)
+{
+ pypy_debug_traceback_print();
+ fprintf(stderr, "Fatal RPython error: %s\n",
+ RPyFetchExceptionType()->ov_name->items);
+ abort();
+}
+
+#endif /* PYPY_NOT_MAIN_FILE */
Modified: pypy/branch/c-traceback/pypy/translator/c/src/g_include.h
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/c/src/g_include.h (original)
+++ pypy/branch/c-traceback/pypy/translator/c/src/g_include.h Tue Jan 12 19:02:21 2010
@@ -52,6 +52,7 @@
#ifdef HAVE_RTYPER /* only if we have an RTyper */
# include "src/rtyper.h"
# include "src/debug_print.h"
+# include "src/debug_traceback.h"
#ifndef AVR
# include "src/ll_os.h"
# include "src/ll_strtod.h"
Modified: pypy/branch/c-traceback/pypy/translator/c/src/main.h
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/c/src/main.h (original)
+++ pypy/branch/c-traceback/pypy/translator/c/src/main.h Tue Jan 12 19:02:21 2010
@@ -37,11 +37,7 @@
exitcode = STANDALONE_ENTRY_POINT(list);
if (RPyExceptionOccurred()) {
/* fish for the exception type, at least */
-#ifndef AVR
- fprintf(stderr, "Fatal RPython error: %s\n",
- RPyFetchExceptionType()->ov_name->items);
-#endif
- abort();
+ pypy_debug_catch_exception();
}
return exitcode;
Modified: pypy/branch/c-traceback/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/c/test/test_standalone.py (original)
+++ pypy/branch/c-traceback/pypy/translator/c/test/test_standalone.py Tue Jan 12 19:02:21 2010
@@ -396,8 +396,8 @@
assert len(lines) >= 4
l0, l1, l2 = lines[-4:-1]
assert l0 == 'RPython traceback:'
- assert re.match(r' File "\w+.c", line \d+, in g', l1)
- assert re.match(r' File "\w+.c", line \d+, in entry_point', l2)
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_g', l1)
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_entry_point', l2)
#
out2, err2 = cbuilder.cmdexec("x", expect_crash=True)
assert out2.strip() == ''
@@ -405,10 +405,10 @@
assert lines2[-1] == 'Fatal RPython error: KeyError'
l0, l1, l2 = lines2[-4:-1]
assert l0 == 'RPython traceback:'
- assert re.match(r' File "\w+.c", line \d+, in g', l1)
- assert re.match(r' File "\w+.c", line \d+, in entry_point', l2)
- assert lines2[-3] != lines[-3]
- assert lines2[-2] == lines[-2]
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_g', l1)
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_entry_point', l2)
+ assert lines2[-3] != lines[-3] # different line number
+ assert lines2[-2] == lines[-2] # same line number
def test_assertion_error(self):
def g(x):
@@ -429,8 +429,8 @@
assert len(lines) >= 4
l0, l1, l2 = lines[-4:-1]
assert l0 == 'RPython traceback:'
- assert re.match(r' File "\w+.c", line \d+, in g', l1)
- assert re.match(r' File "\w+.c", line \d+, in f', l2)
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_g', l1)
+ assert re.match(r' File "\w+.c", line \d+, in pypy_g_f', l2)
# The traceback stops at f() because it's the first function that
# captures the AssertionError, which makes the program abort.
Modified: pypy/branch/c-traceback/pypy/translator/exceptiontransform.py
==============================================================================
--- pypy/branch/c-traceback/pypy/translator/exceptiontransform.py (original)
+++ pypy/branch/c-traceback/pypy/translator/exceptiontransform.py Tue Jan 12 19:02:21 2010
@@ -16,6 +16,7 @@
from pypy.rlib.debug import ll_assert
from pypy.annotation import model as annmodel
from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
+from pypy.tool.sourcetools import func_with_new_name
PrimitiveErrorValue = {lltype.Signed: -1,
lltype.Unsigned: r_uint(-1),
@@ -45,6 +46,9 @@
def error_constant(T):
return Constant(error_value(T), T)
+def constant_value(llvalue):
+ return Constant(llvalue, lltype.typeOf(llvalue))
+
class BaseExceptionTransformer(object):
def __init__(self, translator):
@@ -64,6 +68,10 @@
(n_i_error_ll_exc_type,
n_i_error_ll_exc) = self.get_builtin_exception(NotImplementedError)
+ self.c_assertion_error_ll_exc_type = constant_value(
+ assertion_error_ll_exc_type)
+ self.c_n_i_error_ll_exc_type = constant_value(n_i_error_ll_exc_type)
+
def rpyexc_occured():
exc_type = exc_data.exc_type
return bool(exc_type)
@@ -82,6 +90,7 @@
# assert(!RPyExceptionOccurred());
exc_data.exc_type = etype
exc_data.exc_value = evalue
+ lloperation.llop.debug_start_traceback(lltype.Void)
def rpyexc_fetch_exception():
evalue = rpyexc_fetch_value()
@@ -90,7 +99,8 @@
def rpyexc_restore_exception(evalue):
if evalue:
- rpyexc_raise(rclass.ll_inst_type(evalue), evalue)
+ exc_data.exc_type = rclass.ll_inst_type(evalue)
+ exc_data.exc_value = evalue
def rpyexc_raise_runtime_error():
rpyexc_raise(runtime_error_ll_exc_type, runtime_error_ll_exc)
@@ -117,14 +127,14 @@
self.rpyexc_raise_ptr = self.build_func(
"RPyRaiseException",
- rpyexc_raise,
+ self.noinline(rpyexc_raise),
[self.lltype_of_exception_type, self.lltype_of_exception_value],
lltype.Void,
jitcallkind='rpyexc_raise') # for the JIT
self.rpyexc_raise_runtime_error_ptr = self.build_func(
"RPyRaiseRuntimeError",
- rpyexc_raise_runtime_error,
+ self.noinline(rpyexc_raise_runtime_error),
[], lltype.Void)
self.rpyexc_fetch_exception_ptr = self.build_func(
@@ -134,7 +144,7 @@
self.rpyexc_restore_exception_ptr = self.build_func(
"RPyRestoreException",
- rpyexc_restore_exception,
+ self.noinline(rpyexc_restore_exception),
[self.lltype_of_exception_value], lltype.Void)
self.build_extra_funcs()
@@ -142,6 +152,11 @@
self.mixlevelannotator.finish()
self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
+ def noinline(self, fn):
+ fn = func_with_new_name(fn, fn.__name__ + '_noinline')
+ fn._dont_inline_ = True
+ return fn
+
def build_func(self, name, fn, inputtypes, rettype, **kwds):
l2a = annmodel.lltype_to_annotation
graph = self.mixlevelannotator.getgraph(fn, map(l2a, inputtypes), l2a(rettype))
@@ -185,10 +200,10 @@
for block in list(graph.iterblocks()):
self.replace_stack_unwind(block)
self.replace_fetch_restore_operations(block)
+ self.transform_jump_to_except_block(graph, block.exits)
need_exc_matching, gen_exc_checks = self.transform_block(graph, block)
n_need_exc_matching_blocks += need_exc_matching
n_gen_exc_checks += gen_exc_checks
- self.transform_except_block(graph, graph.exceptblock)
cleanup_graph(graph)
removenoops.remove_superfluous_keep_alive(graph)
return n_need_exc_matching_blocks, n_gen_exc_checks
@@ -266,19 +281,23 @@
self.insert_matching(lastblock, graph)
return need_exc_matching, n_gen_exc_checks
- def transform_except_block(self, graph, block):
- # attach an except block -- let's hope that nobody uses it
- graph.exceptblock = Block([Variable('etype'), # exception class
- Variable('evalue')]) # exception value
- graph.exceptblock.operations = ()
- graph.exceptblock.closeblock()
-
- result = Variable()
- result.concretetype = lltype.Void
- block.operations = [SpaceOperation(
- "direct_call", [self.rpyexc_raise_ptr] + block.inputargs, result)]
- l = Link([error_constant(graph.returnblock.inputargs[0].concretetype)], graph.returnblock)
- block.recloseblock(l)
+ def transform_jump_to_except_block(self, graph, exits):
+ for link in exits:
+ if link.target is graph.exceptblock:
+ result = Variable()
+ result.concretetype = lltype.Void
+ block = Block([copyvar(None, v)
+ for v in graph.exceptblock.inputargs])
+ block.operations = [
+ SpaceOperation("direct_call",
+ [self.rpyexc_raise_ptr] + block.inputargs,
+ result),
+ SpaceOperation('debug_record_traceback', [],
+ varoftype(lltype.Void))]
+ link.target = block
+ RETTYPE = graph.returnblock.inputargs[0].concretetype
+ l = Link([error_constant(RETTYPE)], graph.returnblock)
+ block.recloseblock(l)
def insert_matching(self, block, graph):
proxygraph, op = self.create_proxy_graph(block.operations[-1])
@@ -326,6 +345,11 @@
llops = rtyper.LowLevelOpList(None)
var_value = self.gen_getfield('exc_value', llops)
var_type = self.gen_getfield('exc_type' , llops)
+ #
+ c_check1 = self.c_assertion_error_ll_exc_type
+ c_check2 = self.c_n_i_error_ll_exc_type
+ llops.genop('debug_catch_exception', [var_type, c_check1, c_check2])
+ #
self.gen_setfield('exc_value', self.c_null_evalue, llops)
self.gen_setfield('exc_type', self.c_null_etype, llops)
excblock.operations[:] = llops
@@ -359,7 +383,12 @@
block.exitswitch = var_no_exc
#exception occurred case
+ b = Block([])
+ b.operations = [SpaceOperation('debug_record_traceback', [],
+ varoftype(lltype.Void))]
l = Link([error_constant(returnblock.inputargs[0].concretetype)], returnblock)
+ b.closeblock(l)
+ l = Link([], b)
l.exitcase = l.llexitcase = False
#non-exception case
More information about the Pypy-commit
mailing list