[PATCH] D125778: [llvm-debuginfo-analyzer] 03 - Logical elements
Carlos Alberto Enciso via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 22 09:34:09 PDT 2022
CarlosAlbertoEnciso added inline comments.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVLine.h:84
+ void print(raw_ostream &OS, bool Full = true) const override;
+ void printExtra(raw_ostream &OS, bool Full = true) const override{};
+
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h:155
+ // The parent of this object (nullptr if the root scope). For locations,
+ // the parent it is a symbol object; otherwise is a scope object.
+ union {
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h:108
+ virtual void printSizes(raw_ostream &OS) const {};
+ virtual void printSummary(raw_ostream &OS) const {};
+
----------------
probinson wrote:
> No `;` after the `{}`
Changed.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h:236
+ void printExtra(raw_ostream &OS, bool Full = true) const override;
+ virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements){};
+
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h:518
+
+// Class to represent a DWARF subroutine function.
+class LVScopeFunctionType final : public LVScopeFunction {
----------------
probinson wrote:
> Did you mean "subroutine type"?
Yes. Changed to `// Class to represent a DWARF subroutine type.`
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h:552
+
+class LVScopeRoot final : public LVScope {
+ size_t FileFormatNameIndex = 0;
----------------
probinson wrote:
> Needs comment saying what does LVScopeRoot represent.
Added `// Class to represent the binary file being analyzed.`
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h:39
+ for (auto *Item : *this)
+ delete Item;
+ }
----------------
probinson wrote:
> This appears to be assuming that the vector elements are pointers? And the memory for the pointed-to objects is owned by the vector? I'd think it would be simpler to have a SmallVector of objects, not pointers-to-objects, in which case SmallVector takes care of destroying them for you.
> (Or, use a SmallVector of smart pointers.)
>
> If you really want a SmallVector of normal pointers, then the template needs to guarantee that T is a pointer type, somehow. But this all feels rather fragile.
The `LVAutoSmallVector` is used to record the created logical elements (`LVScope`, `LVSymbol`, etc) which currently are created by `new` and to do the automatic destroy.
Once the patches are accepted, one the tasks is to use Small pointers across all patches and `LVAutoSmallVector` will be replaced with SmallVector of smart pointers.
Adding the check to guarantee that `T` is a pointer type.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h:51
+ void set(T Idx) {
+ assert(static_cast<unsigned>(Idx) < static_cast<unsigned>(T::LastEntry) &&
+ "Invalid property");
----------------
probinson wrote:
> I think the `static_cast<unsigned>` should be unnecessary? because Idx has type T, therefore `Idx < T::LastEntry` should work correctly.
> Same comment in the other methods.
>
> Actually, you could defer the bounds checking to SmallBitVector's `operator[]` and remove a lot of this code. For example
> ```
> void set(T Idx) {
> Bits[static_cast<unsigned>(Idx)] = 1;
> }
> ```
Nice code reduction. Changed to use `operator[]`.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h:64
+ assert(static_cast<unsigned>(Idx) < static_cast<unsigned>(T::LastEntry) &&
+ "Invalid property");
+ return Bits[static_cast<unsigned>(Idx)];
----------------
probinson wrote:
> This assert is redundant, `SmallBitVector::operator[]` does the same assertion.
Nice code reduction. Changed to use `operator[]` for the `reset` method as well.
================
Comment at: llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h:88
+ assert((!Element || (Element && static_cast<LVSymbol *>(Element))) &&
+ "Invalid element");
+ setReference(static_cast<LVSymbol *>(Element));
----------------
probinson wrote:
> This assertion looks a little strange. I think it's trying to verify that Element is either null, or is-a LVSymbol. In that case the assert would be
> `assert((!Element || dyn_cast<LVSymbol *>(Element)) && "Invalid element");`
Good point.
I think the correct form is:
`assert((!Element || dyn_cast<LVSymbol>(Element)) && "Invalid element");`
Changed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp:28
+ : nullptr;
+}
+
----------------
probinson wrote:
> If the LVElement hierarchy is set up for LLVM-style casting, then this could be just `return dyn_cast<LVType *>(ElementType);`
I see your point. But in this case we are not relying on the LVElement hierarchy.
```
class LVElement {
PROPERTY(Property, IsType);
// Type of this element.
LVElement *ElementType = nullptr;
};
```
We are returning the `ElementType` that can be a `LVType` or a `LVScope` and it is determined by the `PROPERTY IsType/IsScope`.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp:33
+ ? static_cast<LVScope *>(ElementType)
+ : nullptr;
+}
----------------
probinson wrote:
> If the LVElement hierarchy is set up for LLVM-style casting, then this could be just `return dyn_cast<LVScope *>(ElementType);`
Same as above comments.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp:97
+void LVElement::setFilename(StringRef Filename) {
+ // Get index for the flatted out filename.
+ FilenameIndex = getStringIndex(Filename);
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp:40
+const char *LVLine::kind() const {
+ static const char *Kind = KindUndefined;
+ if (getIsLineDebug())
----------------
probinson wrote:
> `Kind` doesn't need to be `static` here.
Removed `static`.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:56
+const char *LVScope::kind() const {
+ static const char *Kind = KindUndefined;
+ if (getIsArray())
----------------
probinson wrote:
> `Kind` doesn't need to be `static` here.
Removed `static`.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:411
+StringRef LVScope::resolveReferencesChain() {
+ // If the scope have a DW_AT_specification or DW_AT_abstract_origin,
+ // follow the chain to resolve the name from those references.
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:638
+ while (Parent) {
+ // Terminates if the 'SetFunction' have been already executed.
+ if ((Parent->*GetFunction)())
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:652
+ while (Parent) {
+ // Terminates if the 'SetFunction' have been already executed.
+ if ((Parent->*GetFunction)())
----------------
probinson wrote:
>
Changed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:930
+ float Percentage =
+ rint((float(Size) / CUContributionSize) * 100.0 * 100.0) / 100.0;
+ OS << format("%10d (%6.2f%%) : ", Size, Percentage);
----------------
probinson wrote:
> Did this solve a real problem? I would expect this expression to be folded to
> `rint((float(Size) / CUContributionSize) * 100.0)`
> but maybe my notion of floating-point constant folding is too naive.
>
It solved the issue of differences in the percentage when analyzing the same binary on Windows and Linux. For some cases:
```
Expect value:
Totals by lexical level:
[001]: 106 (100.00%)
[002]: 71 ( 66.99%) <---
[003]: 20 ( 18.87%)
```
```
Actual value
Totals by lexical level:
[001]: 106 (100.00%)
[002]: 71 ( 66.98%) <---
[003]: 20 ( 18.87%)
```
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:1086
+ const_cast<LVScopeCompileUnit *>(this)->Found.reset();
+ const_cast<LVScopeCompileUnit *>(this)->Printed.reset();
+
----------------
probinson wrote:
> Looks like the method shouldn't be declared const. Ordinarily you wouldn't think a print() method would be non-const, but obviously this one is.
All the `print` methods for the logical elements are marked as `const`. Only this one requires to modify some class members (stats).
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp:1145
+ if (Scope->getHasReferenceAbstract() && !Scope->getAddedMissing())
+ // Add missing elements at the function nested scopes.
+ Scope->addMissingElements(Scope->getReference());
----------------
probinson wrote:
> This looks like it just repeats the comment from a few lines above.
Removed.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVSupport.cpp:23
+
+// Transforms '\\' into '/' (Platform independent).
+std::string llvm::logicalview::transformPath(StringRef Path) {
----------------
probinson wrote:
> There should be existing functions in Support for this.
The only similar function in `Support` is `Path.cpp::native`
But we need additional changes to the given `Path`.
Added the comments for further clarification:
```
// Perform the following transformations to the given 'Path':
// - all characters to lowercase.
// - '\\' into '/' (Platform independent).
// - '//' into '/'
```
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp:35
+const char *LVSymbol::kind() const {
+ static const char *Kind = KindUndefined;
+ if (getIsCallSiteParameter())
----------------
probinson wrote:
> `Kind` doesn't need to be `static` here.
Removed `static`.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp:48
+const char *LVType::kind() const {
+ static const char *Kind = KindUndefined;
+ if (getIsBase())
----------------
probinson wrote:
> `Kind` doesn't need to be `static` here.
Removed `static`.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp:90
+ // any reference tags, such as DW_AT_specification, DW_AT_abstract_origin,
+ // DW_AT_extension.
+
----------------
probinson wrote:
> This comment might belong in another patch? It doesn't seem to describe anything in this method.
The comment is intended to explain that a `LVType` does not have references to any DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension, etc.
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp:134
+ // In the case of unnamed types, try to generate a name for it, using
+ // the parents name and the line information. Ignore the template
+ if (!isNamed() && !getIsTemplateParam())
----------------
probinson wrote:
> Ignore the template parameters. (?)
Correct. Changed to `Ignore the template parameters.`
================
Comment at: llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp:273
+ } else
+ Name.append(std::string(ArgType->getName()));
+ } else {
----------------
probinson wrote:
> Even though it's a one-line else clause, please put `{}` around it so that the next line doesn't look like incorrect indentation.
Added `{}`.
================
Comment at: llvm/unittests/DebugInfo/LogicalView/LogicalElementsTest.cpp:65
+ T *Element = new (std::nothrow) T();
+ EXPECT_NE(Element, nullptr);
+ return Element;
----------------
probinson wrote:
> I think `ASSERT_NE` here would be better; bail out of the test in a controlled way if the `new` returns nullptr. Otherwise you'll just get a segfault somewhere later that will be harder to diagnose.
`ASSERT_NE` can be used only inside functions that don't return a value.
See https://google.github.io/googletest/advanced.html#assertion-placement
> The one constraint is that assertions that generate a fatal failure (FAIL* and ASSERT_*) can only be used in void-returning functions.
================
Comment at: llvm/unittests/DebugInfo/LogicalView/LogicalElementsTest.cpp:111
+ Root = getScopesRoot();
+ EXPECT_NE(Root, nullptr);
+
----------------
probinson wrote:
> I think `ASSERT_NE` here too.
`ASSERT_NE` can be used only inside functions that don't return a value.
See https://google.github.io/googletest/advanced.html#assertion-placement
> The one constraint is that assertions that generate a fatal failure (FAIL* and ASSERT_*) can only be used in void-returning functions.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D125778/new/
https://reviews.llvm.org/D125778
More information about the llvm-commits
mailing list