diff options
-rw-r--r-- | CodeGen/CGExpr.cpp | 58 | ||||
-rw-r--r-- | CodeGen/CodeGenFunction.h | 2 |
2 files changed, 52 insertions, 8 deletions
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<llvm::IntegerType>(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<llvm::PointerType>(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); |