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