[cfe-commits] r148178 - in /cfe/trunk: include/clang/AST/ lib/AST/ lib/CodeGen/ test/CodeGen/ test/CodeGenCXX/

Richard Smith richard-llvm at metafoo.co.uk
Fri Jan 13 20:30:29 PST 2012


Author: rsmith
Date: Fri Jan 13 22:30:29 2012
New Revision: 148178

URL: http://llvm.org/viewvc/llvm-project?rev=148178&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp
    cfe/trunk/lib/CodeGen/CGCXXABI.h
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
    cfe/trunk/test/CodeGen/2007-09-28-PackedUnionMember.c
    cfe/trunk/test/CodeGenCXX/blocks.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
    cfe/trunk/test/CodeGenCXX/pr9965.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jan 13 22:30:29 2012
@@ -1309,6 +1309,9 @@
   /// of class definition.
   const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
 
+  /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
+  uint64_t getFieldOffset(const ValueDecl *FD) const;
+
   bool isNearlyEmpty(const CXXRecordDecl *RD) const;
 
   MangleContext *createMangleContext();

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Jan 13 22:30:29 2012
@@ -1024,9 +1024,11 @@
 
   /// \brief Attempt to evaluate the value of the initializer attached to this
   /// declaration, and produce notes explaining why it cannot be evaluated or is
-  /// not a constant expression. Returns true if evaluation succeeded.
-  /// The value can be obtained by calling getEvaluatedValue.
-  bool evaluateValue(llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
+  /// not a constant expression. Returns a pointer to the value if evaluation
+  /// succeeded, 0 otherwise.
+  APValue *evaluateValue() const;
+  APValue *evaluateValue(
+    llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
 
   /// \brief Return the already-evaluated value of this variable's
   /// initializer, or NULL if the value is not yet known. Returns pointer

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Jan 13 22:30:29 2012
@@ -1379,15 +1379,20 @@
   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 @@
     // FIXME: Produce a diagnostic for self-initialization.
     Eval->CheckedICE = true;
     Eval->IsICE = false;
-    return false;
+    return 0;
   }
 
   Eval->IsEvaluating = true;
@@ -1418,7 +1423,7 @@
     Eval->IsICE = Notes.empty();
   }
 
-  return Result;
+  return Result ? &Eval->Evaluated : 0;
 }
 
 bool VarDecl::checkInitIsICE() const {

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Jan 13 22:30:29 2012
@@ -5413,15 +5413,12 @@
     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::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;
 

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Jan 13 22:30:29 2012
@@ -2153,6 +2153,28 @@
   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.
 ///

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Jan 13 22:30:29 2012
@@ -215,6 +215,7 @@
 /// acceptable because we make no promises about address stability of
 /// captured variables.
 static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
+                                            CodeGenFunction *CGF,
                                             const VarDecl *var) {
   QualType type = var->getType();
 
@@ -235,7 +236,7 @@
   const Expr *init = var->getInit();
   if (!init) return 0;
 
-  return CGM.EmitConstantExpr(init, var->getType());
+  return CGM.EmitConstantInit(*var, CGF);
 }
 
 /// Get the low bit of a nonzero character count.  This is the
@@ -278,7 +279,8 @@
 
 /// Compute the layout of the given block.  Attempts to lay the block
 /// out with minimal space requirements.
-static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
+static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
+                             CGBlockInfo &info) {
   ASTContext &C = CGM.getContext();
   const BlockDecl *block = info.getBlockDecl();
 
@@ -342,7 +344,7 @@
 
     // Otherwise, build a layout chunk with the size and alignment of
     // the declaration.
-    if (llvm::Constant *constant = tryCaptureAsConstant(CGM, variable)) {
+    if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) {
       info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant);
       continue;
     }
@@ -497,7 +499,7 @@
 
   // Compute information about the layout, etc., of this block,
   // pushing cleanups as necessary.
-  computeBlockInfo(CGF.CGM, blockInfo);
+  computeBlockInfo(CGF.CGM, &CGF, blockInfo);
 
   // Nothing else to do if it can be global.
   if (blockInfo.CanBeGlobal) return;
@@ -604,7 +606,7 @@
   // layout for it.
   if (!blockExpr->getBlockDecl()->hasCaptures()) {
     CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
-    computeBlockInfo(CGM, blockInfo);
+    computeBlockInfo(CGM, this, blockInfo);
     blockInfo.BlockExpression = blockExpr;
     return EmitBlockLiteral(blockInfo);
   }
@@ -911,7 +913,7 @@
   blockInfo.BlockExpression = blockExpr;
 
   // Compute information about the layout, etc., of this block.
-  computeBlockInfo(*this, blockInfo);
+  computeBlockInfo(*this, 0, blockInfo);
 
   // Using that metadata, generate the actual block function.
   llvm::Constant *blockFn;

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Fri Jan 13 22:30:29 2012
@@ -110,6 +110,10 @@
   return GetBogusMemberPointer(CGM, QualType(MPT, 0));
 }
 
+llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
+  return GetBogusMemberPointer(CGM, MPT);
+}
+
 bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
   // Fake answer.
   return true;

Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Fri Jan 13 22:30:29 2012
@@ -125,6 +125,9 @@
   virtual llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                                 CharUnits offset);
 
+  /// Create a member pointer for the given member pointer constant.
+  virtual llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
+
   /// Emit a comparison between two member pointers.  Returns an i1.
   virtual llvm::Value *
   EmitMemberPointerComparison(CodeGenFunction &CGF,

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Jan 13 22:30:29 2012
@@ -1112,9 +1112,8 @@
   for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
        I != E; ++I)
     if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
-      llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
-      if (V->getInit() && V->evaluateValue(Notes)) {
-        APValue *Value = V->getEvaluatedValue();
+      if (V->getInit()) {
+        const APValue *Value = V->evaluateValue();
         if (Value && Value->isInt()) {
           llvm::ConstantInt *CI
             = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Jan 13 22:30:29 2012
@@ -203,7 +203,7 @@
 llvm::GlobalVariable *
 CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
                                                llvm::GlobalVariable *GV) {
-  llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
+  llvm::Constant *Init = CGM.EmitConstantInit(D, this);
 
   // If constant emission failed, then this should be a C++ static
   // initializer.
@@ -972,7 +972,7 @@
   llvm::Constant *constant = 0;
   if (emission.IsConstantAggregate) {
     assert(!capturedByInit && "constant init contains a capturing block?");
-    constant = CGM.EmitConstantExpr(D.getInit(), type, this);
+    constant = CGM.EmitConstantInit(D, this);
   }
 
   if (!constant) {

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Fri Jan 13 22:30:29 2012
@@ -44,14 +44,16 @@
 public:
   static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
                                      InitListExpr *ILE);
-  
-private:  
+  static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
+                                     const APValue &Value, QualType ValTy);
+
+private:
   ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
     : CGM(CGM), CGF(CGF), Packed(false), 
     NextFieldOffsetInChars(CharUnits::Zero()),
     LLVMStructAlignment(CharUnits::One()) { }
 
-  bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
+  void AppendField(const FieldDecl *Field, uint64_t FieldOffset,
                    llvm::Constant *InitExpr);
 
   void AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
@@ -62,8 +64,10 @@
   void AppendTailPadding(CharUnits RecordSize);
 
   void ConvertStructToPacked();
-                              
+
   bool Build(InitListExpr *ILE);
+  void Build(const APValue &Val, QualType ValTy);
+  llvm::Constant *Finalize(QualType Ty);
 
   CharUnits getAlignment(const llvm::Constant *C) const {
     if (Packed)  return CharUnits::One();
@@ -77,7 +81,7 @@
   }
 };
 
-bool ConstStructBuilder::
+void ConstStructBuilder::
 AppendField(const FieldDecl *Field, uint64_t FieldOffset,
             llvm::Constant *InitCst) {
 
@@ -99,14 +103,13 @@
 
     // Convert the struct to a packed struct.
     ConvertStructToPacked();
-    
+
     AlignedNextFieldOffsetInChars = NextFieldOffsetInChars;
   }
 
   if (AlignedNextFieldOffsetInChars < FieldOffsetInChars) {
     // We need to append padding.
-    AppendPadding(
-        FieldOffsetInChars - NextFieldOffsetInChars);
+    AppendPadding(FieldOffsetInChars - NextFieldOffsetInChars);
 
     assert(NextFieldOffsetInChars == FieldOffsetInChars &&
            "Did not add enough padding!");
@@ -118,14 +121,12 @@
   Elements.push_back(InitCst);
   NextFieldOffsetInChars = AlignedNextFieldOffsetInChars +
                            getSizeInChars(InitCst);
-  
+
   if (Packed)
-    assert(LLVMStructAlignment == CharUnits::One() && 
+    assert(LLVMStructAlignment == CharUnits::One() &&
            "Packed struct not byte-aligned!");
   else
     LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);
-
-  return true;
 }
 
 void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
@@ -382,14 +383,84 @@
     
     if (!Field->isBitField()) {
       // Handle non-bitfield members.
-      if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit))
-        return false;
+      AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
+    } else {
+      // Otherwise we have a bitfield.
+      AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
+                     cast<llvm::ConstantInt>(EltInit));
+    }
+  }
+
+  return true;
+}
+
+void ConstStructBuilder::Build(const APValue &Val, QualType ValTy) {
+  RecordDecl *RD = ValTy->getAs<RecordType>()->getDecl();
+  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+  if (CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
+    unsigned BaseNo = 0;
+    for (CXXRecordDecl::base_class_iterator Base = CD->bases_begin(),
+         BaseEnd = CD->bases_end(); Base != BaseEnd; ++Base, ++BaseNo) {
+      // Build the base class subobject at the appropriately-offset location
+      // within this object.
+      const CXXRecordDecl *BD = Base->getType()->getAsCXXRecordDecl();
+      CharUnits BaseOffset = Layout.getBaseClassOffset(BD);
+      NextFieldOffsetInChars -= BaseOffset;
+
+      Build(Val.getStructBase(BaseNo), Base->getType());
+
+      NextFieldOffsetInChars += BaseOffset;
+    }
+  }
+
+  unsigned FieldNo = 0;
+  const FieldDecl *LastFD = 0;
+  bool IsMsStruct = RD->hasAttr<MsStructAttr>();
+
+  for (RecordDecl::field_iterator Field = RD->field_begin(),
+       FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
+    if (IsMsStruct) {
+      // Zero-length bitfields following non-bitfield members are
+      // ignored:
+      if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD)) {
+        --FieldNo;
+        continue;
+      }
+      LastFD = (*Field);
+    }
+
+    // If this is a union, skip all the fields that aren't being initialized.
+    if (RD->isUnion() && Val.getUnionField() != *Field)
+      continue;
+
+    // Don't emit anonymous bitfields, they just affect layout.
+    if (Field->isUnnamedBitfield()) {
+      LastFD = (*Field);
+      continue;
+    }
+
+    // Emit the value of the initializer.
+    const APValue &FieldValue =
+      RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
+    llvm::Constant *EltInit =
+      CGM.EmitConstantValue(FieldValue, Field->getType(), CGF);
+    assert(EltInit && "EmitConstantValue can't fail");
+
+    if (!Field->isBitField()) {
+      // Handle non-bitfield members.
+      AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
     } else {
       // Otherwise we have a bitfield.
       AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
                      cast<llvm::ConstantInt>(EltInit));
     }
   }
+}
+
+llvm::Constant *ConstStructBuilder::Finalize(QualType Ty) {
+  RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
+  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
 
   CharUnits LayoutSizeInChars = Layout.getSize();
 
@@ -398,62 +469,69 @@
     // we must have a flexible array member at the end.
     assert(RD->hasFlexibleArrayMember() &&
            "Must have flexible array member if struct is bigger than type!");
-    
+
     // No tail padding is necessary.
-    return true;
-  }
+  } else {
+    // Append tail padding if necessary.
+    AppendTailPadding(LayoutSizeInChars);
 
-  CharUnits LLVMSizeInChars = 
-    NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment);
+    CharUnits LLVMSizeInChars =
+      NextFieldOffsetInChars.RoundUpToAlignment(LLVMStructAlignment);
 
-  // Check if we need to convert the struct to a packed struct.
-  if (NextFieldOffsetInChars <= LayoutSizeInChars && 
-      LLVMSizeInChars > LayoutSizeInChars) {
-    assert(!Packed && "Size mismatch!");
-    
-    ConvertStructToPacked();
-    assert(NextFieldOffsetInChars <= LayoutSizeInChars &&
-           "Converting to packed did not help!");
-  }
+    // Check if we need to convert the struct to a packed struct.
+    if (NextFieldOffsetInChars <= LayoutSizeInChars &&
+        LLVMSizeInChars > LayoutSizeInChars) {
+      assert(!Packed && "Size mismatch!");
 
-  // Append tail padding if necessary.
-  AppendTailPadding(LayoutSizeInChars);
+      ConvertStructToPacked();
+      assert(NextFieldOffsetInChars <= LayoutSizeInChars &&
+             "Converting to packed did not help!");
+    }
 
-  assert(LayoutSizeInChars == NextFieldOffsetInChars &&
-         "Tail padding mismatch!");
+    assert(LayoutSizeInChars == NextFieldOffsetInChars &&
+           "Tail padding mismatch!");
+  }
 
-  return true;
-}
-  
-llvm::Constant *ConstStructBuilder::
-  BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, InitListExpr *ILE) {
-  ConstStructBuilder Builder(CGM, CGF);
-  
-  if (!Builder.Build(ILE))
-    return 0;
-  
   // Pick the type to use.  If the type is layout identical to the ConvertType
   // type then use it, otherwise use whatever the builder produced for us.
   llvm::StructType *STy =
       llvm::ConstantStruct::getTypeForElements(CGM.getLLVMContext(),
-                                               Builder.Elements,Builder.Packed);
-  llvm::Type *ILETy = CGM.getTypes().ConvertType(ILE->getType());
-  if (llvm::StructType *ILESTy = dyn_cast<llvm::StructType>(ILETy)) {
-    if (ILESTy->isLayoutIdentical(STy))
-      STy = ILESTy;
+                                               Elements, Packed);
+  llvm::Type *ValTy = CGM.getTypes().ConvertType(Ty);
+  if (llvm::StructType *ValSTy = dyn_cast<llvm::StructType>(ValTy)) {
+    if (ValSTy->isLayoutIdentical(STy))
+      STy = ValSTy;
   }
-    
-  llvm::Constant *Result =
-    llvm::ConstantStruct::get(STy, Builder.Elements);
-  
-  assert(Builder.NextFieldOffsetInChars.RoundUpToAlignment(
-           Builder.getAlignment(Result)) ==
-         Builder.getSizeInChars(Result) && "Size mismatch!");
-  
+
+  llvm::Constant *Result = llvm::ConstantStruct::get(STy, Elements);
+
+  assert(NextFieldOffsetInChars.RoundUpToAlignment(getAlignment(Result)) ==
+         getSizeInChars(Result) && "Size mismatch!");
+
   return Result;
 }
 
-  
+llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
+                                                CodeGenFunction *CGF,
+                                                InitListExpr *ILE) {
+  ConstStructBuilder Builder(CGM, CGF);
+
+  if (!Builder.Build(ILE))
+    return 0;
+
+  return Builder.Finalize(ILE->getType());
+}
+
+llvm::Constant *ConstStructBuilder::BuildStruct(CodeGenModule &CGM,
+                                                CodeGenFunction *CGF,
+                                                const APValue &Val,
+                                                QualType ValTy) {
+  ConstStructBuilder Builder(CGM, CGF);
+  Builder.Build(Val, ValTy);
+  return Builder.Finalize(ValTy);
+}
+
+
 //===----------------------------------------------------------------------===//
 //                             ConstExprEmitter
 //===----------------------------------------------------------------------===//
@@ -863,6 +941,22 @@
 
 }  // end anonymous namespace.
 
+llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
+                                                CodeGenFunction *CGF) {
+  if (const APValue *Value = D.evaluateValue())
+    return EmitConstantValue(*Value, D.getType(), CGF);
+
+  const Expr *E = D.getInit();
+  assert(E && "No initializer to emit");
+
+  llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+  if (C && C->getType()->isIntegerTy(1)) {
+    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+  }
+  return C;
+}
+
 llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
                                                 QualType DestType,
                                                 CodeGenFunction *CGF) {
@@ -875,155 +969,192 @@
   else
     Success = E->EvaluateAsRValue(Result, Context);
 
-  if (Success && !Result.HasSideEffects) {
-    switch (Result.Val.getKind()) {
-    case APValue::Uninitialized:
-      llvm_unreachable("Constant expressions should be initialized.");
-    case APValue::LValue: {
-      llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
-      llvm::Constant *Offset =
-        llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
-                               Result.Val.getLValueOffset().getQuantity());
-
-      llvm::Constant *C;
-      if (APValue::LValueBase LVBase = Result.Val.getLValueBase()) {
-        C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
-
-        // Apply offset if necessary.
-        if (!Offset->isNullValue()) {
-          llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
-          llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
-          Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
-          C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
-        }
+  if (Success && !Result.HasSideEffects)
+    return EmitConstantValue(Result.Val, DestType, CGF);
 
-        // Convert to the appropriate type; this could be an lvalue for
-        // an integer.
-        if (isa<llvm::PointerType>(DestTy))
-          return llvm::ConstantExpr::getBitCast(C, DestTy);
+  llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
+  if (C && C->getType()->isIntegerTy(1)) {
+    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+  }
+  return C;
+}
 
-        return llvm::ConstantExpr::getPtrToInt(C, DestTy);
-      } else {
-        C = Offset;
+llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
+                                                 QualType DestType,
+                                                 CodeGenFunction *CGF) {
+  switch (Value.getKind()) {
+  case APValue::Uninitialized:
+    llvm_unreachable("Constant expressions should be initialized.");
+  case APValue::LValue: {
+    llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
+    llvm::Constant *Offset =
+      llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+                             Value.getLValueOffset().getQuantity());
+
+    llvm::Constant *C;
+    if (APValue::LValueBase LVBase = Value.getLValueBase()) {
+      // An array can be represented as an lvalue referring to the base.
+      if (isa<llvm::ArrayType>(DestTy)) {
+        assert(Offset->isNullValue() && "offset on array initializer");
+        return ConstExprEmitter(*this, CGF).Visit(
+          const_cast<Expr*>(LVBase.get<const Expr*>()));
+      }
 
-        // Convert to the appropriate type; this could be an lvalue for
-        // an integer.
-        if (isa<llvm::PointerType>(DestTy))
-          return llvm::ConstantExpr::getIntToPtr(C, DestTy);
-
-        // If the types don't match this should only be a truncate.
-        if (C->getType() != DestTy)
-          return llvm::ConstantExpr::getTrunc(C, DestTy);
+      C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
 
-        return C;
-      }
-    }
-    case APValue::Int: {
-      llvm::Constant *C = llvm::ConstantInt::get(VMContext,
-                                                 Result.Val.getInt());
-
-      if (C->getType()->isIntegerTy(1)) {
-        llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
-        C = llvm::ConstantExpr::getZExt(C, BoolTy);
+      // Apply offset if necessary.
+      if (!Offset->isNullValue()) {
+        llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
+        llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
+        Casted = llvm::ConstantExpr::getGetElementPtr(Casted, Offset);
+        C = llvm::ConstantExpr::getBitCast(Casted, C->getType());
       }
+
+      // Convert to the appropriate type; this could be an lvalue for
+      // an integer.
+      if (isa<llvm::PointerType>(DestTy))
+        return llvm::ConstantExpr::getBitCast(C, DestTy);
+
+      return llvm::ConstantExpr::getPtrToInt(C, DestTy);
+    } else {
+      C = Offset;
+
+      // Convert to the appropriate type; this could be an lvalue for
+      // an integer.
+      if (isa<llvm::PointerType>(DestTy))
+        return llvm::ConstantExpr::getIntToPtr(C, DestTy);
+
+      // If the types don't match this should only be a truncate.
+      if (C->getType() != DestTy)
+        return llvm::ConstantExpr::getTrunc(C, DestTy);
+
       return C;
     }
-    case APValue::ComplexInt: {
-      llvm::Constant *Complex[2];
+  }
+  case APValue::Int: {
+    llvm::Constant *C = llvm::ConstantInt::get(VMContext,
+                                               Value.getInt());
+
+    if (C->getType()->isIntegerTy(1)) {
+      llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
+      C = llvm::ConstantExpr::getZExt(C, BoolTy);
+    }
+    return C;
+  }
+  case APValue::ComplexInt: {
+    llvm::Constant *Complex[2];
+
+    Complex[0] = llvm::ConstantInt::get(VMContext,
+                                        Value.getComplexIntReal());
+    Complex[1] = llvm::ConstantInt::get(VMContext,
+                                        Value.getComplexIntImag());
+
+    // FIXME: the target may want to specify that this is packed.
+    llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
+                                                  Complex[1]->getType(),
+                                                  NULL);
+    return llvm::ConstantStruct::get(STy, Complex);
+  }
+  case APValue::Float: {
+    const llvm::APFloat &Init = Value.getFloat();
+    if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf)
+      return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
+    else
+      return llvm::ConstantFP::get(VMContext, Init);
+  }
+  case APValue::ComplexFloat: {
+    llvm::Constant *Complex[2];
 
-      Complex[0] = llvm::ConstantInt::get(VMContext,
-                                          Result.Val.getComplexIntReal());
-      Complex[1] = llvm::ConstantInt::get(VMContext,
-                                          Result.Val.getComplexIntImag());
-
-      // FIXME: the target may want to specify that this is packed.
-      llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
-                                                    Complex[1]->getType(),
-                                                    NULL);
-      return llvm::ConstantStruct::get(STy, Complex);
-    }
-    case APValue::Float: {
-      const llvm::APFloat &Init = Result.Val.getFloat();
-      if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf)
-        return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
+    Complex[0] = llvm::ConstantFP::get(VMContext,
+                                       Value.getComplexFloatReal());
+    Complex[1] = llvm::ConstantFP::get(VMContext,
+                                       Value.getComplexFloatImag());
+
+    // FIXME: the target may want to specify that this is packed.
+    llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
+                                                  Complex[1]->getType(),
+                                                  NULL);
+    return llvm::ConstantStruct::get(STy, Complex);
+  }
+  case APValue::Vector: {
+    SmallVector<llvm::Constant *, 4> Inits;
+    unsigned NumElts = Value.getVectorLength();
+
+    for (unsigned i = 0; i != NumElts; ++i) {
+      const APValue &Elt = Value.getVectorElt(i);
+      if (Elt.isInt())
+        Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
       else
-        return llvm::ConstantFP::get(VMContext, Init);
+        Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
     }
-    case APValue::ComplexFloat: {
-      llvm::Constant *Complex[2];
-
-      Complex[0] = llvm::ConstantFP::get(VMContext,
-                                         Result.Val.getComplexFloatReal());
-      Complex[1] = llvm::ConstantFP::get(VMContext,
-                                         Result.Val.getComplexFloatImag());
-
-      // FIXME: the target may want to specify that this is packed.
-      llvm::StructType *STy = llvm::StructType::get(Complex[0]->getType(),
-                                                    Complex[1]->getType(),
-                                                    NULL);
-      return llvm::ConstantStruct::get(STy, Complex);
-    }
-    case APValue::Vector: {
-      SmallVector<llvm::Constant *, 4> Inits;
-      unsigned NumElts = Result.Val.getVectorLength();
-
-      if (Context.getLangOptions().AltiVec &&
-          isa<CastExpr>(E) &&
-          cast<CastExpr>(E)->getCastKind() == CK_VectorSplat) {
-        // AltiVec vector initialization with a single literal
-        APValue &Elt = Result.Val.getVectorElt(0);
-
-        llvm::Constant* InitValue = Elt.isInt()
-          ? cast<llvm::Constant>
-              (llvm::ConstantInt::get(VMContext, Elt.getInt()))
-          : cast<llvm::Constant>
-              (llvm::ConstantFP::get(VMContext, Elt.getFloat()));
+    return llvm::ConstantVector::get(Inits);
+  }
+  case APValue::AddrLabelDiff: {
+    const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS();
+    const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS();
+    llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
+    llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+
+    // Compute difference
+    llvm::Type *ResultType = getTypes().ConvertType(DestType);
+    LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
+    RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+    llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
+
+    // LLVM is a bit sensitive about the exact format of the
+    // address-of-label difference; make sure to truncate after
+    // the subtraction.
+    return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
+  }
+  case APValue::Struct:
+  case APValue::Union:
+    return ConstStructBuilder::BuildStruct(*this, CGF, Value, DestType);
+  case APValue::Array: {
+    const ArrayType *CAT = Context.getAsArrayType(DestType);
+    unsigned NumElements = Value.getArraySize();
+    unsigned NumInitElts = Value.getArrayInitializedElts();
 
-        for (unsigned i = 0; i != NumElts; ++i)
-          Inits.push_back(InitValue);
+    std::vector<llvm::Constant*> Elts;
+    Elts.reserve(NumElements);
 
-      } else {
-        for (unsigned i = 0; i != NumElts; ++i) {
-          APValue &Elt = Result.Val.getVectorElt(i);
-          if (Elt.isInt())
-            Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt()));
-          else
-            Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat()));
-        }
-      }
-      return llvm::ConstantVector::get(Inits);
+    // Emit array filler, if there is one.
+    llvm::Constant *Filler = 0;
+    if (Value.hasArrayFiller())
+      Filler = EmitConstantValue(Value.getArrayFiller(),
+                                 CAT->getElementType(), CGF);
+
+    // Emit initializer elements.
+    llvm::Type *CommonElementType = 0;
+    for (unsigned I = 0; I < NumElements; ++I) {
+      llvm::Constant *C = Filler;
+      if (I < NumInitElts)
+        C = EmitConstantValue(Value.getArrayInitializedElt(I),
+                              CAT->getElementType(), CGF);
+      if (I == 0)
+        CommonElementType = C->getType();
+      else if (C->getType() != CommonElementType)
+        CommonElementType = 0;
+      Elts.push_back(C);
     }
-    case APValue::AddrLabelDiff: {
-      const AddrLabelExpr *LHSExpr = Result.Val.getAddrLabelDiffLHS();
-      const AddrLabelExpr *RHSExpr = Result.Val.getAddrLabelDiffRHS();
-      llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
-      llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
-
-      // Compute difference
-      llvm::Type *ResultType = getTypes().ConvertType(E->getType());
-      LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
-      RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
-      llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
-
-      // LLVM is a bit sensitive about the exact format of the
-      // address-of-label difference; make sure to truncate after
-      // the subtraction.
-      return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
-    }
-    case APValue::Array:
-    case APValue::Struct:
-    case APValue::Union:
-    case APValue::MemberPointer:
-      break;
+
+    if (!CommonElementType) {
+      // FIXME: Try to avoid packing the array
+      std::vector<llvm::Type*> Types;
+      for (unsigned i = 0; i < Elts.size(); ++i)
+        Types.push_back(Elts[i]->getType());
+      llvm::StructType *SType = llvm::StructType::get(VMContext, Types, true);
+      return llvm::ConstantStruct::get(SType, Elts);
     }
-  }
 
-  llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
-  if (C && C->getType()->isIntegerTy(1)) {
-    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
-    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+    llvm::ArrayType *AType =
+      llvm::ArrayType::get(CommonElementType, NumElements);
+    return llvm::ConstantArray::get(AType, Elts);
   }
-  return C;
+  case APValue::MemberPointer:
+    return getCXXABI().EmitMemberPointer(Value, DestType);
+  }
+  llvm_unreachable("Unknown APValue kind");
 }
 
 llvm::Constant *
@@ -1032,11 +1163,6 @@
   return ConstExprEmitter(*this, 0).EmitLValue(E);
 }
 
-static uint64_t getFieldOffset(ASTContext &C, const FieldDecl *field) {
-  const ASTRecordLayout &layout = C.getASTRecordLayout(field->getParent());
-  return layout.getFieldOffset(field->getFieldIndex());
-}
-    
 llvm::Constant *
 CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
   // Member pointer constants always have a very particular form.
@@ -1048,18 +1174,7 @@
     return getCXXABI().EmitMemberPointer(method);
 
   // Otherwise, a member data pointer.
-  uint64_t fieldOffset;
-  if (const FieldDecl *field = dyn_cast<FieldDecl>(decl))
-    fieldOffset = getFieldOffset(getContext(), field);
-  else {
-    const IndirectFieldDecl *ifield = cast<IndirectFieldDecl>(decl);
-
-    fieldOffset = 0;
-    for (IndirectFieldDecl::chain_iterator ci = ifield->chain_begin(),
-           ce = ifield->chain_end(); ci != ce; ++ci)
-      fieldOffset += getFieldOffset(getContext(), cast<FieldDecl>(*ci));
-  }
-
+  uint64_t fieldOffset = getContext().getFieldOffset(decl);
   CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset);
   return getCXXABI().EmitMemberDataPointer(type, chars);
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Jan 13 22:30:29 2012
@@ -1354,7 +1354,8 @@
   QualType ASTTy = D->getType();
   bool NonConstInit = false;
 
-  const Expr *InitExpr = D->getAnyInitializer();
+  const VarDecl *InitDecl;
+  const Expr *InitExpr = D->getAnyInitializer(InitDecl);
   
   if (!InitExpr) {
     // This is a tentative definition; tentative definitions are
@@ -1369,12 +1370,12 @@
     assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
     Init = EmitNullConstant(D->getType());
   } else {
-    Init = EmitConstantExpr(InitExpr, D->getType());       
+    Init = EmitConstantInit(*InitDecl);
     if (!Init) {
       QualType T = InitExpr->getType();
       if (D->getType()->isReferenceType())
         T = D->getType();
-      
+
       if (getLangOptions().CPlusPlus) {
         Init = EmitNullConstant(T);
         NonConstInit = true;

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Jan 13 22:30:29 2012
@@ -687,12 +687,22 @@
 
   llvm::Constant *getMemberPointerConstant(const UnaryOperator *e);
 
+  /// EmitConstantInit - Try to emit the initializer for the given declaration
+  /// as a constant; returns 0 if the expression cannot be emitted as a
+  /// constant.
+  llvm::Constant *EmitConstantInit(const VarDecl &D, CodeGenFunction *CGF = 0);
+
   /// EmitConstantExpr - Try to emit the given expression as a
   /// constant; returns 0 if the expression cannot be emitted as a
   /// constant.
   llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
                                    CodeGenFunction *CGF = 0);
 
+  /// EmitConstantValue - Try to emit the given constant value as a
+  /// constant; returns 0 if the value cannot be emitted as a constant.
+  llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
+                                    CodeGenFunction *CGF = 0);
+
   /// EmitNullConstant - Return the result of value-initializing the given
   /// type, i.e. a null expression of the given type.  This is usually,
   /// but not always, an LLVM null constant.

Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Fri Jan 13 22:30:29 2012
@@ -82,6 +82,9 @@
   llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
                                         CharUnits offset);
+  llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT);
+  llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
+                                     CharUnits ThisAdjustment);
 
   llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
                                            llvm::Value *L,
@@ -500,6 +503,11 @@
 }
 
 llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+  return BuildMemberPointer(MD, CharUnits::Zero());
+}
+
+llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
+                                                  CharUnits ThisAdjustment) {
   assert(MD->isInstance() && "Member function must not be static!");
   MD = MD->getCanonicalDecl();
 
@@ -524,14 +532,16 @@
       //   discrimination as the least significant bit of ptr does for
       //   Itanium.
       MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset);
-      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1);
+      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t,
+                                         2 * ThisAdjustment.getQuantity() + 1);
     } else {
       // Itanium C++ ABI 2.3:
       //   For a virtual function, [the pointer field] is 1 plus the
       //   virtual table offset (in bytes) of the function,
       //   represented as a ptrdiff_t.
       MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1);
-      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+      MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t,
+                                         ThisAdjustment.getQuantity());
     }
   } else {
     const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
@@ -549,12 +559,45 @@
     llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty);
 
     MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t);
-    MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+    MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, (IsARM ? 2 : 1) *
+                                       ThisAdjustment.getQuantity());
   }
   
   return llvm::ConstantStruct::getAnon(MemPtr);
 }
 
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
+                                                 QualType MPType) {
+  const MemberPointerType *MPT = MPType->castAs<MemberPointerType>();
+  const ValueDecl *MPD = MP.getMemberPointerDecl();
+  if (!MPD)
+    return EmitNullMemberPointer(MPT);
+
+  // Compute the this-adjustment.
+  CharUnits ThisAdjustment = CharUnits::Zero();
+  ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
+  bool DerivedMember = MP.isMemberPointerToDerivedMember();
+  const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
+  for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+    const CXXRecordDecl *Base = RD;
+    const CXXRecordDecl *Derived = Path[I];
+    if (DerivedMember)
+      std::swap(Base, Derived);
+    ThisAdjustment +=
+      getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
+    RD = Path[I];
+  }
+  if (DerivedMember)
+    ThisAdjustment = -ThisAdjustment;
+
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
+    return BuildMemberPointer(MD, ThisAdjustment);
+
+  CharUnits FieldOffset =
+    getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
+  return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
+}
+
 /// The comparison algorithm is pretty easy: the member pointers are
 /// the same if they're either bitwise identical *or* both null.
 ///

Modified: cfe/trunk/test/CodeGen/2007-09-28-PackedUnionMember.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/2007-09-28-PackedUnionMember.c?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/2007-09-28-PackedUnionMember.c (original)
+++ cfe/trunk/test/CodeGen/2007-09-28-PackedUnionMember.c Fri Jan 13 22:30:29 2012
@@ -27,6 +27,7 @@
 static long hndlr()
 {
   struct H cmd = { 4, 412 };
+  struct H cmd2 = { 4, 412, 0 };
   return 0;
 }
 void foo(void *inWindow) {
@@ -35,4 +36,3 @@
   };
   bork(hndlr, events);
 }
-

Modified: cfe/trunk/test/CodeGenCXX/blocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/blocks.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/blocks.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/blocks.cpp Fri Jan 13 22:30:29 2012
@@ -203,3 +203,11 @@
   // CHECK-NEXT: call void @_ZN5test63barEv()
   // CHECK-NEXT: ret void
 }
+
+namespace test7 {
+  int f() {
+    static int n;
+    int *const p = &n;
+    return ^{ return *p; }();
+  }
+}

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Fri Jan 13 22:30:29 2012
@@ -1,5 +1,193 @@
 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
 
+// FIXME: The padding in all these objects should be zero-initialized.
+namespace StructUnion {
+  struct A {
+    int n;
+    double d;
+    union U {
+      constexpr U(int x) : x(x) {}
+      constexpr U(const char *y) : y(y) {}
+      int x;
+      const char *y;
+    } u;
+
+    constexpr A(int n, double d, int x) : n(n), d(d), u(x) {}
+    constexpr A(int n, double d, const char *y) : n(n), d(d), u(y) {}
+  };
+
+  // CHECK: @_ZN11StructUnion1aE = global {{.*}} { i32 1, double 2.000000e+00, {{.*}} { i32 3, [4 x i8] undef } }
+  extern constexpr A a(1, 2.0, 3);
+
+  // CHECK: @_ZN11StructUnion1bE = global {{.*}} { i32 4, double 5.000000e+00, {{.*}} { i8* getelementptr inbounds ([6 x i8]* @{{.*}}, i32 0, i32 0) } }
+  extern constexpr A b(4, 5, "hello");
+
+  struct B {
+    int n;
+  };
+
+  // CHECK: @_ZN11StructUnion1cE = global {{.*}} zeroinitializer
+  // CHECK: @_ZN11StructUnion2c2E = global {{.*}} zeroinitializer
+  B c;
+  B c2 = B();
+
+  // CHECK: @_ZN11StructUnion1dE = global {{.*}} zeroinitializer
+  B d[10];
+
+  struct C {
+    constexpr C() : c(0) {}
+    int c;
+  };
+
+  // CHECK: @_ZN11StructUnion1eE = global {{.*}} zeroinitializer
+  C e[10];
+
+  struct D {
+    constexpr D() : d(5) {}
+    int d;
+  };
+
+  // CHECK: @_ZN11StructUnion1fE = global {{.*}} { i32 5 }
+  D f;
+}
+
+namespace BaseClass {
+  template<typename T, unsigned> struct X : T {};
+  struct C { char c = 1; };
+  template<unsigned... Ns> struct Cs : X<C,Ns>... {};
+  struct N { int n = 3; };
+  struct D { double d = 4.0; };
+
+  template<typename ...Ts>
+  struct Test : Ts... { constexpr Test() : Ts()..., n(5) {} int n; };
+
+  using Test1 = Test<N, C, Cs<1,2>, D, X<C,1>>;
+  // CHECK: @_ZN9BaseClass2t1E = global {{.*}} { i32 3, i8 1, i8 1, i8 1, double 4.000000e+00, i8 1, i32 5 }, align 8
+  extern constexpr Test1 t1 = Test1();
+
+  struct DN : D, N {};
+  struct DND : DN, X<D,0> {};
+  struct DNN : DN, X<N,0> {};
+  // CHECK: @_ZN9BaseClass3dndE = global {{.*}} { double 4.000000e+00, i32 3, double 4.000000e+00 }
+  extern constexpr DND dnd = DND();
+  // Note, N subobject is laid out in DN subobject's tail padding.
+  // CHECK: @_ZN9BaseClass3dnnE = global {{.*}} { double 4.000000e+00, i32 3, i32 3 }
+  extern constexpr DNN dnn = DNN();
+
+  struct E {};
+  struct Test2 : X<E,0>, X<E,1>, X<E,2>, X<E,3> {};
+  // CHECK: @_ZN9BaseClass2t2E = global {{.*}} { [4 x i8] undef }
+  extern constexpr Test2 t2 = Test2();
+}
+
+namespace Array {
+  // CHECK: @_ZN5Array3arrE = constant [2 x i32] [i32 4, i32 0]
+  extern constexpr int arr[2] = { 4 };
+
+  // CHECK: @_ZN5Array1cE = constant [6 x [4 x i8]] [{{.*}} c"foo\00", [4 x i8] c"a\00\00\00", [4 x i8] c"bar\00", [4 x i8] c"xyz\00", [4 x i8] c"b\00\00\00", [4 x i8] c"123\00"]
+  extern constexpr char c[6][4] = { "foo", "a", { "bar" }, { 'x', 'y', 'z' }, { "b" }, '1', '2', '3' };
+
+  struct C { constexpr C() : n(5) {} int n, m = 3 * n + 1; };
+  // CHECK: @_ZN5Array5ctorsE = global [3 x {{.*}}] [{{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }]
+  extern const C ctors[3];
+  constexpr C ctors[3];
+
+  // CHECK: @_ZN5Array1dE = constant {{.*}} { [2 x i32] [i32 1, i32 2], [3 x i32] [i32 3, i32 4, i32 5] }
+  struct D { int n[2]; int m[3]; } extern constexpr d = { 1, 2, 3, 4, 5 };
+}
+
+namespace MemberPtr {
+  struct B1 {
+    int a, b;
+    virtual void f();
+    void g();
+  };
+  struct B2 {
+    int c, d;
+    virtual void h();
+    void i();
+  };
+  struct C : B1 {
+    int e;
+    virtual void j();
+    void k();
+  };
+  struct D : C, B2 {
+    int z;
+    virtual void l();
+    void m();
+  };
+
+  // CHECK: @_ZN9MemberPtr2daE = constant i64 8
+  // CHECK: @_ZN9MemberPtr2dbE = constant i64 12
+  // CHECK: @_ZN9MemberPtr2dcE = constant i64 32
+  // CHECK: @_ZN9MemberPtr2ddE = constant i64 36
+  // CHECK: @_ZN9MemberPtr2deE = constant i64 16
+  // CHECK: @_ZN9MemberPtr2dzE = constant i64 40
+  extern constexpr int (D::*da) = &B1::a;
+  extern constexpr int (D::*db) = &C::b;
+  extern constexpr int (D::*dc) = &B2::c;
+  extern constexpr int (D::*dd) = &D::d;
+  extern constexpr int (D::*de) = &C::e;
+  extern constexpr int (D::*dz) = &D::z;
+
+  // CHECK: @_ZN9MemberPtr2baE = constant i64 8
+  // CHECK: @_ZN9MemberPtr2bbE = constant i64 12
+  // CHECK: @_ZN9MemberPtr2bcE = constant i64 8
+  // CHECK: @_ZN9MemberPtr2bdE = constant i64 12
+  // CHECK: @_ZN9MemberPtr2beE = constant i64 16
+  // CHECK: @_ZN9MemberPtr3b1zE = constant i64 40
+  // CHECK: @_ZN9MemberPtr3b2zE = constant i64 16
+  extern constexpr int (B1::*ba) = (int(B1::*))&B1::a;
+  extern constexpr int (B1::*bb) = (int(B1::*))&C::b;
+  extern constexpr int (B2::*bc) = (int(B2::*))&B2::c;
+  extern constexpr int (B2::*bd) = (int(B2::*))&D::d;
+  extern constexpr int (B1::*be) = (int(B1::*))&C::e;
+  extern constexpr int (B1::*b1z) = (int(B1::*))&D::z;
+  extern constexpr int (B2::*b2z) = (int(B2::*))&D::z;
+
+  // CHECK: @_ZN9MemberPtr2dfE = constant {{.*}} { i64 1, i64 0 }
+  // CHECK: @_ZN9MemberPtr2dgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr2dhE = constant {{.*}} { i64 1, i64 24 }
+  // CHECK: @_ZN9MemberPtr2diE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 24 }
+  // CHECK: @_ZN9MemberPtr2djE = constant {{.*}} { i64 9, i64 0 }
+  // CHECK: @_ZN9MemberPtr2dkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr2dlE = constant {{.*}} { i64 17, i64 0 }
+  // CHECK: @_ZN9MemberPtr2dmE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+  extern constexpr void (D::*df)() = &C::f;
+  extern constexpr void (D::*dg)() = &B1::g;
+  extern constexpr void (D::*dh)() = &B2::h;
+  extern constexpr void (D::*di)() = &D::i;
+  extern constexpr void (D::*dj)() = &C::j;
+  extern constexpr void (D::*dk)() = &C::k;
+  extern constexpr void (D::*dl)() = &D::l;
+  extern constexpr void (D::*dm)() = &D::m;
+
+  // CHECK: @_ZN9MemberPtr2bfE = constant {{.*}} { i64 1, i64 0 }
+  // CHECK: @_ZN9MemberPtr2bgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr2bhE = constant {{.*}} { i64 1, i64 0 }
+  // CHECK: @_ZN9MemberPtr2biE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr2bjE = constant {{.*}} { i64 9, i64 0 }
+  // CHECK: @_ZN9MemberPtr2bkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr3b1lE = constant {{.*}} { i64 17, i64 0 }
+  // CHECK: @_ZN9MemberPtr3b1mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+  // CHECK: @_ZN9MemberPtr3b2lE = constant {{.*}} { i64 17, i64 -24 }
+  // CHECK: @_ZN9MemberPtr3b2mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 -24 }
+  extern constexpr void (B1::*bf)()  = (void(B1::*)())&C::f;
+  extern constexpr void (B1::*bg)()  = (void(B1::*)())&B1::g;
+  extern constexpr void (B2::*bh)()  = (void(B2::*)())&B2::h;
+  extern constexpr void (B2::*bi)()  = (void(B2::*)())&D::i;
+  extern constexpr void (B1::*bj)()  = (void(B1::*)())&C::j;
+  extern constexpr void (B1::*bk)()  = (void(B1::*)())&C::k;
+  extern constexpr void (B1::*b1l)() = (void(B1::*)())&D::l;
+  extern constexpr void (B1::*b1m)() = (void(B1::*)())&D::m;
+  extern constexpr void (B2::*b2l)() = (void(B2::*)())&D::l;
+  extern constexpr void (B2::*b2m)() = (void(B2::*)())&D::m;
+}
+
+// Constant initialization tests go before this point,
+// dynamic initialization tests go after.
+
 namespace CrossFuncLabelDiff {
   // Make sure we refuse to constant-fold the variable b.
   constexpr long a() { return (long)&&lbl + (0 && ({lbl: 0;})); }

Modified: cfe/trunk/test/CodeGenCXX/pr9965.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr9965.cpp?rev=148178&r1=148177&r2=148178&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pr9965.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pr9965.cpp Fri Jan 13 22:30:29 2012
@@ -3,6 +3,7 @@
 struct X
 {
     X() = default;
+    ~X() {} // not a literal type
 };
 
 X<int> x;





More information about the cfe-commits mailing list