}
DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
- : M(m), VMContext(M.getContext()), TempEnumTypes(nullptr),
- TempRetainTypes(nullptr), TempSubprograms(nullptr), TempGVs(nullptr),
+ : M(m), VMContext(M.getContext()), CUNode(nullptr),
DeclareFn(nullptr), ValueFn(nullptr),
AllowUnresolvedNodes(AllowUnresolvedNodes) {}
}
void DIBuilder::finalize() {
- TempEnumTypes->replaceAllUsesWith(MDTuple::get(VMContext, AllEnumTypes));
+ if (!CUNode) {
+ assert(!AllowUnresolvedNodes &&
+ "creating type nodes without a CU is not supported");
+ return;
+ }
+
+ CUNode->replaceEnumTypes(MDTuple::get(VMContext, AllEnumTypes));
SmallVector<Metadata *, 16> RetainValues;
// Declarations and definitions of the same type may be retained. Some
for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++)
if (RetainSet.insert(AllRetainTypes[I]).second)
RetainValues.push_back(AllRetainTypes[I]);
- TempRetainTypes->replaceAllUsesWith(MDTuple::get(VMContext, RetainValues));
+
+ if (!RetainValues.empty())
+ CUNode->replaceRetainedTypes(MDTuple::get(VMContext, RetainValues));
DISubprogramArray SPs = MDTuple::get(VMContext, AllSubprograms);
- TempSubprograms->replaceAllUsesWith(SPs.get());
+ if (!AllSubprograms.empty())
+ CUNode->replaceSubprograms(SPs.get());
+
for (auto *SP : SPs) {
if (MDTuple *Temp = SP->getVariables().get()) {
const auto &PV = PreservedVariables.lookup(SP);
}
}
- TempGVs->replaceAllUsesWith(MDTuple::get(VMContext, AllGVs));
+ if (!AllGVs.empty())
+ CUNode->replaceGlobalVariables(MDTuple::get(VMContext, AllGVs));
- TempImportedModules->replaceAllUsesWith(MDTuple::get(
- VMContext, SmallVector<Metadata *, 16>(AllImportedModules.begin(),
- AllImportedModules.end())));
+ if (!AllImportedModules.empty())
+ CUNode->replaceImportedEntities(MDTuple::get(
+ VMContext, SmallVector<Metadata *, 16>(AllImportedModules.begin(),
+ AllImportedModules.end())));
// Now that all temp nodes have been replaced or deleted, resolve remaining
// cycles.
assert(!Filename.empty() &&
"Unable to create compile unit without filename");
- // TODO: Once we make DICompileUnit distinct, stop using temporaries here
- // (just start with operands assigned to nullptr).
- TempEnumTypes = MDTuple::getTemporary(VMContext, None);
- TempRetainTypes = MDTuple::getTemporary(VMContext, None);
- TempSubprograms = MDTuple::getTemporary(VMContext, None);
- TempGVs = MDTuple::getTemporary(VMContext, None);
- TempImportedModules = MDTuple::getTemporary(VMContext, None);
-
- // TODO: Switch to getDistinct(). We never want to merge compile units based
- // on contents.
- DICompileUnit *CUNode = DICompileUnit::get(
+ assert(!CUNode && "Can only make one compile unit per DIBuilder instance");
+ CUNode = DICompileUnit::getDistinct(
VMContext, Lang, DIFile::get(VMContext, Filename, Directory), Producer,
- isOptimized, Flags, RunTimeVer, SplitName, Kind, TempEnumTypes.get(),
- TempRetainTypes.get(), TempSubprograms.get(), TempGVs.get(),
- TempImportedModules.get(), DWOId);
+ isOptimized, Flags, RunTimeVer, SplitName, Kind, nullptr,
+ nullptr, nullptr, nullptr, nullptr, DWOId);
// Create a named metadata so that it is easier to find cu in a module.
// Note that we only generate this when the caller wants to actually
Context, NS, Line, StringRef(), AllImportedModules);
}
+DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M,
+ unsigned Line) {
+ return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module,
+ Context, M, Line, StringRef(), AllImportedModules);
+}
+
DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
DINode *Decl,
unsigned Line,
return R;
}
-DISubroutineType *DIBuilder::createSubroutineType(DIFile *File,
- DITypeRefArray ParameterTypes,
+DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
unsigned Flags) {
return DISubroutineType::get(VMContext, Flags, ParameterTypes);
}
+DICompositeType *DIBuilder::createExternalTypeRef(unsigned Tag, DIFile *File,
+ StringRef UniqueIdentifier) {
+ assert(!UniqueIdentifier.empty() && "external type ref without uid");
+ auto *CTy =
+ DICompositeType::get(VMContext, Tag, "", nullptr, 0, nullptr, nullptr, 0,
+ 0, 0, DINode::FlagExternalTypeRef, nullptr, 0,
+ nullptr, nullptr, UniqueIdentifier);
+ // Types with unique IDs need to be in the type map.
+ retainType(CTy);
+ return CTy;
+}
+
DICompositeType *DIBuilder::createEnumerationType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements,
.release();
}
-DILocalVariable *DIBuilder::createLocalVariable(
- unsigned Tag, DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo,
- DIType *Ty, bool AlwaysPreserve, unsigned Flags, unsigned ArgNo) {
+static DILocalVariable *createLocalVariable(
+ LLVMContext &VMContext,
+ DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> &PreservedVariables,
+ DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File,
+ unsigned LineNo, DIType *Ty, bool AlwaysPreserve, unsigned Flags) {
// FIXME: Why getNonCompileUnitScope()?
// FIXME: Why is "!Context" okay here?
- // FIXME: WHy doesn't this check for a subprogram or lexical block (AFAICT
+ // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT
// the only valid scopes)?
DIScope *Context = getNonCompileUnitScope(Scope);
- auto *Node = DILocalVariable::get(
- VMContext, Tag, cast_or_null<DILocalScope>(Context), Name, File, LineNo,
- DITypeRef::get(Ty), ArgNo, Flags);
+ auto *Node =
+ DILocalVariable::get(VMContext, cast_or_null<DILocalScope>(Context), Name,
+ File, LineNo, DITypeRef::get(Ty), ArgNo, Flags);
if (AlwaysPreserve) {
- // The optimizer may remove local variable. If there is an interest
+ // The optimizer may remove local variables. If there is an interest
// to preserve variable info in such situation then stash it in a
// named mdnode.
DISubprogram *Fn = getDISubprogram(Scope);
return Node;
}
+DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNo,
+ DIType *Ty, bool AlwaysPreserve,
+ unsigned Flags) {
+ return createLocalVariable(VMContext, PreservedVariables, Scope, Name,
+ /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve,
+ Flags);
+}
+
+DILocalVariable *DIBuilder::createParameterVariable(
+ DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File,
+ unsigned LineNo, DIType *Ty, bool AlwaysPreserve, unsigned Flags) {
+ assert(ArgNo && "Expected non-zero argument number for parameter");
+ return createLocalVariable(VMContext, PreservedVariables, Scope, Name, ArgNo,
+ File, LineNo, Ty, AlwaysPreserve, Flags);
+}
+
DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) {
return DIExpression::get(VMContext, Addr);
}
Flags, isOptimized, Fn, TParams, Decl);
}
+template <class... Ts>
+static DISubprogram *getSubprogram(bool IsDistinct, Ts &&... Args) {
+ if (IsDistinct)
+ return DISubprogram::getDistinct(std::forward<Ts>(Args)...);
+ return DISubprogram::get(std::forward<Ts>(Args)...);
+}
+
DISubprogram *DIBuilder::createFunction(DIScope *Context, StringRef Name,
StringRef LinkageName, DIFile *File,
unsigned LineNo, DISubroutineType *Ty,
unsigned ScopeLine, unsigned Flags,
bool isOptimized, Function *Fn,
MDNode *TParams, MDNode *Decl) {
- assert(Ty->getTag() == dwarf::DW_TAG_subroutine_type &&
- "function types should be subroutines");
- auto *Node = DISubprogram::get(
- VMContext, DIScopeRef::get(getNonCompileUnitScope(Context)), Name,
- LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
- nullptr, 0, 0, Flags, isOptimized, Fn, cast_or_null<MDTuple>(TParams),
- cast_or_null<DISubprogram>(Decl),
- MDTuple::getTemporary(VMContext, None).release());
+ auto *Node = getSubprogram(/* IsDistinct = */ isDefinition, VMContext,
+ DIScopeRef::get(getNonCompileUnitScope(Context)),
+ Name, LinkageName, File, LineNo, Ty, isLocalToUnit,
+ isDefinition, ScopeLine, nullptr, 0, 0, Flags,
+ isOptimized, Fn, cast_or_null<MDTuple>(TParams),
+ cast_or_null<DISubprogram>(Decl),
+ MDTuple::getTemporary(VMContext, None).release());
if (isDefinition)
AllSubprograms.push_back(Node);
bool isLocalToUnit, bool isDefinition, unsigned VK,
unsigned VIndex, DIType *VTableHolder, unsigned Flags,
bool isOptimized, Function *Fn, MDNode *TParam) {
- assert(Ty->getTag() == dwarf::DW_TAG_subroutine_type &&
- "function types should be subroutines");
assert(getNonCompileUnitScope(Context) &&
"Methods should have both a Context and a context that isn't "
"the compile unit.");
// FIXME: Do we want to use different scope/lines?
- auto *SP = DISubprogram::get(
- VMContext, DIScopeRef::get(cast<DIScope>(Context)), Name, LinkageName, F,
- LineNo, Ty, isLocalToUnit, isDefinition, LineNo,
- DITypeRef::get(VTableHolder), VK, VIndex, Flags, isOptimized, Fn,
- cast_or_null<MDTuple>(TParam), nullptr, nullptr);
+ auto *SP = getSubprogram(/* IsDistinct = */ isDefinition, VMContext,
+ DIScopeRef::get(cast<DIScope>(Context)), Name,
+ LinkageName, F, LineNo, Ty, isLocalToUnit,
+ isDefinition, LineNo, DITypeRef::get(VTableHolder),
+ VK, VIndex, Flags, isOptimized, Fn,
+ cast_or_null<MDTuple>(TParam), nullptr, nullptr);
if (isDefinition)
AllSubprograms.push_back(SP);
LineNo);
}
+DIModule *DIBuilder::createModule(DIScope *Scope, StringRef Name,
+ StringRef ConfigurationMacros,
+ StringRef IncludePath,
+ StringRef ISysRoot) {
+ return DIModule::get(VMContext, getNonCompileUnitScope(Scope), Name,
+ ConfigurationMacros, IncludePath, ISysRoot);
+}
+
DILexicalBlockFile *DIBuilder::createLexicalBlockFile(DIScope *Scope,
DIFile *File,
unsigned Discriminator) {
if (!T->isResolved())
return;
- // If "T" is resolved, it may be due to a self-reference cycle. Track the
+ // If T is resolved, it may be due to a self-reference cycle. Track the
// arrays explicitly if they're unresolved, or else the cycles will be
// orphaned.
if (Elements)