Implement basic _Complex integer constant folding.
- Merged into single ComplexEvaluator, these share too much logic to
be worth splitting for float/int (IMHO). Will split on request.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63248 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 6626104..af50de6 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -55,8 +55,7 @@
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
-static bool EvaluateComplexFloat(const Expr *E, APValue &Result,
- EvalInfo &Info);
+static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
//===----------------------------------------------------------------------===//
// Misc utilities
@@ -1228,16 +1227,16 @@
}
//===----------------------------------------------------------------------===//
-// Complex Float Evaluation
+// Complex Evaluation (for float and integer)
//===----------------------------------------------------------------------===//
namespace {
-class VISIBILITY_HIDDEN ComplexFloatExprEvaluator
- : public StmtVisitor<ComplexFloatExprEvaluator, APValue> {
+class VISIBILITY_HIDDEN ComplexExprEvaluator
+ : public StmtVisitor<ComplexExprEvaluator, APValue> {
EvalInfo &Info;
public:
- ComplexFloatExprEvaluator(EvalInfo &info) : Info(info) {}
+ ComplexExprEvaluator(EvalInfo &info) : Info(info) {}
//===--------------------------------------------------------------------===//
// Visitor Methods
@@ -1250,12 +1249,28 @@
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitImaginaryLiteral(ImaginaryLiteral *E) {
- APFloat Result(0.0);
- if (!EvaluateFloat(E->getSubExpr(), Result, Info))
- return APValue();
+ Expr* SubExpr = E->getSubExpr();
+
+ if (SubExpr->getType()->isRealFloatingType()) {
+ APFloat Result(0.0);
+
+ if (!EvaluateFloat(SubExpr, Result, Info))
+ return APValue();
- return APValue(APFloat(Result.getSemantics(), APFloat::fcZero),
- Result);
+ return APValue(APFloat(Result.getSemantics(), APFloat::fcZero),
+ Result);
+ } else {
+ assert(SubExpr->getType()->isIntegerType() &&
+ "Unexpected imaginary literal.");
+
+ llvm::APSInt Result;
+ if (!EvaluateInteger(SubExpr, Result, Info))
+ return APValue();
+
+ llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned());
+ Zero = 0;
+ return APValue(Zero, Result);
+ }
}
APValue VisitCastExpr(CastExpr *E) {
@@ -1269,6 +1284,15 @@
return APValue(Result,
APFloat(Result.getSemantics(), APFloat::fcZero));
+ } else if (SubExpr->getType()->isIntegerType()) {
+ APSInt Result;
+
+ if (!EvaluateInteger(SubExpr, Result, Info))
+ return APValue();
+
+ llvm::APSInt Zero(Result.getBitWidth(), !Result.isSigned());
+ Zero = 0;
+ return APValue(Result, Zero);
}
// FIXME: Handle more casts.
@@ -1280,38 +1304,48 @@
};
} // end anonymous namespace
-static bool EvaluateComplexFloat(const Expr *E, APValue &Result, EvalInfo &Info)
+static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info)
{
- Result = ComplexFloatExprEvaluator(Info).Visit(const_cast<Expr*>(E));
- if (Result.isComplexFloat())
- assert(&Result.getComplexFloatReal().getSemantics() ==
- &Result.getComplexFloatImag().getSemantics() &&
- "Invalid complex evaluation.");
- return Result.isComplexFloat();
+ Result = ComplexExprEvaluator(Info).Visit(const_cast<Expr*>(E));
+ assert((!Result.isComplexFloat() ||
+ (&Result.getComplexFloatReal().getSemantics() ==
+ &Result.getComplexFloatImag().getSemantics())) &&
+ "Invalid complex evaluation.");
+ return Result.isComplexFloat() || Result.isComplexInt();
}
-APValue ComplexFloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
+APValue ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E)
{
APValue Result, RHS;
- if (!EvaluateComplexFloat(E->getLHS(), Result, Info))
+ if (!EvaluateComplex(E->getLHS(), Result, Info))
return APValue();
- if (!EvaluateComplexFloat(E->getRHS(), RHS, Info))
+ if (!EvaluateComplex(E->getRHS(), RHS, Info))
return APValue();
-
+
switch (E->getOpcode()) {
default: return APValue();
case BinaryOperator::Add:
- Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
- APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
- APFloat::rmNearestTiesToEven);
+ if (Result.isComplexFloat()) {
+ Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
+ APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().add(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
+ } else {
+ Result.getComplexIntReal() += RHS.getComplexIntReal();
+ Result.getComplexIntImag() += RHS.getComplexIntImag();
+ }
case BinaryOperator::Sub:
- Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
- APFloat::rmNearestTiesToEven);
- Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
- APFloat::rmNearestTiesToEven);
+ if (Result.isComplexFloat()) {
+ Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
+ APFloat::rmNearestTiesToEven);
+ Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(),
+ APFloat::rmNearestTiesToEven);
+ } else {
+ Result.getComplexIntReal() -= RHS.getComplexIntReal();
+ Result.getComplexIntImag() -= RHS.getComplexIntImag();
+ }
}
return Result;
@@ -1346,10 +1380,10 @@
return false;
Result.Val = APValue(f);
- } else if (getType()->isComplexType()) {
- if (!EvaluateComplexFloat(this, Result.Val, Info))
+ } else if (getType()->isAnyComplexType()) {
+ if (!EvaluateComplex(this, Result.Val, Info))
return false;
- } else
+ } else
return false;
return true;