diff options
author | Chris Lattner <sabre@nondot.org> | 2010-06-26 22:09:34 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-06-26 22:09:34 +0000 |
commit | 05dc78c0965caae4c19ad318a1690c70a51156d7 (patch) | |
tree | 61fa9232072361d05d68f03c0957b15d9c8fb26f /clang/lib/CodeGen/CGExprScalar.cpp | |
parent | 93e63a0218cfebc82362621e4553232b48cd5b40 (diff) | |
download | bcm5719-llvm-05dc78c0965caae4c19ad318a1690c70a51156d7.tar.gz bcm5719-llvm-05dc78c0965caae4c19ad318a1690c70a51156d7.zip |
move scalar inc/dec codegen into ScalarExprEmitter instead
of being in CGF. No functionality change.
llvm-svn: 106961
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 119 |
1 files changed, 111 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index c5bc320727a..63d14f0e53b 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -213,22 +213,27 @@ public: Value *VisitBlockDeclRefExpr(const BlockDeclRefExpr *E); // Unary Operators. - Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre) { - LValue LV = EmitLValue(E->getSubExpr()); - return CGF.EmitScalarPrePostIncDec(E, LV, isInc, isPre); - } Value *VisitUnaryPostDec(const UnaryOperator *E) { - return VisitPrePostIncDec(E, false, false); + LValue LV = EmitLValue(E->getSubExpr()); + return EmitScalarPrePostIncDec(E, LV, false, false); } Value *VisitUnaryPostInc(const UnaryOperator *E) { - return VisitPrePostIncDec(E, true, false); + LValue LV = EmitLValue(E->getSubExpr()); + return EmitScalarPrePostIncDec(E, LV, true, false); } Value *VisitUnaryPreDec(const UnaryOperator *E) { - return VisitPrePostIncDec(E, false, true); + LValue LV = EmitLValue(E->getSubExpr()); + return EmitScalarPrePostIncDec(E, LV, false, true); } Value *VisitUnaryPreInc(const UnaryOperator *E) { - return VisitPrePostIncDec(E, true, true); + LValue LV = EmitLValue(E->getSubExpr()); + return EmitScalarPrePostIncDec(E, LV, true, true); } + + llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre); + + Value *VisitUnaryAddrOf(const UnaryOperator *E) { return EmitLValue(E->getSubExpr()).getAddress(); } @@ -1121,6 +1126,97 @@ Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) { // Unary Operators //===----------------------------------------------------------------------===// +llvm::Value *ScalarExprEmitter:: +EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre) { + + QualType ValTy = E->getSubExpr()->getType(); + llvm::Value *InVal = EmitLoadOfLValue(LV, ValTy); + + int AmountVal = isInc ? 1 : -1; + + if (ValTy->isPointerType() && + ValTy->getAs<PointerType>()->isVariableArrayType()) { + // The amount of the addition/subtraction needs to account for the VLA size + CGF.ErrorUnsupported(E, "VLA pointer inc/dec"); + } + + llvm::Value *NextVal; + if (const llvm::PointerType *PT = + dyn_cast<llvm::PointerType>(InVal->getType())) { + llvm::Constant *Inc = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); + if (!isa<llvm::FunctionType>(PT->getElementType())) { + QualType PTEE = ValTy->getPointeeType(); + if (const ObjCObjectType *OIT = PTEE->getAs<ObjCObjectType>()) { + // Handle interface types, which are not represented with a concrete + // type. + int size = CGF.getContext().getTypeSize(OIT) / 8; + if (!isInc) + size = -size; + Inc = llvm::ConstantInt::get(Inc->getType(), size); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); + InVal = Builder.CreateBitCast(InVal, i8Ty); + NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr"); + llvm::Value *lhs = LV.getAddress(); + lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty)); + LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy)); + } else + NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec"); + } else { + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); + NextVal = Builder.CreateBitCast(InVal, i8Ty, "tmp"); + NextVal = Builder.CreateGEP(NextVal, Inc, "ptrincdec"); + NextVal = Builder.CreateBitCast(NextVal, InVal->getType()); + } + } else if (InVal->getType()->isIntegerTy(1) && isInc) { + // Bool++ is an interesting case, due to promotion rules, we get: + // Bool++ -> Bool = Bool+1 -> Bool = (int)Bool+1 -> + // Bool = ((int)Bool+1) != 0 + // An interesting aspect of this is that increment is always true. + // Decrement does not have this property. + NextVal = llvm::ConstantInt::getTrue(VMContext); + } else if (isa<llvm::IntegerType>(InVal->getType())) { + NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal); + + // Signed integer overflow is undefined behavior. + if (ValTy->isSignedIntegerType()) + NextVal = Builder.CreateNSWAdd(InVal, NextVal, isInc ? "inc" : "dec"); + else + NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec"); + } else { + // Add the inc/dec to the real part. + if (InVal->getType()->isFloatTy()) + NextVal = + llvm::ConstantFP::get(VMContext, + llvm::APFloat(static_cast<float>(AmountVal))); + else if (InVal->getType()->isDoubleTy()) + NextVal = + llvm::ConstantFP::get(VMContext, + llvm::APFloat(static_cast<double>(AmountVal))); + else { + llvm::APFloat F(static_cast<float>(AmountVal)); + bool ignored; + F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero, + &ignored); + NextVal = llvm::ConstantFP::get(VMContext, F); + } + NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec"); + } + + // Store the updated result through the lvalue. + if (LV.isBitField()) + CGF.EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, &NextVal); + else + CGF.EmitStoreThroughLValue(RValue::get(NextVal), LV, ValTy); + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + return isPre ? NextVal : InVal; +} + + + Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { TestAndClearIgnoreResultAssign(); // Emit unary minus with EmitSub so we handle overflow cases etc. @@ -2047,6 +2143,13 @@ Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src, DstTy); } + +llvm::Value *CodeGenFunction:: +EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre) { + return ScalarExprEmitter(*this).EmitScalarPrePostIncDec(E, LV, isInc, isPre); +} + LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { llvm::Value *V; // object->isa or (*object).isa |