diff options
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 95 |
1 files changed, 29 insertions, 66 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index d5ed233a97..ad373095de 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -80,8 +80,8 @@ public: llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } - LValue EmitCheckedLValue(const Expr *E, CodeGenFunction::CheckType CT) { - return CGF.EmitCheckedLValue(E, CT); + LValue EmitCheckedLValue(const Expr *E, CodeGenFunction::TypeCheckKind TCK) { + return CGF.EmitCheckedLValue(E, TCK); } Value *EmitLoadOfLValue(LValue LV) { @@ -92,7 +92,7 @@ public: /// value l-value, this method emits the address of the l-value, then loads /// and returns the result. Value *EmitLoadOfLValue(const Expr *E) { - return EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::CT_Load)); + return EmitLoadOfLValue(EmitCheckedLValue(E, CodeGenFunction::TCK_Load)); } /// EmitConversionToBool - Convert the specified expression value to a @@ -416,13 +416,7 @@ public: /// Create a binary op that checks for overflow. /// Currently only supports +, - and *. Value *EmitOverflowCheckedBinOp(const BinOpInfo &Ops); - // Emit the overflow BB when -ftrapv option is activated. - void EmitOverflowBB(llvm::BasicBlock *overflowBB) { - Builder.SetInsertPoint(overflowBB); - llvm::Function *Trap = CGF.CGM.getIntrinsic(llvm::Intrinsic::trap); - Builder.CreateCall(Trap); - Builder.CreateUnreachable(); - } + // Check for undefined division and modulus behaviors. void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops, llvm::Value *Zero,bool isDiv); @@ -1688,7 +1682,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( OpInfo.Opcode = E->getOpcode(); OpInfo.E = E; // Load/convert the LHS. - LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::CT_Store); + LValue LHSLV = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); OpInfo.LHS = EmitLoadOfLValue(LHSLV); llvm::PHINode *atomicPHI = 0; @@ -1760,14 +1754,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, } void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( - const BinOpInfo &Ops, - llvm::Value *Zero, bool isDiv) { - llvm::Function::iterator insertPt = Builder.GetInsertBlock(); - llvm::BasicBlock *contBB = - CGF.createBasicBlock(isDiv ? "div.cont" : "rem.cont", CGF.CurFn, - llvm::next(insertPt)); - llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn); - + const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) { llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType()); if (Ops.Ty->hasSignedIntegerRepresentation()) { @@ -1775,37 +1762,24 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( Builder.getInt(llvm::APInt::getSignedMinValue(Ty->getBitWidth())); llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL); - llvm::Value *Cond1 = Builder.CreateICmpEQ(Ops.RHS, Zero); - llvm::Value *LHSCmp = Builder.CreateICmpEQ(Ops.LHS, IntMin); - llvm::Value *RHSCmp = Builder.CreateICmpEQ(Ops.RHS, NegOne); - llvm::Value *Cond2 = Builder.CreateAnd(LHSCmp, RHSCmp, "and"); - Builder.CreateCondBr(Builder.CreateOr(Cond1, Cond2, "or"), - overflowBB, contBB); + llvm::Value *Cond1 = Builder.CreateICmpNE(Ops.RHS, Zero); + llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin); + llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne); + llvm::Value *Cond2 = Builder.CreateOr(LHSCmp, RHSCmp, "or"); + CGF.EmitCheck(Builder.CreateAnd(Cond1, Cond2, "and")); } else { - CGF.Builder.CreateCondBr(Builder.CreateICmpEQ(Ops.RHS, Zero), - overflowBB, contBB); + CGF.EmitCheck(Builder.CreateICmpNE(Ops.RHS, Zero)); } - EmitOverflowBB(overflowBB); - Builder.SetInsertPoint(contBB); } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { - if (isTrapvOverflowBehavior()) { + if (isTrapvOverflowBehavior()) { llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); if (Ops.Ty->isIntegerType()) EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); - else if (Ops.Ty->isRealFloatingType()) { - llvm::Function::iterator insertPt = Builder.GetInsertBlock(); - llvm::BasicBlock *DivCont = CGF.createBasicBlock("div.cont", CGF.CurFn, - llvm::next(insertPt)); - llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", - CGF.CurFn); - CGF.Builder.CreateCondBr(Builder.CreateFCmpOEQ(Ops.RHS, Zero), - overflowBB, DivCont); - EmitOverflowBB(overflowBB); - Builder.SetInsertPoint(DivCont); - } + else if (Ops.Ty->isRealFloatingType()) + CGF.EmitCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero)); } if (Ops.LHS->getType()->isFPOrFPVectorTy()) { llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div"); @@ -1874,6 +1848,14 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Value *result = Builder.CreateExtractValue(resultAndOverflow, 0); Value *overflow = Builder.CreateExtractValue(resultAndOverflow, 1); + // Handle overflow with llvm.trap if no custom handler has been specified. + const std::string *handlerName = + &CGF.getContext().getLangOpts().OverflowHandler; + if (handlerName->empty()) { + CGF.EmitCheck(Builder.CreateNot(overflow)); + return result; + } + // Branch in case of overflow. llvm::BasicBlock *initialBB = Builder.GetInsertBlock(); llvm::Function::iterator insertPt = initialBB; @@ -1883,15 +1865,6 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Builder.CreateCondBr(overflow, overflowBB, continueBB); - // Handle overflow with llvm.trap. - const std::string *handlerName = - &CGF.getContext().getLangOpts().OverflowHandler; - if (handlerName->empty()) { - EmitOverflowBB(overflowBB); - Builder.SetInsertPoint(continueBB); - return result; - } - // If an overflow handler is set, then we want to call it and then use its // result, if it returns. Builder.SetInsertPoint(overflowBB); @@ -2122,18 +2095,13 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { if (CGF.CatchUndefined && isa<llvm::IntegerType>(Ops.LHS->getType())) { unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth(); - llvm::BasicBlock *Cont = CGF.createBasicBlock("shl.cont"); - llvm::BasicBlock *Trap = CGF.getTrapBB(); llvm::Value *WidthMinusOne = llvm::ConstantInt::get(RHS->getType(), Width - 1); - CGF.Builder.CreateCondBr(Builder.CreateICmpULE(RHS, WidthMinusOne), - Cont, Trap); - CGF.EmitBlock(Cont); + CGF.EmitCheck(Builder.CreateICmpULE(RHS, WidthMinusOne)); if (Ops.Ty->hasSignedIntegerRepresentation()) { // Check whether we are shifting any non-zero bits off the top of the // integer. - Cont = CGF.createBasicBlock("shl.ok"); llvm::Value *BitsShiftedOff = Builder.CreateLShr(Ops.LHS, Builder.CreateSub(WidthMinusOne, RHS, "shl.zeros", @@ -2148,9 +2116,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { BitsShiftedOff = Builder.CreateLShr(BitsShiftedOff, One); } llvm::Value *Zero = llvm::ConstantInt::get(BitsShiftedOff->getType(), 0); - Builder.CreateCondBr(Builder.CreateICmpEQ(BitsShiftedOff, Zero), - Cont, Trap); - CGF.EmitBlock(Cont); + CGF.EmitCheck(Builder.CreateICmpEQ(BitsShiftedOff, Zero)); } } @@ -2166,11 +2132,8 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { if (CGF.CatchUndefined && isa<llvm::IntegerType>(Ops.LHS->getType())) { unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth(); - llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); - CGF.Builder.CreateCondBr(Builder.CreateICmpULT(RHS, - llvm::ConstantInt::get(RHS->getType(), Width)), - Cont, CGF.getTrapBB()); - CGF.EmitBlock(Cont); + llvm::Value *WidthVal = llvm::ConstantInt::get(RHS->getType(), Width); + CGF.EmitCheck(Builder.CreateICmpULT(RHS, WidthVal)); } if (Ops.Ty->hasUnsignedIntegerRepresentation()) @@ -2361,7 +2324,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { case Qualifiers::OCL_Weak: RHS = Visit(E->getRHS()); - LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::CT_Store); + LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); RHS = CGF.EmitARCStoreWeak(LHS.getAddress(), RHS, Ignore); break; @@ -2371,7 +2334,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // __block variables need to have the rhs evaluated first, plus // this should improve codegen just a little. RHS = Visit(E->getRHS()); - LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::CT_Store); + LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); // Store the value into the LHS. Bit-fields are handled specially // because the result is altered by the store, i.e., [C99 6.5.16p1] |