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 (.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 (->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 && ->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 (->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 (->isObjCObjectPointerType() &&
->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