[pure-lang-svn] SF.net SVN: pure-lang:[471] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-08-12 12:56:07
|
Revision: 471 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=471&view=rev Author: agraef Date: 2008-08-12 12:56:14 +0000 (Tue, 12 Aug 2008) Log Message: ----------- Handle SIGFPE. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-08-12 06:49:56 UTC (rev 470) +++ pure/trunk/ChangeLog 2008-08-12 12:56:14 UTC (rev 471) @@ -1,5 +1,10 @@ 2008-08-12 Albert Graef <Dr....@t-...> + * interpreter.cc (builtin_codegen), runtime.cc(bigint_div, + bigint_mod): Handle division by zero by throwing a 'signal SIGFPE' + exception. Previously, these would just bail out with an unhandled + SIGFPE signal. + * lexer.ll: Fixed a bug in option parsing of the 'list' command which would cause an option string starting with '-a' to be interpreted as an ordinary argument. Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-08-12 06:49:56 UTC (rev 470) +++ pure/trunk/interpreter.cc 2008-08-12 12:56:14 UTC (rev 471) @@ -263,6 +263,8 @@ "pure_catch", "expr*", 2, "expr*", "expr*"); declare_extern((void*)pure_throw, "pure_throw", "void", 1, "expr*"); + declare_extern((void*)pure_sigfpe, + "pure_sigfpe", "void", 0); declare_extern((void*)pure_new, "pure_new", "expr*", 1, "expr*"); @@ -3652,11 +3654,43 @@ return b.CreateSub(u, v); else if (f.ftag() == symtab.mult_sym().f) return b.CreateMul(u, v); - else if (f.ftag() == symtab.div_sym().f) - return b.CreateSDiv(u, v); - else if (f.ftag() == symtab.mod_sym().f) - return b.CreateSRem(u, v); - else { + else if (f.ftag() == symtab.div_sym().f) { + // catch division by zero + if (x.xval2().tag() == EXPR::INT && x.xval2().ival() == 0) { + b.CreateCall(module->getFunction("pure_sigfpe")); + return v; + } else { + BasicBlock *okbb = BasicBlock::Create("ok"); + BasicBlock *errbb = BasicBlock::Create("err"); + Value *cmp = b.CreateICmpEQ(v, Zero); + b.CreateCondBr(cmp, errbb, okbb); + act_env().f->getBasicBlockList().push_back(errbb); + b.SetInsertPoint(errbb); + b.CreateCall(module->getFunction("pure_sigfpe")); + b.CreateRet(NullExprPtr); + act_env().f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + return b.CreateSDiv(u, v); + } + } else if (f.ftag() == symtab.mod_sym().f) { + // catch division by zero + if (x.xval2().tag() == EXPR::INT && x.xval2().ival() == 0) { + b.CreateCall(module->getFunction("pure_sigfpe")); + return v; + } else { + BasicBlock *okbb = BasicBlock::Create("ok"); + BasicBlock *errbb = BasicBlock::Create("err"); + Value *cmp = b.CreateICmpEQ(v, Zero); + b.CreateCondBr(cmp, errbb, okbb); + act_env().f->getBasicBlockList().push_back(errbb); + b.SetInsertPoint(errbb); + b.CreateCall(module->getFunction("pure_sigfpe")); + b.CreateRet(NullExprPtr); + act_env().f->getBasicBlockList().push_back(okbb); + b.SetInsertPoint(okbb); + return b.CreateSRem(u, v); + } + } else { assert(0 && "error in type checker"); return 0; } Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-08-12 06:49:56 UTC (rev 470) +++ pure/trunk/runtime.cc 2008-08-12 12:56:14 UTC (rev 471) @@ -1289,7 +1289,15 @@ } } +#include <signal.h> + extern "C" +void pure_sigfpe(void) +{ + pure_throw(signal_exception(SIGFPE)); +} + +extern "C" pure_expr *pure_catch(pure_expr *h, pure_expr *x) { char test; @@ -1952,9 +1960,12 @@ return u; } +// These raise a SIGFPE signal exception for division by zero. + extern "C" pure_expr *bigint_div(mpz_t x, mpz_t y) { + if (mpz_sgn(y) == 0) pure_sigfpe(); pure_expr *u = pure_bigint(0, 0); mpz_t& z = u->data.z; mpz_tdiv_q(z, x, y); @@ -1964,6 +1975,7 @@ extern "C" pure_expr *bigint_mod(mpz_t x, mpz_t y) { + if (mpz_sgn(y) == 0) pure_sigfpe(); pure_expr *u = pure_bigint(0, 0); mpz_t& z = u->data.z; mpz_tdiv_r(z, x, y); Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-08-12 06:49:56 UTC (rev 470) +++ pure/trunk/runtime.h 2008-08-12 12:56:14 UTC (rev 471) @@ -340,6 +340,11 @@ void pure_throw(pure_expr* e); +/* Throw a 'signal SIGFPE' exception. This is used to signal division by + zero. */ + +void pure_sigfpe(void); + /* Execute a parameterless fbox x and return its result. If an exception occurs while x is executed, apply h to the value of the exception instead. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |