From patchwork Thu Feb 23 22:18:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 65547 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 596C63850201 for ; Thu, 23 Feb 2023 22:19:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 596C63850201 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1677190760; bh=FQOnie6OPtTuftoTqIBXPK4sQGcEJ1rkVLMKiEA/U20=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=Vww4S3ixgg4vG+sD4aFlV+s+dUHQ4koDtbL1mVWAG6rU6laD2/ctGRs/gtRgC/4Fg +akmLi2ww3rJfsuDSpBuZp3MKqGms2/ZaIKMgJ/9XTqH6TJef9ZNzLeJ047XuD7OF0 gzcjyBys6FQm4aqQXpKkOtBtCRcEkMJmtYowv/o0= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id 9BE9C38582B0 for ; Thu, 23 Feb 2023 22:18:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9BE9C38582B0 Received: from smarchi-efficios.internal.efficios.com (192-222-180-24.qc.cable.ebox.net [192.222.180.24]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 525E11E4A3; Thu, 23 Feb 2023 17:18:32 -0500 (EST) To: gdb-patches@sourceware.org Cc: Simon Marchi Subject: [PATCH 5/9] gdb: split gdbarch component types to gdbarch_types.py Date: Thu, 23 Feb 2023 17:18:26 -0500 Message-Id: <20230223221830.499934-6-simon.marchi@efficios.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230223221830.499934-1-simon.marchi@efficios.com> References: <20230223221830.499934-1-simon.marchi@efficios.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3497.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Simon Marchi via Gdb-patches From: Simon Marchi Reply-To: Simon Marchi Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Editing gdbarch-components.py is not an experience in an editor that is minimally smart about Python. Because gdbarch-components.py is read and exec'd by gdbarch.py, it doesn't import the Info / Method / Function / Value types. And because these types are defined in gdbarch.py, it can't import them, as that would make a cyclic dependency. Solve this by introducing a third file, gdbarch_types.py, to define these types. Make gdbarch.py and gdbarch-components.py import it. Also, replace the read & exec of gdbarch-components.py by a regular import. For this to work though, gdbarch-components.py needs to be renamed to gdbarch_components.py. Change-Id: Ibe994d56ef9efcc0698b3ca9670d4d9bf8bbb853 --- gdb/gdbarch.py | 178 +---------------- ...ch-components.py => gdbarch_components.py} | 2 + gdb/gdbarch_types.py | 188 ++++++++++++++++++ 3 files changed, 195 insertions(+), 173 deletions(-) rename gdb/{gdbarch-components.py => gdbarch_components.py} (99%) create mode 100755 gdb/gdbarch_types.py diff --git a/gdb/gdbarch.py b/gdb/gdbarch.py index 63c3aee1dc0e..d1ac414d0eb3 100755 --- a/gdb/gdbarch.py +++ b/gdb/gdbarch.py @@ -20,10 +20,12 @@ # along with this program. If not, see . import textwrap -import gdbcopyright -# All the components created in gdbarch-components.py. -components = [] +# gdbarch_components is imported only for its side-effect of filling +# `gdbarch_types.components`. +import gdbarch_components # noqa: F401 # type: ignore +import gdbcopyright +from gdbarch_types import Function, Info, Value, components def indentation(n_columns): @@ -31,176 +33,6 @@ def indentation(n_columns): return "\t" * (n_columns // 8) + " " * (n_columns % 8) -def join_type_and_name(t, n): - "Combine the type T and the name N into a C declaration." - if t.endswith("*") or t.endswith("&"): - return t + n - else: - return t + " " + n - - -def join_params(params): - """Given a sequence of (TYPE, NAME) pairs, generate a comma-separated - list of declarations.""" - params = [join_type_and_name(p[0], p[1]) for p in params] - return ", ".join(params) - - -class _Component: - "Base class for all components." - - def __init__( - self, - name, - type, - printer, - comment=None, - predicate=False, - predefault=None, - postdefault=None, - invalid=None, - params=None, - param_checks=None, - result_checks=None, - implement=True, - ): - self.name = name - self.type = type - self.printer = printer - self.comment = comment - self.predicate = predicate - self.predefault = predefault - self.postdefault = postdefault - self.invalid = invalid - self.params = params - self.param_checks = param_checks - self.result_checks = result_checks - self.implement = implement - - components.append(self) - - # It doesn't make sense to have a check of the result value - # for a function or method with void return type. - if self.type == "void" and self.result_checks: - raise Exception("can't have result checks with a void return type") - - def get_predicate(self): - "Return the expression used for validity checking." - assert self.predicate and not isinstance(self.invalid, str) - if self.predefault: - predicate = f"gdbarch->{self.name} != {self.predefault}" - else: - predicate = f"gdbarch->{self.name} != NULL" - return predicate - - -class Info(_Component): - "An Info component is copied from the gdbarch_info." - - def __init__(self, *, name, type, printer=None): - super().__init__(name=name, type=type, printer=printer) - # This little hack makes the generator a bit simpler. - self.predicate = None - - -class Value(_Component): - "A Value component is just a data member." - - def __init__( - self, - *, - name, - type, - comment=None, - predicate=False, - predefault=None, - postdefault=None, - invalid=None, - printer=None, - ): - super().__init__( - comment=comment, - name=name, - type=type, - predicate=predicate, - predefault=predefault, - postdefault=postdefault, - invalid=invalid, - printer=printer, - ) - - -class Function(_Component): - "A Function component is a function pointer member." - - def __init__( - self, - *, - name, - type, - params, - comment=None, - predicate=False, - predefault=None, - postdefault=None, - invalid=None, - printer=None, - param_checks=None, - result_checks=None, - implement=True, - ): - super().__init__( - comment=comment, - name=name, - type=type, - predicate=predicate, - predefault=predefault, - postdefault=postdefault, - invalid=invalid, - printer=printer, - params=params, - param_checks=param_checks, - result_checks=result_checks, - implement=implement, - ) - - def ftype(self): - "Return the name of the function typedef to use." - return f"gdbarch_{self.name}_ftype" - - def param_list(self): - "Return the formal parameter list as a string." - return join_params(self.params) - - def set_list(self): - """Return the formal parameter list of the caller function, - as a string. This list includes the gdbarch.""" - arch_arg = ("struct gdbarch *", "gdbarch") - arch_tuple = [arch_arg] - return join_params(arch_tuple + list(self.params)) - - def actuals(self): - "Return the actual parameters to forward, as a string." - return ", ".join([p[1] for p in self.params]) - - -class Method(Function): - "A Method is like a Function but passes the gdbarch through." - - def param_list(self): - "See superclass." - return self.set_list() - - def actuals(self): - "See superclass." - result = ["gdbarch"] + [p[1] for p in self.params] - return ", ".join(result) - - -# Read the components. -with open("gdbarch-components.py") as fd: - exec(fd.read()) - copyright = gdbcopyright.copyright( "gdbarch.py", "Dynamic architecture support for GDB, the GNU debugger." ) diff --git a/gdb/gdbarch-components.py b/gdb/gdbarch_components.py similarity index 99% rename from gdb/gdbarch-components.py rename to gdb/gdbarch_components.py index 76ad2832d8a2..fe5c3b3b4bcd 100644 --- a/gdb/gdbarch-components.py +++ b/gdb/gdbarch_components.py @@ -117,6 +117,8 @@ # * "implement" - optional, a boolean. If True (the default), a # wrapper function for this function will be emitted. +from gdbarch_types import Function, Info, Method, Value + Info( type="const struct bfd_arch_info *", name="bfd_arch_info", diff --git a/gdb/gdbarch_types.py b/gdb/gdbarch_types.py new file mode 100755 index 000000000000..95d9b5e65bc5 --- /dev/null +++ b/gdb/gdbarch_types.py @@ -0,0 +1,188 @@ +# Architecture commands for GDB, the GNU debugger. +# +# Copyright (C) 1998-2023 Free Software Foundation, Inc. +# +# This file is part of GDB. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +def join_type_and_name(t, n): + "Combine the type T and the name N into a C declaration." + if t.endswith("*") or t.endswith("&"): + return t + n + else: + return t + " " + n + + +def join_params(params): + """Given a sequence of (TYPE, NAME) pairs, generate a comma-separated + list of declarations.""" + params = [join_type_and_name(p[0], p[1]) for p in params] + return ", ".join(params) + + +class _Component: + "Base class for all components." + + def __init__( + self, + name, + type, + printer, + comment=None, + predicate=False, + predefault=None, + postdefault=None, + invalid=None, + params=None, + param_checks=None, + result_checks=None, + implement=True, + ): + self.name = name + self.type = type + self.printer = printer + self.comment = comment + self.predicate = predicate + self.predefault = predefault + self.postdefault = postdefault + self.invalid = invalid + self.params = params + self.param_checks = param_checks + self.result_checks = result_checks + self.implement = implement + + components.append(self) + + # It doesn't make sense to have a check of the result value + # for a function or method with void return type. + if self.type == "void" and self.result_checks: + raise Exception("can't have result checks with a void return type") + + def get_predicate(self): + "Return the expression used for validity checking." + assert self.predicate and not isinstance(self.invalid, str) + if self.predefault: + predicate = f"gdbarch->{self.name} != {self.predefault}" + else: + predicate = f"gdbarch->{self.name} != NULL" + return predicate + + +class Info(_Component): + "An Info component is copied from the gdbarch_info." + + def __init__(self, *, name, type, printer=None): + super().__init__(name=name, type=type, printer=printer) + # This little hack makes the generator a bit simpler. + self.predicate = None + + +class Value(_Component): + "A Value component is just a data member." + + def __init__( + self, + *, + name, + type, + comment=None, + predicate=False, + predefault=None, + postdefault=None, + invalid=None, + printer=None, + ): + super().__init__( + comment=comment, + name=name, + type=type, + predicate=predicate, + predefault=predefault, + postdefault=postdefault, + invalid=invalid, + printer=printer, + ) + + +class Function(_Component): + "A Function component is a function pointer member." + + def __init__( + self, + *, + name, + type, + params, + comment=None, + predicate=False, + predefault=None, + postdefault=None, + invalid=None, + printer=None, + param_checks=None, + result_checks=None, + implement=True, + ): + super().__init__( + comment=comment, + name=name, + type=type, + predicate=predicate, + predefault=predefault, + postdefault=postdefault, + invalid=invalid, + printer=printer, + params=params, + param_checks=param_checks, + result_checks=result_checks, + implement=implement, + ) + + def ftype(self): + "Return the name of the function typedef to use." + return f"gdbarch_{self.name}_ftype" + + def param_list(self): + "Return the formal parameter list as a string." + return join_params(self.params) + + def set_list(self): + """Return the formal parameter list of the caller function, + as a string. This list includes the gdbarch.""" + arch_arg = ("struct gdbarch *", "gdbarch") + arch_tuple = [arch_arg] + return join_params(arch_tuple + list(self.params)) + + def actuals(self): + "Return the actual parameters to forward, as a string." + return ", ".join([p[1] for p in self.params]) + + +class Method(Function): + "A Method is like a Function but passes the gdbarch through." + + def param_list(self): + "See superclass." + return self.set_list() + + def actuals(self): + "See superclass." + result = ["gdbarch"] + [p[1] for p in self.params] + return ", ".join(result) + + +# All the components created in gdbarch-components.py. +components: list[_Component] = []