diff options
author | Mike Stump <mrs@apple.com> | 2009-10-20 02:12:22 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-10-20 02:12:22 +0000 |
commit | adaaad3715c9c26cdcfdfe3401a13d7b4423ddcf (patch) | |
tree | ad2ec2fa2dd2e020251449a3537edd506bfed18d | |
parent | 9a2c8bb599a2460807e341182655a68515574124 (diff) |
Refine the type of the first parameter to block invoke functions.
WIP. I have yet to find the magic incantation to get the structure
type to be defined. If someone has a pointer, love to hear it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84590 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 24 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 4 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 109 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 24 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 1 |
6 files changed, 160 insertions, 4 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 493d8acf3b..df480e9a36 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -144,6 +144,9 @@ class ASTContext { /// \brief The type for the C sigjmp_buf type. TypeDecl *sigjmp_bufDecl; + /// \brief Type for the Block descriptor for Blocks CodeGen. + RecordDecl *BlockDescriptorType; + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -391,6 +394,27 @@ public: /// of the specified type. QualType getBlockPointerType(QualType T); + /// This gets the struct used to keep track of the descriptor for pointer to + /// blocks. + QualType getBlockDescriptorType(); + + // Set the type for a Block descriptor type. + void setBlockDescriptorType(QualType T); + /// Get the BlockDescriptorType type, or NULL if it hasn't yet been built. + QualType getRawBlockdescriptorType() { + if (BlockDescriptorType) + return getTagDeclType(BlockDescriptorType); + return QualType(); + } + + /// This gets the struct used to keep track of pointer to blocks, complete + /// with captured variables. + QualType getBlockParmType(); + + /// This completes a type created by getBlockParmType. + void completeBlockParmType(QualType Ty, + llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls); + /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. QualType getLValueReferenceType(QualType T); diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index e4161fcae6..dcabcb3187 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -436,7 +436,9 @@ namespace clang { /// \brief Objective-C "id" redefinition type SPECIAL_TYPE_OBJC_ID_REDEFINITION = 10, /// \brief Objective-C "Class" redefinition type - SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11 + SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 11, + /// \brief Block descriptor type for Blocks CodeGen + SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12 }; /// \brief Record codes for each kind of declaration. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d96f5fbf1c..98aef39022 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -40,7 +40,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), - sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts), + sigjmp_bufDecl(0), BlockDescriptorType(0), SourceMgr(SM), LangOpts(LOpts), LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { @@ -2692,6 +2692,113 @@ QualType ASTContext::getObjCFastEnumerationStateType() { return getTagDeclType(ObjCFastEnumerationStateTypeDecl); } +QualType ASTContext::getBlockDescriptorType() { + if (BlockDescriptorType) + return getTagDeclType(BlockDescriptorType); + + RecordDecl *T; + // FIXME: Needs the FlagAppleBlock bit. + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__block_descriptor")); + + QualType FieldTypes[] = { + UnsignedLongTy, + UnsignedLongTy, + }; + + const char *FieldNames[] = { + "reserved", + "Size", + }; + + for (size_t i = 0; i < 2; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, + T, + SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false); + T->addDecl(Field); + } + + T->completeDefinition(*this); + + BlockDescriptorType = T; + + return getTagDeclType(BlockDescriptorType); +} + +void ASTContext::setBlockDescriptorType(QualType T) { + const RecordType *Rec = T->getAs<RecordType>(); + assert(Rec && "Invalid BlockDescriptorType"); + BlockDescriptorType = Rec->getDecl(); +} + +QualType ASTContext::getBlockParmType() { + // FIXME: Move up + static int UniqueBlockParmTypeID = 0; + char Name[36]; + sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID); + RecordDecl *T; + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name)); + +#define REV2 +#ifdef REV2 + cast<TagDecl>(T)->startDefinition(); +#endif + + return getPointerType(getTagDeclType(T)); +} + +void ASTContext::completeBlockParmType(QualType Ty, + llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { + RecordDecl *PT = Ty->getPointeeType()->getAs<RecordType>()->getDecl(); + llvm::StringRef Name = PT->getIdentifier()->getName(); + + RecordDecl *T; +#ifdef REV2 + T = PT; +#else + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name), SourceLocation(), PT); + + cast<TagDecl>(T)->startDefinition(); +#endif + + QualType FieldTypes[] = { + getPointerType(VoidPtrTy), + IntTy, + IntTy, + getPointerType(VoidPtrTy), + getPointerType(getBlockDescriptorType()), + }; + + const char *FieldNames[] = { + "__isa", + "__flags", + "__reserved", + "__FuncPtr", + "__descriptor" + }; + + for (size_t i = 0; i < 5; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, + T, + SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false); + // FIXME: Do this instead or addDecl? + // PushOnScopeChains(FieldTypes, S); + T->addDecl(Field); + } + + T->completeDefinition(*this); +} + void ASTContext::setObjCFastEnumerationStateType(QualType T) { const RecordType *Rec = T->getAs<RecordType>(); assert(Rec && "Invalid ObjCFAstEnumerationStateType"); diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 736425e012..5998493986 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -632,11 +632,15 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, const BlockDecl *BD = BExpr->getBlockDecl(); + IdentifierInfo *II + = &CGM.getContext().Idents.get(".block_descriptor"); + + QualType ParmTy = getContext().getBlockParmType(); // FIXME: This leaks ImplicitParamDecl *SelfDecl = ImplicitParamDecl::Create(getContext(), 0, - SourceLocation(), 0, - getContext().getPointerType(getContext().VoidTy)); + SourceLocation(), II, + ParmTy); Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); BlockStructDecl = SelfDecl; @@ -701,6 +705,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc()); + // And now finish off the type for the parameter, since now we know + // BlockDeclRefDecls is complete. + getContext().completeBlockParmType(ParmTy, BlockDeclRefDecls); + +#define REV2 +#ifdef REV2 + TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl(); + CGM.UpdateCompletedType(TD); +#else + TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl(); + TagDecl::redecl_iterator rdi = TD->redecls_begin(); + ++rdi; + TD = *rdi; + CGM.UpdateCompletedType(TD); +#endif + // The runtime needs a minimum alignment of a void *. uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8; BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index ef73da7c34..82e5033dd8 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1589,6 +1589,8 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { if (unsigned ObjCClassRedef = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); + if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) + Context->setBlockDescriptorType(GetType(String)); } /// \brief Retrieve the name of the original source file name diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index dbe1e9933e..c2530472f2 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1987,6 +1987,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getsigjmp_bufType(), Record); AddTypeRef(Context.ObjCIdRedefinitionType, Record); AddTypeRef(Context.ObjCClassRedefinitionType, Record); + AddTypeRef(Context.getRawBlockdescriptorType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); // Keep writing types and declarations until all types and |