r220850 - Improved capturing variable-length array types in CapturedStmt.

Alexey Bataev a.bataev at hotmail.com
Wed Oct 29 05:21:56 PDT 2014


Author: abataev
Date: Wed Oct 29 07:21:55 2014
New Revision: 220850

URL: http://llvm.org/viewvc/llvm-project?rev=220850&view=rev
Log:
Improved capturing variable-length array types in CapturedStmt.
An updated implemnentation of VLA types capturing based on previously committed solution for Lambdas.
This version captures the whole VLA type instead of particular variables which are part of VLA size expression and allows to use previusly calculated size of VLA type in captured regions. Required for OpenMP.
Differential Revision: http://reviews.llvm.org/D5099

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Sema/ScopeInfo.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/CodeGen/captured-statements-nested.c
    cfe/trunk/test/CodeGen/captured-statements.c

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Oct 29 07:21:55 2014
@@ -3218,6 +3218,13 @@ public:
   /// function object.
   bool isLambda() const;
 
+  /// \brief Determine whether this record is a record for captured variables in
+  /// CapturedStmt construct.
+  bool isCapturedRecord() const;
+  /// \brief Mark the record as a record for captured variables in CapturedStmt
+  /// construct.
+  void setCapturedRecord();
+
   /// getDefinition - Returns the RecordDecl that actually defines
   ///  this struct/union/class.  When determining whether or not a
   ///  struct/union/class is completely defined, one should use this

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Wed Oct 29 07:21:55 2014
@@ -1982,15 +1982,18 @@ public:
 /// @endcode
 class CapturedStmt : public Stmt {
 public:
-  /// \brief The different capture forms: by 'this' or by reference, etc.
+  /// \brief The different capture forms: by 'this', by reference, capture for
+  /// variable-length array type etc.
   enum VariableCaptureKind {
     VCK_This,
-    VCK_ByRef
+    VCK_ByRef,
+    VCK_VLAType,
   };
 
-  /// \brief Describes the capture of either a variable or 'this'.
+  /// \brief Describes the capture of either a variable, or 'this', or
+  /// variable-length array type.
   class Capture {
-    llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind;
+    llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
     SourceLocation Loc;
 
   public:
@@ -2012,6 +2015,10 @@ public:
       case VCK_ByRef:
         assert(Var && "capturing by reference must have a variable!");
         break;
+      case VCK_VLAType:
+        assert(!Var &&
+               "Variable-length array type capture cannot have a variable!");
+        break;
       }
     }
 
@@ -2026,13 +2033,20 @@ public:
     bool capturesThis() const { return getCaptureKind() == VCK_This; }
 
     /// \brief Determine whether this capture handles a variable.
-    bool capturesVariable() const { return getCaptureKind() != VCK_This; }
+    bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+
+    /// \brief Determine whether this capture handles a variable-length array
+    /// type.
+    bool capturesVariableArrayType() const {
+      return getCaptureKind() == VCK_VLAType;
+    }
 
     /// \brief Retrieve the declaration of the variable being captured.
     ///
-    /// This operation is only valid if this capture does not capture 'this'.
+    /// This operation is only valid if this capture captures a variable.
     VarDecl *getCapturedVar() const {
-      assert(!capturesThis() && "No variable available for 'this' capture");
+      assert(capturesVariable() &&
+             "No variable available for 'this' or VAT capture");
       return VarAndKind.getPointer();
     }
     friend class ASTStmtReader;

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Oct 29 07:21:55 2014
@@ -1918,3 +1918,11 @@ def LoopHint : Attr {
 
   let Documentation = [LoopHintDocs, UnrollHintDocs];
 }
+
+def CapturedRecord : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [Undocumented];
+}
+

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Oct 29 07:21:55 2014
@@ -3283,6 +3283,11 @@ bool FieldDecl::isAnonymousStructOrUnion
   return false;
 }
 
+static bool isVLATypeCapturingAllowed(const RecordDecl *RD) {
+  // Allow variable-length array capturing in Lambdas and CapturedStmts.
+  return RD->isLambda() || RD->isCapturedRecord();
+}
+
 unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
   assert(isBitField() && "not a bitfield");
   Expr *BitWidth = static_cast<Expr *>(InitStorage.getPointer());
@@ -3325,7 +3330,8 @@ SourceRange FieldDecl::getSourceRange()
 }
 
 void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
-  assert(getParent()->isLambda() && "capturing type in non-lambda.");
+  assert(isVLATypeCapturingAllowed(getParent()) &&
+         "capturing type in non-lambda or captured record.");
   assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
          InitStorage.getPointer() == nullptr &&
          "bit width, initializer or captured type already set");
@@ -3559,6 +3565,14 @@ bool RecordDecl::isLambda() const {
   return false;
 }
 
+bool RecordDecl::isCapturedRecord() const {
+  return hasAttr<CapturedRecordAttr>();
+}
+
+void RecordDecl::setCapturedRecord() {
+  addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
+}
+
 RecordDecl::field_iterator RecordDecl::field_begin() const {
   if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage)
     LoadFieldsFromExternalStorage();

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Wed Oct 29 07:21:55 2014
@@ -2102,46 +2102,35 @@ void CodeGenFunction::EmitAsmStmt(const
   }
 }
 
-static LValue InitCapturedStruct(CodeGenFunction &CGF, const CapturedStmt &S) {
+LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
   const RecordDecl *RD = S.getCapturedRecordDecl();
-  QualType RecordTy = CGF.getContext().getRecordType(RD);
+  QualType RecordTy = getContext().getRecordType(RD);
 
   // Initialize the captured struct.
-  LValue SlotLV = CGF.MakeNaturalAlignAddrLValue(
-                    CGF.CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
+  LValue SlotLV = MakeNaturalAlignAddrLValue(
+      CreateMemTemp(RecordTy, "agg.captured"), RecordTy);
 
   RecordDecl::field_iterator CurField = RD->field_begin();
   for (CapturedStmt::capture_init_iterator I = S.capture_init_begin(),
                                            E = S.capture_init_end();
        I != E; ++I, ++CurField) {
-    LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField);
-    CGF.EmitInitializerForField(*CurField, LV, *I, None);
+    LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
+    if (CurField->hasCapturedVLAType()) {
+      auto VAT = CurField->getCapturedVLAType();
+      EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
+    } else {
+      EmitInitializerForField(*CurField, LV, *I, None);
+    }
   }
 
   return SlotLV;
 }
 
-static void InitVLACaptures(CodeGenFunction &CGF, const CapturedStmt &S) {
-  for (auto &C : S.captures()) {
-    if (C.capturesVariable()) {
-      QualType QTy;
-      auto VD = C.getCapturedVar();
-      if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD))
-        QTy = PVD->getOriginalType();
-      else
-        QTy = VD->getType();
-      if (QTy->isVariablyModifiedType()) {
-        CGF.EmitVariablyModifiedType(QTy);
-      }
-    }
-  }
-}
-
 /// Generate an outlined function for the body of a CapturedStmt, store any
 /// captured variables into the captured struct, and call the outlined function.
 llvm::Function *
 CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) {
-  LValue CapStruct = InitCapturedStruct(*this, S);
+  LValue CapStruct = InitCapturedStruct(S);
 
   // Emit the CapturedDecl
   CodeGenFunction CGF(CGM, true);
@@ -2157,7 +2146,7 @@ CodeGenFunction::EmitCapturedStmt(const
 
 llvm::Value *
 CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) {
-  LValue CapStruct = InitCapturedStruct(*this, S);
+  LValue CapStruct = InitCapturedStruct(S);
   return CapStruct.getAddress();
 }
 
@@ -2198,14 +2187,21 @@ CodeGenFunction::GenerateCapturedStmtFun
   CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr));
 
   // Initialize variable-length arrays.
-  InitVLACaptures(*this, S);
+  LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
+                                           Ctx.getTagDeclType(RD));
+  for (auto *FD : RD->fields()) {
+    if (FD->hasCapturedVLAType()) {
+      auto *ExprArg = EmitLoadOfLValue(EmitLValueForField(Base, FD),
+                                       S.getLocStart()).getScalarVal();
+      auto VAT = FD->getCapturedVLAType();
+      VLASizeMap[VAT->getSizeExpr()] = ExprArg;
+    }
+  }
 
   // If 'this' is captured, load it into CXXThisValue.
   if (CapturedStmtInfo->isCXXThisExprCaptured()) {
     FieldDecl *FD = CapturedStmtInfo->getThisFieldDecl();
-    LValue LV = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(),
-                                           Ctx.getTagDeclType(RD));
-    LValue ThisLValue = EmitLValueForField(LV, FD);
+    LValue ThisLValue = EmitLValueForField(Base, FD);
     CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
   }
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Oct 29 07:21:55 2014
@@ -193,7 +193,7 @@ public:
            I != E; ++I, ++Field) {
         if (I->capturesThis())
           CXXThisFieldDecl = *Field;
-        else
+        else if (I->capturesVariable())
           CaptureFields[I->getCapturedVar()] = *Field;
       }
     }
@@ -2002,6 +2002,7 @@ public:
   void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
                            ArrayRef<const Attr *> Attrs = None);
 
+  LValue InitCapturedStruct(const CapturedStmt &S);
   llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K);
   void GenerateCapturedStmtFunctionProlog(const CapturedStmt &S);
   llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);

Modified: cfe/trunk/lib/Sema/ScopeInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/ScopeInfo.cpp (original)
+++ cfe/trunk/lib/Sema/ScopeInfo.cpp Wed Oct 29 07:21:55 2014
@@ -95,8 +95,14 @@ FunctionScopeInfo::WeakObjectProfileTy::
 }
 
 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
+  RecordDecl *RD = nullptr;
   if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
-    for (auto *FD : LSI->Lambda->fields()) {
+    RD = LSI->Lambda;
+  else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this))
+    RD = CRSI->TheRecordDecl;
+
+  if (RD)
+    for (auto *FD : RD->fields()) {
       if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
         return true;
     }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Oct 29 07:21:55 2014
@@ -12219,29 +12219,29 @@ bool Sema::tryCaptureVariable(VarDecl *V
           // Unknown size indication requires no size computation.
           // Otherwise, evaluate and record it.
           if (auto Size = VAT->getSizeExpr()) {
-            if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
-              if (!LSI->isVLATypeCaptured(VAT)) {
+            if (!CSI->isVLATypeCaptured(VAT)) {
+              RecordDecl *CapRecord = nullptr;
+              if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
+                CapRecord = LSI->Lambda;
+              } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
+                CapRecord = CRSI->TheRecordDecl;
+              }
+              if (CapRecord) {
                 auto ExprLoc = Size->getExprLoc();
                 auto SizeType = Context.getSizeType();
-                auto Lambda = LSI->Lambda;
-
                 // Build the non-static data member.
                 auto Field = FieldDecl::Create(
-                    Context, Lambda, ExprLoc, ExprLoc,
+                    Context, CapRecord, ExprLoc, ExprLoc,
                     /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr,
                     /*BW*/ nullptr, /*Mutable*/ false,
                     /*InitStyle*/ ICIS_NoInit);
                 Field->setImplicit(true);
                 Field->setAccess(AS_private);
                 Field->setCapturedVLAType(VAT);
-                Lambda->addDecl(Field);
+                CapRecord->addDecl(Field);
 
-                LSI->addVLATypeCapture(ExprLoc, SizeType);
+                CSI->addVLATypeCapture(ExprLoc, SizeType);
               }
-            } else {
-              // Immediately mark all referenced vars for CapturedStatements,
-              // they all are captured by reference.
-              MarkDeclarationsReferencedInExpr(Size);
             }
           }
           QTy = VAT->getElementType();

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Oct 29 07:21:55 2014
@@ -3385,6 +3385,7 @@ Sema::CreateCapturedStmtRecordDecl(Captu
   else
     RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr);
 
+  RD->setCapturedRecord();
   DC->addDecl(RD);
   RD->setImplicit();
   RD->startDefinition();
@@ -3408,6 +3409,11 @@ static void buildCapturedStmtCaptureList
                                                CapturedStmt::VCK_This));
       CaptureInits.push_back(Cap->getInitExpr());
       continue;
+    } else if (Cap->isVLATypeCapture()) {
+      Captures.push_back(
+          CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType));
+      CaptureInits.push_back(nullptr);
+      continue;
     }
 
     assert(Cap->isReferenceCapture() &&

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Oct 29 07:21:55 2014
@@ -307,7 +307,7 @@ void ASTStmtWriter::VisitCapturedStmt(Ca
 
   // Captures
   for (const auto &I : S->captures()) {
-    if (I.capturesThis())
+    if (I.capturesThis() || I.capturesVariableArrayType())
       Writer.AddDeclRef(nullptr, Record);
     else
       Writer.AddDeclRef(I.getCapturedVar(), Record);

Modified: cfe/trunk/test/CodeGen/captured-statements-nested.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/captured-statements-nested.c?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/captured-statements-nested.c (original)
+++ cfe/trunk/test/CodeGen/captured-statements-nested.c Wed Oct 29 07:21:55 2014
@@ -11,9 +11,9 @@ struct A {
 void test_nest_captured_stmt(int param, int size, int param_arr[size]) {
   int w;
   int arr[param][size];
-  // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i{{.+}}*, i32**, i32* }
-  // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i32**, i32*, i{{.+}}*, i32**, i32* }
-  // CHECK1: [[T:%struct.anon.*]] = type { i32*, i32*, %struct.A*, i32**, i32*, i{{.+}}*, i32**, i32* }
+  // CHECK1: %struct.anon{{.*}} = type { [[INT:i.+]]*, [[INT]]*, [[SIZE_TYPE:i.+]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
+  // CHECK1: %struct.anon{{.*}} = type { [[INT]]*, [[INT]]*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
+  // CHECK1: [[T:%struct.anon.*]] = type { [[INT]]*, [[INT]]*, %struct.A*, [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[INT]]**, [[INT]]*, [[SIZE_TYPE]], [[SIZE_TYPE]], [[INT]]* }
   #pragma clang __debug captured
   {
     int x;
@@ -31,39 +31,45 @@ void test_nest_captured_stmt(int param,
         arr[10][z.a] = 12;
 
         // CHECK1: define internal void @__captured_stmt{{.*}}([[T]]
+        // CHECK1: [[PARAM_ARR_SIZE_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 5
+        // CHECK1: [[PARAM_ARR_SIZE:%.+]] = load [[SIZE_TYPE]]* [[PARAM_ARR_SIZE_REF]]
+        // CHECK1: [[ARR_SIZE1_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8
+        // CHECK1: [[ARR_SIZE1:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE1_REF]]
+        // CHECK1: [[ARR_SIZE2_REF:%.+]] = getelementptr inbounds [[T]]* {{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 9
+        // CHECK1: [[ARR_SIZE2:%.+]] = load [[SIZE_TYPE]]* [[ARR_SIZE2_REF]]
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store i{{.+}} 1
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 1
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32 1
-        //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 0
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32 1
-        //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 4
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: load i32*
-        // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 3
-        // CHECK1-NEXT: load i32***
-        // CHECK1-NEXT: load i32**
-        // CHECK1-NEXT: store i32
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}} 1
+        //
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}} 1
+        //
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 4
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: load i{{[0-9]+}}*
+        // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 3
+        // CHECK1-NEXT: load i{{[0-9]+}}***
+        // CHECK1-NEXT: load i{{[0-9]+}}**
+        // CHECK1-NEXT: store i{{[0-9]+}}
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store float
         //
-        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+        // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
         // CHECK1-NEXT: load %struct.A**
         // CHECK1-NEXT: getelementptr inbounds %struct.A*
         // CHECK1-NEXT: store i8 99
         //
-        // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 5
+        // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
         // CHECK1-DAG: [[SIZE_ADDR:%.*]] = load i{{.+}}** [[SIZE_ADDR_REF]]
         // CHECK1-DAG: [[SIZE:%.*]] = load i{{.+}}* [[SIZE_ADDR]]
         // CHECK1-DAG: [[PARAM_ARR_IDX:%.*]] = sub nsw i{{.+}} [[SIZE]], 1
@@ -77,7 +83,7 @@ void test_nest_captured_stmt(int param,
         // CHECK1-DAG: [[Z_ADDR:%.*]] = load %struct.A** [[Z_ADDR_REF]]
         // CHECK1-DAG: [[Z_A_ADDR:%.*]] = getelementptr inbounds %struct.A* [[Z_ADDR]], i{{.+}} 0, i{{.+}} 0
         // CHECK1-DAG: [[ARR_IDX_2:%.*]] = load i{{.+}}* [[Z_A_ADDR]]
-        // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
+        // CHECK1-DAG: [[ARR_ADDR_REF:%.*]] = getelementptr inbounds [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 10
         // CHECK1-DAG: [[ARR_ADDR:%.*]] = load i{{.+}}** [[ARR_ADDR_REF]]
         // CHECK1-DAG: [[ARR_IDX_1:%.*]] = mul {{.*}} 10
         // CHECK1-DAG: [[ARR_10_ADDR:%.*]] = getelementptr inbounds i{{.+}}* [[ARR_ADDR]], i{{.*}} [[ARR_IDX_1]]
@@ -102,15 +108,15 @@ void test_nest_block() {
 
   // CHECK2: define internal void @{{.*}}test_nest_block_block_invoke
   //
-  // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i32
+  // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i{{[0-9]+}}
   // CHECK2: alloca %struct.anon{{.*}}
   //
-  // CHECK2: store i32
-  // CHECK2: store i32* [[Z]]
+  // CHECK2: store i{{[0-9]+}}
+  // CHECK2: store i{{[0-9]+}}* [[Z]]
   //
   // CHECK2: getelementptr inbounds %struct.anon
   // CHECK2-NEXT: getelementptr inbounds
-  // CHECK2-NEXT: store i32*
+  // CHECK2-NEXT: store i{{[0-9]+}}*
   //
   // CHECK2: call void @__captured_stmt
 
@@ -128,22 +134,22 @@ void test_nest_block() {
   }
 
   // CHECK2: alloca %struct.__block_byref_b
-  // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i32
+  // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i{{[0-9]+}}
   // CHECK2-NEXT: alloca %struct.__block_byref_d
   //
   // CHECK2: bitcast %struct.__block_byref_b*
   // CHECK2-NEXT: store i8*
   //
-  // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 7
+  // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 7
   //
-  // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i32 0, i32 0
-  // CHECK2: load i32**
-  // CHECK2: load i32*
-  // CHECK2: store i32 {{.*}}, i32* [[CapA]]
-  //
-  // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 8
-  // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i32* [[C]]
-  // CHECK2-NEXT: store i32 [[Val]], i32* [[CapC]]
+  // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+  // CHECK2: load i{{[0-9]+}}**
+  // CHECK2: load i{{[0-9]+}}*
+  // CHECK2: store i{{[0-9]+}} {{.*}}, i{{[0-9]+}}* [[CapA]]
+  //
+  // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i{{[0-9]+}} 0, i{{[0-9]+}} 8
+  // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i{{[0-9]+}}* [[C]]
+  // CHECK2-NEXT: store i{{[0-9]+}} [[Val]], i{{[0-9]+}}* [[CapC]]
   //
   // CHECK2: bitcast %struct.__block_byref_d*
   // CHECK2-NEXT: store i8*

Modified: cfe/trunk/test/CodeGen/captured-statements.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/captured-statements.c?rev=220850&r1=220849&r2=220850&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/captured-statements.c (original)
+++ cfe/trunk/test/CodeGen/captured-statements.c Wed Oct 29 07:21:55 2014
@@ -4,6 +4,8 @@
 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
 
+typedef __INTPTR_TYPE__ intptr_t;
+
 int foo();
 int global;
 
@@ -61,15 +63,16 @@ void test3(int size) {
 }
 
 // Capture VLA array
-void test4(int size, int vla_arr[size]) {
+void test4(intptr_t size, intptr_t vla_arr[size]) {
   #pragma clang __debug captured
   {
     vla_arr[0] = 1;
   }
-  // CHECK-3: test4([[INT:i.+]] {{.*}}[[SIZE:%.+]], [[INT]]*
-  // CHECK-3: store [[INT]] {{.*}}[[SIZE]], [[INT]]* [[SIZE_ADDR:%.+]],
+  // CHECK-3: test4([[INTPTR_T:i.+]] {{.*}}[[SIZE_ARG:%.+]], [[INTPTR_T]]*
+  // CHECK-3: store [[INTPTR_T]] {{.*}}[[SIZE_ARG]], [[INTPTR_T]]* [[SIZE_ADDR:%.+]],
+  // CHECK-3: [[SIZE:%.+]] = load [[INTPTR_T]]* [[SIZE_ADDR]],
   // CHECK-3: [[REF:%.+]] = getelementptr inbounds
-  // CHECK-3: store [[INT]]* [[SIZE_ADDR]], [[INT]]** [[REF]]
+  // CHECK-3: store [[INTPTR_T]] [[SIZE]], [[INTPTR_T]]* [[REF]]
   // CHECK-3: call void @__captured_stmt
 }
 





More information about the cfe-commits mailing list