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 <luis.pires@eldorado.org.br>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-04-29 10:03:59 -07:00
parent 60c425f328
commit af93ccacc7
3 changed files with 36 additions and 21 deletions

View File

@ -40,9 +40,6 @@ and returns an integral value extracted from there.
A field with no ``unnamed_fields`` and no ``!function`` is in error. 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: Field examples:
+---------------------------+---------------------------------------------+ +---------------------------+---------------------------------------------+
@ -66,9 +63,14 @@ Argument Sets
Syntax:: Syntax::
args_def := '&' identifier ( args_elt )+ ( !extern )? args_def := '&' identifier ( args_elt )+ ( !extern )?
args_elt := identifier args_elt := identifier (':' identifier)?
Each *args_elt* defines an argument within the argument set. 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" Each argument set will be rendered as a C structure "arg_$name"
with each of the fields being one of the member arguments. with each of the fields being one of the member arguments.
@ -86,6 +88,7 @@ Argument set examples::
&reg3 ra rb rc &reg3 ra rb rc
&loadstore reg base offset &loadstore reg base offset
&longldst reg base offset:int64_t
Formats Formats

View File

@ -165,11 +165,15 @@ def is_contiguous(bits):
return -1 return -1
def eq_fields_for_args(flds_a, flds_b): def eq_fields_for_args(flds_a, arg):
if len(flds_a) != len(flds_b): if len(flds_a) != len(arg.fields):
return False 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(): for k, a in flds_a.items():
if k not in flds_b: if k not in arg.fields:
return False return False
return True return True
@ -313,10 +317,11 @@ def __ne__(self, other):
class Arguments: class Arguments:
"""Class representing the extracted fields of a format""" """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.name = nm
self.extern = extern self.extern = extern
self.fields = sorted(flds) self.fields = flds
self.types = types
def __str__(self): def __str__(self):
return self.name + ' ' + str(self.fields) return self.name + ' ' + str(self.fields)
@ -327,8 +332,8 @@ def struct_name(self):
def output_def(self): def output_def(self):
if not self.extern: if not self.extern:
output('typedef struct {\n') output('typedef struct {\n')
for n in self.fields: for (n, t) in zip(self.fields, self.types):
output(' int ', n, ';\n') output(f' {t} {n};\n')
output('} ', self.struct_name(), ';\n\n') output('} ', self.struct_name(), ';\n\n')
# end Arguments # end Arguments
@ -719,21 +724,27 @@ def parse_arguments(lineno, name, toks):
global anyextern global anyextern
flds = [] flds = []
types = []
extern = False extern = False
for t in toks: for n in toks:
if re.fullmatch('!extern', t): if re.fullmatch('!extern', n):
extern = True extern = True
anyextern = True anyextern = True
continue continue
if not re.fullmatch(re_C_ident, t): if re.fullmatch(re_C_ident + ':' + re_C_ident, n):
error(lineno, f'invalid argument set token "{t}"') (n, t) = n.split(':')
if t in flds: elif re.fullmatch(re_C_ident, n):
error(lineno, f'duplicate argument "{t}"') t = 'int'
flds.append(t) 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: if name in arguments:
error(lineno, 'duplicate argument set', name) error(lineno, 'duplicate argument set', name)
arguments[name] = Arguments(name, flds, extern) arguments[name] = Arguments(name, flds, types, extern)
# end parse_arguments # end parse_arguments
@ -760,11 +771,11 @@ def infer_argument_set(flds):
global decode_function global decode_function
for arg in arguments.values(): for arg in arguments.values():
if eq_fields_for_args(flds, arg.fields): if eq_fields_for_args(flds, arg):
return arg return arg
name = decode_function + str(len(arguments)) name = decode_function + str(len(arguments))
arg = Arguments(name, flds.keys(), False) arg = Arguments(name, flds.keys(), ['int'] * len(flds), False)
arguments[name] = arg arguments[name] = arg
return arg return arg

View File

@ -0,0 +1 @@
&asdf b:bool c:uint64_t a