diff options
author | John McCall <rjmccall@apple.com> | 2010-10-09 01:34:31 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-10-09 01:34:31 +0000 |
commit | 189d6ef40eff11b83b2cda941d5ed89a5cef09b2 (patch) | |
tree | b3ed268c2a51e3b69a2da8173a7de925861ed445 | |
parent | 59705aee3fe01aa6fb6962dd11350161b47983d9 (diff) |
Permit constant evaluation of const floating-point variables with
constant initializers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116138 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ExprConstant.cpp | 41 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 33 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/const-init.cpp | 12 |
7 files changed, 79 insertions, 15 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fc29550a1e..69a008fdc5 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 378be1ef49..8764babd63 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -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(); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 0c33fb396b..e36712c197 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -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); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index bc67eb8e0b..ef12cd844c 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -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); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index ed43ccadd2..d291d40c55 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -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); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 8dc8ac1e3d..2c8b1eaebe 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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 //===--------------------------------------------------------------------===// diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index 9cfce7ace8..d206b64951 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -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 }; +} |