From patchwork Fri Dec 20 16:47:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 37026 Received: (qmail 19290 invoked by alias); 20 Dec 2019 16:47:33 -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 19140 invoked by uid 89); 20 Dec 2019 16:47:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=22013, puts, occupied, sk:class_t X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 20 Dec 2019 16:47:24 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id 2BC212058E; Fri, 20 Dec 2019 11:47:20 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id 730D5204BF; Fri, 20 Dec 2019 11:47:08 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id E3DA72816F; Fri, 20 Dec 2019 11:47:07 -0500 (EST) X-Gerrit-PatchSet: 3 Date: Fri, 20 Dec 2019 11:47:06 -0500 From: "Sourceware to Gerrit sync (Code Review)" To: Tankut Baris Aktemur , Andrew Burgess , Tom Tromey , Simon Marchi , gdb-patches@sourceware.org Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [pushed] infcall, c++: allow more info to be computed for pass-by-reference va... X-Gerrit-Change-Id: Ib1c1f87f2490a5737c469f7b7185ddc7f6a164cb X-Gerrit-Change-Number: 136 X-Gerrit-ChangeURL: X-Gerrit-Commit: 9d084466d740e40c655609f9c04b3bb2b9b9ca76 In-Reply-To: References: Reply-To: noreply@gnutoolchain-gerrit.osci.io, tankut.baris.aktemur@intel.com, simon.marchi@polymtl.ca, tromey@sourceware.org, andrew.burgess@embecosm.com, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-79-g83ff7f88f1 Message-Id: <20191220164707.E3DA72816F@gnutoolchain-gerrit.osci.io> The original change was created by Tankut Baris Aktemur. Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/136 ...................................................................... infcall, c++: allow more info to be computed for pass-by-reference values In C++, call-by-value arguments that cannot be trivially copied are implicitly passed by reference. When making an infcall, GDB needs to find out if an argument is pass-by-reference or not, so that the correct semantics can be followed. This patch enriches the information computed by the language ops for pass-by-reference arguments. Instead of a plain binary result, the computed information now includes whether the argument is - copy constructible - destructible - trivially copyable - trivially copy constructible - trivially destructible This information is stored in a struct named 'language_pass_by_ref_info'. This patch paves the way for GDB's infcall mechanism to call the copy ctor and the destructor of a pass-by-ref argument appropriately. gdb/ChangeLog: 2019-12-20 Tankut Baris Aktemur * language.h (struct language_pass_by_ref_info): New struct. (struct language_defn): Change the signature to return a language_pass_by_ref_info instead of an int. (language_pass_by_reference): Ditto. (default_pass_by_reference): Ditto. Adjust the users listed below. * arch-utils.c (default_return_in_first_hidden_param_p): Update. * cp-abi.c (cp_pass_by_reference): Update. * cp-abi.h (cp_pass_by_reference): Update declaration. (struct cp_abi_ops): Update. * gnu-v3-abi.c (gnuv3_pass_by_reference): Update. * infcall.c (call_function_by_hand_dummy): Update. * language.c (language_pass_by_reference): Update. (default_pass_by_reference): Update. * tic6x-tdep.c (tic6x_return_value): Update. Change-Id: Ib1c1f87f2490a5737c469f7b7185ddc7f6a164cb --- M gdb/ChangeLog M gdb/arch-utils.c M gdb/cp-abi.c M gdb/cp-abi.h M gdb/gnu-v3-abi.c M gdb/infcall.c M gdb/language.c M gdb/language.h M gdb/tic6x-tdep.c 9 files changed, 131 insertions(+), 40 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5175ebc..3e88754 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,24 @@ 2019-12-20 Tankut Baris Aktemur + * language.h (struct language_pass_by_ref_info): New struct. + (struct language_defn): Change the signature + to return a language_pass_by_ref_info instead of an int. + (language_pass_by_reference): Ditto. + (default_pass_by_reference): Ditto. + Adjust the users listed below. + * arch-utils.c (default_return_in_first_hidden_param_p): + Update. + * cp-abi.c (cp_pass_by_reference): Update. + * cp-abi.h (cp_pass_by_reference): Update declaration. + (struct cp_abi_ops): Update. + * gnu-v3-abi.c (gnuv3_pass_by_reference): Update. + * infcall.c (call_function_by_hand_dummy): Update. + * language.c (language_pass_by_reference): Update. + (default_pass_by_reference): Update. + * tic6x-tdep.c (tic6x_return_value): Update. + +2019-12-20 Tankut Baris Aktemur + * dwarf2read.c (dwarf2_add_member_fn): Read the DW_AT_defaulted and DW_AT_deleted attributes of a function. (read_structure_type): Read the DW_AT_calling_convention attribute diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 2129c3b..a1a003f 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -858,7 +858,7 @@ /* Usually, the return value's address is stored the in the "first hidden" parameter if the return value should be passed by reference, as specified in ABI. */ - return language_pass_by_reference (type); + return !(language_pass_by_reference (type).trivially_copyable); } int default_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr) diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c index bbb74d4..6503b4c 100644 --- a/gdb/cp-abi.c +++ b/gdb/cp-abi.c @@ -220,11 +220,13 @@ return (*current_cp_abi.get_typename_from_type_info) (value); } -int +/* See cp-abi.h. */ + +struct language_pass_by_ref_info cp_pass_by_reference (struct type *type) { if ((current_cp_abi.pass_by_reference) == NULL) - return 0; + return default_pass_by_reference (type); return (*current_cp_abi.pass_by_reference) (type); } diff --git a/gdb/cp-abi.h b/gdb/cp-abi.h index 3cbf19c..cc77e0b 100644 --- a/gdb/cp-abi.h +++ b/gdb/cp-abi.h @@ -207,9 +207,11 @@ CORE_ADDR cplus_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc); -/* Return non-zero if an argument of type TYPE should be passed by - reference instead of value. */ -extern int cp_pass_by_reference (struct type *type); +/* Return a struct that provides pass-by-reference information + about the given TYPE. */ + +extern struct language_pass_by_ref_info cp_pass_by_reference + (struct type *type); struct cp_abi_ops { @@ -246,7 +248,7 @@ struct type *(*get_type_from_type_info) (struct value *value); std::string (*get_typename_from_type_info) (struct value *value); CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR); - int (*pass_by_reference) (struct type *type); + struct language_pass_by_ref_info (*pass_by_reference) (struct type *type); }; diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index d630ec0..35197e5 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -1230,7 +1230,7 @@ return real_stop_pc; } -/* Return nonzero if a type should be passed by reference. +/* Return pass-by-reference information for the given TYPE. The rule in the v3 ABI document comes from section 3.1.1. If the type has a non-trivial copy constructor or destructor, then the @@ -1248,22 +1248,33 @@ We don't do anything with the constructors or destructors, but we have to get the argument passing right anyway. */ -static int + +static struct language_pass_by_ref_info gnuv3_pass_by_reference (struct type *type) { int fieldnum, fieldelem; type = check_typedef (type); + /* Start with the default values. */ + struct language_pass_by_ref_info info + = default_pass_by_reference (type); + + /* FIXME: Currently, this implementation only fills in the + 'trivially-copyable' field to preserve GDB's existing behavior. */ + /* We're only interested in things that can have methods. */ if (TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) - return 0; + return info; /* A dynamic class has a non-trivial copy constructor. See c++98 section 12.8 Copying class objects [class.copy]. */ if (gnuv3_dynamic_class (type)) - return 1; + { + info.trivially_copyable = false; + return info; + } for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++) for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum); @@ -1280,7 +1291,10 @@ /* If we've found a destructor, we must pass this by reference. */ if (name[0] == '~') - return 1; + { + info.trivially_copyable = false; + return info; + } /* If the mangled name of this method doesn't indicate that it is a constructor, we're not interested. @@ -1302,11 +1316,13 @@ if (TYPE_CODE (arg_type) == TYPE_CODE_REF) { - struct type *arg_target_type; - - arg_target_type = check_typedef (TYPE_TARGET_TYPE (arg_type)); + struct type *arg_target_type + = check_typedef (TYPE_TARGET_TYPE (arg_type)); if (class_types_same_p (arg_target_type, type)) - return 1; + { + info.trivially_copyable = false; + return info; + } } } } @@ -1319,11 +1335,18 @@ about recursive loops here, since we are only looking at members of complete class type. Also ignore any static members. */ for (fieldnum = 0; fieldnum < TYPE_NFIELDS (type); fieldnum++) - if (! field_is_static (&TYPE_FIELD (type, fieldnum)) - && gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum))) - return 1; + if (!field_is_static (&TYPE_FIELD (type, fieldnum))) + { + struct language_pass_by_ref_info field_info + = gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum)); + if (!field_info.trivially_copyable) + { + info.trivially_copyable = false; + return info; + } + } - return 0; + return info; } static void diff --git a/gdb/infcall.c b/gdb/infcall.c index 5553fc9..f3664d5 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -1020,7 +1020,8 @@ args[i] = value_arg_coerce (gdbarch, args[i], param_type, prototyped); - if (param_type != NULL && language_pass_by_reference (param_type)) + if (param_type != NULL + && !(language_pass_by_reference (param_type).trivially_copyable)) args[i] = value_addr (args[i]); } diff --git a/gdb/language.c b/gdb/language.c index 76efc49..ac74c7f 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -652,21 +652,23 @@ return NULL; } -/* Return non-zero if TYPE should be passed (and returned) by - reference at the language level. */ -int +/* Return information about whether TYPE should be passed + (and returned) by reference at the language level. */ + +struct language_pass_by_ref_info language_pass_by_reference (struct type *type) { return current_language->la_pass_by_reference (type); } -/* Return zero; by default, types are passed by value at the language - level. The target ABI may pass or return some structs by reference - independent of this. */ -int +/* Return a default struct that provides pass-by-reference information + about the given TYPE. Languages should update the default values + as appropriate. */ + +struct language_pass_by_ref_info default_pass_by_reference (struct type *type) { - return 0; + return {}; } /* Return the default string containing the list of characters diff --git a/gdb/language.h b/gdb/language.h index 14d6fac..f6cd29b 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -128,6 +128,47 @@ struct type *bool_type_default; }; +/* In a language (particularly C++) a function argument of an aggregate + type (i.e. class/struct/union) may be implicitly passed by reference + even though it is declared a call-by-value argument in the source. + The struct below puts together necessary information for GDB to be + able to detect and carry out pass-by-reference semantics for a + particular type. This type is referred as T in the inlined comments + below. + + The default values of the fields are chosen to give correct semantics + for primitive types and for simple aggregate types, such as + + class T { + int x; + }; */ + +struct language_pass_by_ref_info +{ + /* True if an argument of type T can be passed to a function by value + (i.e. not through an implicit reference). False, otherwise. */ + bool trivially_copyable = true; + + /* True if a copy of a value of type T can be initialized by + memcpy'ing the value bit-by-bit. False, otherwise. + E.g. If T has a user-defined copy ctor, this should be false. */ + bool trivially_copy_constructible = true; + + /* True if a value of type T can be destructed simply by reclaiming + the memory area occupied by the value. False, otherwise. + E.g. If T has a user-defined destructor, this should be false. */ + bool trivially_destructible = true; + + /* True if it is allowed to create a copy of a value of type T. + False, otherwise. + E.g. If T has a deleted copy ctor, this should be false. */ + bool copy_constructible = true; + + /* True if a value of type T can be destructed. False, otherwise. + E.g. If T has a deleted destructor, this should be false. */ + bool destructible = true; +}; + /* Structure tying together assorted information about a language. */ struct language_defn @@ -356,9 +397,10 @@ struct ui_file *stream, const struct value_print_options *options); - /* Return non-zero if TYPE should be passed (and returned) by - reference at the language level. */ - int (*la_pass_by_reference) (struct type *type); + /* Return information about whether TYPE should be passed + (and returned) by reference at the language level. */ + struct language_pass_by_ref_info (*la_pass_by_reference) + (struct type *type); /* Return an expression that can be used for a location watchpoint. TYPE is a pointer type that points to the memory @@ -613,14 +655,14 @@ struct ui_file *stream, const struct value_print_options *options); -/* Return non-zero if TYPE should be passed (and returned) by - reference at the language level. */ -int language_pass_by_reference (struct type *type); +/* Return information about whether TYPE should be passed + (and returned) by reference at the language level. */ +struct language_pass_by_ref_info language_pass_by_reference (struct type *type); -/* Return zero; by default, types are passed by value at the language - level. The target ABI may pass or return some structs by reference - independent of this. */ -int default_pass_by_reference (struct type *type); +/* Return a default struct that provides pass-by-reference information + about the given TYPE. Languages should update the default values + as appropriate. */ +struct language_pass_by_ref_info default_pass_by_reference (struct type *type); /* The default implementation of la_print_typedef. */ void default_print_typedef (struct type *type, struct symbol *new_symbol, diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c index 2df83c4..ca059f9 100644 --- a/gdb/tic6x-tdep.c +++ b/gdb/tic6x-tdep.c @@ -784,7 +784,7 @@ if (type != NULL) { type = check_typedef (type); - if (language_pass_by_reference (type)) + if (!(language_pass_by_reference (type).trivially_copyable)) return RETURN_VALUE_STRUCT_CONVENTION; } }