/* Print all ipcp_lattices of all functions to F. */ static void ipcp_print_all_lattices (FILE * f) { struct cgraph_node *node; int i, count; fprintf (f, "\nLattice:\n"); for (node = cgraph_nodes; node; node = node->next) { struct ipa_node_params *info; if (!node->analyzed) continue; info = IPA_NODE_REF (node); fprintf (f, " Node: %s:\n", cgraph_node_name (node)); count = ipa_get_param_count (info); for (i = 0; i < count; i++) { struct ipcp_lattice *lat = ipcp_get_lattice (info, i); fprintf (f, " param [%d]: ", i); if (lat->type == IPA_CONST_VALUE) { tree cst = lat->constant; fprintf (f, "type is CONST "); print_generic_expr (f, cst, 0); if (TREE_CODE (cst) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (cst, 0)) == CONST_DECL) { fprintf (f, " -> "); print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (cst, 0)), 0); } } else if (lat->type == IPA_TOP) fprintf (f, "type is TOP"); else fprintf (f, "type is BOTTOM"); if (ipa_param_cannot_devirtualize_p (info, i)) fprintf (f, " - cannot_devirtualize set\n"); else if (ipa_param_types_vec_empty (info, i)) fprintf (f, " - type list empty\n"); else fprintf (f, "\n"); } } }
static tree build_junk_fn(unsigned id) { char fnname[32] = {0}; tree decl, resdecl, initial, proto; /* Func decl */ snprintf(fnname, 31, "__func%d", id); proto = build_varargs_function_type_list(void_type_node, NULL_TREE); decl = build_fn_decl(fnname, proto); SET_DECL_ASSEMBLER_NAME(decl, get_identifier(fnname)); printf(TAG "Creating junk function: %s\n", fnname); /* Result */ resdecl=build_decl(BUILTINS_LOCATION,RESULT_DECL,NULL_TREE,void_type_node); DECL_ARTIFICIAL(resdecl) = 1; DECL_CONTEXT(resdecl) = decl; DECL_RESULT(decl) = resdecl; /* Initial */ initial = make_node(BLOCK); TREE_USED(initial) = 1; DECL_INITIAL(decl) = initial; DECL_UNINLINABLE(decl) = 1; DECL_EXTERNAL(decl) = 0; DECL_PRESERVE_P(decl) = 1; /* Func decl */ TREE_USED(decl) = 1; TREE_PUBLIC(decl) = 1; TREE_STATIC(decl) = 1; DECL_ARTIFICIAL(decl) = 1; /* Make the function */ push_struct_function(decl); /* DECL_SAVED_TREE(decl) = gen_junk(); */ cfun->function_end_locus = BUILTINS_LOCATION; gimplify_function_tree(decl); /* Update */ cgraph_add_new_function(decl, false); cgraph_mark_needed_node(cgraph_node(decl)); current_function_decl = NULL_TREE; pop_cfun(); return decl; }
static tree make_alias_for_thunk (tree function) { tree alias; char buf[256]; #if defined (TARGET_IS_PE_COFF) if (DECL_ONE_ONLY (function)) return function; #endif ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); thunk_labelno++; alias = build_decl (FUNCTION_DECL, get_identifier (buf), TREE_TYPE (function)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (function); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_THIS_STATIC (alias) = 1; DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_CLONED_FUNCTION (alias) = NULL_TREE; DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_NO_STATIC_CHAIN (alias) = 1; DECL_PENDING_INLINE_P (alias) = 0; DECL_INLINE (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_DEFERRED_FN (alias) = 0; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INSTANTIATED (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; if (!flag_syntax_only) assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); return alias; }
static tree create_cilk_helper_decl (struct wrapper_data *wd) { char name[20]; if (wd->type == CILK_BLOCK_FOR) sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++); else if (wd->type == CILK_BLOCK_SPAWN) sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++); else gcc_unreachable (); clean_symbol_name (name); tree fndecl = build_decl (DECL_SOURCE_LOCATION (current_function_decl), FUNCTION_DECL, get_identifier (name), wd->fntype); TREE_PUBLIC (fndecl) = 0; TREE_STATIC (fndecl) = 1; TREE_USED (fndecl) = 1; DECL_ARTIFICIAL (fndecl) = 0; DECL_IGNORED_P (fndecl) = 0; DECL_EXTERNAL (fndecl) = 0; DECL_CONTEXT (fndecl) = wd->context; tree block = make_node (BLOCK); DECL_INITIAL (fndecl) = block; TREE_USED (block) = 1; BLOCK_SUPERCONTEXT (block) = fndecl; gcc_assert (!DECL_SAVED_TREE (fndecl)); /* Inlining would defeat the purpose of this wrapper. Either it secretly switches stack frames or it allocates a stable stack frame to hold function arguments even if the parent stack frame is stolen. */ DECL_UNINLINABLE (fndecl) = 1; tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, void_type_node); DECL_ARTIFICIAL (result_decl) = 0; DECL_IGNORED_P (result_decl) = 1; DECL_CONTEXT (result_decl) = fndecl; DECL_RESULT (fndecl) = result_decl; return fndecl; }
/* Remove node from the varpool. */ void varpool_remove_node (varpool_node *node) { tree init; varpool_call_node_removal_hooks (node); symtab_unregister_node (node); /* Because we remove references from external functions before final compilation, we may end up removing useful constructors. FIXME: We probably want to trace boundaries better. */ if (cgraph_state == CGRAPH_LTO_STREAMING) ; else if ((init = ctor_for_folding (node->decl)) == error_mark_node) varpool_remove_initializer (node); else DECL_INITIAL (node->decl) = init; ggc_free (node); }
static void search_local_strs(bool initexit) { unsigned int i; tree var; FOR_EACH_LOCAL_DECL(cfun, i, var) { tree str, init_val = DECL_INITIAL(var); if (init_val == NULL_TREE) continue; if (strcmp(DECL_NAME_POINTER(var), "__func__")) continue; str = get_string_cst(init_val); gcc_assert(str); if (set_init_exit_section(var, initexit) && verbose) inform(DECL_SOURCE_LOCATION(var), "initified local var: %s: %s", DECL_NAME_POINTER(current_function_decl), TREE_STRING_POINTER(str)); }
/* Wrapup a function contained in file FILENAME, ending at line LINENO. */ void tree_code_create_function_wrapup (unsigned char* filename, int lineno) { tree block; tree fn_decl; fn_decl = current_function_decl; emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ /* Get completely built level from debugger symbol table. */ block = (*lang_hooks.decls.poplevel) (1, 0, 0); /* Emit rtl for end of scope. */ expand_end_bindings (block, 0, 1); /* Emit rtl for end of function. */ expand_function_end ((const char *)filename, lineno, 0, fn_decl); /* Pop the level. */ block = (*lang_hooks.decls.poplevel) (1, 0, 1); /* And attach it to the function. */ DECL_INITIAL (fn_decl) = block; /* Emit rtl for end of scope. */ expand_end_bindings (block, 0, 1); /* Call optimization and convert optimized rtl to assembly code. */ rest_of_compilation (fn_decl); /* We are not inside of any scope now. */ current_function_decl = NULL_TREE; }
static void build_function (tree fndecl, tree stmts, tree block) { DECL_INITIAL(fndecl) = block; DECL_SAVED_TREE (fndecl) = stmts ; tree resdecl = build_decl(input_location,RESULT_DECL, NULL_TREE, integer_type_node); DECL_CONTEXT (resdecl) = fndecl; DECL_RESULT(fndecl) = resdecl; current_function_decl = fndecl; if (DECL_STRUCT_FUNCTION(fndecl) == NULL) push_struct_function(fndecl); else push_cfun(DECL_STRUCT_FUNCTION(fndecl)); cfun->function_end_locus = BUILTINS_LOCATION; }
static tree ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) { hash_set<tree> *pset = (hash_set<tree> *) data; if (TREE_CODE (*tp) == BIND_EXPR) { /* Since walk_tree doesn't call the callback function on the decls in BIND_EXPR_VARS, we have to walk them manually, so we can avoid instrumenting DECL_INITIAL of TREE_STATIC vars. */ *walk_subtrees = 0; for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) { if (TREE_STATIC (decl)) continue; walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset, pset); walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset); walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset, pset); } walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset); } else if (TREE_CODE (*tp) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF) { ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true); /* Make sure ubsan_maybe_instrument_array_ref is not called again on the ARRAY_REF, the above call might not instrument anything as the index might be constant or masked, so ensure it is not walked again and walk its subtrees manually. */ tree aref = TREE_OPERAND (*tp, 0); pset->add (aref); *walk_subtrees = 0; walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset); } else if (TREE_CODE (*tp) == ARRAY_REF) ubsan_maybe_instrument_array_ref (tp, false); return NULL_TREE; }
/* Dump given cgraph node. */ void dump_varpool_node (FILE *f, varpool_node *node) { dump_symtab_base (f, node); fprintf (f, " Availability: %s\n", cgraph_function_flags_ready ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] : "not-ready"); fprintf (f, " Varpool flags:"); if (DECL_INITIAL (node->decl)) fprintf (f, " initialized"); if (node->output) fprintf (f, " output"); if (TREE_READONLY (node->decl)) fprintf (f, " read-only"); if (ctor_for_folding (node->decl) != error_mark_node) fprintf (f, " const-value-known"); fprintf (f, "\n"); }
/* Dump given cgraph node. */ void dump_varpool_node (FILE *f, struct varpool_node *node) { dump_symtab_base (f, (symtab_node)node); fprintf (f, " Availability: %s\n", cgraph_function_flags_ready ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] : "not-ready"); fprintf (f, " Varpool flags:"); if (DECL_INITIAL (node->symbol.decl)) fprintf (f, " initialized"); if (node->analyzed) fprintf (f, " analyzed"); if (node->finalized) fprintf (f, " finalized"); if (node->output) fprintf (f, " output"); fprintf (f, "\n"); }
void varpool_analyze_node (struct varpool_node *node) { tree decl = node->symbol.decl; /* When reading back varpool at LTO time, we re-construct the queue in order to have "needed" list right by inserting all needed nodes into varpool. We however don't want to re-analyze already analyzed nodes. */ if (!node->analyzed) { gcc_assert (!in_lto_p || cgraph_function_flags_ready); /* Compute the alignment early so function body expanders are already informed about increased alignment. */ align_variable (decl, 0); } if (node->alias && node->alias_of) { struct varpool_node *tgt = varpool_node_for_decl (node->alias_of); struct varpool_node *n; for (n = tgt; n && n->alias; n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) if (n == node) { error ("variable %q+D part of alias cycle", node->symbol.decl); node->alias = false; continue; } if (!vec_safe_length (node->symbol.ref_list.references)) ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL); if (node->extra_name_alias) { DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of); DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of); DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of); fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->alias_of); } } else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, node->analyzed); node->analyzed = true; }
static tree build_trivial_generic_function () { auto_vec <tree> param_types; tree fndecl = make_fndecl (integer_type_node, "test_fn", param_types); ASSERT_TRUE (fndecl != NULL); /* Populate the function. */ tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node); DECL_ARTIFICIAL (retval) = 1; DECL_IGNORED_P (retval) = 1; DECL_RESULT (fndecl) = retval; /* Create a BIND_EXPR, and within it, a statement list. */ tree stmt_list = alloc_stmt_list (); tree_stmt_iterator stmt_iter = tsi_start (stmt_list); tree block = make_node (BLOCK); tree bind_expr = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block); tree modify_retval = build2 (MODIFY_EXPR, integer_type_node, retval, build_int_cst (integer_type_node, 42)); tree return_stmt = build1 (RETURN_EXPR, integer_type_node, modify_retval); tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING); DECL_INITIAL (fndecl) = block; /* how to add to function? the following appears to be how to set the body of a fndecl: */ DECL_SAVED_TREE(fndecl) = bind_expr; /* Ensure that locals appear in the debuginfo. */ BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr); return fndecl; }
void compile_resource_data (const char *name, const char *buffer, int length) { tree rtype, field = NULL_TREE, data_type, rinit, data, decl; char buf[60]; data_type = build_prim_array_type (unsigned_byte_type_node, strlen (name) + length); rtype = make_node (RECORD_TYPE); PUSH_FIELD (rtype, field, "name_length", unsigned_int_type_node); PUSH_FIELD (rtype, field, "resource_length", unsigned_int_type_node); PUSH_FIELD (rtype, field, "data", data_type); FINISH_RECORD (rtype); START_RECORD_CONSTRUCTOR (rinit, rtype); PUSH_FIELD_VALUE (rinit, "name_length", build_int_cst (NULL_TREE, strlen (name))); PUSH_FIELD_VALUE (rinit, "resource_length", build_int_cst (NULL_TREE, length)); data = build_string (strlen(name) + length, buffer); TREE_TYPE (data) = data_type; PUSH_FIELD_VALUE (rinit, "data", data); FINISH_RECORD_CONSTRUCTOR (rinit); TREE_CONSTANT (rinit) = 1; TREE_INVARIANT (rinit) = 1; /* Generate a unique-enough identifier. */ sprintf (buf, "_Jr%d", ++Jr_count); decl = build_decl (VAR_DECL, get_identifier (buf), rtype); TREE_STATIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; TREE_READONLY (decl) = 1; TREE_THIS_VOLATILE (decl) = 0; DECL_INITIAL (decl) = rinit; layout_decl (decl, 0); pushdecl (decl); rest_of_decl_compilation (decl, global_bindings_p (), 0); make_decl_rtl (decl); assemble_variable (decl, 1, 0, 0); resources = tree_cons (NULL_TREE, decl, resources); }
void compile_resource_data (const char *name, const char *buffer, int length) { tree rtype, field = NULL_TREE, data_type, rinit, data, decl; VEC(constructor_elt,gc) *v = NULL; data_type = build_prim_array_type (unsigned_byte_type_node, strlen (name) + length); rtype = make_node (RECORD_TYPE); PUSH_FIELD (input_location, rtype, field, "name_length", unsigned_int_type_node); PUSH_FIELD (input_location, rtype, field, "resource_length", unsigned_int_type_node); PUSH_FIELD (input_location, rtype, field, "data", data_type); FINISH_RECORD (rtype); START_RECORD_CONSTRUCTOR (v, rtype); PUSH_FIELD_VALUE (v, "name_length", build_int_cst (NULL_TREE, strlen (name))); PUSH_FIELD_VALUE (v, "resource_length", build_int_cst (NULL_TREE, length)); data = build_string (strlen(name) + length, buffer); TREE_TYPE (data) = data_type; PUSH_FIELD_VALUE (v, "data", data); FINISH_RECORD_CONSTRUCTOR (rinit, v, rtype); TREE_CONSTANT (rinit) = 1; decl = build_decl (input_location, VAR_DECL, java_mangle_resource_name (name), rtype); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 1; java_hide_decl (decl); DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; TREE_READONLY (decl) = 1; TREE_THIS_VOLATILE (decl) = 0; DECL_INITIAL (decl) = rinit; layout_decl (decl, 0); pushdecl (decl); rest_of_decl_compilation (decl, global_bindings_p (), 0); varpool_finalize_decl (decl); VEC_safe_push (tree, gc, resources, decl); }
static void build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, tree tidx) { tree array_type, ctor, decl, value_type, name, fetch; gimple load; gimple_stmt_iterator gsi; gcc_assert (info.default_values[num]); value_type = TREE_TYPE (info.default_values[num]); array_type = build_array_type (value_type, arr_index_type); ctor = build_constructor (array_type, info.constructors[num]); TREE_CONSTANT (ctor) = true; decl = build_decl (VAR_DECL, NULL_TREE, array_type); TREE_STATIC (decl) = 1; DECL_INITIAL (decl) = ctor; DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); DECL_ARTIFICIAL (decl) = 1; TREE_CONSTANT (decl) = 1; add_referenced_var (decl); varpool_mark_needed_node (varpool_node (decl)); varpool_finalize_decl (decl); mark_sym_for_renaming (decl); name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL); info.target_inbound_names[num] = name; fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, NULL_TREE); load = gimple_build_assign (name, fetch); SSA_NAME_DEF_STMT (name) = load; gsi = gsi_for_stmt (swtch); gsi_insert_before (&gsi, load, GSI_SAME_STMT); mark_symbols_for_renaming (load); info.arr_ref_last = load; }
static void lto_input_ts_block_tree_pointers (struct lto_input_block *ib, struct data_in *data_in, tree expr) { /* Do not stream BLOCK_SOURCE_LOCATION. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in dwarf2out.c. */ BLOCK_VARS (expr) = streamer_read_chain (ib, data_in); /* Do not stream BLOCK_NONLOCALIZED_VARS. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in dwarf2out.c. */ BLOCK_SUPERCONTEXT (expr) = stream_read_tree (ib, data_in); /* Do not stream BLOCK_ABSTRACT_ORIGIN. We cannot handle debug information for early inlining so drop it on the floor instead of ICEing in dwarf2out.c. */ BLOCK_FRAGMENT_ORIGIN (expr) = stream_read_tree (ib, data_in); BLOCK_FRAGMENT_CHAIN (expr) = stream_read_tree (ib, data_in); /* We re-compute BLOCK_SUBBLOCKS of our parent here instead of streaming it. For non-BLOCK BLOCK_SUPERCONTEXTs we still stream the child relationship explicitly. */ if (BLOCK_SUPERCONTEXT (expr) && TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == BLOCK) { BLOCK_CHAIN (expr) = BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr)); BLOCK_SUBBLOCKS (BLOCK_SUPERCONTEXT (expr)) = expr; } /* The global block is rooted at the TU decl. Hook it here to avoid the need to stream in this block during WPA time. */ else if (BLOCK_SUPERCONTEXT (expr) && TREE_CODE (BLOCK_SUPERCONTEXT (expr)) == TRANSLATION_UNIT_DECL) DECL_INITIAL (BLOCK_SUPERCONTEXT (expr)) = expr; /* The function-level block is connected at the time we read in function bodies for the same reason. */ }
/* Walk the decls we marked as necessary and see if they reference new variables or functions and add them into the worklists. */ bool varpool_analyze_pending_decls (void) { bool changed = false; timevar_push (TV_VARPOOL); while (varpool_first_unanalyzed_node) { struct varpool_node *node = varpool_first_unanalyzed_node, *next; tree decl = node->decl; bool analyzed = node->analyzed; varpool_first_unanalyzed_node->analyzed = true; varpool_first_unanalyzed_node = varpool_first_unanalyzed_node->next_needed; /* When reading back varpool at LTO time, we re-construct the queue in order to have "needed" list right by inserting all needed nodes into varpool. We however don't want to re-analyze already analyzed nodes. */ if (!analyzed) { gcc_assert (!in_lto_p || cgraph_function_flags_ready); /* Compute the alignment early so function body expanders are already informed about increased alignment. */ align_variable (decl, 0); } if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); if (node->same_comdat_group) { for (next = node->same_comdat_group; next != node; next = next->same_comdat_group) varpool_mark_needed_node (next); } changed = true; } timevar_pop (TV_VARPOOL); return changed; }
void varpool_analyze_node (varpool_node *node) { tree decl = node->decl; /* When reading back varpool at LTO time, we re-construct the queue in order to have "needed" list right by inserting all needed nodes into varpool. We however don't want to re-analyze already analyzed nodes. */ if (!node->analyzed) { gcc_assert (!in_lto_p || cgraph_function_flags_ready); /* Compute the alignment early so function body expanders are already informed about increased alignment. */ align_variable (decl, 0); } if (node->alias) symtab_resolve_alias (node, varpool_get_node (node->alias_target)); else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, node->analyzed); node->analyzed = true; }
tree make_alias_for (tree target, tree newid) { tree alias = build_decl (DECL_SOURCE_LOCATION (target), TREE_CODE (target), newid, TREE_TYPE (target)); DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target); cxx_dup_lang_specific_decl (alias); DECL_CONTEXT (alias) = NULL; TREE_READONLY (alias) = TREE_READONLY (target); TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target); TREE_PUBLIC (alias) = 0; DECL_INTERFACE_KNOWN (alias) = 1; if (DECL_LANG_SPECIFIC (alias)) { DECL_NOT_REALLY_EXTERN (alias) = 1; DECL_USE_TEMPLATE (alias) = 0; DECL_TEMPLATE_INFO (alias) = NULL; } DECL_EXTERNAL (alias) = 0; DECL_ARTIFICIAL (alias) = 1; DECL_TEMPLATE_INSTANTIATED (alias) = 0; if (TREE_CODE (alias) == FUNCTION_DECL) { DECL_SAVED_FUNCTION_DATA (alias) = NULL; DECL_DESTRUCTOR_P (alias) = 0; DECL_CONSTRUCTOR_P (alias) = 0; DECL_PENDING_INLINE_P (alias) = 0; DECL_DECLARED_INLINE_P (alias) = 0; DECL_INITIAL (alias) = error_mark_node; DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target)); } else TREE_STATIC (alias) = 1; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; return alias; }
static tree start_handler_array () { tree handler_array_type, decl; push_obstacks_nochange (); end_temporary_allocation (); handler_array_type = build_array_type (handler_element_type, NULL_TREE); decl = build_lang_decl (VAR_DECL, get_unique_identifier ("handler_table"), handler_array_type); /* TREE_TYPE (decl) = handler_array_type;*/ TREE_READONLY (decl) = 1; TREE_STATIC (decl) = 1; DECL_INITIAL (decl) = error_mark_node; pushdecl (decl); make_decl_rtl (decl, NULL_PTR, 0); current_handler->handler_array_decl = decl; return decl; }
/* 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_INITIAL (node->decl)) fprintf (f, " initialized"); 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"); fprintf (f, "\n"); }
/// ValidateRegisterVariable - Check that a static "asm" variable is /// well-formed. If not, emit error messages and return true. If so, return /// false. bool ValidateRegisterVariable(tree decl) { const char *Name = IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(decl)); int RegNumber = decode_reg_name(Name); const Type *Ty = ConvertType(TREE_TYPE(decl)); // If this has already been processed, don't emit duplicate error messages. if (DECL_LLVM_SET_P(decl)) { // Error state encoded into DECL_LLVM. return cast<ConstantInt>(DECL_LLVM(decl))->getZExtValue(); } /* Detect errors in declaring global registers. */ if (RegNumber == -1) error("%Jregister name not specified for %qD", decl, decl); else if (RegNumber < 0) error("%Jinvalid register name for %qD", decl, decl); else if (TYPE_MODE(TREE_TYPE(decl)) == BLKmode) error("%Jdata type of %qD isn%'t suitable for a register", decl, decl); #if 0 // FIXME: enable this. else if (!HARD_REGNO_MODE_OK(RegNumber, TYPE_MODE(TREE_TYPE(decl)))) error("%Jregister specified for %qD isn%'t suitable for data type", decl, decl); #endif else if (DECL_INITIAL(decl) != 0 && TREE_STATIC(decl)) error("global register variable has initial value"); else if (!Ty->isFirstClassType()) sorry("%JLLVM cannot handle register variable %qD, report a bug", decl, decl); else { if (TREE_THIS_VOLATILE(decl)) warning("volatile register variables don%'t work as you might wish"); SET_DECL_LLVM(decl, ConstantInt::getFalse()); return false; // Everything ok. } SET_DECL_LLVM(decl, ConstantInt::getTrue()); return true; }
symtab_node symtab_nonoverwritable_alias (symtab_node node) { tree new_decl; symtab_node new_node = NULL; symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, (void *)&new_node, true); if (new_node) return new_node; new_decl = copy_node (node->symbol.decl); DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias"); if (TREE_CODE (new_decl) == FUNCTION_DECL) DECL_STRUCT_FUNCTION (new_decl) = NULL; DECL_INITIAL (new_decl) = NULL; SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); SET_DECL_RTL (new_decl, NULL); /* Update the properties. */ DECL_EXTERNAL (new_decl) = 0; if (DECL_ONE_ONLY (node->symbol.decl)) DECL_SECTION_NAME (new_decl) = NULL; DECL_COMDAT_GROUP (new_decl) = 0; TREE_PUBLIC (new_decl) = 0; DECL_COMDAT (new_decl) = 0; DECL_WEAK (new_decl) = 0; DECL_VIRTUAL_P (new_decl) = 0; if (TREE_CODE (new_decl) == FUNCTION_DECL) { DECL_STATIC_CONSTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0; new_node = (symtab_node) cgraph_create_function_alias (new_decl, node->symbol.decl); } else new_node = (symtab_node) varpool_create_variable_alias (new_decl, node->symbol.decl); symtab_resolve_alias (new_node, node); return new_node; }
/* * Create a DECL_... node of code CODE, name NAME * and data type TYPE. We do NOT enter this node * in any sort of symbol table. * * layout_decl is used to set up the decl's storage layout. * Other slots are initialized to 0 or null pointers. */ tree build_decl (enum tree_code code, tree name, tree type) { register tree t; t = make_node (code); #if (0) /*************************************/ /* * That is not done, deliberately, so that * having error_mark_node as the type can * suppress useless errors in the use of * this variable. */ if (type == error_mark_node) type = integer_type_node; #endif /*************************************/ DECL_NAME (t) = name; if (name) { DECL_PRINT_NAME (t) = IDENTIFIER_POINTER (name); DECL_ASSEMBLER_NAME (t) = IDENTIFIER_POINTER (name); } TREE_TYPE (t) = type; DECL_ARGUMENTS (t) = NULL_TREE; DECL_INITIAL (t) = NULL_TREE; if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) layout_decl (t, 0); elif (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; return (t); } /* end build_decl */
/* Return lexical scope block insn belong to. */ static tree insn_scope (rtx insn) { int max = VARRAY_ACTIVE_SIZE (block_locators_locs); int min = 0; int loc = INSN_LOCATOR (insn); /* When block_locators_locs was initialized, the pro- and epilogue insns didn't exist yet and can therefore not be found this way. But we know that they belong to the outer most block of the current function. Without this test, the prologue would be put inside the block of the first valid instruction in the function and when that first insn is part of an inlined function then the low_pc of that inlined function is messed up. Likewise for the epilogue and the last valid instruction. */ if (loc == prologue_locator || loc == epilogue_locator) return DECL_INITIAL (cfun->decl); if (!max || !loc) return NULL; while (1) { int pos = (min + max) / 2; int tmp = VARRAY_INT (block_locators_locs, pos); if (tmp <= loc && min != pos) min = pos; else if (tmp > loc && max != pos) max = pos; else { min = pos; break; } } return VARRAY_TREE (block_locators_blocks, min); }
/* 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); }
tree visit_fun(tree *decl, int *subtrees, void *dummy) { (void)subtrees; (void)dummy; enum tree_code code = TREE_CODE(*decl); tree var = NULL_TREE; if(code == BIND_EXPR) { for(var = BIND_EXPR_VARS(*decl); var; var = TREE_CHAIN(var)) { if(TREE_CODE(var) == VAR_DECL) { if(auto_var_in_fn_p(var, current_function_decl) && !DECL_ARTIFICIAL(var)) { if(!DECL_INITIAL(var)) { tree init_var = walk_tree_without_duplicates(decl, walk_init, var); if(init_var == NULL_TREE) { // don't check classes initialization (too complicated) if(!(TREE_CODE(TREE_TYPE(var)) == RECORD_TYPE && CLASSTYPE_DECLARED_CLASS(TREE_TYPE(var)))) { WARNING_DECL(*decl, "uninititialized auto var %qD", var); } } } } } } } return NULL_TREE; }
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; }
static void create_common (gfc_common_head *com, segment_info *head, bool saw_equiv) { segment_info *s, *next_s; tree union_type; tree *field_link; tree field; tree field_init = NULL_TREE; record_layout_info rli; tree decl; bool is_init = false; bool is_saved = false; /* Declare the variables inside the common block. If the current common block contains any equivalence object, then make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the alias analyzer work well when there is no address overlapping for common variables in the current common block. */ if (saw_equiv) union_type = make_node (UNION_TYPE); else union_type = make_node (RECORD_TYPE); rli = start_record_layout (union_type); field_link = &TYPE_FIELDS (union_type); /* Check for overlapping initializers and replace them with a single, artificial field that contains all the data. */ if (saw_equiv) field = get_init_field (head, union_type, &field_init, rli); else field = NULL_TREE; if (field != NULL_TREE) { is_init = true; *field_link = field; field_link = &DECL_CHAIN (field); } for (s = head; s; s = s->next) { build_field (s, union_type, rli); /* Link the field into the type. */ *field_link = s->field; field_link = &DECL_CHAIN (s->field); /* Has initial value. */ if (s->sym->value) is_init = true; /* Has SAVE attribute. */ if (s->sym->attr.save) is_saved = true; } finish_record_layout (rli, true); if (com) decl = build_common_decl (com, union_type, is_init); else decl = build_equiv_decl (union_type, is_init, is_saved); if (is_init) { tree ctor, tmp; VEC(constructor_elt,gc) *v = NULL; if (field != NULL_TREE && field_init != NULL_TREE) CONSTRUCTOR_APPEND_ELT (v, field, field_init); else for (s = head; s; s = s->next) { if (s->sym->value) { /* Add the initializer for this field. */ tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts, TREE_TYPE (s->field), s->sym->attr.dimension, s->sym->attr.pointer || s->sym->attr.allocatable, false); CONSTRUCTOR_APPEND_ELT (v, s->field, tmp); } } gcc_assert (!VEC_empty (constructor_elt, v)); ctor = build_constructor (union_type, v); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; #ifdef ENABLE_CHECKING { tree field, value; unsigned HOST_WIDE_INT idx; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value) gcc_assert (TREE_CODE (field) == FIELD_DECL); } #endif } /* Build component reference for each variable. */ for (s = head; s; s = next_s) { tree var_decl; var_decl = build_decl (s->sym->declared_at.lb->location, VAR_DECL, DECL_NAME (s->field), TREE_TYPE (s->field)); TREE_STATIC (var_decl) = TREE_STATIC (decl); /* Mark the variable as used in order to avoid warnings about unused variables. */ TREE_USED (var_decl) = 1; if (s->sym->attr.use_assoc) DECL_IGNORED_P (var_decl) = 1; if (s->sym->attr.target) TREE_ADDRESSABLE (var_decl) = 1; /* Fake variables are not visible from other translation units. */ TREE_PUBLIC (var_decl) = 0; /* To preserve identifier names in COMMON, chain to procedure scope unless at top level in a module definition. */ if (com && s->sym->ns->proc_name && s->sym->ns->proc_name->attr.flavor == FL_MODULE) var_decl = pushdecl_top_level (var_decl); else gfc_add_decl_to_function (var_decl); SET_DECL_VALUE_EXPR (var_decl, fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (s->field), decl, s->field, NULL_TREE)); DECL_HAS_VALUE_EXPR_P (var_decl) = 1; GFC_DECL_COMMON_OR_EQUIV (var_decl) = 1; if (s->sym->attr.assign) { gfc_allocate_lang_decl (var_decl); GFC_DECL_ASSIGN (var_decl) = 1; GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field); GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field); } s->sym->backend_decl = var_decl; next_s = s->next; free (s); } }