From: Chris Lattner Date: Wed, 11 Jul 2007 23:43:46 +0000 (+0000) Subject: implement codegen support for pre/post inc/dec. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=572747983bf6bc9919a911a5995b564b56cb0fce;p=clang implement codegen support for pre/post inc/dec. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@39765 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp index 936770e42d..0250ab42db 100644 --- a/CodeGen/CGExpr.cpp +++ b/CodeGen/CGExpr.cpp @@ -632,19 +632,63 @@ RValue CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) { printf("Unimplemented unary expr!\n"); E->dump(); return RValue::get(llvm::UndefValue::get(llvm::Type::Int32Ty)); - // FIXME: pre/post inc/dec - case UnaryOperator::AddrOf: return EmitUnaryAddrOf(E); - case UnaryOperator::Deref : return EmitLoadOfLValue(E); - case UnaryOperator::Plus : return EmitUnaryPlus(E); - case UnaryOperator::Minus : return EmitUnaryMinus(E); - case UnaryOperator::Not : return EmitUnaryNot(E); - case UnaryOperator::LNot : return EmitUnaryLNot(E); + case UnaryOperator::PostInc: + case UnaryOperator::PostDec: + case UnaryOperator::PreInc : + case UnaryOperator::PreDec : return EmitUnaryIncDec(E); + case UnaryOperator::AddrOf : return EmitUnaryAddrOf(E); + case UnaryOperator::Deref : return EmitLoadOfLValue(E); + case UnaryOperator::Plus : return EmitUnaryPlus(E); + case UnaryOperator::Minus : return EmitUnaryMinus(E); + case UnaryOperator::Not : return EmitUnaryNot(E); + case UnaryOperator::LNot : return EmitUnaryLNot(E); // FIXME: SIZEOF/ALIGNOF(expr). // FIXME: real/imag case UnaryOperator::Extension: return EmitExpr(E->getSubExpr()); } } +RValue CodeGenFunction::EmitUnaryIncDec(const UnaryOperator *E) { + LValue LV = EmitLValue(E->getSubExpr()); + RValue InVal = EmitLoadOfLValue(LV, E->getSubExpr()->getType()); + + // We know the operand is real or pointer type, so it must be an LLVM scalar. + assert(InVal.isScalar() && "Unknown thing to increment"); + llvm::Value *InV = InVal.getVal(); + + int AmountVal = 1; + if (E->getOpcode() == UnaryOperator::PreDec || + E->getOpcode() == UnaryOperator::PostDec) + AmountVal = -1; + + llvm::Value *NextVal; + if (isa(InV->getType())) { + NextVal = llvm::ConstantInt::get(InV->getType(), AmountVal); + NextVal = Builder.CreateAdd(InV, NextVal, AmountVal == 1 ? "inc" : "dec"); + } else if (InV->getType()->isFloatingPoint()) { + NextVal = llvm::ConstantFP::get(InV->getType(), AmountVal); + NextVal = Builder.CreateAdd(InV, NextVal, AmountVal == 1 ? "inc" : "dec"); + } else { + // FIXME: This is not right for pointers to VLA types. + assert(isa(InV->getType())); + NextVal = llvm::ConstantInt::get(llvm::Type::Int32Ty, AmountVal); + NextVal = Builder.CreateGEP(InV, NextVal, AmountVal == 1 ? "inc" : "dec"); + } + + RValue NextValToStore = RValue::get(NextVal); + + // Store the updated result through the lvalue. + EmitStoreThroughLValue(NextValToStore, LV, E->getSubExpr()->getType()); + + // If this is a postinc, return the value read from memory, otherwise use the + // updated value. + if (E->getOpcode() == UnaryOperator::PreDec || + E->getOpcode() == UnaryOperator::PreInc) + return NextValToStore; + else + return InVal; +} + /// C99 6.5.3.2 RValue CodeGenFunction::EmitUnaryAddrOf(const UnaryOperator *E) { // The address of the operand is just its lvalue. It cannot be a bitfield. diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index acefedf3cc..fe570feb93 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -316,7 +316,7 @@ public: // Unary Operators. RValue EmitUnaryOperator(const UnaryOperator *E); - // FIXME: pre/post inc/dec + RValue EmitUnaryIncDec (const UnaryOperator *E); RValue EmitUnaryAddrOf (const UnaryOperator *E); RValue EmitUnaryPlus (const UnaryOperator *E); RValue EmitUnaryMinus (const UnaryOperator *E);