void change_decl_assembler_name (tree decl, tree name) { symtab_node node = NULL; /* We can have user ASM names on things, like global register variables, that are not in the symbol table. */ if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) || TREE_CODE (decl) == FUNCTION_DECL) node = symtab_get_node (decl); if (!DECL_ASSEMBLER_NAME_SET_P (decl)) { SET_DECL_ASSEMBLER_NAME (decl, name); if (node) insert_to_assembler_name_hash (node); } else { if (name == DECL_ASSEMBLER_NAME (decl)) return; if (node) unlink_from_assembler_name_hash (node); if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) && DECL_RTL_SET_P (decl)) warning (0, "%D renamed after being referenced in assembly", decl); SET_DECL_ASSEMBLER_NAME (decl, name); if (node) insert_to_assembler_name_hash (node); } }
const char * symtab_node::asm_name () const { if (!DECL_ASSEMBLER_NAME_SET_P (decl)) return lang_hooks.decl_printable_name (decl, 2); return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); }
const char * symtab_node_asm_name (symtab_node node) { if (!DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl)) return lang_hooks.decl_printable_name (node->symbol.decl, 2); return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl)); }
const char * gimple_decl_printable_name (tree decl, int verbosity) { if (!DECL_NAME (decl)) return NULL; if (DECL_ASSEMBLER_NAME_SET_P (decl)) { const char *str, *mangled_str; int dmgl_opts = DMGL_NO_OPTS; if (verbosity >= 2) { dmgl_opts = DMGL_VERBOSE | DMGL_ANSI | DMGL_GNU_V3 | DMGL_RET_POSTFIX; if (TREE_CODE (decl) == FUNCTION_DECL) dmgl_opts |= DMGL_PARAMS; } mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); str = cplus_demangle_v3 (mangled_str, dmgl_opts); return (str) ? str : mangled_str; } return IDENTIFIER_POINTER (DECL_NAME (decl)); }
void c_genericize (tree fndecl) { FILE *dump_orig; int local_dump_flags; struct cgraph_node *cgn; /* Dump the C-specific tree IR. */ dump_orig = dump_begin (TDI_original, &local_dump_flags); if (dump_orig) { fprintf (dump_orig, "\n;; Function %s", lang_hooks.decl_printable_name (fndecl, 2)); fprintf (dump_orig, " (%s)\n", (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null" : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)))); fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original)); fprintf (dump_orig, "\n"); if (local_dump_flags & TDF_RAW) dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | local_dump_flags, dump_orig); else print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl)); fprintf (dump_orig, "\n"); dump_end (TDI_original, dump_orig); } /* Dump all nested functions now. */ cgn = cgraph_node (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) c_genericize (cgn->decl); }
static bool decide_is_function_needed (struct cgraph_node *node, tree decl) { if (MAIN_NAME_P (DECL_NAME (decl)) && TREE_PUBLIC (decl)) { node->local.externally_visible = true; return true; } /* If the user told us it is used, then it must be so. */ if (node->local.externally_visible) return true; /* ??? If the assembler name is set by hand, it is possible to assemble the name later after finalizing the function and the fact is noticed in assemble_name then. This is arguably a bug. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) return true; /* With -fkeep-inline-functions we are keeping all inline functions except for extern inline ones. */ if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (decl) && !DECL_EXTERNAL (decl) && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))) return true; /* If we decided it was needed before, but at the time we didn't have the body of the function available, then it's still needed. We have to go back and re-check its dependencies now. */ if (node->needed) return true; /* Externally visible functions must be output. The exception is COMDAT functions that must be output only when they are needed. When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions declared inline and nested functions. These was optimized out in the original implementation and it is unclear whether we want to change the behavior here. */ if (((TREE_PUBLIC (decl) || (!optimize && !node->local.disregard_inline_limits && !DECL_DECLARED_INLINE_P (decl) && !node->origin)) && !flag_whole_program) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* Constructors and destructors are reachable from the runtime by some mechanism. */ if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)) return true; return false; }
static void write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr, bool ref_p) { /* Make sure we don't inadvertently set the assembler name. */ if (DECL_ASSEMBLER_NAME_SET_P (expr)) stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p); else stream_write_tree (ob, NULL_TREE, false); }
enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl) { lto_symtab_entry_t e; gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); e = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)))); while (e && e->decl != decl) e = e->next; if (!e) return LDPR_UNKNOWN; return e->resolution; }
void gcc_genericize (tree fndecl) { FILE *dump_orig; int local_dump_flags; struct cgraph_node *cgn; /* Dump the C-specific tree IR. */ dump_orig = gcc_dump_begin (TDI_original, &local_dump_flags); /* if(dump_orig) { printf("should start dumping original tree.\n"); }else{ printf("no dumping original tree flag.\n"); } */ if (dump_orig) { fprintf (dump_orig, "\n;; Function %s", lang_hooks.decl_printable_name (fndecl, 2)); astTreeBuilder->addFunctionName(lang_hooks.decl_printable_name (fndecl, 2)); fprintf (dump_orig, " (%s)\n", (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null" : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)))); fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original)); fprintf (dump_orig, "\n"); //if (local_dump_flags & TDF_RAW) gcc_dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | local_dump_flags, dump_orig); // else // print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl)); fprintf (dump_orig, "\n"); restore_state(); gcc_dump_end (TDI_original, dump_orig); } /* Dump all nested functions now. */ cgn = cgraph_node (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) gcc_genericize (cgn->decl); }
/* Determine if variable DECL is needed. That is, visible to something either outside this translation unit, something magic in the system configury */ bool decide_is_variable_needed (struct varpool_node *node, tree decl) { /* If the user told us it is used, then it must be so. */ if ((node->externally_visible && !DECL_COMDAT (decl)) || node->force_output) return true; /* ??? If the assembler name is set by hand, it is possible to assemble the name later after finalizing the function and the fact is noticed in assemble_name then. This is arguably a bug. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) return true; /* Externally visible variables must be output. The exception is COMDAT variables that must be output only when they are needed. */ if (TREE_PUBLIC (decl) && !flag_whole_program && !flag_lto && !flag_whopr && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* When emulating tls, we actually see references to the control variable, rather than the user-level variable. */ if (!targetm.have_tls && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) { tree control = emutls_decl (decl); if (decide_is_variable_needed (varpool_node (control), control)) return true; } /* When not reordering top level variables, we have to assume that we are going to keep everything. */ if (flag_toplevel_reorder) return false; /* We want to emit COMDAT variables only when absolutely necessary. */ if (DECL_COMDAT (decl)) return false; return true; }
void c_genericize (tree fndecl) { FILE *dump_orig; dump_flags_t local_dump_flags; struct cgraph_node *cgn; if (flag_sanitize & SANITIZE_BOUNDS) { hash_set<tree> pset; walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset, &pset); } if (warn_duplicated_branches) walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), do_warn_duplicated_branches_r, NULL); /* Dump the C-specific tree IR. */ dump_orig = get_dump_info (TDI_original, &local_dump_flags); if (dump_orig) { fprintf (dump_orig, "\n;; Function %s", lang_hooks.decl_printable_name (fndecl, 2)); fprintf (dump_orig, " (%s)\n", (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null" : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)))); fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original)); fprintf (dump_orig, "\n"); if (local_dump_flags & TDF_RAW) dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | local_dump_flags, dump_orig); else print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl)); fprintf (dump_orig, "\n"); } /* Dump all nested functions now. */ cgn = cgraph_node::get_create (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) c_genericize (cgn->decl); }
void symbol_table::change_decl_assembler_name (tree decl, tree name) { symtab_node *node = NULL; /* We can have user ASM names on things, like global register variables, that are not in the symbol table. */ if ((TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) || TREE_CODE (decl) == FUNCTION_DECL) node = symtab_node::get (decl); if (!DECL_ASSEMBLER_NAME_SET_P (decl)) { SET_DECL_ASSEMBLER_NAME (decl, name); if (node) insert_to_assembler_name_hash (node, true); } else { if (name == DECL_ASSEMBLER_NAME (decl)) return; tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) : NULL); if (node) unlink_from_assembler_name_hash (node, true); if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) && DECL_RTL_SET_P (decl)) warning (0, "%D renamed after being referenced in assembly", decl); SET_DECL_ASSEMBLER_NAME (decl, name); if (alias) { IDENTIFIER_TRANSPARENT_ALIAS (name) = 1; TREE_CHAIN (name) = alias; } if (node) insert_to_assembler_name_hash (node, true); } }
/* Dump given cgraph node. */ void dump_varpool_node (FILE *f, struct varpool_node *node) { fprintf (f, "%s:", varpool_node_name (node)); fprintf (f, " availability:%s", cgraph_function_flags_ready ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] : "not-ready"); if (DECL_ASSEMBLER_NAME_SET_P (node->decl)) fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); if (DECL_INITIAL (node->decl)) fprintf (f, " initialized"); if (TREE_ASM_WRITTEN (node->decl)) fprintf (f, " (asm written)"); if (node->needed) fprintf (f, " needed"); if (node->analyzed) fprintf (f, " analyzed"); if (node->finalized) fprintf (f, " finalized"); if (node->output) fprintf (f, " output"); if (node->externally_visible) fprintf (f, " externally_visible"); if (node->resolution != LDPR_UNKNOWN) fprintf (f, " %s", ld_plugin_symbol_resolution_names[(int)node->resolution]); if (node->in_other_partition) fprintf (f, " in_other_partition"); else if (node->used_from_other_partition) fprintf (f, " used_from_other_partition"); fprintf (f, "\n"); fprintf (f, " References: "); ipa_dump_references (f, &node->ref_list); fprintf (f, " Refering this var: "); ipa_dump_refering (f, &node->ref_list); }
void lto_symtab_register_decl (tree decl, ld_plugin_symbol_resolution_t resolution, struct lto_file_decl_data *file_data) { lto_symtab_entry_t new_entry; void **slot; /* Check that declarations reaching this function do not have properties inconsistent with having external linkage. If any of these asertions fail, then the object file reader has failed to detect these cases and issue appropriate error messages. */ gcc_assert (decl && TREE_PUBLIC (decl) && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) && DECL_ASSEMBLER_NAME_SET_P (decl)); if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) gcc_assert (!DECL_EXTERNAL (decl) || (TREE_STATIC (decl) && TREE_READONLY (decl))); if (TREE_CODE (decl) == FUNCTION_DECL) gcc_assert (!DECL_ABSTRACT (decl)); new_entry = ggc_alloc_cleared_lto_symtab_entry_def (); new_entry->id = (*targetm.asm_out.mangle_assembler_name) (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); new_entry->decl = decl; new_entry->resolution = resolution; new_entry->file_data = file_data; lto_symtab_maybe_init_hash_table (); slot = htab_find_slot (lto_symtab_identifiers, new_entry, INSERT); new_entry->next = (lto_symtab_entry_t) *slot; *slot = new_entry; }
void rest_of_decl_compilation (tree decl, int top_level, int at_end) { /* We deferred calling assemble_alias so that we could collect other attributes such as visibility. Emit the alias now. */ { tree alias; alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); if (alias) { alias = TREE_VALUE (TREE_VALUE (alias)); alias = get_identifier (TREE_STRING_POINTER (alias)); assemble_alias (decl, alias); } } /* Emit tm_* attributes for declarations now */ { tree tm_attribute; tm_attribute = lookup_attribute ("tm_wrapper", DECL_ATTRIBUTES (decl)); if (tm_attribute == NULL) tm_attribute = lookup_attribute ("transaction_wrap", DECL_ATTRIBUTES (decl)); if (tm_attribute) { tm_attribute = TREE_VALUE (TREE_VALUE (tm_attribute)); tm_attribute = get_identifier (TREE_STRING_POINTER (tm_attribute)); assemble_tm_wrapper (decl, tm_attribute); } if (has_tm_pure_attribute(decl)) { assemble_tm_pure (decl); } if (has_tm_callable_attribute(decl)) { assemble_tm_callable (decl); } } /* Can't defer this, because it needs to happen before any later function definitions are processed. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && DECL_REGISTER (decl)) /* LLVM LOCAL begin */ #ifndef ENABLE_LLVM make_decl_rtl (decl); #else make_decl_llvm (decl); #endif /* LLVM LOCAL end */ /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) { timevar_push (TV_VARCONST); /* Don't output anything when a tentative file-scope definition is seen. But at end of compilation, do output code for them. We do output all variables when unit-at-a-time is active and rely on callgraph code to defer them except for forward declarations (see gcc.c-torture/compile/920624-1.c) */ if ((at_end || !DECL_DEFER_OUTPUT (decl) || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { if (TREE_CODE (decl) != FUNCTION_DECL) cgraph_varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); } #ifdef ASM_FINISH_DECLARE_OBJECT if (decl == last_assemble_variable_decl) { ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, top_level, at_end); } #endif timevar_pop (TV_VARCONST); } else if (TREE_CODE (decl) == TYPE_DECL /* Like in rest_of_type_compilation, avoid confusing the debug information machinery when there are errors. */ && !(sorrycount || errorcount)) { /* LLVM LOCAL begin */ #ifndef ENABLE_LLVM timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); timevar_pop (TV_SYMOUT); #else llvm_emit_typedef (decl); #endif /* LLVM LOCAL end */ } /* Let cgraph know about the existence of variables. */ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) cgraph_varpool_node (decl); }
static void dequeue_and_dump (dump_info_p di) { dump_queue_p dq; splay_tree_node stn; dump_node_info_p dni; tree t; unsigned int index; enum tree_code code; enum tree_code_class code_class; const char* code_name; /* Get the next node from the queue. */ dq = di->queue; stn = dq->node; t = (tree) stn->key; dni = (dump_node_info_p) stn->value; index = dni->index; /* Remove the node from the queue, and put it on the free list. */ di->queue = dq->next; if (!di->queue) di->queue_end = 0; dq->next = di->free_list; di->free_list = dq; /* Print the node index. */ dump_index (di, index); /* And the type of node this is. */ if (dni->binfo_p) code_name = "binfo"; else code_name = tree_code_name[(int) TREE_CODE (t)]; fprintf (di->stream, "%-16s ", code_name); di->column = 25; /* Figure out what kind of node this is. */ code = TREE_CODE (t); code_class = TREE_CODE_CLASS (code); /* Although BINFOs are TREE_VECs, we dump them specially so as to be more informative. */ if (dni->binfo_p) { unsigned ix; tree base; VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t); dump_child ("type", BINFO_TYPE (t)); if (BINFO_VIRTUAL_P (t)) dump_string_field (di, "spec", "virt"); dump_int (di, "bases", BINFO_N_BASE_BINFOS (t)); for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++) { tree access = (accesses ? VEC_index (tree, accesses, ix) : access_public_node); const char *string = NULL; if (access == access_public_node) string = "pub"; else if (access == access_protected_node) string = "prot"; else if (access == access_private_node) string = "priv"; else gcc_unreachable (); dump_string_field (di, "accs", string); queue_and_dump_index (di, "binf", base, DUMP_BINFO); } goto done; } /* We can knock off a bunch of expression nodes in exactly the same way. */ if (IS_EXPR_CODE_CLASS (code_class)) { /* If we're dumping children, dump them now. */ queue_and_dump_type (di, t); switch (code_class) { case tcc_unary: dump_child ("op 0", TREE_OPERAND (t, 0)); break; case tcc_binary: case tcc_comparison: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case tcc_expression: case tcc_reference: case tcc_statement: case tcc_vl_exp: /* These nodes are handled explicitly below. */ break; default: gcc_unreachable (); } } else if (DECL_P (t)) { expanded_location xloc; /* All declarations have names. */ if (DECL_NAME (t)) dump_child ("name", DECL_NAME (t)); if (DECL_ASSEMBLER_NAME_SET_P (t) && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); if (DECL_ABSTRACT_ORIGIN (t)) dump_child ("orig", DECL_ABSTRACT_ORIGIN (t)); /* And types. */ queue_and_dump_type (di, t); dump_child ("scpe", DECL_CONTEXT (t)); /* And a source position. */ xloc = expand_location (DECL_SOURCE_LOCATION (t)); if (xloc.file) { const char *filename = lbasename (xloc.file); dump_maybe_newline (di); fprintf (di->stream, "srcp: %s:%-6d ", filename, xloc.line); di->column += 6 + strlen (filename) + 8; } /* And any declaration can be compiler-generated. */ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON) && DECL_ARTIFICIAL (t)) dump_string_field (di, "note", "artificial"); if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) dump_child ("chain", DECL_CHAIN (t)); } else if (code_class == tcc_type) { /* All types have qualifiers. */ int quals = lang_hooks.tree_dump.type_quals (t); if (quals != TYPE_UNQUALIFIED) { fprintf (di->stream, "qual: %c%c%c ", (quals & TYPE_QUAL_CONST) ? 'c' : ' ', (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); di->column += 14; } /* All types have associated declarations. */ dump_child ("name", TYPE_NAME (t)); /* All types have a main variant. */ if (TYPE_MAIN_VARIANT (t) != t) dump_child ("unql", TYPE_MAIN_VARIANT (t)); /* And sizes. */ dump_child ("size", TYPE_SIZE (t)); /* All types have alignments. */ dump_int (di, "algn", TYPE_ALIGN (t)); } else if (code_class == tcc_constant) /* All constants can have types. */ queue_and_dump_type (di, t); /* Give the language-specific code a chance to print something. If it's completely taken care of things, don't bother printing anything more ourselves. */ if (lang_hooks.tree_dump.dump_tree (di, t)) goto done; /* Now handle the various kinds of nodes. */ switch (code) { int i; case IDENTIFIER_NODE: dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); break; case TREE_LIST: dump_child ("purp", TREE_PURPOSE (t)); dump_child ("valu", TREE_VALUE (t)); dump_child ("chan", TREE_CHAIN (t)); break; case STATEMENT_LIST: { tree_stmt_iterator it; for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, tsi_stmt (it)); } } break; case TREE_VEC: dump_int (di, "lngt", TREE_VEC_LENGTH (t)); for (i = 0; i < TREE_VEC_LENGTH (t); ++i) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, TREE_VEC_ELT (t, i)); } break; case INTEGER_TYPE: case ENUMERAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_child ("min", TYPE_MIN_VALUE (t)); dump_child ("max", TYPE_MAX_VALUE (t)); if (code == ENUMERAL_TYPE) dump_child ("csts", TYPE_VALUES (t)); break; case REAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); break; case FIXED_POINT_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_string_field (di, "saturating", TYPE_SATURATING (t) ? "saturating": "non-saturating"); break; case POINTER_TYPE: dump_child ("ptd", TREE_TYPE (t)); break; case REFERENCE_TYPE: dump_child ("refd", TREE_TYPE (t)); break; case METHOD_TYPE: dump_child ("clas", TYPE_METHOD_BASETYPE (t)); /* Fall through. */ case FUNCTION_TYPE: dump_child ("retn", TREE_TYPE (t)); dump_child ("prms", TYPE_ARG_TYPES (t)); break; case ARRAY_TYPE: dump_child ("elts", TREE_TYPE (t)); dump_child ("domn", TYPE_DOMAIN (t)); break; case RECORD_TYPE: case UNION_TYPE: if (TREE_CODE (t) == RECORD_TYPE) dump_string_field (di, "tag", "struct"); else dump_string_field (di, "tag", "union"); dump_child ("flds", TYPE_FIELDS (t)); dump_child ("fncs", TYPE_METHODS (t)); queue_and_dump_index (di, "binf", TYPE_BINFO (t), DUMP_BINFO); break; case CONST_DECL: dump_child ("cnst", DECL_INITIAL (t)); break; case DEBUG_EXPR_DECL: dump_int (di, "-uid", DEBUG_TEMP_UID (t)); /* Fall through. */ case VAR_DECL: case PARM_DECL: case FIELD_DECL: case RESULT_DECL: if (TREE_CODE (t) == PARM_DECL) dump_child ("argt", DECL_ARG_TYPE (t)); else dump_child ("init", DECL_INITIAL (t)); dump_child ("size", DECL_SIZE (t)); dump_int (di, "algn", DECL_ALIGN (t)); if (TREE_CODE (t) == FIELD_DECL) { if (DECL_FIELD_OFFSET (t)) dump_child ("bpos", bit_position (t)); } else if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) { dump_int (di, "used", TREE_USED (t)); if (DECL_REGISTER (t)) dump_string_field (di, "spec", "register"); } break; case FUNCTION_DECL: dump_child ("args", DECL_ARGUMENTS (t)); if (DECL_EXTERNAL (t)) dump_string_field (di, "body", "undefined"); if (TREE_PUBLIC (t)) dump_string_field (di, "link", "extern"); else dump_string_field (di, "link", "static"); if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t)) dump_child ("body", DECL_SAVED_TREE (t)); break; case INTEGER_CST: if (TREE_INT_CST_HIGH (t)) dump_int (di, "high", TREE_INT_CST_HIGH (t)); dump_int (di, "low", TREE_INT_CST_LOW (t)); break; case STRING_CST: fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); dump_int (di, "lngt", TREE_STRING_LENGTH (t)); break; case REAL_CST: dump_real (di, "valu", TREE_REAL_CST_PTR (t)); break; case FIXED_CST: dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t)); break; case TRUTH_NOT_EXPR: case ADDR_EXPR: case INDIRECT_REF: case CLEANUP_POINT_EXPR: case SAVE_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: /* These nodes are unary, but do not have code class `1'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); break; case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: case INIT_EXPR: case MODIFY_EXPR: case COMPOUND_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: /* These nodes are binary, but do not have code class `2'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case COMPONENT_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case ARRAY_REF: case ARRAY_RANGE_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); dump_child ("op 3", TREE_OPERAND (t, 3)); break; case COND_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case TRY_FINALLY_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case CALL_EXPR: { int i = 0; tree arg; call_expr_arg_iterator iter; dump_child ("fn", CALL_EXPR_FN (t)); FOR_EACH_CALL_EXPR_ARG (arg, iter, t) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, arg); i++; } } break; case CONSTRUCTOR: { unsigned HOST_WIDE_INT cnt; tree index, value; dump_int (di, "lngt", VEC_length (constructor_elt, CONSTRUCTOR_ELTS (t))); FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) { dump_child ("idx", index); dump_child ("val", value); } }
void rest_of_decl_compilation (tree decl, int top_level, int at_end) { /* We deferred calling assemble_alias so that we could collect other attributes such as visibility. Emit the alias now. */ { tree alias; alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); if (alias) { alias = TREE_VALUE (TREE_VALUE (alias)); alias = get_identifier (TREE_STRING_POINTER (alias)); assemble_alias (decl, alias); #ifdef KEY // Put aliases into the list of decls emitted by g++ so that we can // iterate through the list when expanding aliases to WHIRL. An alias // can be expanded only if its target, which can be another alias, is // expanded. Bug 4393. if (flag_spin_file) gspin_gxx_emits_decl(decl); #endif } } /* Can't defer this, because it needs to happen before any later function definitions are processed. */ if (DECL_ASSEMBLER_NAME_SET_P (decl) && DECL_REGISTER (decl)) make_decl_rtl (decl); /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) { timevar_push (TV_VARCONST); /* Don't output anything when a tentative file-scope definition is seen. But at end of compilation, do output code for them. We do output all variables when unit-at-a-time is active and rely on callgraph code to defer them except for forward declarations (see gcc.c-torture/compile/920624-1.c) */ if ((at_end || !DECL_DEFER_OUTPUT (decl) || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { if (TREE_CODE (decl) != FUNCTION_DECL) cgraph_varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); } #ifdef ASM_FINISH_DECLARE_OBJECT if (decl == last_assemble_variable_decl) { ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl, top_level, at_end); } #endif timevar_pop (TV_VARCONST); } else if (TREE_CODE (decl) == TYPE_DECL /* Like in rest_of_type_compilation, avoid confusing the debug information machinery when there are errors. */ && !(sorrycount || errorcount)) { timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); timevar_pop (TV_SYMOUT); } /* Let cgraph know about the existence of variables. */ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) cgraph_varpool_node (decl); }
void streamer_write_builtin (struct output_block *ob, tree expr) { gcc_assert (streamer_handle_as_builtin_p (expr)); if (DECL_BUILT_IN_CLASS (expr) == BUILT_IN_MD && !targetm.builtin_decl) sorry ("tree bytecode streams do not support machine specific builtin " "functions on this target"); streamer_write_record_start (ob, LTO_builtin_decl); streamer_write_enum (ob->main_stream, built_in_class, BUILT_IN_LAST, DECL_BUILT_IN_CLASS (expr)); streamer_write_uhwi (ob, DECL_FUNCTION_CODE (expr)); if (DECL_ASSEMBLER_NAME_SET_P (expr)) { /* When the assembler name of a builtin gets a user name, the new name is always prefixed with '*' by set_builtin_user_assembler_name. So, to prevent the reader side from adding a second '*', we omit it here. */ const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (expr)); if (strlen (str) > 1 && str[0] == '*') streamer_write_string (ob, ob->main_stream, &str[1], true); else streamer_write_string (ob, ob->main_stream, NULL, true); } else streamer_write_string (ob, ob->main_stream, NULL, true); }