[cfe-commits] r133827 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CGObjC.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/vla.c test/CodeGenCXX/vla.cpp test/CodeGenObjC/arc.m

John McCall rjmccall at apple.com
Fri Jun 24 14:55:11 PDT 2011


Author: rjmccall
Date: Fri Jun 24 16:55:10 2011
New Revision: 133827

URL: http://llvm.org/viewvc/llvm-project?rev=133827&view=rev
Log:
Change the IR-generation of VLAs so that we capture bounds,
not sizes;  so that we use well-typed allocas;  and so that we
properly recurse through the full set of variably-modified types.


Added:
    cfe/trunk/test/CodeGenCXX/vla.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/test/CodeGen/vla.c
    cfe/trunk/test/CodeGenObjC/arc.m

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Jun 24 16:55:10 2011
@@ -98,7 +98,7 @@
     QualType Ty = TD.getUnderlyingType();
 
     if (Ty->isVariablyModifiedType())
-      EmitVLASize(Ty);
+      EmitVariablyModifiedType(Ty);
   }
   }
 }
@@ -258,7 +258,7 @@
   // even though that doesn't really make any sense.
   // Make sure to evaluate VLA bounds now so that we have them for later.
   if (D.getType()->isVariablyModifiedType())
-    EmitVLASize(D.getType());
+    EmitVariablyModifiedType(D.getType());
   
   // Local static block variables must be treated as globals as they may be
   // referenced in their RHS initializer block-literal expresion.
@@ -699,6 +699,10 @@
   CharUnits alignment = getContext().getDeclAlign(&D);
   emission.Alignment = alignment;
 
+  // If the type is variably-modified, emit all the VLA sizes for it.
+  if (Ty->isVariablyModifiedType())
+    EmitVariablyModifiedType(Ty);
+
   llvm::Value *DeclPtr;
   if (Ty->isConstantSizeType()) {
     if (!Target.useGlobalsForAutomaticVariables()) {
@@ -778,10 +782,6 @@
       DeclPtr = CreateStaticVarDecl(D, Class,
                                     llvm::GlobalValue::InternalLinkage);
     }
-
-    // FIXME: Can this happen?
-    if (Ty->isVariablyModifiedType())
-      EmitVLASize(Ty);
   } else {
     EnsureInsertPoint();
 
@@ -801,19 +801,17 @@
       EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack);
     }
 
-    // Get the element type.
-    const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
-    const llvm::Type *LElemPtrTy =
-      LElemTy->getPointerTo(CGM.getContext().getTargetAddressSpace(Ty));
+    llvm::Value *elementCount;
+    QualType elementType;
+    llvm::tie(elementCount, elementType) = getVLASize(Ty);
 
-    llvm::Value *VLASize = EmitVLASize(Ty);
+    const llvm::Type *llvmTy = ConvertTypeForMem(elementType);
 
     // Allocate memory for the array.
-    llvm::AllocaInst *VLA = 
-      Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
-    VLA->setAlignment(alignment.getQuantity());
+    llvm::AllocaInst *vla = Builder.CreateAlloca(llvmTy, elementCount, "vla");
+    vla->setAlignment(alignment.getQuantity());
 
-    DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
+    DeclPtr = vla;
   }
 
   llvm::Value *&DMEntry = LocalDeclMap[&D];

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Jun 24 16:55:10 2011
@@ -1579,21 +1579,22 @@
   // size is a VLA or Objective-C interface.
   llvm::Value *Address = 0;
   unsigned ArrayAlignment = 0;
-  if (const VariableArrayType *VAT =
+  if (const VariableArrayType *vla =
         getContext().getAsVariableArrayType(E->getType())) {
-    llvm::Value *VLASize = GetVLASize(VAT);
+    // The base must be a pointer, which is not an aggregate.  Emit
+    // it.  It needs to be emitted first in case it's what captures
+    // the VLA bounds.
+    Address = EmitScalarExpr(E->getBase());
 
-    Idx = Builder.CreateMul(Idx, VLASize);
+    // The element count here is the total number of non-VLA elements.
+    llvm::Value *numElements = getVLASize(vla).first;
 
-    // The base must be a pointer, which is not an aggregate.  Emit it.
-    llvm::Value *Base = EmitScalarExpr(E->getBase());
+    Idx = Builder.CreateMul(Idx, numElements);
 
-    Address = EmitCastToVoidPtr(Base);
     if (getContext().getLangOptions().isSignedOverflowDefined())
       Address = Builder.CreateGEP(Address, Idx, "arrayidx");
     else
       Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx");
-    Address = Builder.CreateBitCast(Address, Base->getType());
   } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
     // Indexing over an interface, as in "NSString *P; P[4];"
     llvm::Value *InterfaceSize =

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Fri Jun 24 16:55:10 2011
@@ -269,14 +269,12 @@
   Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
     return CGF.CGM.EmitNullConstant(E->getType());
   }
-  Value *VisitCastExpr(CastExpr *E) {
-    // Make sure to evaluate VLA bounds now so that we have them for later.
+  Value *VisitExplicitCastExpr(ExplicitCastExpr *E) {
     if (E->getType()->isVariablyModifiedType())
-      CGF.EmitVLASize(E->getType());
-
-    return EmitCastExpr(E);
+      CGF.EmitVariablyModifiedType(E->getType());
+    return VisitCastExpr(E);
   }
-  Value *EmitCastExpr(CastExpr *E);
+  Value *VisitCastExpr(CastExpr *E);
 
   Value *VisitCallExpr(const CallExpr *E) {
     if (E->getCallReturnType()->isReferenceType())
@@ -1001,7 +999,7 @@
 // VisitCastExpr - Emit code for an explicit or implicit cast.  Implicit casts
 // have to handle a more broad range of conversions than explicit casts, as they
 // handle things like function to ptr-to-function decay etc.
-Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
+Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
   Expr *E = CE->getSubExpr();
   QualType DestTy = CE->getType();
   CastKind Kind = CE->getCastKind();
@@ -1298,15 +1296,12 @@
 
     // VLA types don't have constant size.
     if (type->isVariableArrayType()) {
-      llvm::Value *vlaSize =
-        CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type));
-      value = CGF.EmitCastToVoidPtr(value);
-      if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize");
+      llvm::Value *numElts = CGF.getVLASize(type).first;
+      if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
       if (CGF.getContext().getLangOptions().isSignedOverflowDefined())
-        value = Builder.CreateGEP(value, vlaSize, "vla.inc");
+        value = Builder.CreateGEP(value, numElts, "vla.inc");
       else
-        value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc");
-      value = Builder.CreateBitCast(value, input->getType());
+        value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc");
     
     // Arithmetic on function pointers (!) is just +-1.
     } else if (type->isFunctionType()) {
@@ -1526,14 +1521,25 @@
           CGF.getContext().getAsVariableArrayType(TypeToSize)) {
       if (E->isArgumentType()) {
         // sizeof(type) - make sure to emit the VLA size.
-        CGF.EmitVLASize(TypeToSize);
+        CGF.EmitVariablyModifiedType(TypeToSize);
       } else {
         // C99 6.5.3.4p2: If the argument is an expression of type
         // VLA, it is evaluated.
         CGF.EmitIgnoredExpr(E->getArgumentExpr());
       }
 
-      return CGF.GetVLASize(VAT);
+      QualType eltType;
+      llvm::Value *numElts;
+      llvm::tie(numElts, eltType) = CGF.getVLASize(VAT);
+
+      llvm::Value *size = numElts;
+
+      // Scale the number of non-VLA elements by the non-VLA element size.
+      CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType);
+      if (!eltSize.isOne())
+        size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), numElts);
+
+      return size;
     }
   }
 

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Jun 24 16:55:10 2011
@@ -1894,9 +1894,10 @@
 
       // If it's a VLA, we have to load the stored size.  Note that
       // this is the size of the VLA in bytes, not its size in elements.
-      llvm::Value *vlaSizeInBytes = 0;
+      llvm::Value *numVLAElements = 0;
       if (isa<VariableArrayType>(arrayType)) {
-        vlaSizeInBytes = CGF.GetVLASize(cast<VariableArrayType>(arrayType));
+        numVLAElements =
+          CGF.getVLASize(cast<VariableArrayType>(arrayType)).first;
 
         // Walk into all VLAs.  This doesn't require changes to addr,
         // which has type T* where T is the first non-VLA element type.
@@ -1907,7 +1908,7 @@
           // If we only have VLA components, 'addr' requires no adjustment.
           if (!arrayType) {
             baseType = elementType;
-            return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
+            return numVLAElements;
           }
         } while (isa<VariableArrayType>(arrayType));
 
@@ -1947,22 +1948,20 @@
         assert(arrayType && "LLVM and Clang types are out-of-synch");
       }
 
+      baseType = arrayType->getElementType();
+
       // Create the actual GEP.
       addr = CGF.Builder.CreateInBoundsGEP(addr, gepIndices.begin(),
                                            gepIndices.end(), "array.begin");
 
-      baseType = arrayType->getElementType();
+      llvm::Value *numElements
+        = llvm::ConstantInt::get(CGF.IntPtrTy, countFromCLAs);
 
-      // If we had an VLA dimensions, we need to use the captured size.
-      if (vlaSizeInBytes)
-        return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
-
-      // Otherwise, use countFromCLAs.
-      assert(countFromCLAs == (uint64_t)
-               (Ctx.getTypeSizeInChars(origArrayType).getQuantity() /
-                Ctx.getTypeSizeInChars(baseType).getQuantity()));
+      // If we had any VLA dimensions, factor them in.
+      if (numVLAElements)
+        numElements = CGF.Builder.CreateNUWMul(numVLAElements, numElements);
 
-      return llvm::ConstantInt::get(CGF.IntPtrTy, countFromCLAs);
+      return numElements;
     }
 
     static llvm::Value *divideVLASizeByBaseType(CodeGenFunction &CGF,

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Jun 24 16:55:10 2011
@@ -343,7 +343,7 @@
     QualType Ty = (*i)->getType();
 
     if (Ty->isVariablyModifiedType())
-      EmitVLASize(Ty);
+      EmitVariablyModifiedType(Ty);
   }
 }
 
@@ -709,13 +709,20 @@
     if (const VariableArrayType *vlaType =
           dyn_cast_or_null<VariableArrayType>(
                                           getContext().getAsArrayType(Ty))) {
-      SizeVal = GetVLASize(vlaType);
+      QualType eltType;
+      llvm::Value *numElts;
+      llvm::tie(numElts, eltType) = getVLASize(vlaType);
+
+      SizeVal = numElts;
+      CharUnits eltSize = getContext().getTypeSizeInChars(eltType);
+      if (!eltSize.isOne())
+        SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize));
       vla = vlaType;
     } else {
       return;
     }
   } else {
-    SizeVal = llvm::ConstantInt::get(IntPtrTy, Size.getQuantity());
+    SizeVal = CGM.getSize(Size);
     vla = 0;
   }
 
@@ -778,60 +785,120 @@
   return IndirectBranch->getParent();
 }
 
-llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
-  llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
+std::pair<llvm::Value*, QualType>
+CodeGenFunction::getVLASize(QualType type) {
+  const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
+  assert(vla && "type was not a variable array type!");
+  return getVLASize(vla);
+}
+
+std::pair<llvm::Value*, QualType>
+CodeGenFunction::getVLASize(const VariableArrayType *type) {
+  // The number of elements so far; always size_t.
+  llvm::Value *numElements = 0;
+
+  QualType elementType;
+  do {
+    elementType = type->getElementType();
+    llvm::Value *vlaSize = VLASizeMap[type->getSizeExpr()];
+    assert(vlaSize && "no size for VLA!");
+    assert(vlaSize->getType() == SizeTy);
 
-  assert(SizeEntry && "Did not emit size for type");
-  return SizeEntry;
+    if (!numElements) {
+      numElements = vlaSize;
+    } else {
+      // It's undefined behavior if this wraps around, so mark it that way.
+      numElements = Builder.CreateNUWMul(numElements, vlaSize);
+    }
+  } while ((type = getContext().getAsVariableArrayType(elementType)));
+
+  return std::pair<llvm::Value*,QualType>(numElements, elementType);
 }
 
-llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) {
-  assert(Ty->isVariablyModifiedType() &&
+void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
+  assert(type->isVariablyModifiedType() &&
          "Must pass variably modified type to EmitVLASizes!");
 
   EnsureInsertPoint();
 
-  if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
-    // unknown size indication requires no size computation.
-    if (!VAT->getSizeExpr())
-      return 0;
-    llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
-
-    if (!SizeEntry) {
-      const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
-
-      // Get the element size;
-      QualType ElemTy = VAT->getElementType();
-      llvm::Value *ElemSize;
-      if (ElemTy->isVariableArrayType())
-        ElemSize = EmitVLASize(ElemTy);
-      else
-        ElemSize = llvm::ConstantInt::get(SizeTy,
-            getContext().getTypeSizeInChars(ElemTy).getQuantity());
-
-      llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr());
-      NumElements = Builder.CreateIntCast(NumElements, SizeTy, false, "tmp");
-
-      SizeEntry = Builder.CreateMul(ElemSize, NumElements);
+  // We're going to walk down into the type and look for VLA
+  // expressions.
+  type = type.getCanonicalType();
+  do {
+    assert(type->isVariablyModifiedType());
+
+    const Type *ty = type.getTypePtr();
+    switch (ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+      llvm_unreachable("unexpected dependent or non-canonical type!");
+
+    // These types are never variably-modified.
+    case Type::Builtin:
+    case Type::Complex:
+    case Type::Vector:
+    case Type::ExtVector:
+    case Type::Record:
+    case Type::Enum:
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+    case Type::ObjCObjectPointer:
+      llvm_unreachable("type class is never variably-modified!");
+
+    case Type::Pointer:
+      type = cast<PointerType>(ty)->getPointeeType();
+      break;
+
+    case Type::BlockPointer:
+      type = cast<BlockPointerType>(ty)->getPointeeType();
+      break;
+
+    case Type::LValueReference:
+    case Type::RValueReference:
+      type = cast<ReferenceType>(ty)->getPointeeType();
+      break;
+
+    case Type::MemberPointer:
+      type = cast<MemberPointerType>(ty)->getPointeeType();
+      break;
+
+    case Type::ConstantArray:
+    case Type::IncompleteArray:
+      // Losing element qualification here is fine.
+      type = cast<ArrayType>(ty)->getElementType();
+      break;
+
+    case Type::VariableArray: {
+      // Losing element qualification here is fine.
+      const VariableArrayType *vat = cast<VariableArrayType>(ty);
+
+      // Unknown size indication requires no size computation.
+      // Otherwise, evaluate and record it.
+      if (const Expr *size = vat->getSizeExpr()) {
+        // It's possible that we might have emitted this already,
+        // e.g. with a typedef and a pointer to it.
+        llvm::Value *&entry = VLASizeMap[size];
+        if (!entry) {
+          // Always zexting here would be wrong if it weren't
+          // undefined behavior to have a negative bound.
+          entry = Builder.CreateIntCast(EmitScalarExpr(size), SizeTy,
+                                        /*signed*/ false);
+        }
+      }
+      type = vat->getElementType();
+      break;
     }
 
-    return SizeEntry;
-  }
-
-  if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
-    EmitVLASize(AT->getElementType());
-    return 0;
-  }
-
-  if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
-    EmitVLASize(PT->getInnerType());
-    return 0;
-  }
-
-  const PointerType *PT = Ty->getAs<PointerType>();
-  assert(PT && "unknown VM type!");
-  EmitVLASize(PT->getPointeeType());
-  return 0;
+    case Type::FunctionProto: 
+    case Type::FunctionNoProto:
+      type = cast<FunctionType>(ty)->getResultType();
+      break;
+    }
+  } while (type->isVariablyModifiedType());
 }
 
 llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Jun 24 16:55:10 2011
@@ -1526,16 +1526,18 @@
   // instruction in LLVM instead once it works well enough.
   llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
 
-  /// EmitVLASize - Generate code for any VLA size expressions that might occur
-  /// in a variably modified type. If Ty is a VLA, will return the value that
-  /// corresponds to the size in bytes of the VLA type. Will return 0 otherwise.
+  /// EmitVLASize - Capture all the sizes for the VLA expressions in
+  /// the given variably-modified type and store them in the VLASizeMap.
   ///
   /// This function can be called with a null (unreachable) insert point.
-  llvm::Value *EmitVLASize(QualType Ty);
+  void EmitVariablyModifiedType(QualType Ty);
 
-  // GetVLASize - Returns an LLVM value that corresponds to the size in bytes
-  // of a variable length array type.
-  llvm::Value *GetVLASize(const VariableArrayType *);
+  /// getVLASize - Returns an LLVM value that corresponds to the size,
+  /// in non-variably-sized elements, of a variable length array type,
+  /// plus that largest non-variably-sized element type.  Assumes that
+  /// the type has already been emitted with EmitVariablyModifiedType.
+  std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla);
+  std::pair<llvm::Value*,QualType> getVLASize(QualType vla);
 
   /// LoadCXXThis - Load the value of 'this'. This function is only valid while
   /// generating code for an C++ member function.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Jun 24 16:55:10 2011
@@ -196,6 +196,10 @@
   getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
 }
 
+llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
+  return llvm::ConstantInt::get(SizeTy, size.getQuantity());
+}
+
 void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
                                         const NamedDecl *D) const {
   // Internal definitions always have default visibility.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Jun 24 16:55:10 2011
@@ -33,6 +33,7 @@
 namespace llvm {
   class Module;
   class Constant;
+  class ConstantInt;
   class Function;
   class GlobalValue;
   class TargetData;
@@ -382,6 +383,9 @@
   static void DecorateInstruction(llvm::Instruction *Inst,
                                   llvm::MDNode *TBAAInfo);
 
+  /// getSize - Emit the given number of characters as a value of type size_t.
+  llvm::ConstantInt *getSize(CharUnits numChars);
+
   /// setGlobalVisibility - Set the visibility for the given LLVM
   /// GlobalValue.
   void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;

Modified: cfe/trunk/test/CodeGen/vla.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/vla.c?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/vla.c (original)
+++ cfe/trunk/test/CodeGen/vla.c Fri Jun 24 16:55:10 2011
@@ -88,13 +88,17 @@
 // http://llvm.org/PR8567
 // CHECK: define double @test_PR8567
 double test_PR8567(int n, double (*p)[n][5]) {
-  // CHECK: store [[vla_type:.*]] %p,
-  // CHECK: load i32*
-  // CHECK-NEXT: mul i32 40
-  // CHECK-NEXT: [[byte_idx:%.*]] = mul i32 1
-  // CHECK-NEXT: [[tmp_1:%.*]] = load [[vla_type]]*
-  // CHECK-NEXT: [[tmp_2:%.*]] = bitcast [[vla_type]] [[tmp_1]] to i8*
-  // CHECK-NEXT: [[idx:%.*]] = getelementptr inbounds i8* [[tmp_2]], i32 [[byte_idx]]
-  // CHECK-NEXT: bitcast i8* [[idx]] to [[vla_type]]
+  // CHECK:      [[NV:%.*]] = alloca i32, align 4
+  // CHECK-NEXT: [[PV:%.*]] = alloca [5 x double]*, align 4
+  // CHECK-NEXT: store
+  // CHECK-NEXT: store
+  // CHECK-NEXT: [[N:%.*]] = load i32* [[NV]], align 4
+  // CHECK-NEXT: [[P:%.*]] = load [5 x double]** [[PV]], align 4
+  // CHECK-NEXT: [[T0:%.*]] = mul i32 1, [[N]]
+  // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [5 x double]* [[P]], i32 [[T0]]
+  // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [5 x double]* [[T1]], i32 2
+  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [5 x double]* [[T2]], i32 0, i32 3
+  // CHECK-NEXT: [[T4:%.*]] = load double* [[T3]]
+  // CHECK-NEXT: ret double [[T4]]
  return p[1][2][3];
 }

Added: cfe/trunk/test/CodeGenCXX/vla.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vla.cpp?rev=133827&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vla.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/vla.cpp Fri Jun 24 16:55:10 2011
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s
+
+// rdar://problem/9506377
+void test0(void *array, int n) {
+  // CHECK: define void @_Z5test0Pvi(
+  // CHECK:      [[ARRAY:%.*]] = alloca i8*, align 8
+  // CHECK-NEXT: [[N:%.*]] = alloca i32, align 4
+  // CHECK-NEXT: [[REF:%.*]] = alloca i16*, align 8
+  // CHECK-NEXT: [[S:%.*]] = alloca i16, align 2
+  // CHECK-NEXT: store i8* 
+  // CHECK-NEXT: store i32
+
+  // Capture the bounds.
+  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+  // CHECK-NEXT: [[DIM0:%.*]] = zext i32 [[T0]] to i64
+  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+  // CHECK-NEXT: [[T1:%.*]] = add nsw i32 [[T0]], 1
+  // CHECK-NEXT: [[DIM1:%.*]] = zext i32 [[T1]] to i64
+  typedef short array_t[n][n+1];
+
+  // CHECK-NEXT: [[T0:%.*]] = load i8** [[ARRAY]], align 8
+  // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i16*
+  // CHECK-NEXT: store i16* [[T1]], i16** [[REF]], align 8
+  array_t &ref = *(array_t*) array;
+
+  // CHECK-NEXT: [[T0:%.*]] = load i16** [[REF]]
+  // CHECK-NEXT: [[T1:%.*]] = mul i64 1, [[DIM1]]
+  // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i16* [[T0]], i64 [[T1]]
+  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i16* [[T2]], i64 2
+  // CHECK-NEXT: store i16 3, i16* [[T3]]
+  ref[1][2] = 3;
+
+  // CHECK-NEXT: [[T0:%.*]] = load i16** [[REF]]
+  // CHECK-NEXT: [[T1:%.*]] = mul i64 4, [[DIM1]]
+  // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i16* [[T0]], i64 [[T1]]
+  // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i16* [[T2]], i64 5
+  // CHECK-NEXT: [[T4:%.*]] = load i16* [[T3]]
+  // CHECK-NEXT: store i16 [[T4]], i16* [[S]], align 2
+  short s = ref[4][5];
+
+  // CHECK-NEXT: ret void
+}
+

Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=133827&r1=133826&r2=133827&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Fri Jun 24 16:55:10 2011
@@ -487,23 +487,23 @@
   id x[n];
 
   // Capture the VLA size.
+  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
+
+  // Save the stack pointer.
   // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave()
   // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]]
-  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
-  // CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
-  // CHECK-NEXT: [[VLA_SIZE:%.*]] = mul i64 8, [[T1]]
 
   // Allocate the VLA.
-  // CHECK-NEXT: [[T0:%.*]] = alloca i8, i64 [[VLA_SIZE]], align 16
-  // CHECK-NEXT: [[VLA:%.*]] = bitcast i8* [[T0]] to i8**
+  // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16
 
   // Zero-initialize.
   // CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8*
-  // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[VLA_SIZE]], i32 8, i1 false)
+  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8
+  // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T1]], i32 8, i1 false)
 
   // Destroy.
-  // CHECK-NEXT: [[VLA_COUNT:%.*]] = udiv i64 [[VLA_SIZE]], 8
-  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[VLA]], i64 [[VLA_COUNT]]
+  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[VLA]], i64 [[DIM]]
   // CHECK-NEXT: br label
 
   // CHECK:      [[CUR:%.*]] = phi i8**
@@ -529,25 +529,28 @@
   id x[2][n][3];
 
   // Capture the VLA size.
+  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
+  // CHECK-NEXT: [[DIM:%.*]] = zext i32 [[T0]] to i64
+
   // CHECK-NEXT: [[T0:%.*]] = call i8* @llvm.stacksave()
   // CHECK-NEXT: store i8* [[T0]], i8** [[SAVED_STACK]]
-  // CHECK-NEXT: [[T0:%.*]] = load i32* [[N]], align 4
-  // CHECK-NEXT: [[T1:%.*]] = zext i32 [[T0]] to i64
-  // CHECK-NEXT: [[T2:%.*]] = mul i64 24, [[T1]]
-  // CHECK-NEXT: [[VLA_SIZE:%.*]] = mul i64 [[T2]], 2
+
 
   // Allocate the VLA.
-  // CHECK-NEXT: [[T0:%.*]] = alloca i8, i64 [[VLA_SIZE]], align 16
-  // CHECK-NEXT: [[VLA:%.*]] = bitcast i8* [[T0]] to [3 x i8*]*
+  // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
+  // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16
 
   // Zero-initialize.
   // CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8*
-  // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[VLA_SIZE]], i32 8, i1 false)
+  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]]
+  // CHECK-NEXT: [[T2:%.*]] = mul nuw i64 [[T1]], 24
+  // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 [[T2]], i32 8, i1 false)
 
   // Destroy.
+  // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]]
   // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [3 x i8*]* [[VLA]], i32 0, i32 0
-  // CHECK-NEXT: [[VLA_COUNT:%.*]] = udiv i64 [[VLA_SIZE]], 8
-  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[VLA_COUNT]]
+  // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[T0]], 3
+  // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[T1]]
   // CHECK-NEXT: br label
 
   // CHECK:      [[CUR:%.*]] = phi i8**





More information about the cfe-commits mailing list