class LVLocationSymbol final : public LVLocation {
// Location descriptors for the active range.
- LVAutoOperations *Entries = nullptr;
+ std::unique_ptr<LVOperations> Entries;
void updateKind() override;
LVLocationSymbol() : LVLocation() {}
LVLocationSymbol(const LVLocationSymbol &) = delete;
LVLocationSymbol &operator=(const LVLocationSymbol &) = delete;
- ~LVLocationSymbol() { delete Entries; };
+ ~LVLocationSymbol() = default;
void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset,
uint64_t LocDescOffset) override;
using LVTypeSetFunction = void (LVType::*)();
using LVTypeGetFunction = bool (LVType::*)() const;
-// The LVScope class represents a logical scope and uses vectors to store its
-// children, which are pointers to other allocated logical elements (types,
-// symbols, lines, scopes, ranges). On destruction, we have to traverse each
-// vector and destroy its elements. The other case is LVSymbol.
-// These definitions are intended to be used by the LVScope and LVSymbol
-// to support automatic vector cleanup.
-using LVAutoLines = LVAutoSmallVector<LVLine *>;
-using LVAutoLocations = LVAutoSmallVector<LVLocation *>;
-using LVAutoOperations = LVAutoSmallVector<LVOperation *, 8>;
-using LVAutoScopes = LVAutoSmallVector<LVScope *>;
-using LVAutoSymbols = LVAutoSmallVector<LVSymbol *>;
-using LVAutoTypes = LVAutoSmallVector<LVType *>;
-
-// These definitions are intended to be used when the vector will be used
-// just a container, with no automatic destruction.
using LVElements = SmallVector<LVElement *, 8>;
using LVLines = SmallVector<LVLine *, 8>;
using LVLocations = SmallVector<LVLocation *, 8>;
raw_fd_ostream &os() { return OutputFile->os(); }
};
+/// The logical reader owns of all the logical elements created during
+/// the debug information parsing. For its creation it uses a specific
+/// bump allocator for each type of logical element.
class LVReader {
LVBinaryType BinaryType;
Error createSplitFolder();
bool OutputSplit = false;
+// Define a specific bump allocator for the given KIND.
+#define LV_OBJECT_ALLOCATOR(KIND) \
+ llvm::SpecificBumpPtrAllocator<LV##KIND> Allocated##KIND;
+
+ // Lines allocator.
+ LV_OBJECT_ALLOCATOR(Line)
+ LV_OBJECT_ALLOCATOR(LineDebug)
+ LV_OBJECT_ALLOCATOR(LineAssembler)
+
+ // Locations allocator.
+ LV_OBJECT_ALLOCATOR(Location)
+ LV_OBJECT_ALLOCATOR(LocationSymbol)
+
+ // Operations allocator.
+ LV_OBJECT_ALLOCATOR(Operation)
+
+ // Scopes allocator.
+ LV_OBJECT_ALLOCATOR(Scope)
+ LV_OBJECT_ALLOCATOR(ScopeAggregate)
+ LV_OBJECT_ALLOCATOR(ScopeAlias)
+ LV_OBJECT_ALLOCATOR(ScopeArray)
+ LV_OBJECT_ALLOCATOR(ScopeCompileUnit)
+ LV_OBJECT_ALLOCATOR(ScopeEnumeration)
+ LV_OBJECT_ALLOCATOR(ScopeFormalPack)
+ LV_OBJECT_ALLOCATOR(ScopeFunction)
+ LV_OBJECT_ALLOCATOR(ScopeFunctionInlined)
+ LV_OBJECT_ALLOCATOR(ScopeFunctionType)
+ LV_OBJECT_ALLOCATOR(ScopeNamespace)
+ LV_OBJECT_ALLOCATOR(ScopeRoot)
+ LV_OBJECT_ALLOCATOR(ScopeTemplatePack)
+
+ // Symbols allocator.
+ LV_OBJECT_ALLOCATOR(Symbol)
+
+ // Types allocator.
+ LV_OBJECT_ALLOCATOR(Type)
+ LV_OBJECT_ALLOCATOR(TypeDefinition)
+ LV_OBJECT_ALLOCATOR(TypeEnumerator)
+ LV_OBJECT_ALLOCATOR(TypeImport)
+ LV_OBJECT_ALLOCATOR(TypeParam)
+ LV_OBJECT_ALLOCATOR(TypeSubrange)
+
+#undef LV_OBJECT_ALLOCATOR
+
protected:
LVScopeRoot *Root = nullptr;
std::string InputFilename;
// Create the Scope Root.
virtual Error createScopes() {
- Root = new LVScopeRoot();
+ Root = createScopeRoot();
Root->setName(getFilename());
if (options().getAttributeFormat())
Root->setFileFormatName(FileFormatName);
OS(W.getOStream()) {}
LVReader(const LVReader &) = delete;
LVReader &operator=(const LVReader &) = delete;
- virtual ~LVReader() {
- if (Root)
- delete Root;
+ virtual ~LVReader() = default;
+
+// Creates a logical object of the given KIND. The signature for the created
+// functions looks like:
+// ...
+// LVScope *createScope()
+// LVScopeRoot *creatScopeRoot()
+// LVType *createType();
+// ...
+#define LV_CREATE_OBJECT(KIND) \
+ LV##KIND *create##KIND() { \
+ return new (Allocated##KIND.Allocate()) LV##KIND(); \
+ }
+
+ // Lines creation.
+ LV_CREATE_OBJECT(Line)
+ LV_CREATE_OBJECT(LineDebug)
+ LV_CREATE_OBJECT(LineAssembler)
+
+ // Locations creation.
+ LV_CREATE_OBJECT(Location)
+ LV_CREATE_OBJECT(LocationSymbol)
+
+ // Scopes creation.
+ LV_CREATE_OBJECT(Scope)
+ LV_CREATE_OBJECT(ScopeAggregate)
+ LV_CREATE_OBJECT(ScopeAlias)
+ LV_CREATE_OBJECT(ScopeArray)
+ LV_CREATE_OBJECT(ScopeCompileUnit)
+ LV_CREATE_OBJECT(ScopeEnumeration)
+ LV_CREATE_OBJECT(ScopeFormalPack)
+ LV_CREATE_OBJECT(ScopeFunction)
+ LV_CREATE_OBJECT(ScopeFunctionInlined)
+ LV_CREATE_OBJECT(ScopeFunctionType)
+ LV_CREATE_OBJECT(ScopeNamespace)
+ LV_CREATE_OBJECT(ScopeRoot)
+ LV_CREATE_OBJECT(ScopeTemplatePack)
+
+ // Symbols creation.
+ LV_CREATE_OBJECT(Symbol)
+
+ // Types creation.
+ LV_CREATE_OBJECT(Type)
+ LV_CREATE_OBJECT(TypeDefinition)
+ LV_CREATE_OBJECT(TypeEnumerator)
+ LV_CREATE_OBJECT(TypeImport)
+ LV_CREATE_OBJECT(TypeParam)
+ LV_CREATE_OBJECT(TypeSubrange)
+
+#undef LV_CREATE_OBJECT
+
+ // Operations creation.
+ LVOperation *createOperation(LVSmall OpCode, LVUnsigned Operand1,
+ LVUnsigned Operand2) {
+ return new (AllocatedOperation.Allocate())
+ LVOperation(OpCode, Operand1, Operand2);
}
StringRef getFilename(LVObject *Object, size_t Index) const;
using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
using LVScopeRequest = std::vector<LVScopeGetFunction>;
-using LVOffsetList = std::list<LVOffset>;
using LVOffsetElementMap = std::map<LVOffset, LVElement *>;
-using LVOffsetLinesMap = std::map<LVOffset, LVLines *>;
-using LVOffsetLocationsMap = std::map<LVOffset, LVLocations *>;
+using LVOffsetLinesMap = std::map<LVOffset, LVLines>;
+using LVOffsetLocationsMap = std::map<LVOffset, LVLocations>;
using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>;
-using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsetList *>;
+using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsets>;
// Class to represent a DWARF Scope.
class LVScope : public LVElement {
// Calculate coverage factor.
void calculateCoverage() {
float CoveragePercentage = 0;
- LVLocation::calculateCoverage(Ranges, CoverageFactor, CoveragePercentage);
+ LVLocation::calculateCoverage(Ranges.get(), CoverageFactor,
+ CoveragePercentage);
}
// Decide if the scope will be printed, using some conditions given by:
protected:
// Types, Symbols, Scopes, Lines, Locations in this scope.
- LVAutoTypes *Types = nullptr;
- LVAutoSymbols *Symbols = nullptr;
- LVAutoScopes *Scopes = nullptr;
- LVAutoLines *Lines = nullptr;
- LVAutoLocations *Ranges = nullptr;
+ std::unique_ptr<LVTypes> Types;
+ std::unique_ptr<LVSymbols> Symbols;
+ std::unique_ptr<LVScopes> Scopes;
+ std::unique_ptr<LVLines> Lines;
+ std::unique_ptr<LVLocations> Ranges;
// Vector of elements (types, scopes and symbols).
// It is the union of (*Types, *Symbols and *Scopes) to be used for
// - Preserve the order the logical elements are read in.
// - To have a single container with all the logical elements, when
// the traversal does not require any specific element kind.
- LVElements *Children = nullptr;
+ std::unique_ptr<LVElements> Children;
// Resolve the template parameters/arguments relationship.
void resolveTemplate();
}
LVScope(const LVScope &) = delete;
LVScope &operator=(const LVScope &) = delete;
- virtual ~LVScope();
+ virtual ~LVScope() = default;
static bool classof(const LVElement *Element) {
return Element->getSubclassID() == LVSubclassID::LV_SCOPE;
const char *kind() const override;
// Get the specific children.
- const LVLines *getLines() const { return Lines; }
- const LVLocations *getRanges() const { return Ranges; }
- const LVScopes *getScopes() const { return Scopes; }
- const LVSymbols *getSymbols() const { return Symbols; }
- const LVTypes *getTypes() const { return Types; }
- const LVElements *getChildren() const { return Children; }
+ const LVLines *getLines() const { return Lines.get(); }
+ const LVLocations *getRanges() const { return Ranges.get(); }
+ const LVScopes *getScopes() const { return Scopes.get(); }
+ const LVSymbols *getSymbols() const { return Symbols.get(); }
+ const LVTypes *getTypes() const { return Types.get(); }
+ const LVElements *getChildren() const { return Children.get(); }
void addElement(LVElement *Element);
void addElement(LVLine *Line);
LVOffsetLocationsMap *Map) {
LVOffset Offset = Element->getOffset();
addInvalidOffset(Offset, Element);
- addItem<LVOffsetLocationsMap, LVLocations, LVOffset, LVLocation *>(
- Map, Offset, Location);
+ addItem<LVOffsetLocationsMap, LVOffset, LVLocation *>(Map, Offset,
+ Location);
}
// Record scope sizes indexed by lexical level.
}
LVScopeCompileUnit(const LVScopeCompileUnit &) = delete;
LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
- ~LVScopeCompileUnit() {
- deleteList<LVTagOffsetsMap>(DebugTags);
- deleteList<LVOffsetLocationsMap>(InvalidLocations);
- deleteList<LVOffsetLocationsMap>(InvalidRanges);
- deleteList<LVOffsetLinesMap>(LinesZero);
- }
+ ~LVScopeCompileUnit() = default;
LVScope *getCompileUnitParent() const override {
return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
// Returns the unique string pool instance.
LVStringPool &getStringPool();
-template <typename T>
-using TypeIsValid = std::bool_constant<std::is_pointer<T>::value>;
-
-// Utility class to help memory management and perform an automatic cleaning.
-template <typename T, unsigned N = 8>
-class LVAutoSmallVector : public SmallVector<T, N> {
- static_assert(TypeIsValid<T>::value, "T must be a pointer type");
-
-public:
- using iterator = typename SmallVector<T, N>::iterator;
- LVAutoSmallVector() : SmallVector<T, N>::SmallVector() {}
-
- ~LVAutoSmallVector() {
- // Destroy the constructed elements in the vector.
- for (auto *Item : *this)
- delete Item;
- }
-};
-
// Used to record specific characteristics about the objects.
template <typename T> class LVProperties {
SmallBitVector Bits = SmallBitVector(static_cast<unsigned>(T::LastEntry) + 1);
return Stream.str();
}
-// Add an item to a map with second being a list.
-template <typename MapType, typename ListType, typename KeyType,
- typename ValueType>
+// Add an item to a map with second being a small vector.
+template <typename MapType, typename KeyType, typename ValueType>
void addItem(MapType *Map, KeyType Key, ValueType Value) {
- ListType *List = nullptr;
- typename MapType::const_iterator Iter = Map->find(Key);
- if (Iter != Map->end())
- List = Iter->second;
- else {
- List = new ListType();
- Map->emplace(Key, List);
- }
- List->push_back(Value);
-}
-
-// Delete the map contained list.
-template <typename MapType> void deleteList(MapType &Map) {
- for (typename MapType::const_reference Entry : Map)
- delete Entry.second;
+ (*Map)[Key].push_back(Value);
}
// Double map data structure.
static_assert(std::is_pointer<ValueType>::value,
"ValueType must be a pointer.");
using LVSecondMapType = std::map<SecondKeyType, ValueType>;
- using LVFirstMapType = std::map<FirstKeyType, LVSecondMapType *>;
+ using LVFirstMapType =
+ std::map<FirstKeyType, std::unique_ptr<LVSecondMapType>>;
using LVAuxMapType = std::map<SecondKeyType, FirstKeyType>;
using LVValueTypes = std::vector<ValueType>;
LVFirstMapType FirstMap;
LVAuxMapType AuxMap;
public:
- LVDoubleMap() = default;
- ~LVDoubleMap() {
- for (auto &Entry : FirstMap)
- delete Entry.second;
- }
-
void add(FirstKeyType FirstKey, SecondKeyType SecondKey, ValueType Value) {
- LVSecondMapType *SecondMap = nullptr;
typename LVFirstMapType::iterator FirstIter = FirstMap.find(FirstKey);
if (FirstIter == FirstMap.end()) {
- SecondMap = new LVSecondMapType();
- FirstMap.emplace(FirstKey, SecondMap);
+ auto SecondMapSP = std::make_unique<LVSecondMapType>();
+ SecondMapSP->emplace(SecondKey, Value);
+ FirstMap.emplace(FirstKey, std::move(SecondMapSP));
} else {
- SecondMap = FirstIter->second;
+ LVSecondMapType *SecondMap = FirstIter->second.get();
+ if (SecondMap->find(SecondKey) == SecondMap->end())
+ SecondMap->emplace(SecondKey, Value);
}
- assert(SecondMap && "SecondMap is null.");
- if (SecondMap && SecondMap->find(SecondKey) == SecondMap->end())
- SecondMap->emplace(SecondKey, Value);
-
typename LVAuxMapType::iterator AuxIter = AuxMap.find(SecondKey);
if (AuxIter == AuxMap.end()) {
AuxMap.emplace(SecondKey, FirstKey);
if (FirstIter == FirstMap.end())
return nullptr;
- LVSecondMapType *SecondMap = FirstIter->second;
- return SecondMap;
+ return FirstIter->second.get();
}
ValueType find(FirstKeyType FirstKey, SecondKeyType SecondKey) const {
if (FirstMap.empty())
return Values;
for (typename LVFirstMapType::const_reference FirstEntry : FirstMap) {
- LVSecondMapType *SecondMap = FirstEntry.second;
- for (typename LVSecondMapType::const_reference SecondEntry : *SecondMap)
+ LVSecondMapType &SecondMap = *FirstEntry.second;
+ for (typename LVSecondMapType::const_reference SecondEntry : SecondMap)
Values.push_back(SecondEntry.second);
}
return Values;
// Reference to DW_AT_specification, DW_AT_abstract_origin attribute.
LVSymbol *Reference = nullptr;
- LVAutoLocations *Locations = nullptr;
+ std::unique_ptr<LVLocations> Locations;
LVLocation *CurrentLocation = nullptr;
// Bitfields length.
float CoveragePercentage = 0;
// Add a location gap into the location list.
- LVAutoLocations::iterator addLocationGap(LVAutoLocations::iterator Pos,
- LVAddress LowPC, LVAddress HighPC);
+ LVLocations::iterator addLocationGap(LVLocations::iterator Pos,
+ LVAddress LowPC, LVAddress HighPC);
// Find the current symbol in the given 'Targets'.
LVSymbol *findIn(const LVSymbols *Targets) const;
}
LVSymbol(const LVSymbol &) = delete;
LVSymbol &operator=(const LVSymbol &) = delete;
- ~LVSymbol() { delete Locations; }
+ ~LVSymbol() = default;
static bool classof(const LVElement *Element) {
return Element->getSubclassID() == LVSubclassID::LV_SYMBOL;
namespace llvm {
namespace logicalview {
-using LVReaders = std::vector<LVReader *>;
+using LVReaders = std::vector<std::unique_ptr<LVReader>>;
using ArgVector = std::vector<std::string>;
using PdbOrObj = PointerUnion<object::ObjectFile *, pdb::PDBFile *>;
LVReaders TheReaders;
Error createReaders();
- void destroyReaders();
Error printReaders();
Error compareReaders();
}
LVReaderHandler(const LVReaderHandler &) = delete;
LVReaderHandler &operator=(const LVReaderHandler &) = delete;
- ~LVReaderHandler() { destroyReaders(); }
Error createReader(StringRef Filename, LVReaders &Readers) {
return handleFile(Readers, Filename);
}
Error process();
- Expected<LVReader *> createReader(StringRef Pathname) {
+ Expected<std::unique_ptr<LVReader>> createReader(StringRef Pathname) {
LVReaders Readers;
if (Error Err = createReader(Pathname, Readers))
return std::move(Err);
- return Readers[0];
+ return std::move(Readers[0]);
}
- void deleteReader(LVReader *Reader) { delete Reader; }
void print(raw_ostream &OS) const;
// Scopes with ranges for current compile unit. It is used to find a line
// giving its exact or closest address. To support comdat functions, all
// addresses for the same section are recorded in the same map.
- using LVSectionRanges = std::map<LVSectionIndex, LVRange *>;
+ using LVSectionRanges = std::map<LVSectionIndex, std::unique_ptr<LVRange>>;
LVSectionRanges SectionRanges;
// Image base and virtual address for Executable file.
using LVSections = std::map<LVSectionIndex, object::SectionRef>;
LVSections Sections;
+ std::vector<std::unique_ptr<LVLines>> DiscoveredLines;
+
protected:
// It contains the LVLineDebug elements representing the logical lines for
// the current compile unit, created by parsing the debug line section.
: LVReader(Filename, FileFormatName, W, BinaryType) {}
LVBinaryReader(const LVBinaryReader &) = delete;
LVBinaryReader &operator=(const LVBinaryReader &) = delete;
- virtual ~LVBinaryReader();
+ virtual ~LVBinaryReader() = default;
void addToSymbolTable(StringRef Name, LVScope *Function,
LVSectionIndex SectionIndex = 0);
void LVLocationSymbol::addObject(LVSmall Opcode, LVUnsigned Operand1,
LVUnsigned Operand2) {
if (!Entries)
- Entries = new LVAutoOperations();
- Entries->emplace_back(new LVOperation(Opcode, Operand1, Operand2));
+ Entries = std::make_unique<LVOperations>();
+ Entries->push_back(getReader().createOperation(Opcode, Operand1, Operand2));
}
// Based on the DWARF attribute, define the location kind.
void LVLocationSymbol::updateKind() {
// Update the location type for simple ones.
if (Entries && Entries->size() == 1) {
- LVOperation *Operation = Entries->front();
- if (dwarf::DW_OP_fbreg == Operation->getOpcode())
+ if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode())
setIsStackOffset();
}
}
//===----------------------------------------------------------------------===//
// DWARF lexical block, such as: namespace, function, compile unit, module, etc.
//===----------------------------------------------------------------------===//
-LVScope::~LVScope() {
- delete Types;
- delete Symbols;
- delete Scopes;
- delete Lines;
- delete Ranges;
- delete Children;
-}
-
// Return a string representation for the scope kind.
const char *LVScope::kind() const {
const char *Kind = KindUndefined;
void LVScope::addToChildren(LVElement *Element) {
if (!Children)
- Children = new LVElements();
+ Children = std::make_unique<LVElements>();
Children->push_back(Element);
}
assert(Line && "Invalid line.");
assert(!Line->getParent() && "Line already inserted");
if (!Lines)
- Lines = new LVAutoLines();
+ Lines = std::make_unique<LVLines>();
// Add it to parent.
Lines->push_back(Line);
assert(Location && "Invalid location.");
assert(!Location->getParent() && "Location already inserted");
if (!Ranges)
- Ranges = new LVAutoLocations();
+ Ranges = std::make_unique<LVLocations>();
// Add it to parent.
Location->setParent(this);
assert(Scope && "Invalid scope.");
assert(!Scope->getParent() && "Scope already inserted");
if (!Scopes)
- Scopes = new LVAutoScopes();
+ Scopes = std::make_unique<LVScopes>();
// Add it to parent.
Scopes->push_back(Scope);
assert(Symbol && "Invalid symbol.");
assert(!Symbol->getParent() && "Symbol already inserted");
if (!Symbols)
- Symbols = new LVAutoSymbols();
+ Symbols = std::make_unique<LVSymbols>();
// Add it to parent.
Symbols->push_back(Symbol);
assert(Type && "Invalid type.");
assert(!Type->getParent() && "Type already inserted");
if (!Types)
- Types = new LVAutoTypes();
+ Types = std::make_unique<LVTypes>();
// Add it to parent.
Types->push_back(Type);
// Add a pair of ranges.
void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {
// Pack the ranges into a Location object.
- LVLocation *Location = new LVLocation();
+ LVLocation *Location = getReader().createLocation();
Location->setLowerAddress(LowerAddress);
Location->setUpperAddress(UpperAddress);
Location->setIsAddressRange();
// information that is incorrect for the element to be inserted.
// As the symbol being added does not exist in the debug section,
// use its parent scope offset, to indicate its DIE location.
- LVSymbol *Symbol = new LVSymbol();
+ LVSymbol *Symbol = getReader().createSymbol();
addElement(Symbol);
Symbol->setOffset(getOffset());
Symbol->setIsOptimized();
if (SortFunction) {
std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =
[&](LVScope *Parent, LVSortFunction SortFunction) {
- auto Traverse = [&](auto *Set, LVSortFunction SortFunction) {
+ auto Traverse = [&](auto &Set, LVSortFunction SortFunction) {
if (Set)
std::stable_sort(Set->begin(), Set->end(), SortFunction);
};
}
void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {
- auto SetCompareState = [&](auto *Container) {
+ auto SetCompareState = [&](auto &Container) {
if (Container)
for (auto *Entry : *Container)
Entry->setIsInCompare();
// Record unsuported DWARF tags.
void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
- addItem<LVTagOffsetsMap, LVOffsetList, dwarf::Tag, LVOffset>(&DebugTags,
- Target, Offset);
+ addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset);
}
// Record elements with invalid offsets.
LVScope *Scope = Line->getParentScope();
LVOffset Offset = Scope->getOffset();
addInvalidOffset(Offset, Scope);
- addItem<LVOffsetLinesMap, LVLines, LVOffset, LVLine *>(&LinesZero, Offset,
- Line);
+ addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line);
}
void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
PrintHeader(Header);
for (LVOffsetLocationsMap::const_reference Entry : Map) {
PrintElement(WarningOffsets, Entry.first);
- for (const LVLocation *Location : *Entry.second)
+ for (const LVLocation *Location : Entry.second)
OS << hexSquareString(Location->getOffset()) << " "
<< Location->getIntervalInfo() << "\n";
}
OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
<< dwarf::TagString(Entry.first) << "\n";
unsigned Count = 0;
- for (const LVOffset &Offset : *Entry.second)
+ for (const LVOffset &Offset : Entry.second)
PrintOffset(Count, Offset);
OS << "\n";
}
for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
PrintElement(WarningOffsets, Entry.first);
unsigned Count = 0;
- for (const LVLine *Line : *Entry.second)
+ for (const LVLine *Line : Entry.second)
PrintOffset(Count, Line->getOffset());
OS << "\n";
}
LVAddress HighPC, LVUnsigned SectionOffset,
uint64_t LocDescOffset, bool CallSiteLocation) {
if (!Locations)
- Locations = new LVAutoLocations();
+ Locations = std::make_unique<LVLocations>();
// Create the location entry.
- CurrentLocation = new LVLocationSymbol();
+ CurrentLocation = getReader().createLocationSymbol();
CurrentLocation->setParent(this);
CurrentLocation->setAttr(Attr);
if (CallSiteLocation)
LVAddress LowPC,
LVAddress HighPC) {
// Create a location entry for the gap.
- LVLocation *Gap = new LVLocationSymbol();
+ LVLocation *Gap = getReader().createLocationSymbol();
Gap->setParent(this);
Gap->setAttr(dwarf::DW_AT_location);
Gap->addObject(LowPC, HighPC,
// Calculate coverage factor.
void LVSymbol::calculateCoverage() {
- if (!LVLocation::calculateCoverage(Locations, CoverageFactor,
+ if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor,
CoveragePercentage)) {
LVScope *Parent = getParentScope();
if (Parent->getIsInlinedFunction()) {
Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));
// Print location information.
- LVLocation::print(Locations, OS, Full);
+ LVLocation::print(Locations.get(), OS, Full);
}
}
if (!Type->getIsTemplateParam())
continue;
if (options().getAttributeArgument()) {
- LVScope *Scope = nullptr;
if (Type->getIsKindType())
- Type = Type->getTypeAsType();
- else {
- if (Type->getIsKindScope()) {
- Scope = Type->getTypeAsScope();
- Type = nullptr;
- }
- }
- Type ? TypesParam->push_back(Type) : ScopesParam->push_back(Scope);
+ TypesParam->push_back(Type->getTypeAsType());
+ else if (Type->getIsKindScope())
+ ScopesParam->push_back(Type->getTypeAsScope());
} else
TypesParam->push_back(Type);
}
return Error::success();
}
-void LVReaderHandler::destroyReaders() {
- LLVM_DEBUG(dbgs() << "destroyReaders\n");
- for (const LVReader *Reader : TheReaders)
- delete Reader;
-}
-
Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers,
PdbOrObj &Input, StringRef FileFormatName,
StringRef ExePath) {
- auto CreateOneReader = [&]() -> LVReader * {
+ auto CreateOneReader = [&]() -> std::unique_ptr<LVReader> {
if (Input.is<ObjectFile *>()) {
ObjectFile &Obj = *Input.get<ObjectFile *>();
if (Obj.isELF() || Obj.isMachO())
- return new LVELFReader(Filename, FileFormatName, Obj, W);
+ return std::make_unique<LVELFReader>(Filename, FileFormatName, Obj, W);
}
return nullptr;
};
- LVReader *Reader = CreateOneReader();
- if (!Reader)
+ std::unique_ptr<LVReader> ReaderObj = CreateOneReader();
+ if (!ReaderObj)
return createStringError(errc::invalid_argument,
"unable to create reader for: '%s'",
Filename.str().c_str());
- Readers.push_back(Reader);
+ LVReader *Reader = ReaderObj.get();
+ Readers.emplace_back(std::move(ReaderObj));
return Reader->doLoad();
}
LVReaders Readers;
if (Error Err = createReader(Object, Readers))
return Err;
- TheReaders.insert(TheReaders.end(), Readers.begin(), Readers.end());
+ TheReaders.insert(TheReaders.end(),
+ std::make_move_iterator(Readers.begin()),
+ std::make_move_iterator(Readers.end()));
}
return Error::success();
Error LVReaderHandler::printReaders() {
LLVM_DEBUG(dbgs() << "printReaders\n");
if (options().getPrintExecute())
- for (LVReader *Reader : TheReaders)
+ for (const std::unique_ptr<LVReader> &Reader : TheReaders)
if (Error Err = Reader->doPrint())
return Err;
size_t ViewPairs = ReadersCount / 2;
LVCompare Compare(OS);
for (size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) {
- if (Error Err = Compare.execute(TheReaders[Index], TheReaders[Index + 1]))
+ if (Error Err = Compare.execute(TheReaders[Index].get(),
+ TheReaders[Index + 1].get()))
return Err;
Index += 2;
}
}
LVRange *LVBinaryReader::getSectionRanges(LVSectionIndex SectionIndex) {
- LVRange *Range = nullptr;
// Check if we already have a mapping for this section index.
LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex);
- if (IterSection == SectionRanges.end()) {
- Range = new LVRange();
- SectionRanges.emplace(SectionIndex, Range);
- } else {
- Range = IterSection->second;
- }
+ if (IterSection == SectionRanges.end())
+ IterSection =
+ SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first;
+ LVRange *Range = IterSection->second.get();
assert(Range && "Range is null.");
return Range;
}
-LVBinaryReader::~LVBinaryReader() {
- // Delete the lines created by 'createInstructions'.
- std::vector<LVLines *> AllInstructionLines = ScopeInstructions.find();
- for (LVLines *Entry : AllInstructionLines)
- delete Entry;
- // Delete the ranges created by 'getSectionRanges'.
- for (LVSectionRanges::reference Entry : SectionRanges)
- delete Entry.second;
-}
-
Error LVBinaryReader::createInstructions(LVScope *Scope,
LVSectionIndex SectionIndex,
const LVNameInfo &NameInfo) {
// Address for first instruction line.
LVAddress FirstAddress = Address;
- LVLines *Instructions = new LVLines();
+ auto InstructionsSP = std::make_unique<LVLines>();
+ LVLines &Instructions = *InstructionsSP;
+ DiscoveredLines.emplace_back(std::move(InstructionsSP));
while (Begin < End) {
MCInst Instruction;
// the 'processLines()' function will move each created logical line
// to its enclosing logical scope, using the debug ranges information
// and they will be released when its scope parent is deleted.
- LVLineAssembler *Line = new LVLineAssembler();
+ LVLineAssembler *Line = createLineAssembler();
Line->setAddress(Address);
Line->setName(StringRef(Stream.str()).trim());
- Instructions->push_back(Line);
+ Instructions.push_back(Line);
break;
}
}
<< " Scope DIE: " << hexValue(Scope->getOffset()) << "\n"
<< "Address: " << hexValue(FirstAddress)
<< format(" - Collected instructions lines: %d\n",
- Instructions->size());
- for (const LVLine *Line : *Instructions)
+ Instructions.size());
+ for (const LVLine *Line : Instructions)
dbgs() << format_decimal(++Index, 5) << ": "
<< hexValue(Line->getOffset()) << ", (" << Line->getName()
<< ")\n";
});
// The scope in the assembler names is linked to its own instructions.
- ScopeInstructions.add(SectionIndex, Scope, Instructions);
+ ScopeInstructions.add(SectionIndex, Scope, &Instructions);
AssemblerMappings.add(SectionIndex, FirstAddress, Scope);
return Error::success();
switch (Tag) {
// Types.
case dwarf::DW_TAG_base_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsBase();
if (options().getAttributeBase())
CurrentType->setIncludeInPrint();
return CurrentType;
case dwarf::DW_TAG_const_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsConst();
CurrentType->setName("const");
return CurrentType;
case dwarf::DW_TAG_enumerator:
- CurrentType = new LVTypeEnumerator();
+ CurrentType = createTypeEnumerator();
return CurrentType;
case dwarf::DW_TAG_imported_declaration:
- CurrentType = new LVTypeImport();
+ CurrentType = createTypeImport();
CurrentType->setIsImportDeclaration();
return CurrentType;
case dwarf::DW_TAG_imported_module:
- CurrentType = new LVTypeImport();
+ CurrentType = createTypeImport();
CurrentType->setIsImportModule();
return CurrentType;
case dwarf::DW_TAG_pointer_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsPointer();
CurrentType->setName("*");
return CurrentType;
case dwarf::DW_TAG_ptr_to_member_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsPointerMember();
CurrentType->setName("*");
return CurrentType;
case dwarf::DW_TAG_reference_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsReference();
CurrentType->setName("&");
return CurrentType;
case dwarf::DW_TAG_restrict_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsRestrict();
CurrentType->setName("restrict");
return CurrentType;
case dwarf::DW_TAG_rvalue_reference_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsRvalueReference();
CurrentType->setName("&&");
return CurrentType;
case dwarf::DW_TAG_subrange_type:
- CurrentType = new LVTypeSubrange();
+ CurrentType = createTypeSubrange();
return CurrentType;
case dwarf::DW_TAG_template_value_parameter:
- CurrentType = new LVTypeParam();
+ CurrentType = createTypeParam();
CurrentType->setIsTemplateValueParam();
return CurrentType;
case dwarf::DW_TAG_template_type_parameter:
- CurrentType = new LVTypeParam();
+ CurrentType = createTypeParam();
CurrentType->setIsTemplateTypeParam();
return CurrentType;
case dwarf::DW_TAG_GNU_template_template_param:
- CurrentType = new LVTypeParam();
+ CurrentType = createTypeParam();
CurrentType->setIsTemplateTemplateParam();
return CurrentType;
case dwarf::DW_TAG_typedef:
- CurrentType = new LVTypeDefinition();
+ CurrentType = createTypeDefinition();
return CurrentType;
case dwarf::DW_TAG_unspecified_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsUnspecified();
return CurrentType;
case dwarf::DW_TAG_volatile_type:
- CurrentType = new LVType();
+ CurrentType = createType();
CurrentType->setIsVolatile();
CurrentType->setName("volatile");
return CurrentType;
// Symbols.
case dwarf::DW_TAG_formal_parameter:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsParameter();
return CurrentSymbol;
case dwarf::DW_TAG_unspecified_parameters:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsUnspecified();
CurrentSymbol->setName("...");
return CurrentSymbol;
case dwarf::DW_TAG_member:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsMember();
return CurrentSymbol;
case dwarf::DW_TAG_variable:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsVariable();
return CurrentSymbol;
case dwarf::DW_TAG_inheritance:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsInheritance();
return CurrentSymbol;
case dwarf::DW_TAG_call_site_parameter:
case dwarf::DW_TAG_GNU_call_site_parameter:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsCallSiteParameter();
return CurrentSymbol;
case dwarf::DW_TAG_constant:
- CurrentSymbol = new LVSymbol();
+ CurrentSymbol = createSymbol();
CurrentSymbol->setIsConstant();
return CurrentSymbol;
// Scopes.
case dwarf::DW_TAG_catch_block:
- CurrentScope = new LVScope();
+ CurrentScope = createScope();
CurrentScope->setIsCatchBlock();
return CurrentScope;
case dwarf::DW_TAG_lexical_block:
- CurrentScope = new LVScope();
+ CurrentScope = createScope();
CurrentScope->setIsLexicalBlock();
return CurrentScope;
case dwarf::DW_TAG_try_block:
- CurrentScope = new LVScope();
+ CurrentScope = createScope();
CurrentScope->setIsTryBlock();
return CurrentScope;
case dwarf::DW_TAG_compile_unit:
case dwarf::DW_TAG_skeleton_unit:
- CurrentScope = new LVScopeCompileUnit();
+ CurrentScope = createScopeCompileUnit();
CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope);
return CurrentScope;
case dwarf::DW_TAG_inlined_subroutine:
- CurrentScope = new LVScopeFunctionInlined();
+ CurrentScope = createScopeFunctionInlined();
return CurrentScope;
case dwarf::DW_TAG_namespace:
- CurrentScope = new LVScopeNamespace();
+ CurrentScope = createScopeNamespace();
return CurrentScope;
case dwarf::DW_TAG_template_alias:
- CurrentScope = new LVScopeAlias();
+ CurrentScope = createScopeAlias();
return CurrentScope;
case dwarf::DW_TAG_array_type:
- CurrentScope = new LVScopeArray();
+ CurrentScope = createScopeArray();
return CurrentScope;
case dwarf::DW_TAG_call_site:
case dwarf::DW_TAG_GNU_call_site:
- CurrentScope = new LVScopeFunction();
+ CurrentScope = createScopeFunction();
CurrentScope->setIsCallSite();
return CurrentScope;
case dwarf::DW_TAG_entry_point:
- CurrentScope = new LVScopeFunction();
+ CurrentScope = createScopeFunction();
CurrentScope->setIsEntryPoint();
return CurrentScope;
case dwarf::DW_TAG_subprogram:
- CurrentScope = new LVScopeFunction();
+ CurrentScope = createScopeFunction();
CurrentScope->setIsSubprogram();
return CurrentScope;
case dwarf::DW_TAG_subroutine_type:
- CurrentScope = new LVScopeFunctionType();
+ CurrentScope = createScopeFunctionType();
return CurrentScope;
case dwarf::DW_TAG_label:
- CurrentScope = new LVScopeFunction();
+ CurrentScope = createScopeFunction();
CurrentScope->setIsLabel();
return CurrentScope;
case dwarf::DW_TAG_class_type:
- CurrentScope = new LVScopeAggregate();
+ CurrentScope = createScopeAggregate();
CurrentScope->setIsClass();
return CurrentScope;
case dwarf::DW_TAG_structure_type:
- CurrentScope = new LVScopeAggregate();
+ CurrentScope = createScopeAggregate();
CurrentScope->setIsStructure();
return CurrentScope;
case dwarf::DW_TAG_union_type:
- CurrentScope = new LVScopeAggregate();
+ CurrentScope = createScopeAggregate();
CurrentScope->setIsUnion();
return CurrentScope;
case dwarf::DW_TAG_enumeration_type:
- CurrentScope = new LVScopeEnumeration();
+ CurrentScope = createScopeEnumeration();
return CurrentScope;
case dwarf::DW_TAG_GNU_formal_parameter_pack:
- CurrentScope = new LVScopeFormalPack();
+ CurrentScope = createScopeFormalPack();
return CurrentScope;
case dwarf::DW_TAG_GNU_template_parameter_pack:
- CurrentScope = new LVScopeTemplatePack();
+ CurrentScope = createScopeTemplatePack();
return CurrentScope;
default:
// Collect TAGs not implemented.
// the 'processLines()' function will move each created logical line
// to its enclosing logical scope, using the debug ranges information
// and they will be released when its scope parent is deleted.
- LVLineDebug *Line = new LVLineDebug();
+ LVLineDebug *Line = createLineDebug();
CULines.push_back(Line);
Line->setAddress(Row.Address.Address);
Line->setFilename(
//===----------------------------------------------------------------------===//
// Basic Reader functionality.
class ReaderTestCompare : public LVReader {
- // Elements created but not added to any logical scope. They are
- // deleted when the logical Reader is destroyed.
- LVAutoSmallVector<LVElement *> OrphanElements;
+#define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr); \
+ VARIABLE->SET_FUNCTION();
public:
// Types.
protected:
void add(LVScope *Parent, LVElement *Element);
- template <typename T, typename F> T *create(F Function) {
- // 'Function' will update a specific kind of the logical element to
- // have the ability of kind selection.
- T *Element = new (std::nothrow) T();
- EXPECT_NE(Element, nullptr);
- (Element->*Function)();
- return Element;
- }
void set(LVElement *Element, StringRef Name, LVOffset Offset,
uint32_t LineNumber = 0, LVElement *Type = nullptr);
ASSERT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
- UnsignedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
- GlobalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
- LocalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
- NestedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
- EnumeratorOne =
- create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
- EnumeratorTwo =
- create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
- TypeDefinitionOne =
- create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
- TypeDefinitionTwo =
- create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
+ CREATE(IntegerType, createType, setIsBase);
+ CREATE(UnsignedType, createType, setIsBase);
+ CREATE(GlobalType, createType, setIsBase);
+ CREATE(LocalType, createType, setIsBase);
+ CREATE(NestedType, createType, setIsBase);
+ CREATE(EnumeratorOne, createTypeEnumerator, setIsEnumerator);
+ CREATE(EnumeratorTwo, createTypeEnumerator, setIsEnumerator);
+ CREATE(TypeDefinitionOne, createTypeDefinition, setIsTypedef);
+ CREATE(TypeDefinitionTwo, createTypeDefinition, setIsTypedef);
// Create the logical scopes.
- NestedScope =
- create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
- InnerScope = create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
- Aggregate =
- create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
- CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
- &LVScope::setIsCompileUnit);
- Enumeration = create<LVScopeEnumeration, LVScopeSetFunction>(
- &LVScope::setIsEnumeration);
- FunctionOne =
- create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
- FunctionTwo =
- create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
- Namespace =
- create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
+ CREATE(NestedScope, createScope, setIsLexicalBlock);
+ CREATE(InnerScope, createScope, setIsLexicalBlock);
+ CREATE(Aggregate, createScopeAggregate, setIsAggregate);
+ CREATE(CompileUnit, createScopeCompileUnit, setIsCompileUnit);
+ CREATE(Enumeration, createScopeEnumeration, setIsEnumeration);
+ CREATE(FunctionOne, createScopeFunction, setIsFunction);
+ CREATE(FunctionTwo, createScopeFunction, setIsFunction);
+ CREATE(Namespace, createScopeNamespace, setIsNamespace);
// Create the logical symbols.
- GlobalVariable =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
- LocalVariable =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
- ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
- NestedVariable =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
- ParameterOne =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
- ParameterTwo =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
+ CREATE(GlobalVariable, createSymbol, setIsVariable);
+ CREATE(LocalVariable, createSymbol, setIsVariable);
+ CREATE(ClassMember, createSymbol, setIsMember);
+ CREATE(NestedVariable, createSymbol, setIsVariable);
+ CREATE(ParameterOne, createSymbol, setIsParameter);
+ CREATE(ParameterTwo, createSymbol, setIsParameter);
// Create the logical lines.
- LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
- LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
- LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
+ CREATE(LineOne, createLine, setIsLineDebug);
+ CREATE(LineTwo, createLine, setIsLineDebug);
+ CREATE(LineThree, createLine, setIsLineDebug);
}
// Reference Reader: Target Reader:
auto Insert = [&](bool Insert, auto *Parent, auto *Child) {
if (Insert)
add(Parent, Child);
- else
- OrphanElements.push_back(Child);
};
setCompileUnit(CompileUnit);
}
// Helper function to create a reader.
-LVReader *createReader(LVReaderHandler &ReaderHandler,
- SmallString<128> &InputsDir, StringRef Filename) {
+std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
+ SmallString<128> &InputsDir,
+ StringRef Filename) {
SmallString<128> ObjectName(InputsDir);
llvm::sys::path::append(ObjectName, Filename);
- Expected<LVReader *> ReaderOrErr =
+ Expected<std::unique_ptr<LVReader>> ReaderOrErr =
ReaderHandler.createReader(std::string(ObjectName));
EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
- LVReader *Reader = *ReaderOrErr;
+ std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
EXPECT_NE(Reader, nullptr);
return Reader;
}
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
// Check logical elements properties.
- LVReader *Reader = createReader(ReaderHandler, InputsDir, DwarfClang);
- checkElementProperties(Reader);
- ReaderHandler.deleteReader(Reader);
+ std::unique_ptr<LVReader> Reader =
+ createReader(ReaderHandler, InputsDir, DwarfClang);
+ checkElementProperties(Reader.get());
}
// Logical elements selection.
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
// Check logical elements selection.
- LVReader *Reader = createReader(ReaderHandler, InputsDir, DwarfGcc);
- checkElementSelection(Reader);
- ReaderHandler.deleteReader(Reader);
+ std::unique_ptr<LVReader> Reader =
+ createReader(ReaderHandler, InputsDir, DwarfGcc);
+ checkElementSelection(Reader.get());
}
// Compare logical elements.
LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
// Check logical comparison.
- LVReader *Reference = createReader(ReaderHandler, InputsDir, DwarfClang);
- LVReader *Target = createReader(ReaderHandler, InputsDir, DwarfGcc);
- checkElementComparison(Reference, Target);
- ReaderHandler.deleteReader(Reference);
- ReaderHandler.deleteReader(Target);
+ std::unique_ptr<LVReader> Reference =
+ createReader(ReaderHandler, InputsDir, DwarfClang);
+ std::unique_ptr<LVReader> Target =
+ createReader(ReaderHandler, InputsDir, DwarfGcc);
+ checkElementComparison(Reference.get(), Target.get());
}
TEST(LogicalViewTest, ELFReader) {
class ReaderTest : public LVReader {
protected:
+ void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
void add(LVScope *Parent, LVElement *Element);
- template <typename T> T *create() {
- T *Element = new (std::nothrow) T();
- EXPECT_NE(Element, nullptr);
- return Element;
- }
void set(LVElement *Element, StringRef Name, LVOffset Offset,
uint32_t LineNumber = 0, LVElement *Type = nullptr);
void set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
LVAddress LowerAddress, LVAddress UpperAddress);
- void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
public:
ReaderTest(ScopedPrinter &W) : LVReader("", "", W) { setInstance(this); }
}
class ReaderTestLocations : public ReaderTest {
+#define CREATE(VARIABLE, CREATE_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr);
+
// Types.
LVType *IntegerType = nullptr;
EXPECT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType>();
+ CREATE(IntegerType, createType);
// Create the logical scopes.
- NestedScope = create<LVScope>();
- CompileUnit = create<LVScopeCompileUnit>();
- Function = create<LVScopeFunction>();
+ CREATE(NestedScope, createScope);
+ CREATE(CompileUnit, createScopeCompileUnit);
+ CREATE(Function, createScopeFunction);
// Create the logical symbols.
- LocalVariable = create<LVSymbol>();
- NestedVariable = create<LVSymbol>();
- Parameter = create<LVSymbol>();
+ CREATE(LocalVariable, createSymbol);
+ CREATE(NestedVariable, createSymbol);
+ CREATE(Parameter, createSymbol);
// Create the logical lines.
- LineOne = create<LVLine>();
- LineTwo = create<LVLine>();
- LineThree = create<LVLine>();
- LineFour = create<LVLine>();
- LineFive = create<LVLine>();
- LineSix = create<LVLine>();
+ CREATE(LineOne, createLine);
+ CREATE(LineTwo, createLine);
+ CREATE(LineThree, createLine);
+ CREATE(LineFour, createLine);
+ CREATE(LineFive, createLine);
+ CREATE(LineSix, createLine);
// Create the logical locations.
- LocationOne = create<LVLocation>();
- LocationTwo = create<LVLocation>();
- LocationThree = create<LVLocation>();
- LocationFour = create<LVLocation>();
- LocationFive = create<LVLocation>();
- LocationSix = create<LVLocation>();
+ CREATE(LocationOne, createLocation);
+ CREATE(LocationTwo, createLocation);
+ CREATE(LocationThree, createLocation);
+ CREATE(LocationFour, createLocation);
+ CREATE(LocationFive, createLocation);
+ CREATE(LocationSix, createLocation);
}
// Create the logical view adding the created logical elements.
EXPECT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType>();
+ IntegerType = createType();
+ EXPECT_NE(IntegerType, nullptr);
// Create the logical scopes.
- CompileUnit = create<LVScopeCompileUnit>();
- Function = create<LVScopeFunction>();
- InlinedFunction = create<LVScopeFunctionInlined>();
+ CompileUnit = createScopeCompileUnit();
+ EXPECT_NE(CompileUnit, nullptr);
+ Function = createScopeFunction();
+ EXPECT_NE(Function, nullptr);
+ InlinedFunction = createScopeFunctionInlined();
+ EXPECT_NE(InlinedFunction, nullptr);
// Create the logical symbols.
- Variable = create<LVSymbol>();
- Parameter = create<LVSymbol>();
+ Variable = createSymbol();
+ EXPECT_NE(Variable, nullptr);
+ Parameter = createSymbol();
+ EXPECT_NE(Parameter, nullptr);
// Create the logical lines.
- LineOne = create<LVLine>();
- LineTwo = create<LVLine>();
- LineThree = create<LVLine>();
- LineFour = create<LVLine>();
- LineFive = create<LVLine>();
- LineSix = create<LVLine>();
+ LineOne = createLine();
+ EXPECT_NE(LineOne, nullptr);
+ LineTwo = createLine();
+ EXPECT_NE(LineTwo, nullptr);
+ LineThree = createLine();
+ EXPECT_NE(LineThree, nullptr);
+ LineFour = createLine();
+ EXPECT_NE(LineFour, nullptr);
+ LineFive = createLine();
+ EXPECT_NE(LineFive, nullptr);
+ LineSix = createLine();
+ EXPECT_NE(LineSix, nullptr);
// Create the logical locations.
- LocationOne = create<LVLocation>();
- LocationTwo = create<LVLocation>();
- LocationFive = create<LVLocation>();
- LocationSix = create<LVLocation>();
+ LocationOne = createLocation();
+ EXPECT_NE(LocationOne, nullptr);
+ LocationTwo = createLocation();
+ EXPECT_NE(LocationTwo, nullptr);
+ LocationFive = createLocation();
+ EXPECT_NE(LocationFive, nullptr);
+ LocationSix = createLocation();
+ EXPECT_NE(LocationSix, nullptr);
}
// Create the logical view adding the created logical elements.
namespace {
class ReaderTestElements : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr);
+
// Types.
LVType *IntegerType = nullptr;
LVType *UnsignedType = nullptr;
protected:
void add(LVScope *Parent, LVElement *Element);
- template <typename T> T *create() {
- T *Element = new (std::nothrow) T();
- EXPECT_NE(Element, nullptr);
- return Element;
- }
void set(LVElement *Element, StringRef Name, LVOffset Offset,
uint32_t LineNumber = 0, LVElement *Type = nullptr);
ASSERT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType>();
- UnsignedType = create<LVType>();
- GlobalType = create<LVType>();
- LocalType = create<LVType>();
- NestedType = create<LVType>();
- EnumeratorOne = create<LVTypeEnumerator>();
- EnumeratorTwo = create<LVTypeEnumerator>();
- TypeDefinitionOne = create<LVTypeDefinition>();
- TypeDefinitionTwo = create<LVTypeDefinition>();
- TypeSubrange = create<LVTypeSubrange>();
- TypeParam = create<LVTypeParam>();
- TypeImport = create<LVTypeImport>();
+ CREATE(IntegerType, createType);
+ CREATE(UnsignedType, createType);
+ CREATE(GlobalType, createType);
+ CREATE(LocalType, createType);
+ CREATE(NestedType, createType);
+ CREATE(EnumeratorOne, createTypeEnumerator);
+ CREATE(EnumeratorTwo, createTypeEnumerator);
+ CREATE(TypeDefinitionOne, createTypeDefinition);
+ CREATE(TypeDefinitionTwo, createTypeDefinition);
+ CREATE(TypeSubrange, createTypeSubrange);
+ CREATE(TypeParam, createTypeParam);
+ CREATE(TypeImport, createTypeImport);
// Create the logical scopes.
- NestedScope = create<LVScope>();
- Aggregate = create<LVScopeAggregate>();
- Array = create<LVScopeArray>();
- CompileUnit = create<LVScopeCompileUnit>();
- Enumeration = create<LVScopeEnumeration>();
- Function = create<LVScopeFunction>();
- ClassFunction = create<LVScopeFunction>();
- InlinedFunction = create<LVScopeFunctionInlined>();
- Namespace = create<LVScopeNamespace>();
+ CREATE(NestedScope, createScope);
+ CREATE(Aggregate, createScopeAggregate);
+ CREATE(Array, createScopeArray);
+ CREATE(CompileUnit, createScopeCompileUnit);
+ CREATE(Enumeration, createScopeEnumeration);
+ CREATE(Function, createScopeFunction);
+ CREATE(ClassFunction, createScopeFunction);
+ CREATE(InlinedFunction, createScopeFunctionInlined);
+ CREATE(Namespace, createScopeNamespace);
// Create the logical symbols.
- GlobalVariable = create<LVSymbol>();
- LocalVariable = create<LVSymbol>();
- ClassMember = create<LVSymbol>();
- NestedVariable = create<LVSymbol>();
- Parameter = create<LVSymbol>();
+ CREATE(GlobalVariable, createSymbol);
+ CREATE(LocalVariable, createSymbol);
+ CREATE(ClassMember, createSymbol);
+ CREATE(NestedVariable, createSymbol);
+ CREATE(Parameter, createSymbol);
// Create the logical lines.
- LocalLine = create<LVLine>();
- NestedLine = create<LVLine>();
+ CREATE(LocalLine, createLine);
+ CREATE(NestedLine, createLine);
}
// Create the logical view adding the created logical elements.
namespace {
class ReaderTestSelection : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr); \
+ VARIABLE->SET_FUNCTION();
+
// Types.
LVType *IntegerType = nullptr;
protected:
void add(LVScope *Parent, LVElement *Element);
- template <typename T, typename F> T *create(F Function) {
- // 'Function' will update a specific kind of the logical element to
- // have the ability of kind selection.
- T *Element = new (std::nothrow) T();
- EXPECT_NE(Element, nullptr);
- (Element->*Function)();
- return Element;
- }
void set(LVElement *Element, StringRef Name, LVOffset Offset,
uint32_t LineNumber = 0, LVElement *Type = nullptr);
EXPECT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
+ CREATE(IntegerType, createType, setIsBase);
// Create the logical scopes.
- CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
- &LVScope::setIsCompileUnit);
- Function =
- create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
- NestedScope =
- create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
- Namespace =
- create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
- Aggregate =
- create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
+ CREATE(CompileUnit, createScopeCompileUnit, setIsCompileUnit);
+ CREATE(Function, createScopeFunction, setIsFunction);
+ CREATE(NestedScope, createScope, setIsLexicalBlock);
+ CREATE(Namespace, createScopeNamespace, setIsNamespace);
+ CREATE(Aggregate, createScopeAggregate, setIsAggregate);
// Create the logical symbols.
- ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
- LocalVariable =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
- NestedVariable =
- create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
- Parameter = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
+ CREATE(ClassMember, createSymbol, setIsMember);
+ CREATE(LocalVariable, createSymbol, setIsVariable);
+ CREATE(NestedVariable, createSymbol, setIsVariable);
+ CREATE(Parameter, createSymbol, setIsParameter);
// Create the logical lines.
- LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
- LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsBasicBlock);
- LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsNewStatement);
- LineFour = create<LVLine, LVLineSetFunction>(&LVLine::setIsPrologueEnd);
- LineFive = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineAssembler);
+ CREATE(LineOne, createLine, setIsLineDebug);
+ CREATE(LineTwo, createLine, setIsBasicBlock);
+ CREATE(LineThree, createLine, setIsNewStatement);
+ CREATE(LineFour, createLine, setIsPrologueEnd);
+ CREATE(LineFive, createLine, setIsLineAssembler);
}
// Create the logical view adding the created logical elements.
namespace {
-class MyLocation;
+class MyLocation : public LVLocation {
+public:
+ bool validateRanges();
+};
// This code emulates the work done by the Readers when processing the
// binary files and the creation of the AddressToLine mapping is done
MyAddressToLine AddressToLine;
class ReaderTestWarningInternal : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr);
+
+#define CREATE_CUSTOM(VARIABLE, CREATE_FUNCTION) \
+ VARIABLE = CREATE_FUNCTION(); \
+ EXPECT_NE(VARIABLE, nullptr);
+
// Types.
LVType *IntegerType = nullptr;
MyLocation *LocationFive = nullptr;
MyLocation *LocationSix = nullptr;
+ llvm::SpecificBumpPtrAllocator<MyLocation> AllocatedLocations;
+
protected:
- void add(LVScope *Parent, LVElement *Element);
- template <typename T> T *create() {
- T *Element = new (std::nothrow) T();
- EXPECT_NE(Element, nullptr);
- return Element;
+ MyLocation *createCustomLocation() {
+ return new (AllocatedLocations.Allocate()) MyLocation();
}
+
+ void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
+ void add(LVScope *Parent, LVElement *Element);
void set(LVElement *Element, StringRef Name, LVOffset Offset,
uint32_t LineNumber = 0, LVElement *Type = nullptr);
void set(MyLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
LVAddress LowerAddress, LVAddress UpperAddress);
- void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
public:
ReaderTestWarningInternal(ScopedPrinter &W) : LVReader("", "", W) {
void checkWarnings();
};
-class MyLocation : public LVLocation {
-public:
- bool validateRanges();
-};
-
bool MyLocation::validateRanges() {
// Traverse the locations and validate them against the address to line
// mapping in the current compile unit. Record those invalid ranges.
EXPECT_NE(Root, nullptr);
// Create the logical types.
- IntegerType = create<LVType>();
+ CREATE(IntegerType, createType);
// Create the logical scopes.
- NestedScope = create<LVScope>();
- CompileUnit = create<LVScopeCompileUnit>();
- Function = create<LVScopeFunction>();
+ CREATE(NestedScope, createScope);
+ CREATE(CompileUnit, createScopeCompileUnit);
+ CREATE(Function, createScopeFunction);
// Create the logical symbols.
- LocalVariable = create<LVSymbol>();
- NestedVariable = create<LVSymbol>();
- Parameter = create<LVSymbol>();
+ CREATE(LocalVariable, createSymbol);
+ CREATE(NestedVariable, createSymbol);
+ CREATE(Parameter, createSymbol);
// Create the logical lines.
- LineOne = create<LVLine>();
- LineTwo = create<LVLine>();
- LineThree = create<LVLine>();
- LineFour = create<LVLine>();
- LineFive = create<LVLine>();
- LineSix = create<LVLine>();
+ CREATE(LineOne, createLine);
+ CREATE(LineTwo, createLine);
+ CREATE(LineThree, createLine);
+ CREATE(LineFour, createLine);
+ CREATE(LineFive, createLine);
+ CREATE(LineSix, createLine);
// Create the logical locations.
- LocationOne = create<MyLocation>();
- LocationTwo = create<MyLocation>();
- LocationThree = create<MyLocation>();
- LocationFour = create<MyLocation>();
- LocationFive = create<MyLocation>();
- LocationSix = create<MyLocation>();
+ CREATE_CUSTOM(LocationOne, createCustomLocation);
+ CREATE_CUSTOM(LocationTwo, createCustomLocation);
+ CREATE_CUSTOM(LocationThree, createCustomLocation);
+ CREATE_CUSTOM(LocationFour, createCustomLocation);
+ CREATE_CUSTOM(LocationFive, createCustomLocation);
+ CREATE_CUSTOM(LocationSix, createCustomLocation);
}
// Create the logical view adding the created logical elements.
LVOffsetLinesMap::iterator IterZero = LinesZero.begin();
EXPECT_EQ(IterZero->first, Function->getOffset());
- LVLines *Lines = IterZero->second;
+ LVLines *Lines = &IterZero->second;
EXPECT_NE(Lines, nullptr);
ASSERT_EQ(Lines->size(), 1u);
LVLine *Line = *(Lines->begin());
++IterZero;
EXPECT_EQ(IterZero->first, NestedScope->getOffset());
- Lines = IterZero->second;
+ Lines = &IterZero->second;
EXPECT_NE(Lines, nullptr);
ASSERT_EQ(Lines->size(), 1u);
Line = *(Lines->begin());
LVOffsetLocationsMap::iterator IterRange = InvalidRanges.begin();
EXPECT_EQ(IterRange->first, Function->getOffset());
- LVLocations *Locations = IterRange->second;
+ LVLocations *Locations = &IterRange->second;
EXPECT_NE(Locations, nullptr);
ASSERT_EQ(Locations->size(), 1u);
LVLocation *Location = *(Locations->begin());
LVOffsetLocationsMap::iterator IterLocations = InvalidLocations.begin();
EXPECT_EQ(IterLocations->first, NestedVariable->getOffset());
- Locations = IterLocations->second;
+ Locations = &IterLocations->second;
EXPECT_NE(Locations, nullptr);
ASSERT_EQ(Locations->size(), 1u);
Location = *(Locations->begin());