36 cl::desc(
"Enable adding flow sensitive discriminators"));
42 cl::desc(
"Preserve line and column number when merging locations."));
50 std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()};
53 : Variable(DVR->getVariable()),
54 Fragment(DVR->getExpression()->getFragmentInfo()),
57DILocation::DILocation(
LLVMContext &
C, StorageType Storage,
unsigned Line,
60 :
MDNode(
C, DILocationKind, Storage, MDs), AtomGroup(AtomGroup),
62 assert(AtomRank <= 7 &&
"AtomRank number should fit in 3 bits");
64 C.updateDILocationAtomGroupWaterline(AtomGroup + 1);
67 "Expected a scope and optional inlined-at");
69 assert(Column < (1u << 16) &&
"Expected 16-bit column");
71 SubclassData32 = Line;
72 SubclassData16 = Column;
74 setImplicitCode(ImplicitCode);
79 if (Column >= (1u << 16))
85 Metadata *InlinedAt,
bool ImplicitCode,
87 StorageType Storage,
bool ShouldCreate) {
95 AtomGroup, AtomRank)))
100 assert(ShouldCreate &&
"Expected non-uniqued nodes to always be created");
116 if (Locs.
size() == 1)
118 auto *Merged = Locs[0];
121 if (Merged ==
nullptr)
129 TempMDNode ClonedScope = LBB->
clone();
130 cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent);
131 return cast<DILexicalBlockBase>(
139 assert(isa<DILocalScope>(S) &&
"Expected DILocalScope.");
141 if (isa<DILexicalBlockFile>(S))
143 if (
auto *LB = dyn_cast<DILexicalBlock>(S))
144 return {LB->getLine(), LB->getColumn()};
145 if (
auto *SP = dyn_cast<DISubprogram>(S))
146 return {SP->getLine(), 0u};
152template <
typename MatcherT>
153static std::pair<DIScope *, LineColumn>
160 LineColumn Loc1(L1->getLine(), L1->getColumn());
161 for (;
S1;
S1 =
S1->getScope()) {
163 Matcher.insert(
S1, Loc1);
164 if (isa<DISubprogram>(
S1))
168 LineColumn Loc2(L2->getLine(), L2->getColumn());
172 if (
DIScope *S = Matcher.match(S2, Loc2))
173 return std::make_pair(S, Loc2);
175 if (isa<DISubprogram>(S2))
178 return std::make_pair(
nullptr,
LineColumn(L2->getLine(), L2->getColumn()));
188 return Scopes.contains(S) ? S :
nullptr;
199 Scopes[{S->
getFile(), Loc}].insert(S);
203 auto ScopesAtLoc = Scopes.find({S->
getFile(), Loc});
205 if (ScopesAtLoc == Scopes.end())
209 if (ScopesAtLoc->second.contains(S))
212 if (!ScopesAtLoc->second.empty())
213 return *ScopesAtLoc->second.begin();
230 return LocA ? LocA : LocB;
232 auto A = std::make_tuple(LocA->getLine(), LocA->getColumn(),
233 LocA->getDiscriminator(), LocA->getFilename(),
234 LocA->getDirectory());
235 auto B = std::make_tuple(LocB->getLine(), LocB->getColumn(),
236 LocB->getDiscriminator(), LocB->getFilename(),
237 LocB->getDirectory());
238 return A <
B ? LocA : LocB;
256 for (
auto [L,
I] = std::make_pair(LocA, 0U); L; L = L->getInlinedAt(),
I++) {
260 assert(Res.second &&
"Multiple <SP, InlinedAt> pairs in a location chain?");
264 LocVec::reverse_iterator ARIt = ALocs.rend();
265 LocVec::reverse_iterator BRIt = BLocs.rend();
271 for (
auto [L,
I] = std::make_pair(LocB, 0U); L; L = L->getInlinedAt(),
I++) {
274 if (ARIt != ALocs.rend())
278 auto IT = ALookup.
find({L->getScope()->getSubprogram(), L->getInlinedAt()});
279 if (
IT == ALookup.
end())
283 ARIt = LocVec::reverse_iterator(ALocs.begin() +
IT->second + 1);
284 BRIt = LocVec::reverse_iterator(BLocs.begin() +
I + 1);
295 auto *LocAIA = LocA->getInlinedAt();
296 auto *LocBIA = LocB->getInlinedAt();
297 auto MergeLocPair = [&
C, LocAIA,
303 L1->getAtomGroup(), L1->getAtomRank());
307 if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())
311 DIScope *
Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first;
312 assert(
Scope &&
"No common scope in the same subprogram?");
315 if (
Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) {
316 auto [CommonLocScope, CommonLoc] =
317 getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);
322 if (
auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
326 Scope = CommonLocScope;
330 if (
Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile())
335 bool SameLine = L1->getLine() == L2->getLine();
336 bool SameCol = L1->getColumn() == L2->getColumn();
337 unsigned Line = SameLine ? L1->getLine() : 0;
338 unsigned Col = SameLine && SameCol ? L1->getColumn() : 0;
339 bool IsImplicitCode = L1->isImplicitCode() && L2->isImplicitCode();
343 if (!SameLine || !(L1->getAtomGroup() || L2->getAtomGroup()))
351 if (LocBIA == LocAIA &&
InlinedAt == LocBIA) {
356 bool UseL1Atom = [L1, L2]() {
357 if (L1->getAtomRank() == L2->getAtomRank()) {
359 if (!L1->getAtomGroup() || !L2->getAtomGroup())
360 return !L2->getAtomGroup();
361 return L1->getAtomGroup() < L2->getAtomGroup();
364 if (!L1->getAtomRank() || !L2->getAtomRank())
365 return !L2->getAtomRank();
366 return L1->getAtomRank() < L2->getAtomRank();
368 Group = UseL1Atom ? L1->getAtomGroup() : L2->getAtomGroup();
369 Rank = UseL1Atom ? L1->getAtomRank() : L2->getAtomRank();
375 Group =
C.incNextDILocationAtomGroup();
382 DILocation *Result = ARIt != ALocs.rend() ? (*ARIt)->getInlinedAt() :
nullptr;
386 for (; ARIt != ALocs.rend() && BRIt != BLocs.rend(); ++ARIt, ++BRIt) {
387 DILocation *Tmp = MergeLocPair(*ARIt, *BRIt, Result);
412std::optional<unsigned>
414 std::array<unsigned, 3> Components = {BD,
DF, CI};
422 std::accumulate(Components.begin(), Components.end(), RemainingWork);
426 unsigned NextBitInsertionIndex = 0;
427 while (RemainingWork > 0) {
428 unsigned C = Components[
I++];
431 Ret |= (EC << NextBitInsertionIndex);
439 unsigned TBD, TDF, TCI = 0;
441 if (TBD == BD && TDF ==
DF && TCI == CI)
457#define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME)
458#include "llvm/IR/DebugInfoFlags.def"
464#define HANDLE_DI_FLAG(ID, NAME) \
466 return "DIFlag" #NAME;
467#include "llvm/IR/DebugInfoFlags.def"
478 if (
A == FlagPrivate)
480 else if (
A == FlagProtected)
487 if (R == FlagSingleInheritance)
488 SplitFlags.
push_back(FlagSingleInheritance);
489 else if (R == FlagMultipleInheritance)
490 SplitFlags.
push_back(FlagMultipleInheritance);
492 SplitFlags.
push_back(FlagVirtualInheritance);
495 if ((Flags & FlagIndirectVirtualBase) == FlagIndirectVirtualBase) {
496 Flags &= ~FlagIndirectVirtualBase;
497 SplitFlags.
push_back(FlagIndirectVirtualBase);
500#define HANDLE_DI_FLAG(ID, NAME) \
501 if (DIFlags Bit = Flags & Flag##NAME) { \
502 SplitFlags.push_back(Bit); \
505#include "llvm/IR/DebugInfoFlags.def"
510 if (
auto *
T = dyn_cast<DIType>(
this))
511 return T->getScope();
513 if (
auto *SP = dyn_cast<DISubprogram>(
this))
514 return SP->getScope();
516 if (
auto *LB = dyn_cast<DILexicalBlockBase>(
this))
517 return LB->getScope();
519 if (
auto *NS = dyn_cast<DINamespace>(
this))
520 return NS->getScope();
522 if (
auto *CB = dyn_cast<DICommonBlock>(
this))
523 return CB->getScope();
525 if (
auto *M = dyn_cast<DIModule>(
this))
526 return M->getScope();
528 assert((isa<DIFile>(
this) || isa<DICompileUnit>(
this)) &&
529 "Unhandled type of scope.");
534 if (
auto *
T = dyn_cast<DIType>(
this))
536 if (
auto *SP = dyn_cast<DISubprogram>(
this))
537 return SP->getName();
538 if (
auto *NS = dyn_cast<DINamespace>(
this))
539 return NS->getName();
540 if (
auto *CB = dyn_cast<DICommonBlock>(
this))
541 return CB->getName();
542 if (
auto *M = dyn_cast<DIModule>(
this))
544 assert((isa<DILexicalBlockBase>(
this) || isa<DIFile>(
this) ||
545 isa<DICompileUnit>(
this)) &&
546 "Unhandled type of scope.");
560 StorageType Storage,
bool ShouldCreate) {
568 Hash = Key.getHash();
570 assert(ShouldCreate &&
"Expected non-uniqued nodes to always be created");
581void GenericDINode::recalculateHash() {
582 setHash(GenericDINodeInfo::KeyTy::calculateHash(
this));
585#define UNWRAP_ARGS_IMPL(...) __VA_ARGS__
586#define UNWRAP_ARGS(ARGS) UNWRAP_ARGS_IMPL ARGS
587#define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS) \
589 if (Storage == Uniqued) { \
590 if (auto *N = getUniqued(Context.pImpl->CLASS##s, \
591 CLASS##Info::KeyTy(UNWRAP_ARGS(ARGS)))) \
596 assert(ShouldCreate && \
597 "Expected non-uniqued nodes to always be created"); \
600#define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS) \
601 return storeImpl(new (std::size(OPS), Storage) \
602 CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
603 Storage, Context.pImpl->CLASS##s)
604#define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS) \
605 return storeImpl(new (0u, Storage) \
606 CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \
607 Storage, Context.pImpl->CLASS##s)
608#define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS) \
609 return storeImpl(new (std::size(OPS), Storage) CLASS(Context, Storage, OPS), \
610 Storage, Context.pImpl->CLASS##s)
611#define DEFINE_GETIMPL_STORE_N(CLASS, ARGS, OPS, NUM_OPS) \
612 return storeImpl(new (NUM_OPS, Storage) \
613 CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
614 Storage, Context.pImpl->CLASS##s)
616DISubrange::DISubrange(
LLVMContext &
C, StorageType Storage,
618 :
DINode(
C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {}
620 StorageType Storage,
bool ShouldCreate) {
630 int64_t
Lo, StorageType Storage,
640 StorageType Storage,
bool ShouldCreate) {
651 assert((isa<ConstantAsMetadata>(CB) || isa<DIVariable>(CB) ||
652 isa<DIExpression>(CB)) &&
653 "Count must be signed constant or DIVariable or DIExpression");
655 if (
auto *MD = dyn_cast<ConstantAsMetadata>(CB))
656 return BoundType(cast<ConstantInt>(MD->getValue()));
658 if (
auto *MD = dyn_cast<DIVariable>(CB))
659 return BoundType(MD);
661 if (
auto *MD = dyn_cast<DIExpression>(CB))
662 return BoundType(MD);
672 assert((isa<ConstantAsMetadata>(LB) || isa<DIVariable>(LB) ||
673 isa<DIExpression>(LB)) &&
674 "LowerBound must be signed constant or DIVariable or DIExpression");
676 if (
auto *MD = dyn_cast<ConstantAsMetadata>(LB))
677 return BoundType(cast<ConstantInt>(MD->getValue()));
679 if (
auto *MD = dyn_cast<DIVariable>(LB))
680 return BoundType(MD);
682 if (
auto *MD = dyn_cast<DIExpression>(LB))
683 return BoundType(MD);
693 assert((isa<ConstantAsMetadata>(UB) || isa<DIVariable>(UB) ||
694 isa<DIExpression>(UB)) &&
695 "UpperBound must be signed constant or DIVariable or DIExpression");
697 if (
auto *MD = dyn_cast<ConstantAsMetadata>(UB))
698 return BoundType(cast<ConstantInt>(MD->getValue()));
700 if (
auto *MD = dyn_cast<DIVariable>(UB))
701 return BoundType(MD);
703 if (
auto *MD = dyn_cast<DIExpression>(UB))
704 return BoundType(MD);
714 assert((isa<ConstantAsMetadata>(ST) || isa<DIVariable>(ST) ||
715 isa<DIExpression>(ST)) &&
716 "Stride must be signed constant or DIVariable or DIExpression");
718 if (
auto *MD = dyn_cast<ConstantAsMetadata>(ST))
719 return BoundType(cast<ConstantInt>(MD->getValue()));
721 if (
auto *MD = dyn_cast<DIVariable>(ST))
722 return BoundType(MD);
724 if (
auto *MD = dyn_cast<DIExpression>(ST))
725 return BoundType(MD);
729DIGenericSubrange::DIGenericSubrange(
LLVMContext &
C, StorageType Storage,
731 :
DINode(
C, DIGenericSubrangeKind, Storage, dwarf::DW_TAG_generic_subrange,
740 Metadata *Ops[] = {CountNode, LB, UB, Stride};
749 assert((isa<DIVariable>(CB) || isa<DIExpression>(CB)) &&
750 "Count must be signed constant or DIVariable or DIExpression");
752 if (
auto *MD = dyn_cast<DIVariable>(CB))
755 if (
auto *MD = dyn_cast<DIExpression>(CB))
766 assert((isa<DIVariable>(LB) || isa<DIExpression>(LB)) &&
767 "LowerBound must be signed constant or DIVariable or DIExpression");
769 if (
auto *MD = dyn_cast<DIVariable>(LB))
772 if (
auto *MD = dyn_cast<DIExpression>(LB))
783 assert((isa<DIVariable>(UB) || isa<DIExpression>(UB)) &&
784 "UpperBound must be signed constant or DIVariable or DIExpression");
786 if (
auto *MD = dyn_cast<DIVariable>(UB))
789 if (
auto *MD = dyn_cast<DIExpression>(UB))
800 assert((isa<DIVariable>(ST) || isa<DIExpression>(ST)) &&
801 "Stride must be signed constant or DIVariable or DIExpression");
803 if (
auto *MD = dyn_cast<DIVariable>(ST))
806 if (
auto *MD = dyn_cast<DIExpression>(ST))
812DISubrangeType::DISubrangeType(
LLVMContext &
C, StorageType Storage,
813 unsigned Line,
uint32_t AlignInBits,
815 :
DIType(
C, DISubrangeTypeKind, Storage, dwarf::DW_TAG_subrange_type, Line,
816 AlignInBits, 0, Flags, Ops) {}
833DISubrangeType::convertRawToBound(
Metadata *IN)
const {
837 assert(isa<ConstantAsMetadata>(IN) || isa<DIVariable>(IN) ||
838 isa<DIExpression>(IN));
840 if (
auto *MD = dyn_cast<ConstantAsMetadata>(IN))
841 return BoundType(cast<ConstantInt>(MD->getValue()));
843 if (
auto *MD = dyn_cast<DIVariable>(IN))
846 if (
auto *MD = dyn_cast<DIExpression>(IN))
852DIEnumerator::DIEnumerator(
LLVMContext &
C, StorageType Storage,
855 :
DINode(
C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
861 StorageType Storage,
bool ShouldCreate) {
870 uint32_t AlignInBits,
unsigned Encoding,
884 case dwarf::DW_ATE_signed:
885 case dwarf::DW_ATE_signed_char:
886 case dwarf::DW_ATE_signed_fixed:
888 case dwarf::DW_ATE_unsigned:
889 case dwarf::DW_ATE_unsigned_char:
890 case dwarf::DW_ATE_unsigned_fixed:
900 unsigned Encoding, DIFlags Flags,
unsigned Kind,
901 int Factor,
APInt Numerator,
APInt Denominator,
902 StorageType Storage,
bool ShouldCreate) {
905 Kind, Factor, Numerator, Denominator));
914 return getEncoding() == dwarf::DW_ATE_signed_fixed;
917std::optional<DIFixedPointType::FixedPointKind>
943 unsigned Encoding, StorageType Storage,
960 if (
auto *CM = cast_or_null<ConstantAsMetadata>(
getExtraData()))
961 if (
auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))
962 return static_cast<uint32_t>(CI->getZExtValue());
967 if (
auto *
C = cast_or_null<ConstantAsMetadata>(
getExtraData()))
968 return C->getValue();
974 getTag() == dwarf::DW_TAG_variable) &&
976 if (
auto *
C = cast_or_null<ConstantAsMetadata>(
getExtraData()))
977 return C->getValue();
982 if (
auto *
C = cast_or_null<ConstantAsMetadata>(
getExtraData()))
983 return C->getValue();
991 std::optional<unsigned> DWARFAddressSpace,
992 std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
Metadata *ExtraData,
1006std::optional<DIDerivedType::PtrAuthData>
1007DIDerivedType::getPtrAuthData()
const {
1008 return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type
1017 Metadata *Elements,
unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1022 StorageType Storage,
bool ShouldCreate) {
1048 Metadata *Elements,
unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1053 if (!
Context.isODRUniquingDebugTypes())
1063 if (CT->getTag() !=
Tag)
1068 if (!CT->isForwardDecl() || (
Flags & DINode::FlagFwdDecl))
1079 assert((std::end(Ops) - std::begin(Ops)) == (
int)CT->getNumOperands() &&
1080 "Mismatched number of operands");
1081 for (
unsigned I = 0, E = CT->getNumOperands();
I != E; ++
I)
1082 if (Ops[
I] != CT->getOperand(
I))
1083 CT->setOperand(
I, Ops[
I]);
1092 Metadata *Elements,
unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1097 if (!
Context.isODRUniquingDebugTypes())
1108 if (CT->getTag() !=
Tag)
1117 if (!
Context.isODRUniquingDebugTypes())
1121DISubroutineType::DISubroutineType(
LLVMContext &
C, StorageType Storage,
1124 :
DIType(
C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0,
1130 StorageType Storage,
1131 bool ShouldCreate) {
1138 std::optional<ChecksumInfo<MDString *>> CS,
MDString *Src,
1140 :
DIScope(
C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
1141 Checksum(CS),
Source(Src) {}
1151StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {
1159std::optional<DIFile::ChecksumKind>
1171 MDString *Source, StorageType Storage,
1172 bool ShouldCreate) {
1182DICompileUnit::DICompileUnit(
LLVMContext &
C, StorageType Storage,
1184 unsigned RuntimeVersion,
unsigned EmissionKind,
1185 uint64_t DWOId,
bool SplitDebugInlining,
1186 bool DebugInfoForProfiling,
unsigned NameTableKind,
1188 :
DIScope(
C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
1191 IsOptimized(IsOptimized), SplitDebugInlining(SplitDebugInlining),
1192 DebugInfoForProfiling(DebugInfoForProfiling),
1193 RangesBaseAddress(RangesBaseAddress) {
1200 unsigned RuntimeVersion,
MDString *SplitDebugFilename,
1203 uint64_t DWOId,
bool SplitDebugInlining,
bool DebugInfoForProfiling,
1204 unsigned NameTableKind,
bool RangesBaseAddress,
MDString *SysRoot,
1205 MDString *SDK, StorageType Storage,
bool ShouldCreate) {
1224 RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining,
1225 DebugInfoForProfiling, NameTableKind, RangesBaseAddress,
1230std::optional<DICompileUnit::DebugEmissionKind>
1240std::optional<DICompileUnit::DebugNameTableKind>
1257 return "LineTablesOnly";
1259 return "DebugDirectivesOnly";
1277DISubprogram::DISubprogram(
LLVMContext &
C, StorageType Storage,
unsigned Line,
1278 unsigned ScopeLine,
unsigned VirtualIndex,
1279 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags,
1281 :
DILocalScope(
C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops),
1282 Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),
1283 ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) {
1289 unsigned Virtuality,
bool IsMainSubprogram) {
1291 static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) &&
1292 int(SPFlagPureVirtual) ==
1293 int(dwarf::DW_VIRTUALITY_pure_virtual),
1294 "Virtuality constant mismatch");
1297 (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) |
1298 (IsDefinition ? SPFlagDefinition : SPFlagZero) |
1299 (IsOptimized ? SPFlagOptimized : SPFlagZero) |
1300 (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero));
1304 if (
auto *
Block = dyn_cast<DILexicalBlockBase>(
this))
1305 return Block->getScope()->getSubprogram();
1306 return const_cast<DISubprogram *
>(cast<DISubprogram>(
this));
1310 if (
auto *File = dyn_cast<DILexicalBlockFile>(
this))
1311 return File->getScope()->getNonLexicalBlockFileScope();
1319 DIScope *CachedResult =
nullptr;
1321 for (
DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);
1322 Scope = Scope->getScope()) {
1323 if (
auto It = Cache.
find(Scope); It != Cache.
end()) {
1324 CachedResult = cast<DIScope>(It->second);
1332 DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
1335 cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
1336 Cache[ScopeToUpdate] = UpdatedScope;
1339 return cast<DILocalScope>(UpdatedScope);
1344#define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)
1345#include "llvm/IR/DebugInfoFlags.def"
1354#define HANDLE_DISP_FLAG(ID, NAME) \
1355 case SPFlag##NAME: \
1356 return "DISPFlag" #NAME;
1357#include "llvm/IR/DebugInfoFlags.def"
1368#define HANDLE_DISP_FLAG(ID, NAME) \
1369 if (DISPFlags Bit = Flags & SPFlag##NAME) { \
1370 SplitFlags.push_back(Bit); \
1373#include "llvm/IR/DebugInfoFlags.def"
1380 unsigned ScopeLine,
Metadata *ContainingType,
unsigned VirtualIndex,
1381 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags,
Metadata *Unit,
1384 bool UsesKeyInstructions, StorageType Storage,
bool ShouldCreate) {
1414 (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags,
1419bool DISubprogram::describes(
const Function *
F)
const {
1420 assert(
F &&
"Invalid function");
1421 return F->getSubprogram() ==
this;
1430 unsigned Column, StorageType Storage,
1431 bool ShouldCreate) {
1443 unsigned Discriminator,
1444 StorageType Storage,
1445 bool ShouldCreate) {
1452DINamespace::DINamespace(
LLVMContext &Context, StorageType Storage,
1454 :
DIScope(
Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops) {
1459 StorageType Storage,
bool ShouldCreate) {
1467DICommonBlock::DICommonBlock(
LLVMContext &Context, StorageType Storage,
1469 :
DIScope(
Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block,
1476 StorageType Storage,
bool ShouldCreate) {
1484DIModule::DIModule(
LLVMContext &Context, StorageType Storage,
unsigned LineNo,
1486 :
DIScope(
Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {
1494 unsigned LineNo,
bool IsDecl, StorageType Storage,
1495 bool ShouldCreate) {
1503DITemplateTypeParameter::DITemplateTypeParameter(
LLVMContext &Context,
1504 StorageType Storage,
1508 dwarf::DW_TAG_template_type_parameter, IsDefault,
1514 StorageType Storage,
bool ShouldCreate) {
1523 bool isDefault,
Metadata *
Value, StorageType Storage,
bool ShouldCreate) {
1535 Metadata *StaticDataMemberDeclaration,
1538 bool ShouldCreate) {
1561 unsigned Arg, DIFlags Flags,
uint32_t AlignInBits,
1563 bool ShouldCreate) {
1565 assert(Arg <= UINT16_MAX &&
"Expected argument number to fit in 16-bits");
1578 :
DINode(
C,
ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {
1586 if (
auto *
T = dyn_cast<DIType>(RawType))
1590 if (
auto *DT = dyn_cast<DIDerivedType>(RawType)) {
1592 RawType = DT->getRawBaseType();
1601 return std::nullopt;
1604DILabel::DILabel(
LLVMContext &
C, StorageType Storage,
unsigned Line,
1605 unsigned Column,
bool IsArtificial,
1606 std::optional<unsigned> CoroSuspendIdx,
1608 :
DINode(
C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) {
1610 this->Column = Column;
1611 this->IsArtificial = IsArtificial;
1612 this->CoroSuspendIdx = CoroSuspendIdx;
1615 Metadata *File,
unsigned Line,
unsigned Column,
1617 std::optional<unsigned> CoroSuspendIdx,
1618 StorageType Storage,
bool ShouldCreate) {
1630 StorageType Storage,
bool ShouldCreate) {
1636 return singleLocElts->size() > 0 &&
1643 return singleLocElts->size() > 0 &&
1644 (*singleLocElts)[0] == dwarf::DW_OP_deref;
1649 return singleLocElts->size() == 1 &&
1650 (*singleLocElts)[0] == dwarf::DW_OP_deref;
1655 bool ShouldCreate) {
1664 if (
Op >= dwarf::DW_OP_breg0 &&
Op <= dwarf::DW_OP_breg31)
1672 case dwarf::DW_OP_bregx:
1674 case dwarf::DW_OP_constu:
1675 case dwarf::DW_OP_consts:
1676 case dwarf::DW_OP_deref_size:
1677 case dwarf::DW_OP_plus_uconst:
1681 case dwarf::DW_OP_regx:
1691 if (
I->get() +
I->getSize() > E->get())
1695 if ((
Op >= dwarf::DW_OP_reg0 &&
Op <= dwarf::DW_OP_reg31) ||
1696 (
Op >= dwarf::DW_OP_breg0 &&
Op <= dwarf::DW_OP_breg31))
1705 return I->get() +
I->getSize() == E->get();
1706 case dwarf::DW_OP_stack_value: {
1708 if (
I->get() +
I->getSize() == E->get())
1715 case dwarf::DW_OP_swap: {
1736 return I->get() == FirstOp->get() &&
I->getArg(0) == 1;
1744 case dwarf::DW_OP_constu:
1745 case dwarf::DW_OP_plus_uconst:
1746 case dwarf::DW_OP_plus:
1747 case dwarf::DW_OP_minus:
1748 case dwarf::DW_OP_mul:
1749 case dwarf::DW_OP_div:
1750 case dwarf::DW_OP_mod:
1751 case dwarf::DW_OP_or:
1752 case dwarf::DW_OP_and:
1753 case dwarf::DW_OP_xor:
1754 case dwarf::DW_OP_shl:
1755 case dwarf::DW_OP_shr:
1756 case dwarf::DW_OP_shra:
1757 case dwarf::DW_OP_deref:
1758 case dwarf::DW_OP_deref_size:
1759 case dwarf::DW_OP_xderef:
1760 case dwarf::DW_OP_lit0:
1761 case dwarf::DW_OP_not:
1762 case dwarf::DW_OP_dup:
1763 case dwarf::DW_OP_regx:
1764 case dwarf::DW_OP_bregx:
1765 case dwarf::DW_OP_push_object_address:
1766 case dwarf::DW_OP_over:
1767 case dwarf::DW_OP_consts:
1768 case dwarf::DW_OP_eq:
1769 case dwarf::DW_OP_ne:
1770 case dwarf::DW_OP_gt:
1771 case dwarf::DW_OP_ge:
1772 case dwarf::DW_OP_lt:
1773 case dwarf::DW_OP_le:
1787 for (
const auto &It :
expr_ops()) {
1788 switch (It.getOp()) {
1791 case dwarf::DW_OP_stack_value:
1808 for (
const auto &It :
expr_ops()) {
1809 switch (It.getOp()) {
1829 auto ExprOpBegin =
expr_ops().begin();
1832 if (ExprOpBegin->getArg(0) != 0)
1837 return !std::any_of(ExprOpBegin, ExprOpEnd, [](
auto Op) {
1842std::optional<ArrayRef<uint64_t>>
1846 return std::nullopt;
1872 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1882std::optional<const DIExpression *>
1885 return std::nullopt;
1890 return std::nullopt;
1899 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1912 if (
Op.getOp() == dwarf::DW_OP_stack_value ||
1917 Op.appendToVector(Ops);
1926 bool SecondIndirect) {
1932 return FirstOps == SecondOps;
1935std::optional<DIExpression::FragmentInfo>
1937 for (
auto I = Start;
I !=
End; ++
I)
1942 return std::nullopt;
1946 std::optional<uint64_t> InitialActiveBits = Var->
getSizeInBits();
1947 std::optional<uint64_t> ActiveBits = InitialActiveBits;
1949 switch (
Op.getOp()) {
1953 ActiveBits = InitialActiveBits;
1959 std::optional<DIBasicType::Signedness> VarSign = Var->
getSignedness();
1962 if (!VarSign || VarSigned != OpSigned) {
1963 ActiveBits = InitialActiveBits;
1971 ActiveBits = std::min(*ActiveBits,
Op.getArg(1));
1973 ActiveBits =
Op.getArg(1);
1983 Ops.
push_back(dwarf::DW_OP_plus_uconst);
1997 if (!SingleLocEltsOpt)
1999 auto SingleLocElts = *SingleLocEltsOpt;
2001 if (SingleLocElts.size() == 0) {
2006 if (SingleLocElts.size() == 2 &&
2007 SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {
2008 Offset = SingleLocElts[1];
2012 if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {
2013 if (SingleLocElts[2] == dwarf::DW_OP_plus) {
2014 Offset = SingleLocElts[1];
2017 if (SingleLocElts[2] == dwarf::DW_OP_minus) {
2018 Offset = -SingleLocElts[1];
2029 RemainingOps.
clear();
2032 if (!SingleLocEltsOpt)
2037 while (ExprOpIt != ExprOpEnd) {
2039 if (
Op == dwarf::DW_OP_deref ||
Op == dwarf::DW_OP_deref_size ||
2044 }
else if (
Op == dwarf::DW_OP_plus_uconst) {
2045 OffsetInBytes += ExprOpIt->getArg(0);
2046 }
else if (
Op == dwarf::DW_OP_constu) {
2049 if (ExprOpIt->getOp() == dwarf::DW_OP_plus)
2050 OffsetInBytes +=
Value;
2051 else if (ExprOpIt->getOp() == dwarf::DW_OP_minus)
2052 OffsetInBytes -=
Value;
2061 RemainingOps.
append(ExprOpIt.getBase(), ExprOpEnd.getBase());
2069 SeenOps.
insert(ExprOp.getArg(0));
2077 unsigned &AddrClass) {
2081 if (!SingleLocEltsOpt)
2083 auto SingleLocElts = *SingleLocEltsOpt;
2085 const unsigned PatternSize = 4;
2086 if (SingleLocElts.size() >= PatternSize &&
2087 SingleLocElts[PatternSize - 4] == dwarf::DW_OP_constu &&
2088 SingleLocElts[PatternSize - 2] == dwarf::DW_OP_swap &&
2089 SingleLocElts[PatternSize - 1] == dwarf::DW_OP_xderef) {
2090 AddrClass = SingleLocElts[PatternSize - 3];
2092 if (SingleLocElts.size() == PatternSize)
2096 ArrayRef(&*SingleLocElts.begin(), SingleLocElts.size() - PatternSize));
2120 assert(Expr &&
"Can't add ops to this expression");
2124 [](
auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {
2126 "Location Index must be 0 for a non-variadic expression.");
2135 if (
Op.getOp() == dwarf::DW_OP_stack_value)
2138 NewOps.
push_back(dwarf::DW_OP_stack_value);
2142 Op.appendToVector(NewOps);
2147 NewOps.
push_back(dwarf::DW_OP_stack_value);
2154 assert(Expr &&
"Can't replace args in this expression");
2160 Op.appendToVector(NewOps);
2164 uint64_t Arg =
Op.getArg(0) == OldArg ? NewArg :
Op.getArg(0);
2177 assert(Expr &&
"Can't prepend ops to this expression");
2193 if (
Op.getOp() == dwarf::DW_OP_stack_value)
2196 Ops.
push_back(dwarf::DW_OP_stack_value);
2200 Op.appendToVector(Ops);
2203 Ops.
push_back(dwarf::DW_OP_stack_value);
2209 assert(Expr && !Ops.
empty() &&
"Can't append ops to this expression");
2215 if (
Op.getOp() == dwarf::DW_OP_stack_value ||
2222 Op.appendToVector(NewOps);
2227 assert(result->isValid() &&
"concatenated expression is not valid");
2233 assert(Expr && !Ops.
empty() &&
"Can't append ops to this expression");
2237 return Op.getOp() == dwarf::DW_OP_stack_value ||
2238 Op.getOp() == dwarf::DW_OP_LLVM_fragment;
2240 "Can't append this op");
2247 unsigned DropUntilStackValue = FI ? 3 : 0;
2250 bool NeedsDeref = (Expr->
getNumElements() > DropUntilStackValue) &&
2251 (ExprOpsBeforeFragment.
back() != dwarf::DW_OP_stack_value);
2252 bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.
empty();
2260 if (NeedsStackValue)
2261 NewOps.
push_back(dwarf::DW_OP_stack_value);
2266 const DIExpression *Expr,
unsigned OffsetInBits,
unsigned SizeInBits) {
2270 bool CanSplitValue =
true;
2272 bool EmitFragment =
true;
2276 switch (
Op.getOp()) {
2279 case dwarf::DW_OP_shr:
2280 case dwarf::DW_OP_shra:
2281 case dwarf::DW_OP_shl:
2282 case dwarf::DW_OP_plus:
2283 case dwarf::DW_OP_plus_uconst:
2284 case dwarf::DW_OP_minus:
2290 CanSplitValue =
false;
2292 case dwarf::DW_OP_deref:
2293 case dwarf::DW_OP_deref_size:
2294 case dwarf::DW_OP_deref_type:
2295 case dwarf::DW_OP_xderef:
2296 case dwarf::DW_OP_xderef_size:
2297 case dwarf::DW_OP_xderef_type:
2300 CanSplitValue =
true;
2302 case dwarf::DW_OP_stack_value:
2305 return std::nullopt;
2312 return std::nullopt;
2314 uint64_t FragmentOffsetInBits =
Op.getArg(0);
2316 (void)FragmentSizeInBits;
2317 assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
2318 "new fragment outside of original fragment");
2319 OffsetInBits += FragmentOffsetInBits;
2329 if (ExtractOffsetInBits >= OffsetInBits &&
2330 ExtractOffsetInBits + ExtractSizeInBits <=
2331 OffsetInBits + SizeInBits) {
2333 Ops.
push_back(ExtractOffsetInBits - OffsetInBits);
2335 EmitFragment =
false;
2341 return std::nullopt;
2344 Op.appendToVector(Ops);
2348 assert(Expr &&
"Unknown DIExpression");
2360 uint64_t SliceSizeInBits,
const Value *DbgPtr, int64_t DbgPtrOffsetInBits,
2362 std::optional<DIExpression::FragmentInfo> &Result,
2363 int64_t &OffsetFromLocationInBits) {
2375 int64_t MemStartRelToDbgStartInBits;
2378 if (!MemOffsetFromDbgInBytes)
2381 MemStartRelToDbgStartInBits = *MemOffsetFromDbgInBytes * 8;
2383 MemStartRelToDbgStartInBits +=
2384 SliceOffsetInBits - (DbgPtrOffsetInBits + DbgExtractOffsetInBits);
2388 OffsetFromLocationInBits = -MemStartRelToDbgStartInBits;
2391 int64_t MemEndRelToDbgStart = MemStartRelToDbgStartInBits + SliceSizeInBits;
2392 if (MemEndRelToDbgStart < 0) {
2404 int64_t MemStartRelToVarInBits =
2406 int64_t MemEndRelToVarInBits = MemStartRelToVarInBits + SliceSizeInBits;
2411 int64_t MemFragStart = std::max<int64_t>(0, MemStartRelToVarInBits);
2412 int64_t MemFragSize =
2413 std::max<int64_t>(0, MemEndRelToVarInBits - MemFragStart);
2419 if (TrimmedSliceOfVariable == VarFrag)
2420 Result = std::nullopt;
2422 Result = TrimmedSliceOfVariable;
2426std::pair<DIExpression *, const ConstantInt *>
2434 bool Changed =
false;
2436 switch (
Op.getOp()) {
2449 if (
Op.getArg(1) == dwarf::DW_ATE_signed)
2452 assert(
Op.getArg(1) == dwarf::DW_ATE_unsigned &&
"Unexpected operand");
2457 Op.appendToVector(Ops);
2469 Result = std::max(Result, ExprOp.getArg(0) + 1);
2471 "Expression is missing one or more location operands.");
2475std::optional<DIExpression::SignedOrUnsignedConstant>
2488 return std::nullopt;
2496 return std::nullopt;
2511 unsigned FromSize,
unsigned ToSize,
2519 bool ShouldCreate) {
2525 unsigned Line,
unsigned Attributes,
2527 :
DINode(
C, DIObjCPropertyKind,
Storage, dwarf::DW_TAG_APPLE_property, Ops),
2533 Metadata *
Type, StorageType Storage,
bool ShouldCreate) {
2547 StorageType Storage,
2548 bool ShouldCreate) {
2558 bool ShouldCreate) {
2567 Metadata *Elements, StorageType Storage,
2568 bool ShouldCreate) {
2577 if (ExistingIt !=
Context.pImpl->DIArgLists.end())
2580 Context.pImpl->DIArgLists.insert(NewArgList);
2586 assert((!New || isa<ValueAsMetadata>(New)) &&
2587 "DIArgList must be passed a ValueAsMetadata");
2594 if (&VM == OldVMPtr) {
2606 if (ExistingArgList) {
2616void DIArgList::track() {
2621void DIArgList::untrack() {
2626void DIArgList::dropAllReferences(
bool Untrack) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
static DISubprogram * getSubprogram(bool IsDistinct, Ts &&...Args)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
static unsigned encodingBits(unsigned C)
static unsigned encodeComponent(unsigned C)
static unsigned getNextComponentInDiscriminator(unsigned D)
Returns the next component stored in discriminator.
static unsigned getUnsignedFromPrefixEncoding(unsigned U)
Reverse transformation as getPrefixEncodingFromUnsigned.
This file contains constants used for implementing Dwarf debug support.
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
This file implements a set that has insertion order iteration characteristics.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
support::ulittle16_t & Lo
Class for arbitrary precision integers.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Annotations lets you mark points and ranges inside source code, for tests:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
back - Get the last element.
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
bool empty() const
empty - Check if the array is empty.
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
List of ValueAsMetadata, to be used as an argument to a dbg.value intrinsic.
LLVM_ABI void handleChangedOperand(void *Ref, Metadata *New)
static LLVM_ABI DIArgList * get(LLVMContext &Context, ArrayRef< ValueAsMetadata * > Args)
Basic type, like 'int' or 'float'.
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t unsigned DIFlags Flags
static DIBasicType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, uint32_t NumExtraInhabitants, DIFlags Flags, StorageType Storage, bool ShouldCreate=true)
unsigned StringRef uint64_t SizeInBits
LLVM_ABI std::optional< Signedness > getSignedness() const
Return the signedness of this type, or std::nullopt if this type is neither signed nor unsigned.
unsigned getEncoding() const
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t unsigned DIFlags Flags unsigned StringRef uint64_t uint32_t unsigned uint32_t NumExtraInhabitants
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t AlignInBits
Metadata Metadata MDString Metadata unsigned LineNo
Metadata Metadata MDString * Name
Metadata Metadata MDString Metadata * File
static LLVM_ABI const char * nameTableKindString(DebugNameTableKind PK)
static LLVM_ABI const char * emissionKindString(DebugEmissionKind EK)
DebugEmissionKind getEmissionKind() const
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata * Macros
unsigned Metadata MDString bool MDString * Flags
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata * EnumTypes
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata * RetainedTypes
DebugNameTableKind getNameTableKind() const
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata * GlobalVariables
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata uint64_t bool bool unsigned bool MDString MDString * SDK
unsigned Metadata MDString * Producer
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata uint64_t bool bool unsigned bool MDString * SysRoot
unsigned Metadata MDString bool MDString unsigned MDString * SplitDebugFilename
unsigned Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata * ImportedEntities
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t AlignInBits
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata * DataLocation
static LLVM_ABI DICompositeType * buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, Metadata *Specification, uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, std::optional< uint32_t > EnumKind, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, Metadata *BitStride)
Build a DICompositeType with the given ODR identifier.
unsigned MDString Metadata unsigned Line
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata * Elements
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata * Annotations
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString * Identifier
static LLVM_ABI DICompositeType * getODRTypeIfExists(LLVMContext &Context, MDString &Identifier)
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata * Discriminator
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata * TemplateParams
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t OffsetInBits
unsigned MDString Metadata unsigned Metadata * Scope
unsigned MDString Metadata * File
unsigned MDString Metadata unsigned Metadata Metadata * BaseType
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Flags
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata * Allocated
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata * Specification
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata * VTableHolder
unsigned MDString Metadata unsigned Metadata Metadata uint64_t SizeInBits
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata * Associated
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata uint32_t NumExtraInhabitants
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata * Rank
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata uint32_t Metadata * BitStride
unsigned StringRef DIFile unsigned DIScope DIType * BaseType
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata * OffsetInBits
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata std::optional< unsigned > std::optional< PtrAuthData > DIFlags Flags
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t AlignInBits
Metadata * getExtraData() const
Get extra data associated with this derived type.
unsigned StringRef DIFile * File
unsigned StringRef DIFile unsigned DIScope * Scope
LLVM_ABI DIType * getClassType() const
Get casted version of extra data.
LLVM_ABI Constant * getConstant() const
unsigned StringRef DIFile unsigned DIScope DIType Metadata * SizeInBits
LLVM_ABI Constant * getStorageOffsetInBits() const
LLVM_ABI Constant * getDiscriminantValue() const
LLVM_ABI uint32_t getVBPtrOffset() const
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata std::optional< unsigned > std::optional< PtrAuthData > DIFlags Metadata * ExtraData
unsigned StringRef DIFile unsigned Line
int64_t bool MDString * Name
LLVM_ABI unsigned getSize() const
Return the size of the operand.
uint64_t getOp() const
Get the operand code.
An iterator for expression operands.
element_iterator elements_end() const
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
iterator_range< expr_op_iterator > expr_ops() const
static LLVM_ABI DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
std::array< uint64_t, 6 > ExtOps
unsigned getNumElements() const
static LLVM_ABI ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed)
Returns the ops for a zero- or sign-extension in a DIExpression.
expr_op_iterator expr_op_begin() const
Visit the elements via ExprOperand wrappers.
LLVM_ABI bool extractIfOffset(int64_t &Offset) const
If this is a constant offset, extract it.
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI bool isEqualExpression(const DIExpression *FirstExpr, bool FirstIndirect, const DIExpression *SecondExpr, bool SecondIndirect)
Determines whether two debug values should produce equivalent DWARF expressions, using their DIExpres...
expr_op_iterator expr_op_end() const
LLVM_ABI bool isImplicit() const
Return whether this is an implicit location description.
static LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
element_iterator elements_begin() const
LLVM_ABI bool hasAllLocationOps(unsigned N) const
Returns true iff this DIExpression contains at least one instance of DW_OP_LLVM_arg,...
std::optional< FragmentInfo > getFragmentInfo() const
Retrieve the details of this fragment expression.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
LLVM_ABI bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static LLVM_ABI std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
LLVM_ABI std::pair< DIExpression *, const ConstantInt * > constantFold(const ConstantInt *CI)
Try to shorten an expression with an initial constant operand.
LLVM_ABI bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static LLVM_ABI const DIExpression * convertToVariadicExpression(const DIExpression *Expr)
If Expr is a non-variadic expression (i.e.
LLVM_ABI uint64_t getNumLocationOperands() const
Return the number of unique location operands referred to (via DW_OP_LLVM_arg) in this expression; th...
ArrayRef< uint64_t > getElements() const
static LLVM_ABI DIExpression * replaceArg(const DIExpression *Expr, uint64_t OldArg, uint64_t NewArg)
Create a copy of Expr with each instance of DW_OP_LLVM_arg, \p OldArg replaced with DW_OP_LLVM_arg,...
LLVM_ABI std::optional< uint64_t > getActiveBits(DIVariable *Var)
Return the number of bits that have an active value, i.e.
static LLVM_ABI void canonicalizeExpressionOps(SmallVectorImpl< uint64_t > &Ops, const DIExpression *Expr, bool IsIndirect)
Inserts the elements of Expr into Ops modified to a canonical form, which uses DW_OP_LLVM_arg (i....
uint64_t getElement(unsigned I) const
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static LLVM_ABI const DIExpression * convertToUndefExpression(const DIExpression *Expr)
Removes all elements from Expr that do not apply to an undef debug value, which includes every operat...
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
static LLVM_ABI DIExpression * appendToStack(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Convert DIExpr into a stack value if it isn't one already by appending DW_OP_deref if needed,...
static LLVM_ABI DIExpression * appendExt(const DIExpression *Expr, unsigned FromSize, unsigned ToSize, bool Signed)
Append a zero- or sign-extension to Expr.
LLVM_ABI std::optional< ArrayRef< uint64_t > > getSingleLocationExpressionElements() const
Returns a reference to the elements contained in this expression, skipping past the leading DW_OP_LLV...
LLVM_ABI bool isSingleLocationExpression() const
Return whether the evaluated expression makes use of a single location at the start of the expression...
LLVM_ABI bool extractLeadingOffset(int64_t &OffsetInBytes, SmallVectorImpl< uint64_t > &RemainingOps) const
Assuming that the expression operates on an address, extract a constant offset and the successive ops...
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
LLVM_ABI bool isValid() const
static LLVM_ABI const DIExpression * extractAddressClass(const DIExpression *Expr, unsigned &AddrClass)
Checks if the last 4 elements of the expression are DW_OP_constu <DWARF Address Space> DW_OP_swap DW_...
static LLVM_ABI DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
MDString MDString * Directory
static LLVM_ABI std::optional< ChecksumKind > getChecksumKind(StringRef CSKindStr)
MDString MDString std::optional< ChecksumInfo< MDString * > > CS
static LLVM_ABI std::optional< FixedPointKind > getFixedPointKind(StringRef Str)
static LLVM_ABI const char * fixedPointKindString(FixedPointKind)
unsigned StringRef uint64_t uint32_t unsigned Encoding
unsigned StringRef uint64_t uint32_t AlignInBits
LLVM_ABI bool isSigned() const
@ FixedPointBinary
Scale factor 2^Factor.
@ FixedPointDecimal
Scale factor 10^Factor.
@ FixedPointRational
Arbitrary rational scale factor.
unsigned StringRef uint64_t uint32_t unsigned DIFlags Flags
unsigned StringRef uint64_t SizeInBits
Metadata * getRawLowerBound() const
Metadata * getRawCountNode() const
Metadata * getRawStride() const
LLVM_ABI BoundType getLowerBound() const
Metadata * getRawUpperBound() const
LLVM_ABI BoundType getCount() const
LLVM_ABI BoundType getUpperBound() const
PointerUnion< DIVariable *, DIExpression * > BoundType
LLVM_ABI BoundType getStride() const
A pair of DIGlobalVariable and DIExpression.
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata Metadata * TemplateParams
Metadata MDString MDString Metadata unsigned Line
Metadata MDString MDString Metadata unsigned Metadata * Type
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata * StaticDataMemberDeclaration
Metadata MDString MDString * LinkageName
Metadata MDString MDString Metadata * File
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata Metadata uint32_t AlignInBits
An imported module (C++ using directive or similar).
unsigned Metadata Metadata * Entity
unsigned Metadata Metadata Metadata unsigned Line
unsigned Metadata Metadata Metadata unsigned MDString * Name
unsigned Metadata Metadata Metadata * File
unsigned Metadata * Scope
Metadata MDString Metadata unsigned Line
Metadata MDString Metadata * File
LLVM_ABI DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef< Metadata * > Ops)
Metadata Metadata unsigned Discriminator
Metadata Metadata unsigned Line
LLVM_ABI DISubprogram * getSubprogram() const
Get the subprogram for this scope.
LLVM_ABI DILocalScope * getNonLexicalBlockFileScope() const
Get the first non DILexicalBlockFile scope of this scope.
static LLVM_ABI DILocalScope * cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx, DenseMap< const MDNode *, MDNode * > &Cache)
Traverses the scope chain rooted at RootScope until it hits a Subprogram, recreating the chain with "...
Metadata MDString Metadata unsigned Metadata * Type
Metadata MDString Metadata * File
Metadata MDString Metadata unsigned Line
Metadata MDString Metadata unsigned Metadata unsigned DIFlags uint32_t AlignInBits
unsigned unsigned DILocalScope * Scope
static LLVM_ABI DILocation * getMergedLocations(ArrayRef< DILocation * > Locs)
Try to combine the vector of locations passed as input in a single one.
static LLVM_ABI std::optional< unsigned > encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI)
Raw encoding of the discriminator.
unsigned unsigned DILocalScope DILocation bool ImplicitCode
static LLVM_ABI void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, unsigned &CI)
Raw decoder for values in an encoded discriminator D.
static LLVM_ABI DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
Attempts to merge LocA and LocB into a single location; see DebugLoc::getMergedLocation for more deta...
unsigned unsigned DILocalScope DILocation * InlinedAt
unsigned unsigned Metadata * File
unsigned unsigned Metadata Metadata * Elements
unsigned unsigned MDString * Name
Represents a module in the programming language, for example, a Clang module, or a Fortran module.
Metadata Metadata * Scope
Metadata Metadata MDString * Name
Metadata Metadata MDString MDString MDString MDString * APINotesFile
Metadata Metadata MDString MDString MDString * IncludePath
Metadata Metadata MDString MDString * ConfigurationMacros
Metadata Metadata MDString MDString MDString MDString unsigned LineNo
Metadata MDString bool ExportSymbols
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
static LLVM_ABI DIFlags getFlag(StringRef Flag)
static LLVM_ABI DIFlags splitFlags(DIFlags Flags, SmallVectorImpl< DIFlags > &SplitFlags)
Split up a flags bitfield.
static LLVM_ABI StringRef getFlagString(DIFlags Flag)
MDString Metadata unsigned MDString * GetterName
MDString Metadata unsigned MDString MDString * SetterName
Base class for scope-like contexts.
LLVM_ABI StringRef getName() const
LLVM_ABI DIScope * getScope() const
String type, Fortran CHARACTER(n)
unsigned MDString Metadata Metadata Metadata uint64_t SizeInBits
unsigned MDString Metadata Metadata Metadata uint64_t uint32_t AlignInBits
unsigned MDString Metadata Metadata Metadata * StringLocationExp
unsigned MDString Metadata Metadata * StringLengthExp
unsigned MDString Metadata * StringLength
Subprogram description. Uses SubclassData1.
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata * Unit
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata Metadata MDString bool UsesKeyInstructions
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata Metadata * Annotations
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata * ContainingType
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata * TemplateParams
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata * Declaration
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata Metadata MDString * TargetFuncName
static LLVM_ABI DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, unsigned Virtuality=SPFlagNonvirtual, bool IsMainSubprogram=false)
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata * ThrownTypes
static LLVM_ABI DISPFlags getFlag(StringRef Flag)
Metadata MDString MDString Metadata * File
static LLVM_ABI DISPFlags splitFlags(DISPFlags Flags, SmallVectorImpl< DISPFlags > &SplitFlags)
Split up a flags bitfield for easier printing.
Metadata MDString MDString * LinkageName
static LLVM_ABI StringRef getFlagString(DISPFlags Flag)
Metadata MDString MDString Metadata unsigned Metadata * Type
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata * RetainedNodes
DISPFlags
Debug info subprogram flags.
StringRef DIFile unsigned Line
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata * UpperBound
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType * BaseType
PointerUnion< ConstantInt *, DIVariable *, DIExpression * > BoundType
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata Metadata Metadata * Bias
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata Metadata * Stride
StringRef DIFile unsigned DIScope uint64_t SizeInBits
StringRef DIFile unsigned DIScope * Scope
StringRef DIFile unsigned DIScope uint64_t uint32_t AlignInBits
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata * LowerBound
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags Flags
LLVM_ABI BoundType getUpperBound() const
LLVM_ABI BoundType getStride() const
LLVM_ABI BoundType getLowerBound() const
LLVM_ABI BoundType getCount() const
Type array for a subprogram.
DIFlags uint8_t Metadata * TypeArray
Base class for template parameters.
unsigned MDString Metadata * Type
bool isStaticMember() const
LLVM_ABI uint32_t getAlignInBits() const
Base class for variables.
std::optional< DIBasicType::Signedness > getSignedness() const
Return the signedness of this variable's type, or std::nullopt if this type is neither signed nor uns...
LLVM_ABI std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
Metadata * getRawType() const
LLVM_ABI DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, signed Line, ArrayRef< Metadata * > Ops, uint32_t AlignInBits=0)
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI DebugVariable(const DbgVariableRecord *DVR)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Class representing an expression and its matching format.
Generic tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
unsigned MDString * Header
unsigned MDString ArrayRef< Metadata * > DwarfOps
DenseSet< DIArgList *, DIArgListInfo > DIArgLists
This is an important class for using LLVM in a threaded context.
LLVMContextImpl *const pImpl
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVM_ABI TempMDNode clone() const
Create a (temporary) clone of this.
static T * storeImpl(T *N, StorageType Storage, StoreT &Store)
LLVMContext & getContext() const
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
LLVM_ABI StringRef getString() const
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Implements a dense probed hash-table based set with some number of buckets stored inline.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM Value Representation.
LLVM_ABI std::optional< int64_t > getPointerOffsetFrom(const Value *Other, const DataLayout &DL) const
If this ptr is provably equal to Other plus a constant offset, return that offset in bytes.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_entry_value
Only used in LLVM metadata.
@ DW_OP_LLVM_implicit_pointer
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
@ DW_OP_LLVM_convert
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
static T * getUniqued(DenseSet< T *, InfoT > &Store, const typename InfoT::KeyTy &Key)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI cl::opt< bool > EnableFSDiscriminator
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
@ Ref
The access may reference the value stored in memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI cl::opt< bool > PickMergedSourceLocations("pick-merged-source-locations", cl::init(false), cl::Hidden, cl::desc("Preserve line and column number when merging locations."))
@ Default
The result values are uniform if and only if all operands are uniform.
Implement std::hash so that hash_code can be used in STL containers.
SmallPtrSet< DIScope *, 8 > Scopes
void insert(DIScope *S, LineColumn Loc)
DIScope * match(DIScope *S, LineColumn Loc)
void insert(DIScope *S, LineColumn Loc)
DIScope * match(DIScope *S, LineColumn Loc)
SmallMapVector< std::pair< DIFile *, LineColumn >, SmallSetVector< DIScope *, 8 >, 8 > Scopes
A single checksum, represented by a Kind and a Value (a string).
static DbgVariableFragmentInfo intersect(DbgVariableFragmentInfo A, DbgVariableFragmentInfo B)
Returns a zero-sized fragment if A and B don't intersect.
A MapVector that performs no allocations if smaller than a certain size.