From af93ccacc772019298be4c3e47251cdaa60d0c21 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 29 Apr 2021 10:03:59 -0700 Subject: [PATCH] decodetree: Extend argument set syntax to allow types Rather than force all structure members to be 'int', allow the type of the member to be specified. Reviewed-by: Luis Pires Signed-off-by: Richard Henderson --- docs/devel/decodetree.rst | 11 ++++--- scripts/decodetree.py | 45 +++++++++++++++++---------- tests/decode/succ_argset_type1.decode | 1 + 3 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 tests/decode/succ_argset_type1.decode diff --git a/docs/devel/decodetree.rst b/docs/devel/decodetree.rst index 74f66bf46e..49ea50c2a7 100644 --- a/docs/devel/decodetree.rst +++ b/docs/devel/decodetree.rst @@ -40,9 +40,6 @@ and returns an integral value extracted from there. A field with no ``unnamed_fields`` and no ``!function`` is in error. -FIXME: the fields of the structure into which this result will be stored -is restricted to ``int``. Which means that we cannot expand 64-bit items. - Field examples: +---------------------------+---------------------------------------------+ @@ -66,9 +63,14 @@ Argument Sets Syntax:: args_def := '&' identifier ( args_elt )+ ( !extern )? - args_elt := identifier + args_elt := identifier (':' identifier)? Each *args_elt* defines an argument within the argument set. +If the form of the *args_elt* contains a colon, the first +identifier is the argument name and the second identifier is +the argument type. If the colon is missing, the argument +type will be ``int``. + Each argument set will be rendered as a C structure "arg_$name" with each of the fields being one of the member arguments. @@ -86,6 +88,7 @@ Argument set examples:: ®3 ra rb rc &loadstore reg base offset + &longldst reg base offset:int64_t Formats diff --git a/scripts/decodetree.py b/scripts/decodetree.py index f85da45ee3..a03dc6b5e3 100644 --- a/scripts/decodetree.py +++ b/scripts/decodetree.py @@ -165,11 +165,15 @@ def is_contiguous(bits): return -1 -def eq_fields_for_args(flds_a, flds_b): - if len(flds_a) != len(flds_b): +def eq_fields_for_args(flds_a, arg): + if len(flds_a) != len(arg.fields): return False + # Only allow inference on default types + for t in arg.types: + if t != 'int': + return False for k, a in flds_a.items(): - if k not in flds_b: + if k not in arg.fields: return False return True @@ -313,10 +317,11 @@ class ParameterField: class Arguments: """Class representing the extracted fields of a format""" - def __init__(self, nm, flds, extern): + def __init__(self, nm, flds, types, extern): self.name = nm self.extern = extern - self.fields = sorted(flds) + self.fields = flds + self.types = types def __str__(self): return self.name + ' ' + str(self.fields) @@ -327,8 +332,8 @@ class Arguments: def output_def(self): if not self.extern: output('typedef struct {\n') - for n in self.fields: - output(' int ', n, ';\n') + for (n, t) in zip(self.fields, self.types): + output(f' {t} {n};\n') output('} ', self.struct_name(), ';\n\n') # end Arguments @@ -719,21 +724,27 @@ def parse_arguments(lineno, name, toks): global anyextern flds = [] + types = [] extern = False - for t in toks: - if re.fullmatch('!extern', t): + for n in toks: + if re.fullmatch('!extern', n): extern = True anyextern = True continue - if not re.fullmatch(re_C_ident, t): - error(lineno, f'invalid argument set token "{t}"') - if t in flds: - error(lineno, f'duplicate argument "{t}"') - flds.append(t) + if re.fullmatch(re_C_ident + ':' + re_C_ident, n): + (n, t) = n.split(':') + elif re.fullmatch(re_C_ident, n): + t = 'int' + else: + error(lineno, f'invalid argument set token "{n}"') + if n in flds: + error(lineno, f'duplicate argument "{n}"') + flds.append(n) + types.append(t) if name in arguments: error(lineno, 'duplicate argument set', name) - arguments[name] = Arguments(name, flds, extern) + arguments[name] = Arguments(name, flds, types, extern) # end parse_arguments @@ -760,11 +771,11 @@ def infer_argument_set(flds): global decode_function for arg in arguments.values(): - if eq_fields_for_args(flds, arg.fields): + if eq_fields_for_args(flds, arg): return arg name = decode_function + str(len(arguments)) - arg = Arguments(name, flds.keys(), False) + arg = Arguments(name, flds.keys(), ['int'] * len(flds), False) arguments[name] = arg return arg diff --git a/tests/decode/succ_argset_type1.decode b/tests/decode/succ_argset_type1.decode new file mode 100644 index 0000000000..ed946b420d --- /dev/null +++ b/tests/decode/succ_argset_type1.decode @@ -0,0 +1 @@ +&asdf b:bool c:uint64_t a