[llvm] c450e47 - [llvm-dwarfdump] Fix unsigned overflow when calculating stats
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 15 03:16:15 PDT 2021
Author: djtodoro
Date: 2021-10-15T12:15:58+02:00
New Revision: c450e47a8c2d7f73ddeb370725e163d418e215e7
URL: https://github.com/llvm/llvm-project/commit/c450e47a8c2d7f73ddeb370725e163d418e215e7
DIFF: https://github.com/llvm/llvm-project/commit/c450e47a8c2d7f73ddeb370725e163d418e215e7.diff
LOG: [llvm-dwarfdump] Fix unsigned overflow when calculating stats
This fixes https://bugs.llvm.org/show_bug.cgi?id=51652.
The idea is to bump all the stat fields to 64-bit wide
unsigned integers. I've confirmed this resolves
the use case for chromium.
Differential Revision: https://reviews.llvm.org/D109217
Added:
llvm/test/tools/llvm-dwarfdump/X86/locstats-big-number-of-bytes.yaml
llvm/test/tools/llvm-dwarfdump/X86/locstats-bytes-overflow.yaml
Modified:
llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml
llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test
llvm/test/tools/llvm-dwarfdump/X86/statistics.ll
llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml
llvm/tools/llvm-dwarfdump/Statistics.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/locstats-big-number-of-bytes.yaml b/llvm/test/tools/llvm-dwarfdump/X86/locstats-big-number-of-bytes.yaml
new file mode 100644
index 0000000000000..76cb9d115ef3b
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/locstats-big-number-of-bytes.yaml
@@ -0,0 +1,92 @@
+# RUN: yaml2obj %s | llvm-dwarfdump --statistics - | FileCheck %s
+
+## Check that we are covering the situation when
+## sum of bytes in scope is a huge (uint64_t) number.
+##
+## The yaml represents this DWARF:
+##
+## DW_TAG_compile_unit
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0x000000000000000b)
+##
+## DW_TAG_subprogram
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0x00000000ffffffff)
+## DW_TAG_variable
+## DW_AT_location (0x00000023:
+## [0x0000000000000003, 0x0000000000000005): DW_OP_reg2 RCX)
+## DW_TAG_subprogram
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0x00000000ffffffff)
+## DW_TAG_variable
+## DW_AT_location (0x00000023:
+## [0x0000000000000003, 0x0000000000000005): DW_OP_reg2 RCX)
+
+# CHECK: "version": 9,
+# CHECK: "sum_all_variables(#bytes in parent scope)": 8589934590
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_loc
+ Type: SHT_PROGBITS
+ AddressAlign: 0x01
+ Content: '00000000000000000600000000000000010055000000000000000000000000000000000300000000000000050000000000000001005200000000000000000000000000000000'
+ - Name: .debug_ranges
+ Type: SHT_PROGBITS
+ AddressAlign: 0x01
+ Content: '000000000000000003000000000000000500000000000000080000000000000000000000000000000000000000000000'
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Code: 1
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data4
+ - Code: 2
+ Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data4
+ - Code: 3
+ Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_location
+ Form: DW_FORM_sec_offset
+ debug_info:
+ - Version: 4
+ AbbrOffset: 0x00
+ Entries:
+ - AbbrCode: 1 ## DW_TAG_compile_unit
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0x0b ## DW_AT_high_pc
+ - AbbrCode: 2 ## DW_TAG_subprogram
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0xFFFFFFFF ## DW_AT_high_pc
+ - AbbrCode: 3 ## DW_TAG_variable
+ Values:
+ - Value: 0x23 ## DW_AT_sec_offset
+ - AbbrCode: 0 ## NULL
+ - AbbrCode: 2 ## DW_TAG_subprogram
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0xFFFFFFFF ## DW_AT_high_pc
+ - AbbrCode: 3 ## DW_TAG_variable
+ Values:
+ - Value: 0x23 ## DW_AT_sec_offset
+ - AbbrCode: 0 ## NULL
+ - AbbrCode: 0 ## NULL
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/locstats-bytes-overflow.yaml b/llvm/test/tools/llvm-dwarfdump/X86/locstats-bytes-overflow.yaml
new file mode 100644
index 0000000000000..0fb82404c72fb
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/locstats-bytes-overflow.yaml
@@ -0,0 +1,90 @@
+# RUN: yaml2obj %s | llvm-dwarfdump --statistics - 2>&1 | FileCheck %s
+
+## Check that we are covering the situation when a stat field overflows.
+##
+## The yaml represents this DWARF:
+##
+## DW_TAG_compile_unit
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0x000000000000000b)
+##
+## DW_TAG_subprogram
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0xffffffffffffffff)
+## DW_TAG_variable
+## DW_AT_location (0x00000023:
+## [0x0000000000000003, 0x0000000000000005): DW_OP_reg2 RCX)
+## DW_TAG_subprogram
+## DW_AT_low_pc (0x0000000000000000)
+## DW_AT_high_pc (0xffffffffffffffff)
+## DW_TAG_variable
+## DW_AT_location (0x00000023:
+## [0x0000000000000003, 0x0000000000000005): DW_OP_reg2 RCX)
+
+# CHECK: "sum_all_variables(#bytes in parent scope)": "overflowed"
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS[[BITS=64]]
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_loc
+ Type: SHT_PROGBITS
+ AddressAlign: 0x01
+ Content: '00000000000000000600000000000000010055000000000000000000000000000000000300000000000000050000000000000001005200000000000000000000000000000000'
+ - Name: .debug_ranges
+ Type: SHT_PROGBITS
+ AddressAlign: 0x01
+ Content: '000000000000000003000000000000000500000000000000080000000000000000000000000000000000000000000000'
+DWARF:
+ debug_abbrev:
+ - Table:
+ - Code: 1
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Code: 2
+ Tag: DW_TAG_subprogram
+ Children: DW_CHILDREN_yes
+ Attributes:
+ - Attribute: DW_AT_low_pc
+ Form: DW_FORM_addr
+ - Attribute: DW_AT_high_pc
+ Form: DW_FORM_data8
+ - Code: 3
+ Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_location
+ Form: DW_FORM_sec_offset
+ debug_info:
+ - Version: 4
+ AbbrOffset: 0x00
+ Entries:
+ - AbbrCode: 1 ## DW_TAG_compile_unit
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0x0b ## DW_AT_high_pc
+ - AbbrCode: 2 ## DW_TAG_subprogram
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0xFFFFFFFFFFFFFFFF ## DW_AT_high_pc
+ - AbbrCode: 3 ## DW_TAG_variable
+ Values:
+ - Value: 0x23 ## DW_AT_sec_offset
+ - AbbrCode: 0 ## NULL
+ - AbbrCode: 2 ## DW_TAG_subprogram
+ Values:
+ - Value: 0x00 ## DW_AT_low_pc
+ - Value: 0xFFFFFFFFFFFFFFFF ## DW_AT_high_pc
+ - AbbrCode: 3 ## DW_TAG_variable
+ Values:
+ - Value: 0x23 ## DW_AT_sec_offset
+ - AbbrCode: 0 ## NULL
+ - AbbrCode: 0 ## NULL
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml b/llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml
index 8a1e1af4a7630..458b556856eba 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml
+++ b/llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml
@@ -120,7 +120,7 @@
## DW_TAG_subprogram
## DW_AT_abstract_origin (0x000000f0)
-# CHECK: "version": 8,
+# CHECK: "version": 9,
# CHECK: "#variables processed by location statistics": 17,
# CHECK: "#variables with 0% of parent scope covered by DW_AT_location": 13,
# CHECK: "#variables with 100% of parent scope covered by DW_AT_location": 4,
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test b/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
index 8d6700562fe31..3e39591c46dce 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
@@ -69,7 +69,7 @@ RUN: llvm-dwarfdump --statistics statistics-fib.split-dwarf.o | FileCheck %s
# }
#
-CHECK: "version": 8,
+CHECK: "version": 9,
CHECK: "#functions": 3,
CHECK: "#functions with location": 3,
CHECK: "#inlined functions": 7,
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test b/llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test
index a2a495c1346ce..855dcedc76f0b 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test
@@ -64,7 +64,7 @@ RUN: llvm-dwarfdump --statistics %t-statistics-fib.o | FileCheck %s
# }
#
-CHECK: "version": 8,
+CHECK: "version": 9,
CHECK: "#functions": 3,
CHECK: "#functions with location": 3,
CHECK: "#inlined functions": 8,
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/statistics.ll b/llvm/test/tools/llvm-dwarfdump/X86/statistics.ll
index ced2f4686b59e..08d1d25286ec6 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/statistics.ll
+++ b/llvm/test/tools/llvm-dwarfdump/X86/statistics.ll
@@ -1,6 +1,6 @@
; RUN: llc -O0 %s -o - -filetype=obj \
; RUN: | llvm-dwarfdump -statistics - | FileCheck %s
-; CHECK: "version": 8,
+; CHECK: "version": 9,
; namespace test {
; extern int a;
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml b/llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml
index 5be144113c709..3d4e9d33f24ab 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml
+++ b/llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml
@@ -33,7 +33,7 @@
## DW_AT_location (0x00000023:
## [0x0000000000000003, 0x0000000000000005): DW_OP_reg2 RCX)
-# CHECK: "version": 8,
+# CHECK: "version": 9,
# CHECK: "sum_all_variables(#bytes in parent scope)": 12,
# CHECK: "sum_all_variables(#bytes in any scope covered by DW_AT_location)": 8
# CHECK: "sum_all_variables(#bytes in parent scope covered by DW_AT_location)": 4
diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index 19a971afa3111..8e91a6be7b084 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -29,6 +29,9 @@ constexpr int NumOfCoverageCategories = 12;
/// This is used for zero location coverage bucket.
constexpr unsigned ZeroCoverageBucket = 0;
+/// The UINT64_MAX is used as an indication of the overflow.
+constexpr uint64_t OverflowValue = std::numeric_limits<uint64_t>::max();
+
/// This represents variables DIE offsets.
using AbstractOriginVarsTy = llvm::SmallVector<uint64_t>;
/// This maps function DIE offset to its variables.
@@ -36,22 +39,43 @@ using AbstractOriginVarsTyMap = llvm::DenseMap<uint64_t, AbstractOriginVarsTy>;
/// This represents function DIE offsets containing an abstract_origin.
using FunctionsWithAbstractOriginTy = llvm::SmallVector<uint64_t>;
+/// This represents a data type for the stats and it helps us to
+/// detect an overflow.
+/// NOTE: This can be implemented as a template if there is an another type
+/// needing this.
+struct SaturatingUINT64 {
+ /// Number that represents the stats.
+ uint64_t Value;
+
+ SaturatingUINT64(uint64_t Value_) : Value(Value_) {}
+
+ void operator++(int) { return *this += 1; }
+ void operator+=(uint64_t Value_) {
+ if (Value != OverflowValue) {
+ if (Value < OverflowValue - Value_)
+ Value += Value_;
+ else
+ Value = OverflowValue;
+ }
+ }
+};
+
/// Holds statistics for one function (or other entity that has a PC range and
/// contains variables, such as a compile unit).
struct PerFunctionStats {
/// Number of inlined instances of this function.
- unsigned NumFnInlined = 0;
+ uint64_t NumFnInlined = 0;
/// Number of out-of-line instances of this function.
- unsigned NumFnOutOfLine = 0;
+ uint64_t NumFnOutOfLine = 0;
/// Number of inlined instances that have abstract origins.
- unsigned NumAbstractOrigins = 0;
+ uint64_t NumAbstractOrigins = 0;
/// Number of variables and parameters with location across all inlined
/// instances.
- unsigned TotalVarWithLoc = 0;
+ uint64_t TotalVarWithLoc = 0;
/// Number of constants with location across all inlined instances.
- unsigned ConstantMembers = 0;
+ uint64_t ConstantMembers = 0;
/// Number of arificial variables, parameters or members across all instances.
- unsigned NumArtificial = 0;
+ uint64_t NumArtificial = 0;
/// List of all Variables and parameters in this function.
StringSet<> VarsInFunction;
/// Compile units also cover a PC range, but have this flag set to false.
@@ -59,63 +83,63 @@ struct PerFunctionStats {
/// Function has source location information.
bool HasSourceLocation = false;
/// Number of function parameters.
- unsigned NumParams = 0;
+ uint64_t NumParams = 0;
/// Number of function parameters with source location.
- unsigned NumParamSourceLocations = 0;
+ uint64_t NumParamSourceLocations = 0;
/// Number of function parameters with type.
- unsigned NumParamTypes = 0;
+ uint64_t NumParamTypes = 0;
/// Number of function parameters with a DW_AT_location.
- unsigned NumParamLocations = 0;
+ uint64_t NumParamLocations = 0;
/// Number of local variables.
- unsigned NumLocalVars = 0;
+ uint64_t NumLocalVars = 0;
/// Number of local variables with source location.
- unsigned NumLocalVarSourceLocations = 0;
+ uint64_t NumLocalVarSourceLocations = 0;
/// Number of local variables with type.
- unsigned NumLocalVarTypes = 0;
+ uint64_t NumLocalVarTypes = 0;
/// Number of local variables with DW_AT_location.
- unsigned NumLocalVarLocations = 0;
+ uint64_t NumLocalVarLocations = 0;
};
/// Holds accumulated global statistics about DIEs.
struct GlobalStats {
/// Total number of PC range bytes covered by DW_AT_locations.
- unsigned TotalBytesCovered = 0;
+ SaturatingUINT64 TotalBytesCovered = 0;
/// Total number of parent DIE PC range bytes covered by DW_AT_Locations.
- unsigned ScopeBytesCovered = 0;
+ SaturatingUINT64 ScopeBytesCovered = 0;
/// Total number of PC range bytes in each variable's enclosing scope.
- unsigned ScopeBytes = 0;
+ SaturatingUINT64 ScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value).
- unsigned ScopeEntryValueBytesCovered = 0;
+ SaturatingUINT64 ScopeEntryValueBytesCovered = 0;
/// Total number of PC range bytes covered by DW_AT_locations of
/// formal parameters.
- unsigned ParamScopeBytesCovered = 0;
+ SaturatingUINT64 ParamScopeBytesCovered = 0;
/// Total number of PC range bytes in each parameter's enclosing scope.
- unsigned ParamScopeBytes = 0;
+ SaturatingUINT64 ParamScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value) (only for parameters).
- unsigned ParamScopeEntryValueBytesCovered = 0;
+ SaturatingUINT64 ParamScopeEntryValueBytesCovered = 0;
/// Total number of PC range bytes covered by DW_AT_locations (only for local
/// variables).
- unsigned LocalVarScopeBytesCovered = 0;
+ SaturatingUINT64 LocalVarScopeBytesCovered = 0;
/// Total number of PC range bytes in each local variable's enclosing scope.
- unsigned LocalVarScopeBytes = 0;
+ SaturatingUINT64 LocalVarScopeBytes = 0;
/// Total number of PC range bytes covered by DW_AT_locations with
/// the debug entry values (DW_OP_entry_value) (only for local variables).
- unsigned LocalVarScopeEntryValueBytesCovered = 0;
+ SaturatingUINT64 LocalVarScopeEntryValueBytesCovered = 0;
/// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
- unsigned CallSiteEntries = 0;
+ SaturatingUINT64 CallSiteEntries = 0;
/// Total number of call site DIEs (DW_TAG_call_site).
- unsigned CallSiteDIEs = 0;
+ SaturatingUINT64 CallSiteDIEs = 0;
/// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
- unsigned CallSiteParamDIEs = 0;
+ SaturatingUINT64 CallSiteParamDIEs = 0;
/// Total byte size of concrete functions. This byte size includes
/// inline functions contained in the concrete functions.
- unsigned FunctionSize = 0;
+ SaturatingUINT64 FunctionSize = 0;
/// Total byte size of inlined functions. This is the total number of bytes
/// for the top inline functions within concrete functions. This can help
/// tune the inline settings when compiling to match user expectations.
- unsigned InlineFunctionSize = 0;
+ SaturatingUINT64 InlineFunctionSize = 0;
};
/// Holds accumulated debug location statistics about local variables and
@@ -126,37 +150,37 @@ struct LocationStats {
/// of variables with the no debug location at all, but the last element
/// in the vector represents the number of fully covered variables within
/// its scope.
- std::vector<unsigned> VarParamLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> VarParamLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// Map non debug entry values coverage.
- std::vector<unsigned> VarParamNonEntryValLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> VarParamNonEntryValLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// The debug location statistics for formal parameters.
- std::vector<unsigned> ParamLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> ParamLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// Map non debug entry values coverage for formal parameters.
- std::vector<unsigned> ParamNonEntryValLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> ParamNonEntryValLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// The debug location statistics for local variables.
- std::vector<unsigned> LocalVarLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> LocalVarLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// Map non debug entry values coverage for local variables.
- std::vector<unsigned> LocalVarNonEntryValLocStats{
- std::vector<unsigned>(NumOfCoverageCategories, 0)};
+ std::vector<SaturatingUINT64> LocalVarNonEntryValLocStats{
+ std::vector<SaturatingUINT64>(NumOfCoverageCategories, 0)};
/// Total number of local variables and function parameters processed.
- unsigned NumVarParam = 0;
+ SaturatingUINT64 NumVarParam = 0;
/// Total number of formal parameters processed.
- unsigned NumParam = 0;
+ SaturatingUINT64 NumParam = 0;
/// Total number of local variables processed.
- unsigned NumVar = 0;
+ SaturatingUINT64 NumVar = 0;
};
} // namespace
/// Collect debug location statistics for one DIE.
static void collectLocStats(uint64_t ScopeBytesCovered, uint64_t BytesInScope,
- std::vector<unsigned> &VarParamLocStats,
- std::vector<unsigned> &ParamLocStats,
- std::vector<unsigned> &LocalVarLocStats,
+ std::vector<SaturatingUINT64> &VarParamLocStats,
+ std::vector<SaturatingUINT64> &ParamLocStats,
+ std::vector<SaturatingUINT64> &LocalVarLocStats,
bool IsParam, bool IsLocalVar) {
auto getCoverageBucket = [ScopeBytesCovered, BytesInScope]() -> unsigned {
// No debug location at all for the variable.
@@ -173,11 +197,11 @@ static void collectLocStats(uint64_t ScopeBytesCovered, uint64_t BytesInScope,
unsigned CoverageBucket = getCoverageBucket();
- VarParamLocStats[CoverageBucket]++;
+ VarParamLocStats[CoverageBucket].Value++;
if (IsParam)
- ParamLocStats[CoverageBucket]++;
+ ParamLocStats[CoverageBucket].Value++;
else if (IsLocalVar)
- LocalVarLocStats[CoverageBucket]++;
+ LocalVarLocStats[CoverageBucket].Value++;
}
/// Construct an identifier for a given DIE from its Prefix, Name, DeclFileName
@@ -350,11 +374,11 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
// Calculate the debug location statistics.
if (BytesInScope && !DeferLocStats) {
- LocStats.NumVarParam++;
+ LocStats.NumVarParam.Value++;
if (IsParam)
- LocStats.NumParam++;
+ LocStats.NumParam.Value++;
else if (IsLocalVar)
- LocStats.NumVar++;
+ LocStats.NumVar.Value++;
collectLocStats(ScopeBytesCovered, BytesInScope, LocStats.VarParamLocStats,
LocStats.ParamLocStats, LocStats.LocalVarLocStats, IsParam,
@@ -389,7 +413,7 @@ static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
GlobalStats.LocalVarScopeEntryValueBytesCovered +=
BytesEntryValuesCovered;
}
- assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
+ assert(GlobalStats.ScopeBytesCovered.Value <= GlobalStats.ScopeBytes.Value);
}
if (IsConstantMember) {
@@ -603,45 +627,78 @@ static void collectStatsRecursive(
/// Print human-readable output.
/// \{
static void printDatum(json::OStream &J, const char *Key, json::Value Value) {
- J.attribute(Key, Value);
+ if (Value == OverflowValue)
+ J.attribute(Key, "overflowed");
+ else
+ J.attribute(Key, Value);
+
LLVM_DEBUG(llvm::dbgs() << Key << ": " << Value << '\n');
}
static void printLocationStats(json::OStream &J, const char *Key,
- std::vector<unsigned> &LocationStats) {
- J.attribute(
- (Twine(Key) + " with 0% of parent scope covered by DW_AT_location").str(),
- LocationStats[0]);
+ std::vector<SaturatingUINT64> &LocationStats) {
+ if (LocationStats[0].Value == OverflowValue)
+ J.attribute((Twine(Key) +
+ " with (0%,10%) of parent scope covered by DW_AT_location")
+ .str(),
+ "overflowed");
+ else
+ J.attribute(
+ (Twine(Key) + " with 0% of parent scope covered by DW_AT_location")
+ .str(),
+ LocationStats[0].Value);
LLVM_DEBUG(
llvm::dbgs() << Key
<< " with 0% of parent scope covered by DW_AT_location: \\"
- << LocationStats[0] << '\n');
- J.attribute(
- (Twine(Key) + " with (0%,10%) of parent scope covered by DW_AT_location")
- .str(),
- LocationStats[1]);
+ << LocationStats[0].Value << '\n');
+
+ if (LocationStats[1].Value == OverflowValue)
+ J.attribute((Twine(Key) +
+ " with (0%,10%) of parent scope covered by DW_AT_location")
+ .str(),
+ "overflowed");
+ else
+ J.attribute((Twine(Key) +
+ " with (0%,10%) of parent scope covered by DW_AT_location")
+ .str(),
+ LocationStats[1].Value);
LLVM_DEBUG(llvm::dbgs()
<< Key
<< " with (0%,10%) of parent scope covered by DW_AT_location: "
- << LocationStats[1] << '\n');
+ << LocationStats[1].Value << '\n');
+
for (unsigned i = 2; i < NumOfCoverageCategories - 1; ++i) {
- J.attribute((Twine(Key) + " with [" + Twine((i - 1) * 10) + "%," +
- Twine(i * 10) + "%) of parent scope covered by DW_AT_location")
- .str(),
- LocationStats[i]);
+ if (LocationStats[i].Value == OverflowValue)
+ J.attribute((Twine(Key) + " with [" + Twine((i - 1) * 10) + "%," +
+ Twine(i * 10) +
+ "%) of parent scope covered by DW_AT_location")
+ .str(),
+ "overflowed");
+ else
+ J.attribute((Twine(Key) + " with [" + Twine((i - 1) * 10) + "%," +
+ Twine(i * 10) +
+ "%) of parent scope covered by DW_AT_location")
+ .str(),
+ LocationStats[i].Value);
LLVM_DEBUG(llvm::dbgs()
<< Key << " with [" << (i - 1) * 10 << "%," << i * 10
<< "%) of parent scope covered by DW_AT_location: "
- << LocationStats[i]);
+ << LocationStats[i].Value);
}
- J.attribute(
- (Twine(Key) + " with 100% of parent scope covered by DW_AT_location")
- .str(),
- LocationStats[NumOfCoverageCategories - 1]);
+ if (LocationStats[NumOfCoverageCategories - 1].Value == OverflowValue)
+ J.attribute(
+ (Twine(Key) + " with 100% of parent scope covered by DW_AT_location")
+ .str(),
+ "overflowed");
+ else
+ J.attribute(
+ (Twine(Key) + " with 100% of parent scope covered by DW_AT_location")
+ .str(),
+ LocationStats[NumOfCoverageCategories - 1].Value);
LLVM_DEBUG(
llvm::dbgs() << Key
<< " with 100% of parent scope covered by DW_AT_location: "
- << LocationStats[NumOfCoverageCategories - 1]);
+ << LocationStats[NumOfCoverageCategories - 1].Value);
}
static void printSectionSizes(json::OStream &J, const SectionSizes &Sizes) {
@@ -750,31 +807,31 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
/// The version number should be increased every time the algorithm is changed
/// (including bug fixes). New metrics may be added without increasing the
/// version.
- unsigned Version = 8;
- unsigned VarParamTotal = 0;
- unsigned VarParamUnique = 0;
- unsigned VarParamWithLoc = 0;
- unsigned NumFunctions = 0;
- unsigned NumInlinedFunctions = 0;
- unsigned NumFuncsWithSrcLoc = 0;
- unsigned NumAbstractOrigins = 0;
- unsigned ParamTotal = 0;
- unsigned ParamWithType = 0;
- unsigned ParamWithLoc = 0;
- unsigned ParamWithSrcLoc = 0;
- unsigned LocalVarTotal = 0;
- unsigned LocalVarWithType = 0;
- unsigned LocalVarWithSrcLoc = 0;
- unsigned LocalVarWithLoc = 0;
+ unsigned Version = 9;
+ SaturatingUINT64 VarParamTotal = 0;
+ SaturatingUINT64 VarParamUnique = 0;
+ SaturatingUINT64 VarParamWithLoc = 0;
+ SaturatingUINT64 NumFunctions = 0;
+ SaturatingUINT64 NumInlinedFunctions = 0;
+ SaturatingUINT64 NumFuncsWithSrcLoc = 0;
+ SaturatingUINT64 NumAbstractOrigins = 0;
+ SaturatingUINT64 ParamTotal = 0;
+ SaturatingUINT64 ParamWithType = 0;
+ SaturatingUINT64 ParamWithLoc = 0;
+ SaturatingUINT64 ParamWithSrcLoc = 0;
+ SaturatingUINT64 LocalVarTotal = 0;
+ SaturatingUINT64 LocalVarWithType = 0;
+ SaturatingUINT64 LocalVarWithSrcLoc = 0;
+ SaturatingUINT64 LocalVarWithLoc = 0;
for (auto &Entry : Statistics) {
PerFunctionStats &Stats = Entry.getValue();
- unsigned TotalVars = Stats.VarsInFunction.size() *
+ uint64_t TotalVars = Stats.VarsInFunction.size() *
(Stats.NumFnInlined + Stats.NumFnOutOfLine);
// Count variables in global scope.
if (!Stats.IsFunction)
TotalVars =
Stats.NumLocalVars + Stats.ConstantMembers + Stats.NumArtificial;
- unsigned Constants = Stats.ConstantMembers;
+ uint64_t Constants = Stats.ConstantMembers;
VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
VarParamTotal += TotalVars;
VarParamUnique += Stats.VarsInFunction.size();
@@ -806,70 +863,72 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
printDatum(J, "file", Filename.str());
printDatum(J, "format", FormatName);
- printDatum(J, "#functions", NumFunctions);
- printDatum(J, "#functions with location", NumFuncsWithSrcLoc);
- printDatum(J, "#inlined functions", NumInlinedFunctions);
- printDatum(J, "#inlined functions with abstract origins", NumAbstractOrigins);
+ printDatum(J, "#functions", NumFunctions.Value);
+ printDatum(J, "#functions with location", NumFuncsWithSrcLoc.Value);
+ printDatum(J, "#inlined functions", NumInlinedFunctions.Value);
+ printDatum(J, "#inlined functions with abstract origins",
+ NumAbstractOrigins.Value);
// This includes local variables and formal parameters.
- printDatum(J, "#unique source variables", VarParamUnique);
- printDatum(J, "#source variables", VarParamTotal);
- printDatum(J, "#source variables with location", VarParamWithLoc);
+ printDatum(J, "#unique source variables", VarParamUnique.Value);
+ printDatum(J, "#source variables", VarParamTotal.Value);
+ printDatum(J, "#source variables with location", VarParamWithLoc.Value);
- printDatum(J, "#call site entries", GlobalStats.CallSiteEntries);
- printDatum(J, "#call site DIEs", GlobalStats.CallSiteDIEs);
- printDatum(J, "#call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
+ printDatum(J, "#call site entries", GlobalStats.CallSiteEntries.Value);
+ printDatum(J, "#call site DIEs", GlobalStats.CallSiteDIEs.Value);
+ printDatum(J, "#call site parameter DIEs",
+ GlobalStats.CallSiteParamDIEs.Value);
printDatum(J, "sum_all_variables(#bytes in parent scope)",
- GlobalStats.ScopeBytes);
+ GlobalStats.ScopeBytes.Value);
printDatum(J,
"sum_all_variables(#bytes in any scope covered by DW_AT_location)",
- GlobalStats.TotalBytesCovered);
+ GlobalStats.TotalBytesCovered.Value);
printDatum(J,
"sum_all_variables(#bytes in parent scope covered by "
"DW_AT_location)",
- GlobalStats.ScopeBytesCovered);
+ GlobalStats.ScopeBytesCovered.Value);
printDatum(J,
"sum_all_variables(#bytes in parent scope covered by "
"DW_OP_entry_value)",
- GlobalStats.ScopeEntryValueBytesCovered);
+ GlobalStats.ScopeEntryValueBytesCovered.Value);
printDatum(J, "sum_all_params(#bytes in parent scope)",
- GlobalStats.ParamScopeBytes);
+ GlobalStats.ParamScopeBytes.Value);
printDatum(J,
"sum_all_params(#bytes in parent scope covered by DW_AT_location)",
- GlobalStats.ParamScopeBytesCovered);
+ GlobalStats.ParamScopeBytesCovered.Value);
printDatum(J,
"sum_all_params(#bytes in parent scope covered by "
"DW_OP_entry_value)",
- GlobalStats.ParamScopeEntryValueBytesCovered);
+ GlobalStats.ParamScopeEntryValueBytesCovered.Value);
printDatum(J, "sum_all_local_vars(#bytes in parent scope)",
- GlobalStats.LocalVarScopeBytes);
+ GlobalStats.LocalVarScopeBytes.Value);
printDatum(J,
"sum_all_local_vars(#bytes in parent scope covered by "
"DW_AT_location)",
- GlobalStats.LocalVarScopeBytesCovered);
+ GlobalStats.LocalVarScopeBytesCovered.Value);
printDatum(J,
"sum_all_local_vars(#bytes in parent scope covered by "
"DW_OP_entry_value)",
- GlobalStats.LocalVarScopeEntryValueBytesCovered);
+ GlobalStats.LocalVarScopeEntryValueBytesCovered.Value);
- printDatum(J, "#bytes within functions", GlobalStats.FunctionSize);
+ printDatum(J, "#bytes within functions", GlobalStats.FunctionSize.Value);
printDatum(J, "#bytes within inlined functions",
- GlobalStats.InlineFunctionSize);
+ GlobalStats.InlineFunctionSize.Value);
// Print the summary for formal parameters.
- printDatum(J, "#params", ParamTotal);
- printDatum(J, "#params with source location", ParamWithSrcLoc);
- printDatum(J, "#params with type", ParamWithType);
- printDatum(J, "#params with binary location", ParamWithLoc);
+ printDatum(J, "#params", ParamTotal.Value);
+ printDatum(J, "#params with source location", ParamWithSrcLoc.Value);
+ printDatum(J, "#params with type", ParamWithType.Value);
+ printDatum(J, "#params with binary location", ParamWithLoc.Value);
// Print the summary for local variables.
- printDatum(J, "#local vars", LocalVarTotal);
- printDatum(J, "#local vars with source location", LocalVarWithSrcLoc);
- printDatum(J, "#local vars with type", LocalVarWithType);
- printDatum(J, "#local vars with binary location", LocalVarWithLoc);
+ printDatum(J, "#local vars", LocalVarTotal.Value);
+ printDatum(J, "#local vars with source location", LocalVarWithSrcLoc.Value);
+ printDatum(J, "#local vars with type", LocalVarWithType.Value);
+ printDatum(J, "#local vars with binary location", LocalVarWithLoc.Value);
// Print the debug section sizes.
printSectionSizes(J, Sizes);
@@ -877,32 +936,34 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
// Print the location statistics for variables (includes local variables
// and formal parameters).
printDatum(J, "#variables processed by location statistics",
- LocStats.NumVarParam);
+ LocStats.NumVarParam.Value);
printLocationStats(J, "#variables", LocStats.VarParamLocStats);
printLocationStats(J, "#variables - entry values",
LocStats.VarParamNonEntryValLocStats);
// Print the location statistics for formal parameters.
- printDatum(J, "#params processed by location statistics", LocStats.NumParam);
+ printDatum(J, "#params processed by location statistics",
+ LocStats.NumParam.Value);
printLocationStats(J, "#params", LocStats.ParamLocStats);
printLocationStats(J, "#params - entry values",
LocStats.ParamNonEntryValLocStats);
// Print the location statistics for local variables.
printDatum(J, "#local vars processed by location statistics",
- LocStats.NumVar);
+ LocStats.NumVar.Value);
printLocationStats(J, "#local vars", LocStats.LocalVarLocStats);
printLocationStats(J, "#local vars - entry values",
LocStats.LocalVarNonEntryValLocStats);
J.objectEnd();
OS << '\n';
- LLVM_DEBUG(
- llvm::dbgs() << "Total Availability: "
- << (int)std::round((VarParamWithLoc * 100.0) / VarParamTotal)
- << "%\n";
- llvm::dbgs() << "PC Ranges covered: "
- << (int)std::round((GlobalStats.ScopeBytesCovered * 100.0) /
- GlobalStats.ScopeBytes)
- << "%\n");
+ LLVM_DEBUG(llvm::dbgs() << "Total Availability: "
+ << (int)std::round((VarParamWithLoc.Value * 100.0) /
+ VarParamTotal.Value)
+ << "%\n";
+ llvm::dbgs() << "PC Ranges covered: "
+ << (int)std::round(
+ (GlobalStats.ScopeBytesCovered.Value * 100.0) /
+ GlobalStats.ScopeBytes.Value)
+ << "%\n");
return true;
}
More information about the llvm-commits
mailing list