Index: llvm/test/tools/llvm-dwarfdump/X86/locstats-big-number-of-bytes.yaml =================================================================== --- /dev/null +++ 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 Index: llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/locstats-for-absctract-origin-vars.yaml +++ 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, Index: llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test +++ llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test @@ -69,7 +69,7 @@ # } # -CHECK: "version": 8, +CHECK: "version": 9, CHECK: "#functions": 3, CHECK: "#functions with location": 3, CHECK: "#inlined functions": 7, Index: llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test +++ llvm/test/tools/llvm-dwarfdump/X86/statistics-v3.test @@ -64,7 +64,7 @@ # } # -CHECK: "version": 8, +CHECK: "version": 9, CHECK: "#functions": 3, CHECK: "#functions with location": 3, CHECK: "#inlined functions": 8, Index: llvm/test/tools/llvm-dwarfdump/X86/statistics.ll =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/statistics.ll +++ 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; Index: llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/stats-scope-bytes-covered.yaml +++ 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 Index: llvm/tools/llvm-dwarfdump/Statistics.cpp =================================================================== --- llvm/tools/llvm-dwarfdump/Statistics.cpp +++ llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -40,18 +40,18 @@ /// 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 +59,63 @@ /// 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; + uint64_t TotalBytesCovered = 0; /// Total number of parent DIE PC range bytes covered by DW_AT_Locations. - unsigned ScopeBytesCovered = 0; + uint64_t ScopeBytesCovered = 0; /// Total number of PC range bytes in each variable's enclosing scope. - unsigned ScopeBytes = 0; + uint64_t 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; + uint64_t ScopeEntryValueBytesCovered = 0; /// Total number of PC range bytes covered by DW_AT_locations of /// formal parameters. - unsigned ParamScopeBytesCovered = 0; + uint64_t ParamScopeBytesCovered = 0; /// Total number of PC range bytes in each parameter's enclosing scope. - unsigned ParamScopeBytes = 0; + uint64_t 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; + uint64_t ParamScopeEntryValueBytesCovered = 0; /// Total number of PC range bytes covered by DW_AT_locations (only for local /// variables). - unsigned LocalVarScopeBytesCovered = 0; + uint64_t LocalVarScopeBytesCovered = 0; /// Total number of PC range bytes in each local variable's enclosing scope. - unsigned LocalVarScopeBytes = 0; + uint64_t 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; + uint64_t LocalVarScopeEntryValueBytesCovered = 0; /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line). - unsigned CallSiteEntries = 0; + uint64_t CallSiteEntries = 0; /// Total number of call site DIEs (DW_TAG_call_site). - unsigned CallSiteDIEs = 0; + uint64_t CallSiteDIEs = 0; /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter). - unsigned CallSiteParamDIEs = 0; + uint64_t CallSiteParamDIEs = 0; /// Total byte size of concrete functions. This byte size includes /// inline functions contained in the concrete functions. - unsigned FunctionSize = 0; + uint64_t 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; + uint64_t InlineFunctionSize = 0; }; /// Holds accumulated debug location statistics about local variables and @@ -126,37 +126,37 @@ /// 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 VarParamLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector VarParamLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// Map non debug entry values coverage. - std::vector VarParamNonEntryValLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector VarParamNonEntryValLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// The debug location statistics for formal parameters. - std::vector ParamLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector ParamLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// Map non debug entry values coverage for formal parameters. - std::vector ParamNonEntryValLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector ParamNonEntryValLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// The debug location statistics for local variables. - std::vector LocalVarLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector LocalVarLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// Map non debug entry values coverage for local variables. - std::vector LocalVarNonEntryValLocStats{ - std::vector(NumOfCoverageCategories, 0)}; + std::vector LocalVarNonEntryValLocStats{ + std::vector(NumOfCoverageCategories, 0)}; /// Total number of local variables and function parameters processed. - unsigned NumVarParam = 0; + uint64_t NumVarParam = 0; /// Total number of formal parameters processed. - unsigned NumParam = 0; + uint64_t NumParam = 0; /// Total number of local variables processed. - unsigned NumVar = 0; + uint64_t NumVar = 0; }; } // namespace /// Collect debug location statistics for one DIE. static void collectLocStats(uint64_t ScopeBytesCovered, uint64_t BytesInScope, - std::vector &VarParamLocStats, - std::vector &ParamLocStats, - std::vector &LocalVarLocStats, + std::vector &VarParamLocStats, + std::vector &ParamLocStats, + std::vector &LocalVarLocStats, bool IsParam, bool IsLocalVar) { auto getCoverageBucket = [ScopeBytesCovered, BytesInScope]() -> unsigned { // No debug location at all for the variable. @@ -376,8 +376,15 @@ GlobalStats.TotalBytesCovered += TotalBytesCovered; if (BytesInScope) { + assert(GlobalStats.ScopeBytesCovered <= UINT64_MAX - ScopeBytesCovered && + "ScopeBytesCovered - overflow"); GlobalStats.ScopeBytesCovered += ScopeBytesCovered; + assert(GlobalStats.ScopeBytes <= UINT64_MAX - BytesInScope && + "ScopeBytes - overflow"); GlobalStats.ScopeBytes += BytesInScope; + assert(GlobalStats.ScopeEntryValueBytesCovered <= + UINT64_MAX - BytesEntryValuesCovered && + "ScopeEntryValueBytesCovered - overflow"); GlobalStats.ScopeEntryValueBytesCovered += BytesEntryValuesCovered; if (IsParam) { GlobalStats.ParamScopeBytesCovered += ScopeBytesCovered; @@ -608,7 +615,7 @@ } static void printLocationStats(json::OStream &J, const char *Key, - std::vector &LocationStats) { + std::vector &LocationStats) { J.attribute( (Twine(Key) + " with 0% of parent scope covered by DW_AT_location").str(), LocationStats[0]); @@ -750,31 +757,31 @@ /// 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; + uint64_t VarParamTotal = 0; + uint64_t VarParamUnique = 0; + uint64_t VarParamWithLoc = 0; + uint64_t NumFunctions = 0; + uint64_t NumInlinedFunctions = 0; + uint64_t NumFuncsWithSrcLoc = 0; + uint64_t NumAbstractOrigins = 0; + uint64_t ParamTotal = 0; + uint64_t ParamWithType = 0; + uint64_t ParamWithLoc = 0; + uint64_t ParamWithSrcLoc = 0; + uint64_t LocalVarTotal = 0; + uint64_t LocalVarWithType = 0; + uint64_t LocalVarWithSrcLoc = 0; + uint64_t 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();