| 1 | //===--- DIBuilder.cpp - Debug Information Builder ------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the DIBuilder. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "llvm/IR/DIBuilder.h" |
| 14 | #include "LLVMContextImpl.h" |
| 15 | #include "llvm/ADT/APInt.h" |
| 16 | #include "llvm/ADT/APSInt.h" |
| 17 | #include "llvm/BinaryFormat/Dwarf.h" |
| 18 | #include "llvm/IR/Constants.h" |
| 19 | #include "llvm/IR/DebugInfo.h" |
| 20 | #include "llvm/IR/Module.h" |
| 21 | #include <optional> |
| 22 | |
| 23 | using namespace llvm; |
| 24 | using namespace llvm::dwarf; |
| 25 | |
| 26 | DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) |
| 27 | : M(m), VMContext(M.getContext()), CUNode(CU), |
| 28 | AllowUnresolvedNodes(AllowUnresolvedNodes) { |
| 29 | if (CUNode) { |
| 30 | if (const auto &ETs = CUNode->getEnumTypes()) |
| 31 | EnumTypes.assign(in_start: ETs.begin(), in_end: ETs.end()); |
| 32 | if (const auto &RTs = CUNode->getRetainedTypes()) |
| 33 | AllRetainTypes.assign(in_start: RTs.begin(), in_end: RTs.end()); |
| 34 | if (const auto &GVs = CUNode->getGlobalVariables()) |
| 35 | Globals.assign(in_start: GVs.begin(), in_end: GVs.end()); |
| 36 | if (const auto &IMs = CUNode->getImportedEntities()) |
| 37 | ImportedModules.assign(in_start: IMs.begin(), in_end: IMs.end()); |
| 38 | if (const auto &MNs = CUNode->getMacros()) |
| 39 | AllMacrosPerParent.insert(KV: {nullptr, {llvm::from_range, MNs}}); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | void DIBuilder::trackIfUnresolved(MDNode *N) { |
| 44 | if (!N) |
| 45 | return; |
| 46 | if (N->isResolved()) |
| 47 | return; |
| 48 | |
| 49 | assert(AllowUnresolvedNodes && "Cannot handle unresolved nodes" ); |
| 50 | UnresolvedNodes.emplace_back(Args&: N); |
| 51 | } |
| 52 | |
| 53 | void DIBuilder::finalizeSubprogram(DISubprogram *SP) { |
| 54 | auto PN = SubprogramTrackedNodes.find(Val: SP); |
| 55 | if (PN == SubprogramTrackedNodes.end()) |
| 56 | return; |
| 57 | |
| 58 | SetVector<Metadata *> RetainedNodes; |
| 59 | for (MDNode *N : llvm::concat<MDNode *>(Ranges: SP->getRetainedNodes(), Ranges&: PN->second)) { |
| 60 | // If the tracked node N was temporary, and the DIBuilder user replaced it |
| 61 | // with a node that does not belong to SP or is non-local, do not add N to |
| 62 | // SP's retainedNodes list. |
| 63 | DILocalScope *Scope = dyn_cast_or_null<DILocalScope>( |
| 64 | Val: DISubprogram::getRawRetainedNodeScope(N)); |
| 65 | if (Scope && Scope->getSubprogram() == SP) |
| 66 | RetainedNodes.insert(X: N); |
| 67 | } |
| 68 | |
| 69 | SP->replaceRetainedNodes( |
| 70 | N: MDTuple::get(Context&: VMContext, MDs: RetainedNodes.getArrayRef())); |
| 71 | } |
| 72 | |
| 73 | void DIBuilder::finalize() { |
| 74 | if (!CUNode) { |
| 75 | assert(!AllowUnresolvedNodes && |
| 76 | "creating type nodes without a CU is not supported" ); |
| 77 | return; |
| 78 | } |
| 79 | |
| 80 | if (!EnumTypes.empty()) |
| 81 | CUNode->replaceEnumTypes( |
| 82 | N: MDTuple::get(Context&: VMContext, MDs: SmallVector<Metadata *, 16>(EnumTypes.begin(), |
| 83 | EnumTypes.end()))); |
| 84 | |
| 85 | SmallVector<Metadata *, 16> RetainValues; |
| 86 | // Declarations and definitions of the same type may be retained. Some |
| 87 | // clients RAUW these pairs, leaving duplicates in the retained types |
| 88 | // list. Use a set to remove the duplicates while we transform the |
| 89 | // TrackingVHs back into Values. |
| 90 | SmallPtrSet<Metadata *, 16> RetainSet; |
| 91 | for (const TrackingMDNodeRef &N : AllRetainTypes) |
| 92 | if (RetainSet.insert(Ptr: N).second) |
| 93 | RetainValues.push_back(Elt: N); |
| 94 | |
| 95 | if (!RetainValues.empty()) |
| 96 | CUNode->replaceRetainedTypes(N: MDTuple::get(Context&: VMContext, MDs: RetainValues)); |
| 97 | |
| 98 | for (auto *SP : AllSubprograms) |
| 99 | finalizeSubprogram(SP); |
| 100 | for (auto *N : RetainValues) |
| 101 | if (auto *SP = dyn_cast<DISubprogram>(Val: N)) |
| 102 | finalizeSubprogram(SP); |
| 103 | |
| 104 | if (!Globals.empty()) |
| 105 | CUNode->replaceGlobalVariables(N: MDTuple::get(Context&: VMContext, MDs: Globals)); |
| 106 | |
| 107 | if (!ImportedModules.empty()) |
| 108 | CUNode->replaceImportedEntities(N: MDTuple::get( |
| 109 | Context&: VMContext, MDs: SmallVector<Metadata *, 16>(ImportedModules.begin(), |
| 110 | ImportedModules.end()))); |
| 111 | |
| 112 | for (const auto &I : AllMacrosPerParent) { |
| 113 | // DIMacroNode's with nullptr parent are DICompileUnit direct children. |
| 114 | if (!I.first) { |
| 115 | CUNode->replaceMacros(N: MDTuple::get(Context&: VMContext, MDs: I.second.getArrayRef())); |
| 116 | continue; |
| 117 | } |
| 118 | // Otherwise, it must be a temporary DIMacroFile that need to be resolved. |
| 119 | auto *TMF = cast<DIMacroFile>(Val: I.first); |
| 120 | auto *MF = DIMacroFile::get(Context&: VMContext, MIType: dwarf::DW_MACINFO_start_file, |
| 121 | Line: TMF->getLine(), File: TMF->getFile(), |
| 122 | Elements: getOrCreateMacroArray(Elements: I.second.getArrayRef())); |
| 123 | replaceTemporary(N: llvm::TempDIMacroNode(TMF), Replacement: MF); |
| 124 | } |
| 125 | |
| 126 | // Now that all temp nodes have been replaced or deleted, resolve remaining |
| 127 | // cycles. |
| 128 | for (const auto &N : UnresolvedNodes) |
| 129 | if (N && !N->isResolved()) |
| 130 | N->resolveCycles(); |
| 131 | UnresolvedNodes.clear(); |
| 132 | |
| 133 | // Can't handle unresolved nodes anymore. |
| 134 | AllowUnresolvedNodes = false; |
| 135 | } |
| 136 | |
| 137 | /// If N is compile unit return NULL otherwise return N. |
| 138 | static DIScope *getNonCompileUnitScope(DIScope *N) { |
| 139 | if (!N || isa<DICompileUnit>(Val: N)) |
| 140 | return nullptr; |
| 141 | return cast<DIScope>(Val: N); |
| 142 | } |
| 143 | |
| 144 | DICompileUnit *DIBuilder::createCompileUnit( |
| 145 | DISourceLanguageName Lang, DIFile *File, StringRef Producer, |
| 146 | bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, |
| 147 | DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, |
| 148 | bool SplitDebugInlining, bool DebugInfoForProfiling, |
| 149 | DICompileUnit::DebugNameTableKind NameTableKind, bool RangesBaseAddress, |
| 150 | StringRef SysRoot, StringRef SDK) { |
| 151 | |
| 152 | assert(!CUNode && "Can only make one compile unit per DIBuilder instance" ); |
| 153 | CUNode = DICompileUnit::getDistinct( |
| 154 | Context&: VMContext, SourceLanguage: Lang, File, Producer, IsOptimized: isOptimized, Flags, RuntimeVersion: RunTimeVer, |
| 155 | SplitDebugFilename: SplitName, EmissionKind: Kind, EnumTypes: nullptr, RetainedTypes: nullptr, GlobalVariables: nullptr, ImportedEntities: nullptr, Macros: nullptr, DWOId, |
| 156 | SplitDebugInlining, DebugInfoForProfiling, NameTableKind, |
| 157 | RangesBaseAddress, SysRoot, SDK); |
| 158 | |
| 159 | // Create a named metadata so that it is easier to find cu in a module. |
| 160 | NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name: "llvm.dbg.cu" ); |
| 161 | NMD->addOperand(M: CUNode); |
| 162 | trackIfUnresolved(N: CUNode); |
| 163 | return CUNode; |
| 164 | } |
| 165 | |
| 166 | static DIImportedEntity * |
| 167 | createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context, |
| 168 | Metadata *NS, DIFile *File, unsigned Line, StringRef Name, |
| 169 | DINodeArray Elements, |
| 170 | SmallVectorImpl<TrackingMDNodeRef> &ImportedModules) { |
| 171 | if (Line) |
| 172 | assert(File && "Source location has line number but no file" ); |
| 173 | unsigned EntitiesCount = C.pImpl->DIImportedEntitys.size(); |
| 174 | auto *M = DIImportedEntity::get(Context&: C, Tag, Scope: Context, Entity: cast_or_null<DINode>(Val: NS), |
| 175 | File, Line, Name, Elements); |
| 176 | if (EntitiesCount < C.pImpl->DIImportedEntitys.size()) |
| 177 | // A new Imported Entity was just added to the context. |
| 178 | // Add it to the Imported Modules list. |
| 179 | ImportedModules.emplace_back(Args&: M); |
| 180 | return M; |
| 181 | } |
| 182 | |
| 183 | DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, |
| 184 | DINamespace *NS, DIFile *File, |
| 185 | unsigned Line, |
| 186 | DINodeArray Elements) { |
| 187 | return ::createImportedModule(C&: VMContext, Tag: dwarf::DW_TAG_imported_module, |
| 188 | Context, NS, File, Line, Name: StringRef(), Elements, |
| 189 | ImportedModules&: getImportTrackingVector(S: Context)); |
| 190 | } |
| 191 | |
| 192 | DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, |
| 193 | DIImportedEntity *NS, |
| 194 | DIFile *File, unsigned Line, |
| 195 | DINodeArray Elements) { |
| 196 | return ::createImportedModule(C&: VMContext, Tag: dwarf::DW_TAG_imported_module, |
| 197 | Context, NS, File, Line, Name: StringRef(), Elements, |
| 198 | ImportedModules&: getImportTrackingVector(S: Context)); |
| 199 | } |
| 200 | |
| 201 | DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M, |
| 202 | DIFile *File, unsigned Line, |
| 203 | DINodeArray Elements) { |
| 204 | return ::createImportedModule(C&: VMContext, Tag: dwarf::DW_TAG_imported_module, |
| 205 | Context, NS: M, File, Line, Name: StringRef(), Elements, |
| 206 | ImportedModules&: getImportTrackingVector(S: Context)); |
| 207 | } |
| 208 | |
| 209 | DIImportedEntity * |
| 210 | DIBuilder::createImportedDeclaration(DIScope *Context, DINode *Decl, |
| 211 | DIFile *File, unsigned Line, |
| 212 | StringRef Name, DINodeArray Elements) { |
| 213 | // Make sure to use the unique identifier based metadata reference for |
| 214 | // types that have one. |
| 215 | return ::createImportedModule(C&: VMContext, Tag: dwarf::DW_TAG_imported_declaration, |
| 216 | Context, NS: Decl, File, Line, Name, Elements, |
| 217 | ImportedModules&: getImportTrackingVector(S: Context)); |
| 218 | } |
| 219 | |
| 220 | DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory, |
| 221 | std::optional<DIFile::ChecksumInfo<StringRef>> CS, |
| 222 | std::optional<StringRef> Source) { |
| 223 | return DIFile::get(Context&: VMContext, Filename, Directory, CS, Source); |
| 224 | } |
| 225 | |
| 226 | DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber, |
| 227 | unsigned MacroType, StringRef Name, |
| 228 | StringRef Value) { |
| 229 | assert(!Name.empty() && "Unable to create macro without name" ); |
| 230 | assert((MacroType == dwarf::DW_MACINFO_undef || |
| 231 | MacroType == dwarf::DW_MACINFO_define) && |
| 232 | "Unexpected macro type" ); |
| 233 | auto *M = DIMacro::get(Context&: VMContext, MIType: MacroType, Line: LineNumber, Name, Value); |
| 234 | AllMacrosPerParent[Parent].insert(X: M); |
| 235 | return M; |
| 236 | } |
| 237 | |
| 238 | DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent, |
| 239 | unsigned LineNumber, DIFile *File) { |
| 240 | auto *MF = DIMacroFile::getTemporary(Context&: VMContext, MIType: dwarf::DW_MACINFO_start_file, |
| 241 | Line: LineNumber, File, Elements: DIMacroNodeArray()) |
| 242 | .release(); |
| 243 | AllMacrosPerParent[Parent].insert(X: MF); |
| 244 | // Add the new temporary DIMacroFile to the macro per parent map as a parent. |
| 245 | // This is needed to assure DIMacroFile with no children to have an entry in |
| 246 | // the map. Otherwise, it will not be resolved in DIBuilder::finalize(). |
| 247 | AllMacrosPerParent.insert(KV: {MF, {}}); |
| 248 | return MF; |
| 249 | } |
| 250 | |
| 251 | DIEnumerator *DIBuilder::createEnumerator(StringRef Name, uint64_t Val, |
| 252 | bool IsUnsigned) { |
| 253 | assert(!Name.empty() && "Unable to create enumerator without name" ); |
| 254 | return DIEnumerator::get(Context&: VMContext, Value: APInt(64, Val, !IsUnsigned), IsUnsigned, |
| 255 | Name); |
| 256 | } |
| 257 | |
| 258 | DIEnumerator *DIBuilder::createEnumerator(StringRef Name, const APSInt &Value) { |
| 259 | assert(!Name.empty() && "Unable to create enumerator without name" ); |
| 260 | return DIEnumerator::get(Context&: VMContext, Value: APInt(Value), IsUnsigned: Value.isUnsigned(), Name); |
| 261 | } |
| 262 | |
| 263 | DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) { |
| 264 | assert(!Name.empty() && "Unable to create type without name" ); |
| 265 | return DIBasicType::get(Context&: VMContext, Tag: dwarf::DW_TAG_unspecified_type, Name); |
| 266 | } |
| 267 | |
| 268 | DIBasicType *DIBuilder::createNullPtrType() { |
| 269 | return createUnspecifiedType(Name: "decltype(nullptr)" ); |
| 270 | } |
| 271 | |
| 272 | DIBasicType *DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, |
| 273 | unsigned Encoding, |
| 274 | DINode::DIFlags Flags, |
| 275 | uint32_t , |
| 276 | uint32_t DataSizeInBits) { |
| 277 | return DIBasicType::get(Context&: VMContext, Tag: dwarf::DW_TAG_base_type, Name, File: nullptr, LineNo: 0, |
| 278 | Scope: nullptr, SizeInBits, AlignInBits: 0, Encoding, NumExtraInhabitants, |
| 279 | DataSizeInBits, Flags); |
| 280 | } |
| 281 | |
| 282 | DIBasicType *DIBuilder::createBasicType(StringRef Name, DIFile *File, |
| 283 | unsigned LineNo, DIScope *Context, |
| 284 | uint64_t SizeInBits, unsigned Encoding, |
| 285 | DINode::DIFlags Flags, |
| 286 | uint32_t , |
| 287 | uint32_t DataSizeInBits) { |
| 288 | auto *R = DIBasicType::get(Context&: VMContext, Tag: dwarf::DW_TAG_base_type, Name, File, |
| 289 | LineNo, Scope: Context, SizeInBits, AlignInBits: 0, Encoding, |
| 290 | NumExtraInhabitants, DataSizeInBits, Flags); |
| 291 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 292 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 293 | trackIfUnresolved(N: R); |
| 294 | return R; |
| 295 | } |
| 296 | |
| 297 | DIFixedPointType *DIBuilder::createBinaryFixedPointType( |
| 298 | StringRef Name, DIFile *File, unsigned LineNo, DIScope *Context, |
| 299 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, |
| 300 | DINode::DIFlags Flags, int Factor) { |
| 301 | auto *R = DIFixedPointType::get( |
| 302 | Context&: VMContext, Tag: dwarf::DW_TAG_base_type, Name, File, LineNo, Scope: Context, |
| 303 | SizeInBits, AlignInBits, Encoding, Flags, |
| 304 | Kind: DIFixedPointType::FixedPointBinary, Factor, Numerator: APInt(), Denominator: APInt()); |
| 305 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 306 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 307 | trackIfUnresolved(N: R); |
| 308 | return R; |
| 309 | } |
| 310 | |
| 311 | DIFixedPointType *DIBuilder::createDecimalFixedPointType( |
| 312 | StringRef Name, DIFile *File, unsigned LineNo, DIScope *Context, |
| 313 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, |
| 314 | DINode::DIFlags Flags, int Factor) { |
| 315 | auto *R = DIFixedPointType::get( |
| 316 | Context&: VMContext, Tag: dwarf::DW_TAG_base_type, Name, File, LineNo, Scope: Context, |
| 317 | SizeInBits, AlignInBits, Encoding, Flags, |
| 318 | Kind: DIFixedPointType::FixedPointDecimal, Factor, Numerator: APInt(), Denominator: APInt()); |
| 319 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 320 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 321 | trackIfUnresolved(N: R); |
| 322 | return R; |
| 323 | } |
| 324 | |
| 325 | DIFixedPointType *DIBuilder::createRationalFixedPointType( |
| 326 | StringRef Name, DIFile *File, unsigned LineNo, DIScope *Context, |
| 327 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, |
| 328 | DINode::DIFlags Flags, APInt Numerator, APInt Denominator) { |
| 329 | auto *R = DIFixedPointType::get( |
| 330 | Context&: VMContext, Tag: dwarf::DW_TAG_base_type, Name, File, LineNo, Scope: Context, |
| 331 | SizeInBits, AlignInBits, Encoding, Flags, |
| 332 | Kind: DIFixedPointType::FixedPointRational, Factor: 0, Numerator, Denominator); |
| 333 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 334 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 335 | trackIfUnresolved(N: R); |
| 336 | return R; |
| 337 | } |
| 338 | |
| 339 | DIStringType *DIBuilder::createStringType(StringRef Name, uint64_t SizeInBits) { |
| 340 | assert(!Name.empty() && "Unable to create type without name" ); |
| 341 | return DIStringType::get(Context&: VMContext, Tag: dwarf::DW_TAG_string_type, Name, |
| 342 | SizeInBits, AlignInBits: 0); |
| 343 | } |
| 344 | |
| 345 | DIStringType *DIBuilder::createStringType(StringRef Name, |
| 346 | DIVariable *StringLength, |
| 347 | DIExpression *StrLocationExp) { |
| 348 | assert(!Name.empty() && "Unable to create type without name" ); |
| 349 | return DIStringType::get(Context&: VMContext, Tag: dwarf::DW_TAG_string_type, Name, |
| 350 | StringLength, StringLengthExp: nullptr, StringLocationExp: StrLocationExp, SizeInBits: 0, AlignInBits: 0, Encoding: 0); |
| 351 | } |
| 352 | |
| 353 | DIStringType *DIBuilder::createStringType(StringRef Name, |
| 354 | DIExpression *StringLengthExp, |
| 355 | DIExpression *StrLocationExp) { |
| 356 | assert(!Name.empty() && "Unable to create type without name" ); |
| 357 | return DIStringType::get(Context&: VMContext, Tag: dwarf::DW_TAG_string_type, Name, StringLength: nullptr, |
| 358 | StringLengthExp, StringLocationExp: StrLocationExp, SizeInBits: 0, AlignInBits: 0, Encoding: 0); |
| 359 | } |
| 360 | |
| 361 | DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { |
| 362 | return DIDerivedType::get(Context&: VMContext, Tag, Name: "" , File: nullptr, Line: 0, Scope: nullptr, BaseType: FromTy, |
| 363 | SizeInBits: (uint64_t)0, AlignInBits: 0, OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, |
| 364 | PtrAuthData: std::nullopt, Flags: DINode::FlagZero); |
| 365 | } |
| 366 | |
| 367 | DIDerivedType *DIBuilder::createPtrAuthQualifiedType( |
| 368 | DIType *FromTy, unsigned Key, bool IsAddressDiscriminated, |
| 369 | unsigned , bool IsaPointer, |
| 370 | bool AuthenticatesNullValues) { |
| 371 | return DIDerivedType::get( |
| 372 | Context&: VMContext, Tag: dwarf::DW_TAG_LLVM_ptrauth_type, Name: "" , File: nullptr, Line: 0, Scope: nullptr, |
| 373 | BaseType: FromTy, SizeInBits: (uint64_t)0, AlignInBits: 0, OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, |
| 374 | PtrAuthData: std::optional<DIDerivedType::PtrAuthData>( |
| 375 | std::in_place, Key, IsAddressDiscriminated, ExtraDiscriminator, |
| 376 | IsaPointer, AuthenticatesNullValues), |
| 377 | Flags: DINode::FlagZero); |
| 378 | } |
| 379 | |
| 380 | DIDerivedType * |
| 381 | DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits, |
| 382 | uint32_t AlignInBits, |
| 383 | std::optional<unsigned> DWARFAddressSpace, |
| 384 | StringRef Name, DINodeArray Annotations) { |
| 385 | // FIXME: Why is there a name here? |
| 386 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_pointer_type, Name, |
| 387 | File: nullptr, Line: 0, Scope: nullptr, BaseType: PointeeTy, SizeInBits, |
| 388 | AlignInBits, OffsetInBits: 0, DWARFAddressSpace, PtrAuthData: std::nullopt, |
| 389 | Flags: DINode::FlagZero, ExtraData: nullptr, Annotations); |
| 390 | } |
| 391 | |
| 392 | DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, |
| 393 | DIType *Base, |
| 394 | uint64_t SizeInBits, |
| 395 | uint32_t AlignInBits, |
| 396 | DINode::DIFlags Flags) { |
| 397 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_ptr_to_member_type, Name: "" , |
| 398 | File: nullptr, Line: 0, Scope: nullptr, BaseType: PointeeTy, SizeInBits, |
| 399 | AlignInBits, OffsetInBits: 0, DWARFAddressSpace: std::nullopt, PtrAuthData: std::nullopt, Flags, |
| 400 | ExtraData: Base); |
| 401 | } |
| 402 | |
| 403 | DIDerivedType * |
| 404 | DIBuilder::createReferenceType(unsigned Tag, DIType *RTy, uint64_t SizeInBits, |
| 405 | uint32_t AlignInBits, |
| 406 | std::optional<unsigned> DWARFAddressSpace) { |
| 407 | assert(RTy && "Unable to create reference type" ); |
| 408 | return DIDerivedType::get(Context&: VMContext, Tag, Name: "" , File: nullptr, Line: 0, Scope: nullptr, BaseType: RTy, |
| 409 | SizeInBits, AlignInBits, OffsetInBits: 0, DWARFAddressSpace, PtrAuthData: {}, |
| 410 | Flags: DINode::FlagZero); |
| 411 | } |
| 412 | |
| 413 | DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, |
| 414 | DIFile *File, unsigned LineNo, |
| 415 | DIScope *Context, uint32_t AlignInBits, |
| 416 | DINode::DIFlags Flags, |
| 417 | DINodeArray Annotations) { |
| 418 | auto *T = DIDerivedType::get( |
| 419 | Context&: VMContext, Tag: dwarf::DW_TAG_typedef, Name, File, Line: LineNo, |
| 420 | Scope: getNonCompileUnitScope(N: Context), BaseType: Ty, SizeInBits: (uint64_t)0, AlignInBits, |
| 421 | OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, PtrAuthData: std::nullopt, Flags, ExtraData: nullptr, Annotations); |
| 422 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 423 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: T); |
| 424 | return T; |
| 425 | } |
| 426 | |
| 427 | DIDerivedType * |
| 428 | DIBuilder::createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File, |
| 429 | unsigned LineNo, DIScope *Context, |
| 430 | DINodeArray TParams, uint32_t AlignInBits, |
| 431 | DINode::DIFlags Flags, DINodeArray Annotations) { |
| 432 | auto *T = |
| 433 | DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_template_alias, Name, File, |
| 434 | Line: LineNo, Scope: getNonCompileUnitScope(N: Context), BaseType: Ty, |
| 435 | SizeInBits: (uint64_t)0, AlignInBits, OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, |
| 436 | PtrAuthData: std::nullopt, Flags, ExtraData: TParams.get(), Annotations); |
| 437 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 438 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: T); |
| 439 | return T; |
| 440 | } |
| 441 | |
| 442 | DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { |
| 443 | assert(Ty && "Invalid type!" ); |
| 444 | assert(FriendTy && "Invalid friend type!" ); |
| 445 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_friend, Name: "" , File: nullptr, Line: 0, Scope: Ty, |
| 446 | BaseType: FriendTy, SizeInBits: (uint64_t)0, AlignInBits: 0, OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, |
| 447 | PtrAuthData: std::nullopt, Flags: DINode::FlagZero); |
| 448 | } |
| 449 | |
| 450 | DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, |
| 451 | uint64_t BaseOffset, |
| 452 | uint32_t VBPtrOffset, |
| 453 | DINode::DIFlags Flags) { |
| 454 | assert(Ty && "Unable to create inheritance" ); |
| 455 | Metadata * = ConstantAsMetadata::get( |
| 456 | C: ConstantInt::get(Ty: IntegerType::get(C&: VMContext, NumBits: 32), V: VBPtrOffset)); |
| 457 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_inheritance, Name: "" , File: nullptr, |
| 458 | Line: 0, Scope: Ty, BaseType: BaseTy, SizeInBits: 0, AlignInBits: 0, OffsetInBits: BaseOffset, DWARFAddressSpace: std::nullopt, |
| 459 | PtrAuthData: std::nullopt, Flags, ExtraData); |
| 460 | } |
| 461 | |
| 462 | DIDerivedType *DIBuilder::createMemberType( |
| 463 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 464 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, |
| 465 | DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { |
| 466 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, |
| 467 | Line: LineNumber, Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, |
| 468 | SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace: std::nullopt, |
| 469 | PtrAuthData: std::nullopt, Flags, ExtraData: nullptr, Annotations); |
| 470 | } |
| 471 | |
| 472 | DIDerivedType *DIBuilder::createMemberType( |
| 473 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 474 | Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, |
| 475 | DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { |
| 476 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, |
| 477 | Line: LineNumber, Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, |
| 478 | SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace: std::nullopt, |
| 479 | PtrAuthData: std::nullopt, Flags, ExtraData: nullptr, Annotations); |
| 480 | } |
| 481 | |
| 482 | static ConstantAsMetadata *getConstantOrNull(Constant *C) { |
| 483 | if (C) |
| 484 | return ConstantAsMetadata::get(C); |
| 485 | return nullptr; |
| 486 | } |
| 487 | |
| 488 | DIDerivedType *DIBuilder::createVariantMemberType( |
| 489 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 490 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, |
| 491 | Constant *Discriminant, DINode::DIFlags Flags, DIType *Ty) { |
| 492 | // "ExtraData" is overloaded for bit fields and for variants, so |
| 493 | // make sure to disallow this. |
| 494 | assert((Flags & DINode::FlagBitField) == 0); |
| 495 | return DIDerivedType::get( |
| 496 | Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, Line: LineNumber, |
| 497 | Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, SizeInBits, AlignInBits, OffsetInBits, |
| 498 | DWARFAddressSpace: std::nullopt, PtrAuthData: std::nullopt, Flags, ExtraData: getConstantOrNull(C: Discriminant)); |
| 499 | } |
| 500 | |
| 501 | DIDerivedType *DIBuilder::createVariantMemberType(DIScope *Scope, |
| 502 | DINodeArray Elements, |
| 503 | Constant *Discriminant, |
| 504 | DIType *Ty) { |
| 505 | auto *V = DICompositeType::get(Context&: VMContext, Tag: dwarf::DW_TAG_variant, Name: {}, File: nullptr, |
| 506 | Line: 0, Scope: getNonCompileUnitScope(N: Scope), BaseType: {}, |
| 507 | SizeInBits: (uint64_t)0, AlignInBits: 0, OffsetInBits: (uint64_t)0, Flags: DINode::FlagZero, |
| 508 | Elements, RuntimeLang: 0, EnumKind: {}, VTableHolder: nullptr); |
| 509 | |
| 510 | trackIfUnresolved(N: V); |
| 511 | return createVariantMemberType(Scope, Name: {}, File: nullptr, LineNumber: 0, SizeInBits: 0, AlignInBits: 0, OffsetInBits: 0, Discriminant, |
| 512 | Flags: DINode::FlagZero, Ty: V); |
| 513 | } |
| 514 | |
| 515 | DIDerivedType *DIBuilder::createBitFieldMemberType( |
| 516 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 517 | Metadata *SizeInBits, Metadata *OffsetInBits, uint64_t StorageOffsetInBits, |
| 518 | DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { |
| 519 | Flags |= DINode::FlagBitField; |
| 520 | return DIDerivedType::get( |
| 521 | Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, Line: LineNumber, |
| 522 | Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, SizeInBits, /*AlignInBits=*/0, |
| 523 | OffsetInBits, DWARFAddressSpace: std::nullopt, PtrAuthData: std::nullopt, Flags, |
| 524 | ExtraData: ConstantAsMetadata::get(C: ConstantInt::get(Ty: IntegerType::get(C&: VMContext, NumBits: 64), |
| 525 | V: StorageOffsetInBits)), |
| 526 | Annotations); |
| 527 | } |
| 528 | |
| 529 | DIDerivedType *DIBuilder::createBitFieldMemberType( |
| 530 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 531 | uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits, |
| 532 | DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { |
| 533 | Flags |= DINode::FlagBitField; |
| 534 | return DIDerivedType::get( |
| 535 | Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, Line: LineNumber, |
| 536 | Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, SizeInBits, /*AlignInBits=*/0, |
| 537 | OffsetInBits, DWARFAddressSpace: std::nullopt, PtrAuthData: std::nullopt, Flags, |
| 538 | ExtraData: ConstantAsMetadata::get(C: ConstantInt::get(Ty: IntegerType::get(C&: VMContext, NumBits: 64), |
| 539 | V: StorageOffsetInBits)), |
| 540 | Annotations); |
| 541 | } |
| 542 | |
| 543 | DIDerivedType * |
| 544 | DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name, DIFile *File, |
| 545 | unsigned LineNumber, DIType *Ty, |
| 546 | DINode::DIFlags Flags, llvm::Constant *Val, |
| 547 | unsigned Tag, uint32_t AlignInBits) { |
| 548 | Flags |= DINode::FlagStaticMember; |
| 549 | return DIDerivedType::get(Context&: VMContext, Tag, Name, File, Line: LineNumber, |
| 550 | Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, SizeInBits: (uint64_t)0, |
| 551 | AlignInBits, OffsetInBits: (uint64_t)0, DWARFAddressSpace: std::nullopt, |
| 552 | PtrAuthData: std::nullopt, Flags, ExtraData: getConstantOrNull(C: Val)); |
| 553 | } |
| 554 | |
| 555 | DIDerivedType * |
| 556 | DIBuilder::createObjCIVar(StringRef Name, DIFile *File, unsigned LineNumber, |
| 557 | uint64_t SizeInBits, uint32_t AlignInBits, |
| 558 | uint64_t OffsetInBits, DINode::DIFlags Flags, |
| 559 | DIType *Ty, MDNode *PropertyNode) { |
| 560 | return DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_member, Name, File, |
| 561 | Line: LineNumber, Scope: getNonCompileUnitScope(N: File), BaseType: Ty, |
| 562 | SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace: std::nullopt, |
| 563 | PtrAuthData: std::nullopt, Flags, ExtraData: PropertyNode); |
| 564 | } |
| 565 | |
| 566 | DIObjCProperty * |
| 567 | DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber, |
| 568 | StringRef GetterName, StringRef SetterName, |
| 569 | unsigned PropertyAttributes, DIType *Ty) { |
| 570 | return DIObjCProperty::get(Context&: VMContext, Name, File, Line: LineNumber, GetterName, |
| 571 | SetterName, Attributes: PropertyAttributes, Type: Ty); |
| 572 | } |
| 573 | |
| 574 | DIProperty *DIBuilder::createProperty(StringRef Name, DIFile *File, |
| 575 | unsigned LineNumber, DIType *Ty, |
| 576 | DIDerivedType *BackingStorage) { |
| 577 | return DIProperty::get(Context&: VMContext, Name, File, Line: LineNumber, Type: Ty, BackingStorage); |
| 578 | } |
| 579 | |
| 580 | DITemplateTypeParameter * |
| 581 | DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name, |
| 582 | DIType *Ty, bool isDefault) { |
| 583 | assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit" ); |
| 584 | return DITemplateTypeParameter::get(Context&: VMContext, Name, Type: Ty, IsDefault: isDefault); |
| 585 | } |
| 586 | |
| 587 | static DITemplateValueParameter * |
| 588 | createTemplateValueParameterHelper(LLVMContext &VMContext, unsigned Tag, |
| 589 | DIScope *Context, StringRef Name, DIType *Ty, |
| 590 | bool IsDefault, Metadata *MD) { |
| 591 | assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit" ); |
| 592 | return DITemplateValueParameter::get(Context&: VMContext, Tag, Name, Type: Ty, IsDefault, Value: MD); |
| 593 | } |
| 594 | |
| 595 | DITemplateValueParameter * |
| 596 | DIBuilder::createTemplateValueParameter(DIScope *Context, StringRef Name, |
| 597 | DIType *Ty, bool isDefault, |
| 598 | Constant *Val) { |
| 599 | return createTemplateValueParameterHelper( |
| 600 | VMContext, Tag: dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, |
| 601 | IsDefault: isDefault, MD: getConstantOrNull(C: Val)); |
| 602 | } |
| 603 | |
| 604 | DITemplateValueParameter * |
| 605 | DIBuilder::createTemplateTemplateParameter(DIScope *Context, StringRef Name, |
| 606 | DIType *Ty, StringRef Val, |
| 607 | bool IsDefault) { |
| 608 | return createTemplateValueParameterHelper( |
| 609 | VMContext, Tag: dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, |
| 610 | IsDefault, MD: MDString::get(Context&: VMContext, Str: Val)); |
| 611 | } |
| 612 | |
| 613 | DITemplateValueParameter * |
| 614 | DIBuilder::createTemplateParameterPack(DIScope *Context, StringRef Name, |
| 615 | DIType *Ty, DINodeArray Val) { |
| 616 | return createTemplateValueParameterHelper( |
| 617 | VMContext, Tag: dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty, |
| 618 | IsDefault: false, MD: Val.get()); |
| 619 | } |
| 620 | |
| 621 | DICompositeType *DIBuilder::createClassType( |
| 622 | DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, |
| 623 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, |
| 624 | DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, |
| 625 | unsigned RunTimeLang, DIType *VTableHolder, MDNode *TemplateParams, |
| 626 | StringRef UniqueIdentifier, DINodeArray Annotations) { |
| 627 | assert((!Context || isa<DIScope>(Context)) && |
| 628 | "createClassType should be called with a valid Context" ); |
| 629 | |
| 630 | auto *R = DICompositeType::get( |
| 631 | Context&: VMContext, Tag: dwarf::DW_TAG_class_type, Name, File, Line: LineNumber, |
| 632 | Scope: getNonCompileUnitScope(N: Context), BaseType: DerivedFrom, SizeInBits, AlignInBits, |
| 633 | OffsetInBits, Flags, Elements, RuntimeLang: RunTimeLang, /*EnumKind=*/std::nullopt, |
| 634 | VTableHolder, TemplateParams: cast_or_null<MDTuple>(Val: TemplateParams), Identifier: UniqueIdentifier, |
| 635 | Discriminator: nullptr, DataLocation: nullptr, Associated: nullptr, Allocated: nullptr, Rank: nullptr, Annotations); |
| 636 | trackIfUnresolved(N: R); |
| 637 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 638 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 639 | return R; |
| 640 | } |
| 641 | |
| 642 | DICompositeType *DIBuilder::createStructType( |
| 643 | DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, |
| 644 | Metadata *SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, |
| 645 | DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang, |
| 646 | DIType *VTableHolder, StringRef UniqueIdentifier, DIType *Specification, |
| 647 | uint32_t , DINodeArray Annotations) { |
| 648 | auto *R = DICompositeType::get( |
| 649 | Context&: VMContext, Tag: dwarf::DW_TAG_structure_type, Name, File, Line: LineNumber, |
| 650 | Scope: getNonCompileUnitScope(N: Context), BaseType: DerivedFrom, SizeInBits, AlignInBits, OffsetInBits: 0, |
| 651 | Flags, Elements, RuntimeLang: RunTimeLang, /*EnumKind=*/std::nullopt, VTableHolder, |
| 652 | TemplateParams: nullptr, Identifier: UniqueIdentifier, Discriminator: nullptr, DataLocation: nullptr, Associated: nullptr, Allocated: nullptr, Rank: nullptr, |
| 653 | Annotations, Specification, NumExtraInhabitants); |
| 654 | trackIfUnresolved(N: R); |
| 655 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 656 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 657 | return R; |
| 658 | } |
| 659 | |
| 660 | DICompositeType *DIBuilder::createStructType( |
| 661 | DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber, |
| 662 | uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, |
| 663 | DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang, |
| 664 | DIType *VTableHolder, StringRef UniqueIdentifier, DIType *Specification, |
| 665 | uint32_t , DINodeArray Annotations) { |
| 666 | auto *R = DICompositeType::get( |
| 667 | Context&: VMContext, Tag: dwarf::DW_TAG_structure_type, Name, File, Line: LineNumber, |
| 668 | Scope: getNonCompileUnitScope(N: Context), BaseType: DerivedFrom, SizeInBits, AlignInBits, OffsetInBits: 0, |
| 669 | Flags, Elements, RuntimeLang: RunTimeLang, /*EnumKind=*/std::nullopt, VTableHolder, |
| 670 | TemplateParams: nullptr, Identifier: UniqueIdentifier, Discriminator: nullptr, DataLocation: nullptr, Associated: nullptr, Allocated: nullptr, Rank: nullptr, |
| 671 | Annotations, Specification, NumExtraInhabitants); |
| 672 | trackIfUnresolved(N: R); |
| 673 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 674 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: R); |
| 675 | return R; |
| 676 | } |
| 677 | |
| 678 | DICompositeType *DIBuilder::createUnionType( |
| 679 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 680 | uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, |
| 681 | DINodeArray Elements, unsigned RunTimeLang, StringRef UniqueIdentifier, |
| 682 | DINodeArray Annotations) { |
| 683 | auto *R = DICompositeType::get( |
| 684 | Context&: VMContext, Tag: dwarf::DW_TAG_union_type, Name, File, Line: LineNumber, |
| 685 | Scope: getNonCompileUnitScope(N: Scope), BaseType: nullptr, SizeInBits, AlignInBits, OffsetInBits: 0, Flags, |
| 686 | Elements, RuntimeLang: RunTimeLang, /*EnumKind=*/std::nullopt, VTableHolder: nullptr, TemplateParams: nullptr, |
| 687 | Identifier: UniqueIdentifier, Discriminator: nullptr, DataLocation: nullptr, Associated: nullptr, Allocated: nullptr, Rank: nullptr, |
| 688 | Annotations); |
| 689 | trackIfUnresolved(N: R); |
| 690 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 691 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: R); |
| 692 | return R; |
| 693 | } |
| 694 | |
| 695 | DICompositeType * |
| 696 | DIBuilder::createVariantPart(DIScope *Scope, StringRef Name, DIFile *File, |
| 697 | unsigned LineNumber, uint64_t SizeInBits, |
| 698 | uint32_t AlignInBits, DINode::DIFlags Flags, |
| 699 | DIDerivedType *Discriminator, DINodeArray Elements, |
| 700 | StringRef UniqueIdentifier) { |
| 701 | auto *R = DICompositeType::get( |
| 702 | Context&: VMContext, Tag: dwarf::DW_TAG_variant_part, Name, File, Line: LineNumber, |
| 703 | Scope: getNonCompileUnitScope(N: Scope), BaseType: nullptr, SizeInBits, AlignInBits, OffsetInBits: 0, Flags, |
| 704 | Elements, RuntimeLang: 0, /*EnumKind=*/std::nullopt, VTableHolder: nullptr, TemplateParams: nullptr, |
| 705 | Identifier: UniqueIdentifier, Discriminator); |
| 706 | trackIfUnresolved(N: R); |
| 707 | return R; |
| 708 | } |
| 709 | |
| 710 | DISubroutineType *DIBuilder::createSubroutineType(DITypeArray ParameterTypes, |
| 711 | DINode::DIFlags Flags, |
| 712 | unsigned CC) { |
| 713 | return DISubroutineType::get(Context&: VMContext, Flags, CC, TypeArray: ParameterTypes); |
| 714 | } |
| 715 | |
| 716 | DICompositeType *DIBuilder::createEnumerationType( |
| 717 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 718 | uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements, |
| 719 | DIType *UnderlyingType, unsigned RunTimeLang, StringRef UniqueIdentifier, |
| 720 | bool IsScoped, std::optional<uint32_t> EnumKind) { |
| 721 | auto *CTy = DICompositeType::get( |
| 722 | Context&: VMContext, Tag: dwarf::DW_TAG_enumeration_type, Name, File, Line: LineNumber, |
| 723 | Scope: getNonCompileUnitScope(N: Scope), BaseType: UnderlyingType, SizeInBits, AlignInBits, OffsetInBits: 0, |
| 724 | Flags: IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements, |
| 725 | RuntimeLang: RunTimeLang, EnumKind, VTableHolder: nullptr, TemplateParams: nullptr, Identifier: UniqueIdentifier); |
| 726 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 727 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: CTy); |
| 728 | else |
| 729 | EnumTypes.emplace_back(Args&: CTy); |
| 730 | trackIfUnresolved(N: CTy); |
| 731 | return CTy; |
| 732 | } |
| 733 | |
| 734 | DIDerivedType *DIBuilder::createSetType(DIScope *Scope, StringRef Name, |
| 735 | DIFile *File, unsigned LineNo, |
| 736 | uint64_t SizeInBits, |
| 737 | uint32_t AlignInBits, DIType *Ty) { |
| 738 | auto *R = DIDerivedType::get(Context&: VMContext, Tag: dwarf::DW_TAG_set_type, Name, File, |
| 739 | Line: LineNo, Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, |
| 740 | SizeInBits, AlignInBits, OffsetInBits: 0, DWARFAddressSpace: std::nullopt, |
| 741 | PtrAuthData: std::nullopt, Flags: DINode::FlagZero); |
| 742 | trackIfUnresolved(N: R); |
| 743 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 744 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: R); |
| 745 | return R; |
| 746 | } |
| 747 | |
| 748 | DICompositeType * |
| 749 | DIBuilder::createArrayType(uint64_t Size, uint32_t AlignInBits, DIType *Ty, |
| 750 | DINodeArray Subscripts, |
| 751 | PointerUnion<DIExpression *, DIVariable *> DL, |
| 752 | PointerUnion<DIExpression *, DIVariable *> AS, |
| 753 | PointerUnion<DIExpression *, DIVariable *> AL, |
| 754 | PointerUnion<DIExpression *, DIVariable *> RK) { |
| 755 | return createArrayType(Scope: nullptr, Name: StringRef(), File: nullptr, LineNumber: 0, Size, AlignInBits, |
| 756 | Ty, Subscripts, DataLocation: DL, Associated: AS, Allocated: AL, Rank: RK); |
| 757 | } |
| 758 | |
| 759 | DICompositeType *DIBuilder::createArrayType( |
| 760 | DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, |
| 761 | uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts, |
| 762 | PointerUnion<DIExpression *, DIVariable *> DL, |
| 763 | PointerUnion<DIExpression *, DIVariable *> AS, |
| 764 | PointerUnion<DIExpression *, DIVariable *> AL, |
| 765 | PointerUnion<DIExpression *, DIVariable *> RK, Metadata *BitStride) { |
| 766 | auto *R = DICompositeType::get( |
| 767 | Context&: VMContext, Tag: dwarf::DW_TAG_array_type, Name, File, Line: LineNumber, |
| 768 | Scope: getNonCompileUnitScope(N: Scope), BaseType: Ty, SizeInBits: Size, AlignInBits, OffsetInBits: 0, Flags: DINode::FlagZero, |
| 769 | Elements: Subscripts, RuntimeLang: 0, /*EnumKind=*/std::nullopt, VTableHolder: nullptr, TemplateParams: nullptr, Identifier: "" , Discriminator: nullptr, |
| 770 | DataLocation: isa<DIExpression *>(Val: DL) ? (Metadata *)cast<DIExpression *>(Val&: DL) |
| 771 | : (Metadata *)cast<DIVariable *>(Val&: DL), |
| 772 | Associated: isa<DIExpression *>(Val: AS) ? (Metadata *)cast<DIExpression *>(Val&: AS) |
| 773 | : (Metadata *)cast<DIVariable *>(Val&: AS), |
| 774 | Allocated: isa<DIExpression *>(Val: AL) ? (Metadata *)cast<DIExpression *>(Val&: AL) |
| 775 | : (Metadata *)cast<DIVariable *>(Val&: AL), |
| 776 | Rank: isa<DIExpression *>(Val: RK) ? (Metadata *)cast<DIExpression *>(Val&: RK) |
| 777 | : (Metadata *)cast<DIVariable *>(Val&: RK), |
| 778 | Annotations: nullptr, Specification: nullptr, NumExtraInhabitants: 0, BitStride); |
| 779 | trackIfUnresolved(N: R); |
| 780 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 781 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: R); |
| 782 | return R; |
| 783 | } |
| 784 | |
| 785 | DICompositeType *DIBuilder::createVectorType(uint64_t Size, |
| 786 | uint32_t AlignInBits, DIType *Ty, |
| 787 | DINodeArray Subscripts, |
| 788 | Metadata *BitStride) { |
| 789 | auto *R = DICompositeType::get( |
| 790 | Context&: VMContext, Tag: dwarf::DW_TAG_array_type, /*Name=*/"" , |
| 791 | /*File=*/nullptr, /*Line=*/0, /*Scope=*/nullptr, /*BaseType=*/Ty, |
| 792 | /*SizeInBits=*/Size, /*AlignInBits=*/AlignInBits, /*OffsetInBits=*/0, |
| 793 | /*Flags=*/DINode::FlagVector, /*Elements=*/Subscripts, |
| 794 | /*RuntimeLang=*/0, /*EnumKind=*/std::nullopt, /*VTableHolder=*/nullptr, |
| 795 | /*TemplateParams=*/nullptr, /*Identifier=*/"" , |
| 796 | /*Discriminator=*/nullptr, /*DataLocation=*/nullptr, |
| 797 | /*Associated=*/nullptr, /*Allocated=*/nullptr, /*Rank=*/nullptr, |
| 798 | /*Annotations=*/nullptr, /*Specification=*/nullptr, |
| 799 | /*NumExtraInhabitants=*/0, |
| 800 | /*BitStride=*/BitStride); |
| 801 | trackIfUnresolved(N: R); |
| 802 | return R; |
| 803 | } |
| 804 | |
| 805 | DISubprogram *DIBuilder::createArtificialSubprogram(DISubprogram *SP) { |
| 806 | auto NewSP = SP->cloneWithFlags(NewFlags: SP->getFlags() | DINode::FlagArtificial); |
| 807 | return MDNode::replaceWithDistinct(N: std::move(NewSP)); |
| 808 | } |
| 809 | |
| 810 | static DIType *createTypeWithFlags(const DIType *Ty, |
| 811 | DINode::DIFlags FlagsToSet) { |
| 812 | auto NewTy = Ty->cloneWithFlags(NewFlags: Ty->getFlags() | FlagsToSet); |
| 813 | return MDNode::replaceWithUniqued(N: std::move(NewTy)); |
| 814 | } |
| 815 | |
| 816 | DIType *DIBuilder::createArtificialType(DIType *Ty) { |
| 817 | // FIXME: Restrict this to the nodes where it's valid. |
| 818 | if (Ty->isArtificial()) |
| 819 | return Ty; |
| 820 | return createTypeWithFlags(Ty, FlagsToSet: DINode::FlagArtificial); |
| 821 | } |
| 822 | |
| 823 | DIType *DIBuilder::createObjectPointerType(DIType *Ty, bool Implicit) { |
| 824 | // FIXME: Restrict this to the nodes where it's valid. |
| 825 | if (Ty->isObjectPointer()) |
| 826 | return Ty; |
| 827 | DINode::DIFlags Flags = DINode::FlagObjectPointer; |
| 828 | |
| 829 | if (Implicit) |
| 830 | Flags |= DINode::FlagArtificial; |
| 831 | |
| 832 | return createTypeWithFlags(Ty, FlagsToSet: Flags); |
| 833 | } |
| 834 | |
| 835 | void DIBuilder::retainType(DIScope *T) { |
| 836 | assert(T && "Expected non-null type" ); |
| 837 | assert((isa<DIType>(T) || (isa<DISubprogram>(T) && |
| 838 | cast<DISubprogram>(T)->isDefinition() == false)) && |
| 839 | "Expected type or subprogram declaration" ); |
| 840 | if (!isa_and_nonnull<DILocalScope>(Val: T->getScope())) |
| 841 | AllRetainTypes.emplace_back(Args&: T); |
| 842 | } |
| 843 | |
| 844 | DIBasicType *DIBuilder::createUnspecifiedParameter() { return nullptr; } |
| 845 | |
| 846 | DICompositeType *DIBuilder::createForwardDecl( |
| 847 | unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, |
| 848 | unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, |
| 849 | StringRef UniqueIdentifier, std::optional<uint32_t> EnumKind) { |
| 850 | // FIXME: Define in terms of createReplaceableForwardDecl() by calling |
| 851 | // replaceWithUniqued(). |
| 852 | auto *RetTy = DICompositeType::get( |
| 853 | Context&: VMContext, Tag, Name, File: F, Line, Scope: getNonCompileUnitScope(N: Scope), BaseType: nullptr, |
| 854 | SizeInBits, AlignInBits, OffsetInBits: 0, Flags: DINode::FlagFwdDecl, Elements: nullptr, RuntimeLang, |
| 855 | /*EnumKind=*/EnumKind, VTableHolder: nullptr, TemplateParams: nullptr, Identifier: UniqueIdentifier); |
| 856 | trackIfUnresolved(N: RetTy); |
| 857 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 858 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: RetTy); |
| 859 | return RetTy; |
| 860 | } |
| 861 | |
| 862 | DICompositeType *DIBuilder::createReplaceableCompositeType( |
| 863 | unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, |
| 864 | unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, |
| 865 | DINode::DIFlags Flags, StringRef UniqueIdentifier, DINodeArray Annotations, |
| 866 | std::optional<uint32_t> EnumKind) { |
| 867 | auto *RetTy = |
| 868 | DICompositeType::getTemporary( |
| 869 | Context&: VMContext, Tag, Name, File: F, Line, Scope: getNonCompileUnitScope(N: Scope), BaseType: nullptr, |
| 870 | SizeInBits, AlignInBits, OffsetInBits: 0, Flags, Elements: nullptr, RuntimeLang, EnumKind, |
| 871 | VTableHolder: nullptr, TemplateParams: nullptr, Identifier: UniqueIdentifier, Discriminator: nullptr, DataLocation: nullptr, Associated: nullptr, |
| 872 | Allocated: nullptr, Rank: nullptr, Annotations) |
| 873 | .release(); |
| 874 | trackIfUnresolved(N: RetTy); |
| 875 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 876 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: RetTy); |
| 877 | return RetTy; |
| 878 | } |
| 879 | |
| 880 | DINodeArray DIBuilder::getOrCreateArray(ArrayRef<Metadata *> Elements) { |
| 881 | return MDTuple::get(Context&: VMContext, MDs: Elements); |
| 882 | } |
| 883 | |
| 884 | DIMacroNodeArray |
| 885 | DIBuilder::getOrCreateMacroArray(ArrayRef<Metadata *> Elements) { |
| 886 | return MDTuple::get(Context&: VMContext, MDs: Elements); |
| 887 | } |
| 888 | |
| 889 | DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) { |
| 890 | SmallVector<llvm::Metadata *, 16> Elts; |
| 891 | for (Metadata *E : Elements) { |
| 892 | if (isa_and_nonnull<MDNode>(Val: E)) |
| 893 | Elts.push_back(Elt: cast<DIType>(Val: E)); |
| 894 | else |
| 895 | Elts.push_back(Elt: E); |
| 896 | } |
| 897 | return DITypeArray(MDNode::get(Context&: VMContext, MDs: Elts)); |
| 898 | } |
| 899 | |
| 900 | DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { |
| 901 | auto *LB = ConstantAsMetadata::get( |
| 902 | C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: VMContext), V: Lo)); |
| 903 | auto *CountNode = ConstantAsMetadata::get( |
| 904 | C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: VMContext), V: Count)); |
| 905 | return DISubrange::get(Context&: VMContext, CountNode, LowerBound: LB, UpperBound: nullptr, Stride: nullptr); |
| 906 | } |
| 907 | |
| 908 | DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, Metadata *CountNode) { |
| 909 | auto *LB = ConstantAsMetadata::get( |
| 910 | C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: VMContext), V: Lo)); |
| 911 | return DISubrange::get(Context&: VMContext, CountNode, LowerBound: LB, UpperBound: nullptr, Stride: nullptr); |
| 912 | } |
| 913 | |
| 914 | DISubrange *DIBuilder::getOrCreateSubrange(Metadata *CountNode, Metadata *LB, |
| 915 | Metadata *UB, Metadata *Stride) { |
| 916 | return DISubrange::get(Context&: VMContext, CountNode, LowerBound: LB, UpperBound: UB, Stride); |
| 917 | } |
| 918 | |
| 919 | DIGenericSubrange *DIBuilder::getOrCreateGenericSubrange( |
| 920 | DIGenericSubrange::BoundType CountNode, DIGenericSubrange::BoundType LB, |
| 921 | DIGenericSubrange::BoundType UB, DIGenericSubrange::BoundType Stride) { |
| 922 | auto ConvToMetadata = [&](DIGenericSubrange::BoundType Bound) -> Metadata * { |
| 923 | return isa<DIExpression *>(Val: Bound) ? (Metadata *)cast<DIExpression *>(Val&: Bound) |
| 924 | : (Metadata *)cast<DIVariable *>(Val&: Bound); |
| 925 | }; |
| 926 | return DIGenericSubrange::get(Context&: VMContext, CountNode: ConvToMetadata(CountNode), |
| 927 | LowerBound: ConvToMetadata(LB), UpperBound: ConvToMetadata(UB), |
| 928 | Stride: ConvToMetadata(Stride)); |
| 929 | } |
| 930 | |
| 931 | DISubrangeType *DIBuilder::createSubrangeType( |
| 932 | StringRef Name, DIFile *File, unsigned LineNo, DIScope *Scope, |
| 933 | uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, |
| 934 | DIType *Ty, Metadata *LowerBound, Metadata *UpperBound, Metadata *Stride, |
| 935 | Metadata *Bias) { |
| 936 | auto *T = DISubrangeType::get(Context&: VMContext, Name, File, Line: LineNo, Scope, |
| 937 | SizeInBits, AlignInBits, Flags, BaseType: Ty, LowerBound, |
| 938 | UpperBound, Stride, Bias); |
| 939 | if (isa_and_nonnull<DILocalScope>(Val: Scope)) |
| 940 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: T); |
| 941 | return T; |
| 942 | } |
| 943 | |
| 944 | static void checkGlobalVariableScope(DIScope *Context) { |
| 945 | #ifndef NDEBUG |
| 946 | if (auto *CT = |
| 947 | dyn_cast_or_null<DICompositeType>(getNonCompileUnitScope(Context))) |
| 948 | assert(CT->getIdentifier().empty() && |
| 949 | "Context of a global variable should not be a type with identifier" ); |
| 950 | #endif |
| 951 | } |
| 952 | |
| 953 | DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression( |
| 954 | DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, |
| 955 | unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, bool isDefined, |
| 956 | DIExpression *Expr, MDNode *Decl, MDTuple *TemplateParams, |
| 957 | uint32_t AlignInBits, DINodeArray Annotations) { |
| 958 | checkGlobalVariableScope(Context); |
| 959 | |
| 960 | auto *GV = DIGlobalVariable::getDistinct( |
| 961 | Context&: VMContext, Scope: cast_or_null<DIScope>(Val: Context), Name, LinkageName, File: F, |
| 962 | Line: LineNumber, Type: Ty, IsLocalToUnit, IsDefinition: isDefined, |
| 963 | StaticDataMemberDeclaration: cast_or_null<DIDerivedType>(Val: Decl), TemplateParams, AlignInBits, |
| 964 | Annotations); |
| 965 | if (!Expr) |
| 966 | Expr = createExpression(); |
| 967 | auto *N = DIGlobalVariableExpression::get(Context&: VMContext, Variable: GV, Expression: Expr); |
| 968 | if (isa_and_nonnull<DILocalScope>(Val: Context)) |
| 969 | getSubprogramNodesTrackingVector(S: Context).emplace_back(Args&: N); |
| 970 | else |
| 971 | Globals.push_back(Elt: N); |
| 972 | return N; |
| 973 | } |
| 974 | |
| 975 | DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( |
| 976 | DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, |
| 977 | unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, MDNode *Decl, |
| 978 | MDTuple *TemplateParams, uint32_t AlignInBits) { |
| 979 | checkGlobalVariableScope(Context); |
| 980 | |
| 981 | return DIGlobalVariable::getTemporary( |
| 982 | Context&: VMContext, Scope: cast_or_null<DIScope>(Val: Context), Name, LinkageName, File: F, |
| 983 | Line: LineNumber, Type: Ty, IsLocalToUnit, IsDefinition: false, |
| 984 | StaticDataMemberDeclaration: cast_or_null<DIDerivedType>(Val: Decl), TemplateParams, AlignInBits, |
| 985 | Annotations: nullptr) |
| 986 | .release(); |
| 987 | } |
| 988 | |
| 989 | static DILocalVariable *createLocalVariable( |
| 990 | LLVMContext &VMContext, |
| 991 | SmallVectorImpl<TrackingMDNodeRef> &PreservedNodes, |
| 992 | DIScope *Context, StringRef Name, unsigned ArgNo, DIFile *File, |
| 993 | unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, |
| 994 | uint32_t AlignInBits, DINodeArray Annotations = nullptr) { |
| 995 | // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT |
| 996 | // the only valid scopes)? |
| 997 | auto *Scope = cast<DILocalScope>(Val: Context); |
| 998 | auto *Node = DILocalVariable::get(Context&: VMContext, Scope, Name, File, Line: LineNo, Type: Ty, |
| 999 | Arg: ArgNo, Flags, AlignInBits, Annotations); |
| 1000 | if (AlwaysPreserve) { |
| 1001 | // The optimizer may remove local variables. If there is an interest |
| 1002 | // to preserve variable info in such situation then stash it in a |
| 1003 | // named mdnode. |
| 1004 | PreservedNodes.emplace_back(Args&: Node); |
| 1005 | } |
| 1006 | return Node; |
| 1007 | } |
| 1008 | |
| 1009 | DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name, |
| 1010 | DIFile *File, unsigned LineNo, |
| 1011 | DIType *Ty, bool AlwaysPreserve, |
| 1012 | DINode::DIFlags Flags, |
| 1013 | uint32_t AlignInBits) { |
| 1014 | assert(Scope && isa<DILocalScope>(Scope) && |
| 1015 | "Unexpected scope for a local variable." ); |
| 1016 | return createLocalVariable( |
| 1017 | VMContext, PreservedNodes&: getSubprogramNodesTrackingVector(S: Scope), Context: Scope, Name, |
| 1018 | /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, Flags, AlignInBits); |
| 1019 | } |
| 1020 | |
| 1021 | DILocalVariable *DIBuilder::createParameterVariable( |
| 1022 | DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, |
| 1023 | unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, |
| 1024 | DINodeArray Annotations) { |
| 1025 | assert(ArgNo && "Expected non-zero argument number for parameter" ); |
| 1026 | assert(Scope && isa<DILocalScope>(Scope) && |
| 1027 | "Unexpected scope for a local variable." ); |
| 1028 | return createLocalVariable( |
| 1029 | VMContext, PreservedNodes&: getSubprogramNodesTrackingVector(S: Scope), Context: Scope, Name, ArgNo, |
| 1030 | File, LineNo, Ty, AlwaysPreserve, Flags, /*AlignInBits=*/0, Annotations); |
| 1031 | } |
| 1032 | |
| 1033 | DILabel *DIBuilder::createLabel(DIScope *Context, StringRef Name, DIFile *File, |
| 1034 | unsigned LineNo, unsigned Column, |
| 1035 | bool IsArtificial, |
| 1036 | std::optional<unsigned> CoroSuspendIdx, |
| 1037 | bool AlwaysPreserve) { |
| 1038 | auto *Scope = cast<DILocalScope>(Val: Context); |
| 1039 | auto *Node = DILabel::get(Context&: VMContext, Scope, Name, File, Line: LineNo, Column, |
| 1040 | IsArtificial, CoroSuspendIdx); |
| 1041 | |
| 1042 | if (AlwaysPreserve) { |
| 1043 | /// The optimizer may remove labels. If there is an interest |
| 1044 | /// to preserve label info in such situation then append it to |
| 1045 | /// the list of retained nodes of the DISubprogram. |
| 1046 | getSubprogramNodesTrackingVector(S: Scope).emplace_back(Args&: Node); |
| 1047 | } |
| 1048 | return Node; |
| 1049 | } |
| 1050 | |
| 1051 | DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) { |
| 1052 | return DIExpression::get(Context&: VMContext, Elements: Addr); |
| 1053 | } |
| 1054 | |
| 1055 | template <class... Ts> |
| 1056 | static DISubprogram *getSubprogram(bool IsDistinct, Ts &&...Args) { |
| 1057 | if (IsDistinct) |
| 1058 | return DISubprogram::getDistinct(std::forward<Ts>(Args)...); |
| 1059 | return DISubprogram::get(std::forward<Ts>(Args)...); |
| 1060 | } |
| 1061 | |
| 1062 | DISubprogram *DIBuilder::createFunction( |
| 1063 | DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, |
| 1064 | unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, |
| 1065 | DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, |
| 1066 | DITemplateParameterArray TParams, DISubprogram *Decl, |
| 1067 | DITypeArray ThrownTypes, DINodeArray Annotations, StringRef TargetFuncName, |
| 1068 | bool UseKeyInstructions) { |
| 1069 | bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; |
| 1070 | auto *Node = getSubprogram( |
| 1071 | /*IsDistinct=*/IsDefinition, Args&: VMContext, Args: getNonCompileUnitScope(N: Context), |
| 1072 | Args&: Name, Args&: LinkageName, Args&: File, Args&: LineNo, Args&: Ty, Args&: ScopeLine, Args: nullptr, Args: 0, Args: 0, Args&: Flags, |
| 1073 | Args&: SPFlags, Args: IsDefinition ? CUNode : nullptr, Args&: TParams, Args&: Decl, Args: nullptr, |
| 1074 | Args&: ThrownTypes, Args&: Annotations, Args&: TargetFuncName, Args&: UseKeyInstructions); |
| 1075 | |
| 1076 | AllSubprograms.push_back(Elt: Node); |
| 1077 | trackIfUnresolved(N: Node); |
| 1078 | return Node; |
| 1079 | } |
| 1080 | |
| 1081 | DISubprogram *DIBuilder::createTempFunctionFwdDecl( |
| 1082 | DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, |
| 1083 | unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, |
| 1084 | DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, |
| 1085 | DITemplateParameterArray TParams, DISubprogram *Decl, |
| 1086 | DITypeArray ThrownTypes) { |
| 1087 | bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; |
| 1088 | return DISubprogram::getTemporary(Context&: VMContext, Scope: getNonCompileUnitScope(N: Context), |
| 1089 | Name, LinkageName, File, Line: LineNo, Type: Ty, |
| 1090 | ScopeLine, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags, SPFlags, |
| 1091 | Unit: IsDefinition ? CUNode : nullptr, TemplateParams: TParams, |
| 1092 | Declaration: Decl, RetainedNodes: nullptr, ThrownTypes) |
| 1093 | .release(); |
| 1094 | } |
| 1095 | |
| 1096 | DISubprogram *DIBuilder::createMethod( |
| 1097 | DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, |
| 1098 | unsigned LineNo, DISubroutineType *Ty, unsigned VIndex, int ThisAdjustment, |
| 1099 | DIType *VTableHolder, DINode::DIFlags Flags, |
| 1100 | DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, |
| 1101 | DITypeArray ThrownTypes, bool UseKeyInstructions) { |
| 1102 | assert(getNonCompileUnitScope(Context) && |
| 1103 | "Methods should have both a Context and a context that isn't " |
| 1104 | "the compile unit." ); |
| 1105 | // FIXME: Do we want to use different scope/lines? |
| 1106 | bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; |
| 1107 | auto *SP = getSubprogram( |
| 1108 | /*IsDistinct=*/IsDefinition, Args&: VMContext, Args: cast<DIScope>(Val: Context), Args&: Name, |
| 1109 | Args&: LinkageName, Args&: F, Args&: LineNo, Args&: Ty, Args&: LineNo, Args&: VTableHolder, Args&: VIndex, Args&: ThisAdjustment, |
| 1110 | Args&: Flags, Args&: SPFlags, Args: IsDefinition ? CUNode : nullptr, Args&: TParams, Args: nullptr, |
| 1111 | Args: nullptr, Args&: ThrownTypes, Args: nullptr, Args: "" , Args: IsDefinition && UseKeyInstructions); |
| 1112 | |
| 1113 | AllSubprograms.push_back(Elt: SP); |
| 1114 | trackIfUnresolved(N: SP); |
| 1115 | return SP; |
| 1116 | } |
| 1117 | |
| 1118 | DICommonBlock *DIBuilder::createCommonBlock(DIScope *Scope, |
| 1119 | DIGlobalVariable *Decl, |
| 1120 | StringRef Name, DIFile *File, |
| 1121 | unsigned LineNo) { |
| 1122 | return DICommonBlock::get(Context&: VMContext, Scope, Decl, Name, File, LineNo); |
| 1123 | } |
| 1124 | |
| 1125 | DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name, |
| 1126 | bool ExportSymbols) { |
| 1127 | |
| 1128 | // It is okay to *not* make anonymous top-level namespaces distinct, because |
| 1129 | // all nodes that have an anonymous namespace as their parent scope are |
| 1130 | // guaranteed to be unique and/or are linked to their containing |
| 1131 | // DICompileUnit. This decision is an explicit tradeoff of link time versus |
| 1132 | // memory usage versus code simplicity and may get revisited in the future. |
| 1133 | return DINamespace::get(Context&: VMContext, Scope: getNonCompileUnitScope(N: Scope), Name, |
| 1134 | ExportSymbols); |
| 1135 | } |
| 1136 | |
| 1137 | DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name, |
| 1138 | StringRef ConfigurationMacros, |
| 1139 | StringRef IncludePath, StringRef APINotesFile, |
| 1140 | DIFile *File, unsigned LineNo, bool IsDecl) { |
| 1141 | return DIModule::get(Context&: VMContext, File, Scope: getNonCompileUnitScope(N: Scope), Name, |
| 1142 | ConfigurationMacros, IncludePath, APINotesFile, LineNo, |
| 1143 | IsDecl); |
| 1144 | } |
| 1145 | |
| 1146 | DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope, |
| 1147 | DIFile *File, |
| 1148 | unsigned Discriminator) { |
| 1149 | return DILexicalBlockFile::get(Context&: VMContext, Scope, File, Discriminator); |
| 1150 | } |
| 1151 | |
| 1152 | DILexicalBlock *DIBuilder::createLexicalBlock(DIScope *Scope, DIFile *File, |
| 1153 | unsigned Line, unsigned Col) { |
| 1154 | // Make these distinct, to avoid merging two lexical blocks on the same |
| 1155 | // file/line/column. |
| 1156 | return DILexicalBlock::getDistinct(Context&: VMContext, Scope: getNonCompileUnitScope(N: Scope), |
| 1157 | File, Line, Column: Col); |
| 1158 | } |
| 1159 | |
| 1160 | DbgRecord *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, |
| 1161 | DIExpression *Expr, const DILocation *DL, |
| 1162 | BasicBlock *InsertAtEnd) { |
| 1163 | // If this block already has a terminator then insert this record before |
| 1164 | // the terminator. Otherwise, put it at the end of the block. |
| 1165 | Instruction *InsertBefore = InsertAtEnd->getTerminatorOrNull(); |
| 1166 | return insertDeclare(Storage, VarInfo, Expr, DL, |
| 1167 | InsertPt: InsertBefore ? InsertBefore->getIterator() |
| 1168 | : InsertAtEnd->end()); |
| 1169 | } |
| 1170 | |
| 1171 | DbgRecord *DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val, |
| 1172 | DILocalVariable *SrcVar, |
| 1173 | DIExpression *ValExpr, Value *Addr, |
| 1174 | DIExpression *AddrExpr, |
| 1175 | const DILocation *DL) { |
| 1176 | auto *Link = cast_or_null<DIAssignID>( |
| 1177 | Val: LinkedInstr->getMetadata(KindID: LLVMContext::MD_DIAssignID)); |
| 1178 | assert(Link && "Linked instruction must have DIAssign metadata attached" ); |
| 1179 | |
| 1180 | DbgVariableRecord *DVR = DbgVariableRecord::createDVRAssign( |
| 1181 | Val, Variable: SrcVar, Expression: ValExpr, AssignID: Link, Address: Addr, AddressExpression: AddrExpr, DI: DL); |
| 1182 | // Insert after LinkedInstr. |
| 1183 | BasicBlock::iterator NextIt = std::next(x: LinkedInstr->getIterator()); |
| 1184 | NextIt.setHeadBit(true); |
| 1185 | insertDbgVariableRecord(DVR, InsertPt: NextIt); |
| 1186 | return DVR; |
| 1187 | } |
| 1188 | |
| 1189 | DbgRecord *DIBuilder::insertDbgValue(Value *Val, DILocalVariable *VarInfo, |
| 1190 | DIExpression *Expr, const DILocation *DL, |
| 1191 | InsertPosition InsertPt) { |
| 1192 | DbgVariableRecord *DVR = |
| 1193 | DbgVariableRecord::createDbgVariableRecord(Location: Val, DV: VarInfo, Expr, DI: DL); |
| 1194 | insertDbgVariableRecord(DVR, InsertPt); |
| 1195 | return DVR; |
| 1196 | } |
| 1197 | |
| 1198 | DbgRecord *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, |
| 1199 | DIExpression *Expr, const DILocation *DL, |
| 1200 | InsertPosition InsertPt) { |
| 1201 | assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare" ); |
| 1202 | assert(DL && "Expected debug loc" ); |
| 1203 | assert(DL->getScope()->getSubprogram() == |
| 1204 | VarInfo->getScope()->getSubprogram() && |
| 1205 | "Expected matching subprograms" ); |
| 1206 | |
| 1207 | DbgVariableRecord *DVR = |
| 1208 | DbgVariableRecord::createDVRDeclare(Address: Storage, DV: VarInfo, Expr, DI: DL); |
| 1209 | insertDbgVariableRecord(DVR, InsertPt); |
| 1210 | return DVR; |
| 1211 | } |
| 1212 | |
| 1213 | DbgRecord *DIBuilder::insertDeclareValue(Value *Storage, |
| 1214 | DILocalVariable *VarInfo, |
| 1215 | DIExpression *Expr, |
| 1216 | const DILocation *DL, |
| 1217 | InsertPosition InsertPt) { |
| 1218 | assert(VarInfo && |
| 1219 | "empty or invalid DILocalVariable* passed to dbg.declare_value" ); |
| 1220 | assert(DL && "Expected debug loc" ); |
| 1221 | assert(DL->getScope()->getSubprogram() == |
| 1222 | VarInfo->getScope()->getSubprogram() && |
| 1223 | "Expected matching subprograms" ); |
| 1224 | |
| 1225 | DbgVariableRecord *DVR = |
| 1226 | DbgVariableRecord::createDVRDeclareValue(Address: Storage, DV: VarInfo, Expr, DI: DL); |
| 1227 | insertDbgVariableRecord(DVR, InsertPt); |
| 1228 | return DVR; |
| 1229 | } |
| 1230 | |
| 1231 | void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR, |
| 1232 | InsertPosition InsertPt) { |
| 1233 | assert(InsertPt.isValid()); |
| 1234 | trackIfUnresolved(N: DVR->getVariable()); |
| 1235 | trackIfUnresolved(N: DVR->getExpression()); |
| 1236 | if (DVR->isDbgAssign()) |
| 1237 | trackIfUnresolved(N: DVR->getAddressExpression()); |
| 1238 | |
| 1239 | auto *BB = InsertPt.getBasicBlock(); |
| 1240 | BB->insertDbgRecordBefore(DR: DVR, Here: InsertPt); |
| 1241 | } |
| 1242 | |
| 1243 | DbgRecord *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, |
| 1244 | InsertPosition InsertPt) { |
| 1245 | assert(LabelInfo && "empty or invalid DILabel* passed to dbg.label" ); |
| 1246 | assert(DL && "Expected debug loc" ); |
| 1247 | assert(DL->getScope()->getSubprogram() == |
| 1248 | LabelInfo->getScope()->getSubprogram() && |
| 1249 | "Expected matching subprograms" ); |
| 1250 | |
| 1251 | trackIfUnresolved(N: LabelInfo); |
| 1252 | DbgLabelRecord *DLR = new DbgLabelRecord(LabelInfo, DL); |
| 1253 | if (InsertPt.isValid()) { |
| 1254 | auto *BB = InsertPt.getBasicBlock(); |
| 1255 | BB->insertDbgRecordBefore(DR: DLR, Here: InsertPt); |
| 1256 | } |
| 1257 | return DLR; |
| 1258 | } |
| 1259 | |
| 1260 | void DIBuilder::replaceVTableHolder(DICompositeType *&T, DIType *VTableHolder) { |
| 1261 | { |
| 1262 | TypedTrackingMDRef<DICompositeType> N(T); |
| 1263 | N->replaceVTableHolder(VTableHolder); |
| 1264 | T = N.get(); |
| 1265 | } |
| 1266 | |
| 1267 | // If this didn't create a self-reference, just return. |
| 1268 | if (T != VTableHolder) |
| 1269 | return; |
| 1270 | |
| 1271 | // Look for unresolved operands. T will drop RAUW support, orphaning any |
| 1272 | // cycles underneath it. |
| 1273 | if (T->isResolved()) |
| 1274 | for (const MDOperand &O : T->operands()) |
| 1275 | if (auto *N = dyn_cast_or_null<MDNode>(Val: O)) |
| 1276 | trackIfUnresolved(N); |
| 1277 | } |
| 1278 | |
| 1279 | void DIBuilder::replaceArrays(DICompositeType *&T, DINodeArray Elements, |
| 1280 | DINodeArray TParams) { |
| 1281 | { |
| 1282 | TypedTrackingMDRef<DICompositeType> N(T); |
| 1283 | if (Elements) |
| 1284 | N->replaceElements(Elements); |
| 1285 | if (TParams) |
| 1286 | N->replaceTemplateParams(TemplateParams: DITemplateParameterArray(TParams)); |
| 1287 | T = N.get(); |
| 1288 | } |
| 1289 | |
| 1290 | // If T isn't resolved, there's no problem. |
| 1291 | if (!T->isResolved()) |
| 1292 | return; |
| 1293 | |
| 1294 | // If T is resolved, it may be due to a self-reference cycle. Track the |
| 1295 | // arrays explicitly if they're unresolved, or else the cycles will be |
| 1296 | // orphaned. |
| 1297 | if (Elements) |
| 1298 | trackIfUnresolved(N: Elements.get()); |
| 1299 | if (TParams) |
| 1300 | trackIfUnresolved(N: TParams.get()); |
| 1301 | } |
| 1302 | |