mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-07 00:00:12 +01:00
gallium/tools: implement 'named' pointers option in dump.py
As suggested by zmike in issue #4609, raw pointer values in are problematic for diffing state dumps. In attempt to remedy this, we implement an option --named/-N in dump.py that generates symbolic names for all pointers based on the context. Signed-off-by: Matti Hamalainen <ccr@tnsp.org> Acked-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10648>
This commit is contained in:
parent
054b2afcb9
commit
d730c18bdb
3 changed files with 85 additions and 38 deletions
|
|
@ -36,6 +36,7 @@ import copy
|
|||
import argparse
|
||||
|
||||
import model
|
||||
import format
|
||||
import parse as parser
|
||||
|
||||
|
||||
|
|
@ -706,7 +707,7 @@ class Context(Dispatcher):
|
|||
return so_target
|
||||
|
||||
|
||||
class Interpreter(parser.TraceParser):
|
||||
class Interpreter(parser.SimpleTraceDumper):
|
||||
'''Specialization of a trace parser that interprets the calls as it goes
|
||||
along.'''
|
||||
|
||||
|
|
@ -722,9 +723,8 @@ class Interpreter(parser.TraceParser):
|
|||
('pipe_context', 'flush_resource'),
|
||||
))
|
||||
|
||||
def __init__(self, stream, options):
|
||||
parser.TraceParser.__init__(self, stream)
|
||||
self.options = options
|
||||
def __init__(self, stream, options, formatter):
|
||||
parser.SimpleTraceDumper.__init__(self, stream, options, formatter)
|
||||
self.objects = {}
|
||||
self.result = None
|
||||
self.globl = Global(self)
|
||||
|
|
@ -805,7 +805,8 @@ class Main(parser.Main):
|
|||
return optparser
|
||||
|
||||
def process_arg(self, stream, options):
|
||||
parser = Interpreter(stream, options)
|
||||
formatter = format.Formatter(sys.stderr)
|
||||
parser = Interpreter(stream, options, formatter)
|
||||
parser.parse()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -105,9 +105,23 @@ class Struct(Node):
|
|||
|
||||
class Pointer(Node):
|
||||
|
||||
def __init__(self, address):
|
||||
ptr_list = {}
|
||||
ptr_type_list = {}
|
||||
ptr_types_list = {}
|
||||
|
||||
def __init__(self, address, pname):
|
||||
self.address = address
|
||||
|
||||
if address not in self.ptr_list or (self.ptr_type_list[address] == "ret" and pname != "ret"):
|
||||
if pname not in self.ptr_types_list:
|
||||
self.ptr_types_list[pname] = 1
|
||||
else:
|
||||
self.ptr_types_list[pname] += 1
|
||||
|
||||
tmp = "{}_{}".format(pname, self.ptr_types_list[pname])
|
||||
self.ptr_list[address] = tmp
|
||||
self.ptr_type_list[address] = pname
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_pointer(self)
|
||||
|
||||
|
|
@ -166,7 +180,6 @@ class PrettyPrinter:
|
|||
|
||||
def __init__(self, formatter, options):
|
||||
self.formatter = formatter
|
||||
|
||||
self.options = options
|
||||
|
||||
def visit_literal(self, node):
|
||||
|
|
@ -207,7 +220,10 @@ class PrettyPrinter:
|
|||
self.formatter.text('}')
|
||||
|
||||
def visit_pointer(self, node):
|
||||
self.formatter.address(node.address)
|
||||
if "named_ptrs" in self.options and self.options.named_ptrs:
|
||||
self.formatter.address(node.ptr_list[node.address])
|
||||
else:
|
||||
self.formatter.address(node.address)
|
||||
|
||||
def visit_call(self, node):
|
||||
if not self.options.suppress_variants:
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import sys
|
|||
import xml.parsers.expat as xpat
|
||||
import argparse
|
||||
|
||||
import format
|
||||
from model import *
|
||||
|
||||
|
||||
|
|
@ -236,134 +237,151 @@ class TraceParser(XmlParser):
|
|||
def parse_arg(self):
|
||||
attrs = self.element_start('arg')
|
||||
name = attrs['name']
|
||||
value = self.parse_value()
|
||||
value = self.parse_value(name)
|
||||
self.element_end('arg')
|
||||
|
||||
return name, value
|
||||
|
||||
def parse_ret(self):
|
||||
attrs = self.element_start('ret')
|
||||
value = self.parse_value()
|
||||
value = self.parse_value('ret')
|
||||
self.element_end('ret')
|
||||
|
||||
return value
|
||||
|
||||
def parse_time(self):
|
||||
attrs = self.element_start('time')
|
||||
time = self.parse_value();
|
||||
time = self.parse_value('time');
|
||||
self.element_end('time')
|
||||
return time
|
||||
|
||||
def parse_value(self):
|
||||
def parse_value(self, name):
|
||||
expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes')
|
||||
if self.token.type == ELEMENT_START:
|
||||
if self.token.name_or_data in expected_tokens:
|
||||
method = getattr(self, 'parse_' + self.token.name_or_data)
|
||||
return method()
|
||||
return method(name)
|
||||
raise TokenMismatch(" or " .join(expected_tokens), self.token)
|
||||
|
||||
def parse_null(self):
|
||||
def parse_null(self, pname):
|
||||
self.element_start('null')
|
||||
self.element_end('null')
|
||||
return Literal(None)
|
||||
|
||||
def parse_bool(self):
|
||||
def parse_bool(self, pname):
|
||||
self.element_start('bool')
|
||||
value = int(self.character_data())
|
||||
self.element_end('bool')
|
||||
return Literal(value)
|
||||
|
||||
def parse_int(self):
|
||||
def parse_int(self, pname):
|
||||
self.element_start('int')
|
||||
value = int(self.character_data())
|
||||
self.element_end('int')
|
||||
return Literal(value)
|
||||
|
||||
def parse_uint(self):
|
||||
def parse_uint(self, pname):
|
||||
self.element_start('uint')
|
||||
value = int(self.character_data())
|
||||
self.element_end('uint')
|
||||
return Literal(value)
|
||||
|
||||
def parse_float(self):
|
||||
def parse_float(self, pname):
|
||||
self.element_start('float')
|
||||
value = float(self.character_data())
|
||||
self.element_end('float')
|
||||
return Literal(value)
|
||||
|
||||
def parse_enum(self):
|
||||
def parse_enum(self, pname):
|
||||
self.element_start('enum')
|
||||
name = self.character_data()
|
||||
self.element_end('enum')
|
||||
return NamedConstant(name)
|
||||
|
||||
def parse_string(self):
|
||||
def parse_string(self, pname):
|
||||
self.element_start('string')
|
||||
value = self.character_data()
|
||||
self.element_end('string')
|
||||
return Literal(value)
|
||||
|
||||
def parse_bytes(self):
|
||||
def parse_bytes(self, pname):
|
||||
self.element_start('bytes')
|
||||
value = self.character_data()
|
||||
self.element_end('bytes')
|
||||
return Blob(value)
|
||||
|
||||
def parse_array(self):
|
||||
def parse_array(self, pname):
|
||||
self.element_start('array')
|
||||
elems = []
|
||||
while self.token.type != ELEMENT_END:
|
||||
elems.append(self.parse_elem())
|
||||
elems.append(self.parse_elem('array'))
|
||||
self.element_end('array')
|
||||
return Array(elems)
|
||||
|
||||
def parse_elem(self):
|
||||
def parse_elem(self, pname):
|
||||
self.element_start('elem')
|
||||
value = self.parse_value()
|
||||
value = self.parse_value('elem')
|
||||
self.element_end('elem')
|
||||
return value
|
||||
|
||||
def parse_struct(self):
|
||||
def parse_struct(self, pname):
|
||||
attrs = self.element_start('struct')
|
||||
name = attrs['name']
|
||||
members = []
|
||||
while self.token.type != ELEMENT_END:
|
||||
members.append(self.parse_member())
|
||||
members.append(self.parse_member(name))
|
||||
self.element_end('struct')
|
||||
return Struct(name, members)
|
||||
|
||||
def parse_member(self):
|
||||
def parse_member(self, pname):
|
||||
attrs = self.element_start('member')
|
||||
name = attrs['name']
|
||||
value = self.parse_value()
|
||||
value = self.parse_value(name)
|
||||
self.element_end('member')
|
||||
|
||||
return name, value
|
||||
|
||||
def parse_ptr(self):
|
||||
def parse_ptr(self, pname):
|
||||
self.element_start('ptr')
|
||||
address = self.character_data()
|
||||
self.element_end('ptr')
|
||||
|
||||
return Pointer(address)
|
||||
return Pointer(address, pname)
|
||||
|
||||
def handle_call(self, call):
|
||||
pass
|
||||
|
||||
|
||||
class TraceDumper(TraceParser):
|
||||
class SimpleTraceDumper(TraceParser):
|
||||
|
||||
def __init__(self, fp, options, outStream = sys.stdout):
|
||||
def __init__(self, fp, options, formatter):
|
||||
TraceParser.__init__(self, fp)
|
||||
if "plain" in options and options.plain:
|
||||
self.formatter = format.Formatter(outStream)
|
||||
else:
|
||||
self.formatter = format.DefaultFormatter(outStream)
|
||||
self.options = options
|
||||
self.formatter = formatter
|
||||
self.pretty_printer = PrettyPrinter(self.formatter, options)
|
||||
|
||||
def handle_call(self, call):
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
|
||||
class TraceDumper(SimpleTraceDumper):
|
||||
|
||||
def __init__(self, fp, options, formatter):
|
||||
SimpleTraceDumper.__init__(self, fp, options, formatter)
|
||||
self.call_stack = []
|
||||
|
||||
def handle_call(self, call):
|
||||
if self.options.named_ptrs:
|
||||
self.call_stack.append(call)
|
||||
else:
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
def dump_calls(self):
|
||||
for call in self.call_stack:
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
|
||||
class Main:
|
||||
|
|
@ -403,12 +421,24 @@ class Main:
|
|||
optparser.add_argument("-S", "--suppress",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="suppress_variants", help="suppress some variants in output for better diffability")
|
||||
optparser.add_argument("-N", "--named",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="named_ptrs", help="generate symbolic names for raw pointer values")
|
||||
|
||||
return optparser
|
||||
|
||||
def process_arg(self, stream, options):
|
||||
parser = TraceDumper(stream, options)
|
||||
if options.plain:
|
||||
formatter = format.Formatter(sys.stdout)
|
||||
else:
|
||||
formatter = format.DefaultFormatter(sys.stdout)
|
||||
|
||||
parser = TraceDumper(stream, options, formatter)
|
||||
parser.parse()
|
||||
|
||||
if options.named_ptrs:
|
||||
parser.dump_calls()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Main().main()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue