[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.
|