CGBlocks.cpp revision 4e7a1f7682d94811bd41fca8aefccc38f686db23
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 24enum { 25 BLOCK_NEEDS_FREE = (1 << 24), 26 BLOCK_HAS_COPY_DISPOSE = (1 << 25), 27 BLOCK_HAS_CXX_OBJ = (1 << 26), 28 BLOCK_IS_GC = (1 << 27), 29 BLOCK_IS_GLOBAL = (1 << 28), 30 BLOCK_HAS_DESCRIPTOR = (1 << 29) 31}; 32 33llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) { 34 const llvm::PointerType *PtrToInt8Ty 35 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 36 const llvm::Type *UnsignedLongTy 37 = CGM.getTypes().ConvertType(getContext().UnsignedLongTy); 38 llvm::Constant *C; 39 std::vector<llvm::Constant*> Elts; 40 41 // reserved 42 C = llvm::ConstantInt::get(UnsignedLongTy, 0); 43 Elts.push_back(C); 44 45 // Size 46 C = llvm::ConstantInt::get(UnsignedLongTy, Size); 47 Elts.push_back(C); 48 49 if (BlockHasCopyDispose) { 50 // copy_func_helper_decl 51 // FIXME: implement 52 C = llvm::ConstantInt::get(UnsignedLongTy, 0); 53 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); 54 Elts.push_back(C); 55 56 // destroy_func_decl 57 // FIXME: implement 58 C = llvm::ConstantInt::get(UnsignedLongTy, 0); 59 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); 60 Elts.push_back(C); 61 } 62 63 C = llvm::ConstantStruct::get(Elts); 64 65 C = new llvm::GlobalVariable(C->getType(), true, 66 llvm::GlobalValue::InternalLinkage, 67 C, "__block_descriptor_tmp", &CGM.getModule()); 68 return C; 69} 70 71llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { 72 if (NSConcreteGlobalBlock) 73 return NSConcreteGlobalBlock; 74 75 const llvm::PointerType *PtrToInt8Ty 76 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 77 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the 78 // same thing as CreateRuntimeFunction if there's already a variable with 79 // the same name. 80 NSConcreteGlobalBlock 81 = new llvm::GlobalVariable(PtrToInt8Ty, false, 82 llvm::GlobalValue::ExternalLinkage, 83 0, "_NSConcreteGlobalBlock", 84 &getModule()); 85 86 return NSConcreteGlobalBlock; 87} 88 89llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { 90 if (NSConcreteStackBlock) 91 return NSConcreteStackBlock; 92 93 const llvm::PointerType *PtrToInt8Ty 94 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 95 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the 96 // same thing as CreateRuntimeFunction if there's already a variable with 97 // the same name. 98 NSConcreteStackBlock 99 = new llvm::GlobalVariable(PtrToInt8Ty, false, 100 llvm::GlobalValue::ExternalLinkage, 101 0, "_NSConcreteStackBlock", 102 &getModule()); 103 104 return NSConcreteStackBlock; 105} 106 107// FIXME: Push most into CGM, passing down a few bits, like current 108// function name. 109llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { 110 bool insideFunction = false; 111 bool BlockRefDeclList = false; 112 bool BlockByrefDeclList = false; 113 114 std::vector<llvm::Constant*> Elts; 115 llvm::Constant *C; 116 117 { 118 // C = BuildBlockStructInitlist(); 119 unsigned int flags = BLOCK_HAS_DESCRIPTOR; 120 121 if (BlockHasCopyDispose) 122 flags |= BLOCK_HAS_COPY_DISPOSE; 123 124 // __isa 125 C = CGM.getNSConcreteStackBlock(); 126 if (!insideFunction || 127 (!BlockRefDeclList && !BlockByrefDeclList)) { 128 C = CGM.getNSConcreteGlobalBlock(); 129 flags |= BLOCK_IS_GLOBAL; 130 } 131 const llvm::PointerType *PtrToInt8Ty 132 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 133 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); 134 Elts.push_back(C); 135 136 // __flags 137 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 138 CGM.getTypes().ConvertType(CGM.getContext().IntTy)); 139 C = llvm::ConstantInt::get(IntTy, flags); 140 Elts.push_back(C); 141 142 // __reserved 143 C = llvm::ConstantInt::get(IntTy, 0); 144 Elts.push_back(C); 145 146 // __invoke 147 const char *Name = ""; 148 if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurFuncDecl)) 149 if (ND->getIdentifier()) 150 Name = ND->getNameAsCString(); 151 BlockInfo Info(0, Name); 152 uint64_t subBlockSize; 153 llvm::Function *Fn 154 = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize); 155 Elts.push_back(Fn); 156 157 // __descriptor 158 Elts.push_back(BuildDescriptorBlockDecl(subBlockSize)); 159 160 // FIXME: Add block_original_ref_decl_list and block_byref_decl_list. 161 } 162 163 C = llvm::ConstantStruct::get(Elts); 164 165 char Name[32]; 166 sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount()); 167 C = new llvm::GlobalVariable(C->getType(), true, 168 llvm::GlobalValue::InternalLinkage, 169 C, Name, &CGM.getModule()); 170 QualType BPT = BE->getType(); 171 C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT)); 172 return C; 173} 174 175 176 177 178const llvm::Type *CodeGenModule::getBlockDescriptorType() { 179 if (BlockDescriptorType) 180 return BlockDescriptorType; 181 182 const llvm::Type *UnsignedLongTy = 183 getTypes().ConvertType(getContext().UnsignedLongTy); 184 185 // struct __block_descriptor { 186 // unsigned long reserved; 187 // unsigned long block_size; 188 // }; 189 BlockDescriptorType = llvm::StructType::get(UnsignedLongTy, 190 UnsignedLongTy, 191 NULL); 192 193 // FIXME: This breaks an unrelated testcase in the testsuite, we 194 // _want_ llvm to not use structural equality, sometimes. What 195 // should we do, modify the testcase and do this anyway, or... 196#if 0 197 getModule().addTypeName("struct.__block_descriptor", 198 BlockDescriptorType); 199#endif 200 201 return BlockDescriptorType; 202} 203 204const llvm::Type * 205CodeGenModule::getGenericBlockLiteralType() { 206 if (GenericBlockLiteralType) 207 return GenericBlockLiteralType; 208 209 const llvm::Type *Int8PtrTy = 210 llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 211 212 const llvm::Type *BlockDescPtrTy = 213 llvm::PointerType::getUnqual(getBlockDescriptorType()); 214 215 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 216 getTypes().ConvertType(getContext().IntTy)); 217 218 // struct __block_literal_generic { 219 // void *__isa; 220 // int __flags; 221 // int __reserved; 222 // void (*__invoke)(void *); 223 // struct __block_descriptor *__descriptor; 224 // }; 225 GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy, 226 IntTy, 227 IntTy, 228 Int8PtrTy, 229 BlockDescPtrTy, 230 NULL); 231 232 // FIXME: See struct.__block_descriptor 233 getModule().addTypeName("struct.__block_literal_generic", 234 GenericBlockLiteralType); 235 236 return GenericBlockLiteralType; 237} 238 239const llvm::Type * 240CodeGenModule::getGenericExtendedBlockLiteralType() { 241 if (GenericExtendedBlockLiteralType) 242 return GenericExtendedBlockLiteralType; 243 244 const llvm::Type *Int8PtrTy = 245 llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 246 247 const llvm::Type *BlockDescPtrTy = 248 llvm::PointerType::getUnqual(getBlockDescriptorType()); 249 250 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 251 getTypes().ConvertType(getContext().IntTy)); 252 253 // struct __block_literal_generic { 254 // void *__isa; 255 // int __flags; 256 // int __reserved; 257 // void (*__invoke)(void *); 258 // struct __block_descriptor *__descriptor; 259 // void *__copy_func_helper_decl; 260 // void *__destroy_func_decl; 261 // }; 262 GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy, 263 IntTy, 264 IntTy, 265 Int8PtrTy, 266 BlockDescPtrTy, 267 Int8PtrTy, 268 Int8PtrTy, 269 NULL); 270 271 // FIXME: See struct.__block_descriptor 272 getModule().addTypeName("struct.__block_literal_extended_generic", 273 GenericExtendedBlockLiteralType); 274 275 return GenericExtendedBlockLiteralType; 276} 277 278/// getBlockFunctionType - Given a BlockPointerType, will return the 279/// function type for the block, including the first block literal argument. 280static QualType getBlockFunctionType(ASTContext &Ctx, 281 const BlockPointerType *BPT) { 282 const FunctionTypeProto *FTy = cast<FunctionTypeProto>(BPT->getPointeeType()); 283 284 llvm::SmallVector<QualType, 8> Types; 285 Types.push_back(Ctx.getPointerType(Ctx.VoidTy)); 286 287 for (FunctionTypeProto::arg_type_iterator i = FTy->arg_type_begin(), 288 e = FTy->arg_type_end(); i != e; ++i) 289 Types.push_back(*i); 290 291 return Ctx.getFunctionType(FTy->getResultType(), 292 &Types[0], Types.size(), 293 FTy->isVariadic(), 0); 294} 295 296RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { 297 const BlockPointerType *BPT = 298 E->getCallee()->getType()->getAsBlockPointerType(); 299 300 llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 301 302 // Get a pointer to the generic block literal. 303 const llvm::Type *BlockLiteralTy = 304 llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 305 306 // Bitcast the callee to a block literal. 307 llvm::Value *BlockLiteral = 308 Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 309 310 // Get the function pointer from the literal. 311 llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); 312 // FIXME: second argument should be false? 313 llvm::Value *Func = Builder.CreateLoad(FuncPtr, FuncPtr, "tmp"); 314 315 // Cast the function pointer to the right type. 316 const llvm::Type *BlockFTy = 317 ConvertType(getBlockFunctionType(getContext(), BPT)); 318 const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 319 Func = Builder.CreateBitCast(Func, BlockFTyPtr); 320 321 BlockLiteral = 322 Builder.CreateBitCast(BlockLiteral, 323 llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 324 "tmp"); 325 326 // Add the block literal. 327 QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); 328 CallArgList Args; 329 Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy)); 330 331 // And the rest of the arguments. 332 for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end(); 333 i != e; ++i) 334 Args.push_back(std::make_pair(EmitAnyExprToTemp(*i), 335 i->getType())); 336 337 // And call the block. 338 return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args), 339 Func, Args); 340} 341 342llvm::Constant * 343CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { 344 // Generate the block descriptor. 345 const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy); 346 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 347 getTypes().ConvertType(getContext().IntTy)); 348 349 llvm::Constant *DescriptorFields[2]; 350 351 // Reserved 352 DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy); 353 354 // Block literal size. For global blocks we just use the size of the generic 355 // block literal struct. 356 uint64_t BlockLiteralSize = 357 TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8; 358 DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); 359 360 llvm::Constant *DescriptorStruct = 361 llvm::ConstantStruct::get(&DescriptorFields[0], 2); 362 363 llvm::GlobalVariable *Descriptor = 364 new llvm::GlobalVariable(DescriptorStruct->getType(), true, 365 llvm::GlobalVariable::InternalLinkage, 366 DescriptorStruct, "__block_descriptor_global", 367 &getModule()); 368 369 // Generate the constants for the block literal. 370 llvm::Constant *LiteralFields[5]; 371 372 CodeGenFunction::BlockInfo Info(0, n); 373 uint64_t subBlockSize; 374 llvm::Function *Fn 375 = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize); 376 assert(subBlockSize == BlockLiteralSize 377 && "no imports allowed for global block"); 378 379 // isa 380 LiteralFields[0] = getNSConcreteGlobalBlock(); 381 382 // Flags 383 LiteralFields[1] = llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL); 384 385 // Reserved 386 LiteralFields[2] = llvm::Constant::getNullValue(IntTy); 387 388 // Function 389 LiteralFields[3] = Fn; 390 391 // Descriptor 392 LiteralFields[4] = Descriptor; 393 394 llvm::Constant *BlockLiteralStruct = 395 llvm::ConstantStruct::get(&LiteralFields[0], 5); 396 397 llvm::GlobalVariable *BlockLiteral = 398 new llvm::GlobalVariable(BlockLiteralStruct->getType(), true, 399 llvm::GlobalVariable::InternalLinkage, 400 BlockLiteralStruct, "__block_literal_global", 401 &getModule()); 402 403 return BlockLiteral; 404} 405 406llvm::Value *CodeGenFunction::LoadBlockStruct() { 407 return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self"); 408} 409 410llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, 411 const BlockInfo& Info, 412 uint64_t &Size) { 413 const FunctionTypeProto *FTy = 414 cast<FunctionTypeProto>(Expr->getFunctionType()); 415 416 FunctionArgList Args; 417 418 const BlockDecl *BD = Expr->getBlockDecl(); 419 420 // FIXME: This leaks 421 ImplicitParamDecl *SelfDecl = 422 ImplicitParamDecl::Create(getContext(), 0, 423 SourceLocation(), 0, 424 getContext().getPointerType(getContext().VoidTy)); 425 426 Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); 427 BlockStructDecl = SelfDecl; 428 429 for (BlockDecl::param_iterator i = BD->param_begin(), 430 e = BD->param_end(); i != e; ++i) 431 Args.push_back(std::make_pair(*i, (*i)->getType())); 432 433 const CGFunctionInfo &FI = 434 CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args); 435 436 std::string Name = std::string("__") + Info.Name + "_block_invoke_"; 437 CodeGenTypes &Types = CGM.getTypes(); 438 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic()); 439 440 llvm::Function *Fn = 441 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 442 Name, 443 &CGM.getModule()); 444 445 StartFunction(BD, FTy->getResultType(), Fn, Args, 446 Expr->getBody()->getLocEnd()); 447 EmitStmt(Expr->getBody()); 448 FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc()); 449 450 Size = BlockOffset; 451 452 return Fn; 453} 454