25#include "llvm/ADT/SmallSet.h"
26#include "llvm/IR/DataLayout.h"
27#include "llvm/IR/Module.h"
28#include "llvm/Support/ScopedPrinter.h"
33using namespace CodeGen;
36 : Name(name), CXXThisIndex(0), CanBeGlobal(
false), NeedsCopyDispose(
false),
38 HasCapturedVariableLayout(
false), CapturesNonExternalType(
false),
39 LocalAddress(
Address::invalid()), StructureType(nullptr),
Block(block) {
43 if (!name.empty() && name[0] ==
'\01')
44 name = name.substr(1);
53 llvm::Constant *blockFn);
69enum class CaptureStrKind {
81 CaptureStrKind StrKind,
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 =
127 std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(),
'@',
'\1');
128 Name +=
"e" + llvm::to_string(TypeAtEncoding.size()) +
"_" + TypeAtEncoding;
151 llvm::IntegerType *
ulong =
153 llvm::PointerType *i8p =
nullptr;
155 i8p = llvm::PointerType::get(
160 std::string descName;
163 if (
C.getLangOpts().ObjC &&
166 if (llvm::GlobalValue *desc = CGM.
getModule().getNamedValue(descName))
167 return llvm::ConstantExpr::getBitCast(desc,
177 elements.addInt(
ulong, 0);
186 bool hasInternalHelper =
false;
190 elements.add(copyHelper);
194 elements.add(disposeHelper);
196 if (cast<llvm::Function>(copyHelper->stripPointerCasts())
197 ->hasInternalLinkage() ||
198 cast<llvm::Function>(disposeHelper->stripPointerCasts())
199 ->hasInternalLinkage())
200 hasInternalHelper =
true;
204 std::string typeAtEncoding =
206 elements.add(llvm::ConstantExpr::getBitCast(
210 if (
C.getLangOpts().ObjC) {
217 elements.addNullPointer(i8p);
219 unsigned AddrSpace = 0;
220 if (
C.getLangOpts().OpenCL)
223 llvm::GlobalValue::LinkageTypes linkage;
224 if (descName.empty()) {
225 linkage = llvm::GlobalValue::InternalLinkage;
226 descName =
"__block_descriptor_tmp";
227 }
else if (hasInternalHelper) {
230 linkage = llvm::GlobalValue::InternalLinkage;
232 linkage = llvm::GlobalValue::LinkOnceODRLinkage;
235 llvm::GlobalVariable *global =
237 true, linkage, AddrSpace);
239 if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) {
241 global->setComdat(CGM.
getModule().getOrInsertComdat(descName));
242 global->setVisibility(llvm::GlobalValue::HiddenVisibility);
243 global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
262 struct objc_class *isa;
290 _ResultType (*invoke)(Block_literal *, _ParamTypes...);
293 struct Block_descriptor *block_descriptor;
296 _CapturesTypes captures...;
302 struct BlockLayoutChunk {
318 FieldType(fieldType), CopyKind(CopyKind), DisposeKind(DisposeKind),
319 CopyFlags(CopyFlags), DisposeFlags(DisposeFlags) {}
328 index, offset, FieldType, CopyKind, CopyFlags, DisposeKind,
334 return CopyKind == BlockCaptureEntityKind::None &&
335 DisposeKind == BlockCaptureEntityKind::None;
342 bool operator<(
const BlockLayoutChunk &left,
const BlockLayoutChunk &right) {
343 if (left.Alignment != right.Alignment)
344 return left.Alignment > right.Alignment;
346 auto getPrefOrder = [](
const BlockLayoutChunk &chunk) {
347 switch (chunk.CopyKind) {
351 switch (chunk.CopyFlags.getBitMask()) {
370 return getPrefOrder(left) < getPrefOrder(right);
374static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
378static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
389 Layout.push_back(BlockLayoutChunk(
399 std::tie(CopyKind, CopyFlags) =
401 std::tie(DisposeKind, DisposeFlags) =
403 Layout.push_back(BlockLayoutChunk(align, size, capture,
type, fieldType,
404 CopyKind, CopyFlags, DisposeKind,
410 if (!Layout.back().isTrivial())
422 const auto *record = cast<CXXRecordDecl>(
recordType->getDecl());
425 if (!record->hasTrivialDestructor())
return false;
426 if (record->hasNonTrivialCopyConstructor())
return false;
430 return !record->hasMutableFields();
444 if (isa<ParmVarDecl>(var))
450 if (!
type.isConstQualified())
return nullptr;
464 if (!init)
return nullptr;
478 assert(elementTypes.empty());
488 assert((2 * CGM.
getIntSize()).isMultipleOf(GenPtrAlign));
489 elementTypes.push_back(CGM.
IntTy);
490 elementTypes.push_back(CGM.
IntTy);
491 elementTypes.push_back(
496 unsigned BlockAlign = GenPtrAlign.getQuantity();
499 for (
auto *I : Helper->getCustomFieldTypes()) {
502 unsigned Align = CGM.
getDataLayout().getABITypeAlign(I).value();
503 if (BlockAlign < Align)
505 assert(Offset % Align == 0);
507 elementTypes.push_back(I);
521 elementTypes.push_back(CGM.
IntTy);
522 elementTypes.push_back(CGM.
IntTy);
537 return FD->getType();
554 bool hasNonConstantCustomFields =
false;
555 if (
auto *OpenCLHelper =
557 hasNonConstantCustomFields =
558 !OpenCLHelper->areAllCustomFieldValuesConstant(info);
559 if (!block->
hasCaptures() && !hasNonConstantCustomFields) {
565 else if (
C.getLangOpts().ObjC &&
582 "Can't capture 'this' outside a method");
589 maxFieldAlign = std::max(maxFieldAlign, TInfo.Align);
591 addBlockLayout(TInfo.Align, TInfo.Width,
nullptr, llvmType, thisType,
596 for (
const auto &CI : block->
captures()) {
597 const VarDecl *variable = CI.getVariable();
599 if (CI.isEscapingByref()) {
602 maxFieldAlign = std::max(maxFieldAlign, align);
607 "capture type differs from the variable type");
609 variable->
getType(), layout, info, CGM);
625 if (CI.hasCopyExpr() || !record->hasTrivialDestructor()) {
627 if (!record->isExternallyVisible())
634 maxFieldAlign = std::max(maxFieldAlign, align);
636 llvm::Type *llvmType =
639 addBlockLayout(align, size, &CI, llvmType, VT, layout, info, CGM);
643 if (layout.empty()) {
654 llvm::stable_sort(layout);
678 if (endAlign < maxFieldAlign) {
680 li = layout.begin() + 1, le = layout.end();
684 for (; li != le && endAlign < li->Alignment; ++li)
691 for (; li != le; ++li) {
692 assert(endAlign >= li->Alignment);
694 li->setIndex(info, elementTypes.size(), blockSize);
695 elementTypes.push_back(li->Type);
696 blockSize += li->Size;
700 if (endAlign >= maxFieldAlign) {
706 layout.erase(first, li);
710 assert(endAlign ==
getLowBit(blockSize));
714 if (endAlign < maxFieldAlign) {
716 CharUnits padding = newBlockSize - blockSize;
724 elementTypes.push_back(llvm::ArrayType::get(CGM.
Int8Ty,
726 blockSize = newBlockSize;
730 assert(endAlign >= maxFieldAlign);
731 assert(endAlign ==
getLowBit(blockSize));
736 li = layout.begin(), le = layout.end(); li != le; ++li) {
737 if (endAlign < li->Alignment) {
741 CharUnits padding = li->Alignment - endAlign;
742 elementTypes.push_back(llvm::ArrayType::get(CGM.
Int8Ty,
744 blockSize += padding;
747 assert(endAlign >= li->Alignment);
748 li->setIndex(info, elementTypes.size(), blockSize);
749 elementTypes.push_back(li->Type);
750 blockSize += li->Size;
763 if (!
blockExpr->getBlockDecl()->hasCaptures())
772 if (!blockInfo.CanBeGlobal)
774 blockInfo.BlockAlign,
"block");
789 auto *InvokeFn = BlockCGF.GenerateBlockFunction(
791 auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
800 assert(blockAddr.
isValid() &&
"block has no address!");
803 llvm::Constant *descriptor;
809 llvm::Constant *blockISA = blockInfo.
NoEscape
812 isa = llvm::ConstantExpr::getBitCast(blockISA,
VoidPtrTy);
831 auto projectField = [&](
unsigned index,
const Twine &
name) ->
Address {
834 auto storeField = [&](llvm::Value *value,
unsigned index,
const Twine &
name) {
843 auto addHeaderField = [&](llvm::Value *value,
CharUnits size,
845 storeField(value, index, name);
864 addHeaderField(blockFn, GenVoidPtrSize,
"block.invoke");
867 else if (
auto *Helper =
869 for (
auto I : Helper->getCustomFieldValues(*
this, blockInfo)) {
885 projectField(blockInfo.
CXXThisIndex,
"block.captured-this.addr");
890 for (
const auto &CI :
blockDecl->captures()) {
891 const VarDecl *variable = CI.getVariable();
901 Address blockField = projectField(capture.
getIndex(),
"block.captured");
907 if (
blockDecl->isConversionFromLambda()) {
911 }
else if (CI.isEscapingByref()) {
920 "block.capture.addr");
922 auto I = LocalDeclMap.find(variable);
923 assert(I != LocalDeclMap.end());
938 if (CI.isEscapingByref()) {
940 llvm::Value *byrefPointer;
950 }
else if (
const Expr *copyExpr = CI.getCopyExpr()) {
951 if (
blockDecl->isConversionFromLambda()) {
966 }
else if (
type->isReferenceType()) {
970 }
else if (
type.isConstQualified() &&
984 type->isBlockPointerType()) {
1037 if (
type.isConstQualified() &&
1041 "expected ObjC ARC to be enabled");
1051 if (useArrayEHCleanup)
1058 auto IsBlockDeclInRetExpr = [&]() {
1059 auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(
RetExpr);
1061 for (
auto &
C : EWC->getObjects())
1068 if (IsBlockDeclInRetExpr())
1069 pushDestroy(cleanupKind, blockField,
type, destroyer, useArrayEHCleanup);
1077 llvm::Value *result =
Builder.CreatePointerCast(
1090 if (BlockDescriptorType)
1091 return BlockDescriptorType;
1093 llvm::Type *UnsignedLongTy =
1110 BlockDescriptorType = llvm::StructType::create(
1111 "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy);
1114 unsigned AddrSpace = 0;
1117 BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace);
1118 return BlockDescriptorType;
1122 if (GenericBlockLiteralType)
1123 return GenericBlockLiteralType;
1137 llvm::append_range(StructFields, Helper->getCustomFieldTypes());
1139 GenericBlockLiteralType = llvm::StructType::create(
1140 StructFields,
"struct.__opencl_block_literal_generic");
1149 GenericBlockLiteralType =
1150 llvm::StructType::create(
"struct.__block_literal_generic",
VoidPtrTy,
1154 return GenericBlockLiteralType;
1162 llvm::Value *Func =
nullptr;
1172 llvm::Type *GenericVoidPtrTy =
1174 llvm::Value *BlockDescriptor =
Builder.CreatePointerCast(
1175 BlockPtr, GenericVoidPtrTy);
1192 BlockPtr =
Builder.CreatePointerCast(
1193 BlockPtr, llvm::PointerType::get(GenBlockTy, 0),
"block.literal");
1214 llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
1215 Func =
Builder.CreatePointerCast(Func, BlockFTyPtr);
1225 assert(
BlockInfo &&
"evaluating block ref without block information?");
1229 if (capture.
isConstant())
return LocalDeclMap.find(variable)->second;
1232 "block.capture.addr");
1240 byrefInfo.ByrefAlignment);
1248 "the capture field of a non-escaping variable should have a "
1257 llvm::Constant *Addr) {
1258 bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;
1260 assert(Ok &&
"Trying to replace an already-existing global block!");
1288 llvm::Constant *blockFn) {
1294 "Refusing to re-emit a global block.");
1317 fields.addInt(CGM.
IntTy, 0);
1324 fields.add(blockFn);
1329 }
else if (
auto *Helper =
1331 for (
auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
1336 unsigned AddrSpace = 0;
1340 llvm::GlobalVariable *literal = fields.finishAndCreateGlobal(
1341 "__block_literal_global", blockInfo.
BlockAlign,
1342 !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
1344 literal->addAttribute(
"objc_arc_inert");
1349 auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
1350 {}), llvm::GlobalValue::InternalLinkage,
".block_isa_init",
1352 llvm::IRBuilder<>
b(llvm::BasicBlock::Create(CGM.
getLLVMContext(),
"entry",
1355 b.CreateStructGEP(literal->getValueType(), literal, 0),
1360 auto *InitVar =
new llvm::GlobalVariable(CGM.
getModule(), Init->getType(),
1361 true, llvm::GlobalValue::InternalLinkage,
1362 Init,
".block_isa_init_ptr");
1363 InitVar->setSection(
".CRT$XCLa");
1368 llvm::Type *RequiredType =
1371 llvm::ConstantExpr::getPointerCast(literal, RequiredType);
1376 cast<llvm::Function>(blockFn->stripPointerCasts()),
Result,
1377 literal->getValueType());
1384 assert(
BlockInfo &&
"not emitting prologue of block invocation function?!");
1393 DI->EmitDeclareOfBlockLiteralArgVariable(
1406 llvm::PointerType::get(
1415 assert(
BlockInfo &&
"not in a block invocation function!");
1422 bool IsLambdaConversionToBlock,
bool BuildGlobalBlock) {
1434 for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
1435 const auto *var = dyn_cast<VarDecl>(i->first);
1436 if (var && !var->hasLocalStorage())
1437 setAddrOfLocalVar(var, i->second);
1462 args.push_back(&SelfDecl);
1477 llvm::Function *fn = llvm::Function::Create(
1478 fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &
CGM.
getModule());
1481 if (BuildGlobalBlock) {
1486 llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));
1520 for (
const auto &CI :
blockDecl->captures()) {
1521 const VarDecl *variable = CI.getVariable();
1531 setAddrOfLocalVar(variable, alloca);
1535 llvm::BasicBlock *entry =
Builder.GetInsertBlock();
1536 llvm::BasicBlock::iterator entry_ptr =
Builder.GetInsertPoint();
1539 if (IsLambdaConversionToBlock)
1548 llvm::BasicBlock *resume =
Builder.GetInsertBlock();
1552 Builder.SetInsertPoint(entry, entry_ptr);
1557 for (
const auto &CI :
blockDecl->captures()) {
1558 const VarDecl *variable = CI.getVariable();
1564 auto addr = LocalDeclMap.find(variable)->second;
1565 (void)DI->EmitDeclareOfAutoVariable(variable, addr.
getPointer(),
1570 DI->EmitDeclareOfBlockDeclRefVariable(
1571 variable, BlockPointerDbgLoc,
Builder, blockInfo,
1572 entry_ptr == entry->end() ? nullptr : &*entry_ptr);
1577 cast<CompoundStmt>(
blockDecl->getBody())->getRBracLoc());
1581 if (resume ==
nullptr)
1582 Builder.ClearInsertionPoint();
1584 Builder.SetInsertPoint(resume);
1591static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
1650 llvm_unreachable(
"after exhaustive PrimitiveCopyKind switch");
1662 : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),
1666 llvm::Value *BlockVarAddr;
1667 if (LoadBlockVarAddr) {
1670 BlockVarAddr = Addr.getPointer();
1688 CaptureStrKind StrKind,
1701 assert((StrKind != CaptureStrKind::Merged ||
1704 "different operations and flags");
1706 if (StrKind == CaptureStrKind::DisposeHelper) {
1718 llvm::raw_svector_ostream Out(TyStr);
1720 Str += llvm::to_string(TyStr.size()) + TyStr.c_str();
1739 if (StrKind != CaptureStrKind::DisposeHelper) {
1743 if (StrKind != CaptureStrKind::CopyHelper) {
1762 std::string FuncStr;
1763 if (StrKind == CaptureStrKind::DisposeHelper)
1765 CaptureTy, Alignment, IsVolatile, Ctx);
1770 CaptureTy, Alignment, IsVolatile, Ctx);
1773 Str += llvm::to_string(FuncStr.size()) +
"_" + FuncStr;
1786 assert((StrKind == CaptureStrKind::CopyHelper ||
1787 StrKind == CaptureStrKind::DisposeHelper) &&
1788 "unexpected CaptureStrKind");
1789 std::string Name = StrKind == CaptureStrKind::CopyHelper
1790 ?
"__copy_helper_block_"
1791 :
"__destroy_helper_block_";
1796 Name += llvm::to_string(BlockAlignment.
getQuantity()) +
"_";
1798 for (
auto &Cap : Captures) {
1799 if (Cap.isConstantOrTrivial())
1801 Name += llvm::to_string(Cap.getOffset().getQuantity());
1812 bool EHOnly = ForCopyHelper;
1814 switch (CaptureKind) {
1854 if (CapturesNonExternalType) {
1857 Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
1858 Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1875 CaptureStrKind::CopyHelper,
CGM);
1877 if (llvm::GlobalValue *Func =
CGM.
getModule().getNamedValue(FuncName))
1878 return llvm::ConstantExpr::getBitCast(Func,
VoidPtrTy);
1886 args.push_back(&DstDecl);
1888 args.push_back(&SrcDecl);
1897 llvm::Function *Fn =
1898 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
1901 Fn->setComdat(
CGM.
getModule().getOrInsertComdat(FuncName));
1904 ArgTys.push_back(
C.VoidPtrTy);
1905 ArgTys.push_back(
C.VoidPtrTy);
1928 unsigned index = capture.
getIndex();
1935 assert(CI.
getCopyExpr() &&
"copy expression for variable is missing");
1955 auto *ty = cast<llvm::PointerType>(srcValue->getType());
1956 llvm::Value *null = llvm::ConstantPointerNull::get(ty);
1970 cast<llvm::Instruction>(dstField.
getPointer())->eraseFromParent();
1976 llvm::Value *dstAddr = dstField.
getPointer();
1977 llvm::Value *args[] = {
1999 return llvm::ConstantExpr::getBitCast(Fn,
VoidPtrTy);
2011static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
2048 llvm_unreachable(
"after exhaustive DestructionKind switch");
2062 CaptureStrKind::DisposeHelper,
CGM);
2064 if (llvm::GlobalValue *Func =
CGM.
getModule().getNamedValue(FuncName))
2065 return llvm::ConstantExpr::getBitCast(Func,
VoidPtrTy);
2073 args.push_back(&SrcDecl);
2082 llvm::Function *Fn =
2083 llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
2086 Fn->setComdat(
CGM.
getModule().getOrInsertComdat(FuncName));
2089 ArgTys.push_back(
C.VoidPtrTy);
2102 CodeGenFunction::RunCleanupsScope cleanups(*
this);
2118 cleanups.ForceCleanup();
2122 return llvm::ConstantExpr::getBitCast(Fn,
VoidPtrTy);
2144 llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.
Int32Ty, flags);
2147 llvm::Value *args[] = { destField.
getPointer(), srcValue, flagsVal };
2158 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2159 id.AddInteger(Flags.getBitMask());
2177 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2197 llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
2213 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2223 ARCStrongBlockByrefHelpers(
CharUnits alignment)
2240 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2250 const Expr *CopyExpr;
2254 const Expr *copyExpr)
2257 bool needsCopy()
const override {
return CopyExpr !=
nullptr; }
2260 if (!CopyExpr)
return;
2270 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2271 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2290 bool needsDispose()
const override {
2291 return VarType.isDestructedType();
2296 CGF.
pushDestroy(VarType.isDestructedType(), field, VarType);
2300 void profileImpl(llvm::FoldingSetNodeID &
id)
const override {
2301 id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2306static llvm::Constant *
2315 args.push_back(&Dst);
2318 args.push_back(&Src);
2327 llvm::Function *Fn =
2328 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
2356 generator.
emitCopy(CGF, destField, srcField);
2361 return llvm::ConstantExpr::getBitCast(Fn, CGF.
Int8PtrTy);
2373static llvm::Constant *
2383 args.push_back(&Src);
2392 llvm::Function *Fn =
2393 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
2394 "__Block_byref_object_dispose_",
2417 return llvm::ConstantExpr::getBitCast(Fn, CGF.
Int8PtrTy);
2433 llvm::FoldingSetNodeID id;
2434 generator.Profile(
id);
2439 if (node)
return static_cast<T*
>(node);
2444 T *copy =
new (CGM.
getContext()) T(std::forward<T>(generator));
2453CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
2454 const AutoVarEmission &emission) {
2455 const VarDecl &var = *emission.Variable;
2457 "only escaping __block variables need byref helpers");
2469 const Expr *copyExpr =
2471 if (!copyExpr && record->hasTrivialDestructor())
return nullptr;
2473 return ::buildByrefHelpers(
2474 CGM, byrefInfo, CXXByrefHelpers(valueAlignment,
type, copyExpr));
2481 return ::buildByrefHelpers(
2482 CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment,
type));
2486 if (!
type->isObjCRetainableType())
return nullptr;
2503 return ::buildByrefHelpers(
CGM, byrefInfo,
2504 ARCWeakByrefHelpers(valueAlignment));
2510 if (
type->isBlockPointerType()) {
2511 return ::buildByrefHelpers(
CGM, byrefInfo,
2512 ARCStrongBlockByrefHelpers(valueAlignment));
2517 return ::buildByrefHelpers(
CGM, byrefInfo,
2518 ARCStrongByrefHelpers(valueAlignment));
2521 llvm_unreachable(
"fell out of lifetime switch!");
2525 if (
type->isBlockPointerType()) {
2528 type->isObjCObjectPointerType()) {
2534 if (
type.isObjCGCWeak())
2537 return ::buildByrefHelpers(
CGM, byrefInfo,
2538 ObjectByrefHelpers(valueAlignment, flags));
2543 bool followForward) {
2551 const llvm::Twine &name) {
2553 if (followForward) {
2578 auto it = BlockByrefInfos.find(D);
2579 if (it != BlockByrefInfos.end())
2582 llvm::StructType *byrefType =
2596 types.push_back(llvm::PointerType::getUnqual(byrefType));
2609 if (hasCopyAndDispose) {
2619 bool HasByrefExtendedLayout =
false;
2621 if (
getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
2622 HasByrefExtendedLayout) {
2631 bool packed =
false;
2636 if (varOffset != size) {
2637 llvm::Type *paddingTy =
2638 llvm::ArrayType::get(
Int8Ty, (varOffset - size).getQuantity());
2640 types.push_back(paddingTy);
2648 types.push_back(varTy);
2650 byrefType->setBody(
types, packed);
2653 info.
Type = byrefType;
2658 auto pair = BlockByrefInfos.insert({D, info});
2659 assert(pair.second &&
"info was inserted recursively?");
2660 return pair.first->second;
2670 llvm::StructType *byrefType = cast<llvm::StructType>(addr.
getElementType());
2672 unsigned nextHeaderIndex = 0;
2674 auto storeHeaderField = [&](llvm::Value *value,
CharUnits fieldSize,
2675 const Twine &
name) {
2680 nextHeaderOffset += fieldSize;
2686 const VarDecl &D = *emission.Variable;
2689 bool HasByrefExtendedLayout =
false;
2691 bool ByRefHasLifetime =
2698 if (
type.isObjCGCWeak())
2711 if (ByRefHasLifetime) {
2713 else switch (ByrefLifetime) {
2724 if (!
type->isObjCObjectPointerType() && !
type->isBlockPointerType())
2731 printf(
"\n Inline flag for BYREF variable layout (%d):", flags.
getBitMask());
2733 printf(
" BLOCK_BYREF_HAS_COPY_DISPOSE");
2737 printf(
" BLOCK_BYREF_LAYOUT_EXTENDED");
2739 printf(
" BLOCK_BYREF_LAYOUT_STRONG");
2741 printf(
" BLOCK_BYREF_LAYOUT_WEAK");
2743 printf(
" BLOCK_BYREF_LAYOUT_UNRETAINED");
2745 printf(
" BLOCK_BYREF_LAYOUT_NON_OBJECT");
2759 "byref.copyHelper");
2761 "byref.disposeHelper");
2764 if (ByRefHasLifetime && HasByrefExtendedLayout) {
2773 llvm::Value *args[] = {
V,
2784 bool LoadBlockVarAddr,
bool CanThrow) {
2785 EHStack.pushCleanup<CallBlockRelease>(
Kind, Addr, Flags, LoadBlockVarAddr,
2791 llvm::Constant *
C) {
2792 auto *GV = cast<llvm::GlobalValue>(
C->stripPointerCasts());
2799 assert((isa<llvm::Function>(
C->stripPointerCasts()) ||
2800 isa<llvm::GlobalVariable>(
C->stripPointerCasts())) &&
2801 "expected Function or GlobalVariable");
2805 if ((ND = dyn_cast<FunctionDecl>(
Result)) ||
2806 (ND = dyn_cast<VarDecl>(
Result)))
2810 if (GV->isDeclaration() && (!ND || !ND->
hasAttr<DLLExportAttr>())) {
2811 GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2812 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2814 GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2815 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2819 if (CGM.
getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
2820 GV->hasExternalLinkage())
2821 GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
2827 if (BlockObjectDispose)
2828 return BlockObjectDispose;
2831 llvm::FunctionType *fty
2832 = llvm::FunctionType::get(
VoidTy, args,
false);
2835 *
this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
2836 return BlockObjectDispose;
2840 if (BlockObjectAssign)
2841 return BlockObjectAssign;
2844 llvm::FunctionType *fty
2845 = llvm::FunctionType::get(
VoidTy, args,
false);
2848 *
this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
2849 return BlockObjectAssign;
2853 if (NSConcreteGlobalBlock)
2854 return NSConcreteGlobalBlock;
2859 return NSConcreteGlobalBlock;
2863 if (NSConcreteStackBlock)
2864 return NSConcreteStackBlock;
2869 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.
static bool isBlockPointer(Expr *Arg)
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.
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.
llvm::Value * getPointer() const
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)
void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue)
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)
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **callOrInvoke, bool IsMustTail, SourceLocation Loc)
EmitCall - Generate a call of the given function, expecting the given result type,...
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)
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)
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitBlockLiteral(const BlockExpr *)
Emit block literal.
Address CreateMemTemp(QualType T, const Twine &Name="tmp", Address *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
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)
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
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs=std::nullopt)
EmitStmt - Emit the code for the statement.
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.
const CGFunctionInfo & arrangeBlockFunctionDeclaration(const FunctionProtoType *type, const FunctionArgList &args)
Block invocation functions are C functions with an implicit parameter.
llvm::Type * ConvertTypeForMem(QualType T, bool ForBitField=false)
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.
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(CodeGenFunction &CGF) const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
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 ...
@ ObjCSelf
Parameter for Objective-C 'self' argument.
@ Other
Other implicit parameter.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
virtual void mangleTypeName(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...
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
@ DK_objc_strong_lifetime
PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const
Check if this is a non-trivial type that would cause a C struct transitively containing this type to ...
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isObjCGCWeak() const
true when Type is objc's weak.
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.
bool hasObjCLifetime() const
ObjCLifetime getObjCLifetime() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
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<specific type>.
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<specific type>'.
bool isObjCRetainableType() const
Represents a variable declaration or definition.
const Expr * getInit() const
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 size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool isa(CodeGen::Address addr)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
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.
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
CharUnits getPointerAlign() const