diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-07-16 00:00:19 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-07-16 00:00:19 +0000 |
commit | 754b9fbaa13749c61393cc613eec7c79efe60ddf (patch) | |
tree | 976a999d6480d8ae25cbc7548ed248a81c6a8824 | |
parent | 673431a2986f750b4d8fadb57abf3f00db27bbbd (diff) |
IRgen: Support user defined attributes on block runtime functions.
- This issue here is that /usr/include/Blocks.h wants to define some of the
block runtime globals as weak, depending on the target. This doesn't work in
Clang because we aren't using the AST decl for these globals.
- The fix is a pretty gross hack which just watches all the decls for the
specific blocks globals we need to know about; if we see one we use it,
otherwise we use the hand coded type.
In time, I would like to clean this up by changing IRgen to ask Sema/AST for
the decl, which would then be lazily loaded from the builtin table if
necessary. This could be used in a whole host of places in IRgen and would
get rid of a lot of grotty hand coding of LLVM IR; however, we need some
extra Sema support for this as well as support for builtin global variables.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108482 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/Builtins.def | 5 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 55 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 5 | ||||
-rw-r--r-- | test/CodeGen/block-decl-merging.c | 20 |
4 files changed, 85 insertions, 0 deletions
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index eff4f5e672..44b7f117d4 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -560,5 +560,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h") LIBBUILTIN(cosl, "LdLd", "fe", "math.h") LIBBUILTIN(cosf, "ff", "fe", "math.h") +// Blocks runtime Builtin math library functions +LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h") +LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h") +// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock. + #undef BUILTIN #undef LIBBUILTIN diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index f05a018e91..f6788c6c30 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -52,7 +52,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, VTables(*this), Runtime(0), ABI(0), CFConstantStringClassRef(0), NSConstantStringClassRef(0), VMContext(M.getContext()), + NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0), NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), + BlockObjectAssignDecl(0), BlockObjectDisposeDecl(0), BlockObjectAssign(0), BlockObjectDispose(0){ if (!Features.ObjC1) @@ -775,6 +777,15 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Ignore declarations, they will be emitted on their first use. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { + if (FD->getIdentifier()) { + llvm::StringRef Name = FD->getName(); + if (Name == "_Block_object_assign") { + BlockObjectAssignDecl = FD; + } else if (Name == "_Block_object_dispose") { + BlockObjectDisposeDecl = FD; + } + } + // Forward declarations are emitted lazily on first use. if (!FD->isThisDeclarationADefinition()) return; @@ -782,6 +793,16 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { const VarDecl *VD = cast<VarDecl>(Global); assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); + if (VD->getIdentifier()) { + llvm::StringRef Name = VD->getName(); + if (Name == "_NSConcreteGlobalBlock") { + NSConcreteGlobalBlockDecl = VD; + } else if (Name == "_NSConcreteStackBlock") { + NSConcreteStackBlockDecl = VD; + } + } + + if (VD->isThisDeclarationADefinition() != VarDecl::Definition) return; } @@ -2144,6 +2165,14 @@ llvm::Constant *CodeGenModule::getBlockObjectDispose() { if (BlockObjectDispose) return BlockObjectDispose; + // If we saw an explicit decl, use that. + if (BlockObjectDisposeDecl) { + return BlockObjectDispose = GetAddrOfFunction( + BlockObjectDisposeDecl, + getTypes().GetFunctionType(BlockObjectDisposeDecl)); + } + + // Otherwise construct the function by hand. const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); @@ -2158,6 +2187,14 @@ llvm::Constant *CodeGenModule::getBlockObjectAssign() { if (BlockObjectAssign) return BlockObjectAssign; + // If we saw an explicit decl, use that. + if (BlockObjectAssignDecl) { + return BlockObjectAssign = GetAddrOfFunction( + BlockObjectAssignDecl, + getTypes().GetFunctionType(BlockObjectAssignDecl)); + } + + // Otherwise construct the function by hand. const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); @@ -2172,6 +2209,15 @@ llvm::Constant *CodeGenModule::getBlockObjectAssign() { llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { if (NSConcreteGlobalBlock) return NSConcreteGlobalBlock; + + // If we saw an explicit decl, use that. + if (NSConcreteGlobalBlockDecl) { + return NSConcreteGlobalBlock = GetAddrOfGlobalVar( + NSConcreteGlobalBlockDecl, + getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType())); + } + + // Otherwise construct the variable by hand. return NSConcreteGlobalBlock = CreateRuntimeVariable( PtrToInt8Ty, "_NSConcreteGlobalBlock"); } @@ -2179,6 +2225,15 @@ llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { if (NSConcreteStackBlock) return NSConcreteStackBlock; + + // If we saw an explicit decl, use that. + if (NSConcreteStackBlockDecl) { + return NSConcreteStackBlock = GetAddrOfGlobalVar( + NSConcreteStackBlockDecl, + getTypes().ConvertType(NSConcreteStackBlockDecl->getType())); + } + + // Otherwise construct the variable by hand. return NSConcreteStackBlock = CreateRuntimeVariable( PtrToInt8Ty, "_NSConcreteStackBlock"); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index f3bd307129..420900acdf 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -197,8 +197,13 @@ class CodeGenModule : public BlockModule { /// @name Cache for Blocks Runtime Globals /// @{ + const VarDecl *NSConcreteGlobalBlockDecl; + const VarDecl *NSConcreteStackBlockDecl; llvm::Constant *NSConcreteGlobalBlock; llvm::Constant *NSConcreteStackBlock; + + const FunctionDecl *BlockObjectAssignDecl; + const FunctionDecl *BlockObjectDisposeDecl; llvm::Constant *BlockObjectAssign; llvm::Constant *BlockObjectDispose; diff --git a/test/CodeGen/block-decl-merging.c b/test/CodeGen/block-decl-merging.c new file mode 100644 index 0000000000..5a3d95b827 --- /dev/null +++ b/test/CodeGen/block-decl-merging.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -emit-llvm -o - %s | \ +// RUN: FileCheck %s + +// CHECK: @_NSConcreteGlobalBlock = extern_weak global +extern void * _NSConcreteStackBlock[32] __attribute__((weak_import)); +// CHECK: @_NSConcreteStackBlock = extern_weak global +extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import)); +// CHECK: declare extern_weak void @_Block_object_dispose +extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import)); +// CHECK: declare extern_weak void @_Block_object_assign +extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import)); + +void *x = ^(){}; + +void f1(void (^a0)(void)); + +void f0() { + __block int x; + f1(^(void){ x = 1; }); +} |