| /* D language support routines for GDB, the GNU debugger. | |
| Copyright (C) 2005-2025 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 <http://www.gnu.org/licenses/>. */ | |
| #include "symtab.h" | |
| #include "language.h" | |
| #include "varobj.h" | |
| #include "d-lang.h" | |
| #include "c-lang.h" | |
| #include "demangle.h" | |
| #include "cp-support.h" | |
| #include "gdbarch.h" | |
| #include "parser-defs.h" | |
| /* The name of the symbol to use to get the name of the main subprogram. */ | |
| static const char D_MAIN[] = "D main"; | |
| /* Function returning the special symbol name used by D for the main | |
| procedure in the main program if it is found in minimal symbol list. | |
| This function tries to find minimal symbols so that it finds them even | |
| if the program was compiled without debugging information. */ | |
| const char * | |
| d_main_name (void) | |
| { | |
| bound_minimal_symbol msym | |
| = lookup_minimal_symbol (current_program_space, D_MAIN); | |
| if (msym.minsym != NULL) | |
| return D_MAIN; | |
| /* No known entry procedure found, the main program is probably not D. */ | |
| return NULL; | |
| } | |
| /* Implements the la_demangle language_defn routine for language D. */ | |
| gdb::unique_xmalloc_ptr<char> | |
| d_demangle (const char *symbol, int options) | |
| { | |
| return gdb_demangle (symbol, options | DMGL_DLANG); | |
| } | |
| /* Class representing the D language. */ | |
| class d_language : public language_defn | |
| { | |
| public: | |
| d_language () | |
| : language_defn (language_d) | |
| { /* Nothing. */ } | |
| /* See language.h. */ | |
| const char *name () const override | |
| { return "d"; } | |
| /* See language.h. */ | |
| const char *natural_name () const override | |
| { return "D"; } | |
| /* See language.h. */ | |
| const std::vector<const char *> &filename_extensions () const override | |
| { | |
| static const std::vector<const char *> extensions = { ".d" }; | |
| return extensions; | |
| } | |
| /* See language.h. */ | |
| void language_arch_info (struct gdbarch *gdbarch, | |
| struct language_arch_info *lai) const override | |
| { | |
| const struct builtin_d_type *builtin = builtin_d_type (gdbarch); | |
| /* Helper function to allow shorter lines below. */ | |
| auto add = [&] (struct type * t) | |
| { | |
| lai->add_primitive_type (t); | |
| }; | |
| add (builtin->builtin_void); | |
| add (builtin->builtin_bool); | |
| add (builtin->builtin_byte); | |
| add (builtin->builtin_ubyte); | |
| add (builtin->builtin_short); | |
| add (builtin->builtin_ushort); | |
| add (builtin->builtin_int); | |
| add (builtin->builtin_uint); | |
| add (builtin->builtin_long); | |
| add (builtin->builtin_ulong); | |
| add (builtin->builtin_cent); | |
| add (builtin->builtin_ucent); | |
| add (builtin->builtin_float); | |
| add (builtin->builtin_double); | |
| add (builtin->builtin_real); | |
| add (builtin->builtin_ifloat); | |
| add (builtin->builtin_idouble); | |
| add (builtin->builtin_ireal); | |
| add (builtin->builtin_cfloat); | |
| add (builtin->builtin_cdouble); | |
| add (builtin->builtin_creal); | |
| add (builtin->builtin_char); | |
| add (builtin->builtin_wchar); | |
| add (builtin->builtin_dchar); | |
| lai->set_string_char_type (builtin->builtin_char); | |
| lai->set_bool_type (builtin->builtin_bool, "bool"); | |
| } | |
| /* See language.h. */ | |
| bool sniff_from_mangled_name | |
| (const char *mangled, | |
| gdb::unique_xmalloc_ptr<char> *demangled) const override | |
| { | |
| *demangled = d_demangle (mangled, 0); | |
| return *demangled != NULL; | |
| } | |
| /* See language.h. */ | |
| gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled, | |
| int options) const override | |
| { | |
| return d_demangle (mangled, options); | |
| } | |
| /* See language.h. */ | |
| bool can_print_type_offsets () const override | |
| { | |
| return true; | |
| } | |
| /* See language.h. */ | |
| void print_type (struct type *type, const char *varstring, | |
| struct ui_file *stream, int show, int level, | |
| const struct type_print_options *flags) const override | |
| { | |
| c_print_type (type, varstring, stream, show, level, la_language, flags); | |
| } | |
| /* See language.h. */ | |
| void value_print_inner | |
| (struct value *val, struct ui_file *stream, int recurse, | |
| const struct value_print_options *options) const override | |
| { | |
| return d_value_print_inner (val, stream, recurse, options); | |
| } | |
| /* See language.h. */ | |
| struct block_symbol lookup_symbol_nonlocal | |
| (const char *name, const struct block *block, | |
| const domain_search_flags domain) const override | |
| { | |
| return d_lookup_symbol_nonlocal (this, name, block, domain); | |
| } | |
| /* See language.h. */ | |
| int parser (struct parser_state *ps) const override | |
| { | |
| return d_parse (ps); | |
| } | |
| /* See language.h. */ | |
| const char *name_of_this () const override | |
| { return "this"; } | |
| }; | |
| /* Single instance of the D language class. */ | |
| static d_language d_language_defn; | |
| /* Build all D language types for the specified architecture. */ | |
| static struct builtin_d_type * | |
| build_d_types (struct gdbarch *gdbarch) | |
| { | |
| struct builtin_d_type *builtin_d_type = new struct builtin_d_type; | |
| /* Basic types. */ | |
| type_allocator alloc (gdbarch); | |
| builtin_d_type->builtin_void = builtin_type (gdbarch)->builtin_void; | |
| builtin_d_type->builtin_bool | |
| = init_boolean_type (alloc, 8, 1, "bool"); | |
| builtin_d_type->builtin_byte | |
| = init_integer_type (alloc, 8, 0, "byte"); | |
| builtin_d_type->builtin_ubyte | |
| = init_integer_type (alloc, 8, 1, "ubyte"); | |
| builtin_d_type->builtin_short | |
| = init_integer_type (alloc, 16, 0, "short"); | |
| builtin_d_type->builtin_ushort | |
| = init_integer_type (alloc, 16, 1, "ushort"); | |
| builtin_d_type->builtin_int | |
| = init_integer_type (alloc, 32, 0, "int"); | |
| builtin_d_type->builtin_uint | |
| = init_integer_type (alloc, 32, 1, "uint"); | |
| builtin_d_type->builtin_long | |
| = init_integer_type (alloc, 64, 0, "long"); | |
| builtin_d_type->builtin_ulong | |
| = init_integer_type (alloc, 64, 1, "ulong"); | |
| builtin_d_type->builtin_cent | |
| = init_integer_type (alloc, 128, 0, "cent"); | |
| builtin_d_type->builtin_ucent | |
| = init_integer_type (alloc, 128, 1, "ucent"); | |
| builtin_d_type->builtin_float | |
| = init_float_type (alloc, gdbarch_float_bit (gdbarch), | |
| "float", gdbarch_float_format (gdbarch)); | |
| builtin_d_type->builtin_double | |
| = init_float_type (alloc, gdbarch_double_bit (gdbarch), | |
| "double", gdbarch_double_format (gdbarch)); | |
| builtin_d_type->builtin_real | |
| = init_float_type (alloc, gdbarch_long_double_bit (gdbarch), | |
| "real", gdbarch_long_double_format (gdbarch)); | |
| builtin_d_type->builtin_byte->set_instance_flags | |
| (builtin_d_type->builtin_byte->instance_flags () | |
| | TYPE_INSTANCE_FLAG_NOTTEXT); | |
| builtin_d_type->builtin_ubyte->set_instance_flags | |
| (builtin_d_type->builtin_ubyte->instance_flags () | |
| | TYPE_INSTANCE_FLAG_NOTTEXT); | |
| /* Imaginary and complex types. */ | |
| builtin_d_type->builtin_ifloat | |
| = init_float_type (alloc, gdbarch_float_bit (gdbarch), | |
| "ifloat", gdbarch_float_format (gdbarch)); | |
| builtin_d_type->builtin_idouble | |
| = init_float_type (alloc, gdbarch_double_bit (gdbarch), | |
| "idouble", gdbarch_double_format (gdbarch)); | |
| builtin_d_type->builtin_ireal | |
| = init_float_type (alloc, gdbarch_long_double_bit (gdbarch), | |
| "ireal", gdbarch_long_double_format (gdbarch)); | |
| builtin_d_type->builtin_cfloat | |
| = init_complex_type ("cfloat", builtin_d_type->builtin_float); | |
| builtin_d_type->builtin_cdouble | |
| = init_complex_type ("cdouble", builtin_d_type->builtin_double); | |
| builtin_d_type->builtin_creal | |
| = init_complex_type ("creal", builtin_d_type->builtin_real); | |
| /* Character types. */ | |
| builtin_d_type->builtin_char | |
| = init_character_type (alloc, 8, 1, "char"); | |
| builtin_d_type->builtin_wchar | |
| = init_character_type (alloc, 16, 1, "wchar"); | |
| builtin_d_type->builtin_dchar | |
| = init_character_type (alloc, 32, 1, "dchar"); | |
| return builtin_d_type; | |
| } | |
| static const registry<gdbarch>::key<struct builtin_d_type> d_type_data; | |
| /* Return the D type table for the specified architecture. */ | |
| const struct builtin_d_type * | |
| builtin_d_type (struct gdbarch *gdbarch) | |
| { | |
| struct builtin_d_type *result = d_type_data.get (gdbarch); | |
| if (result == nullptr) | |
| { | |
| result = build_d_types (gdbarch); | |
| d_type_data.set (gdbarch, result); | |
| } | |
| return result; | |
| } |