]> granicus.if.org Git - clang/commitdiff
Implement basic _Complex integer constant folding.
authorDaniel Dunbar <daniel@zuster.org>
Wed, 28 Jan 2009 22:24:07 +0000 (22:24 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 28 Jan 2009 22:24:07 +0000 (22:24 +0000)
 - 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

lib/AST/ExprConstant.cpp
lib/CodeGen/CGExprConstant.cpp
test/CodeGen/const-init.c

index 66261045a5b6aa3b089dfdabfa1f52683aa583a2..af50de6f948147bbe4d6ca54f48de258b7a4d991 100644 (file)
@@ -55,8 +55,7 @@ static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
 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 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
 }
 
 //===----------------------------------------------------------------------===//
-// 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 @@ public:
   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 @@ public:
       
       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 @@ public:
 };
 } // 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 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
       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;
index 3b6ebb4d56f3905d5bd93ba910ceee21e62aa9e2..87868ed347a8c10bd599fd720d4a5ae5c4e77d02 100644 (file)
@@ -597,7 +597,9 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
     assert(!Result.HasSideEffects && 
            "Constant expr should not have any side effects!");
     switch (Result.Val.getKind()) {
-    default: assert(0 && "unhandled value kind!");
+    case APValue::Uninitialized:
+      assert(0 && "Constant expressions should be uninitialized.");
+      return llvm::UndefValue::get(getTypes().ConvertType(type));
     case APValue::LValue: {
       llvm::Constant *Offset = 
         llvm::ConstantInt::get(llvm::Type::Int64Ty, 
@@ -631,6 +633,14 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
       }
       return C;
     }
+    case APValue::ComplexInt: {
+      llvm::Constant *Complex[2];
+      
+      Complex[0] = llvm::ConstantInt::get(Result.Val.getComplexIntReal());
+      Complex[1] = llvm::ConstantInt::get(Result.Val.getComplexIntImag());
+      
+      return llvm::ConstantStruct::get(Complex, 2);
+    }
     case APValue::Float:
       return llvm::ConstantFP::get(Result.Val.getFloat());
     case APValue::ComplexFloat: {
index bded2e0a3f6fcfac4bd7274f2fedaea46ee1f273..3aabcfe60894902ce40434e1faf6ac58c917429c 100644 (file)
@@ -21,3 +21,6 @@ union s2 {
 };
 
 int g0 = (int)(&(((union s2 *) 0)->f0.f0) - 0);
+
+_Complex int g1 = 1 + 10i;
+_Complex double g2 = 1.0 + 10.0i;