changeset 14941:1e3d0366ac8b

warn on divide by zero
author Max Brister <max@2bass.com>
date Thu, 07 Jun 2012 17:25:58 -0500
parents 5f05007ccc5f
children e8487d98561c
files src/pt-jit.cc src/pt-jit.h
diffstat 2 files changed, 53 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/pt-jit.cc	Thu Jun 07 16:45:19 2012 -0500
+++ b/src/pt-jit.cc	Thu Jun 07 17:25:58 2012 -0500
@@ -384,10 +384,6 @@
   add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul);
   add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul);
 
-  // FIXME: Warn if rhs is zero
-  add_binary_op (scalar, octave_value::op_div, llvm::Instruction::FDiv);
-  add_binary_op (scalar, octave_value::op_el_div, llvm::Instruction::FDiv);
-
   add_binary_fcmp (scalar, octave_value::op_lt, llvm::CmpInst::FCMP_ULT);
   add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE);
   add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ);
@@ -395,6 +391,52 @@
   add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT);
   add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE);
 
+  llvm::Function *gripe_div0 = create_function ("gripe_divide_by_zero", void_t);
+  engine->addGlobalMapping (gripe_div0,
+                            reinterpret_cast<void *> (&gripe_divide_by_zero));
+
+  // divide is annoying because it might error
+  fn = create_function ("octave_jit_div_scalar_scalar", scalar, scalar, scalar);
+  llvm::BasicBlock *body = llvm::BasicBlock::Create (context, "body", fn);
+  builder.SetInsertPoint (body);
+  {
+    llvm::BasicBlock *warn_block = llvm::BasicBlock::Create (context, "warn", fn);
+    llvm::BasicBlock *normal_block = llvm::BasicBlock::Create (context, "normal", fn);
+
+    llvm::Value *zero = llvm::ConstantFP::get (dbl, 0);
+    llvm::Value *check = builder.CreateFCmpUEQ (zero, ++fn->arg_begin ());
+    builder.CreateCondBr (check, warn_block, normal_block);
+
+    builder.SetInsertPoint (warn_block);
+    builder.CreateCall (gripe_div0);
+    builder.CreateBr (normal_block);
+
+    builder.SetInsertPoint (normal_block);
+    llvm::Value *ret = builder.CreateFDiv (fn->arg_begin (), ++fn->arg_begin ());
+    builder.CreateRet (ret);
+
+    jit_function::overload ol (fn, true, true, scalar, scalar, scalar);
+    binary_ops[octave_value::op_div].add_overload (ol);
+    binary_ops[octave_value::op_el_div].add_overload (ol);
+  }
+  llvm::verifyFunction (*fn);
+
+  // ldiv is the same as div with the operators reversed
+  llvm::Function *div = fn;
+  fn = create_function ("octave_jit_ldiv_scalar_scalar", scalar, scalar, scalar);
+  body = llvm::BasicBlock::Create (context, "body", fn);
+  builder.SetInsertPoint (body);
+  {
+    llvm::Value *ret = builder.CreateCall2 (div, ++fn->arg_begin (),
+                                            fn->arg_begin ());
+    builder.CreateRet (ret);
+
+    jit_function::overload ol (fn, true, true, scalar, scalar, scalar);
+    binary_ops[octave_value::op_ldiv].add_overload (ol);
+    binary_ops[octave_value::op_el_ldiv].add_overload (ol);
+  }
+  llvm::verifyFunction (*fn);
+
   // now for binary index operators
   add_binary_op (index, octave_value::op_add, llvm::Instruction::Add);
 
@@ -407,7 +449,7 @@
   for_init_fn.stash_name ("for_init");
 
   fn = create_function ("octave_jit_for_range_init", index, range);
-  llvm::BasicBlock *body = llvm::BasicBlock::Create (context, "body", fn); 
+  body = llvm::BasicBlock::Create (context, "body", fn);
   builder.SetInsertPoint (body);
   {
     llvm::Value *zero = llvm::ConstantInt::get (index_t, 0);
--- a/src/pt-jit.h	Thu Jun 07 16:45:19 2012 -0500
+++ b/src/pt-jit.h	Thu Jun 07 17:25:58 2012 -0500
@@ -440,6 +440,12 @@
 
   void add_binary_fcmp (jit_type *ty, int op, int llvm_op);
 
+  llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret)
+  {
+    std::vector<llvm::Type *> args;
+    return create_function (name, ret, args);
+  }
+
   llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret,
                                    llvm::Type *arg0)
   {