# New Ticket Created by Andy Dougherty # Please include the string: [perl #52454] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=52454 >
The test in t/compilers/imcc/syn/regressions_2.pir is failing, at least on SPARC, with the following error message. error:imcc:The opcode 'div_i_ic_ic' (div<3>) was not found. Check the type and number of the arguments in file 't/compilers/imcc/syn/regressions_2.pir' line 3 It apparently is passing on Linux/x86. The test itself is as follows: .sub fold_by_zero push_eh ok $I1 = 1/0 pop_eh ok: say "ok" .end What is going on is a combination of several things. First, deep inside IMCC_subst_constants() in compilers/imcc/optimizer.c, when the divide by zero fails, it returns a NULL value, but forgets to also set the undocumented "return" value for 'ok'. The appended patch sets it to 0, figuring all is not ok if we encountered an exception. This is a problem because in compilers/imcc/parser_util.c, inside INS(), the ok variable is never initialized. Apparently, on x86, it ends up filled with some non-zero value, but on SPARC it ends up as a zero. The appended patch initializes the variable. What to do with the return values, however, is a different question. After this patch is applied, the information that an exception occured has now correctly propagated up to the INS() function, but it's not at all clear to me what to do with it from here. Finally, this hasn't shown up on x86 because the test itself is misleading. Because the uninitialized variable caused the 1/0 to appear to succeed, no error handler ever needed to be invoked. Parrot simply continued stepping through the function to the C< say "ok" > line, just as it would have if it had calculated 1/1 instead of 1/0. This patch fixes that problem. In the end, this levels the playing field -- this test now fails for everyone. I think the next step forward is for someone more familiar with the PIR design than me to decide what behavior is actually wanted when '1/0' appears in the source. I'm also completely unfamiliar with exception handlers in parrot, so I don't know where they are supposed to figure in either. diff -r -u parrot-svn/compilers/imcc/optimizer.c parrot-andy/compilers/imcc/optimizer.c --- parrot-svn/compilers/imcc/optimizer.c 2008-03-31 15:14:39.000000000 -0400 +++ parrot-andy/compilers/imcc/optimizer.c 2008-04-03 13:14:52.000000000 -0400 @@ -976,8 +976,10 @@ * from the result */ branched = eval_ins(interp, op, found, r); - if (branched == -1) + if (branched == -1) { + *ok = 0; /* XXX Is this return value sensible? */ return NULL; + } /* * for math ops result is in I0/N0 * if it was a branch with constant args, the result is diff -r -u parrot-svn/compilers/imcc/parser_util.c parrot-andy/compilers/imcc/parser_util.c --- parrot-svn/compilers/imcc/parser_util.c 2008-03-31 15:14:40.000000000 -0400 +++ parrot-andy/compilers/imcc/parser_util.c 2008-04-03 13:17:44.000000000 -0400 @@ -642,14 +642,18 @@ op = try_find_op(interp, unit, name, r, n, keyvec, emit); if (op < 0) { - int ok; + int ok = 0; /* check mixed constants */ ins = IMCC_subst_constants_umix(interp, unit, name, r, n + 1); if (ins) goto found_ins; - /* and finally multiple constants */ + /* and finally multiple constants + Returns ins==NULL, ok == 0 if an exception occured. + XXX The logic here isn't quite right, as imcc may then + report the instruction was not found. + */ ins = IMCC_subst_constants(interp, unit, name, r, n + 1, &ok); if (ok) { diff -r -u parrot-svn/t/compilers/imcc/syn/regressions.t parrot-andy/t/compilers/imcc/syn/regressions.t --- parrot-svn/t/compilers/imcc/syn/regressions.t 2008-04-02 10:23:14.000000000 -0400 +++ parrot-andy/t/compilers/imcc/syn/regressions.t 2008-04-03 13:18:44.000000000 -0400 @@ -20,6 +20,8 @@ .sub fold_by_zero push_eh ok $I1 = 1/0 + say "Not ok" + end pop_eh ok: say "ok" -- Andy Dougherty [EMAIL PROTECTED]