diff options
Diffstat (limited to 'contrib/gcc/final.c')
-rw-r--r-- | contrib/gcc/final.c | 544 |
1 files changed, 345 insertions, 199 deletions
diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c index d86ed5e..94a0f4c 100644 --- a/contrib/gcc/final.c +++ b/contrib/gcc/final.c @@ -68,6 +68,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "target.h" #include "debug.h" #include "expr.h" +#include "profile.h" +#include "cfglayout.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -98,6 +100,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define JUMP_TABLES_IN_TEXT_SECTION 0 #endif +#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP) +#define HAVE_READONLY_DATA_SECTION 1 +#else +#define HAVE_READONLY_DATA_SECTION 0 +#endif + /* Last insn processed by final_scan_insn. */ static rtx debug_insn; rtx current_output_insn; @@ -114,15 +122,12 @@ static int high_function_linenum; /* Filename of last NOTE. */ static const char *last_filename; -/* Number of instrumented arcs when profile_arc_flag is set. */ -extern int count_instrumented_edges; - extern int length_unit_log; /* This is defined in insn-attrtab.c. */ /* Nonzero while outputting an `asm' with operands. This means that inconsistencies are the user's fault, so don't abort. The precise value is the insn being output, to pass to error_for_asm. */ -static rtx this_is_asm_operands; +rtx this_is_asm_operands; /* Number of operands of this insn, for an `asm' with operands. */ static unsigned int insn_noperands; @@ -198,6 +203,17 @@ static char *line_note_exists; rtx current_insn_predicate; #endif +struct function_list +{ + struct function_list *next; /* next function */ + const char *name; /* function name */ + long cfg_checksum; /* function checksum */ + long count_edges; /* number of intrumented edges in this function */ +}; + +static struct function_list *functions_head = 0; +static struct function_list **functions_tail = &functions_head; + #ifdef HAVE_ATTR_length static int asm_insn_count PARAMS ((rtx)); #endif @@ -206,6 +222,7 @@ static void profile_after_prologue PARAMS ((FILE *)); static void notice_source_line PARAMS ((rtx)); static rtx walk_alter_subreg PARAMS ((rtx *)); static void output_asm_name PARAMS ((void)); +static void output_alternate_entry_point PARAMS ((FILE *, rtx)); static tree get_mem_expr_from_op PARAMS ((rtx, int *)); static void output_asm_operand_names PARAMS ((rtx *, int *, int)); static void output_operand PARAMS ((rtx, int)); @@ -237,137 +254,268 @@ init_final (filename) } /* Called at end of source file, - to output the block-profiling table for this entire compilation. */ + to output the arc-profiling table for this entire compilation. */ void end_final (filename) const char *filename; { - if (profile_arc_flag) + if (profile_arc_flag && profile_info.count_instrumented_edges) { char name[20]; - int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT); - int size, rounded; - int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT; - int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT; - int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT; - unsigned int align2 = LONG_TYPE_SIZE; - - size = gcov_type_bytes * count_instrumented_edges; - rounded = size; - - rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; - rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); - - /* ??? This _really_ ought to be done with a structure layout - and with assemble_constructor. If long_bytes != pointer_bytes - we'll be emitting unaligned data at some point. */ - if (long_bytes != pointer_bytes) - abort (); + tree string_type, string_cst; + tree structure_decl, structure_value, structure_pointer_type; + tree field_decl, decl_chain, value_chain; + tree sizeof_field_value, domain_type; - data_section (); + /* Build types. */ + string_type = build_pointer_type (char_type_node); - /* Output the main header, of 11 words: - 0: 1 if this file is initialized, else 0. - 1: address of file name (LPBX1). - 2: address of table of counts (LPBX2). - 3: number of counts in the table. - 4: always 0, for compatibility with Sun. + /* Libgcc2 bb structure. */ + structure_decl = make_node (RECORD_TYPE); + structure_pointer_type = build_pointer_type (structure_decl); - The following are GNU extensions: - - 5: address of table of start addrs of basic blocks (LPBX3). - 6: Number of bytes in this header. - 7: address of table of function names (LPBX4). - 8: address of table of line numbers (LPBX5) or 0. - 9: address of table of file names (LPBX6) or 0. - 10: space reserved for basic block profiling. */ + /* Output the main header, of 7 words: + 0: 1 if this file is initialized, else 0. + 1: address of file name (LPBX1). + 2: address of table of counts (LPBX2). + 3: number of counts in the table. + 4: always 0, libgcc2 uses this as a pointer to next ``struct bb'' - ASM_OUTPUT_ALIGN (asm_out_file, align); + The following are GNU extensions: - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0); + 5: Number of bytes in this header. + 6: address of table of function checksums (LPBX7). */ - /* Zero word. */ - assemble_integer (const0_rtx, long_bytes, align2, 1); + /* The zero word. */ + decl_chain = + build_decl (FIELD_DECL, get_identifier ("zero_word"), + long_integer_type_node); + value_chain = build_tree_list (decl_chain, + convert (long_integer_type_node, + integer_zero_node)); /* Address of filename. */ - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1); - assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, - align2, 1); + { + char *cwd, *da_filename; + int da_filename_len; + + field_decl = + build_decl (FIELD_DECL, get_identifier ("filename"), string_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + cwd = getpwd (); + da_filename_len = strlen (filename) + strlen (cwd) + 4 + 1; + da_filename = (char *) alloca (da_filename_len); + strcpy (da_filename, cwd); + strcat (da_filename, "/"); + strcat (da_filename, filename); + strcat (da_filename, ".da"); + da_filename_len = strlen (da_filename); + string_cst = build_string (da_filename_len + 1, da_filename); + domain_type = build_index_type (build_int_2 (da_filename_len, 0)); + TREE_TYPE (string_cst) + = build_array_type (char_type_node, domain_type); + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, string_type, string_cst), + value_chain); + } - /* Address of count table. */ - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); - assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, - align2, 1); + /* Table of counts. */ + { + tree gcov_type_type = make_unsigned_type (GCOV_TYPE_SIZE); + tree gcov_type_pointer_type = build_pointer_type (gcov_type_type); + tree domain_tree + = build_index_type (build_int_2 (profile_info. + count_instrumented_edges - 1, 0)); + tree gcov_type_array_type + = build_array_type (gcov_type_type, domain_tree); + tree gcov_type_array_pointer_type + = build_pointer_type (gcov_type_array_type); + tree counts_table; + + field_decl = + build_decl (FIELD_DECL, get_identifier ("counts"), + gcov_type_pointer_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + /* No values. */ + counts_table + = build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE); + TREE_STATIC (counts_table) = 1; + ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); + DECL_NAME (counts_table) = get_identifier (name); + assemble_variable (counts_table, 0, 0, 0); + + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, + gcov_type_array_pointer_type, + counts_table), value_chain); + } /* Count of the # of instrumented arcs. */ - assemble_integer (GEN_INT (count_instrumented_edges), - long_bytes, align2, 1); + field_decl + = build_decl (FIELD_DECL, get_identifier ("ncounts"), + long_integer_type_node); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + value_chain = tree_cons (field_decl, + convert (long_integer_type_node, + build_int_2 (profile_info. + count_instrumented_edges, + 0)), value_chain); + /* Pointer to the next bb. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("next"), + structure_pointer_type); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + value_chain = tree_cons (field_decl, null_pointer_node, value_chain); + + /* sizeof(struct bb). We'll set this after entire structure + is laid out. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("sizeof_bb"), + long_integer_type_node); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; + + sizeof_field_value = tree_cons (field_decl, NULL, value_chain); + value_chain = sizeof_field_value; + + /* struct bb_function []. */ + { + struct function_list *item; + int num_nodes; + tree checksum_field, arc_count_field, name_field; + tree domain; + tree array_value_chain = NULL_TREE; + tree bb_fn_struct_type; + tree bb_fn_struct_array_type; + tree bb_fn_struct_array_pointer_type; + tree bb_fn_struct_pointer_type; + tree field_value, field_value_chain; - /* Zero word (link field). */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + bb_fn_struct_type = make_node (RECORD_TYPE); - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + checksum_field = build_decl (FIELD_DECL, get_identifier ("checksum"), + long_integer_type_node); - /* Byte count for extended structure. */ - assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1); + arc_count_field + = build_decl (FIELD_DECL, get_identifier ("arc_count"), + integer_type_node); + TREE_CHAIN (checksum_field) = arc_count_field; - /* Address of function name table. */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + name_field + = build_decl (FIELD_DECL, get_identifier ("name"), string_type); + TREE_CHAIN (arc_count_field) = name_field; - /* Address of line number and filename tables if debugging. */ - assemble_integer (const0_rtx, pointer_bytes, align2, 1); - assemble_integer (const0_rtx, pointer_bytes, align2, 1); + TYPE_FIELDS (bb_fn_struct_type) = checksum_field; - /* Space for extension ptr (link field). */ - assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1); + num_nodes = 0; - /* Output the file name changing the suffix to .d for - Sun tcov compatibility. */ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1); - { - char *cwd = getpwd (); - int len = strlen (filename) + strlen (cwd) + 1; - char *data_file = (char *) alloca (len + 4); - - strcpy (data_file, cwd); - strcat (data_file, "/"); - strcat (data_file, filename); - strip_off_ending (data_file, len); - strcat (data_file, ".da"); - assemble_string (data_file, strlen (data_file) + 1); + for (item = functions_head; item != 0; item = item->next) + num_nodes++; + + /* Note that the array contains a terminator, hence no - 1. */ + domain = build_index_type (build_int_2 (num_nodes, 0)); + + bb_fn_struct_pointer_type = build_pointer_type (bb_fn_struct_type); + bb_fn_struct_array_type + = build_array_type (bb_fn_struct_type, domain); + bb_fn_struct_array_pointer_type + = build_pointer_type (bb_fn_struct_array_type); + + layout_type (bb_fn_struct_type); + layout_type (bb_fn_struct_pointer_type); + layout_type (bb_fn_struct_array_type); + layout_type (bb_fn_struct_array_pointer_type); + + for (item = functions_head; item != 0; item = item->next) + { + size_t name_len; + + /* create constructor for structure. */ + field_value_chain + = build_tree_list (checksum_field, + convert (long_integer_type_node, + build_int_2 (item->cfg_checksum, 0))); + field_value_chain + = tree_cons (arc_count_field, + convert (integer_type_node, + build_int_2 (item->count_edges, 0)), + field_value_chain); + + name_len = strlen (item->name); + string_cst = build_string (name_len + 1, item->name); + domain_type = build_index_type (build_int_2 (name_len, 0)); + TREE_TYPE (string_cst) + = build_array_type (char_type_node, domain_type); + field_value_chain = tree_cons (name_field, + build1 (ADDR_EXPR, string_type, + string_cst), + field_value_chain); + + /* Add to chain. */ + array_value_chain + = tree_cons (NULL_TREE, build (CONSTRUCTOR, + bb_fn_struct_type, NULL_TREE, + nreverse (field_value_chain)), + array_value_chain); + } + + /* Add terminator. */ + field_value = build_tree_list (arc_count_field, + convert (integer_type_node, + build_int_2 (-1, 0))); + + array_value_chain = tree_cons (NULL_TREE, + build (CONSTRUCTOR, bb_fn_struct_type, + NULL_TREE, field_value), + array_value_chain); + + + /* Create constructor for array. */ + field_decl + = build_decl (FIELD_DECL, get_identifier ("function_infos"), + bb_fn_struct_pointer_type); + value_chain = tree_cons (field_decl, + build1 (ADDR_EXPR, + bb_fn_struct_array_pointer_type, + build (CONSTRUCTOR, + bb_fn_struct_array_type, + NULL_TREE, + nreverse + (array_value_chain))), + value_chain); + TREE_CHAIN (field_decl) = decl_chain; + decl_chain = field_decl; } - /* Make space for the table of counts. */ - if (size == 0) - { - /* Realign data section. */ - ASM_OUTPUT_ALIGN (asm_out_file, align); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2); - if (size != 0) - assemble_zeros (size); - } - else - { - ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); -#ifdef ASM_OUTPUT_SHARED_LOCAL - if (flag_shared_data) - ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); - else -#endif -#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL - ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, - size, BIGGEST_ALIGNMENT); -#else -#ifdef ASM_OUTPUT_ALIGNED_LOCAL - ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, - BIGGEST_ALIGNMENT); -#else - ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); -#endif -#endif - } + /* Finish structure. */ + TYPE_FIELDS (structure_decl) = nreverse (decl_chain); + layout_type (structure_decl); + + structure_value + = build (VAR_DECL, structure_decl, NULL_TREE, NULL_TREE); + DECL_INITIAL (structure_value) + = build (CONSTRUCTOR, structure_decl, NULL_TREE, + nreverse (value_chain)); + TREE_STATIC (structure_value) = 1; + ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0); + DECL_NAME (structure_value) = get_identifier (name); + + /* Size of this structure. */ + TREE_VALUE (sizeof_field_value) + = convert (long_integer_type_node, + build_int_2 (int_size_in_bytes (structure_decl), 0)); + + /* Build structure. */ + assemble_variable (structure_value, 0, 0, 0); } } @@ -438,9 +586,7 @@ dbr_sequence_length () static int *insn_lengths; -#ifdef HAVE_ATTR_length varray_type insn_addresses_; -#endif /* Max uid for which the above arrays are valid. */ static int insn_lengths_max_uid; @@ -527,7 +673,7 @@ get_attr_length (insn) case JUMP_INSN: body = PATTERN (insn); - if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) + if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC) { /* Alignment is machine-dependent and should be handled by ADDR_VEC_ALIGN. */ @@ -787,8 +933,8 @@ insn_current_reference_address (branch) void compute_alignments () { - int i; int log, max_skip, max_log; + basic_block bb; if (label_align) { @@ -805,9 +951,8 @@ compute_alignments () if (! optimize || optimize_size) return; - for (i = 0; i < n_basic_blocks; i++) + FOR_EACH_BB (bb) { - basic_block bb = BASIC_BLOCK (i); rtx label = bb->head; int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0; edge e; @@ -837,8 +982,8 @@ compute_alignments () if (!has_fallthru && (branch_frequency > BB_FREQ_MAX / 10 - || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10 - && (BASIC_BLOCK (i - 1)->frequency + || (bb->frequency > bb->prev_bb->frequency * 10 + && (bb->prev_bb->frequency <= ENTRY_BLOCK_PTR->frequency / 2)))) { log = JUMP_ALIGN (label); @@ -849,10 +994,10 @@ compute_alignments () } } /* In case block is frequent and reached mostly by non-fallthru edge, - align it. It is most likely an first block of loop. */ + align it. It is most likely a first block of loop. */ if (has_fallthru && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10 - && branch_frequency > fallthru_frequency * 5) + && branch_frequency > fallthru_frequency * 2) { log = LOOP_ALIGN (label); if (max_log < log) @@ -974,11 +1119,7 @@ shorten_branches (first) next = NEXT_INSN (insn); /* ADDR_VECs only take room if read-only data goes into the text section. */ - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) if (next && GET_CODE (next) == JUMP_INSN) { rtx nextbody = PATTERN (next); @@ -1128,7 +1269,7 @@ shorten_branches (first) } } - INSN_ADDRESSES (uid) = insn_current_address; + INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid]; if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER || GET_CODE (insn) == CODE_LABEL) @@ -1141,11 +1282,7 @@ shorten_branches (first) { /* This only takes room if read-only data goes into the text section. */ - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC) * GET_MODE_SIZE (GET_MODE (body))); @@ -1346,11 +1483,7 @@ shorten_branches (first) PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr, max_addr - rel_addr, body)); - if (JUMP_TABLES_IN_TEXT_SECTION -#if !defined(READONLY_DATA_SECTION) - || 1 -#endif - ) + if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION) { insn_lengths[uid] = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body))); @@ -1380,7 +1513,7 @@ shorten_branches (first) insn_current_address += insn_lengths[inner_uid]; } - } + } else insn_current_address += insn_lengths[uid]; @@ -1537,7 +1670,7 @@ final_start_function (first, file, optimize) if (write_symbols) { remove_unnecessary_notes (); - reorder_blocks (); + scope_to_insns_finalize (); number_blocks (current_function_decl); /* We never actually put out begin/end notes for the top-level block in the function. But, conceptually, that block is @@ -1548,12 +1681,6 @@ final_start_function (first, file, optimize) /* First output the function prologue: code to set up the stack frame. */ (*targetm.asm_out.function_prologue) (file, get_frame_size ()); -#ifdef VMS_DEBUGGING_INFO - /* Output label after the prologue of the function. */ - if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) - vmsdbgout_after_prologue (); -#endif - /* If the machine represents the prologue as RTL, the profiling code must be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ #ifdef HAVE_prologue @@ -1591,7 +1718,7 @@ profile_function (file) #ifndef NO_PROFILE_COUNTERS data_section (); ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); - ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_profile_label_no); + ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_funcdef_no); assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1); #endif @@ -1621,7 +1748,7 @@ profile_function (file) #endif #endif - FUNCTION_PROFILER (file, current_function_profile_label_no); + FUNCTION_PROFILER (file, current_function_funcdef_no); #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH) if (cxt) @@ -1664,12 +1791,12 @@ final_end_function () (*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ()); /* And debug output. */ - (*debug_hooks->end_epilogue) (); + (*debug_hooks->end_epilogue) (last_linenum, last_filename); #if defined (DWARF2_UNWIND_INFO) if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG && dwarf2out_do_frame ()) - dwarf2out_end_epilogue (); + dwarf2out_end_epilogue (last_linenum, last_filename); #endif } @@ -1763,16 +1890,12 @@ final (first, file, optimize, prescan) #ifdef HAVE_ATTR_length if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ()) { -#ifdef STACK_REGS - /* Irritatingly, the reg-stack pass is creating new instructions - and because of REG_DEAD note abuse it has to run after - shorten_branches. Fake address of -1 then. */ - insn_current_address = -1; -#else /* This can be triggered by bugs elsewhere in the compiler if new insns are created after init_insn_lengths is called. */ - abort (); -#endif + if (GET_CODE (insn) == NOTE) + insn_current_address = -1; + else + abort (); } else insn_current_address = INSN_ADDRESSES (INSN_UID (insn)); @@ -1781,6 +1904,23 @@ final (first, file, optimize, prescan) insn = final_scan_insn (insn, file, optimize, prescan, 0); } + /* Store function names for edge-profiling. */ + /* ??? Probably should re-use the existing struct function. */ + + if (cfun->arc_profile) + { + struct function_list *new_item = xmalloc (sizeof (struct function_list)); + + *functions_tail = new_item; + functions_tail = &new_item->next; + + new_item->next = 0; + new_item->name = xstrdup (IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (current_function_decl))); + new_item->cfg_checksum = profile_info.current_function_cfg_checksum; + new_item->count_edges = profile_info.count_edges_instrumented_now; + } + free (line_note_exists); line_note_exists = NULL; } @@ -1807,6 +1947,39 @@ get_insn_template (code, insn) } } +/* Emit the appropriate declaration for an alternate-entry-point + symbol represented by INSN, to FILE. INSN is a CODE_LABEL with + LABEL_KIND != LABEL_NORMAL. + + The case fall-through in this function is intentional. */ +static void +output_alternate_entry_point (file, insn) + FILE *file; + rtx insn; +{ + const char *name = LABEL_NAME (insn); + + switch (LABEL_KIND (insn)) + { + case LABEL_WEAK_ENTRY: +#ifdef ASM_WEAKEN_LABEL + ASM_WEAKEN_LABEL (file, name); +#endif + case LABEL_GLOBAL_ENTRY: + (*targetm.asm_out.globalize_label) (file, name); + case LABEL_STATIC_ENTRY: +#ifdef ASM_OUTPUT_TYPE_DIRECTIVE + ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); +#endif + ASM_OUTPUT_LABEL (file, name); + break; + + case LABEL_NORMAL: + default: + abort (); + } +} + /* The final scan for one insn, INSN. Args are same as in `final', except that INSN is the insn being scanned. @@ -1850,9 +2023,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) case NOTE_INSN_LOOP_VTOP: case NOTE_INSN_FUNCTION_END: case NOTE_INSN_REPEATED_LINE_NUMBER: - case NOTE_INSN_RANGE_BEG: - case NOTE_INSN_RANGE_END: - case NOTE_INSN_LIVE: case NOTE_INSN_EXPECTED_VALUE: break; @@ -1886,7 +2056,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) case NOTE_INSN_FUNCTION_BEG: app_disable (); - (*debug_hooks->end_prologue) (last_linenum); + (*debug_hooks->end_prologue) (last_linenum, last_filename); break; case NOTE_INSN_BLOCK_BEG: @@ -2016,8 +2186,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip); #else +#ifdef ASM_OUTPUT_ALIGN_WITH_NOP + ASM_OUTPUT_ALIGN_WITH_NOP (file, align); +#else ASM_OUTPUT_ALIGN (file, align); #endif +#endif } } #ifdef HAVE_cc0 @@ -2100,17 +2274,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), NEXT_INSN (insn)); #else - if (LABEL_ALTERNATE_NAME (insn)) - ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn); - else - ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); + ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); #endif #endif break; } } - if (LABEL_ALTERNATE_NAME (insn)) - ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn); + if (LABEL_ALT_ENTRY_P (insn)) + output_alternate_entry_point (file, insn); else ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn)); break; @@ -2539,13 +2710,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) insn_code_number = recog_memoized (insn); cleanup_subreg_operands (insn); - /* Dump the insn in the assembly for debugging. */ - if (flag_dump_rtl_in_asm) - { - print_rtx_head = ASM_COMMENT_START; - print_rtl_single (asm_out_file, insn); - print_rtx_head = ""; - } + /* Dump the insn in the assembly for debugging. */ + if (flag_dump_rtl_in_asm) + { + print_rtx_head = ASM_COMMENT_START; + print_rtl_single (asm_out_file, insn); + print_rtx_head = ""; + } if (! constrain_operands_cached (1)) fatal_insn_not_found (insn); @@ -2755,7 +2926,7 @@ alter_subreg (xp) ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y); /* This field has a different meaning for REGs and SUBREGs. Make sure to clear it! */ - x->used = 0; + RTX_FLAG (x, used) = 0; } else abort (); @@ -2970,7 +3141,7 @@ output_operand_lossage VPARAMS ((const char *msgid, ...)) pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: "; asprintf (&fmt_string, "%s%s", pfx_str, _(msgid)); vasprintf (&new_message, fmt_string, ap); - + if (this_is_asm_operands) error_for_asm (this_is_asm_operands, "%s", new_message); else @@ -3768,7 +3939,6 @@ split_double (value, first, second) } else { -#ifdef REAL_ARITHMETIC REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, value); @@ -3797,30 +3967,6 @@ split_double (value, first, second) *first = GEN_INT ((HOST_WIDE_INT) l[0]); *second = GEN_INT ((HOST_WIDE_INT) l[1]); -#else - if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) - && ! flag_pretend_float) - abort (); - - if ( -#ifdef HOST_WORDS_BIG_ENDIAN - WORDS_BIG_ENDIAN -#else - ! WORDS_BIG_ENDIAN -#endif - ) - { - /* Host and target agree => no need to swap. */ - *first = GEN_INT (CONST_DOUBLE_LOW (value)); - *second = GEN_INT (CONST_DOUBLE_HIGH (value)); - } - else - { - *second = GEN_INT (CONST_DOUBLE_LOW (value)); - *first = GEN_INT (CONST_DOUBLE_HIGH (value)); - } -#endif /* no REAL_ARITHMETIC */ } } @@ -3865,7 +4011,7 @@ leaf_function_p () return 1; } -/* Return 1 if branch is an forward branch. +/* Return 1 if branch is a forward branch. Uses insn_shuid array, so it works only in the final pass. May be used by output templates to customary add branch prediction hints. */ |