From: Chris Lattner Date: Sat, 9 Jan 2010 21:40:03 +0000 (+0000) Subject: refactor pre/postinc logic into CGF and require the caller to pass in the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dd36d328730d8c02915d0884541b45ec6ca0049d;p=clang refactor pre/postinc logic into CGF and require the caller to pass in the lvalue to poke, no functionality change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93075 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index cd79fb2b53..2c2b76f2e4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -240,6 +240,132 @@ void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) { EmitBlock(Cont); } + +llvm::Value *CodeGenFunction:: +EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre) { + QualType ValTy = E->getSubExpr()->getType(); + llvm::Value *InVal = EmitLoadOfLValue(LV, ValTy).getScalarVal(); + + int AmountVal = isInc ? 1 : -1; + + if (ValTy->isPointerType() && + ValTy->getAs()->isVariableArrayType()) { + // The amount of the addition/subtraction needs to account for the VLA size + ErrorUnsupported(E, "VLA pointer inc/dec"); + } + + llvm::Value *NextVal; + if (const llvm::PointerType *PT = + dyn_cast(InVal->getType())) { + llvm::Constant *Inc = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); + if (!isa(PT->getElementType())) { + QualType PTEE = ValTy->getPointeeType(); + if (const ObjCInterfaceType *OIT = + dyn_cast(PTEE)) { + // Handle interface types, which are not represented with a concrete + // type. + int size = 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, 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() == llvm::Type::getInt1Ty(VMContext) && 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(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(AmountVal))); + else if (InVal->getType()->isDoubleTy()) + NextVal = + llvm::ConstantFP::get(VMContext, + llvm::APFloat(static_cast(AmountVal))); + else { + llvm::APFloat F(static_cast(AmountVal)); + bool ignored; + F.convert(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()) + EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, &NextVal); + else + 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; +} + + +CodeGenFunction::ComplexPairTy CodeGenFunction:: +EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre) { + ComplexPairTy InVal = LoadComplexFromAddr(LV.getAddress(), + LV.isVolatileQualified()); + + llvm::Value *NextVal; + if (isa(InVal.first->getType())) { + uint64_t AmountVal = isInc ? 1 : -1; + NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true); + + // Add the inc/dec to the real part. + NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); + } else { + QualType ElemTy = E->getType()->getAs()->getElementType(); + llvm::APFloat FVal(getContext().getFloatTypeSemantics(ElemTy), 1); + if (!isInc) + FVal.changeSign(); + NextVal = llvm::ConstantFP::get(getLLVMContext(), FVal); + + // Add the inc/dec to the real part. + NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); + } + + ComplexPairTy IncVal(NextVal, InVal.second); + + // Store the updated result through the lvalue. + StoreComplexToAddr(IncVal, LV.getAddress(), LV.isVolatileQualified()); + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + return isPre ? IncVal : InVal; +} + + //===----------------------------------------------------------------------===// // LValue Expression Emission //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index be2239ffb6..5ec336ce79 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -145,7 +145,10 @@ public: // Operators. ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E, - bool isInc, bool isPre); + bool isInc, bool isPre) { + LValue LV = CGF.EmitLValue(E->getSubExpr()); + return CGF.EmitComplexPrePostIncDec(E, LV, isInc, isPre); + } ComplexPairTy VisitUnaryPostDec(const UnaryOperator *E) { return VisitPrePostIncDec(E, false, false); } @@ -355,40 +358,6 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) { return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType())); } -ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, - bool isInc, bool isPre) { - LValue LV = CGF.EmitLValue(E->getSubExpr()); - ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), - LV.isVolatileQualified()); - - llvm::Value *NextVal; - if (isa(InVal.first->getType())) { - uint64_t AmountVal = isInc ? 1 : -1; - NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true); - - // Add the inc/dec to the real part. - NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); - } else { - QualType ElemTy = E->getType()->getAs()->getElementType(); - llvm::APFloat FVal(CGF.getContext().getFloatTypeSemantics(ElemTy), 1); - if (!isInc) - FVal.changeSign(); - NextVal = llvm::ConstantFP::get(CGF.getLLVMContext(), FVal); - - // Add the inc/dec to the real part. - NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); - } - - ComplexPairTy IncVal(NextVal, InVal.second); - - // Store the updated result through the lvalue. - EmitStoreOfComplex(IncVal, LV.getAddress(), LV.isVolatileQualified()); - - // If this is a postinc, return the value read from memory, otherwise use the - // updated value. - return isPre ? IncVal : InVal; -} - ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index d26f4b802e..69ffaf2505 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -208,7 +208,10 @@ public: Value *VisitBlockDeclRefExpr(const BlockDeclRefExpr *E); // Unary Operators. - Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre); + 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); } @@ -1003,98 +1006,6 @@ Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) { // Unary Operators //===----------------------------------------------------------------------===// -Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, - bool isInc, bool isPre) { - LValue LV = EmitLValue(E->getSubExpr()); - QualType ValTy = E->getSubExpr()->getType(); - Value *InVal = CGF.EmitLoadOfLValue(LV, ValTy).getScalarVal(); - - llvm::LLVMContext &VMContext = CGF.getLLVMContext(); - - int AmountVal = isInc ? 1 : -1; - - if (ValTy->isPointerType() && - ValTy->getAs()->isVariableArrayType()) { - // The amount of the addition/subtraction needs to account for the VLA size - CGF.ErrorUnsupported(E, "VLA pointer inc/dec"); - } - - Value *NextVal; - if (const llvm::PointerType *PT = - dyn_cast(InVal->getType())) { - llvm::Constant *Inc = - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); - if (!isa(PT->getElementType())) { - QualType PTEE = ValTy->getPointeeType(); - if (const ObjCInterfaceType *OIT = - dyn_cast(PTEE)) { - // 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() == llvm::Type::getInt1Ty(VMContext) && 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(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(AmountVal))); - else if (InVal->getType()->isDoubleTy()) - NextVal = - llvm::ConstantFP::get(VMContext, - llvm::APFloat(static_cast(AmountVal))); - else { - llvm::APFloat F(static_cast(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(); Value *Op = Visit(E->getSubExpr()); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f7ed4db455..8dbfb190df 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -798,7 +798,7 @@ public: llvm::Value *NumElements, llvm::Value *This); - llvm::Constant * GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, + llvm::Constant *GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, const ArrayType *Array, llvm::Value *This); @@ -819,6 +819,10 @@ public: void EmitCheck(llvm::Value *, unsigned Size); + llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre); + ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, + bool isInc, bool isPre); //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===//