📄 dwarfout.c
字号:
lookahead = (TREE_CODE (ret_val) == BLOCK) ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL; } while (lookahead != NULL && lookahead != ret_val); return ret_val; }}/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT of a virtual function may refer to a base class, so we check the 'this' parameter. */static treedecl_class_context (decl) tree decl;{ tree context = NULL_TREE; if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl)) context = DECL_CONTEXT (decl); else context = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't') context = NULL_TREE; return context;}static voidoutput_unsigned_leb128 (value) register unsigned long value;{ register unsigned long orig_value = value; do { register unsigned byte = (value & 0x7f); value >>= 7; if (value != 0) /* more bytes to follow */ byte |= 0x80; fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte); if (flag_debug_asm && value == 0) fprintf (asm_out_file, "\t%s ULEB128 number - value = %u", ASM_COMMENT_START, orig_value); fputc ('\n', asm_out_file); } while (value != 0);}static voidoutput_signed_leb128 (value) register long value;{ register long orig_value = value; register int negative = (value < 0); register int more; do { register unsigned byte = (value & 0x7f); value >>= 7; if (negative) value |= 0xfe000000; /* manually sign extend */ if (((value == 0) && ((byte & 0x40) == 0)) || ((value == -1) && ((byte & 0x40) == 1))) more = 0; else { byte |= 0x80; more = 1; } fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte); if (flag_debug_asm && more == 0) fprintf (asm_out_file, "\t%s SLEB128 number - value = %d", ASM_COMMENT_START, orig_value); fputc ('\n', asm_out_file); } while (more);}/**************** utility functions for attribute functions ******************//* Given a pointer to a BLOCK node return non-zero if (and only if) the node in question represents the outermost pair of curly braces (i.e. the "body block") of a function or method. For any BLOCK node representing a "body block" of a function or method, the BLOCK_SUPERCONTEXT of the node will point to another BLOCK node which represents the outermost (function) scope for the function or method (i.e. the one which includes the formal parameters). The BLOCK_SUPERCONTEXT of *that* node in turn will point to the relevant FUNCTION_DECL node.*/static inline intis_body_block (stmt) register tree stmt;{ if (TREE_CODE (stmt) == BLOCK) { register tree parent = BLOCK_SUPERCONTEXT (stmt); if (TREE_CODE (parent) == BLOCK) { register tree grandparent = BLOCK_SUPERCONTEXT (parent); if (TREE_CODE (grandparent) == FUNCTION_DECL) return 1; } } return 0;}/* Given a pointer to a tree node for some type, return a Dwarf fundamental type code for the given type. This routine must only be called for GCC type nodes that correspond to Dwarf fundamental types. The current Dwarf draft specification calls for Dwarf fundamental types to accurately reflect the fact that a given type was either a "plain" integral type or an explicitly "signed" integral type. Unfortunately, we can't always do this, because GCC may already have thrown away the information about the precise way in which the type was originally specified, as in: typedef signed int my_type; struct s { my_type f; }; Since we may be stuck here without enought information to do exactly what is called for in the Dwarf draft specification, we do the best that we can under the circumstances and always use the "plain" integral fundamental type codes for int, short, and long types. That's probably good enough. The additional accuracy called for in the current DWARF draft specification is probably never even useful in practice. */static intfundamental_type_code (type) register tree type;{ if (TREE_CODE (type) == ERROR_MARK) return 0; switch (TREE_CODE (type)) { case ERROR_MARK: return FT_void; case VOID_TYPE: return FT_void; case INTEGER_TYPE: /* Carefully distinguish all the standard types of C, without messing up if the language is not C. Note that we check only for the names that contain spaces; other names might occur by coincidence in other languages. */ if (TYPE_NAME (type) != 0 && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_NAME (TYPE_NAME (type)) != 0 && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE) { char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); if (!strcmp (name, "unsigned char")) return FT_unsigned_char; if (!strcmp (name, "signed char")) return FT_signed_char; if (!strcmp (name, "unsigned int")) return FT_unsigned_integer; if (!strcmp (name, "short int")) return FT_short; if (!strcmp (name, "short unsigned int")) return FT_unsigned_short; if (!strcmp (name, "long int")) return FT_long; if (!strcmp (name, "long unsigned int")) return FT_unsigned_long; if (!strcmp (name, "long long int")) return FT_long_long; /* Not grok'ed by svr4 SDB */ if (!strcmp (name, "long long unsigned int")) return FT_unsigned_long_long; /* Not grok'ed by svr4 SDB */ } /* Most integer types will be sorted out above, however, for the sake of special `array index' integer types, the following code is also provided. */ if (TYPE_PRECISION (type) == INT_TYPE_SIZE) return (TREE_UNSIGNED (type) ? FT_unsigned_integer : FT_integer); if (TYPE_PRECISION (type) == LONG_TYPE_SIZE) return (TREE_UNSIGNED (type) ? FT_unsigned_long : FT_long); if (TYPE_PRECISION (type) == LONG_LONG_TYPE_SIZE) return (TREE_UNSIGNED (type) ? FT_unsigned_long_long : FT_long_long); if (TYPE_PRECISION (type) == SHORT_TYPE_SIZE) return (TREE_UNSIGNED (type) ? FT_unsigned_short : FT_short); if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE) return (TREE_UNSIGNED (type) ? FT_unsigned_char : FT_char); abort (); case REAL_TYPE: /* Carefully distinguish all the standard types of C, without messing up if the language is not C. */ if (TYPE_NAME (type) != 0 && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_NAME (TYPE_NAME (type)) != 0 && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE) { char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); /* Note that here we can run afowl of a serious bug in "classic" svr4 SDB debuggers. They don't seem to understand the FT_ext_prec_float type (even though they should). */ if (!strcmp (name, "long double")) return FT_ext_prec_float; } if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE) return FT_dbl_prec_float; if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE) return FT_float; /* Note that here we can run afowl of a serious bug in "classic" svr4 SDB debuggers. They don't seem to understand the FT_ext_prec_float type (even though they should). */ if (TYPE_PRECISION (type) == LONG_DOUBLE_TYPE_SIZE) return FT_ext_prec_float; abort (); case COMPLEX_TYPE: return FT_complex; /* GNU FORTRAN COMPLEX type. */ case CHAR_TYPE: return FT_char; /* GNU Pascal CHAR type. Not used in C. */ case BOOLEAN_TYPE: return FT_boolean; /* GNU FORTRAN BOOLEAN type. */ default: abort (); /* No other TREE_CODEs are Dwarf fundamental types. */ } return 0;}/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to the Dwarf "root" type for the given input type. The Dwarf "root" type of a given type is generally the same as the given type, except that if the given type is a pointer or reference type, then the root type of the given type is the root type of the "basis" type for the pointer or reference type. (This definition of the "root" type is recursive.) Also, the root type of a `const' qualified type or a `volatile' qualified type is the root type of the given type without the qualifiers. */static treeroot_type_1 (type, count) register tree type; register int count;{ /* Give up after searching 1000 levels, in case this is a recursive pointer type. Such types are possible in Ada, but it is not possible to represent them in DWARF1 debug info. */ if (count > 1000) return error_mark_node; switch (TREE_CODE (type)) { case ERROR_MARK: return error_mark_node; case POINTER_TYPE: case REFERENCE_TYPE: return root_type_1 (TREE_TYPE (type), count+1); default: return type; }}static treeroot_type (type) register tree type;{ type = root_type_1 (type, 0); if (type != error_mark_node) type = type_main_variant (type); return type;}/* Given a pointer to an arbitrary ..._TYPE tree node, write out a sequence of zero or more Dwarf "type-modifier" bytes applicable to the type. */static voidwrite_modifier_bytes_1 (type, decl_const, decl_volatile, count) register tree type; register int decl_const; register int decl_volatile; register int count;{ if (TREE_CODE (type) == ERROR_MARK) return; /* Give up after searching 1000 levels, in case this is a recursive pointer type. Such types are possible in Ada, but it is not possible to represent them in DWARF1 debug info. */ if (count > 1000) return; if (TYPE_READONLY (type) || decl_const) ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_const); if (TYPE_VOLATILE (type) || decl_volatile) ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_volatile); switch (TREE_CODE (type)) { case POINTER_TYPE: ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_pointer_to); write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1); return; case REFERENCE_TYPE: ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_reference_to); write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1); return; case ERROR_MARK: default: return; }}static voidwrite_modifier_bytes (type, decl_const, decl_volatile) register tree type; register int decl_const; register int decl_volatile;{ write_modifier_bytes_1 (type, decl_const, decl_volatile, 0);}/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the given input type is a Dwarf "fundamental" type. Otherwise return zero. */static inline inttype_is_fundamental (type) register tree type;{ switch (TREE_CODE (type)) { case ERROR_MARK: case VOID_TYPE: case INTEGER_TYPE: case REAL_TYPE: case COMPLEX_TYPE: case BOOLEAN_TYPE: case CHAR_TYPE: return 1; case SET_TYPE: case ARRAY_TYPE: case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: case ENUMERAL_TYPE: case FUNCTION_TYPE: case METHOD_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: case FILE_TYPE: case OFFSET_TYPE: case LANG_TYPE: return 0; default: abort (); } return 0;}/* Given a pointer to some ..._DECL tree node, generate an assembly language equate directive which will associate a symbolic name with the current DIE. The name used is an artificial label generated from the DECL_UID number associated with the given decl node. The name it gets equated to is the symbolic label that we (previously) output at the start of the DIE that we are currently generating. Calling this function while generating some "decl related" form of DIE makes it possible to later refer to the DIE which represents the given decl simply by re-generating the symbolic name from the ..._DECL node's
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -