]> granicus.if.org Git - clang/commitdiff
Permit constant evaluation of const floating-point variables with
authorJohn McCall <rjmccall@apple.com>
Sat, 9 Oct 2010 01:34:31 +0000 (01:34 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 9 Oct 2010 01:34:31 +0000 (01:34 +0000)
constant initializers.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116138 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
lib/CodeGen/CGDebugInfo.cpp
lib/CodeGen/CGDebugInfo.h
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/const-init.cpp

index fc29550a1ece5dad50ae32b4d8bd904421ffc97a..69a008fdc57f0b069a4412cf170e62f0eaa6d7e4 100644 (file)
@@ -1780,6 +1780,8 @@ public:
   bool VisitUnaryReal(const UnaryOperator *E);
   bool VisitUnaryImag(const UnaryOperator *E);
 
+  bool VisitDeclRefExpr(const DeclRefExpr *E);
+
   // FIXME: Missing: array subscript of vector, member of vector,
   //                 ImplicitValueInitExpr
 };
@@ -1867,6 +1869,45 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
   }
 }
 
+bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
+  const Decl *D = E->getDecl();
+  if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D)) return false;
+  const VarDecl *VD = cast<VarDecl>(D);
+
+  // Require the qualifiers to be const and not volatile.
+  CanQualType T = Info.Ctx.getCanonicalType(E->getType());
+  if (!T.isConstQualified() || T.isVolatileQualified())
+    return false;
+
+  const Expr *Init = VD->getAnyInitializer();
+  if (!Init) return false;
+
+  if (APValue *V = VD->getEvaluatedValue()) {
+    if (V->isFloat()) {
+      Result = V->getFloat();
+      return true;
+    }
+    return false;
+  }
+
+  if (VD->isEvaluatingValue())
+    return false;
+
+  VD->setEvaluatingValue();
+
+  Expr::EvalResult InitResult;
+  if (Init->Evaluate(InitResult, Info.Ctx) && !InitResult.HasSideEffects &&
+      InitResult.Val.isFloat()) {
+    // Cache the evaluated value in the variable declaration.
+    Result = InitResult.Val.getFloat();
+    VD->setEvaluatedValue(InitResult.Val);
+    return true;
+  }
+
+  VD->setEvaluatedValue(APValue());
+  return false;
+}
+
 bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
   if (E->getSubExpr()->getType()->isAnyComplexType()) {
     ComplexValue CV;
index 378be1ef4931317386710308984013e42e6d6f18..8764babd63127e6f5120d342bbd437827354799f 100644 (file)
@@ -1941,7 +1941,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
 
 /// EmitGlobalVariable - Emit global variable's debug info.
 void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, 
-                                     llvm::ConstantInt *Init) {
+                                     llvm::Constant *Init) {
   // Create the descriptor for the variable.
   llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
   llvm::StringRef Name = VD->getName();
index 0c33fb396b90b32fe2d7f74a52d258235cd9b0c2..e36712c197f0906657a2a0d7862611fac74ced74 100644 (file)
@@ -186,7 +186,7 @@ public:
   void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
 
   /// EmitGlobalVariable - Emit global variable's debug info.
-  void EmitGlobalVariable(const ValueDecl *VD, llvm::ConstantInt *Init);
+  void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
 
   /// getOrCreateRecordType - Emit record type's standalone debug info. 
   llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
index bc67eb8e0bd5ae51ca0d0be35cb9eb68ecbb1384..ef12cd844c33667a2d47cba852cddbd836f2509d 100644 (file)
@@ -161,18 +161,29 @@ public:
   // l-values.
   Value *VisitDeclRefExpr(DeclRefExpr *E) {
     Expr::EvalResult Result;
-    if (E->Evaluate(Result, CGF.getContext()) && Result.Val.isInt()) {
-      assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
-      llvm::ConstantInt *CI 
-        = llvm::ConstantInt::get(VMContext, Result.Val.getInt());
-      if (VarDecl *VD = dyn_cast<VarDecl>((E->getDecl()))) {
-        if (!CGF.getContext().DeclMustBeEmitted(VD))
-          CGF.EmitDeclRefExprDbgValue(E, CI);
-      } else if (isa<EnumConstantDecl>(E->getDecl()))
-        CGF.EmitDeclRefExprDbgValue(E, CI);        
-      return CI;
+    if (!E->Evaluate(Result, CGF.getContext()))
+      return EmitLoadOfLValue(E);
+
+    assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
+
+    llvm::Constant *C;
+    if (Result.Val.isInt()) {
+      C = llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+    } else if (Result.Val.isFloat()) {
+      C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
+    } else {
+      return EmitLoadOfLValue(E);
     }
-    return EmitLoadOfLValue(E);
+
+    // Make sure we emit a debug reference to the global variable.
+    if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+      if (!CGF.getContext().DeclMustBeEmitted(VD))
+        CGF.EmitDeclRefExprDbgValue(E, C);
+    } else if (isa<EnumConstantDecl>(E->getDecl())) {
+      CGF.EmitDeclRefExprDbgValue(E, C);
+    }
+
+    return C;
   }
   Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
     return CGF.EmitObjCSelectorExpr(E);
index ed43ccadd2d76c4bdf261d6cc28fce41f55d3f67..d291d40c559342486bf9e6eae88718f3364fcb30 100644 (file)
@@ -1547,7 +1547,7 @@ llvm::Value *CodeGenFunction::getEHCleanupDestSlot() {
 }
 
 void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E, 
-                                              llvm::ConstantInt *Init) {
+                                              llvm::Constant *Init) {
   assert (Init && "Invalid DeclRefExpr initializer!");
   if (CGDebugInfo *Dbg = getDebugInfo())
     Dbg->EmitGlobalVariable(E->getDecl(), Init);
index 8dc8ac1e3d2c5c01de3a3923c5c3afa32b5aad0a..2c8b1eaebe02106d226b8a3d8dc397af4e8f8673 100644 (file)
@@ -1443,7 +1443,7 @@ public:
   LValue EmitStmtExprLValue(const StmtExpr *E);
   LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
   LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
-  void   EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::ConstantInt *Init);
+  void   EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
   //===--------------------------------------------------------------------===//
   //                         Scalar Expression Emission
   //===--------------------------------------------------------------------===//
index 9cfce7ace86b6e55bc719a7e89383bd0dc5e6ce4..d206b6495193a1cf3ea083376baeed2092028b29 100644 (file)
@@ -24,3 +24,15 @@ public:
 // CHECK: @_ZN6PR55812g0E = global %1 { i32 1 }
 C g0 = { C::e1 };
 }
+
+namespace test2 {
+  struct A {
+    static const double d = 1.0;
+    static const float f = d / 2;
+  };
+
+  // CHECK: @_ZN5test22t0E = global double 1.000000e+00, align 8
+  // CHECK: @_ZN5test22t1E = global [2 x double] [double 1.000000e+00, double 5.000000e-01], align 16
+  double t0 = A::d;
+  double t1[] = { A::d, A::f };
+}