summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-14 04:30:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-14 04:30:29 +0000
commitdafff947599e3e397d39bc3ee3c36e51f34c1375 (patch)
tree592df6135488708bc3fd9f3e281bf7e19804671b /clang/lib/AST
parent23ef0d6c40f29b6c685f1737ac092e61c33aa219 (diff)
downloadbcm5719-llvm-dafff947599e3e397d39bc3ee3c36e51f34c1375.tar.gz
bcm5719-llvm-dafff947599e3e397d39bc3ee3c36e51f34c1375.zip
constexpr irgen: Add irgen support for APValue::Struct, APValue::Union,
APValue::Array and APValue::MemberPointer. All APValue values can now be emitted as constants. Add new CGCXXABI entry point for emitting an APValue MemberPointer. The other entrypoints dealing with constant member pointers are no longer necessary and will be removed in a later change. Switch codegen from using EvaluateAsRValue/EvaluateAsLValue to VarDecl::evaluateValue. This performs caching and deals with the nasty cases in C++11 where a non-const object's initializer can refer indirectly to previously-initialized fields within the same object. Building the intermediate APValue object incurs a measurable performance hit on pathological testcases with huge initializer lists, so we continue to build IR directly from the Expr nodes for array and record types outside of C++11. llvm-svn: 148178
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/Decl.cpp15
-rw-r--r--clang/lib/AST/ExprConstant.cpp13
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp22
3 files changed, 40 insertions, 10 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 9132b0a1903..3caca9d7e6c 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1379,15 +1379,20 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
return Eval;
}
-bool VarDecl::evaluateValue(
- llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+APValue *VarDecl::evaluateValue() const {
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ return evaluateValue(Notes);
+}
+
+APValue *VarDecl::evaluateValue(
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();
// We only produce notes indicating why an initializer is non-constant the
// first time it is evaluated. FIXME: The notes won't always be emitted the
// first time we try evaluation, so might not be produced at all.
if (Eval->WasEvaluated)
- return !Eval->Evaluated.isUninit();
+ return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated;
const Expr *Init = cast<Expr>(Eval->Value);
assert(!Init->isValueDependent());
@@ -1396,7 +1401,7 @@ bool VarDecl::evaluateValue(
// FIXME: Produce a diagnostic for self-initialization.
Eval->CheckedICE = true;
Eval->IsICE = false;
- return false;
+ return 0;
}
Eval->IsEvaluating = true;
@@ -1418,7 +1423,7 @@ bool VarDecl::evaluateValue(
Eval->IsICE = Notes.empty();
}
- return Result;
+ return Result ? &Eval->Evaluated : 0;
}
bool VarDecl::checkInitIsICE() const {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 912b111d617..ec5111579a2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5413,15 +5413,12 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const {
return true;
}
- // FIXME: Evaluating initializers for large arrays can cause performance
- // problems, and we don't use such values yet. Once we have a more efficient
- // array representation, this should be reinstated, and used by CodeGen.
- // The same problem affects large records.
+ // FIXME: Evaluating values of large array and record types can cause
+ // performance problems. Only do so in C++11 for now.
if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
!Ctx.getLangOptions().CPlusPlus0x)
return false;
- // FIXME: If this is the initializer for an lvalue, pass that in.
EvalInfo Info(Ctx, Result);
return ::EvaluateAsRValue(Info, this, Result.Val);
}
@@ -5461,6 +5458,12 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
const VarDecl *VD,
llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+ // FIXME: Evaluating initializers for large array and record types can cause
+ // performance problems. Only do so in C++11 for now.
+ if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
+ !Ctx.getLangOptions().CPlusPlus0x)
+ return false;
+
Expr::EvalStatus EStatus;
EStatus.Diag = &Notes;
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 5223219a306..d094461dc35 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2153,6 +2153,28 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) {
return Entry;
}
+static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) {
+ const ASTRecordLayout &Layout = C.getASTRecordLayout(FD->getParent());
+ return Layout.getFieldOffset(FD->getFieldIndex());
+}
+
+uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const {
+ uint64_t OffsetInBits;
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
+ OffsetInBits = ::getFieldOffset(*this, FD);
+ } else {
+ const IndirectFieldDecl *IFD = cast<IndirectFieldDecl>(VD);
+
+ OffsetInBits = 0;
+ for (IndirectFieldDecl::chain_iterator CI = IFD->chain_begin(),
+ CE = IFD->chain_end();
+ CI != CE; ++CI)
+ OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(*CI));
+ }
+
+ return OffsetInBits;
+}
+
/// getObjCLayout - Get or compute information about the layout of the
/// given interface.
///
OpenPOWER on IntegriCloud