From patchwork Fri Mar 23 14:54:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 26440 Received: (qmail 61499 invoked by alias); 23 Mar 2018 14:54:15 -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 61484 invoked by uid 89); 23 Mar 2018 14:54:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LOTSOFHASH, KAM_SHORT, MIME_BASE64_BLANKS, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=didn, Hx-spam-relays-external:15.20.0609.012, H*RU:15.20.0609.012, H*r:15.20.0609.012 X-HELO: EUR01-HE1-obe.outbound.protection.outlook.com Received: from mail-he1eur01on0061.outbound.protection.outlook.com (HELO EUR01-HE1-obe.outbound.protection.outlook.com) (104.47.0.61) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 23 Mar 2018 14:54:11 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com (10.160.211.19) by AM3PR08MB0006.eurprd08.prod.outlook.com (10.160.236.140) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.567.14; Fri, 23 Mar 2018 14:54:05 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::64e8:8f30:eae8:a839]) by AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::64e8:8f30:eae8:a839%13]) with mapi id 15.20.0609.012; Fri, 23 Mar 2018 14:54:05 +0000 From: Alan Hayward To: Simon Marchi CC: "gdb-patches@sourceware.org" , nd Subject: Re: [PATCH v4 02/10] Make gdbserver reg_defs a vector of objects Date: Fri, 23 Mar 2018 14:54:05 +0000 Message-ID: References: <20180322084429.26250-1-alan.hayward@arm.com> <20180322084429.26250-3-alan.hayward@arm.com> <74733d19-17a0-6a38-73d0-e1201f27d5cd@ericsson.com> In-Reply-To: <74733d19-17a0-6a38-73d0-e1201f27d5cd@ericsson.com> authentication-results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; AM3PR08MB0006; 7:cvzxfq7Z8fDPOpntZkAnzuEKNUyxv+eH8w9MjzqJPg2UpkWgJ1ovHLHUg7p9OXWqyoJG2LwRka26he6IB4UwmM4kiQub1IY3RXBiZPBIYgULAQspLd8v1yTl+lTkWwa50i43dCAulNYtUEM9yAPnAK2YJNIEG+H9YmGCBBfouxzVT3zTGweR2/uW+3o5sLIiPoZC3q7xnNu5toGx/Imyc9pd+1bH/aLvAYLMKjPLqL0TfLqk8/nmwYcsv4UvW2fa x-ms-exchange-antispam-srfa-diagnostics: SOS; x-ms-office365-filtering-ht: Tenant x-ms-office365-filtering-correlation-id: 8f3f3c50-6870-468d-bfe4-08d590cdecc7 x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(3008032)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:AM3PR08MB0006; x-ms-traffictypediagnostic: AM3PR08MB0006: nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(37575265505322)(250305191791016)(180628864354917)(22074186197030)(131327999870524)(788757137089); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(3231221)(944501327)(52105095)(10201501046)(6055026)(6041310)(20161123562045)(20161123560045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(6072148)(201708071742011); SRVR:AM3PR08MB0006; BCL:0; PCL:0; RULEID:; SRVR:AM3PR08MB0006; x-forefront-prvs: 0620CADDF3 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(376002)(346002)(39860400002)(39380400002)(366004)(396003)(377424004)(199004)(189003)(51914003)(51444003)(53546011)(72206003)(106356001)(66066001)(3280700002)(6436002)(68736007)(186003)(81156014)(26005)(6116002)(99286004)(25786009)(8936002)(966005)(54906003)(6512007)(11346002)(6916009)(59450400001)(102836004)(76176011)(81166006)(3846002)(2906002)(105586002)(6506007)(6246003)(316002)(33656002)(53946003)(6306002)(82746002)(305945005)(36756003)(2900100001)(8676002)(7736002)(53936002)(5660300001)(229853002)(14454004)(575784001)(446003)(97736004)(83716003)(6486002)(3660700001)(5250100002)(478600001)(4326008)(86362001)(481834002); DIR:OUT; SFP:1101; SCL:1; SRVR:AM3PR08MB0006; H:AM3PR08MB0101.eurprd08.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: YPoAh9kVpQ3QiAXaAAAnHgmPYboDRr47eli8cczCqlqEYxOy74m1Gqlvfm3UDPZ+JwWvB+3nNkunLaLlltpS42Z+X11Nn8Ca5cyNKEIEr272RDbcwjlvb5olvYdWO01nn9f6UGVuU4eOjqW7Ufrgy0dyL3ZkLHMDjqThw8ML7EVBoaaoq6wtDn9eWlx5ledbwxMXnCxhFotnqtY6gn9Gv2WrHqGDIu971t5yLKKRLFqLFoVcgknISby83EGpIq/Cb/XgDMdfUiioOJ/zXTKsZFjQlxf1HMXWl7rh2KHRLHW+8TXG4ibnazTHJDz6U7y/bdpKRosrl9ZS+2I0e3zpWw== spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <25DCDB84ECEF2747B2F62C5A8B0E5882@eurprd08.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8f3f3c50-6870-468d-bfe4-08d590cdecc7 X-MS-Exchange-CrossTenant-originalarrivaltime: 23 Mar 2018 14:54:05.5346 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM3PR08MB0006 X-IsSubscribed: yes > On 22 Mar 2018, at 21:33, Simon Marchi wrote: > > On 2018-03-22 04:44 AM, alan.hayward@arm.com wrote: >> From: Alan Hayward >> >> Following a suggestion from Philipp, this patch changes reg_defs in >> gdbserver tdesc so that it is a vector of objects instead of a vector >> of pointers. Updated uses of reg_defs to use references. >> >> This change reduces the number of small hunks allocated when building >> reg_defs. >> >> find_register_by_number() is only used by regcache, therefore I made >> it a static function and moved it earlier in the file so that find_regno() >> could use it. The eventual plan is to replace this with accessor functions >> in a common tdesc class. >> >> Alan. >> >> 2018-03-21 Alan Hayward >> >> gdb/gdbserver/ >> * regcache.c (find_register_by_number): Make static and return a ref. >> (find_regno): Use find_register_by_number >> (register_size): Use references. >> (register_data): Likewise. >> * regcache.h (struct reg): Remove declaration. >> * tdesc.c (target_desc::~target_desc): Remove free calls. >> (target_desc::operator==): Use references. >> (init_target_desc): Likewise. >> (tdesc_create_reg): Use references and resize in a single call. >> * tdesc.h (struct target_desc): Replace pointer with object. >> --- >> gdb/gdbserver/regcache.c | 27 +++++++++++---------------- >> gdb/gdbserver/regcache.h | 4 ---- >> gdb/gdbserver/tdesc.c | 30 ++++++++++++++---------------- >> gdb/gdbserver/tdesc.h | 2 +- >> 4 files changed, 26 insertions(+), 37 deletions(-) >> >> diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c >> index 1bb15900dd..df5b9e9dd2 100644 >> --- a/gdb/gdbserver/regcache.c >> +++ b/gdb/gdbserver/regcache.c >> @@ -196,6 +196,13 @@ regcache_cpy (struct regcache *dst, struct regcache *src) >> dst->registers_valid = src->registers_valid; >> } >> >> +/* Return a reference to the description of register ``n''. */ >> + >> +static const struct reg & >> +find_register_by_number (const struct target_desc *tdesc, int n) >> +{ >> + return tdesc->reg_defs[n]; >> +} >> >> #ifndef IN_PROCESS_AGENT >> >> @@ -243,25 +250,13 @@ int >> find_regno (const struct target_desc *tdesc, const char *name) >> { >> for (int i = 0; i < tdesc->reg_defs.size (); ++i) >> - { >> - struct reg *reg = tdesc->reg_defs[i]; >> + if (strcmp (name, find_register_by_number (tdesc, i).name) == 0) >> + return i; >> >> - if (strcmp (name, reg->name) == 0) >> - return i; >> - } >> internal_error (__FILE__, __LINE__, "Unknown register %s requested", >> name); > > Please keep the curly braces for the for, as shown here: > > https://www.gnu.org/prep/standards/html_node/Syntactic-Conventions.html#index-multiple-variables-in-a-line > > Can you put the moving of this function/making it static/removing the declaration > in its own patch? It's pre-approved, with that fixed. > Ok, I’ve pushed this bit as requested: diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c index 1bb15900dd..d6511fda65 100644 --- a/gdb/gdbserver/regcache.c +++ b/gdb/gdbserver/regcache.c @@ -196,6 +196,13 @@ regcache_cpy (struct regcache *dst, struct regcache *src) dst->registers_valid = src->registers_valid; } +/* Return a pointer to the description of register N. */ + +static const struct reg * +find_register_by_number (const struct target_desc *tdesc, int n) +{ + return tdesc->reg_defs[n]; +} #ifndef IN_PROCESS_AGENT @@ -244,24 +251,13 @@ find_regno (const struct target_desc *tdesc, const char *name) { for (int i = 0; i < tdesc->reg_defs.size (); ++i) { - struct reg *reg = tdesc->reg_defs[i]; - - if (strcmp (name, reg->name) == 0) + if (strcmp (name, find_register_by_number (tdesc, i)->name) == 0) return i; } internal_error (__FILE__, __LINE__, "Unknown register %s requested", name); } -#endif - -struct reg * -find_register_by_number (const struct target_desc *tdesc, int n) -{ - return tdesc->reg_defs[n]; -} - -#ifndef IN_PROCESS_AGENT static void free_register_cache_thread (struct thread_info *thread) { diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h index 3a75ce3fe1..6ff13084b0 100644 --- a/gdb/gdbserver/regcache.h +++ b/gdb/gdbserver/regcache.h @@ -94,10 +94,6 @@ void registers_from_string (struct regcache *regcache, char *buf); void regcache_write_pc (struct regcache *regcache, CORE_ADDR pc); -/* Return a pointer to the description of register ``n''. */ - -struct reg *find_register_by_number (const struct target_desc *tdesc, int n); - int register_cache_size (const struct target_desc *tdesc); int register_size (const struct target_desc *tdesc, int n); >> } >> >> -#endif >> - >> -struct reg * >> -find_register_by_number (const struct target_desc *tdesc, int n) >> -{ >> - return tdesc->reg_defs[n]; >> -} >> - >> -#ifndef IN_PROCESS_AGENT >> static void >> free_register_cache_thread (struct thread_info *thread) >> { >> @@ -292,7 +287,7 @@ register_cache_size (const struct target_desc *tdesc) >> int >> register_size (const struct target_desc *tdesc, int n) >> { >> - return find_register_by_number (tdesc, n)->size / 8; >> + return find_register_by_number (tdesc, n).size / 8; >> } >> >> /* See common/common-regcache.h. */ >> @@ -307,7 +302,7 @@ static unsigned char * >> register_data (struct regcache *regcache, int n, int fetch) >> { >> return (regcache->registers >> - + find_register_by_number (regcache->tdesc, n)->offset / 8); >> + + find_register_by_number (regcache->tdesc, n).offset / 8); >> } >> >> /* Supply register N, whose contents are stored in BUF, to REGCACHE. >> diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h >> index 3a75ce3fe1..6ff13084b0 100644 >> --- a/gdb/gdbserver/regcache.h >> +++ b/gdb/gdbserver/regcache.h >> @@ -94,10 +94,6 @@ void registers_from_string (struct regcache *regcache, char *buf); >> >> void regcache_write_pc (struct regcache *regcache, CORE_ADDR pc); >> >> -/* Return a pointer to the description of register ``n''. */ >> - >> -struct reg *find_register_by_number (const struct target_desc *tdesc, int n); >> - >> int register_cache_size (const struct target_desc *tdesc); >> >> int register_size (const struct target_desc *tdesc, int n); >> diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c >> index e50a848e2f..8e68a27c7c 100644 >> --- a/gdb/gdbserver/tdesc.c >> +++ b/gdb/gdbserver/tdesc.c >> @@ -25,9 +25,6 @@ target_desc::~target_desc () >> { >> int i; >> >> - for (reg *reg : reg_defs) >> - xfree (reg); >> - >> xfree ((char *) arch); >> xfree ((char *) osabi); >> >> @@ -45,10 +42,10 @@ bool target_desc::operator== (const target_desc &other) const >> >> for (int i = 0; i < reg_defs.size (); ++i) >> { >> - struct reg *reg = reg_defs[i]; >> - struct reg *reg2 = other.reg_defs[i]; >> + struct reg reg = reg_defs[i]; >> + struct reg reg2 = other.reg_defs[i]; >> >> - if (reg != reg2 && *reg != *reg2) >> + if (® != ®2 && reg != reg2) > > I don't think the first part, "® != ®", makes sense. It's comparing > the addresses of the local variables. Also, that comparison only made > sense as a shortcut when the vector held pointers to dynamically allocated > memory. So I think it should just be removed. > > Actually, now that the vector elements are the objects directly, I think that > this whole for loop could be replaced with: > > if (reg_defs != other.reg_defs) > return false; > > The if that compares the vector sizes above that can also be removed, since > it's also done by std::vector::operator==: > > template > inline bool > operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) > { return (__x.size() == __y.size() > && std::equal(__x.begin(), __x.end(), __y.begin())); } > Didn’t realise that std:vector worked like this. Agreed with the change. >> return false; >> } >> >> @@ -72,10 +69,10 @@ init_target_desc (struct target_desc *tdesc) >> { >> int offset = 0; >> >> - for (reg *reg : tdesc->reg_defs) >> + for (reg ® : tdesc->reg_defs) >> { >> - reg->offset = offset; >> - offset += reg->size; >> + reg.offset = offset; >> + offset += reg.size; >> } >> >> tdesc->registers_size = offset / 8; >> @@ -240,24 +237,25 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, >> int bitsize, const char *type) >> { >> struct target_desc *tdesc = (struct target_desc *) feature; >> + int current_size = tdesc->reg_defs.size (); >> >> - while (tdesc->reg_defs.size () < regnum) >> - { >> - struct reg *reg = XCNEW (struct reg); >> + tdesc->reg_defs.resize (regnum != 0 ? regnum + 1 : current_size + 1); >> >> + while (current_size < regnum) >> + { >> + struct reg *reg = &tdesc->reg_defs[current_size]; >> reg->name = ""; >> reg->size = 0; >> - tdesc->reg_defs.push_back (reg); >> + current_size++; >> } >> >> gdb_assert (regnum == 0 >> - || regnum == tdesc->reg_defs.size ()); >> + || regnum + 1 == tdesc->reg_defs.size ()); >> >> - struct reg *reg = XCNEW (struct reg); >> + struct reg *reg = &tdesc->reg_defs.back (); >> >> reg->name = name; >> reg->size = bitsize; >> - tdesc->reg_defs.push_back (reg); >> } > > To simplify this further, I would suggest adding a default constructor to reg > that initializes everything to nullptr/0, and adding a constructor that takes > parameters. The .resize() will only be necessary if regnum != 0 and will > automatically initialize all the unused register slots properly, so the for > loop will be unnecessary: > > if (regnum != 0) > tdesc->reg_defs.resize (regnum); > > The register can then be added with > > tdesc->reg_defs.emplace_back (name, bitsize); I need to remember to think in C++ and not C. This way is much nicer/simpler. > > One behavior that might change compared to the previous code is when trying to > add a register with a regnum smaller than the current size of the vector. I > think that the old code would have asserted, but the new code would just > accept it and resize the vector to a smaller size. Could you verify? In that > case, maybe we should move the gdb_assert to the beginning of the function: > > gdb_assert (regnum == 0 || regnum >= tdesc->reg_defs.size ()) > > something like that. It can also be moved under the "if (regnum != 0)" shown > above. Yes, in the old code, if you give it a smaller regnum, vector wouldn’t have been resized, and then the assert would have fired. I’ll move the assert to the top of the function to ensure it doesn’t resize smaller. New version updated with all of the above. Checked this on X86 with make check on target board gdbserver. (Patch 3/10, and possibly others, will need updating too, but should be obvious). Thanks for the review. Alan. gdb/ * regformats/regdef.h (reg): Add constructors. gdb/gdbserver/ * regcache.c (find_register_by_number): Return a ref. (find_regno): Use references. (register_size): Likewise. (register_data): Likewise. * tdesc.c (target_desc::~target_desc): Remove free calls. (target_desc::operator==): Use std::vector compare. (init_target_desc): Use reference. (tdesc_create_reg): Use reg constructors. * tdesc.h (struct target_desc): Replace pointer with object. diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c index d6511fda650ca52688cd4d7db1acd94e822a3c0d..cbdf766df2c2b95f605198c617ffead9f9ac3775 100644 --- a/gdb/gdbserver/regcache.c +++ b/gdb/gdbserver/regcache.c @@ -196,9 +196,9 @@ regcache_cpy (struct regcache *dst, struct regcache *src) dst->registers_valid = src->registers_valid; } -/* Return a pointer to the description of register N. */ +/* Return a reference to the description of register N. */ -static const struct reg * +static const struct reg & find_register_by_number (const struct target_desc *tdesc, int n) { return tdesc->reg_defs[n]; @@ -251,7 +251,7 @@ find_regno (const struct target_desc *tdesc, const char *name) { for (int i = 0; i < tdesc->reg_defs.size (); ++i) { - if (strcmp (name, find_register_by_number (tdesc, i)->name) == 0) + if (strcmp (name, find_register_by_number (tdesc, i).name) == 0) return i; } internal_error (__FILE__, __LINE__, "Unknown register %s requested", @@ -288,7 +288,7 @@ register_cache_size (const struct target_desc *tdesc) int register_size (const struct target_desc *tdesc, int n) { - return find_register_by_number (tdesc, n)->size / 8; + return find_register_by_number (tdesc, n).size / 8; } /* See common/common-regcache.h. */ @@ -303,7 +303,7 @@ static unsigned char * register_data (struct regcache *regcache, int n, int fetch) { return (regcache->registers - + find_register_by_number (regcache->tdesc, n)->offset / 8); + + find_register_by_number (regcache->tdesc, n).offset / 8); } /* Supply register N, whose contents are stored in BUF, to REGCACHE. diff --git a/gdb/gdbserver/tdesc.h b/gdb/gdbserver/tdesc.h index 4513ea74232a456cc86eb9a655904012ff117373..a62544341cd23a9a8ec6833e1eae73616a315d2d 100644 --- a/gdb/gdbserver/tdesc.h +++ b/gdb/gdbserver/tdesc.h @@ -34,7 +34,7 @@ struct target_desc : tdesc_feature { /* A vector of elements of register definitions that describe the inferior's register set. */ - std::vector reg_defs; + std::vector reg_defs; /* The register cache size, in bytes. */ int registers_size; diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c index e50a848e2f9f280a84ab139cfce4d1f17bd05884..877dbdaecac43f42c031dffafe2bd9f01b577038 100644 --- a/gdb/gdbserver/tdesc.c +++ b/gdb/gdbserver/tdesc.c @@ -25,9 +25,6 @@ target_desc::~target_desc () { int i; - for (reg *reg : reg_defs) - xfree (reg); - xfree ((char *) arch); xfree ((char *) osabi); @@ -40,18 +37,9 @@ target_desc::~target_desc () bool target_desc::operator== (const target_desc &other) const { - if (reg_defs.size () != other.reg_defs.size ()) + if (reg_defs != other.reg_defs) return false; - for (int i = 0; i < reg_defs.size (); ++i) - { - struct reg *reg = reg_defs[i]; - struct reg *reg2 = other.reg_defs[i]; - - if (reg != reg2 && *reg != *reg2) - return false; - } - /* Compare expedite_regs. */ int i = 0; for (; expedite_regs[i] != NULL; i++) @@ -72,10 +60,10 @@ init_target_desc (struct target_desc *tdesc) { int offset = 0; - for (reg *reg : tdesc->reg_defs) + for (reg ® : tdesc->reg_defs) { - reg->offset = offset; - offset += reg->size; + reg.offset = offset; + offset += reg.size; } tdesc->registers_size = offset / 8; @@ -241,23 +229,12 @@ tdesc_create_reg (struct tdesc_feature *feature, const char *name, { struct target_desc *tdesc = (struct target_desc *) feature; - while (tdesc->reg_defs.size () < regnum) - { - struct reg *reg = XCNEW (struct reg); - - reg->name = ""; - reg->size = 0; - tdesc->reg_defs.push_back (reg); - } - - gdb_assert (regnum == 0 - || regnum == tdesc->reg_defs.size ()); + gdb_assert (regnum == 0 || regnum >= tdesc->reg_defs.size ()); - struct reg *reg = XCNEW (struct reg); + if (regnum != 0) + tdesc->reg_defs.resize (regnum); - reg->name = name; - reg->size = bitsize; - tdesc->reg_defs.push_back (reg); + tdesc->reg_defs.emplace_back (name, 0, bitsize); } /* See common/tdesc.h. */ diff --git a/gdb/regformats/regdef.h b/gdb/regformats/regdef.h index 262d03c0785f48e83b784b6177c52e2d253a6067..1f7861fd98dd9085c3fe9d7ee4b8396999060265 100644 --- a/gdb/regformats/regdef.h +++ b/gdb/regformats/regdef.h @@ -21,6 +21,18 @@ struct reg { + reg () + : name (""), + offset (0), + size (0) + {} + + reg (const char *_name, int _offset, int _size) + : name (_name), + offset (_offset), + size (_size) + {} + /* The name of this register - NULL for pad entries. */ const char *name;