26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/Module.h"
28#include "llvm/Support/ScopedPrinter.h"
44 name.consume_front(
"\01");
53 llvm::Constant *blockFn);
69enum class CaptureStrKind {
81 CaptureStrKind StrKind,
82 CharUnits BlockAlignment,
87 std::string Name =
"__block_descriptor_";
98 if (Cap.isConstantOrTrivial())
101 Name += llvm::to_string(Cap.getOffset().getQuantity());
103 if (Cap.CopyKind == Cap.DisposeKind) {
107 "shouldn't see BlockCaptureManagedEntity that is None");
123 std::string TypeAtEncoding;
130 llvm::replace(TypeAtEncoding,
'@',
'\1');
132 Name +=
"e" + llvm::to_string(TypeAtEncoding.size()) +
"_" + TypeAtEncoding;
155 llvm::IntegerType *
ulong =
157 llvm::PointerType *i8p =
nullptr;
159 i8p = llvm::PointerType::get(
164 std::string descName;
167 if (
C.getLangOpts().ObjC &&
170 if (llvm::GlobalValue *desc = CGM.
getModule().getNamedValue(descName))
180 elements.addInt(
ulong, 0);
189 bool hasInternalHelper =
false;
201 ->hasInternalLinkage() ||
203 ->hasInternalLinkage())
204 hasInternalHelper =
true;
209 elements.addNullPointer(i8p);
211 std::string typeAtEncoding =
217 if (
C.getLangOpts().ObjC) {
224 elements.addNullPointer(i8p);
226 unsigned AddrSpace = 0;
227 if (
C.getLangOpts().OpenCL)
230 llvm::GlobalValue::LinkageTypes linkage;
231 if (descName.empty()) {
232 linkage = llvm::GlobalValue::InternalLinkage;
233 descName =
"__block_descriptor_tmp";
234 }
else if (hasInternalHelper) {
237 linkage = llvm::GlobalValue::InternalLinkage;
239 linkage = llvm::GlobalValue::LinkOnceODRLinkage;
242 llvm::GlobalVariable *global =
244 true, linkage, AddrSpace);
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);
269 struct objc_class *isa;
297 _ResultType (*invoke)(Block_literal *, _ParamTypes...);
300 struct Block_descriptor *block_descriptor;
303 _CapturesTypes captures...;
309 struct BlockLayoutChunk {
312 const BlockDecl::Capture *
Capture;
316 BlockFieldFlags CopyFlags, DisposeFlags;
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) {}
329 void setIndex(CGBlockInfo &info,
unsigned index, CharUnits offset) {
331 info.CXXThisIndex = index;
332 info.CXXThisOffset = offset;
335 index, offset, FieldType, CopyKind, CopyFlags, DisposeKind,
341 return CopyKind == BlockCaptureEntityKind::None &&
342 DisposeKind == BlockCaptureEntityKind::None;
349 bool operator<(
const BlockLayoutChunk &left,
const BlockLayoutChunk &right) {
350 if (left.Alignment != right.Alignment)
351 return left.Alignment > right.Alignment;
353 auto getPrefOrder = [](
const BlockLayoutChunk &chunk) {
354 switch (chunk.CopyKind) {
358 switch (chunk.CopyFlags.getBitMask()) {
377 return getPrefOrder(left) < getPrefOrder(right);
381static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
383 const LangOptions &LangOpts);
385static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
387 const LangOptions &LangOpts);
396 Layout.push_back(BlockLayoutChunk(
406 std::tie(CopyKind, CopyFlags) =
408 std::tie(DisposeKind, DisposeFlags) =
410 Layout.push_back(BlockLayoutChunk(align, size, capture,
type, fieldType,
411 CopyKind, CopyFlags, DisposeKind,
417 if (!Layout.back().isTrivial())
423 const auto *record =
type->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
430 if (!record->hasTrivialDestructor())
return false;
431 if (record->hasNonTrivialCopyConstructor())
return false;
435 return !record->hasMutableFields();
455 if (!
type.isConstQualified())
return nullptr;
468 const Expr *init = var->getInit();
469 if (!init)
return nullptr;
483 assert(elementTypes.empty());
493 assert((2 * CGM.
getIntSize()).isMultipleOf(GenPtrAlign));
494 elementTypes.push_back(CGM.
IntTy);
495 elementTypes.push_back(CGM.
IntTy);
496 elementTypes.push_back(
501 unsigned BlockAlign = GenPtrAlign.getQuantity();
504 for (
auto *I : Helper->getCustomFieldTypes()) {
507 unsigned Align = CGM.
getDataLayout().getABITypeAlign(I).value();
508 if (BlockAlign < Align)
510 assert(Offset % Align == 0);
512 elementTypes.push_back(I);
526 elementTypes.push_back(CGM.
IntTy);
527 elementTypes.push_back(CGM.
IntTy);
542 return FD->getType();
555 const BlockDecl *block = info.getBlockDecl();
559 bool hasNonConstantCustomFields =
false;
560 if (
auto *OpenCLHelper =
562 hasNonConstantCustomFields =
563 !OpenCLHelper->areAllCustomFieldValuesConstant(info);
564 if (!block->
hasCaptures() && !hasNonConstantCustomFields) {
567 info.CanBeGlobal =
true;
569 }
else if (
C.getLangOpts().ObjC &&
571 info.HasCapturedVariableLayout =
true;
574 info.NoEscape =
true;
585 assert(CGF && isa_and_nonnull<CXXMethodDecl>(CGF->
CurFuncDecl) &&
586 "Can't capture 'this' outside a method");
593 maxFieldAlign = std::max(maxFieldAlign, TInfo.Align);
595 addBlockLayout(TInfo.Align, TInfo.Width,
nullptr, llvmType, thisType,
600 for (
const auto &CI : block->
captures()) {
601 const VarDecl *variable = CI.getVariable();
603 if (CI.isEscapingByref()) {
606 maxFieldAlign = std::max(maxFieldAlign, align);
611 "capture type differs from the variable type");
613 variable->
getType(), layout, info, CGM);
620 info.SortedCaptures.push_back(
629 if (CI.hasCopyExpr() || !record->hasTrivialDestructor()) {
630 info.HasCXXObject =
true;
631 if (!record->isExternallyVisible())
632 info.CapturesNonExternalType =
true;
638 maxFieldAlign = std::max(maxFieldAlign, align);
640 llvm::Type *llvmType =
643 addBlockLayout(align, size, &CI, llvmType, VT, layout, info, CGM);
647 if (layout.empty()) {
650 info.CanBeGlobal =
true;
651 info.buildCaptureMap();
658 llvm::stable_sort(layout);
661 info.BlockHeaderForcedGapOffset = info.BlockSize;
665 info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
682 if (endAlign < maxFieldAlign) {
684 li = layout.begin() + 1, le = layout.end();
688 for (; li != le && endAlign < li->Alignment; ++li)
695 for (; li != le; ++li) {
696 assert(endAlign >= li->Alignment);
698 li->setIndex(info, elementTypes.size(), blockSize);
699 elementTypes.push_back(li->Type);
700 blockSize += li->Size;
704 if (endAlign >= maxFieldAlign) {
710 layout.erase(first, li);
714 assert(endAlign ==
getLowBit(blockSize));
718 if (endAlign < maxFieldAlign) {
720 CharUnits padding = newBlockSize - blockSize;
724 if (blockSize == info.BlockHeaderForcedGapOffset) {
725 info.BlockHeaderForcedGapSize = padding;
728 elementTypes.push_back(llvm::ArrayType::get(CGM.
Int8Ty,
730 blockSize = newBlockSize;
734 assert(endAlign >= maxFieldAlign);
735 assert(endAlign ==
getLowBit(blockSize));
740 li = layout.begin(), le = layout.end(); li != le; ++li) {
741 if (endAlign < li->Alignment) {
745 CharUnits padding = li->Alignment - endAlign;
746 elementTypes.push_back(llvm::ArrayType::get(CGM.
Int8Ty,
748 blockSize += padding;
751 assert(endAlign >= li->Alignment);
752 li->setIndex(info, elementTypes.size(), blockSize);
753 elementTypes.push_back(li->Type);
754 blockSize += li->Size;
758 info.buildCaptureMap();
767 if (!
blockExpr->getBlockDecl()->hasCaptures())
784 llvm::PointerType *GenVoidPtrTy =
795 auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
804 assert(blockAddr.
isValid() &&
"block has no address!");
807 llvm::Constant *descriptor;
813 llvm::Constant *blockISA = blockInfo.
NoEscape
836 auto projectField = [&](
unsigned index,
const Twine &name) ->
Address {
837 return Builder.CreateStructGEP(blockAddr,
index, name);
839 auto storeField = [&](llvm::Value *value,
unsigned index,
const Twine &
name) {
840 Builder.CreateStore(value, projectField(index, name));
848 auto addHeaderField = [&](llvm::Value *value, CharUnits size,
850 storeField(value, index, name);
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);
860 Schema, StorageAddress.emitRawPointer(*
this),
Decl,
Type);
869 addSignedHeaderField(
870 isa,
CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers, GlobalDecl(),
886 llvm::Value *blockFnPtr =
887 llvm::ConstantExpr::getBitCast(InvokeFn,
VoidPtrTy);
890 ->
castAs<BlockPointerType>()
892 addSignedHeaderField(
894 CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
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)) {
907 CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
911 addHeaderField(blockFn, GenVoidPtrSize,
"block.invoke");
920 projectField(blockInfo.
CXXThisIndex,
"block.captured-this.addr");
925 for (
const auto &CI :
blockDecl->captures()) {
926 const VarDecl *variable = CI.getVariable();
927 const CGBlockInfo::Capture &capture = blockInfo.
getCapture(variable);
936 Address blockField = projectField(capture.
getIndex(),
"block.captured");
942 if (
blockDecl->isConversionFromLambda()) {
946 }
else if (CI.isEscapingByref()) {
949 const CGBlockInfo::Capture &enclosingCapture =
955 "block.capture.addr");
957 auto I = LocalDeclMap.find(variable);
958 assert(I != LocalDeclMap.end());
962 DeclRefExpr declRef(
getContext(),
const_cast<VarDecl *
>(variable),
973 if (CI.isEscapingByref()) {
975 llvm::Value *byrefPointer;
977 byrefPointer =
Builder.CreateLoad(src,
"byref.capture");
982 Builder.CreateStore(byrefPointer, blockField);
985 }
else if (
const Expr *copyExpr = CI.getCopyExpr()) {
986 if (
blockDecl->isConversionFromLambda()) {
1001 }
else if (
type->getAs<ReferenceType>()) {
1005 }
else if (
type.isConstQualified() &&
1007 CGM.getCodeGenOpts().OptimizationLevel != 0) {
1008 llvm::Value *value =
Builder.CreateLoad(src,
"captured");
1009 Builder.CreateStore(value, blockField);
1019 type->isBlockPointerType()) {
1021 llvm::Value *value =
Builder.CreateLoad(src,
"block.captured_block");
1025 Builder.CreateStore(value, blockField);
1036 DeclRefExpr declRef(
getContext(),
const_cast<VarDecl *
>(variable),
1072 if (
type.isConstQualified() &&
1074 CGM.getCodeGenOpts().OptimizationLevel != 0) {
1075 assert(
CGM.getLangOpts().ObjCAutoRefCount &&
1076 "expected ObjC ARC to be enabled");
1086 if (useArrayEHCleanup)
1093 auto IsBlockDeclInRetExpr = [&]() {
1094 auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(
RetExpr);
1096 for (
auto &
C : EWC->getObjects())
1097 if (
auto *BD =
C.dyn_cast<BlockDecl *>())
1103 if (IsBlockDeclInRetExpr())
1104 pushDestroy(cleanupKind, blockField,
type, destroyer, useArrayEHCleanup);
1112 llvm::Value *result =
Builder.CreatePointerCast(
1125 if (BlockDescriptorType)
1126 return BlockDescriptorType;
1128 unsigned AddrSpace = 0;
1131 BlockDescriptorType = llvm::PointerType::get(
getLLVMContext(), AddrSpace);
1132 return BlockDescriptorType;
1136 if (GenericBlockLiteralType)
1137 return GenericBlockLiteralType;
1151 llvm::append_range(StructFields, Helper->getCustomFieldTypes());
1153 GenericBlockLiteralType = llvm::StructType::create(
1154 StructFields,
"struct.__opencl_block_literal_generic");
1163 GenericBlockLiteralType =
1164 llvm::StructType::create(
"struct.__block_literal_generic",
VoidPtrTy,
1168 return GenericBlockLiteralType;
1173 llvm::CallBase **CallOrInvoke) {
1176 llvm::Type *GenBlockTy =
CGM.getGenericBlockLiteralType();
1177 llvm::Value *
Func =
nullptr;
1182 llvm::Value *FuncPtr =
nullptr;
1189 llvm::Type *GenericVoidPtrTy =
1190 CGM.getOpenCLRuntime().getGenericVoidPointerType();
1191 llvm::Value *BlockDescriptor =
Builder.CreatePointerCast(
1192 BlockPtr, GenericVoidPtrTy);
1203 FuncPtr =
Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
1204 Func =
Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
1212 FuncPtr =
Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
1226 CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
1230 if (
auto &AuthSchema =
1231 CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
1232 assert(FuncPtr !=
nullptr &&
"Missing function pointer for AuthInfo");
1244 assert(
BlockInfo &&
"evaluating block ref without block information?");
1248 if (capture.
isConstant())
return LocalDeclMap.find(variable)->second;
1251 "block.capture.addr");
1259 byrefInfo.ByrefAlignment);
1267 "the capture field of a non-escaping variable should have a "
1276 llvm::Constant *
Addr) {
1277 bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE,
Addr)).second;
1279 assert(
Ok &&
"Trying to replace an already-existing global block!");
1307 llvm::Constant *blockFn) {
1313 "Refusing to re-emit a global block.");
1328 CGOPointerAuth.ObjCIsaPointers,
GlobalDecl(),
1341 fields.addInt(CGM.
IntTy, 0);
1348 if (
auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
1353 fields.addSignedPointer(blockFn, Schema,
GlobalDecl(), FnType);
1355 fields.add(blockFn);
1360 fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
1362 }
else if (
auto *Helper =
1364 for (
auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
1369 unsigned AddrSpace = 0;
1373 llvm::GlobalVariable *literal = fields.finishAndCreateGlobal(
1374 "__block_literal_global", blockInfo.
BlockAlign,
1375 !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
1377 literal->addAttribute(
"objc_arc_inert");
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),
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");
1401 llvm::Type *RequiredType =
1404 llvm::ConstantExpr::getPointerCast(literal, RequiredType);
1410 literal->getValueType());
1417 assert(
BlockInfo &&
"not emitting prologue of block invocation function?!");
1423 Builder.CreateStore(arg, alloc);
1425 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
1427 DI->EmitDeclareOfBlockLiteralArgVariable(
1441 llvm::PointerType::get(
1450 assert(
BlockInfo &&
"not in a block invocation function!");
1457 bool IsLambdaConversionToBlock,
bool BuildGlobalBlock) {
1469 for (
const auto &KV : ldm) {
1470 const auto *var = dyn_cast<VarDecl>(KV.first);
1471 if (var && !var->hasLocalStorage())
1472 setAddrOfLocalVar(var, KV.second);
1497 args.push_back(SelfDecl);
1505 CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args);
1506 if (
CGM.ReturnSlotInterferesWithArgs(fnInfo))
1509 llvm::FunctionType *fnLLVMType =
CGM.getTypes().GetFunctionType(fnInfo);
1511 StringRef name =
CGM.getBlockMangledName(GD,
blockDecl);
1512 llvm::Function *fn = llvm::Function::Create(
1513 fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &
CGM.getModule());
1514 CGM.SetInternalFunctionAttributes(
blockDecl, fn, fnInfo);
1516 if (BuildGlobalBlock) {
1518 ?
CGM.getOpenCLRuntime().getGenericVoidPointerType()
1521 llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));
1534 if (
CGM.getCodeGenOpts().OptimizationLevel == 0) {
1551 CXXThisValue =
Builder.CreateLoad(addr,
"this");
1555 for (
const auto &CI :
blockDecl->captures()) {
1556 const VarDecl *variable = CI.getVariable();
1562 "block.captured-const");
1566 setAddrOfLocalVar(variable, alloca);
1570 llvm::BasicBlock *entry =
Builder.GetInsertBlock();
1571 llvm::BasicBlock::iterator entry_ptr =
Builder.GetInsertPoint();
1574 if (IsLambdaConversionToBlock)
1584 llvm::BasicBlock *resume =
Builder.GetInsertBlock();
1587 if (entry_ptr->getNextNode())
1588 entry_ptr = entry_ptr->getNextNode()->getIterator();
1590 entry_ptr = entry->end();
1591 Builder.SetInsertPoint(entry, entry_ptr);
1596 for (
const auto &CI :
blockDecl->captures()) {
1597 const VarDecl *variable = CI.getVariable();
1600 if (
CGM.getCodeGenOpts().hasReducedDebugInfo()) {
1603 auto addr = LocalDeclMap.find(variable)->second;
1604 (void)DI->EmitDeclareOfAutoVariable(
1609 DI->EmitDeclareOfBlockDeclRefVariable(
1610 variable, BlockPointerDbgLoc,
Builder, blockInfo,
1611 entry_ptr == entry->end() ?
nullptr : &*entry_ptr);
1620 if (resume ==
nullptr)
1621 Builder.ClearInsertionPoint();
1623 Builder.SetInsertPoint(resume);
1630static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
1641 if (
T.isObjCGCWeak())
1646 if (
T.hasAddressDiscriminatedPointerAuth())
1647 return std::make_pair(
1655 switch (
T.isNonTrivialToPrimitiveCopy()) {
1671 return std::make_pair(
1676 if (!
T->isObjCRetainableType())
1682 if (
T->isObjCInertUnsafeUnretainedType())
1697 llvm_unreachable(
"after exhaustive PrimitiveCopyKind switch");
1702struct CallBlockRelease final : EHScopeStack::Cleanup {
1704 BlockFieldFlags FieldFlags;
1707 CallBlockRelease(Address
Addr, BlockFieldFlags Flags,
bool LoadValue,
1709 :
Addr(
Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),
1712 void Emit(CodeGenFunction &CGF, Flags flags)
override {
1713 llvm::Value *BlockVarAddr;
1714 if (LoadBlockVarAddr) {
1717 BlockVarAddr =
Addr.emitRawPointer(CGF);
1727 if (
const auto *RD =
T->getAsCXXRecordDecl())
1735 CaptureStrKind StrKind,
1748 assert((StrKind != CaptureStrKind::Merged ||
1751 "different operations and flags");
1753 if (StrKind == CaptureStrKind::DisposeHelper) {
1765 llvm::raw_svector_ostream Out(TyStr);
1767 Str += llvm::to_string(TyStr.size()) + TyStr.c_str();
1778 assert(PtrAuth && PtrAuth.isAddressDiscriminated());
1779 Str +=
"p" + llvm::to_string(PtrAuth.getKey()) +
"d" +
1780 llvm::to_string(PtrAuth.getExtraDiscriminator());
1793 if (StrKind != CaptureStrKind::DisposeHelper) {
1797 if (StrKind != CaptureStrKind::CopyHelper) {
1816 std::string FuncStr;
1817 if (StrKind == CaptureStrKind::DisposeHelper)
1819 CaptureTy, Alignment, IsVolatile, Ctx);
1824 CaptureTy, Alignment, IsVolatile, Ctx);
1827 Str += llvm::to_string(FuncStr.size()) +
"_" + FuncStr;
1840 assert((StrKind == CaptureStrKind::CopyHelper ||
1841 StrKind == CaptureStrKind::DisposeHelper) &&
1842 "unexpected CaptureStrKind");
1843 std::string Name = StrKind == CaptureStrKind::CopyHelper
1844 ?
"__copy_helper_block_"
1845 :
"__destroy_helper_block_";
1850 Name += llvm::to_string(BlockAlignment.
getQuantity()) +
"_";
1852 for (
auto &Cap : Captures) {
1853 if (Cap.isConstantOrTrivial())
1855 Name += llvm::to_string(Cap.getOffset().getQuantity());
1866 bool EHOnly = ForCopyHelper;
1868 switch (CaptureKind) {
1909 if (CapturesNonExternalType) {
1912 Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
1913 Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1930 CaptureStrKind::CopyHelper,
CGM);
1932 if (llvm::GlobalValue *
Func =
CGM.getModule().getNamedValue(FuncName))
1946 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
1950 llvm::FunctionType *LTy =
CGM.getTypes().GetFunctionType(FI);
1952 llvm::Function *Fn =
1953 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
1954 FuncName, &
CGM.getModule());
1955 if (
CGM.supportsCOMDAT())
1956 Fn->setComdat(
CGM.getModule().getOrInsertComdat(FuncName));
1986 assert(CI.
getCopyExpr() &&
"copy expression for variable is missing");
2009 llvm::Value *srcValue =
Builder.CreateLoad(srcField,
"blockcopy.src");
2013 if (
CGM.getCodeGenOpts().OptimizationLevel == 0) {
2015 llvm::Value *null = llvm::ConstantPointerNull::get(ty);
2016 Builder.CreateStore(null, dstField);
2029 if (
auto *I = cast_or_null<llvm::Instruction>(
2031 I->eraseFromParent();
2036 llvm::Value *srcValue =
Builder.CreateLoad(srcField,
"blockcopy.src");
2038 llvm::Value *args[] = {
2067 if (
T->isBlockPointerType())
2072static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
2077 if (
T.isObjCGCWeak())
2082 switch (
T.isDestructedType()) {
2101 if (
T->isObjCRetainableType() && !
T.getQualifiers().hasObjCLifetime() &&
2102 !LangOpts.ObjCAutoRefCount && !
T->isObjCInertUnsafeUnretainedType())
2109 llvm_unreachable(
"after exhaustive DestructionKind switch");
2123 CaptureStrKind::DisposeHelper,
CGM);
2125 if (llvm::GlobalValue *
Func =
CGM.getModule().getNamedValue(FuncName))
2137 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
2141 llvm::FunctionType *LTy =
CGM.getTypes().GetFunctionType(FI);
2143 llvm::Function *Fn =
2144 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
2145 FuncName, &
CGM.getModule());
2146 if (
CGM.supportsCOMDAT())
2147 Fn->setComdat(
CGM.getModule().getOrInsertComdat(FuncName));
2202 llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.
Int32Ty, flags);
2205 llvm::Value *args[] = {destField.
emitRawPointer(CGF), srcValue, flagsVal};
2209 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2216 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2217 id.AddInteger(Flags.getBitMask());
2224 ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
2226 void emitCopy(CodeGenFunction &CGF, Address destField,
2227 Address srcField)
override {
2231 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2235 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2245 ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
2247 void emitCopy(CodeGenFunction &CGF, Address destField,
2248 Address srcField)
override {
2267 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2271 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2281 ARCStrongBlockByrefHelpers(CharUnits alignment)
2282 : BlockByrefHelpers(alignment) {}
2284 void emitCopy(CodeGenFunction &CGF, Address destField,
2285 Address srcField)
override {
2294 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2298 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2308 const Expr *CopyExpr;
2311 CXXByrefHelpers(CharUnits alignment, QualType
type,
2312 const Expr *copyExpr)
2313 : BlockByrefHelpers(alignment), VarType(
type), CopyExpr(copyExpr) {}
2315 bool needsCopy()
const override {
return CopyExpr !=
nullptr; }
2316 void emitCopy(CodeGenFunction &CGF, Address destField,
2317 Address srcField)
override {
2318 if (!CopyExpr)
return;
2322 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2328 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2329 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2339 AddressDiscriminatedByrefHelpers(CharUnits Alignment, QualType
Type)
2340 : BlockByrefHelpers(Alignment), VarType(
Type) {
2341 assert(
Type.hasAddressDiscriminatedPointerAuth());
2344 void emitCopy(CodeGenFunction &CGF, Address DestField,
2345 Address SrcField)
override {
2350 bool needsDispose()
const override {
return false; }
2351 void emitDispose(CodeGenFunction &CGF, Address Field)
override {
2352 llvm_unreachable(
"should never be called");
2355 void profileImpl(llvm::FoldingSetNodeID &ID)
const override {
2356 ID.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2366 NonTrivialCStructByrefHelpers(CharUnits alignment, QualType
type)
2367 : BlockByrefHelpers(alignment), VarType(
type) {}
2369 void emitCopy(CodeGenFunction &CGF, Address destField,
2370 Address srcField)
override {
2375 bool needsDispose()
const override {
2376 return VarType.isDestructedType();
2379 void emitDispose(CodeGenFunction &CGF, Address field)
override {
2381 CGF.
pushDestroy(VarType.isDestructedType(), field, VarType);
2385 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2386 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2391static llvm::Constant *
2396 QualType ReturnTy = Context.VoidTy;
2411 llvm::Function *Fn =
2412 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
2436 generator.
emitCopy(CGF, destField, srcField);
2453static llvm::Constant *
2471 llvm::Function *Fn =
2472 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
2473 "__Block_byref_object_dispose_",
2509 llvm::FoldingSetNodeID id;
2510 generator.Profile(
id);
2512 llvm::FoldingSetInsertToken InsertToken;
2514 if (node)
return static_cast<T*
>(node);
2519 T *copy =
new (CGM.
getContext())
T(std::forward<T>(generator));
2528CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
2529 const AutoVarEmission &emission) {
2530 const VarDecl &
var = *emission.Variable;
2531 assert(
var.isEscapingByref() &&
2532 "only escaping __block variables need byref helpers");
2534 QualType
type =
var.getType();
2540 CharUnits valueAlignment =
2541 byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);
2543 if (
const CXXRecordDecl *record =
type->getAsCXXRecordDecl()) {
2544 const Expr *copyExpr =
2545 CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr();
2546 if (!copyExpr && record->hasTrivialDestructor())
return nullptr;
2548 return ::buildByrefHelpers(
2549 CGM, byrefInfo, CXXByrefHelpers(valueAlignment,
type, copyExpr));
2551 if (
type.hasAddressDiscriminatedPointerAuth()) {
2552 return ::buildByrefHelpers(
2553 CGM, byrefInfo, AddressDiscriminatedByrefHelpers(valueAlignment,
type));
2559 return ::buildByrefHelpers(
2560 CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment,
type));
2564 if (!
type->isObjCRetainableType())
return nullptr;
2566 Qualifiers qs =
type.getQualifiers();
2581 return ::buildByrefHelpers(
CGM, byrefInfo,
2582 ARCWeakByrefHelpers(valueAlignment));
2588 if (
type->isBlockPointerType()) {
2589 return ::buildByrefHelpers(
CGM, byrefInfo,
2590 ARCStrongBlockByrefHelpers(valueAlignment));
2595 return ::buildByrefHelpers(
CGM, byrefInfo,
2596 ARCStrongByrefHelpers(valueAlignment));
2599 llvm_unreachable(
"fell out of lifetime switch!");
2602 BlockFieldFlags flags;
2603 if (
type->isBlockPointerType()) {
2605 }
else if (
CGM.getContext().isObjCNSObjectType(
type) ||
2606 type->isObjCObjectPointerType()) {
2612 if (
type.isObjCGCWeak())
2615 return ::buildByrefHelpers(
CGM, byrefInfo,
2616 ObjectByrefHelpers(valueAlignment, flags));
2621 bool followForward) {
2629 const llvm::Twine &name) {
2631 if (followForward) {
2632 Address forwardingAddr =
Builder.CreateStructGEP(baseAddr, 1,
"forwarding");
2633 baseAddr =
Address(
Builder.CreateLoad(forwardingAddr), info.Type,
2634 info.ByrefAlignment);
2637 return Builder.CreateStructGEP(baseAddr, info.FieldIndex, name);
2656 auto it = BlockByrefInfos.find(D);
2657 if (it != BlockByrefInfos.end())
2683 if (hasCopyAndDispose) {
2693 bool HasByrefExtendedLayout =
false;
2695 if (
getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
2696 HasByrefExtendedLayout) {
2705 bool packed =
false;
2710 if (varOffset != size) {
2711 llvm::Type *paddingTy =
2712 llvm::ArrayType::get(
Int8Ty, (varOffset - size).getQuantity());
2714 types.push_back(paddingTy);
2718 }
else if (
CGM.getDataLayout().getABITypeAlign(varTy) >
2722 types.push_back(varTy);
2724 llvm::StructType *byrefType = llvm::StructType::create(
2729 info.Type = byrefType;
2730 info.FieldIndex = types.size() - 1;
2731 info.FieldOffset = varOffset;
2734 auto pair = BlockByrefInfos.insert({D, info});
2735 assert(pair.second &&
"info was inserted recursively?");
2736 return pair.first->second;
2748 unsigned nextHeaderIndex = 0;
2750 auto storeHeaderField = [&](llvm::Value *value,
CharUnits fieldSize,
2751 const Twine &name,
bool isFunction =
false) {
2752 auto fieldAddr =
Builder.CreateStructGEP(addr, nextHeaderIndex, name);
2754 if (
auto &Schema =
CGM.getCodeGenOpts()
2755 .PointerAuth.BlockByrefHelperFunctionPointers) {
2761 Builder.CreateStore(value, fieldAddr);
2764 nextHeaderOffset += fieldSize;
2770 const VarDecl &D = *emission.Variable;
2773 bool HasByrefExtendedLayout =
false;
2775 bool ByRefHasLifetime =
2782 if (
type.isObjCGCWeak())
2789 "byref.forwarding");
2796 if (ByRefHasLifetime) {
2798 else switch (ByrefLifetime) {
2809 if (!
type->isObjCObjectPointerType() && !
type->isBlockPointerType())
2815 if (
CGM.getLangOpts().ObjCGCBitmapPrint) {
2816 printf(
"\n Inline flag for BYREF variable layout (%d):", flags.
getBitMask());
2818 printf(
" BLOCK_BYREF_HAS_COPY_DISPOSE");
2822 printf(
" BLOCK_BYREF_LAYOUT_EXTENDED");
2824 printf(
" BLOCK_BYREF_LAYOUT_STRONG");
2826 printf(
" BLOCK_BYREF_LAYOUT_WEAK");
2828 printf(
" BLOCK_BYREF_LAYOUT_UNRETAINED");
2830 printf(
" BLOCK_BYREF_LAYOUT_NON_OBJECT");
2838 CharUnits byrefSize =
CGM.GetTargetTypeStoreSize(byrefType);
2846 "byref.disposeHelper",
true);
2849 if (ByRefHasLifetime && HasByrefExtendedLayout) {
2850 auto layoutInfo =
CGM.getObjCRuntime().BuildByrefLayout(
CGM,
type);
2857 llvm::FunctionCallee F =
CGM.getBlockObjectDispose();
2858 llvm::Value *args[] = {
V,
2869 bool LoadBlockVarAddr,
bool CanThrow) {
2870 EHStack.pushCleanup<CallBlockRelease>(Kind,
Addr, Flags, LoadBlockVarAddr,
2876 llvm::Constant *
C) {
2887 "expected Function or GlobalVariable");
2891 if ((ND = dyn_cast<FunctionDecl>(
Result)) ||
2892 (ND = dyn_cast<VarDecl>(
Result)))
2895 if (GV->isDeclaration() && (!ND || !ND->
hasAttr<DLLExportAttr>())) {
2896 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2897 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2899 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2900 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2904 if (CGM.
getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
2905 GV->hasExternalLinkage())
2906 GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
2912 if (BlockObjectDispose)
2913 return BlockObjectDispose;
2915 QualType args[] = {Context.VoidPtrTy, Context.IntTy};
2916 BlockObjectDispose =
2920 return BlockObjectDispose;
2924 if (BlockObjectAssign)
2925 return BlockObjectAssign;
2927 QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy};
2932 return BlockObjectAssign;
2936 if (NSConcreteGlobalBlock)
2937 return NSConcreteGlobalBlock;
2942 return NSConcreteGlobalBlock;
2946 if (NSConcreteStackBlock)
2947 return NSConcreteStackBlock;
2952 return NSConcreteStackBlock;
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.
Result
Implement __builtin_bit_cast and related operations.
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()
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)
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
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.
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.
void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags, bool CanThrow)
SanitizerSet SanOpts
Sanitizers enabled for this function.
void callCStructMoveConstructor(LValue Dst, LValue Src)
Address LoadBlockStruct()
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.
CGPointerAuthInfo EmitPointerAuthInfo(const PointerAuthSchema &Schema, llvm::Value *StorageAddress, llvm::ConstantInt *Discriminator)
void EmitARCDestroyWeak(Address addr)
void @objc_destroyWeak(i8** addr) Essentially objc_storeWeak(addr, nil).
RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)
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.
const LangOptions & getLangOpts() const
llvm::Function * GenerateBlockFunction(GlobalDecl GD, const CGBlockInfo &Info, const DeclMapTy &ldm, bool IsLambdaConversionToBlock, bool BuildGlobalBlock)
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 *...
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:
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.
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.
void maybeCreateMCDCCondBitmap()
Allocate a temp value on the stack that MCDC can use to track condition results.
const Expr * RetExpr
If a return statement is being visited, this holds the return statment's result expression.
Address GetAddrOfBlockDecl(const VarDecl *var)
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.
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...
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,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitPointerAuthCopy(PointerAuthQualifier Qualifier, QualType Type, Address DestField, Address SrcField)
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()
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum, llvm::Value *ptr)
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...
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
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()
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.
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...
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, 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.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
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<specific type>.
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<specific type>'.
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.
@ Address
A pointer to a ValueDecl.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Top level wrappers for InstallAPI frontend operations.
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.