CGBlocks.cpp revision a91b5905755a9066576db16f1d3ac0ffb9e43e09
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// Temporary code to enable testing of __block variables 25// #include "clang/Frontend/CompileOptions.h" 26#include "llvm/Support/CommandLine.h" 27static llvm::cl::opt<bool> 28Enable__block("f__block", 29 // See all the FIXMEs for the various work that needs to be done 30 llvm::cl::desc("temporary option to turn on __block precessing " 31 "even though the code isn't done yet"), 32 llvm::cl::ValueDisallowed, llvm::cl::AllowInverse, 33 llvm::cl::ZeroOrMore, 34 llvm::cl::init(true)); 35 36llvm::Constant *CodeGenFunction:: 37BuildDescriptorBlockDecl(uint64_t Size, const llvm::StructType* Ty, 38 std::vector<HelperInfo> *NoteForHelper) { 39 const llvm::Type *UnsignedLongTy 40 = CGM.getTypes().ConvertType(getContext().UnsignedLongTy); 41 llvm::Constant *C; 42 std::vector<llvm::Constant*> Elts; 43 44 // reserved 45 C = llvm::ConstantInt::get(UnsignedLongTy, 0); 46 Elts.push_back(C); 47 48 // Size 49 // FIXME: What is the right way to say this doesn't fit? We should give 50 // a user diagnostic in that case. Better fix would be to change the 51 // API to size_t. 52 C = llvm::ConstantInt::get(UnsignedLongTy, Size); 53 Elts.push_back(C); 54 55 if (BlockHasCopyDispose) { 56 // copy_func_helper_decl 57 Elts.push_back(BuildCopyHelper(Ty, *NoteForHelper)); 58 59 // destroy_func_decl 60 Elts.push_back(BuildDestroyHelper(Ty, *NoteForHelper)); 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 *BlockModule::getNSConcreteGlobalBlock() { 72 if (NSConcreteGlobalBlock) 73 return NSConcreteGlobalBlock; 74 75 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the 76 // same thing as CreateRuntimeFunction if there's already a variable with the 77 // same name. 78 NSConcreteGlobalBlock 79 = new llvm::GlobalVariable(PtrToInt8Ty, false, 80 llvm::GlobalValue::ExternalLinkage, 81 0, "_NSConcreteGlobalBlock", 82 &getModule()); 83 84 return NSConcreteGlobalBlock; 85} 86 87llvm::Constant *BlockModule::getNSConcreteStackBlock() { 88 if (NSConcreteStackBlock) 89 return NSConcreteStackBlock; 90 91 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the 92 // same thing as CreateRuntimeFunction if there's already a variable with the 93 // same name. 94 NSConcreteStackBlock 95 = new llvm::GlobalVariable(PtrToInt8Ty, false, 96 llvm::GlobalValue::ExternalLinkage, 97 0, "_NSConcreteStackBlock", 98 &getModule()); 99 100 return NSConcreteStackBlock; 101} 102 103static void CollectBlockDeclRefInfo(const Stmt *S, 104 CodeGenFunction::BlockInfo &Info) { 105 for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); 106 I != E; ++I) 107 if (*I) 108 CollectBlockDeclRefInfo(*I, Info); 109 110 if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) { 111 // FIXME: Handle enums. 112 if (isa<FunctionDecl>(DE->getDecl())) 113 return; 114 115 if (DE->isByRef()) 116 Info.ByRefDeclRefs.push_back(DE); 117 else 118 Info.ByCopyDeclRefs.push_back(DE); 119 } 120} 121 122/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be 123/// declared as a global variable instead of on the stack. 124static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) 125{ 126 return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty(); 127} 128 129// FIXME: Push most into CGM, passing down a few bits, like current function 130// name. 131llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { 132 133 std::string Name = CurFn->getName(); 134 CodeGenFunction::BlockInfo Info(0, Name.c_str()); 135 CollectBlockDeclRefInfo(BE->getBody(), Info); 136 137 // Check if the block can be global. 138 // FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like 139 // to just have one code path. We should move this function into CGM and pass 140 // CGF, then we can just check to see if CGF is 0. 141 if (0 && CanBlockBeGlobal(Info)) 142 return CGM.GetAddrOfGlobalBlock(BE, Name.c_str()); 143 144 std::vector<llvm::Constant*> Elts(5); 145 llvm::Constant *C; 146 llvm::Value *V; 147 148 { 149 // C = BuildBlockStructInitlist(); 150 unsigned int flags = BLOCK_HAS_DESCRIPTOR; 151 152 // We run this first so that we set BlockHasCopyDispose from the entire 153 // block literal. 154 // __invoke 155 uint64_t subBlockSize, subBlockAlign; 156 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; 157 llvm::Function *Fn 158 = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize, 159 subBlockAlign, 160 subBlockDeclRefDecls, 161 BlockHasCopyDispose); 162 Elts[3] = Fn; 163 164 if (!Enable__block && BlockHasCopyDispose) 165 ErrorUnsupported(BE, "block literal that requires copy/dispose"); 166 167 if (BlockHasCopyDispose) 168 flags |= BLOCK_HAS_COPY_DISPOSE; 169 170 // __isa 171 C = CGM.getNSConcreteStackBlock(); 172 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); 173 Elts[0] = C; 174 175 // __flags 176 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 177 CGM.getTypes().ConvertType(CGM.getContext().IntTy)); 178 C = llvm::ConstantInt::get(IntTy, flags); 179 Elts[1] = C; 180 181 // __reserved 182 C = llvm::ConstantInt::get(IntTy, 0); 183 Elts[2] = C; 184 185 if (subBlockDeclRefDecls.size() == 0) { 186 // __descriptor 187 Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0, 0); 188 189 // Optimize to being a global block. 190 Elts[0] = CGM.getNSConcreteGlobalBlock(); 191 Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL); 192 193 C = llvm::ConstantStruct::get(Elts); 194 195 char Name[32]; 196 sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount()); 197 C = new llvm::GlobalVariable(C->getType(), true, 198 llvm::GlobalValue::InternalLinkage, 199 C, Name, &CGM.getModule()); 200 QualType BPT = BE->getType(); 201 C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT)); 202 return C; 203 } 204 205 std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size()); 206 for (int i=0; i<4; ++i) 207 Types[i] = Elts[i]->getType(); 208 Types[4] = PtrToInt8Ty; 209 210 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) { 211 const Expr *E = subBlockDeclRefDecls[i]; 212 const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); 213 QualType Ty = E->getType(); 214 if (BDRE && BDRE->isByRef()) { 215 uint64_t Align = getContext().getDeclAlignInBytes(BDRE->getDecl()); 216 Types[i+5] = llvm::PointerType::get(BuildByRefType(Ty, Align), 0); 217 } else 218 Types[i+5] = ConvertType(Ty); 219 } 220 221 llvm::StructType *Ty = llvm::StructType::get(Types, true); 222 223 llvm::AllocaInst *A = CreateTempAlloca(Ty); 224 A->setAlignment(subBlockAlign); 225 V = A; 226 227 std::vector<HelperInfo> NoteForHelper(subBlockDeclRefDecls.size()); 228 int helpersize = 0; 229 230 for (unsigned i=0; i<4; ++i) 231 Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp")); 232 233 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) 234 { 235 // FIXME: Push const down. 236 Expr *E = const_cast<Expr*>(subBlockDeclRefDecls[i]); 237 DeclRefExpr *DR; 238 ValueDecl *VD; 239 240 DR = dyn_cast<DeclRefExpr>(E); 241 // Skip padding. 242 if (DR) continue; 243 244 BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); 245 VD = BDRE->getDecl(); 246 247 llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp"); 248 NoteForHelper[helpersize].index = i+5; 249 NoteForHelper[helpersize].RequiresCopying = BlockRequiresCopying(VD->getType()); 250 NoteForHelper[helpersize].flag 251 = VD->getType()->isBlockPointerType() ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT; 252 253 if (LocalDeclMap[VD]) { 254 if (BDRE->isByRef()) { 255 // FIXME: For only local, or all byrefs? 256 NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | 257 // FIXME: Someone double check this. 258 (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0); 259 const llvm::Type *Ty = Types[i+5]; 260 llvm::Value *Loc = LocalDeclMap[VD]; 261 Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); 262 Loc = Builder.CreateLoad(Loc, false); 263 Loc = Builder.CreateBitCast(Loc, Ty); 264 Builder.CreateStore(Loc, Addr); 265 ++helpersize; 266 continue; 267 } else 268 E = new (getContext()) DeclRefExpr (cast<NamedDecl>(VD), 269 VD->getType(), SourceLocation(), 270 false, false); 271 } 272 if (BDRE->isByRef()) { 273 E = new (getContext()) 274 UnaryOperator(E, UnaryOperator::AddrOf, 275 getContext().getPointerType(E->getType()), 276 SourceLocation()); 277 } 278 ++helpersize; 279 280 RValue r = EmitAnyExpr(E, Addr, false); 281 if (r.isScalar()) { 282 llvm::Value *Loc = r.getScalarVal(); 283 const llvm::Type *Ty = Types[i+5]; 284 if (BDRE->isByRef()) { 285 // E is now the address of the value field, instead, we want the 286 // address of the actual ByRef struct. We optimize this slightly 287 // compared to gcc by not grabbing the forwarding slot as this must 288 // be done during Block_copy for us, and we can postpone the work 289 // until then. 290 uint64_t offset = BlockDecls[BDRE->getDecl()]; 291 292 llvm::Value *BlockLiteral = LoadBlockStruct(); 293 294 Loc = Builder.CreateGEP(BlockLiteral, 295 llvm::ConstantInt::get(llvm::Type::Int64Ty, 296 offset), 297 "block.literal"); 298 Ty = llvm::PointerType::get(Ty, 0); 299 Loc = Builder.CreateBitCast(Loc, Ty); 300 Loc = Builder.CreateLoad(Loc, false); 301 // Loc = Builder.CreateBitCast(Loc, Ty); 302 } 303 Builder.CreateStore(Loc, Addr); 304 } else if (r.isComplex()) 305 // FIXME: implement 306 ErrorUnsupported(BE, "complex in block literal"); 307 else if (r.isAggregate()) 308 ; // Already created into the destination 309 else 310 assert (0 && "bad block variable"); 311 // FIXME: Ensure that the offset created by the backend for 312 // the struct matches the previously computed offset in BlockDecls. 313 } 314 NoteForHelper.resize(helpersize); 315 316 // __descriptor 317 llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockSize, Ty, 318 &NoteForHelper); 319 Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty); 320 Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp")); 321 } 322 323 QualType BPT = BE->getType(); 324 return Builder.CreateBitCast(V, ConvertType(BPT)); 325} 326 327 328const llvm::Type *BlockModule::getBlockDescriptorType() { 329 if (BlockDescriptorType) 330 return BlockDescriptorType; 331 332 const llvm::Type *UnsignedLongTy = 333 getTypes().ConvertType(getContext().UnsignedLongTy); 334 335 // struct __block_descriptor { 336 // unsigned long reserved; 337 // unsigned long block_size; 338 // }; 339 BlockDescriptorType = llvm::StructType::get(UnsignedLongTy, 340 UnsignedLongTy, 341 NULL); 342 343 getModule().addTypeName("struct.__block_descriptor", 344 BlockDescriptorType); 345 346 return BlockDescriptorType; 347} 348 349const llvm::Type *BlockModule::getGenericBlockLiteralType() { 350 if (GenericBlockLiteralType) 351 return GenericBlockLiteralType; 352 353 const llvm::Type *BlockDescPtrTy = 354 llvm::PointerType::getUnqual(getBlockDescriptorType()); 355 356 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 357 getTypes().ConvertType(getContext().IntTy)); 358 359 // struct __block_literal_generic { 360 // void *__isa; 361 // int __flags; 362 // int __reserved; 363 // void (*__invoke)(void *); 364 // struct __block_descriptor *__descriptor; 365 // }; 366 GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, 367 IntTy, 368 IntTy, 369 PtrToInt8Ty, 370 BlockDescPtrTy, 371 NULL); 372 373 getModule().addTypeName("struct.__block_literal_generic", 374 GenericBlockLiteralType); 375 376 return GenericBlockLiteralType; 377} 378 379const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { 380 if (GenericExtendedBlockLiteralType) 381 return GenericExtendedBlockLiteralType; 382 383 const llvm::Type *BlockDescPtrTy = 384 llvm::PointerType::getUnqual(getBlockDescriptorType()); 385 386 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 387 getTypes().ConvertType(getContext().IntTy)); 388 389 // struct __block_literal_generic { 390 // void *__isa; 391 // int __flags; 392 // int __reserved; 393 // void (*__invoke)(void *); 394 // struct __block_descriptor *__descriptor; 395 // void *__copy_func_helper_decl; 396 // void *__destroy_func_decl; 397 // }; 398 GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, 399 IntTy, 400 IntTy, 401 PtrToInt8Ty, 402 BlockDescPtrTy, 403 PtrToInt8Ty, 404 PtrToInt8Ty, 405 NULL); 406 407 getModule().addTypeName("struct.__block_literal_extended_generic", 408 GenericExtendedBlockLiteralType); 409 410 return GenericExtendedBlockLiteralType; 411} 412 413/// getBlockFunctionType - Given a BlockPointerType, will return the 414/// function type for the block, including the first block literal argument. 415static QualType getBlockFunctionType(ASTContext &Ctx, 416 const BlockPointerType *BPT) { 417 const FunctionProtoType *FTy = cast<FunctionProtoType>(BPT->getPointeeType()); 418 419 llvm::SmallVector<QualType, 8> Types; 420 Types.push_back(Ctx.getPointerType(Ctx.VoidTy)); 421 422 for (FunctionProtoType::arg_type_iterator i = FTy->arg_type_begin(), 423 e = FTy->arg_type_end(); i != e; ++i) 424 Types.push_back(*i); 425 426 return Ctx.getFunctionType(FTy->getResultType(), 427 &Types[0], Types.size(), 428 FTy->isVariadic(), 0); 429} 430 431RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { 432 const BlockPointerType *BPT = 433 E->getCallee()->getType()->getAsBlockPointerType(); 434 435 llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 436 437 // Get a pointer to the generic block literal. 438 const llvm::Type *BlockLiteralTy = 439 llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 440 441 // Bitcast the callee to a block literal. 442 llvm::Value *BlockLiteral = 443 Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 444 445 // Get the function pointer from the literal. 446 llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); 447 llvm::Value *Func = Builder.CreateLoad(FuncPtr, false, "tmp"); 448 449 // Cast the function pointer to the right type. 450 const llvm::Type *BlockFTy = 451 ConvertType(getBlockFunctionType(getContext(), BPT)); 452 const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 453 Func = Builder.CreateBitCast(Func, BlockFTyPtr); 454 455 BlockLiteral = 456 Builder.CreateBitCast(BlockLiteral, 457 llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 458 "tmp"); 459 460 // Add the block literal. 461 QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); 462 CallArgList Args; 463 Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy)); 464 465 // And the rest of the arguments. 466 for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end(); 467 i != e; ++i) 468 Args.push_back(std::make_pair(EmitAnyExprToTemp(*i), 469 i->getType())); 470 471 // And call the block. 472 return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args), 473 Func, Args); 474} 475 476llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { 477 uint64_t &offset = BlockDecls[E->getDecl()]; 478 479 const llvm::Type *Ty; 480 Ty = CGM.getTypes().ConvertType(E->getDecl()->getType()); 481 482 if (!Enable__block && E->isByRef()) 483 ErrorUnsupported(E, "__block variable in block literal"); 484 else if (!Enable__block && E->getType()->isBlockPointerType()) 485 ErrorUnsupported(E, "block pointer in block literal"); 486 else if (!Enable__block && (E->getDecl()->getAttr<ObjCNSObjectAttr>() || 487 getContext().isObjCNSObjectType(E->getType()))) 488 ErrorUnsupported(E, "__attribute__((NSObject)) variable in block " 489 "literal"); 490 else if (!Enable__block && getContext().isObjCObjectPointerType(E->getType())) 491 ErrorUnsupported(E, "Objective-C variable in block literal"); 492 493 // See if we have already allocated an offset for this variable. 494 if (offset == 0) { 495 // Don't run the expensive check, unless we have to. 496 if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType())) 497 BlockHasCopyDispose = true; 498 // if not, allocate one now. 499 offset = getBlockOffset(E); 500 } 501 502 llvm::Value *BlockLiteral = LoadBlockStruct(); 503 llvm::Value *V = Builder.CreateGEP(BlockLiteral, 504 llvm::ConstantInt::get(llvm::Type::Int64Ty, 505 offset), 506 "block.literal"); 507 if (E->isByRef()) { 508 bool needsCopyDispose = BlockRequiresCopying(E->getType()); 509 uint64_t Align = getContext().getDeclAlignInBytes(E->getDecl()); 510 const llvm::Type *PtrStructTy 511 = llvm::PointerType::get(BuildByRefType(E->getType(), Align), 0); 512 Ty = PtrStructTy; 513 Ty = llvm::PointerType::get(Ty, 0); 514 V = Builder.CreateBitCast(V, Ty); 515 V = Builder.CreateLoad(V, false); 516 V = Builder.CreateStructGEP(V, 1, "forwarding"); 517 V = Builder.CreateLoad(V, false); 518 V = Builder.CreateBitCast(V, PtrStructTy); 519 V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x"); 520 } else { 521 Ty = llvm::PointerType::get(Ty, 0); 522 V = Builder.CreateBitCast(V, Ty); 523 } 524 return V; 525} 526 527llvm::Constant * 528BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { 529 // Generate the block descriptor. 530 const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy); 531 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( 532 getTypes().ConvertType(getContext().IntTy)); 533 534 llvm::Constant *DescriptorFields[2]; 535 536 // Reserved 537 DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy); 538 539 // Block literal size. For global blocks we just use the size of the generic 540 // block literal struct. 541 uint64_t BlockLiteralSize = 542 TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8; 543 DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); 544 545 llvm::Constant *DescriptorStruct = 546 llvm::ConstantStruct::get(&DescriptorFields[0], 2); 547 548 llvm::GlobalVariable *Descriptor = 549 new llvm::GlobalVariable(DescriptorStruct->getType(), true, 550 llvm::GlobalVariable::InternalLinkage, 551 DescriptorStruct, "__block_descriptor_global", 552 &getModule()); 553 554 // Generate the constants for the block literal. 555 llvm::Constant *LiteralFields[5]; 556 557 CodeGenFunction::BlockInfo Info(0, n); 558 uint64_t subBlockSize, subBlockAlign; 559 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; 560 bool subBlockHasCopyDispose; 561 llvm::Function *Fn 562 = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize, 563 subBlockAlign, 564 subBlockDeclRefDecls, 565 subBlockHasCopyDispose); 566 assert(subBlockSize == BlockLiteralSize 567 && "no imports allowed for global block"); 568 // FIXME: This causes a failure on clang-i686-linux, not sure why, 569 // disable for now. 570 // assert(!subBlockHasCopyDispose && "no imports allowed for global block"); 571 572 // isa 573 LiteralFields[0] = getNSConcreteGlobalBlock(); 574 575 // Flags 576 LiteralFields[1] = 577 llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR); 578 579 // Reserved 580 LiteralFields[2] = llvm::Constant::getNullValue(IntTy); 581 582 // Function 583 LiteralFields[3] = Fn; 584 585 // Descriptor 586 LiteralFields[4] = Descriptor; 587 588 llvm::Constant *BlockLiteralStruct = 589 llvm::ConstantStruct::get(&LiteralFields[0], 5); 590 591 llvm::GlobalVariable *BlockLiteral = 592 new llvm::GlobalVariable(BlockLiteralStruct->getType(), true, 593 llvm::GlobalVariable::InternalLinkage, 594 BlockLiteralStruct, "__block_literal_global", 595 &getModule()); 596 597 return BlockLiteral; 598} 599 600llvm::Value *CodeGenFunction::LoadBlockStruct() { 601 return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self"); 602} 603 604llvm::Function * 605CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, 606 const BlockInfo& Info, 607 uint64_t &Size, 608 uint64_t &Align, 609 llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls, 610 bool &subBlockHasCopyDispose) { 611 const FunctionProtoType *FTy = 612 cast<FunctionProtoType>(BExpr->getFunctionType()); 613 614 FunctionArgList Args; 615 616 const BlockDecl *BD = BExpr->getBlockDecl(); 617 618 // FIXME: This leaks 619 ImplicitParamDecl *SelfDecl = 620 ImplicitParamDecl::Create(getContext(), 0, 621 SourceLocation(), 0, 622 getContext().getPointerType(getContext().VoidTy)); 623 624 Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); 625 BlockStructDecl = SelfDecl; 626 627 for (BlockDecl::param_iterator i = BD->param_begin(), 628 e = BD->param_end(); i != e; ++i) 629 Args.push_back(std::make_pair(*i, (*i)->getType())); 630 631 const CGFunctionInfo &FI = 632 CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args); 633 634 std::string Name = std::string("__") + Info.Name + "_block_invoke_"; 635 CodeGenTypes &Types = CGM.getTypes(); 636 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic()); 637 638 llvm::Function *Fn = 639 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 640 Name, 641 &CGM.getModule()); 642 643 StartFunction(BD, FTy->getResultType(), Fn, Args, 644 BExpr->getBody()->getLocEnd()); 645 EmitStmt(BExpr->getBody()); 646 FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc()); 647 648 // The runtime needs a minimum alignment of a void *. 649 uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8; 650 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign); 651 652 Size = BlockOffset; 653 Align = BlockAlign; 654 subBlockDeclRefDecls = BlockDeclRefDecls; 655 subBlockHasCopyDispose |= BlockHasCopyDispose; 656 return Fn; 657} 658 659uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { 660 const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl()); 661 662 uint64_t Size = getContext().getTypeSize(D->getType()) / 8; 663 uint64_t Align = getContext().getDeclAlignInBytes(D); 664 665 if (BDRE->isByRef()) { 666 Size = getContext().getTypeSize(getContext().VoidPtrTy) / 8; 667 Align = getContext().getTypeAlign(getContext().VoidPtrTy) / 8; 668 } 669 670 assert ((Align > 0) && "alignment must be 1 byte or more"); 671 672 uint64_t OldOffset = BlockOffset; 673 674 // Ensure proper alignment, even if it means we have to have a gap 675 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align); 676 BlockAlign = std::max(Align, BlockAlign); 677 678 uint64_t Pad = BlockOffset - OldOffset; 679 if (Pad) { 680 llvm::ArrayType::get(llvm::Type::Int8Ty, Pad); 681 QualType PadTy = getContext().getConstantArrayType(getContext().CharTy, 682 llvm::APInt(32, Pad), 683 ArrayType::Normal, 0); 684 ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(), 685 0, QualType(PadTy), VarDecl::None, 686 SourceLocation()); 687 Expr *E; 688 E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(), 689 SourceLocation(), false, false); 690 BlockDeclRefDecls.push_back(E); 691 } 692 BlockDeclRefDecls.push_back(BDRE); 693 694 BlockOffset += Size; 695 return BlockOffset-Size; 696} 697 698llvm::Constant *BlockFunction:: 699GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, 700 std::vector<HelperInfo> &NoteForHelper) { 701 QualType R = getContext().VoidTy; 702 703 FunctionArgList Args; 704 // FIXME: This leaks 705 ImplicitParamDecl *Dst = 706 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 707 getContext().getPointerType(getContext().VoidTy)); 708 Args.push_back(std::make_pair(Dst, Dst->getType())); 709 ImplicitParamDecl *Src = 710 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 711 getContext().getPointerType(getContext().VoidTy)); 712 Args.push_back(std::make_pair(Src, Src->getType())); 713 714 const CGFunctionInfo &FI = 715 CGM.getTypes().getFunctionInfo(R, Args); 716 717 std::string Name = std::string("__copy_helper_block_"); 718 CodeGenTypes &Types = CGM.getTypes(); 719 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 720 721 llvm::Function *Fn = 722 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 723 Name, 724 &CGM.getModule()); 725 726 IdentifierInfo *II 727 = &CGM.getContext().Idents.get("__copy_helper_block_"); 728 729 FunctionDecl *FD = FunctionDecl::Create(getContext(), 730 getContext().getTranslationUnitDecl(), 731 SourceLocation(), II, R, 732 FunctionDecl::Static, false, 733 true); 734 CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); 735 736 llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src); 737 llvm::Type *PtrPtrT; 738 PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0); 739 SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT); 740 SrcObj = Builder.CreateLoad(SrcObj); 741 742 llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst); 743 DstObj = Builder.CreateBitCast(DstObj, llvm::PointerType::get(T, 0)); 744 745 for (unsigned i=0; i < NoteForHelper.size(); ++i) { 746 int flag = NoteForHelper[i].flag; 747 int index = NoteForHelper[i].index; 748 749 if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) 750 || NoteForHelper[i].RequiresCopying) { 751 llvm::Value *Srcv = SrcObj; 752 Srcv = Builder.CreateStructGEP(Srcv, index); 753 Srcv = Builder.CreateBitCast(Srcv, 754 llvm::PointerType::get(PtrToInt8Ty, 0)); 755 Srcv = Builder.CreateLoad(Srcv); 756 757 llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index); 758 Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty); 759 760 llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); 761 llvm::Value *F = getBlockObjectAssign(); 762 Builder.CreateCall3(F, Dstv, Srcv, N); 763 } 764 } 765 766 CGF.FinishFunction(); 767 768 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); 769} 770 771llvm::Constant *BlockFunction:: 772GenerateDestroyHelperFunction(bool BlockHasCopyDispose, 773 const llvm::StructType* T, 774 std::vector<HelperInfo> &NoteForHelper) { 775 QualType R = getContext().VoidTy; 776 777 FunctionArgList Args; 778 // FIXME: This leaks 779 ImplicitParamDecl *Src = 780 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 781 getContext().getPointerType(getContext().VoidTy)); 782 783 Args.push_back(std::make_pair(Src, Src->getType())); 784 785 const CGFunctionInfo &FI = 786 CGM.getTypes().getFunctionInfo(R, Args); 787 788 std::string Name = std::string("__destroy_helper_block_"); 789 CodeGenTypes &Types = CGM.getTypes(); 790 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 791 792 llvm::Function *Fn = 793 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 794 Name, 795 &CGM.getModule()); 796 797 IdentifierInfo *II 798 = &CGM.getContext().Idents.get("__destroy_helper_block_"); 799 800 FunctionDecl *FD = FunctionDecl::Create(getContext(), 801 getContext().getTranslationUnitDecl(), 802 SourceLocation(), II, R, 803 FunctionDecl::Static, false, 804 true); 805 CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); 806 807 llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src); 808 llvm::Type *PtrPtrT; 809 PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0); 810 SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT); 811 SrcObj = Builder.CreateLoad(SrcObj); 812 813 for (unsigned i=0; i < NoteForHelper.size(); ++i) { 814 int flag = NoteForHelper[i].flag; 815 int index = NoteForHelper[i].index; 816 817 if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) 818 || NoteForHelper[i].RequiresCopying) { 819 llvm::Value *Srcv = SrcObj; 820 Srcv = Builder.CreateStructGEP(Srcv, index); 821 Srcv = Builder.CreateBitCast(Srcv, 822 llvm::PointerType::get(PtrToInt8Ty, 0)); 823 Srcv = Builder.CreateLoad(Srcv); 824 825 BuildBlockRelease(Srcv, flag); 826 } 827 } 828 829 CGF.FinishFunction(); 830 831 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); 832} 833 834llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T, 835 std::vector<HelperInfo> &NoteForHelper) { 836 return CodeGenFunction(CGM).GenerateCopyHelperFunction(BlockHasCopyDispose, 837 T, NoteForHelper); 838} 839 840llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T, 841 std::vector<HelperInfo> &NoteForHelper) { 842 return CodeGenFunction(CGM).GenerateDestroyHelperFunction(BlockHasCopyDispose, 843 T, NoteForHelper); 844} 845 846llvm::Constant *BlockFunction:: 847GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { 848 QualType R = getContext().VoidTy; 849 850 FunctionArgList Args; 851 // FIXME: This leaks 852 ImplicitParamDecl *Dst = 853 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 854 getContext().getPointerType(getContext().VoidTy)); 855 Args.push_back(std::make_pair(Dst, Dst->getType())); 856 857 // FIXME: This leaks 858 ImplicitParamDecl *Src = 859 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 860 getContext().getPointerType(getContext().VoidTy)); 861 Args.push_back(std::make_pair(Src, Src->getType())); 862 863 const CGFunctionInfo &FI = 864 CGM.getTypes().getFunctionInfo(R, Args); 865 866 std::string Name = std::string("__Block_byref_id_object_copy_"); 867 CodeGenTypes &Types = CGM.getTypes(); 868 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 869 870 llvm::Function *Fn = 871 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 872 Name, 873 &CGM.getModule()); 874 875 IdentifierInfo *II 876 = &CGM.getContext().Idents.get("__Block_byref_id_object_copy_"); 877 878 FunctionDecl *FD = FunctionDecl::Create(getContext(), 879 getContext().getTranslationUnitDecl(), 880 SourceLocation(), II, R, 881 FunctionDecl::Static, false, 882 true); 883 CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); 884 885 // dst->x 886 llvm::Value *V = CGF.GetAddrOfLocalVar(Dst); 887 V = Builder.CreateBitCast(V, T); 888 V = Builder.CreateStructGEP(V, 6, "x"); 889 llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty); 890 891 // src->x 892 V = CGF.GetAddrOfLocalVar(Src); 893 V = Builder.CreateLoad(V); 894 V = Builder.CreateBitCast(V, T); 895 V = Builder.CreateStructGEP(V, 6, "x"); 896 V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); 897 llvm::Value *SrcObj = Builder.CreateLoad(V); 898 899 flag |= BLOCK_BYREF_CALLER; 900 901 llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); 902 llvm::Value *F = getBlockObjectAssign(); 903 Builder.CreateCall3(F, DstObj, SrcObj, N); 904 905 CGF.FinishFunction(); 906 907 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); 908} 909 910llvm::Constant * 911BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, 912 int flag) { 913 QualType R = getContext().VoidTy; 914 915 FunctionArgList Args; 916 // FIXME: This leaks 917 ImplicitParamDecl *Src = 918 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 919 getContext().getPointerType(getContext().VoidTy)); 920 921 Args.push_back(std::make_pair(Src, Src->getType())); 922 923 const CGFunctionInfo &FI = 924 CGM.getTypes().getFunctionInfo(R, Args); 925 926 std::string Name = std::string("__Block_byref_id_object_dispose_"); 927 CodeGenTypes &Types = CGM.getTypes(); 928 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 929 930 llvm::Function *Fn = 931 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 932 Name, 933 &CGM.getModule()); 934 935 IdentifierInfo *II 936 = &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_"); 937 938 FunctionDecl *FD = FunctionDecl::Create(getContext(), 939 getContext().getTranslationUnitDecl(), 940 SourceLocation(), II, R, 941 FunctionDecl::Static, false, 942 true); 943 CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); 944 945 llvm::Value *V = CGF.GetAddrOfLocalVar(Src); 946 V = Builder.CreateBitCast(V, T); 947 V = Builder.CreateStructGEP(V, 6, "x"); 948 V = Builder.CreateBitCast(V, PtrToInt8Ty); 949 950 flag |= BLOCK_BYREF_CALLER; 951 BuildBlockRelease(V, flag); 952 CGF.FinishFunction(); 953 954 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); 955} 956 957llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T, 958 int flag) { 959 return CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag); 960} 961 962llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T, 963 int flag) { 964 return CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag); 965} 966 967llvm::Value *BlockFunction::getBlockObjectDispose() { 968 if (CGM.BlockObjectDispose == 0) { 969 const llvm::FunctionType *FTy; 970 std::vector<const llvm::Type*> ArgTys; 971 const llvm::Type *ResultType = llvm::Type::VoidTy; 972 ArgTys.push_back(PtrToInt8Ty); 973 ArgTys.push_back(llvm::Type::Int32Ty); 974 FTy = llvm::FunctionType::get(ResultType, ArgTys, false); 975 CGM.BlockObjectDispose 976 = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose"); 977 } 978 return CGM.BlockObjectDispose; 979} 980 981llvm::Value *BlockFunction::getBlockObjectAssign() { 982 if (CGM.BlockObjectAssign == 0) { 983 const llvm::FunctionType *FTy; 984 std::vector<const llvm::Type*> ArgTys; 985 const llvm::Type *ResultType = llvm::Type::VoidTy; 986 ArgTys.push_back(PtrToInt8Ty); 987 ArgTys.push_back(PtrToInt8Ty); 988 ArgTys.push_back(llvm::Type::Int32Ty); 989 FTy = llvm::FunctionType::get(ResultType, ArgTys, false); 990 CGM.BlockObjectAssign 991 = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign"); 992 } 993 return CGM.BlockObjectAssign; 994} 995 996void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) { 997 llvm::Value *F = getBlockObjectDispose(); 998 llvm::Value *N; 999 V = Builder.CreateBitCast(V, PtrToInt8Ty); 1000 N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); 1001 Builder.CreateCall2(F, V, N); 1002} 1003 1004ASTContext &BlockFunction::getContext() const { return CGM.getContext(); } 1005 1006BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, 1007 CGBuilderTy &B) 1008 : CGM(cgm), CGF(cgf), Builder(B) { 1009 PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 1010 1011 BlockHasCopyDispose = false; 1012} 1013