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 | |