From patchwork Mon Jun 12 08:41:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 20924 Received: (qmail 71276 invoked by alias); 12 Jun 2017 08:42:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 70814 invoked by uid 89); 12 Jun 2017 08:42:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=defaulted, xfree, 1015 X-HELO: mail-it0-f43.google.com Received: from mail-it0-f43.google.com (HELO mail-it0-f43.google.com) (209.85.214.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 12 Jun 2017 08:42:03 +0000 Received: by mail-it0-f43.google.com with SMTP id m47so17651910iti.0 for ; Mon, 12 Jun 2017 01:42:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=uUtbPSVk+DUkgYLlcey928/gpkeTUFaq4nZ//CBTpgo=; b=hfeaq4GpTLGpRX2qEfZ9eQT8nPPEhcu53SRoJbDlVBBz/TatNujS/MiY/YjICbMDeZ QoC22tedp/FWd3qhodLJ/D7A1wMWWe+c4da0DwUIpr83aN+XWlyt3QtVU8Z05/llB06Q zjST39t/M5B9iUtQjqIqgEp1bXTu7j0po2KwUJXSCcd+TpBJ54Bqp0bvk/EFJ3wc5GcI pW2kRjXKX0T+jViuF5dmsb6cOIO75xLLp+YXKzyx3x3VmvxU1E74AgYukmCt8CZB+r2A WpGX+J08s+GYw08M5no1GfGHr8TaC5//A/qiZ4LWxb1BXDWJ43o0vU5JODxhBAEZO/DY yqBA== X-Gm-Message-State: AODbwcDWJXaGRLqH0Eb1GVGN3L0O9W/kaahOFw69g3TKpClPnvryeF6U omK2dyB7/kuhYXrN X-Received: by 10.36.181.4 with SMTP id v4mr11245523ite.103.1497256925131; Mon, 12 Jun 2017 01:42:05 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id u4sm5280289itu.1.2017.06.12.01.42.04 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 12 Jun 2017 01:42:04 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 05/25] Use visitor pattern for "maint print c-tdesc" Date: Mon, 12 Jun 2017 09:41:36 +0100 Message-Id: <1497256916-4958-6-git-send-email-yao.qi@linaro.org> In-Reply-To: <1497256916-4958-1-git-send-email-yao.qi@linaro.org> References: <1497256916-4958-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes Target description can be modeled as a tree, the target description is the root node, features are children nodes, registers and types are grand-children nodes. So command "maint print c-tdesc" in effect traverse/visit each node, and print them in c. This can be implemented by visitor pattern, this is the first reason. Secondly, I want to this command prints c files in a different way for some specific xml files, but still print c files the same way for the rest of xml files. Third, I even want to print xml files from target descriptions, so that GDBserver can use it to reply GDB's query qXfer:features:read:target.xml. After this change, all features/*.c should be re-generated, but this patch only includes part changes features/*.c files. gdb: 2017-05-25 Yao Qi * target-descriptions.c (tdesc_element_visitor): New class. (tdesc_element): New class. (tdesc_reg): Inherit from tdesc_element. (tdesc_reg::accept): New function. (tdesc_type): Inherit from tdesc_element. (tdesc_type::accept): New function. (tdesc_feature): Inherit from tdesc_element. (tdesc_feature::accept): New function. (target_desc): Inherit from tdesc_element. (target_desc::target_desc): New. (target_desc::~target_desc): New. (target_desc::accept): New. (allocate_target_description): Use new. (free_target_description): Use delete. (print_c_tdesc): New class. (maint_print_c_tdesc_cmd): Adjust. * features/i386/i386-avx-avx512-linux.c: Re-generated. * features/i386/i386-avx-linux.c: Re-generated. * features/i386/i386-avx-mpx-avx512-pku-linux.c: Re-generated. * features/i386/i386-avx-mpx-linux.c: Re-generated. * features/i386/i386-linux.c: Re-generated. * features/i386/i386-mmx-linux.c: Re-generated. --- gdb/features/i386/i386-avx-avx512-linux.c | 8 +- gdb/features/i386/i386-avx-avx512.c | 8 +- gdb/features/i386/i386-avx-linux.c | 8 +- gdb/features/i386/i386-avx-mpx-avx512-pku-linux.c | 8 +- gdb/features/i386/i386-avx-mpx-avx512-pku.c | 8 +- gdb/features/i386/i386-avx-mpx-linux.c | 8 +- gdb/features/i386/i386-avx-mpx.c | 8 +- gdb/features/i386/i386-avx.c | 8 +- gdb/features/i386/i386-linux.c | 8 +- gdb/features/i386/i386-mmx-linux.c | 8 +- gdb/features/i386/i386-mmx.c | 8 +- gdb/features/i386/i386-mpx-linux.c | 8 +- gdb/features/i386/i386-mpx.c | 8 +- gdb/features/i386/i386.c | 8 +- gdb/target-descriptions.c | 657 ++++++++++++---------- 15 files changed, 427 insertions(+), 342 deletions(-) diff --git a/gdb/features/i386/i386-avx-avx512-linux.c b/gdb/features/i386/i386-avx-avx512-linux.c index 81149d5..545149d 100644 --- a/gdb/features/i386/i386-avx-avx512-linux.c +++ b/gdb/features/i386/i386-avx-avx512-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_avx_avx512_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-avx512.c b/gdb/features/i386/i386-avx-avx512.c index 1075ca0..585a0ac 100644 --- a/gdb/features/i386/i386-avx-avx512.c +++ b/gdb/features/i386/i386-avx-avx512.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_avx_avx512 (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-linux.c b/gdb/features/i386/i386-avx-linux.c index 4a8c6b5..3ef087d 100644 --- a/gdb/features/i386/i386-avx-linux.c +++ b/gdb/features/i386/i386-avx-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_avx_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-mpx-avx512-pku-linux.c b/gdb/features/i386/i386-avx-mpx-avx512-pku-linux.c index f90c834..e6eebf1 100644 --- a/gdb/features/i386/i386-avx-mpx-avx512-pku-linux.c +++ b/gdb/features/i386/i386-avx-mpx-avx512-pku-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_avx_mpx_avx512_pku_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-mpx-avx512-pku.c b/gdb/features/i386/i386-avx-mpx-avx512-pku.c index 08d9b4b..d7dd3bb 100644 --- a/gdb/features/i386/i386-avx-mpx-avx512-pku.c +++ b/gdb/features/i386/i386-avx-mpx-avx512-pku.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_avx_mpx_avx512_pku (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-mpx-linux.c b/gdb/features/i386/i386-avx-mpx-linux.c index 4b27bfc..f62c487 100644 --- a/gdb/features/i386/i386-avx-mpx-linux.c +++ b/gdb/features/i386/i386-avx-mpx-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_avx_mpx_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx-mpx.c b/gdb/features/i386/i386-avx-mpx.c index b27b40a..f479bda 100644 --- a/gdb/features/i386/i386-avx-mpx.c +++ b/gdb/features/i386/i386-avx-mpx.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_avx_mpx (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-avx.c b/gdb/features/i386/i386-avx.c index 1cb0f9e..f888335 100644 --- a/gdb/features/i386/i386-avx.c +++ b/gdb/features/i386/i386-avx.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_avx (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-linux.c b/gdb/features/i386/i386-linux.c index c7796c3..0394842 100644 --- a/gdb/features/i386/i386-linux.c +++ b/gdb/features/i386/i386-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-mmx-linux.c b/gdb/features/i386/i386-mmx-linux.c index e53b55f..1577972 100644 --- a/gdb/features/i386/i386-mmx-linux.c +++ b/gdb/features/i386/i386-mmx-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_mmx_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-mmx.c b/gdb/features/i386/i386-mmx.c index 74f67ed..02aee89 100644 --- a/gdb/features/i386/i386-mmx.c +++ b/gdb/features/i386/i386-mmx.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_mmx (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-mpx-linux.c b/gdb/features/i386/i386-mpx-linux.c index 43ea192..6dea8e0 100644 --- a/gdb/features/i386/i386-mpx-linux.c +++ b/gdb/features/i386/i386-mpx-linux.c @@ -10,15 +10,15 @@ static void initialize_tdesc_i386_mpx_linux (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386-mpx.c b/gdb/features/i386/i386-mpx.c index e832d2e..d08441b 100644 --- a/gdb/features/i386/i386-mpx.c +++ b/gdb/features/i386/i386-mpx.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386_mpx (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/features/i386/i386.c b/gdb/features/i386/i386.c index ede73fc..eb9a266 100644 --- a/gdb/features/i386/i386.c +++ b/gdb/features/i386/i386.c @@ -10,13 +10,13 @@ static void initialize_tdesc_i386 (void) { struct target_desc *result = allocate_target_description (); - struct tdesc_feature *feature; - struct tdesc_type *field_type; - struct tdesc_type *type; - set_tdesc_architecture (result, bfd_scan_arch ("i386")); + struct tdesc_feature *feature; + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + struct tdesc_type *field_type; + struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); tdesc_add_flag (type, 0, "CF"); tdesc_add_flag (type, 1, ""); diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index e2dcd1d..ac19792 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -35,6 +35,23 @@ #include "hashtab.h" #include "inferior.h" +class tdesc_element_visitor +{ +public: + virtual void visit (const target_desc *e) = 0; + virtual void visit_end (const target_desc *e) = 0; + + virtual void visit (const tdesc_feature *e) = 0; + virtual void visit (const tdesc_type *e) = 0; + virtual void visit (const tdesc_reg *e) = 0; +}; + +class tdesc_element +{ +public: + virtual void accept (tdesc_element_visitor &v) const = 0; +}; + /* Types. */ typedef struct property @@ -46,7 +63,7 @@ DEF_VEC_O(property_s); /* An individual register from a target description. */ -typedef struct tdesc_reg +typedef struct tdesc_reg : tdesc_element { public: tdesc_reg (struct tdesc_feature *feature, const char *name_, @@ -63,7 +80,7 @@ public: tdesc_type = tdesc_named_type (feature, type); } - ~tdesc_reg () + virtual ~tdesc_reg () { xfree (name); xfree (type); @@ -107,6 +124,12 @@ public: /* The target-described type corresponding to TYPE, if found. */ struct tdesc_type *tdesc_type; + + void accept (tdesc_element_visitor &v) const override + { + v.visit (this); + } + } *tdesc_reg_p; DEF_VEC_P(tdesc_reg_p); @@ -152,7 +175,7 @@ enum tdesc_type_kind TDESC_TYPE_ENUM }; -typedef struct tdesc_type +typedef struct tdesc_type : tdesc_element { public: tdesc_type (const char *name_, enum tdesc_type_kind kind_) @@ -161,7 +184,7 @@ public: memset (&u, 0, sizeof (u)); } - ~tdesc_type () + virtual ~tdesc_type () { switch (kind) { @@ -216,20 +239,25 @@ public: int size; } u; } u; + void accept (tdesc_element_visitor &v) const override + { + v.visit (this); + } + } *tdesc_type_p; DEF_VEC_P(tdesc_type_p); /* A feature from a target description. Each feature is a collection of other elements, e.g. registers and types. */ -typedef struct tdesc_feature +typedef struct tdesc_feature : tdesc_element { public: tdesc_feature (const char *name_) : name (xstrdup (name_)) {} - ~tdesc_feature () + virtual ~tdesc_feature () { struct tdesc_reg *reg; struct tdesc_type *type; @@ -259,6 +287,30 @@ public: /* The types associated with this feature. */ VEC(tdesc_type_p) *types = NULL; + + void accept (tdesc_element_visitor &v) const override + { + v.visit (this); + + struct tdesc_type *type; + + for (int ix = 0; + VEC_iterate (tdesc_type_p, types, ix, type); + ix++) + { + type->accept (v); + } + + struct tdesc_reg *reg; + + for (int ix = 0; + VEC_iterate (tdesc_reg_p, registers, ix, reg); + ix++) + { + reg->accept (v); + } + } + } *tdesc_feature_p; DEF_VEC_P(tdesc_feature_p); @@ -268,23 +320,67 @@ DEF_VEC_P(arch_p); /* A target description. */ -struct target_desc +struct target_desc : tdesc_element { +public: + target_desc () + {} + + virtual ~target_desc () + { + struct tdesc_feature *feature; + struct property *prop; + int ix; + + for (ix = 0; + VEC_iterate (tdesc_feature_p, features, ix, feature); + ix++) + delete feature; + VEC_free (tdesc_feature_p, features); + + for (ix = 0; + VEC_iterate (property_s, properties, ix, prop); + ix++) + { + xfree (prop->key); + xfree (prop->value); + } + + VEC_free (property_s, properties); + VEC_free (arch_p, compatible); + } + /* The architecture reported by the target, if any. */ - const struct bfd_arch_info *arch; + const struct bfd_arch_info *arch = NULL; /* The osabi reported by the target, if any; GDB_OSABI_UNKNOWN otherwise. */ - enum gdb_osabi osabi; + enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; /* The list of compatible architectures reported by the target. */ - VEC(arch_p) *compatible; + VEC(arch_p) *compatible = NULL; /* Any architecture-specific properties specified by the target. */ - VEC(property_s) *properties; + VEC(property_s) *properties = NULL; /* The features associated with this target. */ - VEC(tdesc_feature_p) *features; + VEC(tdesc_feature_p) *features = NULL; + + void accept (tdesc_element_visitor &v) const override + { + v.visit (this); + + struct tdesc_feature *feature; + + for (int ix = 0; + VEC_iterate (tdesc_feature_p, features, ix, feature); + ix++) + { + feature->accept (v); + } + + v.visit_end (this); + } }; /* Per-architecture data associated with a target description. The @@ -1554,35 +1650,15 @@ tdesc_create_feature (struct target_desc *tdesc, const char *name) struct target_desc * allocate_target_description (void) { - return XCNEW (struct target_desc); + return new target_desc (); } static void free_target_description (void *arg) { struct target_desc *target_desc = (struct target_desc *) arg; - struct tdesc_feature *feature; - struct property *prop; - int ix; - for (ix = 0; - VEC_iterate (tdesc_feature_p, target_desc->features, ix, feature); - ix++) - delete feature; - VEC_free (tdesc_feature_p, target_desc->features); - - for (ix = 0; - VEC_iterate (property_s, target_desc->properties, ix, prop); - ix++) - { - xfree (prop->key); - xfree (prop->value); - } - VEC_free (property_s, target_desc->properties); - - VEC_free (arch_p, target_desc->compatible); - - xfree (target_desc); + delete target_desc; } struct cleanup * @@ -1707,279 +1783,288 @@ unset_tdesc_filename_cmd (char *args, int from_tty) target_find_description (); } -static void -maint_print_c_tdesc_cmd (char *args, int from_tty) +class print_c_tdesc : public tdesc_element_visitor { - const struct target_desc *tdesc; - const struct bfd_arch_info *compatible; - const char *filename, *inp; - char *function, *outp; - struct property *prop; - struct tdesc_feature *feature; - struct tdesc_reg *reg; - struct tdesc_type *type; - struct tdesc_type_field *f; - int ix, ix2, ix3; - int printed_field_type = 0; +public: + print_c_tdesc (std::string &filename_after_features) + : m_filename_after_features (filename_after_features) + { + const char *inp; + char *outp; + const char *filename = lbasename (m_filename_after_features.c_str ()); - /* Use the global target-supplied description, not the current - architecture's. This lets a GDB for one architecture generate C - for another architecture's description, even though the gdbarch - initialization code will reject the new description. */ - tdesc = current_target_desc; - if (tdesc == NULL) - error (_("There is no target description to print.")); + m_function = (char *) xmalloc (strlen (filename) + 1); + for (inp = filename, outp = m_function; *inp != '\0'; inp++) + if (*inp == '.') + break; + else if (*inp == '-') + *outp++ = '_'; + else + *outp++ = *inp; + *outp = '\0'; + + /* Standard boilerplate. */ + printf_unfiltered ("/* THIS FILE IS GENERATED. " + "-*- buffer-read-only: t -*- vi" + ":set ro:\n"); + printf_unfiltered (" Original: %s */\n\n", filename); + } - if (target_description_filename == NULL) - error (_("The current target description did not come from an XML file.")); + ~print_c_tdesc () + { + xfree (m_function); + } - filename = lbasename (target_description_filename); - function = (char *) alloca (strlen (filename) + 1); - for (inp = filename, outp = function; *inp != '\0'; inp++) - if (*inp == '.') - break; - else if (*inp == '-') - *outp++ = '_'; - else - *outp++ = *inp; - *outp = '\0'; - - /* Standard boilerplate. */ - printf_unfiltered ("/* THIS FILE IS GENERATED. " - "-*- buffer-read-only: t -*- vi" - ":set ro:\n"); - printf_unfiltered (" Original: %s */\n\n", filename); - printf_unfiltered ("#include \"defs.h\"\n"); - printf_unfiltered ("#include \"osabi.h\"\n"); - printf_unfiltered ("#include \"target-descriptions.h\"\n"); - printf_unfiltered ("\n"); - - printf_unfiltered ("struct target_desc *tdesc_%s;\n", function); - printf_unfiltered ("static void\n"); - printf_unfiltered ("initialize_tdesc_%s (void)\n", function); - printf_unfiltered ("{\n"); - printf_unfiltered - (" struct target_desc *result = allocate_target_description ();\n"); - printf_unfiltered (" struct tdesc_feature *feature;\n"); - - /* Now we do some "filtering" in order to know which variables to - declare. This is needed because otherwise we would declare unused - variables `field_type' and `type'. */ - for (ix = 0; - VEC_iterate (tdesc_feature_p, tdesc->features, ix, feature); - ix++) - { - int printed_desc_type = 0; + void visit (const target_desc *e) override + { + printf_unfiltered ("#include \"defs.h\"\n"); + printf_unfiltered ("#include \"osabi.h\"\n"); + printf_unfiltered ("#include \"target-descriptions.h\"\n"); + printf_unfiltered ("\n"); - for (ix2 = 0; - VEC_iterate (tdesc_type_p, feature->types, ix2, type); - ix2++) - { - if (!printed_field_type) - { - printf_unfiltered (" struct tdesc_type *field_type;\n"); - printed_field_type = 1; - } + printf_unfiltered ("struct target_desc *tdesc_%s;\n", m_function); + printf_unfiltered ("static void\n"); + printf_unfiltered ("initialize_tdesc_%s (void)\n", m_function); + printf_unfiltered ("{\n"); + printf_unfiltered + (" struct target_desc *result = allocate_target_description ();\n"); - if ((type->kind == TDESC_TYPE_UNION - || type->kind == TDESC_TYPE_STRUCT - || type->kind == TDESC_TYPE_FLAGS - || type->kind == TDESC_TYPE_ENUM) - && VEC_length (tdesc_type_field, type->u.u.fields) > 0) - { - printf_unfiltered (" struct tdesc_type *type;\n"); - printed_desc_type = 1; - break; - } - } + if (tdesc_architecture (e) != NULL) + { + printf_unfiltered + (" set_tdesc_architecture (result, bfd_scan_arch (\"%s\"));\n", + tdesc_architecture (e)->printable_name); + printf_unfiltered ("\n"); + } + if (tdesc_osabi (e) > GDB_OSABI_UNKNOWN + && tdesc_osabi (e) < GDB_OSABI_INVALID) + { + printf_unfiltered + (" set_tdesc_osabi (result, osabi_from_tdesc_string (\"%s\"));\n", + gdbarch_osabi_name (tdesc_osabi (e))); + printf_unfiltered ("\n"); + } - if (printed_desc_type) - break; - } + int ix; + const struct bfd_arch_info *compatible; + struct property *prop; - printf_unfiltered ("\n"); + for (ix = 0; VEC_iterate (arch_p, e->compatible, ix, compatible); + ix++) + { + printf_unfiltered + (" tdesc_add_compatible (result, bfd_scan_arch (\"%s\"));\n", + compatible->printable_name); + } - if (tdesc_architecture (tdesc) != NULL) - { - printf_unfiltered - (" set_tdesc_architecture (result, bfd_scan_arch (\"%s\"));\n", - tdesc_architecture (tdesc)->printable_name); + if (ix) printf_unfiltered ("\n"); - } - if (tdesc_osabi (tdesc) > GDB_OSABI_UNKNOWN - && tdesc_osabi (tdesc) < GDB_OSABI_INVALID) - { - printf_unfiltered - (" set_tdesc_osabi (result, osabi_from_tdesc_string (\"%s\"));\n", - gdbarch_osabi_name (tdesc_osabi (tdesc))); - printf_unfiltered ("\n"); - } + for (ix = 0; VEC_iterate (property_s, e->properties, ix, prop); + ix++) + { + printf_unfiltered (" set_tdesc_property (result, \"%s\", \"%s\");\n", + prop->key, prop->value); + } + printf_unfiltered (" struct tdesc_feature *feature;\n"); + } - for (ix = 0; VEC_iterate (arch_p, tdesc->compatible, ix, compatible); - ix++) - { - printf_unfiltered - (" tdesc_add_compatible (result, bfd_scan_arch (\"%s\"));\n", - compatible->printable_name); - } - if (ix) - printf_unfiltered ("\n"); + void visit (const tdesc_feature *e) override + { + printf_unfiltered ("\n feature = tdesc_create_feature (result, \"%s\");\n", + e->name); + } - for (ix = 0; VEC_iterate (property_s, tdesc->properties, ix, prop); - ix++) - { - printf_unfiltered (" set_tdesc_property (result, \"%s\", \"%s\");\n", - prop->key, prop->value); - } + void visit_end (const target_desc *e) override + { + printf_unfiltered ("\n tdesc_%s = result;\n", m_function); + printf_unfiltered ("}\n"); + } - for (ix = 0; - VEC_iterate (tdesc_feature_p, tdesc->features, ix, feature); - ix++) - { - printf_unfiltered (" \ -feature = tdesc_create_feature (result, \"%s\");\n", - feature->name); + void visit (const tdesc_type *type) override + { + struct tdesc_type_field *f; - for (ix2 = 0; - VEC_iterate (tdesc_type_p, feature->types, ix2, type); - ix2++) - { - switch (type->kind) - { - case TDESC_TYPE_VECTOR: - printf_unfiltered - (" field_type = tdesc_named_type (feature, \"%s\");\n", - type->u.v.type->name); + /* Now we do some "filtering" in order to know which variables to + declare. This is needed because otherwise we would declare unused + variables `field_type' and `type'. */ + if (!m_printed_field_type) + { + printf_unfiltered (" struct tdesc_type *field_type;\n"); + m_printed_field_type = true; + } + + if ((type->kind == TDESC_TYPE_UNION + || type->kind == TDESC_TYPE_STRUCT + || type->kind == TDESC_TYPE_FLAGS + || type->kind == TDESC_TYPE_ENUM) + && VEC_length (tdesc_type_field, type->u.u.fields) > 0 + && !m_printed_type) + { + printf_unfiltered (" struct tdesc_type *type;\n"); + m_printed_type = true; + } + + switch (type->kind) + { + case TDESC_TYPE_VECTOR: + printf_unfiltered + (" field_type = tdesc_named_type (feature, \"%s\");\n", + type->u.v.type->name); + printf_unfiltered + (" tdesc_create_vector (feature, \"%s\", field_type, %d);\n", + type->name, type->u.v.count); + break; + case TDESC_TYPE_STRUCT: + case TDESC_TYPE_FLAGS: + if (type->kind == TDESC_TYPE_STRUCT) + { + printf_unfiltered + (" type = tdesc_create_struct (feature, \"%s\");\n", + type->name); + if (type->u.u.size != 0) printf_unfiltered - (" tdesc_create_vector (feature, \"%s\", field_type, %d);\n", - type->name, type->u.v.count); - break; - case TDESC_TYPE_STRUCT: - case TDESC_TYPE_FLAGS: - if (type->kind == TDESC_TYPE_STRUCT) - { - printf_unfiltered - (" type = tdesc_create_struct (feature, \"%s\");\n", - type->name); - if (type->u.u.size != 0) + (" tdesc_set_struct_size (type, %d);\n", + type->u.u.size); + } + else + { + printf_unfiltered + (" type = tdesc_create_flags (feature, \"%s\", %d);\n", + type->name, type->u.u.size); + } + for (int ix3 = 0; + VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); + ix3++) + { + const char *type_name; + + gdb_assert (f->type != NULL); + type_name = f->type->name; + + /* To minimize changes to generated files, don't emit type + info for fields that have defaulted types. */ + if (f->start != -1) + { + gdb_assert (f->end != -1); + if (f->type->kind == TDESC_TYPE_BOOL) + { + gdb_assert (f->start == f->end); printf_unfiltered - (" tdesc_set_struct_size (type, %d);\n", - type->u.u.size); - } - else - { - printf_unfiltered - (" type = tdesc_create_flags (feature, \"%s\", %d);\n", - type->name, type->u.u.size); - } - for (ix3 = 0; - VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); - ix3++) - { - const char *type_name; - - gdb_assert (f->type != NULL); - type_name = f->type->name; - - /* To minimize changes to generated files, don't emit type - info for fields that have defaulted types. */ - if (f->start != -1) - { - gdb_assert (f->end != -1); - if (f->type->kind == TDESC_TYPE_BOOL) - { - gdb_assert (f->start == f->end); - printf_unfiltered - (" tdesc_add_flag (type, %d, \"%s\");\n", - f->start, f->name); - } - else if ((type->u.u.size == 4 - && f->type->kind == TDESC_TYPE_UINT32) - || (type->u.u.size == 8 - && f->type->kind == TDESC_TYPE_UINT64)) - { - printf_unfiltered - (" tdesc_add_bitfield (type, \"%s\", %d, %d);\n", - f->name, f->start, f->end); - } - else - { - printf_unfiltered - (" field_type = tdesc_named_type (feature," - " \"%s\");\n", - type_name); - printf_unfiltered - (" tdesc_add_typed_bitfield (type, \"%s\"," - " %d, %d, field_type);\n", - f->name, f->start, f->end); - } - } - else /* Not a bitfield. */ - { - gdb_assert (f->end == -1); - gdb_assert (type->kind == TDESC_TYPE_STRUCT); - printf_unfiltered - (" field_type = tdesc_named_type (feature," - " \"%s\");\n", - type_name); - printf_unfiltered - (" tdesc_add_field (type, \"%s\", field_type);\n", - f->name); - } - } - break; - case TDESC_TYPE_UNION: - printf_unfiltered - (" type = tdesc_create_union (feature, \"%s\");\n", - type->name); - for (ix3 = 0; - VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); - ix3++) - { - printf_unfiltered - (" field_type = tdesc_named_type (feature, \"%s\");\n", - f->type->name); - printf_unfiltered - (" tdesc_add_field (type, \"%s\", field_type);\n", - f->name); - } - break; - case TDESC_TYPE_ENUM: - printf_unfiltered - (" type = tdesc_create_enum (feature, \"%s\", %d);\n", - type->name, type->u.u.size); - for (ix3 = 0; - VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); - ix3++) + (" tdesc_add_flag (type, %d, \"%s\");\n", + f->start, f->name); + } + else if ((type->u.u.size == 4 + && f->type->kind == TDESC_TYPE_UINT32) + || (type->u.u.size == 8 + && f->type->kind == TDESC_TYPE_UINT64)) + { + printf_unfiltered + (" tdesc_add_bitfield (type, \"%s\", %d, %d);\n", + f->name, f->start, f->end); + } + else + { + printf_unfiltered + (" field_type = tdesc_named_type (feature," + " \"%s\");\n", + type_name); + printf_unfiltered + (" tdesc_add_typed_bitfield (type, \"%s\"," + " %d, %d, field_type);\n", + f->name, f->start, f->end); + } + } + else /* Not a bitfield. */ + { + gdb_assert (f->end == -1); + gdb_assert (type->kind == TDESC_TYPE_STRUCT); printf_unfiltered - (" tdesc_add_enum_value (type, %d, \"%s\");\n", - f->start, f->name); - break; - default: - error (_("C output is not supported type \"%s\"."), type->name); - } - printf_unfiltered ("\n"); - } + (" field_type = tdesc_named_type (feature," + " \"%s\");\n", + type_name); + printf_unfiltered + (" tdesc_add_field (type, \"%s\", field_type);\n", + f->name); + } + } + break; + case TDESC_TYPE_UNION: + printf_unfiltered + (" type = tdesc_create_union (feature, \"%s\");\n", + type->name); + for (int ix3 = 0; + VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); + ix3++) + { + printf_unfiltered + (" field_type = tdesc_named_type (feature, \"%s\");\n", + f->type->name); + printf_unfiltered + (" tdesc_add_field (type, \"%s\", field_type);\n", + f->name); + } + break; + case TDESC_TYPE_ENUM: + printf_unfiltered + (" type = tdesc_create_enum (feature, \"%s\", %d);\n", + type->name, type->u.u.size); + for (int ix3 = 0; + VEC_iterate (tdesc_type_field, type->u.u.fields, ix3, f); + ix3++) + printf_unfiltered + (" tdesc_add_enum_value (type, %d, \"%s\");\n", + f->start, f->name); + break; + default: + error (_("C output is not supported type \"%s\"."), type->name); + } + printf_unfiltered ("\n"); + } - for (ix2 = 0; - VEC_iterate (tdesc_reg_p, feature->registers, ix2, reg); - ix2++) - { - printf_unfiltered (" tdesc_create_reg (feature, \"%s\", %ld, %d, ", - reg->name, reg->target_regnum, reg->save_restore); - if (reg->group) - printf_unfiltered ("\"%s\", ", reg->group); - else - printf_unfiltered ("NULL, "); - printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type); - } + void visit (const tdesc_reg *reg) override + { + printf_unfiltered (" tdesc_create_reg (feature, \"%s\", %ld, %d, ", + reg->name, reg->target_regnum, reg->save_restore); + if (reg->group) + printf_unfiltered ("\"%s\", ", reg->group); + else + printf_unfiltered ("NULL, "); + printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type); + } - printf_unfiltered ("\n"); - } +private: + char *m_function; + std::string m_filename_after_features; + bool m_printed_field_type = false; + bool m_printed_type = false; +}; + +static void +maint_print_c_tdesc_cmd (char *args, int from_tty) +{ + const struct target_desc *tdesc; + + /* Use the global target-supplied description, not the current + architecture's. This lets a GDB for one architecture generate C + for another architecture's description, even though the gdbarch + initialization code will reject the new description. */ + tdesc = current_target_desc; + if (tdesc == NULL) + error (_("There is no target description to print.")); + + if (target_description_filename == NULL) + error (_("The current target description did not come from an XML file.")); + + std::string filename_after_features (target_description_filename); + auto loc = filename_after_features.rfind ("/features/"); + + if (loc != std::string::npos) + filename_after_features = filename_after_features.substr (loc + 10); + + print_c_tdesc v (filename_after_features); - printf_unfiltered (" tdesc_%s = result;\n", function); - printf_unfiltered ("}\n"); + tdesc->accept (v); } /* Provide a prototype to silence -Wmissing-prototypes. */