aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CodeGen/CGExpr.cpp58
-rw-r--r--CodeGen/CodeGenFunction.h2
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);