mirror of https://gitee.com/openkylin/qemu.git
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:
parent
60c425f328
commit
af93ccacc7
|
@ -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::
|
||||||
|
|
||||||
®3 ra rb rc
|
®3 ra rb rc
|
||||||
&loadstore reg base offset
|
&loadstore reg base offset
|
||||||
|
&longldst reg base offset:int64_t
|
||||||
|
|
||||||
|
|
||||||
Formats
|
Formats
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
&asdf b:bool c:uint64_t a
|
Loading…
Reference in New Issue