forked from OSchip/llvm-project
[DebugInfo] Added DI macro creation API to DIBuilder.
Differential Revision: https://reviews.llvm.org/D16077 llvm-svn: 291769
This commit is contained in:
parent
ae03595bfb
commit
9607571861
|
@ -17,7 +17,9 @@
|
|||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
|
@ -51,6 +53,10 @@ namespace llvm {
|
|||
SmallVector<Metadata *, 4> AllSubprograms;
|
||||
SmallVector<Metadata *, 4> AllGVs;
|
||||
SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
|
||||
/// Map Macro parent (which can be DIMacroFile or nullptr) to a list of
|
||||
/// Metadata all of type DIMacroNode.
|
||||
/// DIMacroNode's with nullptr parent are DICompileUnit direct children.
|
||||
MapVector<MDNode *, SetVector<Metadata *>> AllMacrosPerParent;
|
||||
|
||||
/// Track nodes that may be unresolved.
|
||||
SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
|
||||
|
@ -116,6 +122,24 @@ namespace llvm {
|
|||
DIFile::ChecksumKind CSKind = DIFile::CSK_None,
|
||||
StringRef Checksum = StringRef());
|
||||
|
||||
/// Create debugging information entry for a macro.
|
||||
/// \param Parent Macro parent (could be nullptr).
|
||||
/// \param Line Source line number where the macro is defined.
|
||||
/// \param MacroType DW_MACINFO_define or DW_MACINFO_undef.
|
||||
/// \param Name Macro name.
|
||||
/// \param Value Macro value.
|
||||
DIMacro *createMacro(DIMacroFile *Parent, unsigned Line, unsigned MacroType,
|
||||
StringRef Name, StringRef Value = StringRef());
|
||||
|
||||
/// Create debugging information temporary entry for a macro file.
|
||||
/// List of macro node direct children will be calculated by DIBuilder,
|
||||
/// using the \p Parent relationship.
|
||||
/// \param Parent Macro file parent (could be nullptr).
|
||||
/// \param Line Source line number where the macro file is included.
|
||||
/// \param File File descriptor containing the name of the macro file.
|
||||
DIMacroFile *createTempMacroFile(DIMacroFile *Parent, unsigned Line,
|
||||
DIFile *File);
|
||||
|
||||
/// Create a single enumerator value.
|
||||
DIEnumerator *createEnumerator(StringRef Name, int64_t Val);
|
||||
|
||||
|
@ -447,6 +471,9 @@ namespace llvm {
|
|||
/// Get a DINodeArray, create one if required.
|
||||
DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements);
|
||||
|
||||
/// Get a DIMacroNodeArray, create one if required.
|
||||
DIMacroNodeArray getOrCreateMacroArray(ArrayRef<Metadata *> Elements);
|
||||
|
||||
/// Get a DITypeRefArray, create one if required.
|
||||
DITypeRefArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements);
|
||||
|
||||
|
|
|
@ -90,6 +90,20 @@ void DIBuilder::finalize() {
|
|||
VMContext, SmallVector<Metadata *, 16>(AllImportedModules.begin(),
|
||||
AllImportedModules.end())));
|
||||
|
||||
for (const auto &I : AllMacrosPerParent) {
|
||||
// DIMacroNode's with nullptr parent are DICompileUnit direct children.
|
||||
if (!I.first) {
|
||||
CUNode->replaceMacros(MDTuple::get(VMContext, I.second.getArrayRef()));
|
||||
continue;
|
||||
}
|
||||
// Otherwise, it must be a temporary DIMacroFile that need to be resolved.
|
||||
auto *TMF = cast<DIMacroFile>(I.first);
|
||||
auto *MF = DIMacroFile::get(VMContext, dwarf::DW_MACINFO_start_file,
|
||||
TMF->getLine(), TMF->getFile(),
|
||||
getOrCreateMacroArray(I.second.getArrayRef()));
|
||||
replaceTemporary(llvm::TempDIMacroNode(TMF), MF);
|
||||
}
|
||||
|
||||
// Now that all temp nodes have been replaced or deleted, resolve remaining
|
||||
// cycles.
|
||||
for (const auto &N : UnresolvedNodes)
|
||||
|
@ -179,6 +193,31 @@ DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,
|
|||
return DIFile::get(VMContext, Filename, Directory, CSKind, Checksum);
|
||||
}
|
||||
|
||||
DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber,
|
||||
unsigned MacroType, StringRef Name,
|
||||
StringRef Value) {
|
||||
assert(!Name.empty() && "Unable to create macro without name");
|
||||
assert((MacroType == dwarf::DW_MACINFO_undef ||
|
||||
MacroType == dwarf::DW_MACINFO_define) &&
|
||||
"Unexpected macro type");
|
||||
auto *M = DIMacro::get(VMContext, MacroType, LineNumber, Name, Value);
|
||||
AllMacrosPerParent[Parent].insert(M);
|
||||
return M;
|
||||
}
|
||||
|
||||
DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent,
|
||||
unsigned LineNumber, DIFile *File) {
|
||||
auto *MF = DIMacroFile::getTemporary(VMContext, dwarf::DW_MACINFO_start_file,
|
||||
LineNumber, File, DIMacroNodeArray())
|
||||
.release();
|
||||
AllMacrosPerParent[Parent].insert(MF);
|
||||
// Add the new temporary DIMacroFile to the macro per parent map as a parent.
|
||||
// This is needed to assure DIMacroFile with no children to have an entry in
|
||||
// the map. Otherwise, it will not be resolved in DIBuilder::finalize().
|
||||
AllMacrosPerParent.insert({MF, {}});
|
||||
return MF;
|
||||
}
|
||||
|
||||
DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) {
|
||||
assert(!Name.empty() && "Unable to create enumerator without name");
|
||||
return DIEnumerator::get(VMContext, Val, Name);
|
||||
|
@ -509,6 +548,11 @@ DINodeArray DIBuilder::getOrCreateArray(ArrayRef<Metadata *> Elements) {
|
|||
return MDTuple::get(VMContext, Elements);
|
||||
}
|
||||
|
||||
DIMacroNodeArray
|
||||
DIBuilder::getOrCreateMacroArray(ArrayRef<Metadata *> Elements) {
|
||||
return MDTuple::get(VMContext, Elements);
|
||||
}
|
||||
|
||||
DITypeRefArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) {
|
||||
SmallVector<llvm::Metadata *, 16> Elts;
|
||||
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
|
||||
|
|
|
@ -435,4 +435,73 @@ TEST_F(IRBuilderTest, DIImportedEntity) {
|
|||
EXPECT_TRUE(verifyModule(*M));
|
||||
EXPECT_TRUE(CU->getImportedEntities().size() == 2);
|
||||
}
|
||||
|
||||
// 0: #define M0 V0 <-- command line definition
|
||||
// 0: main.c <-- main file
|
||||
// 3: #define M1 V1 <-- M1 definition in main.c
|
||||
// 5: #include "file.h" <-- inclusion of file.h from main.c
|
||||
// 1: #define M2 <-- M2 definition in file.h with no value
|
||||
// 7: #undef M1 V1 <-- M1 un-definition in main.c
|
||||
TEST_F(IRBuilderTest, DIBuilderMacro) {
|
||||
IRBuilder<> Builder(BB);
|
||||
DIBuilder DIB(*M);
|
||||
auto File1 = DIB.createFile("main.c", "/");
|
||||
auto File2 = DIB.createFile("file.h", "/");
|
||||
auto CU = DIB.createCompileUnit(
|
||||
dwarf::DW_LANG_C, DIB.createFile("main.c", "/"), "llvm-c", true, "", 0);
|
||||
auto MDef0 =
|
||||
DIB.createMacro(nullptr, 0, dwarf::DW_MACINFO_define, "M0", "V0");
|
||||
auto TMF1 = DIB.createTempMacroFile(nullptr, 0, File1);
|
||||
auto MDef1 = DIB.createMacro(TMF1, 3, dwarf::DW_MACINFO_define, "M1", "V1");
|
||||
auto TMF2 = DIB.createTempMacroFile(TMF1, 5, File2);
|
||||
auto MDef2 = DIB.createMacro(TMF2, 1, dwarf::DW_MACINFO_define, "M2");
|
||||
auto MUndef1 = DIB.createMacro(TMF1, 7, dwarf::DW_MACINFO_undef, "M1");
|
||||
|
||||
EXPECT_EQ(dwarf::DW_MACINFO_define, MDef1->getMacinfoType());
|
||||
EXPECT_EQ(3, MDef1->getLine());
|
||||
EXPECT_EQ("M1", MDef1->getName());
|
||||
EXPECT_EQ("V1", MDef1->getValue());
|
||||
|
||||
EXPECT_EQ(dwarf::DW_MACINFO_undef, MUndef1->getMacinfoType());
|
||||
EXPECT_EQ(7, MUndef1->getLine());
|
||||
EXPECT_EQ("M1", MUndef1->getName());
|
||||
EXPECT_EQ("", MUndef1->getValue());
|
||||
|
||||
EXPECT_EQ(dwarf::DW_MACINFO_start_file, TMF2->getMacinfoType());
|
||||
EXPECT_EQ(5, TMF2->getLine());
|
||||
EXPECT_EQ(File2, TMF2->getFile());
|
||||
|
||||
DIB.finalize();
|
||||
|
||||
SmallVector<Metadata *, 4> Elements;
|
||||
Elements.push_back(MDef2);
|
||||
auto MF2 = DIMacroFile::get(Ctx, dwarf::DW_MACINFO_start_file, 5, File2,
|
||||
DIB.getOrCreateMacroArray(Elements));
|
||||
|
||||
Elements.clear();
|
||||
Elements.push_back(MDef1);
|
||||
Elements.push_back(MF2);
|
||||
Elements.push_back(MUndef1);
|
||||
auto MF1 = DIMacroFile::get(Ctx, dwarf::DW_MACINFO_start_file, 0, File1,
|
||||
DIB.getOrCreateMacroArray(Elements));
|
||||
|
||||
Elements.clear();
|
||||
Elements.push_back(MDef0);
|
||||
Elements.push_back(MF1);
|
||||
auto MN0 = MDTuple::get(Ctx, Elements);
|
||||
EXPECT_EQ(MN0, CU->getRawMacros());
|
||||
|
||||
Elements.clear();
|
||||
Elements.push_back(MDef1);
|
||||
Elements.push_back(MF2);
|
||||
Elements.push_back(MUndef1);
|
||||
auto MN1 = MDTuple::get(Ctx, Elements);
|
||||
EXPECT_EQ(MN1, MF1->getRawElements());
|
||||
|
||||
Elements.clear();
|
||||
Elements.push_back(MDef2);
|
||||
auto MN2 = MDTuple::get(Ctx, Elements);
|
||||
EXPECT_EQ(MN2, MF2->getRawElements());
|
||||
EXPECT_TRUE(verifyModule(*M));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue