CGBlocks.cpp revision 7cbb3608a7c28a7fb285fdc7f44060c5c175c8a0
1//===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This contains code to emit blocks. 11// 12//===----------------------------------------------------------------------===// 13 14#include "CodeGenFunction.h" 15#include "CodeGenModule.h" 16#include "llvm/Module.h" 17#include "llvm/Target/TargetData.h" 18 19#include <algorithm> 20 21using namespace clang; 22using namespace CodeGen; 23 24// Block flags 25enum { 26 IsGlobal = 1 << 28 27}; 28 29const llvm::Type *CodeGenModule::getBlockDescriptorType() { 30 if (BlockDescriptorType) 31 return BlockDescriptorType; 32 33 const llvm::Type *UnsignedLongTy = 34 getTypes().ConvertType(getContext().UnsignedLongTy); 35 36 // struct __block_descriptor { 37 // unsigned long reserved; 38 // unsigned long block_size; 39 // }; 40 BlockDescriptorType = llvm::StructType::get(UnsignedLongTy, 41 UnsignedLongTy, 42 NULL); 43 44 getModule().addTypeName("struct.__block_descriptor", 45 BlockDescriptorType); 46 47 return BlockDescriptorType; 48} 49 50const llvm::Type * 51CodeGenModule::getGenericBlockLiteralType() { 52 if (GenericBlockLiteralType) 53 return GenericBlockLiteralType; 54 55 const llvm::Type *Int8PtrTy = 56 llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 57 58 const llvm::Type *BlockDescPtrTy = 59 llvm::PointerType::getUnqual(getBlockDescriptorType()); 60 61 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 62 getTypes().ConvertType(getContext().IntTy)); 63 64 // struct __block_literal_generic { 65 // void *isa; 66 // int flags; 67 // int reserved; 68 // void (*invoke)(void *); 69 // struct __block_descriptor *descriptor; 70 // }; 71 GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy, 72 IntTy, 73 IntTy, 74 Int8PtrTy, 75 BlockDescPtrTy, 76 NULL); 77 78 getModule().addTypeName("struct.__block_literal_generic", 79 GenericBlockLiteralType); 80 81 return GenericBlockLiteralType; 82} 83 84/// getBlockFunctionType - Given a BlockPointerType, will return the 85/// function type for the block, including the first block literal argument. 86static QualType getBlockFunctionType(ASTContext &Ctx, 87 const BlockPointerType *BPT) { 88 const FunctionTypeProto *FTy = cast<FunctionTypeProto>(BPT->getPointeeType()); 89 90 llvm::SmallVector<QualType, 8> Types; 91 Types.push_back(Ctx.getPointerType(Ctx.VoidTy)); 92 93 for (FunctionTypeProto::arg_type_iterator i = FTy->arg_type_begin(), 94 e = FTy->arg_type_end(); i != e; ++i) 95 Types.push_back(*i); 96 97 return Ctx.getFunctionType(FTy->getResultType(), 98 &Types[0], Types.size(), 99 FTy->isVariadic(), 0); 100} 101 102RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { 103 const BlockPointerType *BPT = 104 E->getCallee()->getType()->getAsBlockPointerType(); 105 106 llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 107 108 // Get a pointer to the generic block literal. 109 const llvm::Type *BlockLiteralTy = 110 llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 111 112 // Bitcast the callee to a block literal. 113 llvm::Value *BlockLiteral = 114 Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 115 116 // Get the function pointer from the literal. 117 llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); 118 llvm::Value *Func = Builder.CreateLoad(FuncPtr, FuncPtr, "tmp"); 119 120 // Cast the function pointer to the right type. 121 const llvm::Type *BlockFTy = 122 ConvertType(getBlockFunctionType(getContext(), BPT)); 123 const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 124 Func = Builder.CreateBitCast(Func, BlockFTyPtr); 125 126 BlockLiteral = 127 Builder.CreateBitCast(BlockLiteral, 128 llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 129 "tmp"); 130 131 // Add the block literal. 132 QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); 133 CallArgList Args; 134 Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy)); 135 136 // And the rest of the arguments. 137 for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end(); 138 i != e; ++i) 139 Args.push_back(std::make_pair(EmitAnyExprToTemp(*i), 140 i->getType())); 141 142 // And call the block. 143 return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args), 144 Func, Args); 145} 146 147llvm::Constant *CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE) { 148 if (!NSConcreteGlobalBlock) { 149 const llvm::Type *Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 150 151 // FIXME: Wee should have a CodeGenModule::AddRuntimeVariable that does the 152 // same thing as CreateRuntimeFunction if there's already a variable with 153 // the same name. 154 NSConcreteGlobalBlock = 155 new llvm::GlobalVariable(Ty, false, 156 llvm::GlobalVariable::ExternalLinkage, 0, 157 "_NSConcreteGlobalBlock", &getModule()); 158 } 159 160 // Generate the block descriptor. 161 const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy); 162 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 163 getTypes().ConvertType(getContext().IntTy)); 164 165 llvm::Constant *DescriptorFields[2]; 166 167 // Reserved 168 DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy); 169 170 // Block literal size. For global blocks we just use the size of the generic 171 // block literal struct. 172 uint64_t BlockLiteralSize = 173 TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8; 174 DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); 175 176 llvm::Constant *DescriptorStruct = 177 llvm::ConstantStruct::get(&DescriptorFields[0], 2); 178 179 llvm::GlobalVariable *Descriptor = 180 new llvm::GlobalVariable(DescriptorStruct->getType(), true, 181 llvm::GlobalVariable::InternalLinkage, 182 DescriptorStruct, "__block_descriptor_global", 183 &getModule()); 184 185 // Generate the constants for the block literal. 186 llvm::Constant *LiteralFields[5]; 187 188 CodeGenFunction::BlockInfo Info(0, "global"); 189 llvm::Function *Fn = CodeGenFunction(*this).GenerateBlockFunction(BE, Info); 190 191 // isa 192 LiteralFields[0] = NSConcreteGlobalBlock; 193 194 // Flags 195 LiteralFields[1] = llvm::ConstantInt::get(IntTy, IsGlobal); 196 197 // Reserved 198 LiteralFields[2] = llvm::Constant::getNullValue(IntTy); 199 200 // Function 201 LiteralFields[3] = Fn; 202 203 // Descriptor 204 LiteralFields[4] = Descriptor; 205 206 llvm::Constant *BlockLiteralStruct = 207 llvm::ConstantStruct::get(&LiteralFields[0], 5); 208 209 llvm::GlobalVariable *BlockLiteral = 210 new llvm::GlobalVariable(BlockLiteralStruct->getType(), true, 211 llvm::GlobalVariable::InternalLinkage, 212 BlockLiteralStruct, "__block_literal_global", 213 &getModule()); 214 215 return BlockLiteral; 216} 217 218llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, 219 const BlockInfo& Info) 220{ 221 const FunctionTypeProto *FTy = 222 cast<FunctionTypeProto>(Expr->getFunctionType()); 223 224 FunctionArgList Args; 225 226 const BlockDecl *BD = Expr->getBlockDecl(); 227 228 // FIXME: This leaks 229 ImplicitParamDecl *SelfDecl = 230 ImplicitParamDecl::Create(getContext(), 0, 231 SourceLocation(), 0, 232 getContext().getPointerType(getContext().VoidTy)); 233 234 Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); 235 236 for (BlockDecl::param_iterator i = BD->param_begin(), 237 e = BD->param_end(); i != e; ++i) 238 Args.push_back(std::make_pair(*e, (*e)->getType())); 239 240 const CGFunctionInfo &FI = 241 CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args); 242 243 std::string Name = std::string("__block_function_") + Info.NameSuffix; 244 245 CodeGenTypes &Types = CGM.getTypes(); 246 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic()); 247 248 llvm::Function *Fn = 249 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 250 Name, 251 &CGM.getModule()); 252 253 StartFunction(BD, FTy->getResultType(), Fn, Args, 254 Expr->getBody()->getLocEnd()); 255 EmitStmt(Expr->getBody()); 256 FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc()); 257 258 return Fn; 259} 260