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 <tankut.baris.aktemur@intel.com> * language.h (struct language_pass_by_ref_info): New struct. (struct language_defn)<la_pass_by_reference>: 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)<pass_by_reference>: 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
This commit is contained in:
parent
e35000a7f8
commit
9d084466d7
|
@ -1,3 +1,22 @@
|
|||
2019-12-20 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
|
||||
|
||||
* language.h (struct language_pass_by_ref_info): New struct.
|
||||
(struct language_defn)<la_pass_by_reference>: 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)<pass_by_reference>: 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 <tankut.baris.aktemur@intel.com>
|
||||
|
||||
* dwarf2read.c (dwarf2_add_member_fn): Read the DW_AT_defaulted
|
||||
|
|
|
@ -858,7 +858,7 @@ default_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
|
|||
/* 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)
|
||||
|
|
|
@ -220,11 +220,13 @@ cplus_typename_from_type_info (struct value *value)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
10
gdb/cp-abi.h
10
gdb/cp-abi.h
|
@ -207,9 +207,11 @@ extern std::string cplus_typename_from_type_info (struct value *value);
|
|||
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 cp_abi_ops
|
|||
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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1230,7 +1230,7 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
|
|||
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 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
|
|||
|
||||
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 @@ gnuv3_pass_by_reference (struct type *type)
|
|||
|
||||
/* 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 @@ gnuv3_pass_by_reference (struct type *type)
|
|||
|
||||
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 @@ gnuv3_pass_by_reference (struct type *type)
|
|||
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
|
||||
|
|
|
@ -1020,7 +1020,8 @@ call_function_by_hand_dummy (struct value *function,
|
|||
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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -652,21 +652,23 @@ language_class_name_from_physname (const struct language_defn *lang,
|
|||
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
|
||||
|
|
|
@ -128,6 +128,47 @@ struct language_arch_info
|
|||
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 language_defn
|
|||
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 @@ extern void default_print_array_index (struct value *index_value,
|
|||
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,
|
||||
|
|
|
@ -784,7 +784,7 @@ tic6x_return_value (struct gdbarch *gdbarch, struct value *function,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue