From 4ed019aabebd185a56a7cfa155739ca646452047 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 29 Oct 2014 12:21:55 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220850 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Decl.h | 7 +++ include/clang/AST/Stmt.h | 28 ++++++--- include/clang/Basic/Attr.td | 8 +++ lib/AST/Decl.cpp | 16 ++++- lib/CodeGen/CGStmt.cpp | 52 ++++++++-------- lib/CodeGen/CodeGenFunction.h | 3 +- lib/Sema/ScopeInfo.cpp | 8 ++- lib/Sema/SemaExpr.cpp | 22 +++---- lib/Sema/SemaStmt.cpp | 6 ++ lib/Serialization/ASTWriterStmt.cpp | 2 +- test/CodeGen/captured-statements-nested.c | 74 ++++++++++++----------- test/CodeGen/captured-statements.c | 11 ++-- 12 files changed, 149 insertions(+), 88 deletions(-) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e2f3bdaffd..1b33f95284 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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 diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 88417b2bec..380c3b956e 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -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 VarAndKind; + llvm::PointerIntPair 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; diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index ed86c4fe9c..51837fe2ad 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -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]; +} + diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 0de5459a4c..431adaf184 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3283,6 +3283,11 @@ bool FieldDecl::isAnonymousStructOrUnion() const { 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(InitStorage.getPointer()); @@ -3325,7 +3330,8 @@ SourceRange FieldDecl::getSourceRange() const { } 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(); +} + +void RecordDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + RecordDecl::field_iterator RecordDecl::field_begin() const { if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage) LoadFieldsFromExternalStorage(); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index d4fd3b5178..f207a4f7f8 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -2102,46 +2102,35 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } } -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(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 CapturedStmt &S, CapturedRegionKind K) { llvm::Value * CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) { - LValue CapStruct = InitCapturedStruct(*this, S); + LValue CapStruct = InitCapturedStruct(S); return CapStruct.getAddress(); } @@ -2198,14 +2187,21 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { 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(); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 66f3fcecff..eb3e656633 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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 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); diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp index 259cd674c3..c4bf67b76c 100644 --- a/lib/Sema/ScopeInfo.cpp +++ b/lib/Sema/ScopeInfo.cpp @@ -95,8 +95,14 @@ FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { } bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { + RecordDecl *RD = nullptr; if (auto *LSI = dyn_cast(this)) - for (auto *FD : LSI->Lambda->fields()) { + RD = LSI->Lambda; + else if (auto CRSI = dyn_cast(this)) + RD = CRSI->TheRecordDecl; + + if (RD) + for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT) return true; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8c13f89c0b..a8e4407f34 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12219,29 +12219,29 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, // Unknown size indication requires no size computation. // Otherwise, evaluate and record it. if (auto Size = VAT->getSizeExpr()) { - if (auto LSI = dyn_cast(CSI)) { - if (!LSI->isVLATypeCaptured(VAT)) { + if (!CSI->isVLATypeCaptured(VAT)) { + RecordDecl *CapRecord = nullptr; + if (auto LSI = dyn_cast(CSI)) { + CapRecord = LSI->Lambda; + } else if (auto CRSI = dyn_cast(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(); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0c2d9e3e7a..3c4085afe1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3385,6 +3385,7 @@ Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, 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() && diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 99e7e6d2ef..61ec6a058b 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -307,7 +307,7 @@ void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { // 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); diff --git a/test/CodeGen/captured-statements-nested.c b/test/CodeGen/captured-statements-nested.c index 2ff9ee9cc8..c57226f259 100644 --- a/test/CodeGen/captured-statements-nested.c +++ b/test/CodeGen/captured-statements-nested.c @@ -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, int size, int param_arr[size]) { 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]]* {{.*}}, 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]]* {{.*}}, i32 0, i32 0 - // CHECK1-NEXT: load i32** - // CHECK1-NEXT: store i32 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]]* {{.*}}, 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]+}} 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, int size, int param_arr[size]) { // 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: 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 {{.*}}, i32 0, i32 8 - // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i32* [[C]] - // CHECK2-NEXT: store i32 [[Val]], i32* [[CapC]] + // 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* diff --git a/test/CodeGen/captured-statements.c b/test/CodeGen/captured-statements.c index 85d597aeb3..52747fba1e 100644 --- a/test/CodeGen/captured-statements.c +++ b/test/CodeGen/captured-statements.c @@ -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 } -- 2.40.0