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

1

2

3

4

5

6

7

8

9

10

11

12

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

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

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

29#include

30#include

31

32using namespace clang;

34

41

42

43

44 name.consume_front("\01");

45}

46

47

49

50

53 llvm::Constant *blockFn);

54

55

60

61

66

67namespace {

68

69enum class CaptureStrKind {

70

71 CopyHelper,

72

73 DisposeHelper,

74

75 Merged

76};

77

78}

79

81 CaptureStrKind StrKind,

82 CharUnits BlockAlignment,

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 llvm::replace(TypeAtEncoding, '@', '\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;

192

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

194 elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());

195

196

198 elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());

199

201 ->hasInternalLinkage() ||

203 ->hasInternalLinkage())

204 hasInternalHelper = true;

205 }

206

207

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

209 elements.addNullPointer(i8p);

210 } else {

211 std::string typeAtEncoding =

214 }

215

216

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

220 else

222 }

223 else

224 elements.addNullPointer(i8p);

225

226 unsigned AddrSpace = 0;

227 if (C.getLangOpts().OpenCL)

229

230 llvm::GlobalValue::LinkageTypes linkage;

231 if (descName.empty()) {

232 linkage = llvm::GlobalValue::InternalLinkage;

233 descName = "__block_descriptor_tmp";

234 } else if (hasInternalHelper) {

235

236

237 linkage = llvm::GlobalValue::InternalLinkage;

238 } else {

239 linkage = llvm::GlobalValue::LinkOnceODRLinkage;

240 }

241

242 llvm::GlobalVariable *global =

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

244 true, linkage, AddrSpace);

245

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

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

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

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

251 }

252

253 return global;

254}

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269 struct objc_class *isa;

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291 int flags;

292

293

294 int reserved;

295

296

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

298

299

300 struct Block_descriptor *block_descriptor;

301

302

303 _CapturesTypes captures...;

304 };

305 */

306

307namespace {

308

309 struct BlockLayoutChunk {

310 CharUnits Alignment;

311 CharUnits Size;

312 const BlockDecl::Capture *Capture;

313 llvm::Type *Type;

314 QualType FieldType;

316 BlockFieldFlags CopyFlags, DisposeFlags;

317

318 BlockLayoutChunk(CharUnits align, CharUnits size,

319 const BlockDecl::Capture *capture, llvm::Type *type,

321 BlockFieldFlags CopyFlags,

323 BlockFieldFlags DisposeFlags)

325 FieldType(fieldType), CopyKind(CopyKind), DisposeKind(DisposeKind),

326 CopyFlags(CopyFlags), DisposeFlags(DisposeFlags) {}

327

328

329 void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) {

333 } else {

335 index, offset, FieldType, CopyKind, CopyFlags, DisposeKind,

337 }

338 }

339

341 return CopyKind == BlockCaptureEntityKind::None &&

342 DisposeKind == BlockCaptureEntityKind::None;

343 }

344 };

345

346

347

348

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

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

351 return left.Alignment > right.Alignment;

352

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

354 switch (chunk.CopyKind) {

356 return 0;

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

360 return 0;

362 return 1;

364 return 2;

365 default:

366 break;

367 }

368 break;

370 return 3;

371 default:

372 break;

373 }

374 return 4;

375 };

376

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

378 }

379}

380

381static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

383 const LangOptions &LangOpts);

384

385static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

387 const LangOptions &LangOpts);

388

394 if (!capture) {

395

396 Layout.push_back(BlockLayoutChunk(

399 return;

400 }

401

405

406 std::tie(CopyKind, CopyFlags) =

408 std::tie(DisposeKind, DisposeFlags) =

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

411 CopyKind, CopyFlags, DisposeKind,

412 DisposeFlags));

413

415 return;

416

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

419}

420

421

423 const auto *record = type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();

424

425

426 if (!record)

427 return true;

428

429

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

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

432

433

434

435 return !record->hasMutableFields();

436}

437

438

439

440

441

442

443

447

448

450 return nullptr;

451

453

454

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

456

457

458

459

460

461

463 return nullptr;

464

465

466

467

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

469 if (!init) return nullptr;

470

472}

473

474

475

479

482

483 assert(elementTypes.empty());

485

486

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

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

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

494 elementTypes.push_back(CGM.IntTy);

495 elementTypes.push_back(CGM.IntTy);

496 elementTypes.push_back(

499 unsigned Offset =

501 unsigned BlockAlign = GenPtrAlign.getQuantity();

502 if (auto *Helper =

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

505

506

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

508 if (BlockAlign < Align)

509 BlockAlign = Align;

510 assert(Offset % Align == 0);

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

512 elementTypes.push_back(I);

513 }

514 }

517 } else {

518

519

525 elementTypes.push_back(CGM.VoidPtrTy);

526 elementTypes.push_back(CGM.IntTy);

527 elementTypes.push_back(CGM.IntTy);

528 elementTypes.push_back(CGM.VoidPtrTy);

530 }

531}

532

536

537

538

542 return FD->getType();

543

544

545

548}

549

550

551

556

559 bool hasNonConstantCustomFields = false;

560 if (auto *OpenCLHelper =

562 hasNonConstantCustomFields =

563 !OpenCLHelper->areAllCustomFieldValuesConstant(info);

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

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

568 return;

569 } else if (C.getLangOpts().ObjC &&

572

575

576

580

582

583

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

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

588

589

590

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

594

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

596 layout, info, CGM);

597 }

598

599

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

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

602

603 if (CI.isEscapingByref()) {

604

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

607

608

609

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

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

614 continue;

615 }

616

617

618

622 continue;

623 }

624

626

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

631 if (!record->isExternallyVisible())

633 }

634

635 CharUnits size = C.getTypeSizeInChars(VT);

636 CharUnits align = C.getDeclAlign(variable);

637

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

639

640 llvm::Type *llvmType =

642

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

644 }

645

646

647 if (layout.empty()) {

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

652 return;

653 }

654

655

656

657

658 llvm::stable_sort(layout);

659

660

663

666

667

668

670

671

672

673

674

675

676

677

678

679

680

681

682 if (endAlign < maxFieldAlign) {

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

685

686

687

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

689 ;

690

691

692

693 if (li != le) {

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

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

697

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

699 elementTypes.push_back(li->Type);

700 blockSize += li->Size;

702

703

704 if (endAlign >= maxFieldAlign) {

705 ++li;

706 break;

707 }

708 }

709

710 layout.erase(first, li);

711 }

712 }

713

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

715

716

717

718 if (endAlign < maxFieldAlign) {

720 CharUnits padding = newBlockSize - blockSize;

721

722

723

726 }

727

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

730 blockSize = newBlockSize;

731 endAlign = getLowBit(blockSize);

732 }

733

734 assert(endAlign >= maxFieldAlign);

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

736

737

738

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

741 if (endAlign < li->Alignment) {

742

743

744

745 CharUnits padding = li->Alignment - endAlign;

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

748 blockSize += padding;

750 }

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

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

753 elementTypes.push_back(li->Type);

754 blockSize += li->Size;

756 }

757

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

761}

762

763

765

766

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

768

769

770 if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))

772

780}

781

784 llvm::PointerType *GenVoidPtrTy =

789

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

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

796

797

800

801

802

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

805

806 llvm::Constant *isa;

807 llvm::Constant *descriptor;

809 if (!IsOpenCL) {

810

811

812

813 llvm::Constant *blockISA = blockInfo.NoEscape

816 isa = blockISA;

817

818

831

832

834 }

835

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

837 return Builder.CreateStructGEP(blockAddr, index, name);

838 };

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

840 Builder.CreateStore(value, projectField(index, name));

841 };

842

843

844 {

845

846 unsigned index = 0;

847 CharUnits offset;

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

849 const Twine &name) {

850 storeField(value, index, name);

851 offset += size;

852 index++;

853 };

854 auto addSignedHeaderField =

855 [&](llvm::Value *Value, const PointerAuthSchema &Schema,

856 GlobalDecl Decl, QualType Type, CharUnits Size, const Twine &Name) {

857 auto StorageAddress = projectField(index, Name);

858 if (Schema) {

860 Schema, StorageAddress.emitRawPointer(*this), Decl, Type);

862 }

864 offset += Size;

865 index++;

866 };

867

868 if (!IsOpenCL) {

869 addSignedHeaderField(

870 isa, CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers, GlobalDecl(),

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

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

875 "block.reserved");

876 } else {

877 addHeaderField(

880 addHeaderField(

883 }

884

885 if (!IsOpenCL) {

886 llvm::Value *blockFnPtr =

887 llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);

890 ->castAs()

892 addSignedHeaderField(

893 blockFnPtr,

894 CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,

896

897 addSignedHeaderField(

898 descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,

900 } else if (auto *Helper =

901 CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {

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

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

904 addHeaderField(

905 I.first,

907 CGM.getDataLayout().getTypeAllocSize(I.first->getType())),

908 I.second);

909 }

910 } else

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

912 }

913

914

916

917

918 if (blockDecl->capturesCXXThis()) {

919 Address addr =

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

922 }

923

924

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

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

927 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);

928

929

931

933

934

935

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

937

938

939

941

942 if (blockDecl->isConversionFromLambda()) {

943

944

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

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

948

949 const CGBlockInfo::Capture &enclosingCapture =

951

952

955 "block.capture.addr");

956 } else {

957 auto I = LocalDeclMap.find(variable);

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

959 src = I->second;

960 }

961 } else {

962 DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),

963 CI.isNested(),

965 SourceLocation());

967 };

968

969

970

971

972

973 if (CI.isEscapingByref()) {

974

975 llvm::Value *byrefPointer;

976 if (CI.isNested())

977 byrefPointer = Builder.CreateLoad(src, "byref.capture");

978 else

980

981

982 Builder.CreateStore(byrefPointer, blockField);

983

984

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

986 if (blockDecl->isConversionFromLambda()) {

987

988

989 AggValueSlot Slot =

996 } else {

998 }

999

1000

1001 } else if (type->getAs()) {

1003

1004

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

1007 CGM.getCodeGenOpts().OptimizationLevel != 0) {

1008 llvm::Value *value = Builder.CreateLoad(src, "captured");

1009 Builder.CreateStore(value, blockField);

1010

1011

1012

1013

1014

1015

1016

1017

1019 type->isBlockPointerType()) {

1020

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

1023

1024

1025 Builder.CreateStore(value, blockField);

1026

1027

1028 } else {

1029

1030

1031 ImplicitParamDecl BlockFieldPseudoVar(getContext(), type,

1033

1034

1035

1036 DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),

1037 CI.isNested(),

1039

1041 &declRef, VK_PRValue, FPOptionsOverride());

1042

1043

1044

1047 false);

1048 }

1049

1050

1052 continue;

1053

1054

1055

1056 if (CI.isByRef())

1057 continue;

1058

1059

1062 continue;

1063

1065

1066

1067

1068

1069

1070

1071

1072 if (type.isConstQualified() &&

1074 CGM.getCodeGenOpts().OptimizationLevel != 0) {

1075 assert(CGM.getLangOpts().ObjCAutoRefCount &&

1076 "expected ObjC ARC to be enabled");

1080 } else {

1082 }

1083

1086 if (useArrayEHCleanup)

1088

1089

1090

1091

1092

1093 auto IsBlockDeclInRetExpr = [&]() {

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

1095 if (EWC)

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

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

1099 return true;

1100 return false;

1101 };

1102

1103 if (IsBlockDeclInRetExpr())

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

1105 else

1107 useArrayEHCleanup);

1108 }

1109

1110

1111

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

1114

1115 if (IsOpenCL) {

1116 CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn,

1118 }

1119

1120 return result;

1121}

1122

1123

1125 if (BlockDescriptorType)

1126 return BlockDescriptorType;

1127

1128 unsigned AddrSpace = 0;

1131 BlockDescriptorType = llvm::PointerType::get(getLLVMContext(), AddrSpace);

1132 return BlockDescriptorType;

1133}

1134

1136 if (GenericBlockLiteralType)

1137 return GenericBlockLiteralType;

1138

1140

1142

1143

1144

1145

1146

1147

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

1152 }

1153 GenericBlockLiteralType = llvm::StructType::create(

1154 StructFields, "struct.__opencl_block_literal_generic");

1155 } else {

1156

1157

1158

1159

1160

1161

1162

1163 GenericBlockLiteralType =

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

1166 }

1167

1168 return GenericBlockLiteralType;

1169}

1170

1173 llvm::CallBase **CallOrInvoke) {

1176 llvm::Type *GenBlockTy = CGM.getGenericBlockLiteralType();

1177 llvm::Value *Func = nullptr;

1181

1182 llvm::Value *FuncPtr = nullptr;

1183

1185

1186

1187

1188

1189 llvm::Type *GenericVoidPtrTy =

1190 CGM.getOpenCLRuntime().getGenericVoidPointerType();

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

1192 BlockPtr, GenericVoidPtrTy);

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

1196

1198

1199

1201 Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());

1202 else {

1203 FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);

1204 Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,

1206 }

1207 } else {

1208

1209 BlockPtr =

1211

1212 FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);

1213

1214

1217

1219

1220

1222 }

1223

1226 CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);

1227

1228

1230 if (auto &AuthSchema =

1231 CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {

1232 assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");

1233 PointerAuth =

1235 }

1236

1238

1239

1241}

1242

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

1246

1247

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

1249

1251 "block.capture.addr");

1252

1254

1255

1256

1258 addr = Address(Builder.CreateLoad(addr), byrefInfo.Type,

1259 byrefInfo.ByrefAlignment);

1260

1263 }

1264

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

1268 "reference type");

1271

1272 return addr;

1273}

1274

1276 llvm::Constant *Addr) {

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

1278 (void)Ok;

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

1280}

1281

1282llvm::Constant *

1284 StringRef Name) {

1286 return Block;

1287

1290

1291

1293

1294

1295 {

1298 GlobalDecl(), blockInfo, LocalDeclMap,

1299 false, true);

1300 }

1301

1303}

1304

1307 llvm::Constant *blockFn) {

1309

1310

1311

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

1314

1315

1318

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

1322 if (!IsOpenCL) {

1323

1324 if (IsWindows)

1326 else

1328 CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),

1330

1331

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

1337

1339

1340

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

1342 } else {

1345 }

1346

1347

1348 if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {

1353 fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);

1354 } else

1355 fields.add(blockFn);

1356

1357 if (!IsOpenCL) {

1358

1360 fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,

1362 } else if (auto *Helper =

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

1365 fields.add(I);

1366 }

1367 }

1368

1369 unsigned AddrSpace = 0;

1372

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

1374 "__block_literal_global", blockInfo.BlockAlign,

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

1376

1377 literal->addAttribute("objc_arc_inert");

1378

1379

1380

1381 if (IsWindows) {

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

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

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

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

1390 b.CreateRetVoid();

1391

1392

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

1394 true, llvm::GlobalValue::InternalLinkage,

1395 Init, ".block_isa_init_ptr");

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

1398 }

1399

1400

1401 llvm::Type *RequiredType =

1403 llvm::Constant *Result =

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

1410 literal->getValueType());

1411 return Result;

1412}

1413

1415 unsigned argNum,

1416 llvm::Value *arg) {

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

1418

1419

1420

1422 Builder.CreateStore(arg, alloc);

1424 if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {

1426 DI->EmitDeclareOfBlockLiteralArgVariable(

1430 }

1431 }

1432

1435

1436

1437

1439 arg,

1440 llvm::PointerType::get(

1444 : 0),

1445 "block");

1446}

1447

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

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

1452}

1453

1456 bool IsLambdaConversionToBlock, bool BuildGlobalBlock) {

1458

1460

1462

1464

1465

1466

1467

1468 for (const auto &KV : ldm) {

1469 const auto *var = dyn_cast(KV.first);

1470 if (var && !var->hasLocalStorage())

1471 setAddrOfLocalVar(var, KV.second);

1472 }

1473

1474

1475

1476

1478

1479

1480

1482

1483

1484

1485

1486

1490

1491 const IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");

1492

1496 args.push_back(&SelfDecl);

1497

1498

1500

1501

1504 CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args);

1505 if (CGM.ReturnSlotInterferesWithArgs(fnInfo))

1507

1508 llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);

1509

1510 StringRef name = CGM.getBlockMangledName(GD, blockDecl);

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

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

1513 CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);

1514

1515 if (BuildGlobalBlock) {

1517 ? CGM.getOpenCLRuntime().getGenericVoidPointerType()

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

1521 }

1522

1523

1527

1528

1529

1530

1531

1532 llvm::Value *BlockPointerDbgLoc = BlockPointer;

1533 if (CGM.getCodeGenOpts().OptimizationLevel == 0) {

1534

1537 "block.addr");

1538

1539

1543 }

1544

1545

1546

1547 if (blockDecl->capturesCXXThis()) {

1550 CXXThisValue = Builder.CreateLoad(addr, "this");

1551 }

1552

1553

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

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

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

1558

1562

1564

1565 setAddrOfLocalVar(variable, alloca);

1566 }

1567

1568

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

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

1571 --entry_ptr;

1572

1573 if (IsLambdaConversionToBlock)

1575 else {

1579 }

1580

1581

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

1583

1584

1585 if (entry_ptr->getNextNode())

1586 entry_ptr = entry_ptr->getNextNode()->getIterator();

1587 else

1588 entry_ptr = entry->end();

1589 Builder.SetInsertPoint(entry, entry_ptr);

1590

1591

1592

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

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

1597

1598 if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {

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

1602 (void)DI->EmitDeclareOfAutoVariable(

1604 continue;

1605 }

1606

1607 DI->EmitDeclareOfBlockDeclRefVariable(

1608 variable, BlockPointerDbgLoc, Builder, blockInfo,

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

1610 }

1611 }

1612

1613 DI->EmitLocation(Builder,

1615 }

1616

1617

1618 if (resume == nullptr)

1619 Builder.ClearInsertionPoint();

1620 else

1621 Builder.SetInsertPoint(resume);

1622

1624

1625 return fn;

1626}

1627

1628static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

1633

1635 }

1639 if (T.isObjCGCWeak())

1642 }

1643

1644 if (T.hasAddressDiscriminatedPointerAuth())

1645 return std::make_pair(

1647

1652

1653 switch (T.isNonTrivialToPrimitiveCopy()) {

1658

1661

1662

1663

1664

1667 Flags);

1669 return std::make_pair(

1674 if (T->isObjCRetainableType())

1675

1677

1678

1679

1680 if (T->isObjCInertUnsafeUnretainedType())

1682

1683

1685

1686

1687

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

1690

1691

1693 }

1694 }

1695 llvm_unreachable("after exhaustive PrimitiveCopyKind switch");

1696}

1697

1698namespace {

1699

1700struct CallBlockRelease final : EHScopeStack::Cleanup {

1701 Address Addr;

1702 BlockFieldFlags FieldFlags;

1703 bool LoadBlockVarAddr, CanThrow;

1704

1705 CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue,

1706 bool CT)

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

1709

1710 void Emit(CodeGenFunction &CGF, Flags flags) override {

1711 llvm::Value *BlockVarAddr;

1712 if (LoadBlockVarAddr) {

1714 } else {

1715 BlockVarAddr = Addr.emitRawPointer(CGF);

1716 }

1717

1719 }

1720};

1721}

1722

1723

1725 if (const auto *RD = T->getAsCXXRecordDecl())

1728 return false;

1729}

1730

1731

1733 CaptureStrKind StrKind,

1736 std::string Str;

1740

1743

1744

1745

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

1749 "different operations and flags");

1750

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

1754 } else {

1757 }

1758

1759 switch (Kind) {

1761 Str += "c";

1763 llvm::raw_svector_ostream Out(TyStr);

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

1766 break;

1767 }

1769 Str += "w";

1770 break;

1772 Str += "s";

1773 break;

1776 assert(PtrAuth && PtrAuth.isAddressDiscriminated());

1777 Str += "p" + llvm::to_string(PtrAuth.getKey()) + "d" +

1778 llvm::to_string(PtrAuth.getExtraDiscriminator());

1779 break;

1780 }

1785 Str += "r";

1787 Str += "w";

1788 else {

1789

1790

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

1793 Str += "c";

1794 }

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

1797 Str += "d";

1798 }

1799 }

1800 } else {

1803 Str += "b";

1804 else

1805 Str += "o";

1806 }

1807 break;

1808 }

1812

1813 Str += "n";

1814 std::string FuncStr;

1815 if (StrKind == CaptureStrKind::DisposeHelper)

1817 CaptureTy, Alignment, IsVolatile, Ctx);

1818 else

1819

1820

1822 CaptureTy, Alignment, IsVolatile, Ctx);

1823

1824

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

1826 break;

1827 }

1829 break;

1830 }

1831

1832 return Str;

1833}

1834

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

1839 StrKind == CaptureStrKind::DisposeHelper) &&

1840 "unexpected CaptureStrKind");

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

1842 ? "__copy_helper_block_"

1843 : "__destroy_helper_block_";

1845 Name += "e";

1846 if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)

1847 Name += "a";

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

1849

1850 for (auto &Cap : Captures) {

1851 if (Cap.isConstantOrTrivial())

1852 continue;

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

1855 }

1856

1857 return Name;

1858}

1859

1864 bool EHOnly = ForCopyHelper;

1865

1866 switch (CaptureKind) {

1881 }

1882 break;

1883 }

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

1887

1888

1889

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

1894 }

1895 break;

1896 }

1899 break;

1900 }

1901}

1902

1904 llvm::Function *Fn,

1907 if (CapturesNonExternalType) {

1909 } else {

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

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

1914 }

1915}

1916

1917

1918

1919

1920

1921

1922

1923

1924llvm::Constant *

1928 CaptureStrKind::CopyHelper, CGM);

1929

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

1931 return Func;

1932

1934

1936

1939 args.push_back(&DstDecl);

1941 args.push_back(&SrcDecl);

1942

1944 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);

1945

1946

1947

1948 llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);

1949

1950 llvm::Function *Fn =

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

1952 FuncName, &CGM.getModule());

1953 if (CGM.supportsCOMDAT())

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

1955

1957 ArgTys.push_back(C.VoidPtrTy);

1958 ArgTys.push_back(C.VoidPtrTy);

1959

1964

1968

1972

1975 continue;

1976

1980

1984

1987

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

1990 break;

1993 break;

1999

2000 continue;

2001 }

2003

2004

2008 break;

2009 }

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

2012

2013

2014

2015 if (CGM.getCodeGenOpts().OptimizationLevel == 0) {

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

2018 Builder.CreateStore(null, dstField);

2020

2021

2022

2023

2024 } else {

2026

2027

2028

2029

2031 if (auto *I = cast_or_nullllvm::Instruction(

2033 I->eraseFromParent();

2034 }

2035 break;

2036 }

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

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

2040 llvm::Value *args[] = {

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

2042 };

2043

2046 else

2048 break;

2049 }

2051 continue;

2052 }

2053

2054

2055

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

2058 }

2059

2061

2062 return Fn;

2063}

2064

2069 if (T->isBlockPointerType())

2071 return Flags;

2072}

2073

2074static std::pair<BlockCaptureEntityKind, BlockFieldFlags>

2079 if (T.isObjCGCWeak())

2082 }

2083

2084 switch (T.isDestructedType()) {

2088

2089

2093

2100

2101

2102

2103 if (T->isObjCRetainableType() && T.getQualifiers().hasObjCLifetime() &&

2104 !LangOpts.ObjCAutoRefCount && T->isObjCInertUnsafeUnretainedType())

2107

2109 }

2110 }

2111 llvm_unreachable("after exhaustive DestructionKind switch");

2112}

2113

2114

2115

2116

2117

2118

2119

2120

2121llvm::Constant *

2125 CaptureStrKind::DisposeHelper, CGM);

2126

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

2128 return Func;

2129

2131

2133

2136 args.push_back(&SrcDecl);

2137

2139 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);

2140

2141

2142

2143 llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);

2144

2145 llvm::Function *Fn =

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

2147 FuncName, &CGM.getModule());

2148 if (CGM.supportsCOMDAT())

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

2150

2152 ArgTys.push_back(C.VoidPtrTy);

2153

2158

2160

2164

2166

2169 continue;

2170

2173

2175

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

2179 }

2180

2182

2184

2185 return Fn;

2186}

2187

2188namespace {

2189

2190

2193

2194public:

2197

2199 Address srcField) override {

2201

2204

2206

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

2209

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

2212 }

2213

2214 void emitDispose(CodeGenFunction &CGF, Address field) override {

2217

2219 }

2220

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

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

2223 }

2224};

2225

2226

2228public:

2229 ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}

2230

2231 void emitCopy(CodeGenFunction &CGF, Address destField,

2232 Address srcField) override {

2234 }

2235

2236 void emitDispose(CodeGenFunction &CGF, Address field) override {

2238 }

2239

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

2241

2242 id.AddInteger(0);

2243 }

2244};

2245

2246

2247

2249public:

2250 ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}

2251

2252 void emitCopy(CodeGenFunction &CGF, Address destField,

2253 Address srcField) override {

2254

2255

2256

2258

2259 llvm::Value *null =

2261

2266 return;

2267 }

2270 }

2271

2272 void emitDispose(CodeGenFunction &CGF, Address field) override {

2274 }

2275

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

2277

2278 id.AddInteger(1);

2279 }

2280};

2281

2282

2283

2284class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {

2285public:

2286 ARCStrongBlockByrefHelpers(CharUnits alignment)

2287 : BlockByrefHelpers(alignment) {}

2288

2289 void emitCopy(CodeGenFunction &CGF, Address destField,

2290 Address srcField) override {

2291

2292

2293

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

2297 }

2298

2299 void emitDispose(CodeGenFunction &CGF, Address field) override {

2301 }

2302

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

2304

2305 id.AddInteger(2);

2306 }

2307};

2308

2309

2310

2312 QualType VarType;

2313 const Expr *CopyExpr;

2314

2315public:

2316 CXXByrefHelpers(CharUnits alignment, QualType type,

2317 const Expr *copyExpr)

2318 : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}

2319

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

2321 void emitCopy(CodeGenFunction &CGF, Address destField,

2322 Address srcField) override {

2323 if (!CopyExpr) return;

2325 }

2326

2327 void emitDispose(CodeGenFunction &CGF, Address field) override {

2328 EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();

2331 }

2332

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

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

2335 }

2336};

2337

2338

2339

2340class AddressDiscriminatedByrefHelpers final : public BlockByrefHelpers {

2341 QualType VarType;

2342

2343public:

2344 AddressDiscriminatedByrefHelpers(CharUnits Alignment, QualType Type)

2345 : BlockByrefHelpers(Alignment), VarType(Type) {

2346 assert(Type.hasAddressDiscriminatedPointerAuth());

2347 }

2348

2349 void emitCopy(CodeGenFunction &CGF, Address DestField,

2350 Address SrcField) override {

2352 SrcField);

2353 }

2354

2355 bool needsDispose() const override { return false; }

2356 void emitDispose(CodeGenFunction &CGF, Address Field) override {

2357 llvm_unreachable("should never be called");

2358 }

2359

2360 void profileImpl(llvm::FoldingSetNodeID &ID) const override {

2361 ID.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());

2362 }

2363};

2364

2365

2366

2367class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {

2368 QualType VarType;

2369

2370public:

2371 NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type)

2372 : BlockByrefHelpers(alignment), VarType(type) {}

2373

2374 void emitCopy(CodeGenFunction &CGF, Address destField,

2375 Address srcField) override {

2378 }

2379

2380 bool needsDispose() const override {

2381 return VarType.isDestructedType();

2382 }

2383

2384 void emitDispose(CodeGenFunction &CGF, Address field) override {

2385 EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();

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

2388 }

2389

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

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

2392 }

2393};

2394}

2395

2396static llvm::Constant *

2400

2401 QualType ReturnTy = Context.VoidTy;

2402

2405 args.push_back(&Dst);

2406

2408 args.push_back(&Src);

2409

2412

2414

2415

2416

2417 llvm::Function *Fn =

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

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

2420

2422 ArgTys.push_back(Context.VoidPtrTy);

2423 ArgTys.push_back(Context.VoidPtrTy);

2424

2426

2428

2430

2432

2436 destField =

2438

2439

2443 srcField =

2445

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

2447 }

2448

2450

2451 return Fn;

2452}

2453

2454

2461

2462

2463static llvm::Constant *

2468 QualType R = Context.VoidTy;

2469

2473 args.push_back(&Src);

2474

2477

2479

2480

2481

2482 llvm::Function *Fn =

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

2484 "__Block_byref_object_dispose_",

2486

2488 ArgTys.push_back(Context.VoidPtrTy);

2489

2491

2493

2495

2501

2503 }

2504

2506

2507 return Fn;

2508}

2509

2510

2517

2518

2519

2520template

2522 T &&generator) {

2523 llvm::FoldingSetNodeID id;

2524 generator.Profile(id);

2525

2526 void *insertPos;

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

2530

2533

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

2536 return copy;

2537}

2538

2539

2540

2541

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

2544 const AutoVarEmission &emission) {

2545 const VarDecl &var = *emission.Variable;

2546 assert(var.isEscapingByref() &&

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

2548

2549 QualType type = var.getType();

2550

2552

2553

2554

2555 CharUnits valueAlignment =

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

2557

2558 if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {

2559 const Expr *copyExpr =

2560 CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr();

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

2562

2563 return ::buildByrefHelpers(

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

2565 }

2566 if (type.hasAddressDiscriminatedPointerAuth()) {

2567 return ::buildByrefHelpers(

2568 CGM, byrefInfo, AddressDiscriminatedByrefHelpers(valueAlignment, type));

2569 }

2570

2571

2574 return ::buildByrefHelpers(

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

2576

2577

2578

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

2580

2581 Qualifiers qs = type.getQualifiers();

2582

2583

2585 switch (lifetime) {

2587

2588

2591 return nullptr;

2592

2593

2594

2596 return ::buildByrefHelpers(CGM, byrefInfo,

2597 ARCWeakByrefHelpers(valueAlignment));

2598

2599

2601

2602

2603 if (type->isBlockPointerType()) {

2604 return ::buildByrefHelpers(CGM, byrefInfo,

2605 ARCStrongBlockByrefHelpers(valueAlignment));

2606

2607

2608

2609 } else {

2610 return ::buildByrefHelpers(CGM, byrefInfo,

2611 ARCStrongByrefHelpers(valueAlignment));

2612 }

2613 }

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

2615 }

2616

2617 BlockFieldFlags flags;

2618 if (type->isBlockPointerType()) {

2620 } else if (CGM.getContext().isObjCNSObjectType(type) ||

2621 type->isObjCObjectPointerType()) {

2623 } else {

2624 return nullptr;

2625 }

2626

2627 if (type.isObjCGCWeak())

2629

2630 return ::buildByrefHelpers(CGM, byrefInfo,

2631 ObjectByrefHelpers(valueAlignment, flags));

2632}

2633

2636 bool followForward) {

2639}

2640

2643 bool followForward,

2644 const llvm::Twine &name) {

2645

2646 if (followForward) {

2647 Address forwardingAddr = Builder.CreateStructGEP(baseAddr, 1, "forwarding");

2650 }

2651

2652 return Builder.CreateStructGEP(baseAddr, info.FieldIndex, name);

2653}

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2669

2671 auto it = BlockByrefInfos.find(D);

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

2673 return it->second;

2674

2676

2679

2680

2683

2684

2687

2688

2689 types.push_back(Int32Ty);

2691

2692

2693 types.push_back(Int32Ty);

2695

2696

2698 if (hasCopyAndDispose) {

2699

2702

2703

2706 }

2707

2708 bool HasByrefExtendedLayout = false;

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

2711 HasByrefExtendedLayout) {

2712

2715 }

2716

2717

2719

2720 bool packed = false;

2723

2724

2725 if (varOffset != size) {

2726 llvm::Type *paddingTy =

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

2728

2729 types.push_back(paddingTy);

2730 size = varOffset;

2731

2732

2733 } else if (CGM.getDataLayout().getABITypeAlign(varTy) >

2735 packed = true;

2736 }

2737 types.push_back(varTy);

2738

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

2741 packed);

2742

2744 info.Type = byrefType;

2748

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

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

2751 return pair.first->second;

2752}

2753

2754

2755

2757

2758 Address addr = emission.Addr;

2759

2760

2762

2763 unsigned nextHeaderIndex = 0;

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

2766 const Twine &name, bool isFunction = false) {

2767 auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);

2768 if (isFunction) {

2769 if (auto &Schema = CGM.getCodeGenOpts()

2770 .PointerAuth.BlockByrefHelperFunctionPointers) {

2774 }

2775 }

2776 Builder.CreateStore(value, fieldAddr);

2777

2778 nextHeaderIndex++;

2779 nextHeaderOffset += fieldSize;

2780 };

2781

2782

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

2784

2785 const VarDecl &D = *emission.Variable;

2787

2788 bool HasByrefExtendedLayout = false;

2790 bool ByRefHasLifetime =

2792

2793 llvm::Value *V;

2794

2795

2796 int isa = 0;

2797 if (type.isObjCGCWeak())

2798 isa = 1;

2801

2802

2804 "byref.forwarding");

2805

2806

2807

2808

2811 if (ByRefHasLifetime) {

2813 else switch (ByrefLifetime) {

2816 break;

2819 break;

2822 break;

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

2826 break;

2827 default:

2828 break;

2829 }

2830 if (CGM.getLangOpts().ObjCGCBitmapPrint) {

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

2833 printf(" BLOCK_BYREF_HAS_COPY_DISPOSE");

2837 printf(" BLOCK_BYREF_LAYOUT_EXTENDED");

2839 printf(" BLOCK_BYREF_LAYOUT_STRONG");

2841 printf(" BLOCK_BYREF_LAYOUT_WEAK");

2843 printf(" BLOCK_BYREF_LAYOUT_UNRETAINED");

2845 printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT");

2846 }

2848 }

2849 }

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

2852

2853 CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);

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

2856

2857 if (helpers) {

2859 true);

2861 "byref.disposeHelper", true);

2862 }

2863

2864 if (ByRefHasLifetime && HasByrefExtendedLayout) {

2865 auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);

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

2867 }

2868}

2869

2872 llvm::FunctionCallee F = CGM.getBlockObjectDispose();

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

2875

2878 else

2880}

2881

2884 bool LoadBlockVarAddr, bool CanThrow) {

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

2887}

2888

2889

2891 llvm::Constant *C) {

2893

2899

2902 "expected Function or GlobalVariable");

2903

2905 for (const auto *Result : DC->lookup(&II))

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

2907 (ND = dyn_cast(Result)))

2908 break;

2909

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

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

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

2913 } else {

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

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

2916 }

2917 }

2918

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

2920 GV->hasExternalLinkage())

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

2922

2924}

2925

2927 if (BlockObjectDispose)

2928 return BlockObjectDispose;

2929

2930 QualType args[] = {Context.VoidPtrTy, Context.IntTy};

2931 BlockObjectDispose =

2935 return BlockObjectDispose;

2936}

2937

2939 if (BlockObjectAssign)

2940 return BlockObjectAssign;

2941

2942 QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy};

2943 BlockObjectAssign =

2947 return BlockObjectAssign;

2948}

2949

2951 if (NSConcreteGlobalBlock)

2952 return NSConcreteGlobalBlock;

2953

2957 return NSConcreteGlobalBlock;

2958}

2959

2961 if (NSConcreteStackBlock)

2962 return NSConcreteStackBlock;

2963

2967 return NSConcreteStackBlock;

2968}

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.

Definition CGBlocks.cpp:2511

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

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

Definition CGBlocks.cpp:151

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

Definition CGBlocks.cpp:389

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

Generate code for a __block variable's dispose helper.

Definition CGBlocks.cpp:2464

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

Definition CGBlocks.cpp:533

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

Definition CGBlocks.cpp:1835

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

Definition CGBlocks.cpp:85

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

Build the helper function to copy a block.

Definition CGBlocks.cpp:56

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

Definition CGBlocks.cpp:1732

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

It is illegal to modify a const object after initialization.

Definition CGBlocks.cpp:444

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

Definition CGBlocks.cpp:2397

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

Definition CGBlocks.cpp:2075

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

Build the copy helper for a __block variable.

Definition CGBlocks.cpp:2455

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

Definition CGBlocks.cpp:2066

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

Compute the layout of the given block.

Definition CGBlocks.cpp:552

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.

Definition CGBlocks.cpp:2521

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

Build the given block as a global block.

Definition CGBlocks.cpp:1305

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

Build the helper function to dispose of a block.

Definition CGBlocks.cpp:62

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

Adjust the declaration of something from the blocks API.

Definition CGBlocks.cpp:2890

static bool isSafeForCXXConstantCapture(QualType type)

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

Definition CGBlocks.cpp:422

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

Definition CGBlocks.cpp:1860

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

Definition CGBlocks.cpp:1629

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

Definition CGBlocks.cpp:1903

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

Definition CGBlocks.cpp:480

static CharUnits getLowBit(CharUnits v)

Get the low bit of a nonzero character count.

Definition CGBlocks.cpp:476

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

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

static QualType getPointeeType(const MemRegion *R)

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.

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.

PointerAuthOptions PointerAuth

Configuration for pointer-signing.

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

llvm::Value * getPointerIfNotSigned() 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()

Definition CGBlocks.cpp:48

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)

Definition CGBlocks.cpp:35

StringRef Name

Name - The name of the block, kindof.

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)

llvm::LoadInst * CreateLoad(Address Addr, 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 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

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)

Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.

void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})

Force the emission of cleanups now, instead of waiting until this object is destroyed.

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

GlobalDecl CurGD

CurGD - The GlobalDecl for the current function being compiled.

void EmitARCMoveWeak(Address dst, Address src)

void @objc_moveWeak(i8** dest, i8** src) Disregards the current value in dest.

void emitByrefStructureInit(const AutoVarEmission &emission)

Initialize the structural components of a __block variable, i.e.

Definition CGBlocks.cpp:2756

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

Definition CGBlocks.cpp:2870

SanitizerSet SanOpts

Sanitizers enabled for this function.

void callCStructMoveConstructor(LValue Dst, LValue Src)

Address LoadBlockStruct()

Definition CGBlocks.cpp:1448

llvm::Type * ConvertType(QualType T)

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

Emits a call or invoke instruction to the given runtime function.

void EmitARCDestroyWeak(Address addr)

void @objc_destroyWeak(i8** addr) Essentially objc_storeWeak(addr, nil).

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

Definition CGBlocks.cpp:1171

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

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

Enter a cleanup to destroy a __block variable.

Definition CGBlocks.cpp:2882

const LangOptions & getLangOpts() const

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

Definition CGBlocks.cpp:1454

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

pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.

const CodeGen::CGBlockInfo * BlockInfo

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

Generate the copy-helper function for a block closure object: static void block_copy_helper(block_t *...

Definition CGBlocks.cpp:1925

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

const BlockByrefInfo & getBlockByrefInfo(const VarDecl *var)

BuildByrefInfo - This routine changes a __block variable declared as T x into:

Definition CGBlocks.cpp:2670

Destroyer * getDestroyer(QualType::DestructionKind destructionKind)

void PushDestructorCleanup(QualType T, Address Addr)

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

static bool cxxDestructorCanThrow(QualType T)

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

Definition CGBlocks.cpp:1724

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

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.

const Expr * RetExpr

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

Address GetAddrOfBlockDecl(const VarDecl *var)

Definition CGBlocks.cpp:1243

void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise)

Destroy a __strong variable.

static Destroyer destroyARCStrongImprecise

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.

llvm::Value * EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer)

void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn)

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

llvm::Value * BlockPointer

LValue EmitDeclRefLValue(const DeclRefExpr *E)

void callCStructCopyConstructor(LValue Dst, LValue Src)

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

Retain the given block, with _Block_copy semantics.

CGDebugInfo * getDebugInfo()

llvm::Value * EmitBlockLiteral(const BlockExpr *)

Emit block literal.

Definition CGBlocks.cpp:764

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...

Definition CGBlocks.cpp:2634

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...

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,...

CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType)

Emit the concrete pointer authentication informaton for the given authentication schema.

void EmitPointerAuthCopy(PointerAuthQualifier Qualifier, QualType Type, Address DestField, Address SrcField)

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

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

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

ASTContext & getContext() const

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

const Decl * CurFuncDecl

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

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

bool needsEHCleanup(QualType::DestructionKind kind)

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

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

EmitStmt - Emit the code for the statement.

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

CleanupKind getCleanupKind(QualType::DestructionKind kind)

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

Retain the given object, with normal retain semantics.

llvm::Type * ConvertTypeForMem(QualType T)

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

void EmitLambdaBlockInvokeBody()

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...

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

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

Definition CGBlocks.cpp:1414

void EmitAggExpr(const Expr *E, AggValueSlot AS)

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

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

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

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

EmitCallArgs - Emit call arguments for a function.

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

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

llvm::Value * LoadCXXThis()

LoadCXXThis - Load the value of 'this'.

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

Store into a strong object.

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

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

Generate the destroy-helper function for a block closure object: static void block_destroy_helper(blo...

Definition CGBlocks.cpp:2122

llvm::LLVMContext & getLLVMContext()

void EmitARCCopyWeak(Address dst, Address src)

void @objc_copyWeak(i8** dest, i8** src) Disregards the current value in dest.

static Destroyer emitARCIntrinsicUse

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...

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

llvm::FunctionCallee getBlockObjectAssign()

Definition CGBlocks.cpp:2938

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.

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

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

Definition CGBlocks.cpp:1275

llvm::Type * getBlockDescriptorType()

Fetches the type of a generic block descriptor.

Definition CGBlocks.cpp:1124

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

Gets the address of a block which requires no captures.

Definition CGBlocks.cpp:1283

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()

Definition CGBlocks.cpp:2950

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...

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()

Definition CGBlocks.cpp:2960

bool supportsCOMDAT() const

const TargetCodeGenInfo & getTargetCodeGenInfo()

const CodeGenOptions & getCodeGenOpts() const

llvm::FunctionCallee getBlockObjectDispose()

Definition CGBlocks.cpp:2926

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.

Definition CGBlocks.cpp:1135

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, StringRef GlobalName=".str")

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

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 & 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.

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.

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.

SourceLocation getLocation() const

This represents one expression.

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.

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.

std::string getNameAsString() const

Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...

Pointer-authentication qualifiers.

bool isAddressDiscriminated() const

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

PointerAuthQualifier getPointerAuth() const

@ 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_PtrAuth

The type is an address-discriminated signed pointer type.

@ 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

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)

CXXRecordDecl * getAsCXXRecordDecl() const

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

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.

const T * getAs() const

Member-template getAs'.

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

@ Type

The l-value was considered opaque, so the alignment was determined from a type.

@ 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...

@ AddressDiscriminatedPointerAuth

@ 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 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)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

const FunctionProtoType * T

static bool isBlockPointer(Expr *Arg)

@ Type

The name was classified as a type.

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.

U cast(CodeGen::Address addr)

@ Other

Other implicit parameter.

@ ObjCSelf

Parameter for Objective-C 'self' argument.

unsigned long ulong

An unsigned 64-bit integer.

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

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

CharUnits getPointerAlign() const

llvm::PointerType * DefaultPtrTy

PointerAuthSchema BlockHelperFunctionPointers

The ABI for block object copy/destroy function pointers.