From nobody Fri Nov 14 19:24:25 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1589820802; cv=none; d=zohomail.com; s=zohoarc; b=CWM4fLa0dItavnMv+j+eATjomG0TOsCtlrtp4xzioC58NfBfaJu3KB0mmdX9XtUcssNWWI/c2sovjEPdhTvO8D2scBhm4PWsbdcLO5e7NmosFJuW+q5dpQ05ds2I4ZT4JC8r53M5+e8AuUPYDK6qnjg7O+x5Gai6cpOnIg0bvvc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1589820802; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=MPJKFuko3o4wPQ/LQBUVo3W7uSIJWuyYbNATR0QRJU4=; b=oC+e4ubKHlo5P7KZlUvA1ABnSoztUzis15BJ4silNCvqbdasnQTm+l9YbXxGXe+eP7uW7GMTY73vZnhn5P9jPtTIlAMwgcvE2yBqygq7j7dPmbu3syNx67lmOaDJYWJrQYR78l+xWtYIvwGkXUUTDdvvE5sI9VDFyvmCTHQMc5g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 158982080263090.69476037871789; Mon, 18 May 2020 09:53:22 -0700 (PDT) Received: from localhost ([::1]:32990 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jaj0z-0004EP-5O for importer@patchew.org; Mon, 18 May 2020 12:53:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60244) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jaipA-0002DA-6R for qemu-devel@nongnu.org; Mon, 18 May 2020 12:41:08 -0400 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]:41386) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jaip8-0005ry-AR for qemu-devel@nongnu.org; Mon, 18 May 2020 12:41:07 -0400 Received: by mail-pg1-x544.google.com with SMTP id r10so5085943pgv.8 for ; Mon, 18 May 2020 09:41:05 -0700 (PDT) Received: from localhost.localdomain (174-21-143-238.tukw.qwest.net. [174.21.143.238]) by smtp.gmail.com with ESMTPSA id x132sm5790610pfd.214.2020.05.18.09.41.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 May 2020 09:41:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MPJKFuko3o4wPQ/LQBUVo3W7uSIJWuyYbNATR0QRJU4=; b=Rdr/B7ZI/okB7UoaMC0ANOO8pcLb4y2+yJb4AZ8lHDtbc1vZ6Ydynhd1w0//6u3z78 tvQWjGkAl4i+4nLGwjgWmdOzLlb1jsRzVCNN25MaIasUxPETksYb+LDD9p78FlWTxI+t jnh4C6BSeulQVABfCyUvCfOEMk3wI0aI77udHiAv/OeS366KVUvYQcz88ecUDWjE3DMe C8lkZpx1UzfLZNRDjfl6B0YctF8rQy09zHS4iuwL0WDQ1Vzsm3UObH6XFlRjVmrTN8WG xh3uW/+DPSWUCAnOecFjmJssnA79cGFzrUFs1Znwqs04iCeXgN5oJfOAyGOOSdJFkaSS n8yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MPJKFuko3o4wPQ/LQBUVo3W7uSIJWuyYbNATR0QRJU4=; b=H8l3A60tTXPHXYaTT85iT5SdQONtut8iqyzuMtEI4hLxrjCP9Gu2nr7u2LDonSw0IA U9D7uKuB1kX1ZySzm3r6V6funDr21bB6W/jvf6UXoLPZX/lhGiaFtSLOtVcVl+LffxBo VEqrFXVVAyKJ2LcfLFycxo1G+uBlKuUrW6TPtPWxnmL3rkn6f1IijyNlQIAN0ar9UG57 5O36KcyBmx3i44NA5D2m+tOwCBDx3fHl+gGGj7iIlkfFQbH9Y9T76Bq51eKYSeyxfIlZ jSE6t+cPi27mI7SzNAcbKXj8vzefjxF2Inw4hgg991dVXMT4rbh6niHiGaHZ9UZjjDDC Y1+A== X-Gm-Message-State: AOAM530wiHry6pAeuSKHbuCU/pbTngK2gDrDQngn++buTgNaaC88EjAX YdxduRPpGjzjuF71tpfqnA8nLNw7B7g= X-Google-Smtp-Source: ABdhPJxPJet6MvjTYXfJlV53qIyCERGwJtOesZp2bAT+EWwAhT2pADLLcNxpvdlAMXdbbLJDLZcjYw== X-Received: by 2002:aa7:939c:: with SMTP id t28mr17528853pfe.38.1589820063706; Mon, 18 May 2020 09:41:03 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Subject: [PATCH 6/8] decodetree: Move semantic propagation into classes Date: Mon, 18 May 2020 09:40:50 -0700 Message-Id: <20200518164052.18689-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200518164052.18689-1-richard.henderson@linaro.org> References: <20200518164052.18689-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::544; envelope-from=richard.henderson@linaro.org; helo=mail-pg1-x544.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @linaro.org) Content-Type: text/plain; charset="utf-8" Create ExcMultiPattern to hold an set of non-overlapping patterns. The body of build_tree, prop_format become member functions on this class. Add minimal member functions to Pattern and MultiPattern to allow recusion through the tree. Move the bulk of build_incmulti_pattern to prop_masks and prop_width in MultiPattern, since we will need this for both kinds of containers. Only perform prop_width for variablewidth. Remove global patterns variable, and pass down container object into parse_file from main. No functional change in all of this. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell --- scripts/decodetree.py | 464 +++++++++++++++++++++++------------------- 1 file changed, 253 insertions(+), 211 deletions(-) diff --git a/scripts/decodetree.py b/scripts/decodetree.py index 3307c74c30..0ba01e049c 100755 --- a/scripts/decodetree.py +++ b/scripts/decodetree.py @@ -31,7 +31,6 @@ variablewidth =3D False fields =3D {} arguments =3D {} formats =3D {} -patterns =3D [] allpatterns =3D [] anyextern =3D False =20 @@ -371,16 +370,27 @@ class Pattern(General): output(ind, 'u.f_', arg, '.', n, ' =3D ', f.str_extract(), ';\= n') output(ind, 'if (', translate_prefix, '_', self.name, '(ctx, &u.f_', arg, ')) return true;\n') + + # Normal patterns do not have children. + def build_tree(self): + return + def prop_masks(self): + return + def prop_format(self): + return + def prop_width(self): + return + # end Pattern =20 =20 class MultiPattern(General): """Class representing a set of instruction patterns""" =20 - def __init__(self, lineno, pats): + def __init__(self, lineno): self.file =3D input_file self.lineno =3D lineno - self.pats =3D pats + self.pats =3D [] self.base =3D None self.fixedbits =3D 0 self.fixedmask =3D 0 @@ -396,22 +406,63 @@ class MultiPattern(General): def output_decl(self): for p in self.pats: p.output_decl() + + def prop_masks(self): + global insnmask + + fixedmask =3D insnmask + undefmask =3D insnmask + + # Collect fixedmask/undefmask for all of the children. + for p in self.pats: + p.prop_masks() + fixedmask &=3D p.fixedmask + undefmask &=3D p.undefmask + + # Widen fixedmask until all fixedbits match + repeat =3D True + fixedbits =3D 0 + while repeat and fixedmask !=3D 0: + fixedbits =3D None + for p in self.pats: + thisbits =3D p.fixedbits & fixedmask + if fixedbits is None: + fixedbits =3D thisbits + elif fixedbits !=3D thisbits: + fixedmask &=3D ~(fixedbits ^ thisbits) + break + else: + repeat =3D False + + self.fixedbits =3D fixedbits + self.fixedmask =3D fixedmask + self.undefmask =3D undefmask + + def build_tree(self): + for p in self.pats: + p.build_tree() + + def prop_format(self): + for p in self.pats: + p.build_tree() + + def prop_width(self): + width =3D None + for p in self.pats: + p.prop_width() + if width is None: + width =3D p.width + elif width !=3D p.width: + error_with_file(self.file, self.lineno, + 'width mismatch in patterns within braces') + self.width =3D width + # end MultiPattern =20 =20 class IncMultiPattern(MultiPattern): """Class representing an overlapping set of instruction patterns""" =20 - def __init__(self, lineno, pats, fixb, fixm, udfm, w): - self.file =3D input_file - self.lineno =3D lineno - self.pats =3D pats - self.base =3D None - self.fixedbits =3D fixb - self.fixedmask =3D fixm - self.undefmask =3D udfm - self.width =3D w - def output_code(self, i, extracted, outerbits, outermask): global translate_prefix ind =3D str_indent(i) @@ -431,6 +482,153 @@ class IncMultiPattern(MultiPattern): #end IncMultiPattern =20 =20 +class Tree: + """Class representing a node in a decode tree""" + + def __init__(self, fm, tm): + self.fixedmask =3D fm + self.thismask =3D tm + self.subs =3D [] + self.base =3D None + + def str1(self, i): + ind =3D str_indent(i) + r =3D '{0}{1:08x}'.format(ind, self.fixedmask) + if self.format: + r +=3D ' ' + self.format.name + r +=3D ' [\n' + for (b, s) in self.subs: + r +=3D '{0} {1:08x}:\n'.format(ind, b) + r +=3D s.str1(i + 4) + '\n' + r +=3D ind + ']' + return r + + def __str__(self): + return self.str1(0) + + def output_code(self, i, extracted, outerbits, outermask): + ind =3D str_indent(i) + + # If we identified all nodes below have the same format, + # extract the fields now. + if not extracted and self.base: + output(ind, self.base.extract_name(), + '(ctx, &u.f_', self.base.base.name, ', insn);\n') + extracted =3D True + + # Attempt to aid the compiler in producing compact switch statemen= ts. + # If the bits in the mask are contiguous, extract them. + sh =3D is_contiguous(self.thismask) + if sh > 0: + # Propagate SH down into the local functions. + def str_switch(b, sh=3Dsh): + return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh) + + def str_case(b, sh=3Dsh): + return '0x{0:x}'.format(b >> sh) + else: + def str_switch(b): + return 'insn & 0x{0:08x}'.format(b) + + def str_case(b): + return '0x{0:08x}'.format(b) + + output(ind, 'switch (', str_switch(self.thismask), ') {\n') + for b, s in sorted(self.subs): + assert (self.thismask & ~s.fixedmask) =3D=3D 0 + innermask =3D outermask | self.thismask + innerbits =3D outerbits | b + output(ind, 'case ', str_case(b), ':\n') + output(ind, ' /* ', + str_match_bits(innerbits, innermask), ' */\n') + s.output_code(i + 4, extracted, innerbits, innermask) + output(ind, ' return false;\n') + output(ind, '}\n') +# end Tree + + +class ExcMultiPattern(MultiPattern): + """Class representing a non-overlapping set of instruction patterns""" + + def output_code(self, i, extracted, outerbits, outermask): + # Defer everything to our decomposed Tree node + self.tree.output_code(i, extracted, outerbits, outermask) + + @staticmethod + def __build_tree(pats, outerbits, outermask): + # Find the intersection of all remaining fixedmask. + innermask =3D ~outermask & insnmask + for i in pats: + innermask &=3D i.fixedmask + + if innermask =3D=3D 0: + # Edge condition: One pattern covers the entire insnmask + if len(pats) =3D=3D 1: + t =3D Tree(outermask, innermask) + t.subs.append((0, pats[0])) + return t + + text =3D 'overlapping patterns:' + for p in pats: + text +=3D '\n' + p.file + ':' + str(p.lineno) + ': ' + str= (p) + error_with_file(pats[0].file, pats[0].lineno, text) + + fullmask =3D outermask | innermask + + # Sort each element of pats into the bin selected by the mask. + bins =3D {} + for i in pats: + fb =3D i.fixedbits & innermask + if fb in bins: + bins[fb].append(i) + else: + bins[fb] =3D [i] + + # We must recurse if any bin has more than one element or if + # the single element in the bin has not been fully matched. + t =3D Tree(fullmask, innermask) + + for b, l in bins.items(): + s =3D l[0] + if len(l) > 1 or s.fixedmask & ~fullmask !=3D 0: + s =3D ExcMultiPattern.__build_tree(l, b | outerbits, fullm= ask) + t.subs.append((b, s)) + + return t + + def build_tree(self): + super().prop_format() + self.tree =3D self.__build_tree(self.pats, self.fixedbits, + self.fixedmask) + + @staticmethod + def __prop_format(tree): + """Propagate Format objects into the decode tree""" + + # Depth first search. + for (b, s) in tree.subs: + if isinstance(s, Tree): + ExcMultiPattern.__prop_format(s) + + # If all entries in SUBS have the same format, then + # propagate that into the tree. + f =3D None + for (b, s) in tree.subs: + if f is None: + f =3D s.base + if f is None: + return + if f is not s.base: + return + tree.base =3D f + + def prop_format(self): + super().prop_format() + self.__prop_format(self.tree) + +# end ExcMultiPattern + + def parse_field(lineno, name, toks): """Parse one instruction field from TOKS at LINENO""" global fields @@ -587,18 +785,19 @@ def infer_format(arg, fieldmask, flds, width): # end infer_format =20 =20 -def parse_generic(lineno, is_format, name, toks): +def parse_generic(lineno, parent_pat, name, toks): """Parse one instruction format from TOKS at LINENO""" global fields global arguments global formats - global patterns global allpatterns global re_ident global insnwidth global insnmask global variablewidth =20 + is_format =3D parent_pat is None + fixedmask =3D 0 fixedbits =3D 0 undefmask =3D 0 @@ -749,7 +948,7 @@ def parse_generic(lineno, is_format, name, toks): error(lineno, 'field {0} not initialized'.format(f)) pat =3D Pattern(name, lineno, fmt, fixedbits, fixedmask, undefmask, fieldmask, flds, width) - patterns.append(pat) + parent_pat.pats.append(pat) allpatterns.append(pat) =20 # Validate the masks that we have assembled. @@ -769,61 +968,16 @@ def parse_generic(lineno, is_format, name, toks): .format(allbits ^ insnmask)) # end parse_general =20 -def build_incmulti_pattern(lineno, pats): - """Validate the Patterns going into a IncMultiPattern.""" - global patterns - global insnmask =20 - if len(pats) < 2: - error(lineno, 'less than two patterns within braces') - - fixedmask =3D insnmask - undefmask =3D insnmask - - # Collect fixed/undefmask for all of the children. - # Move the defining lineno back to that of the first child. - for p in pats: - fixedmask &=3D p.fixedmask - undefmask &=3D p.undefmask - if p.lineno < lineno: - lineno =3D p.lineno - - width =3D None - for p in pats: - if width is None: - width =3D p.width - elif width !=3D p.width: - error(lineno, 'width mismatch in patterns within braces') - - repeat =3D True - fixedbits =3D 0 - while repeat and fixedmask !=3D 0: - fixedbits =3D None - for p in pats: - thisbits =3D p.fixedbits & fixedmask - if fixedbits is None: - fixedbits =3D thisbits - elif fixedbits !=3D thisbits: - fixedmask &=3D ~(fixedbits ^ thisbits) - break - else: - repeat =3D False - - mp =3D IncMultiPattern(lineno, pats, fixedbits, fixedmask, undefmask, = width) - patterns.append(mp) -# end build_incmulti_pattern - -def parse_file(f): +def parse_file(f, parent_pat): """Parse all of the patterns within a file""" =20 - global patterns - # Read all of the lines of the file. Concatenate lines # ending in backslash; discard empty lines and comments. toks =3D [] lineno =3D 0 nesting =3D 0 - saved_pats =3D [] + nesting_pats =3D [] =20 for line in f: lineno +=3D 1 @@ -868,16 +1022,20 @@ def parse_file(f): =20 # End nesting? if name =3D=3D '}': - if nesting =3D=3D 0: - error(start_lineno, 'mismatched close brace') if len(toks) !=3D 0: error(start_lineno, 'extra tokens after close brace') + if len(parent_pat.pats) < 2: + error(lineno, 'less than two patterns within braces') + + try: + parent_pat =3D nesting_pats.pop() + except: + error(lineno, 'mismatched close brace') + nesting -=3D 2 if indent !=3D nesting: - error(start_lineno, 'indentation ', indent, ' !=3D ', nest= ing) - pats =3D patterns - patterns =3D saved_pats.pop() - build_incmulti_pattern(lineno, pats) + error(lineno, 'indentation ', indent, ' !=3D ', nesting) + toks =3D [] continue =20 @@ -889,8 +1047,12 @@ def parse_file(f): if name =3D=3D '{': if len(toks) !=3D 0: error(start_lineno, 'extra tokens after open brace') - saved_pats.append(patterns) - patterns =3D [] + + nested_pat =3D IncMultiPattern(start_lineno) + parent_pat.pats.append(nested_pat) + nesting_pats.append(parent_pat) + parent_pat =3D nested_pat + nesting +=3D 2 toks =3D [] continue @@ -901,121 +1063,13 @@ def parse_file(f): elif name[0] =3D=3D '&': parse_arguments(start_lineno, name[1:], toks) elif name[0] =3D=3D '@': - parse_generic(start_lineno, True, name[1:], toks) + parse_generic(start_lineno, None, name[1:], toks) else: - parse_generic(start_lineno, False, name, toks) + parse_generic(start_lineno, parent_pat, name, toks) toks =3D [] # end parse_file =20 =20 -class Tree: - """Class representing a node in a decode tree""" - - def __init__(self, fm, tm): - self.fixedmask =3D fm - self.thismask =3D tm - self.subs =3D [] - self.base =3D None - - def str1(self, i): - ind =3D str_indent(i) - r =3D '{0}{1:08x}'.format(ind, self.fixedmask) - if self.format: - r +=3D ' ' + self.format.name - r +=3D ' [\n' - for (b, s) in self.subs: - r +=3D '{0} {1:08x}:\n'.format(ind, b) - r +=3D s.str1(i + 4) + '\n' - r +=3D ind + ']' - return r - - def __str__(self): - return self.str1(0) - - def output_code(self, i, extracted, outerbits, outermask): - ind =3D str_indent(i) - - # If we identified all nodes below have the same format, - # extract the fields now. - if not extracted and self.base: - output(ind, self.base.extract_name(), - '(ctx, &u.f_', self.base.base.name, ', insn);\n') - extracted =3D True - - # Attempt to aid the compiler in producing compact switch statemen= ts. - # If the bits in the mask are contiguous, extract them. - sh =3D is_contiguous(self.thismask) - if sh > 0: - # Propagate SH down into the local functions. - def str_switch(b, sh=3Dsh): - return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh) - - def str_case(b, sh=3Dsh): - return '0x{0:x}'.format(b >> sh) - else: - def str_switch(b): - return 'insn & 0x{0:08x}'.format(b) - - def str_case(b): - return '0x{0:08x}'.format(b) - - output(ind, 'switch (', str_switch(self.thismask), ') {\n') - for b, s in sorted(self.subs): - assert (self.thismask & ~s.fixedmask) =3D=3D 0 - innermask =3D outermask | self.thismask - innerbits =3D outerbits | b - output(ind, 'case ', str_case(b), ':\n') - output(ind, ' /* ', - str_match_bits(innerbits, innermask), ' */\n') - s.output_code(i + 4, extracted, innerbits, innermask) - output(ind, ' return false;\n') - output(ind, '}\n') -# end Tree - - -def build_tree(pats, outerbits, outermask): - # Find the intersection of all remaining fixedmask. - innermask =3D ~outermask & insnmask - for i in pats: - innermask &=3D i.fixedmask - - if innermask =3D=3D 0: - # Edge condition: One pattern covers the entire insnmask - if len(pats) =3D=3D 1: - t =3D Tree(outermask, innermask) - t.subs.append((0, pats[0])) - return t - - text =3D 'overlapping patterns:' - for p in pats: - text +=3D '\n' + p.file + ':' + str(p.lineno) + ': ' + str(p) - error_with_file(pats[0].file, pats[0].lineno, text) - - fullmask =3D outermask | innermask - - # Sort each element of pats into the bin selected by the mask. - bins =3D {} - for i in pats: - fb =3D i.fixedbits & innermask - if fb in bins: - bins[fb].append(i) - else: - bins[fb] =3D [i] - - # We must recurse if any bin has more than one element or if - # the single element in the bin has not been fully matched. - t =3D Tree(fullmask, innermask) - - for b, l in bins.items(): - s =3D l[0] - if len(l) > 1 or s.fixedmask & ~fullmask !=3D 0: - s =3D build_tree(l, b | outerbits, fullmask) - t.subs.append((b, s)) - - return t -# end build_tree - - class SizeTree: """Class representing a node in a size decode tree""" =20 @@ -1157,28 +1211,6 @@ def build_size_tree(pats, width, outerbits, outermas= k): # end build_size_tree =20 =20 -def prop_format(tree): - """Propagate Format objects into the decode tree""" - - # Depth first search. - for (b, s) in tree.subs: - if isinstance(s, Tree): - prop_format(s) - - # If all entries in SUBS have the same format, then - # propagate that into the tree. - f =3D None - for (b, s) in tree.subs: - if f is None: - f =3D s.base - if f is None: - return - if f is not s.base: - return - tree.base =3D f -# end prop_format - - def prop_size(tree): """Propagate minimum widths up the decode size tree""" =20 @@ -1199,7 +1231,6 @@ def prop_size(tree): def main(): global arguments global formats - global patterns global allpatterns global translate_scope global translate_prefix @@ -1246,18 +1277,29 @@ def main(): =20 if len(args) < 1: error(0, 'missing input file') + + toppat =3D ExcMultiPattern(0) + for filename in args: input_file =3D filename f =3D open(filename, 'r') - parse_file(f) + parse_file(f, toppat) f.close() =20 - if variablewidth: - stree =3D build_size_tree(patterns, 8, 0, 0) - prop_size(stree) + # We do not want to compute masks for toppat, because those masks + # are used as a starting point for build_tree. For toppat, we must + # insist that decode begins from naught. + for i in toppat.pats: + i.prop_masks() =20 - dtree =3D build_tree(patterns, 0, 0) - prop_format(dtree) + toppat.build_tree() + toppat.prop_format() + + if variablewidth: + for i in toppat.pats: + i.prop_width() + stree =3D build_size_tree(toppat.pats, 8, 0, 0) + prop_size(stree) =20 if output_file: output_fd =3D open(output_file, 'w') @@ -1316,7 +1358,7 @@ def main(): f =3D arguments[n] output(i4, i4, f.struct_name(), ' f_', f.name, ';\n') output(i4, '} u;\n\n') - dtree.output_code(4, False, 0, 0) + toppat.output_code(4, False, 0, 0) =20 output(i4, 'return false;\n') output('}\n') --=20 2.20.1