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