//===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Constant Expr nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CGObjCRuntime.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;

namespace  {

class VISIBILITY_HIDDEN ConstStructBuilder {
  CodeGenModule &CGM;
  CodeGenFunction *CGF;

  bool Packed;

  unsigned NextFieldOffsetInBytes;

  unsigned LLVMStructAlignment;
  
  std::vector<llvm::Constant *> Elements;

  ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
    : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0),
    LLVMStructAlignment(1) { }

  bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
                   const Expr *InitExpr) {
    uint64_t FieldOffsetInBytes = FieldOffset / 8;

    assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
           && "Field offset mismatch!");

    // Emit the field.
    llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
    if (!C)
      return false;

    unsigned FieldAlignment = getAlignment(C);

    // Round up the field offset to the alignment of the field type.
    uint64_t AlignedNextFieldOffsetInBytes =
      llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);

    if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
      assert(!Packed && "Alignment is wrong even with a packed struct!");

      // Convert the struct to a packed struct.
      ConvertStructToPacked();
      
      AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
    }

    if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
      // We need to append padding.
      AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes);

      assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
             "Did not add enough padding!");

      AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
    }

    // Add the field.
    Elements.push_back(C);
    NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
    
    if (Packed)
      assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!");
    else
      LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment);

    return true;
  }

  bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
                      const Expr *InitExpr) {
    llvm::ConstantInt *CI =
      cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr,
                                                           Field->getType(),
                                                           CGF));
    // FIXME: Can this ever happen?
    if (!CI)
      return false;

    if (FieldOffset > NextFieldOffsetInBytes * 8) {
      // We need to add padding.
      uint64_t NumBytes =
        llvm::RoundUpToAlignment(FieldOffset -
                                 NextFieldOffsetInBytes * 8, 8) / 8;

      AppendPadding(NumBytes);
    }

    uint64_t FieldSize =
      Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue();

    llvm::APInt FieldValue = CI->getValue();

    // Promote the size of FieldValue if necessary
    // FIXME: This should never occur, but currently it can because initializer
    // constants are cast to bool, and because clang is not enforcing bitfield
    // width limits.
    if (FieldSize > FieldValue.getBitWidth())
      FieldValue.zext(FieldSize);

    // Truncate the size of FieldValue to the bit field size.
    if (FieldSize < FieldValue.getBitWidth())
      FieldValue.trunc(FieldSize);

    if (FieldOffset < NextFieldOffsetInBytes * 8) {
      // Either part of the field or the entire field can go into the previous
      // byte.
      assert(!Elements.empty() && "Elements can't be empty!");

      unsigned BitsInPreviousByte =
        NextFieldOffsetInBytes * 8 - FieldOffset;

      bool FitsCompletelyInPreviousByte =
        BitsInPreviousByte >= FieldValue.getBitWidth();

      llvm::APInt Tmp = FieldValue;

      if (!FitsCompletelyInPreviousByte) {
        unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;

        if (CGM.getTargetData().isBigEndian()) {
          Tmp = Tmp.lshr(NewFieldWidth);
          Tmp.trunc(BitsInPreviousByte);

          // We want the remaining high bits.
          FieldValue.trunc(NewFieldWidth);
        } else {
          Tmp.trunc(BitsInPreviousByte);

          // We want the remaining low bits.
          FieldValue = FieldValue.lshr(BitsInPreviousByte);
          FieldValue.trunc(NewFieldWidth);
        }
      }

      Tmp.zext(8);
      if (CGM.getTargetData().isBigEndian()) {
        if (FitsCompletelyInPreviousByte)
          Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth());
      } else {
        Tmp = Tmp.shl(8 - BitsInPreviousByte);
      }

      // Or in the bits that go into the previous byte.
      Tmp |= cast<llvm::ConstantInt>(Elements.back())->getValue();
      Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);

      if (FitsCompletelyInPreviousByte)
        return true;
    }

    while (FieldValue.getBitWidth() > 8) {
      llvm::APInt Tmp;

      if (CGM.getTargetData().isBigEndian()) {
        // We want the high bits.
        Tmp = FieldValue;
        Tmp = Tmp.lshr(Tmp.getBitWidth() - 8);
        Tmp.trunc(8);
      } else {
        // We want the low bits.
        Tmp = FieldValue;
        Tmp.trunc(8);

        FieldValue = FieldValue.lshr(8);
      }

      Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));
      NextFieldOffsetInBytes++;

      FieldValue.trunc(FieldValue.getBitWidth() - 8);
    }

    assert(FieldValue.getBitWidth() > 0 &&
           "Should have at least one bit left!");
    assert(FieldValue.getBitWidth() <= 8 &&
           "Should not have more than a byte left!");

    if (FieldValue.getBitWidth() < 8) {
      if (CGM.getTargetData().isBigEndian()) {
        unsigned BitWidth = FieldValue.getBitWidth();

        FieldValue.zext(8);
        FieldValue = FieldValue << (8 - BitWidth);
      } else
        FieldValue.zext(8);
    }

    // Append the last element.
    Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(),
                                              FieldValue));
    NextFieldOffsetInBytes++;
    return true;
  }

  void AppendPadding(uint64_t NumBytes) {
    if (!NumBytes)
      return;

    const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
    if (NumBytes > 1)
      Ty = llvm::ArrayType::get(Ty, NumBytes);

    llvm::Constant *C = llvm::UndefValue::get(Ty);
    Elements.push_back(C);
    assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");

    NextFieldOffsetInBytes += getSizeInBytes(C);
  }

  void AppendTailPadding(uint64_t RecordSize) {
    assert(RecordSize % 8 == 0 && "Invalid record size!");

    uint64_t RecordSizeInBytes = RecordSize / 8;
    assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");

    unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
    AppendPadding(NumPadBytes);
  }

  void ConvertStructToPacked() {
    std::vector<llvm::Constant *> PackedElements;
    uint64_t ElementOffsetInBytes = 0;

    for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
      llvm::Constant *C = Elements[i];

      unsigned ElementAlign =
        CGM.getTargetData().getABITypeAlignment(C->getType());
      uint64_t AlignedElementOffsetInBytes =
        llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign);

      if (AlignedElementOffsetInBytes > ElementOffsetInBytes) {
        // We need some padding.
        uint64_t NumBytes =
          AlignedElementOffsetInBytes - ElementOffsetInBytes;

        const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext());
        if (NumBytes > 1)
          Ty = llvm::ArrayType::get(Ty, NumBytes);

        llvm::Constant *Padding = llvm::UndefValue::get(Ty);
        PackedElements.push_back(Padding);
        ElementOffsetInBytes += getSizeInBytes(Padding);
      }

      PackedElements.push_back(C);
      ElementOffsetInBytes += getSizeInBytes(C);
    }

    assert(ElementOffsetInBytes == NextFieldOffsetInBytes &&
           "Packing the struct changed its size!");

    Elements = PackedElements;
    LLVMStructAlignment = 1;
    Packed = true;
  }
                              
  bool Build(InitListExpr *ILE) {
    RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl();
    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);

    unsigned FieldNo = 0;
    unsigned ElementNo = 0;
    for (RecordDecl::field_iterator Field = RD->field_begin(),
         FieldEnd = RD->field_end();
         ElementNo < ILE->getNumInits() && Field != FieldEnd;
         ++Field, ++FieldNo) {
      if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
        continue;

      if (Field->isBitField()) {
        if (!Field->getIdentifier())
          continue;

        if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
                            ILE->getInit(ElementNo)))
          return false;
      } else {
        if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
                         ILE->getInit(ElementNo)))
          return false;
      }

      ElementNo++;
    }

    uint64_t LayoutSizeInBytes = Layout.getSize() / 8;

    if (NextFieldOffsetInBytes > LayoutSizeInBytes) {
      // If the struct is bigger than the size of the record type,
      // 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;
    }

    uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes, 
                                                        LLVMStructAlignment);

    // Check if we need to convert the struct to a packed struct.
    if (NextFieldOffsetInBytes <= LayoutSizeInBytes && 
        LLVMSizeInBytes > LayoutSizeInBytes) {
      assert(!Packed && "Size mismatch!");
      
      ConvertStructToPacked();
      assert(NextFieldOffsetInBytes == LayoutSizeInBytes &&
             "Converting to packed did not help!");
    }

    // Append tail padding if necessary.
    AppendTailPadding(Layout.getSize());

    assert(Layout.getSize() / 8 == NextFieldOffsetInBytes &&
           "Tail padding mismatch!");

    return true;
  }

  unsigned getAlignment(const llvm::Constant *C) const {
    if (Packed)
      return 1;

    return CGM.getTargetData().getABITypeAlignment(C->getType());
  }

  uint64_t getSizeInBytes(const llvm::Constant *C) const {
    return CGM.getTargetData().getTypeAllocSize(C->getType());
  }

public:
  static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
                                     InitListExpr *ILE) {
    ConstStructBuilder Builder(CGM, CGF);

    if (!Builder.Build(ILE))
      return 0;

    llvm::Constant *Result =
      llvm::ConstantStruct::get(CGM.getLLVMContext(),
                                Builder.Elements, Builder.Packed);

    assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes,
                                    Builder.getAlignment(Result)) ==
           Builder.getSizeInBytes(Result) && "Size mismatch!");

    return Result;
  }
};

class VISIBILITY_HIDDEN ConstExprEmitter :
  public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
  CodeGenModule &CGM;
  CodeGenFunction *CGF;
  llvm::LLVMContext &VMContext;
public:
  ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf)
    : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) {
  }

  //===--------------------------------------------------------------------===//
  //                            Visitor Methods
  //===--------------------------------------------------------------------===//

  llvm::Constant *VisitStmt(Stmt *S) {
    return 0;
  }

  llvm::Constant *VisitParenExpr(ParenExpr *PE) {
    return Visit(PE->getSubExpr());
  }

  llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
    return Visit(E->getInitializer());
  }
    
  llvm::Constant *EmitMemberFunctionPointer(CXXMethodDecl *MD) {
    assert(MD->isInstance() && "Member function must not be static!");
    
    const llvm::Type *PtrDiffTy = 
      CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
    
    llvm::Constant *Values[2];
    
    // Get the function pointer (or index if this is a virtual function).
    if (MD->isVirtual()) {
      int64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD);
      
      Values[0] = llvm::ConstantInt::get(PtrDiffTy, Index + 1);
    } else {
      llvm::Constant *FuncPtr = CGM.GetAddrOfFunction(MD);

      Values[0] = llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
    } 
    
    // The adjustment will always be 0.
    Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0);
    
    return llvm::ConstantStruct::get(CGM.getLLVMContext(),
                                     Values, 2, /*Packed=*/false);
  }

  llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
    if (const MemberPointerType *MPT = 
        E->getType()->getAs<MemberPointerType>()) {
      QualType T = MPT->getPointeeType();
      if (T->isFunctionProtoType()) {
        DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
        
        return EmitMemberFunctionPointer(cast<CXXMethodDecl>(DRE->getDecl()));
      }
      
      // FIXME: Should we handle other member pointer types here too,
      // or should they be handled by Expr::Evaluate?
    }
    
    return 0;
  }
    
  llvm::Constant *VisitBinSub(BinaryOperator *E) {
    // This must be a pointer/pointer subtraction.  This only happens for
    // address of label.
    if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) ||
       !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext())))
      return 0;
    
    llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(),
                                               E->getLHS()->getType(), CGF);
    llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(),
                                               E->getRHS()->getType(), CGF);

    const llvm::Type *ResultType = ConvertType(E->getType());
    LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType);
    RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType);
        
    // No need to divide by element size, since addr of label is always void*,
    // which has size 1 in GNUish.
    return llvm::ConstantExpr::getSub(LHS, RHS);
  }
    
  llvm::Constant *VisitCastExpr(CastExpr* E) {
    switch (E->getCastKind()) {
    case CastExpr::CK_ToUnion: {
      // GCC cast to union extension
      assert(E->getType()->isUnionType() &&
             "Destination type is not union type!");
      const llvm::Type *Ty = ConvertType(E->getType());
      Expr *SubExpr = E->getSubExpr();

      llvm::Constant *C =
        CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
      if (!C)
        return 0;

      // Build a struct with the union sub-element as the first member,
      // and padded to the appropriate size
      std::vector<llvm::Constant*> Elts;
      std::vector<const llvm::Type*> Types;
      Elts.push_back(C);
      Types.push_back(C->getType());
      unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType());
      unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty);

      assert(CurSize <= TotalSize && "Union size mismatch!");
      if (unsigned NumPadBytes = TotalSize - CurSize) {
        const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
        if (NumPadBytes > 1)
          Ty = llvm::ArrayType::get(Ty, NumPadBytes);

        Elts.push_back(llvm::UndefValue::get(Ty));
        Types.push_back(Ty);
      }

      llvm::StructType* STy =
        llvm::StructType::get(C->getType()->getContext(), Types, false);
      return llvm::ConstantStruct::get(STy, Elts);
    }
    case CastExpr::CK_NullToMemberPointer:
      return CGM.EmitNullConstant(E->getType());
      
    case CastExpr::CK_BaseToDerivedMemberPointer: {
      Expr *SubExpr = E->getSubExpr();

      const MemberPointerType *SrcTy = 
        SubExpr->getType()->getAs<MemberPointerType>();
      const MemberPointerType *DestTy = 
        E->getType()->getAs<MemberPointerType>();
      
      const CXXRecordDecl *BaseClass =
        cast<CXXRecordDecl>(cast<RecordType>(SrcTy->getClass())->getDecl());
      const CXXRecordDecl *DerivedClass =
        cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl());

      if (SrcTy->getPointeeType()->isFunctionProtoType()) {
        llvm::Constant *C = 
          CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
        if (!C)
          return 0;
        
        llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
        
        // Check if we need to update the adjustment.
        if (llvm::Constant *Offset = CGM.GetCXXBaseClassOffset(DerivedClass,
                                                               BaseClass)) {
          llvm::Constant *Values[2];
        
          Values[0] = CS->getOperand(0);
          Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
          return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 
                                           /*Packed=*/false);
        }
        
        return CS;
      }          
    }

    case CastExpr::CK_BitCast: 
      // This must be a member function pointer cast.
      return Visit(E->getSubExpr());

    default: {
      // FIXME: This should be handled by the CK_NoOp cast kind.
      // Explicit and implicit no-op casts
      QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType();
      if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy))
        return Visit(E->getSubExpr());

      // Handle integer->integer casts for address-of-label differences.
      if (Ty->isIntegerType() && SubTy->isIntegerType() &&
          CGF) {
        llvm::Value *Src = Visit(E->getSubExpr());
        if (Src == 0) return 0;
        
        // Use EmitScalarConversion to perform the conversion.
        return cast<llvm::Constant>(CGF->EmitScalarConversion(Src, SubTy, Ty));
      }
      
      return 0;
    }
    }
  }

  llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
    return Visit(DAE->getExpr());
  }

  llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
    std::vector<llvm::Constant*> Elts;
    const llvm::ArrayType *AType =
        cast<llvm::ArrayType>(ConvertType(ILE->getType()));
    unsigned NumInitElements = ILE->getNumInits();
    // FIXME: Check for wide strings
    // FIXME: Check for NumInitElements exactly equal to 1??
    if (NumInitElements > 0 &&
        (isa<StringLiteral>(ILE->getInit(0)) ||
         isa<ObjCEncodeExpr>(ILE->getInit(0))) &&
        ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
      return Visit(ILE->getInit(0));
    const llvm::Type *ElemTy = AType->getElementType();
    unsigned NumElements = AType->getNumElements();

    // Initialising an array requires us to automatically
    // initialise any elements that have not been initialised explicitly
    unsigned NumInitableElts = std::min(NumInitElements, NumElements);

    // Copy initializer elements.
    unsigned i = 0;
    bool RewriteType = false;
    for (; i < NumInitableElts; ++i) {
      Expr *Init = ILE->getInit(i);
      llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
      if (!C)
        return 0;
      RewriteType |= (C->getType() != ElemTy);
      Elts.push_back(C);
    }

    // Initialize remaining array elements.
    // FIXME: This doesn't handle member pointers correctly!
    for (; i < NumElements; ++i)
      Elts.push_back(llvm::Constant::getNullValue(ElemTy));

    if (RewriteType) {
      // FIXME: Try to avoid packing the array
      std::vector<const llvm::Type*> Types;
      for (unsigned i = 0; i < Elts.size(); ++i)
        Types.push_back(Elts[i]->getType());
      const llvm::StructType *SType = llvm::StructType::get(AType->getContext(),
                                                            Types, true);
      return llvm::ConstantStruct::get(SType, Elts);
    }

    return llvm::ConstantArray::get(AType, Elts);
  }

  llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
    return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
  }

  llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) {
    return ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
  }

  llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) {
    const llvm::VectorType *VType =
        cast<llvm::VectorType>(ConvertType(ILE->getType()));
    const llvm::Type *ElemTy = VType->getElementType();
    std::vector<llvm::Constant*> Elts;
    unsigned NumElements = VType->getNumElements();
    unsigned NumInitElements = ILE->getNumInits();

    unsigned NumInitableElts = std::min(NumInitElements, NumElements);

    // Copy initializer elements.
    unsigned i = 0;
    for (; i < NumInitableElts; ++i) {
      Expr *Init = ILE->getInit(i);
      llvm::Constant *C = CGM.EmitConstantExpr(Init, Init->getType(), CGF);
      if (!C)
        return 0;
      Elts.push_back(C);
    }

    for (; i < NumElements; ++i)
      Elts.push_back(llvm::Constant::getNullValue(ElemTy));

    return llvm::ConstantVector::get(VType, Elts);
  }

  llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) {
    return CGM.EmitNullConstant(E->getType());
  }

  llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
    if (ILE->getType()->isScalarType()) {
      // We have a scalar in braces. Just use the first element.
      if (ILE->getNumInits() > 0) {
        Expr *Init = ILE->getInit(0);
        return CGM.EmitConstantExpr(Init, Init->getType(), CGF);
      }
      return CGM.EmitNullConstant(ILE->getType());
    }

    if (ILE->getType()->isArrayType())
      return EmitArrayInitialization(ILE);

    if (ILE->getType()->isStructureType())
      return EmitStructInitialization(ILE);

    if (ILE->getType()->isUnionType())
      return EmitUnionInitialization(ILE);

    if (ILE->getType()->isVectorType())
      return EmitVectorInitialization(ILE);

    assert(0 && "Unable to handle InitListExpr");
    // Get rid of control reaches end of void function warning.
    // Not reached.
    return 0;
  }

  llvm::Constant *VisitStringLiteral(StringLiteral *E) {
    assert(!E->getType()->isPointerType() && "Strings are always arrays");

    // This must be a string initializing an array in a static initializer.
    // Don't emit it as the address of the string, emit the string data itself
    // as an inline array.
    return llvm::ConstantArray::get(VMContext,
                                    CGM.GetStringForStringLiteral(E), false);
  }

  llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
    // This must be an @encode initializing an array in a static initializer.
    // Don't emit it as the address of the string, emit the string data itself
    // as an inline array.
    std::string Str;
    CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
    const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType());

    // Resize the string to the right size, adding zeros at the end, or
    // truncating as needed.
    Str.resize(CAT->getSize().getZExtValue(), '\0');
    return llvm::ConstantArray::get(VMContext, Str, false);
  }

  llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) {
    return Visit(E->getSubExpr());
  }

  // Utility methods
  const llvm::Type *ConvertType(QualType T) {
    return CGM.getTypes().ConvertType(T);
  }

public:
  llvm::Constant *EmitLValue(Expr *E) {
    switch (E->getStmtClass()) {
    default: break;
    case Expr::CompoundLiteralExprClass: {
      // Note that due to the nature of compound literals, this is guaranteed
      // to be the only use of the variable, so we just generate it here.
      CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
      llvm::Constant* C = Visit(CLE->getInitializer());
      // FIXME: "Leaked" on failure.
      if (C)
        C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
                                     E->getType().isConstant(CGM.getContext()),
                                     llvm::GlobalValue::InternalLinkage,
                                     C, ".compoundliteral", 0, false,
                                     E->getType().getAddressSpace());
      return C;
    }
    case Expr::DeclRefExprClass: {
      NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
        return CGM.GetAddrOfFunction(FD);
      if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
        // We can never refer to a variable with local storage.
        if (!VD->hasLocalStorage()) {
          if (VD->isFileVarDecl() || VD->hasExternalStorage())
            return CGM.GetAddrOfGlobalVar(VD);
          else if (VD->isBlockVarDecl()) {
            assert(CGF && "Can't access static local vars without CGF");
            return CGF->GetAddrOfStaticLocalVar(VD);
          }
        }
      }
      break;
    }
    case Expr::StringLiteralClass:
      return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
    case Expr::ObjCEncodeExprClass:
      return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
    case Expr::ObjCStringLiteralClass: {
      ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
      llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(SL);
      return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
    }
    case Expr::PredefinedExprClass: {
      unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
      if (CGF) {
        LValue Res = CGF->EmitPredefinedFunctionName(Type);
        return cast<llvm::Constant>(Res.getAddress());
      } else if (Type == PredefinedExpr::PrettyFunction) {
        return CGM.GetAddrOfConstantCString("top level", ".tmp");
      }

      return CGM.GetAddrOfConstantCString("", ".tmp");
    }
    case Expr::AddrLabelExprClass: {
      assert(CGF && "Invalid address of label expression outside function.");
      llvm::Constant *Ptr =
        CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
      return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
    }
    case Expr::CallExprClass: {
      CallExpr* CE = cast<CallExpr>(E);
      if (CE->isBuiltinCall(CGM.getContext()) !=
            Builtin::BI__builtin___CFStringMakeConstantString)
        break;
      const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
      const StringLiteral *Literal = cast<StringLiteral>(Arg);
      // FIXME: need to deal with UCN conversion issues.
      return CGM.GetAddrOfConstantCFString(Literal);
    }
    case Expr::BlockExprClass: {
      std::string FunctionName;
      if (CGF)
        FunctionName = CGF->CurFn->getName();
      else
        FunctionName = "global";

      return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
    }
    }

    return 0;
  }
};

}  // end anonymous namespace.

llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
                                                QualType DestType,
                                                CodeGenFunction *CGF) {
  Expr::EvalResult Result;

  bool Success = false;

  if (DestType->isReferenceType())
    Success = E->EvaluateAsLValue(Result, Context);
  else
    Success = E->Evaluate(Result, Context);

  if (Success && !Result.HasSideEffects) {
    switch (Result.Val.getKind()) {
    case APValue::Uninitialized:
      assert(0 && "Constant expressions should be initialized.");
      return 0;
    case APValue::LValue: {
      const llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
      llvm::Constant *Offset =
        llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
                               Result.Val.getLValueOffset());

      llvm::Constant *C;
      if (const Expr *LVBase = Result.Val.getLValueBase()) {
        C = ConstExprEmitter(*this, CGF).EmitLValue(const_cast<Expr*>(LVBase));

        // Apply offset if necessary.
        if (!Offset->isNullValue()) {
          const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
          llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type);
          Casted = llvm::ConstantExpr::getGetElementPtr(Casted, &Offset, 1);
          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::Int: {
      llvm::Constant *C = llvm::ConstantInt::get(VMContext,
                                                 Result.Val.getInt());

      if (C->getType() == llvm::Type::getInt1Ty(VMContext)) {
        const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
        C = llvm::ConstantExpr::getZExt(C, BoolTy);
      }
      return C;
    }
    case APValue::ComplexInt: {
      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.
      return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
    }
    case APValue::Float:
      return llvm::ConstantFP::get(VMContext, Result.Val.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.
      return llvm::ConstantStruct::get(VMContext, Complex, 2, false);
    }
    case APValue::Vector: {
      llvm::SmallVector<llvm::Constant *, 4> Inits;
      unsigned NumElts = Result.Val.getVectorLength();

      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[0], Inits.size());
    }
    }
  }

  llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
  if (C && C->getType() == llvm::Type::getInt1Ty(VMContext)) {
    const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
    C = llvm::ConstantExpr::getZExt(C, BoolTy);
  }
  return C;
}

static inline bool isDataMemberPointerType(QualType T) {
  if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
    return !MPT->getPointeeType()->isFunctionType();
  
  return false;
}

llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
  // No need to check for member pointers when not compiling C++.
  if (!getContext().getLangOptions().CPlusPlus)
    return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));

  if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {

    QualType ElementTy = CAT->getElementType();

    // FIXME: Handle arrays of structs that contain member pointers.
    if (isDataMemberPointerType(Context.getBaseElementType(ElementTy))) {
      llvm::Constant *Element = EmitNullConstant(ElementTy);
      uint64_t NumElements = CAT->getSize().getZExtValue();
      std::vector<llvm::Constant *> Array(NumElements);
      for (uint64_t i = 0; i != NumElements; ++i)
        Array[i] = Element;

      const llvm::ArrayType *ATy =
        cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));
      return llvm::ConstantArray::get(ATy, Array);
    }
  }

  if (const RecordType *RT = T->getAs<RecordType>()) {
    const RecordDecl *RD = RT->getDecl();
    // FIXME: It would be better if there was a way to explicitly compute the
    // record layout instead of converting to a type.
    Types.ConvertTagDeclType(RD);

    const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
    if (Layout.containsMemberPointer()) {
      assert(0 && "FIXME: No support for structs with member pointers yet!");
    }
  }

  // FIXME: Handle structs that contain member pointers.
  if (isDataMemberPointerType(T))
    return llvm::Constant::getAllOnesValue(getTypes().ConvertTypeForMem(T));

  return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
}
