clang: lib/CodeGen/CGBlocks.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25#include "llvm/IR/DataLayout.h"

26#include "llvm/IR/Module.h"

27#include "llvm/Support/ScopedPrinter.h"

28#include

29#include

30

31using namespace clang;

32using namespace CodeGen;

33

35 : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),

37 HasCapturedVariableLayout(false), CapturesNonExternalType(false),

38 LocalAddress(RawAddress::invalid()), StructureType(nullptr),

40

41

42

43 if (!name.empty() && name[0] == '\01')

44 name = name.substr(1);

45}

46

47

49

50

53 llvm::Constant *blockFn);

54

55

59}

60

61

65}

66

67namespace {

68

69enum class CaptureStrKind {

70

71 CopyHelper,

72

73 DisposeHelper,

74

75 Merged

76};

77

78}

79

81 CaptureStrKind StrKind,

84

87 std::string Name = "__block_descriptor_";

89

92 Name += "e";

94 Name += "a";

96

98 if (Cap.isConstantOrTrivial())

99 continue;

100

101 Name += llvm::to_string(Cap.getOffset().getQuantity());

102

103 if (Cap.CopyKind == Cap.DisposeKind) {

104

105

107 "shouldn't see BlockCaptureManagedEntity that is None");

110 } else {

111

112

113

118 }

119 }

120 Name += "_";

121 }

122

123 std::string TypeAtEncoding;

124

125 if (!CGM.getCodeGenOpts().DisableBlockSignatureString) {

126 TypeAtEncoding =

128

129

130 std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');

131 }

132 Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;

134 return Name;

135}

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

154

155 llvm::IntegerType *ulong =

157 llvm::PointerType *i8p = nullptr;

159 i8p = llvm::PointerType::get(

161 else

163

164 std::string descName;

165

166

167 if (C.getLangOpts().ObjC &&

170 if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName))

171 return desc;

172 }

173

174

175

178

179

180 elements.addInt(ulong, 0);

181

182

183

184

185

187

188

189 bool hasInternalHelper = false;

191

192 llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);

193 elements.add(copyHelper);

194

195

197 elements.add(disposeHelper);

198

199 if (castllvm::Function(copyHelper->stripPointerCasts())

200 ->hasInternalLinkage() ||

201 castllvm::Function(disposeHelper->stripPointerCasts())

202 ->hasInternalLinkage())

203 hasInternalHelper = true;

204 }

205

206

207 if (CGM.getCodeGenOpts().DisableBlockSignatureString) {

208 elements.addNullPointer(i8p);

209 } else {

210 std::string typeAtEncoding =

213 }

214

215

216 if (C.getLangOpts().ObjC) {

219 else

221 }

222 else

223 elements.addNullPointer(i8p);

224

225 unsigned AddrSpace = 0;

226 if (C.getLangOpts().OpenCL)

228

229 llvm::GlobalValue::LinkageTypes linkage;

230 if (descName.empty()) {

231 linkage = llvm::GlobalValue::InternalLinkage;

232 descName = "__block_descriptor_tmp";

233 } else if (hasInternalHelper) {

234

235

236 linkage = llvm::GlobalValue::InternalLinkage;

237 } else {

238 linkage = llvm::GlobalValue::LinkOnceODRLinkage;

239 }

240

241 llvm::GlobalVariable *global =

242 elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(),

243 true, linkage, AddrSpace);

244

245 if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) {

247 global->setComdat(CGM.getModule().getOrInsertComdat(descName));

248 global->setVisibility(llvm::GlobalValue::HiddenVisibility);

249 global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

250 }

251

252 return global;

253}

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268 struct objc_class *isa;

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290 int flags;

291

292

293 int reserved;

294

295

296 _ResultType (*invoke)(Block_literal *, _ParamTypes...);

297

298

299 struct Block_descriptor *block_descriptor;

300

301

302 _CapturesTypes captures...;

303 };

304 */

305

306namespace {

307

308 struct BlockLayoutChunk {

312 llvm::Type *Type;

316

324 FieldType(fieldType), CopyKind(CopyKind), DisposeKind(DisposeKind),

325 CopyFlags(CopyFlags), DisposeFlags(DisposeFlags) {}

326

327

332 } else {

334 index, offset, FieldType, CopyKind, CopyFlags, DisposeKind,

336 }

337 }

338

340 return CopyKind == BlockCaptureEntityKind::None &&

341 DisposeKind == BlockCaptureEntityKind::None;

342 }

343 };

344

345

346

347

348 bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {

349 if (left.Alignment != right.Alignment)

350 return left.Alignment > right.Alignment;

351

352 auto getPrefOrder = [](const BlockLayoutChunk &chunk) {

353 switch (chunk.CopyKind) {

355 return 0;

357 switch (chunk.CopyFlags.getBitMask()) {

359 return 0;

361 return 1;

363 return 2;

364 default:

365 break;

366 }

367 break;

369 return 3;

370 default:

371 break;

372 }

373 return 4;

374 };

375

376 return getPrefOrder(left) < getPrefOrder(right);

377 }

378}

379

380static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

383

384static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

387

393 if (!capture) {

394

395 Layout.push_back(BlockLayoutChunk(

398 return;

399 }

400

404

405 std::tie(CopyKind, CopyFlags) =

407 std::tie(DisposeKind, DisposeFlags) =

409 Layout.push_back(BlockLayoutChunk(align, size, capture, type, fieldType,

410 CopyKind, CopyFlags, DisposeKind,

411 DisposeFlags));

412

414 return;

415

416 if (!Layout.back().isTrivial())

418}

419

420

423 type->getBaseElementTypeUnsafe()->getAs<RecordType>();

424

425

427

428 const auto *record = cast(recordType->getDecl());

429

430

431 if (!record->hasTrivialDestructor()) return false;

432 if (record->hasNonTrivialCopyConstructor()) return false;

433

434

435

436 return !record->hasMutableFields();

437}

438

439

440

441

442

443

444

448

449

450 if (isa(var))

451 return nullptr;

452

454

455

456 if (type.isConstQualified()) return nullptr;

457

458

459

460

461

462

464 return nullptr;

465

466

467

468

469 const Expr *init = var->getInit();

470 if (!init) return nullptr;

471

473}

474

475

476

479}

480

483

484 assert(elementTypes.empty());

486

487

492 assert(CGM.getIntSize() <= GenPtrSize);

493 assert(CGM.getIntAlign() <= GenPtrAlign);

494 assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));

495 elementTypes.push_back(CGM.IntTy);

496 elementTypes.push_back(CGM.IntTy);

497 elementTypes.push_back(

500 unsigned Offset =

502 unsigned BlockAlign = GenPtrAlign.getQuantity();

503 if (auto *Helper =

505 for (auto *I : Helper->getCustomFieldTypes()) {

506

507

508 unsigned Align = CGM.getDataLayout().getABITypeAlign(I).value();

509 if (BlockAlign < Align)

510 BlockAlign = Align;

511 assert(Offset % Align == 0);

512 Offset += CGM.getDataLayout().getTypeAllocSize(I);

513 elementTypes.push_back(I);

514 }

515 }

518 } else {

519

520

526 elementTypes.push_back(CGM.VoidPtrTy);

527 elementTypes.push_back(CGM.IntTy);

528 elementTypes.push_back(CGM.IntTy);

529 elementTypes.push_back(CGM.VoidPtrTy);

531 }

532}

533

537

538

539

543 return FD->getType();

544

545

546

549}

550

551

552

557

560 bool hasNonConstantCustomFields = false;

561 if (auto *OpenCLHelper =

563 hasNonConstantCustomFields =

564 !OpenCLHelper->areAllCustomFieldValuesConstant(info);

565 if (!block->hasCaptures() && !hasNonConstantCustomFields) {

567 llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);

569 return;

570 }

571 else if (C.getLangOpts().ObjC &&

574

577

578

582

584

585

587 assert(CGF && isa_and_nonnull(CGF->CurFuncDecl) &&

588 "Can't capture 'this' outside a method");

589 QualType thisType = cast(CGF->CurFuncDecl)->getThisType();

590

591

592

595 maxFieldAlign = std::max(maxFieldAlign, TInfo.Align);

596

597 addBlockLayout(TInfo.Align, TInfo.Width, nullptr, llvmType, thisType,

598 layout, info, CGM);

599 }

600

601

602 for (const auto &CI : block->captures()) {

603 const VarDecl *variable = CI.getVariable();

604

605 if (CI.isEscapingByref()) {

606

608 maxFieldAlign = std::max(maxFieldAlign, align);

609

610

611

613 "capture type differs from the variable type");

615 variable->getType(), layout, info, CGM);

616 continue;

617 }

618

619

620

624 continue;

625 }

626

628

631 if (CI.hasCopyExpr() || !record->hasTrivialDestructor()) {

633 if (!record->isExternallyVisible())

635 }

636

637 CharUnits size = C.getTypeSizeInChars(VT);

638 CharUnits align = C.getDeclAlign(variable);

639

640 maxFieldAlign = std::max(maxFieldAlign, align);

641

642 llvm::Type *llvmType =

644

645 addBlockLayout(align, size, &CI, llvmType, VT, layout, info, CGM);

646 }

647

648

649 if (layout.empty()) {

651 llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);

654 return;

655 }

656

657

658

659

660 llvm::stable_sort(layout);

661

662

665

668

669

670

672

673

674

675

676

677

678

679

680

681

682

683

684 if (endAlign < maxFieldAlign) {

686 li = layout.begin() + 1, le = layout.end();

687

688

689

690 for (; li != le && endAlign < li->Alignment; ++li)

691 ;

692

693

694

695 if (li != le) {

697 for (; li != le; ++li) {

698 assert(endAlign >= li->Alignment);

699

700 li->setIndex(info, elementTypes.size(), blockSize);

701 elementTypes.push_back(li->Type);

702 blockSize += li->Size;

704

705

706 if (endAlign >= maxFieldAlign) {

707 ++li;

708 break;

709 }

710 }

711

712 layout.erase(first, li);

713 }

714 }

715

716 assert(endAlign == getLowBit(blockSize));

717

718

719

720 if (endAlign < maxFieldAlign) {

722 CharUnits padding = newBlockSize - blockSize;

723

724

725

728 }

729

730 elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,

732 blockSize = newBlockSize;

733 endAlign = getLowBit(blockSize);

734 }

735

736 assert(endAlign >= maxFieldAlign);

737 assert(endAlign == getLowBit(blockSize));

738

739

740

742 li = layout.begin(), le = layout.end(); li != le; ++li) {

743 if (endAlign < li->Alignment) {

744

745

746

747 CharUnits padding = li->Alignment - endAlign;

748 elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,

750 blockSize += padding;

752 }

753 assert(endAlign >= li->Alignment);

754 li->setIndex(info, elementTypes.size(), blockSize);

755 elementTypes.push_back(li->Type);

756 blockSize += li->Size;

758 }

759

762 llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);

763}

764

765

767

768

769 if (blockExpr->getBlockDecl()->hasCaptures())

770

771

774

777 blockInfo.BlockExpression = blockExpr;

778 if (!blockInfo.CanBeGlobal)

779 blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType,

780 blockInfo.BlockAlign, "block");

782}

783

786 auto GenVoidPtrTy =

791

794 BlockCGF.SanOpts = SanOpts;

795 auto *InvokeFn = BlockCGF.GenerateBlockFunction(

796 CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);

797 auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);

798

799

802

803

804

806 assert(blockAddr.isValid() && "block has no address!");

807

808 llvm::Constant *isa;

809 llvm::Constant *descriptor;

811 if (!IsOpenCL) {

812

813

814

815 llvm::Constant *blockISA = blockInfo.NoEscape

818 isa = blockISA;

819

820

822

823

836 }

837

838 auto projectField = [&](unsigned index, const Twine &name) -> Address {

840 };

841 auto storeField = [&](llvm::Value *value, unsigned index, const Twine &name) {

843 };

844

845

846 {

847

848 unsigned index = 0;

850 auto addHeaderField = [&](llvm::Value *value, CharUnits size,

851 const Twine &name) {

852 storeField(value, index, name);

853 offset += size;

854 index++;

855 };

856

857 if (!IsOpenCL) {

859 addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),

861 addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(),

862 "block.reserved");

863 } else {

864 addHeaderField(

867 addHeaderField(

870 }

871 addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");

872 if (!IsOpenCL)

873 addHeaderField(descriptor, getPointerSize(), "block.descriptor");

874 else if (auto *Helper =

876 for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {

877 addHeaderField(

878 I.first,

881 I.second);

882 }

883 }

884 }

885

886

888

889

890 if (blockDecl->capturesCXXThis()) {

892 projectField(blockInfo.CXXThisIndex, "block.captured-this.addr");

894 }

895

896

897 for (const auto &CI : blockDecl->captures()) {

898 const VarDecl *variable = CI.getVariable();

900

901

903

905

906

907

908 Address blockField = projectField(capture.getIndex(), "block.captured");

909

910

911

913

914 if (blockDecl->isConversionFromLambda()) {

915

916

918 } else if (CI.isEscapingByref()) {

919 if (BlockInfo && CI.isNested()) {

920

923

924

927 "block.capture.addr");

928 } else {

929 auto I = LocalDeclMap.find(variable);

930 assert(I != LocalDeclMap.end());

931 src = I->second;

932 }

933 } else {

935 CI.isNested(),

939 };

940

941

942

943

944

945 if (CI.isEscapingByref()) {

946

947 llvm::Value *byrefPointer;

948 if (CI.isNested())

950 else

952

953

955

956

957 } else if (const Expr *copyExpr = CI.getCopyExpr()) {

958 if (blockDecl->isConversionFromLambda()) {

959

960

968 } else {

970 }

971

972

975

976

977 } else if (type.isConstQualified() &&

982

983

984

985

986

987

988

989

991 type->isBlockPointerType()) {

992

993 llvm::Value *value = Builder.CreateLoad(src, "block.captured_block");

995

996

998

999

1000 } else {

1001

1002

1005

1006

1007

1009 CI.isNested(),

1011

1014

1015

1016

1019 false);

1020 }

1021

1022

1024 continue;

1025

1026

1027

1028 if (CI.isByRef())

1029 continue;

1030

1031

1034 continue;

1035

1037

1038

1039

1040

1041

1042

1043

1044 if (type.isConstQualified() &&

1048 "expected ObjC ARC to be enabled");

1052 } else {

1054 }

1055

1058 if (useArrayEHCleanup)

1060

1061

1062

1063

1064

1065 auto IsBlockDeclInRetExpr = [&]() {

1066 auto *EWC = llvm::dyn_cast_or_null(RetExpr);

1067 if (EWC)

1068 for (auto &C : EWC->getObjects())

1069 if (auto *BD = C.dyn_cast<BlockDecl *>())

1071 return true;

1072 return false;

1073 };

1074

1075 if (IsBlockDeclInRetExpr())

1076 pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup);

1077 else

1079 useArrayEHCleanup);

1080 }

1081

1082

1083

1084 llvm::Value *result = Builder.CreatePointerCast(

1086

1087 if (IsOpenCL) {

1090 }

1091

1092 return result;

1093}

1094

1095

1097 if (BlockDescriptorType)

1098 return BlockDescriptorType;

1099

1100 llvm::Type *UnsignedLongTy =

1102

1103

1104

1105

1106

1107

1108

1109

1110

1111

1112

1113

1114

1115

1116

1117 BlockDescriptorType = llvm::StructType::create(

1118 "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy);

1119

1120

1121 unsigned AddrSpace = 0;

1124 BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace);

1125 return BlockDescriptorType;

1126}

1127

1129 if (GenericBlockLiteralType)

1130 return GenericBlockLiteralType;

1131

1133

1135

1136

1137

1138

1139

1140

1144 llvm::append_range(StructFields, Helper->getCustomFieldTypes());

1145 }

1146 GenericBlockLiteralType = llvm::StructType::create(

1147 StructFields, "struct.__opencl_block_literal_generic");

1148 } else {

1149

1150

1151

1152

1153

1154

1155

1156 GenericBlockLiteralType =

1157 llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,

1159 }

1160

1161 return GenericBlockLiteralType;

1162}

1163

1166 llvm::CallBase **CallOrInvoke) {

1170 llvm::Value *Func = nullptr;

1174

1176

1177

1178

1179

1180 llvm::Type *GenericVoidPtrTy =

1182 llvm::Value *BlockDescriptor = Builder.CreatePointerCast(

1183 BlockPtr, GenericVoidPtrTy);

1186 Args.add(RValue::get(BlockDescriptor), VoidPtrQualTy);

1187

1189

1190

1191 if (!isa(E->getCalleeDecl()))

1193 else {

1197 }

1198 } else {

1199

1200 BlockPtr =

1202

1204

1205

1208

1210

1211

1213 }

1214

1218

1219

1221

1222

1224}

1225

1227 assert(BlockInfo && "evaluating block ref without block information?");

1229

1230

1231 if (capture.isConstant()) return LocalDeclMap.find(variable)->second;

1232

1234 "block.capture.addr");

1235

1237

1238

1239

1242 byrefInfo.ByrefAlignment);

1243

1246 }

1247

1250 "the capture field of a non-escaping variable should have a "

1251 "reference type");

1254

1255 return addr;

1256}

1257

1259 llvm::Constant *Addr) {

1260 bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;

1261 (void)Ok;

1262 assert(Ok && "Trying to replace an already-existing global block!");

1263}

1264

1265llvm::Constant *

1267 StringRef Name) {

1269 return Block;

1270

1273

1274

1276

1277

1278 {

1281 GlobalDecl(), blockInfo, LocalDeclMap,

1282 false, true);

1283 }

1284

1286}

1287

1290 llvm::Constant *blockFn) {

1292

1293

1294

1296 "Refusing to re-emit a global block.");

1297

1298

1301

1302 bool IsOpenCL = CGM.getLangOpts().OpenCL;

1304 if (!IsOpenCL) {

1305

1306 if (IsWindows)

1308 else

1310

1311

1313 if (!CGM.getCodeGenOpts().DisableBlockSignatureString)

1317

1319

1320

1321 fields.addInt(CGM.IntTy, 0);

1322 } else {

1325 }

1326

1327

1328 fields.add(blockFn);

1329

1330 if (!IsOpenCL) {

1331

1333 } else if (auto *Helper =

1335 for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {

1336 fields.add(I);

1337 }

1338 }

1339

1340 unsigned AddrSpace = 0;

1343

1344 llvm::GlobalVariable *literal = fields.finishAndCreateGlobal(

1345 "__block_literal_global", blockInfo.BlockAlign,

1346 !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);

1347

1348 literal->addAttribute("objc_arc_inert");

1349

1350

1351

1352 if (IsWindows) {

1353 auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,

1354 {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",

1356 llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",

1359 b.CreateStructGEP(literal->getValueType(), literal, 0),

1361 b.CreateRetVoid();

1362

1363

1364 auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),

1365 true, llvm::GlobalValue::InternalLinkage,

1366 Init, ".block_isa_init_ptr");

1367 InitVar->setSection(".CRT$XCLa");

1369 }

1370

1371

1372 llvm::Type *RequiredType =

1374 llvm::Constant *Result =

1375 llvm::ConstantExpr::getPointerCast(literal, RequiredType);

1380 castllvm::Function(blockFn->stripPointerCasts()), Result,

1381 literal->getValueType());

1383}

1384

1386 unsigned argNum,

1387 llvm::Value *arg) {

1388 assert(BlockInfo && "not emitting prologue of block invocation function?!");

1389

1390

1391

1397 DI->EmitDeclareOfBlockLiteralArgVariable(

1399 castllvm::AllocaInst(alloc.getPointer()->stripPointerCasts()),

1401 }

1402 }

1403

1406

1407

1408

1410 arg,

1411 llvm::PointerType::get(

1415 : 0),

1416 "block");

1417}

1418

1420 assert(BlockInfo && "not in a block invocation function!");

1421 assert(BlockPointer && "no block pointer set!");

1423}

1424

1427 bool IsLambdaConversionToBlock, bool BuildGlobalBlock) {

1429

1431

1433

1435

1436

1437

1438

1439 for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {

1440 const auto *var = dyn_cast(i->first);

1441 if (var && var->hasLocalStorage())

1442 setAddrOfLocalVar(var, i->second);

1443 }

1444

1445

1446

1447

1449

1450

1451

1453

1454

1455

1456

1457

1461

1463

1467 args.push_back(&SelfDecl);

1468

1469

1471

1472

1478

1480

1482 llvm::Function *fn = llvm::Function::Create(

1483 fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());

1485

1486 if (BuildGlobalBlock) {

1491 llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));

1492 }

1493

1494

1498

1499

1500

1501

1502

1503 llvm::Value *BlockPointerDbgLoc = BlockPointer;

1505

1508 "block.addr");

1509

1510

1514 }

1515

1516

1517

1518 if (blockDecl->capturesCXXThis()) {

1522 }

1523

1524

1525 for (const auto &CI : blockDecl->captures()) {

1526 const VarDecl *variable = CI.getVariable();

1528 if (!capture.isConstant()) continue;

1529

1533

1535

1536 setAddrOfLocalVar(variable, alloca);

1537 }

1538

1539

1540 llvm::BasicBlock *entry = Builder.GetInsertBlock();

1541 llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();

1542 --entry_ptr;

1543

1544 if (IsLambdaConversionToBlock)

1546 else {

1550 }

1551

1552

1553 llvm::BasicBlock *resume = Builder.GetInsertBlock();

1554

1555

1556 if (entry_ptr->getNextNonDebugInstruction())

1557 entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();

1558 else

1559 entry_ptr = entry->end();

1560 Builder.SetInsertPoint(entry, entry_ptr);

1561

1562

1563

1565 for (const auto &CI : blockDecl->captures()) {

1566 const VarDecl *variable = CI.getVariable();

1568

1572 auto addr = LocalDeclMap.find(variable)->second;

1573 (void)DI->EmitDeclareOfAutoVariable(

1575 continue;

1576 }

1577

1578 DI->EmitDeclareOfBlockDeclRefVariable(

1579 variable, BlockPointerDbgLoc, Builder, blockInfo,

1580 entry_ptr == entry->end() ? nullptr : &*entry_ptr);

1581 }

1582 }

1583

1584 DI->EmitLocation(Builder,

1585 cast(blockDecl->getBody())->getRBracLoc());

1586 }

1587

1588

1589 if (resume == nullptr)

1590 Builder.ClearInsertionPoint();

1591 else

1592 Builder.SetInsertPoint(resume);

1593

1595

1596 return fn;

1597}

1598

1599static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

1604

1606 }

1610 if (T.isObjCGCWeak())

1613 }

1614

1619

1620 switch (T.isNonTrivialToPrimitiveCopy()) {

1625

1628

1629

1630

1631

1634 Flags);

1638

1640

1641

1642

1645

1646

1648

1649

1650

1651 if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)

1653

1654

1656 }

1657 }

1658 llvm_unreachable("after exhaustive PrimitiveCopyKind switch");

1659}

1660

1661namespace {

1662

1666 bool LoadBlockVarAddr, CanThrow;

1667

1669 bool CT)

1670 : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),

1672

1674 llvm::Value *BlockVarAddr;

1675 if (LoadBlockVarAddr) {

1677 } else {

1678 BlockVarAddr = Addr.emitRawPointer(CGF);

1679 }

1680

1682 }

1683};

1684}

1685

1686

1691 return false;

1692}

1693

1694

1696 CaptureStrKind StrKind,

1699 std::string Str;

1703

1706

1707

1708

1709 assert((StrKind != CaptureStrKind::Merged ||

1712 "different operations and flags");

1713

1714 if (StrKind == CaptureStrKind::DisposeHelper) {

1717 } else {

1720 }

1721

1722 switch (Kind) {

1724 Str += "c";

1726 llvm::raw_svector_ostream Out(TyStr);

1728 Str += llvm::to_string(TyStr.size()) + TyStr.c_str();

1729 break;

1730 }

1732 Str += "w";

1733 break;

1735 Str += "s";

1736 break;

1741 Str += "r";

1743 Str += "w";

1744 else {

1745

1746

1747 if (StrKind != CaptureStrKind::DisposeHelper) {

1749 Str += "c";

1750 }

1751 if (StrKind != CaptureStrKind::CopyHelper) {

1753 Str += "d";

1754 }

1755 }

1756 } else {

1759 Str += "b";

1760 else

1761 Str += "o";

1762 }

1763 break;

1764 }

1768

1769 Str += "n";

1770 std::string FuncStr;

1771 if (StrKind == CaptureStrKind::DisposeHelper)

1773 CaptureTy, Alignment, IsVolatile, Ctx);

1774 else

1775

1776

1778 CaptureTy, Alignment, IsVolatile, Ctx);

1779

1780

1781 Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr;

1782 break;

1783 }

1785 break;

1786 }

1787

1788 return Str;

1789}

1790

1794 assert((StrKind == CaptureStrKind::CopyHelper ||

1795 StrKind == CaptureStrKind::DisposeHelper) &&

1796 "unexpected CaptureStrKind");

1797 std::string Name = StrKind == CaptureStrKind::CopyHelper

1798 ? "__copy_helper_block_"

1799 : "__destroy_helper_block_";

1801 Name += "e";

1802 if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)

1803 Name += "a";

1804 Name += llvm::to_string(BlockAlignment.getQuantity()) + "_";

1805

1806 for (auto &Cap : Captures) {

1807 if (Cap.isConstantOrTrivial())

1808 continue;

1809 Name += llvm::to_string(Cap.getOffset().getQuantity());

1811 }

1812

1813 return Name;

1814}

1815

1820 bool EHOnly = ForCopyHelper;

1821

1822 switch (CaptureKind) {

1837 }

1838 break;

1839 }

1841 if (!EHOnly || CGF.getLangOpts().Exceptions) {

1843

1844

1845

1848 CGF.enterByrefCleanup(Kind, Field, Flags, true,

1850 }

1851 break;

1852 }

1854 break;

1855 }

1856}

1857

1859 llvm::Function *Fn,

1862 if (CapturesNonExternalType) {

1864 } else {

1865 Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);

1866 Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

1869 }

1870}

1871

1872

1873

1874

1875

1876

1877

1878

1879llvm::Constant *

1883 CaptureStrKind::CopyHelper, CGM);

1884

1885 if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))

1886 return Func;

1887

1889

1891

1894 args.push_back(&DstDecl);

1896 args.push_back(&SrcDecl);

1897

1900

1901

1902

1904

1905 llvm::Function *Fn =

1906 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,

1909 Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));

1910

1912 ArgTys.push_back(C.VoidPtrTy);

1913 ArgTys.push_back(C.VoidPtrTy);

1914

1919

1923

1927

1930 continue;

1931

1935

1936 unsigned index = capture.getIndex();

1939

1942

1943 assert(CI.getCopyExpr() && "copy expression for variable is missing");

1945 break;

1948 break;

1950

1951

1955 break;

1956 }

1958 llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");

1959

1960

1961

1963 auto *ty = castllvm::PointerType(srcValue->getType());

1964 llvm::Value *null = llvm::ConstantPointerNull::get(ty);

1967

1968

1969

1970

1971 } else {

1973

1974

1975

1976

1978 if (auto *I =

1979 cast_or_nullllvm::Instruction(dstField.getBasePointer()))

1980 I->eraseFromParent();

1981 }

1982 break;

1983 }

1985 llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");

1986 llvm::Value *dstAddr = dstField.emitRawPointer(*this);

1987 llvm::Value *args[] = {

1988 dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())

1989 };

1990

1993 else

1995 break;

1996 }

1998 continue;

1999 }

2000

2001

2002

2004 true, CI.getVariable(), *this);

2005 }

2006

2008

2009 return Fn;

2010}

2011

2018 return Flags;

2019}

2020

2021static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

2026 if (T.isObjCGCWeak())

2029 }

2030

2031 switch (T.isDestructedType()) {

2035

2036

2040

2047

2048

2049

2054

2056 }

2057 }

2058 llvm_unreachable("after exhaustive DestructionKind switch");

2059}

2060

2061

2062

2063

2064

2065

2066

2067

2068llvm::Constant *

2072 CaptureStrKind::DisposeHelper, CGM);

2073

2074 if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))

2075 return Func;

2076

2078

2080

2083 args.push_back(&SrcDecl);

2084

2087

2088

2089

2091

2092 llvm::Function *Fn =

2093 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,

2096 Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));

2097

2099 ArgTys.push_back(C.VoidPtrTy);

2100

2105

2107

2111

2112 CodeGenFunction::RunCleanupsScope cleanups(*this);

2113

2116 continue;

2117

2120

2122

2125 false, CI.getVariable(), *this);

2126 }

2127

2128 cleanups.ForceCleanup();

2129

2131

2132 return Fn;

2133}

2134

2135namespace {

2136

2137

2140

2141public:

2144

2146 Address srcField) override {

2148

2151

2153

2154 llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);

2156

2157 llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal};

2159 }

2160

2164

2166 }

2167

2168 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2169 id.AddInteger(Flags.getBitMask());

2170 }

2171};

2172

2173

2175public:

2177

2179 Address srcField) override {

2181 }

2182

2185 }

2186

2187 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2188

2189 id.AddInteger(0);

2190 }

2191};

2192

2193

2194

2196public:

2198

2200 Address srcField) override {

2201

2202

2203

2205

2206 llvm::Value *null =

2207 llvm::ConstantPointerNull::get(castllvm::PointerType(value->getType()));

2208

2213 return;

2214 }

2217 }

2218

2221 }

2222

2223 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2224

2225 id.AddInteger(1);

2226 }

2227};

2228

2229

2230

2231class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {

2232public:

2233 ARCStrongBlockByrefHelpers(CharUnits alignment)

2235

2237 Address srcField) override {

2238

2239

2240

2242 llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, true);

2244 }

2245

2248 }

2249

2250 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2251

2252 id.AddInteger(2);

2253 }

2254};

2255

2256

2257

2260 const Expr *CopyExpr;

2261

2262public:

2264 const Expr *copyExpr)

2266

2267 bool needsCopy() const override { return CopyExpr != nullptr; }

2269 Address srcField) override {

2270 if (!CopyExpr) return;

2272 }

2273

2278 }

2279

2280 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2281 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());

2282 }

2283};

2284

2285

2286

2287class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {

2289

2290public:

2293

2295 Address srcField) override {

2298 }

2299

2300 bool needsDispose() const override {

2301 return VarType.isDestructedType();

2302 }

2303

2306 CGF.pushDestroy(VarType.isDestructedType(), field, VarType);

2308 }

2309

2310 void profileImpl(llvm::FoldingSetNodeID &id) const override {

2311 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());

2312 }

2313};

2314}

2315

2316static llvm::Constant *

2320

2322

2325 args.push_back(&Dst);

2326

2328 args.push_back(&Src);

2329

2332

2334

2335

2336

2337 llvm::Function *Fn =

2338 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,

2339 "__Block_byref_object_copy_", &CGF.CGM.getModule());

2340

2342 ArgTys.push_back(Context.VoidPtrTy);

2343 ArgTys.push_back(Context.VoidPtrTy);

2344

2346

2348

2350

2352

2356 destField =

2358

2359

2363 srcField =

2365

2366 generator.emitCopy(CGF, destField, srcField);

2367 }

2368

2370

2371 return Fn;

2372}

2373

2374

2380}

2381

2382

2383static llvm::Constant *

2389

2393 args.push_back(&Src);

2394

2397

2399

2400

2401

2402 llvm::Function *Fn =

2403 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,

2404 "__Block_byref_object_dispose_",

2406

2408 ArgTys.push_back(Context.VoidPtrTy);

2409

2411

2413

2415

2421

2423 }

2424

2426

2427 return Fn;

2428}

2429

2430

2436}

2437

2438

2439

2440template

2442 T &&generator) {

2443 llvm::FoldingSetNodeID id;

2444 generator.Profile(id);

2445

2446 void *insertPos;

2449 if (node) return static_cast<T*>(node);

2450

2453

2454 T *copy = new (CGM.getContext()) T(std::forward(generator));

2456 return copy;

2457}

2458

2459

2460

2461

2463CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,

2464 const AutoVarEmission &emission) {

2465 const VarDecl &var = *emission.Variable;

2466 assert(var.isEscapingByref() &&

2467 "only escaping __block variables need byref helpers");

2468

2470

2472

2473

2474

2476 byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);

2477

2479 const Expr *copyExpr =

2481 if (!copyExpr && record->hasTrivialDestructor()) return nullptr;

2482

2483 return ::buildByrefHelpers(

2484 CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));

2485 }

2486

2487

2488

2491 return ::buildByrefHelpers(

2492 CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type));

2493

2494

2495

2496 if (type->isObjCRetainableType()) return nullptr;

2497

2499

2500

2502 switch (lifetime) {

2504

2505

2508 return nullptr;

2509

2510

2511

2513 return ::buildByrefHelpers(CGM, byrefInfo,

2514 ARCWeakByrefHelpers(valueAlignment));

2515

2516

2518

2519

2520 if (type->isBlockPointerType()) {

2521 return ::buildByrefHelpers(CGM, byrefInfo,

2522 ARCStrongBlockByrefHelpers(valueAlignment));

2523

2524

2525

2526 } else {

2527 return ::buildByrefHelpers(CGM, byrefInfo,

2528 ARCStrongByrefHelpers(valueAlignment));

2529 }

2530 }

2531 llvm_unreachable("fell out of lifetime switch!");

2532 }

2533

2535 if (type->isBlockPointerType()) {

2538 type->isObjCObjectPointerType()) {

2540 } else {

2541 return nullptr;

2542 }

2543

2544 if (type.isObjCGCWeak())

2546

2547 return ::buildByrefHelpers(CGM, byrefInfo,

2548 ObjectByrefHelpers(valueAlignment, flags));

2549}

2550

2553 bool followForward) {

2556}

2557

2560 bool followForward,

2561 const llvm::Twine &name) {

2562

2563 if (followForward) {

2567 }

2568

2570}

2571

2572

2573

2574

2575

2576

2577

2578

2579

2580

2581

2582

2583

2584

2585

2586

2588 auto it = BlockByrefInfos.find(D);

2589 if (it != BlockByrefInfos.end())

2590 return it->second;

2591

2593

2596

2597

2600

2601

2604

2605

2608

2609

2612

2613

2615 if (hasCopyAndDispose) {

2616

2619

2620

2623 }

2624

2625 bool HasByrefExtendedLayout = false;

2627 if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&

2628 HasByrefExtendedLayout) {

2629

2632 }

2633

2634

2636

2637 bool packed = false;

2640

2641

2642 if (varOffset != size) {

2643 llvm::Type *paddingTy =

2644 llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity());

2645

2646 types.push_back(paddingTy);

2647 size = varOffset;

2648

2649

2652 packed = true;

2653 }

2654 types.push_back(varTy);

2655

2656 llvm::StructType *byrefType = llvm::StructType::create(

2658 packed);

2659

2661 info.Type = byrefType;

2665

2666 auto pair = BlockByrefInfos.insert({D, info});

2667 assert(pair.second && "info was inserted recursively?");

2668 return pair.first->second;

2669}

2670

2671

2672

2674

2675 Address addr = emission.Addr;

2676

2677

2678 llvm::StructType *byrefType = castllvm::StructType(addr.getElementType());

2679

2680 unsigned nextHeaderIndex = 0;

2682 auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,

2683 const Twine &name) {

2686

2687 nextHeaderIndex++;

2688 nextHeaderOffset += fieldSize;

2689 };

2690

2691

2692 BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission);

2693

2694 const VarDecl &D = *emission.Variable;

2696

2697 bool HasByrefExtendedLayout = false;

2699 bool ByRefHasLifetime =

2701

2702 llvm::Value *V;

2703

2704

2705 int isa = 0;

2706 if (type.isObjCGCWeak())

2707 isa = 1;

2710

2711

2713 "byref.forwarding");

2714

2715

2716

2717

2720 if (ByRefHasLifetime) {

2722 else switch (ByrefLifetime) {

2725 break;

2728 break;

2731 break;

2733 if (type->isObjCObjectPointerType() && type->isBlockPointerType())

2735 break;

2736 default:

2737 break;

2738 }

2740 printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask());

2742 printf(" BLOCK_BYREF_HAS_COPY_DISPOSE");

2746 printf(" BLOCK_BYREF_LAYOUT_EXTENDED");

2748 printf(" BLOCK_BYREF_LAYOUT_STRONG");

2750 printf(" BLOCK_BYREF_LAYOUT_WEAK");

2752 printf(" BLOCK_BYREF_LAYOUT_UNRETAINED");

2754 printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT");

2755 }

2757 }

2758 }

2759 storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),

2761

2764 storeHeaderField(V, getIntSize(), "byref.size");

2765

2766 if (helpers) {

2768 "byref.copyHelper");

2770 "byref.disposeHelper");

2771 }

2772

2773 if (ByRefHasLifetime && HasByrefExtendedLayout) {

2775 storeHeaderField(layoutInfo, getPointerSize(), "byref.layout");

2776 }

2777}

2778

2782 llvm::Value *args[] = {V,

2784

2787 else

2789}

2790

2793 bool LoadBlockVarAddr, bool CanThrow) {

2794 EHStack.pushCleanup(Kind, Addr, Flags, LoadBlockVarAddr,

2796}

2797

2798

2800 llvm::Constant *C) {

2801 auto *GV = castllvm::GlobalValue(C->stripPointerCasts());

2802

2807

2808 assert((isallvm::Function(C->stripPointerCasts()) ||

2809 isallvm::GlobalVariable(C->stripPointerCasts())) &&

2810 "expected Function or GlobalVariable");

2811

2814 if ((ND = dyn_cast(Result)) ||

2815 (ND = dyn_cast(Result)))

2816 break;

2817

2818

2819 if (GV->isDeclaration() && (!ND || !ND->hasAttr())) {

2820 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

2821 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);

2822 } else {

2823 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);

2824 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);

2825 }

2826 }

2827

2828 if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&

2829 GV->hasExternalLinkage())

2830 GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);

2831

2833}

2834

2836 if (BlockObjectDispose)

2837 return BlockObjectDispose;

2838

2840 BlockObjectDispose =

2843 *this, castllvm::Constant(BlockObjectDispose.getCallee()));

2844 return BlockObjectDispose;

2845}

2846

2848 if (BlockObjectAssign)

2849 return BlockObjectAssign;

2850

2852 BlockObjectAssign =

2855 *this, castllvm::Constant(BlockObjectAssign.getCallee()));

2856 return BlockObjectAssign;

2857}

2858

2860 if (NSConcreteGlobalBlock)

2861 return NSConcreteGlobalBlock;

2862

2866 return NSConcreteGlobalBlock;

2867}

2868

2870 if (NSConcreteStackBlock)

2871 return NSConcreteStackBlock;

2872

2876 return NSConcreteStackBlock;

2877}

static bool CanThrow(Expr *E, ASTContext &Ctx)

static llvm::Constant * buildByrefDisposeHelper(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo, BlockByrefHelpers &generator)

Build the dispose helper for a __block variable.

static llvm::Constant * buildBlockDescriptor(CodeGenModule &CGM, const CGBlockInfo &blockInfo)

buildBlockDescriptor - Build the block descriptor meta-data for a block.

static void addBlockLayout(CharUnits align, CharUnits size, const BlockDecl::Capture *capture, llvm::Type *type, QualType fieldType, SmallVectorImpl< BlockLayoutChunk > &Layout, CGBlockInfo &Info, CodeGenModule &CGM)

static llvm::Constant * generateByrefDisposeHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, BlockByrefHelpers &generator)

Generate code for a __block variable's dispose helper.

static QualType getCaptureFieldType(const CodeGenFunction &CGF, const BlockDecl::Capture &CI)

static std::string getCopyDestroyHelperFuncName(const SmallVectorImpl< CGBlockInfo::Capture > &Captures, CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM)

static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo, CodeGenModule &CGM)

static llvm::Constant * buildCopyHelper(CodeGenModule &CGM, const CGBlockInfo &blockInfo)

Build the helper function to copy a block.

static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap, CaptureStrKind StrKind, CharUnits BlockAlignment, CodeGenModule &CGM)

static llvm::Constant * tryCaptureAsConstant(CodeGenModule &CGM, CodeGenFunction *CGF, const VarDecl *var)

It is illegal to modify a const object after initialization.

static llvm::Constant * generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, BlockByrefHelpers &generator)

static std::pair< BlockCaptureEntityKind, BlockFieldFlags > computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, const LangOptions &LangOpts)

static llvm::Constant * buildByrefCopyHelper(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo, BlockByrefHelpers &generator)

Build the copy helper for a __block variable.

static BlockFieldFlags getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI, QualType T)

static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, CGBlockInfo &info)

Compute the layout of the given block.

static T * buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo, T &&generator)

Lazily build the copy and dispose helpers for a __block variable with the given information.

static llvm::Constant * buildGlobalBlock(CodeGenModule &CGM, const CGBlockInfo &blockInfo, llvm::Constant *blockFn)

Build the given block as a global block.

static llvm::Constant * buildDisposeHelper(CodeGenModule &CGM, const CGBlockInfo &blockInfo)

Build the helper function to dispose of a block.

static void configureBlocksRuntimeObject(CodeGenModule &CGM, llvm::Constant *C)

Adjust the declaration of something from the blocks API.

static bool isSafeForCXXConstantCapture(QualType type)

Determines if the given type is safe for constant capture in C++.

static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind, Address Field, QualType CaptureType, BlockFieldFlags Flags, bool ForCopyHelper, VarDecl *Var, CodeGenFunction &CGF)

static std::pair< BlockCaptureEntityKind, BlockFieldFlags > computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, const LangOptions &LangOpts)

static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType, llvm::Function *Fn, const CGFunctionInfo &FI, CodeGenModule &CGM)

static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, SmallVectorImpl< llvm::Type * > &elementTypes)

static CharUnits getLowBit(CharUnits v)

Get the low bit of a nonzero character count.

static bool isTrivial(ASTContext &Ctx, const Expr *E)

Checks if the expression is constant or does not have non-trivial function calls.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

bool getByrefLifetime(QualType Ty, Qualifiers::ObjCLifetime &Lifetime, bool &HasByrefExtendedLayout) const

Returns true, if given type has a known lifetime.

TranslationUnitDecl * getTranslationUnitDecl() const

QualType getPointerType(QualType T) const

Return the uniqued reference to the type for a pointer to the specified type.

QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const

Return the uniqued reference to the type for an lvalue reference to the specified type.

bool BlockRequiresCopying(QualType Ty, const VarDecl *D)

Returns true iff we need copy/dispose helpers for the given type.

const LangOptions & getLangOpts() const

BlockVarCopyInit getBlockVarCopyInit(const VarDecl *VD) const

Get the copy initialization expression of the VarDecl VD, or nullptr if none exists.

TypeInfoChars getTypeInfoInChars(const Type *T) const

CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const

Return a conservative estimate of the alignment of the specified decl D.

static bool isObjCNSObjectType(QualType Ty)

Return true if this is an NSObject object with its NSObject attribute set.

std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const

Return the encoded type for this block declaration.

QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const

Return the uniqued reference to the type for an address space qualified type with the specified type ...

unsigned getTargetAddressSpace(LangAS AS) const

A class which contains all the information about a particular captured value.

bool isNested() const

Whether this is a nested capture, i.e.

Expr * getCopyExpr() const

bool isByRef() const

Whether this is a "by ref" capture, i.e.

VarDecl * getVariable() const

The variable being captured.

bool isEscapingByref() const

Represents a block literal declaration, which is like an unnamed FunctionDecl.

capture_const_iterator capture_begin() const

capture_const_iterator capture_end() const

ArrayRef< Capture > captures() const

bool capturesCXXThis() const

bool doesNotEscape() const

bool hasCaptures() const

True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...

bool isConversionFromLambda() const

BlockExpr - Adaptor class for mixing a BlockDecl with expressions.

const Stmt * getBody() const

SourceLocation getEndLoc() const LLVM_READONLY

const FunctionProtoType * getFunctionType() const

getFunctionType - Return the underlying function type for this block.

const BlockDecl * getBlockDecl() const

Represents a C++ destructor within a class.

Represents a C++ struct/union/class.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

CharUnits - This is an opaque type for sizes expressed in character units.

CharUnits alignmentAtOffset(CharUnits offset) const

Given that this is a non-zero alignment value, what is the alignment at the given offset?

llvm::Align getAsAlign() const

getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

CharUnits alignTo(const CharUnits &Align) const

alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...

static CharUnits Zero()

Zero - Construct a CharUnits quantity of zero.

bool hasReducedDebugInfo() const

Check if type and variable info should be emitted.

Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...

llvm::Value * getBasePointer() const

llvm::Value * emitRawPointer(CodeGenFunction &CGF) const

Return the pointer contained in this class after authenticating it and adding offset to it if necessa...

llvm::Type * getElementType() const

Return the type of the values stored in this address.

Address withElementType(llvm::Type *ElemTy) const

Return address with different element type, but same pointer and alignment.

static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)

forAddr - Make a slot for an aggregate value.

A scoped helper to set the current debug location to the specified location or preferred location of ...

static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)

Apply TemporaryLocation if it is valid.

static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)

Set the IRBuilder to not attach debug locations.

A pair of helper functions for a __block variable.

virtual ~BlockByrefHelpers()

virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src)=0

virtual bool needsCopy() const

llvm::Constant * CopyHelper

virtual void emitDispose(CodeGenFunction &CGF, Address field)=0

virtual bool needsDispose() const

llvm::Constant * DisposeHelper

Information about the layout of a __block variable.

uint32_t getBitMask() const

uint32_t getBitMask() const

const BlockDecl::Capture * Cap

BlockFieldFlags DisposeFlags

static Capture makeIndex(unsigned index, CharUnits offset, QualType FieldType, BlockCaptureEntityKind CopyKind, BlockFieldFlags CopyFlags, BlockCaptureEntityKind DisposeKind, BlockFieldFlags DisposeFlags, const BlockDecl::Capture *Cap)

BlockCaptureEntityKind CopyKind

bool isConstantOrTrivial() const

QualType fieldType() const

BlockFieldFlags CopyFlags

BlockCaptureEntityKind DisposeKind

llvm::Value * getConstant() const

unsigned getIndex() const

static Capture makeConstant(llvm::Value *value, const BlockDecl::Capture *Cap)

CharUnits getOffset() const

CGBlockInfo - Information to generate a block literal.

CGBlockInfo(const BlockDecl *blockDecl, StringRef Name)

unsigned CXXThisIndex

The field index of 'this' within the block, if there is one.

const BlockDecl * getBlockDecl() const

llvm::StructType * StructureType

CharUnits BlockHeaderForcedGapOffset

bool UsesStret

UsesStret : True if the block uses an stret return.

const BlockExpr * BlockExpression

const BlockExpr * getBlockExpr() const

bool HasCapturedVariableLayout

HasCapturedVariableLayout : True if block has captured variables and their layout meta-data has been ...

bool CapturesNonExternalType

Indicates whether an object of a non-external C++ class is captured.

bool NeedsCopyDispose

True if the block has captures that would necessitate custom copy or dispose helper functions if the ...

bool CanBeGlobal

CanBeGlobal - True if the block can be global, i.e.

bool HasCXXObject

HasCXXObject - True if the block's custom copy/dispose functions need to be run even in GC mode.

CharUnits BlockHeaderForcedGapSize

const Capture & getCapture(const VarDecl *var) const

llvm::SmallVector< Capture, 4 > SortedCaptures

The block's captures. Non-constant captures are sorted by their offsets.

bool NoEscape

Indicates whether the block is non-escaping.

llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)

Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")

MangleContext & getMangleContext()

Gets the mangle context.

Abstract information about a function or function prototype.

All available information about a concrete callee.

This class gathers all debug information during compilation and is responsible for emitting to llvm g...

CGFunctionInfo - Class to encapsulate the information about a function definition.

virtual llvm::Constant * BuildByrefLayout(CodeGen::CodeGenModule &CGM, QualType T)=0

Returns an i8* which points to the byref layout information.

virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo)

virtual llvm::Constant * BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0

virtual llvm::Constant * BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0

llvm::Function * getInvokeFunction(const Expr *E)

void recordBlockInfo(const BlockExpr *E, llvm::Function *InvokeF, llvm::Value *Block, llvm::Type *BlockTy)

Record invoke function and block literal emitted during normal codegen for a block expression.

llvm::PointerType * getGenericVoidPointerType()

CallArgList - Type for representing both the value and type of arguments in a call.

void add(RValue rvalue, QualType type)

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

void EmitARCDestroyWeak(Address addr)

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

void enterByrefCleanup(CleanupKind Kind, Address Addr, BlockFieldFlags Flags, bool LoadBlockVarAddr, bool CanThrow)

Enter a cleanup to destroy a __block variable.

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

static bool cxxDestructorCanThrow(QualType T)

Check if T is a C++ class that has a destructor that can throw.

SanitizerSet SanOpts

Sanitizers enabled for this function.

void EmitARCMoveWeak(Address dst, Address src)

RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)

void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)

const BlockByrefInfo & getBlockByrefInfo(const VarDecl *var)

void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)

void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp)

void callCStructMoveConstructor(LValue Dst, LValue Src)

void callCStructCopyConstructor(LValue Dst, LValue Src)

const LangOptions & getLangOpts() const

llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)

CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...

const CodeGen::CGBlockInfo * BlockInfo

Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)

void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)

EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...

void emitByrefStructureInit(const AutoVarEmission &emission)

llvm::Value * EmitARCStoreStrongCall(Address addr, llvm::Value *value, bool resultIgnored)

void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize, std::initializer_list< llvm::Value ** > ValuesToReload={})

Takes the old cleanup stack size and emits the cleanup blocks that have been added.

llvm::Type * ConvertTypeForMem(QualType T)

llvm::Value * EmitARCRetainBlock(llvm::Value *value, bool mandatory)

RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)

CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...

void EmitLambdaBlockInvokeBody()

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

static std::string getNonTrivialDestructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)

llvm::DenseMap< const Decl *, Address > DeclMapTy

llvm::Constant * GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo)

const Expr * RetExpr

If a return statement is being visited, this holds the return statment's result expression.

void EmitARCCopyWeak(Address dst, Address src)

void PushDestructorCleanup(QualType T, Address Addr)

PushDestructorCleanup - Push a cleanup to call the complete-object destructor of an object of the giv...

llvm::Value * BlockPointer

void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum, llvm::Value *ptr)

void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())

Emit code for the start of a function.

void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn)

Annotate the function with an attribute that disables TSan checking at runtime.

CGDebugInfo * getDebugInfo()

Address LoadBlockStruct()

Address emitBlockByrefAddress(Address baseAddr, const VarDecl *V, bool followForward=true)

BuildBlockByrefAddress - Computes the location of the data in a variable which is declared as __block...

LValue EmitDeclRefLValue(const DeclRefExpr *E)

llvm::Constant * GenerateCopyHelperFunction(const CGBlockInfo &blockInfo)

void EmitAggExpr(const Expr *E, AggValueSlot AS)

EmitAggExpr - Emit the computation of the specified expression of aggregate type.

llvm::Function * GenerateBlockFunction(GlobalDecl GD, const CGBlockInfo &Info, const DeclMapTy &ldm, bool IsLambdaConversionToBlock, bool BuildGlobalBlock)

RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)

EmitCall - Generate a call of the given function, expecting the given result type,...

llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

ASTContext & getContext() const

llvm::Value * EmitBlockLiteral(const BlockExpr *)

Emit block literal.

void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty)

const Decl * CurFuncDecl

CurFuncDecl - Holds the Decl for the current outermost non-closure context.

void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)

void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})

EmitStmt - Emit the code for the statement.

bool needsEHCleanup(QualType::DestructionKind kind)

Determines whether an EH cleanup is required to destroy a type with the given destruction kind.

llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields

CleanupKind getCleanupKind(QualType::DestructionKind kind)

llvm::Type * ConvertType(QualType T)

Address GetAddrOfBlockDecl(const VarDecl *var)

llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")

llvm::Value * EmitARCRetainNonBlock(llvm::Value *value)

LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)

llvm::Value * LoadCXXThis()

LoadCXXThis - Load the value of 'this'.

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

static Destroyer destroyARCStrongImprecise

llvm::LLVMContext & getLLVMContext()

llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)

EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...

void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)

Increment the profiler's counter for the given statement by StepV.

static std::string getNonTrivialCopyConstructorStr(QualType QT, CharUnits Alignment, bool IsVolatile, ASTContext &Ctx)

static Destroyer emitARCIntrinsicUse

void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags, bool CanThrow)

void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise)

This class organizes the cross-function state that is used while generating LLVM code.

StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD)

llvm::FunctionCallee getBlockObjectAssign()

llvm::FoldingSet< BlockByrefHelpers > ByrefHelpersCache

void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)

Set the attributes on the LLVM function for the given decl and function info.

void setDSOLocal(llvm::GlobalValue *GV) const

llvm::Module & getModule() const

llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)

Create or return a runtime function declaration with the specified type and name.

CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const

Return the store size, in character units, of the given LLVM type.

void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr)

Notes that BE's global block is available via Addr.

llvm::Type * getBlockDescriptorType()

Fetches the type of a generic block descriptor.

llvm::Constant * GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name)

Gets the address of a block which requires no captures.

const LangOptions & getLangOpts() const

CodeGenTypes & getTypes()

CGOpenCLRuntime & getOpenCLRuntime()

Return a reference to the configured OpenCL runtime.

const TargetInfo & getTarget() const

void addUsedGlobal(llvm::GlobalValue *GV)

Add a global to a list to be added to the llvm.used metadata.

const llvm::DataLayout & getDataLayout() const

llvm::Constant * getNSConcreteGlobalBlock()

CGCXXABI & getCXXABI() const

llvm::Constant * getAddrOfGlobalBlockIfEmitted(const BlockExpr *BE)

Returns the address of a block which requires no caputres, or null if we've yet to emit the block for...

bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI)

Return true iff the given type uses an argument slot when 'sret' is used as a return type.

llvm::Constant * GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, LangAS AddrSpace, const VarDecl *D, ForDefinition_t IsForDefinition=NotForDefinition)

GetOrCreateLLVMGlobal - If the specified mangled name is not in the module, create and return an llvm...

ASTContext & getContext() const

llvm::Constant * getNSConcreteStackBlock()

bool supportsCOMDAT() const

const TargetCodeGenInfo & getTargetCodeGenInfo()

const CodeGenOptions & getCodeGenOpts() const

llvm::FunctionCallee getBlockObjectDispose()

llvm::LLVMContext & getLLVMContext()

CGObjCRuntime & getObjCRuntime()

Return a reference to the configured Objective-C runtime.

void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info, llvm::Function *F, bool IsThunk)

Set the LLVM function attributes (sext, zext, etc).

llvm::Type * getGenericBlockLiteralType()

The type of a generic block literal.

void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F)

Set the LLVM function attributes which only apply to a function definition.

ConstantAddress GetAddrOfConstantCString(const std::string &Str, const char *GlobalName=nullptr)

Returns a pointer to a character array containing the literal and a terminating '\0' character.

void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)

Assign counters to regions and configure them for PGO of a given function.

llvm::Type * ConvertType(QualType T)

ConvertType - Convert type T into a llvm::Type.

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

const CGFunctionInfo & arrangeBlockFunctionCall(const CallArgList &args, const FunctionType *type)

A block function is essentially a free function with an extra implicit argument.

const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)

A builtin function is a freestanding function using the default C conventions.

llvm::Type * ConvertTypeForMem(QualType T)

ConvertTypeForMem - Convert type T into a llvm::Type.

const CGFunctionInfo & arrangeBlockFunctionDeclaration(const FunctionProtoType *type, const FunctionArgList &args)

Block invocation functions are C functions with an implicit parameter.

llvm::Constant * getPointer() const

llvm::Constant * tryEmitAbstractForInitializer(const VarDecl &D)

Try to emit the initializer of the given declaration as an abstract constant.

StructBuilder beginStruct(llvm::StructType *structTy=nullptr)

The standard implementation of ConstantInitBuilder used in Clang.

Information for lazily generating a cleanup.

A saved depth on the scope stack.

stable_iterator stable_begin() const

Create a stable reference to the top of the EH stack.

FunctionArgList - Type for representing both the decl and type of parameters to a function.

Address getAddress() const

RValue - This trivial value class is used to represent the result of an expression that is evaluated.

static RValue get(llvm::Value *V)

An abstract representation of an aligned address.

llvm::Value * getPointer() const

ReturnValueSlot - Contains the address where the return value of a function can be stored,...

virtual TargetOpenCLBlockHelper * getTargetOpenCLBlockHelper() const

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

lookup_result lookup(DeclarationName Name) const

lookup - Find the declarations (if any) with the given Name in this context.

A reference to a declared variable, function, enum, etc.

SourceLocation getLocation() const

This represents one expression.

Represents difference between two FPOptions values.

Represents a prototype with parameter type info, e.g.

FunctionType - C99 6.7.5.3 - Function Declarators.

QualType getReturnType() const

GlobalDecl - represents a global declaration.

One of these records is kept for each identifier that is lexed.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0

Generates a unique string for an externally visible type for use with TBAA or type uniquing.

This represents a decl that may have a name.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

@ DK_objc_strong_lifetime

DestructionKind isDestructedType() const

Returns a nonzero value if objects of this type require non-trivial work to clean up after.

@ PCK_Struct

The type is a struct containing a field whose type is neither PCK_Trivial nor PCK_VolatileTrivial.

@ PCK_Trivial

The type does not fall into any of the following categories.

@ PCK_ARCStrong

The type is an Objective-C retainable pointer type that is qualified with the ARC __strong qualifier.

@ PCK_VolatileTrivial

The type would be trivial except that it is volatile-qualified.

@ PCK_ARCWeak

The type is an Objective-C retainable pointer type that is qualified with the ARC __weak qualifier.

The collection of all-type qualifiers we support.

@ OCL_Strong

Assigning into this object requires the old value to be released and the new value to be retained.

@ OCL_ExplicitNone

This object can be modified without requiring retains or releases.

@ OCL_None

There is no lifetime qualification on this type.

@ OCL_Weak

Reading or writing from this object requires a barrier call.

@ OCL_Autoreleasing

Assigning into this object requires a lifetime extension.

ObjCLifetime getObjCLifetime() const

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

Base for LValueReferenceType and RValueReferenceType.

Scope - A scope is a transient data structure that is used while parsing the program.

Encodes a location in the source.

SourceLocation getBeginLoc() const LLVM_READONLY

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

uint64_t getPointerWidth(LangAS AddrSpace) const

Return the width of pointers on this target, for the specified address space.

uint64_t getPointerAlign(LangAS AddrSpace) const

The top declaration context.

static DeclContext * castToDeclContext(const TranslationUnitDecl *D)

The base class of the type hierarchy.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isBlockPointerType() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isObjCInertUnsafeUnretainedType() const

Was this type written with the special inert-in-ARC __unsafe_unretained qualifier?

const T * getAs() const

Member-template getAs'.

bool isObjCRetainableType() const

Represents a variable declaration or definition.

bool isNonEscapingByref() const

Indicates the capture is a __block variable that is never captured by an escaping block.

bool isEscapingByref() const

Indicates the capture is a __block variable that is captured by a block that can potentially escape (...

@ BLOCK_HAS_EXTENDED_LAYOUT

@ BLOCK_BYREF_LAYOUT_MASK

@ BLOCK_BYREF_LAYOUT_WEAK

@ BLOCK_BYREF_LAYOUT_STRONG

@ BLOCK_BYREF_LAYOUT_EXTENDED

@ BLOCK_BYREF_LAYOUT_NON_OBJECT

@ BLOCK_BYREF_HAS_COPY_DISPOSE

@ BLOCK_BYREF_LAYOUT_UNRETAINED

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

BlockCaptureEntityKind

Represents a type of copy/destroy operation that should be performed for an entity that's captured by...

@ NormalCleanup

Denotes a cleanup that should run when a scope is exited using normal control flow (falling off the e...

@ EHCleanup

Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...

const internal::VariadicAllOfMatcher< Type > type

Matches Types in the clang AST.

const internal::VariadicDynCastAllOfMatcher< Stmt, BlockExpr > blockExpr

Matches a reference to a block.

const AstTypeMatcher< RecordType > recordType

Matches record types (e.g.

const internal::VariadicDynCastAllOfMatcher< Decl, BlockDecl > blockDecl

Matches block declarations.

constexpr Variable var(Literal L)

Returns the variable of L.

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

RangeSelector name(std::string ID)

Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

@ Result

The result type of a method or function.

static bool isBlockPointer(Expr *Arg)

LangAS

Defines the address space values used by the address space qualifier of QualType.

@ VK_PRValue

A pr-value expression (in the C++11 taxonomy) produces a temporary value.

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

const FunctionProtoType * T

@ Other

Other implicit parameter.

@ ObjCSelf

Parameter for Objective-C 'self' argument.

int printf(__constant const char *st,...) __attribute__((format(printf

unsigned long ulong

An unsigned 64-bit integer.

Expr * getCopyExpr() const

llvm::PointerType * VoidPtrTy

llvm::PointerType * Int8PtrPtrTy

CharUnits getIntAlign() const

llvm::IntegerType * Int8Ty

i8, i16, i32, and i64

CharUnits getPointerSize() const

unsigned char PointerSizeInBytes

CharUnits getIntSize() const

llvm::IntegerType * Int32Ty

llvm::IntegerType * IntTy

int

llvm::PointerType * Int8PtrTy

llvm::PointerType * UnqualPtrTy

CharUnits getPointerAlign() const