# HG changeset patch # User Max Brister # Date 1339107958 18000 # Node ID 1e3d0366ac8bc0d6a9bc6c4bb1df41259c8a7040 # Parent 5f05007ccc5fcb208ba51e9ff66922cee60620bb warn on divide by zero diff --git a/src/pt-jit.cc b/src/pt-jit.cc --- a/src/pt-jit.cc +++ b/src/pt-jit.cc @@ -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 (&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); diff --git a/src/pt-jit.h b/src/pt-jit.h --- a/src/pt-jit.h +++ b/src/pt-jit.h @@ -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 args; + return create_function (name, ret, args); + } + llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, llvm::Type *arg0) {