📄 final.c
字号:
profile_label_no++; /* If we are doing basic block profiling, remember a printable version of the function name. */ if (profile_block_flag) { char *junk = "function"; bb_func_label_num = add_bb_string ((*decl_printable_name) (current_function_decl, &junk), FALSE); }}static voidprofile_after_prologue (file) FILE *file;{#ifdef FUNCTION_BLOCK_PROFILER if (profile_block_flag) { FUNCTION_BLOCK_PROFILER (file, profile_label_no); }#endif /* FUNCTION_BLOCK_PROFILER */#ifndef PROFILE_BEFORE_PROLOGUE if (profile_flag) profile_function (file);#endif /* not PROFILE_BEFORE_PROLOGUE */}static voidprofile_function (file) FILE *file;{ int align = MIN (BIGGEST_ALIGNMENT, POINTER_SIZE); int sval = current_function_returns_struct; int cxt = current_function_needs_context; data_section (); ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no); assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1); text_section ();#ifdef STRUCT_VALUE_INCOMING_REGNUM if (sval) ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);#else#ifdef STRUCT_VALUE_REGNUM if (sval) ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);#endif#endif#if 0#ifdef STATIC_CHAIN_INCOMING_REGNUM if (cxt) ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);#else#ifdef STATIC_CHAIN_REGNUM if (cxt) ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);#endif#endif#endif /* 0 */ FUNCTION_PROFILER (file, profile_label_no);#if 0#ifdef STATIC_CHAIN_INCOMING_REGNUM if (cxt) ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);#else#ifdef STATIC_CHAIN_REGNUM if (cxt) ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);#endif#endif#endif /* 0 */#ifdef STRUCT_VALUE_INCOMING_REGNUM if (sval) ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);#else#ifdef STRUCT_VALUE_REGNUM if (sval) ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);#endif#endif}/* Output assembler code for the end of a function. For clarity, args are same as those of `final_start_function' even though not all of them are needed. */voidfinal_end_function (first, file, optimize) rtx first; FILE *file; int optimize;{ if (app_on) { fprintf (file, ASM_APP_OFF); app_on = 0; }#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) sdbout_end_function (high_function_linenum);#endif#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) dwarfout_end_function ();#endif#ifdef XCOFF_DEBUGGING_INFO if (write_symbols == XCOFF_DEBUG) xcoffout_end_function (file, high_function_linenum);#endif#ifdef FUNCTION_EPILOGUE /* Finally, output the function epilogue: code to restore the stack frame and return to the caller. */ FUNCTION_EPILOGUE (file, get_frame_size ());#endif#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) sdbout_end_epilogue ();#endif#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) dwarfout_end_epilogue ();#endif#ifdef XCOFF_DEBUGGING_INFO if (write_symbols == XCOFF_DEBUG) xcoffout_end_epilogue (file);#endif bb_func_label_num = -1; /* not in function, nuke label # */ /* If FUNCTION_EPILOGUE is not defined, then the function body itself contains return instructions wherever needed. */}/* Add a block to the linked list that remembers the current line/file/function for basic block profiling. Emit the label in front of the basic block and the instructions that increment the count field. */static voidadd_bb (file) FILE *file;{ struct bb_list *ptr = (struct bb_list *) permalloc (sizeof (struct bb_list)); /* Add basic block to linked list. */ ptr->next = 0; ptr->line_num = last_linenum; ptr->file_label_num = bb_file_label_num; ptr->func_label_num = bb_func_label_num; *bb_tail = ptr; bb_tail = &ptr->next; /* Enable the table of basic-block use counts to point at the code it applies to. */ ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks); /* Before first insn of this basic block, increment the count of times it was entered. */#ifdef BLOCK_PROFILER BLOCK_PROFILER (file, count_basic_blocks); CC_STATUS_INIT;#endif new_block = 0; count_basic_blocks++;}/* Add a string to be used for basic block profiling. */static intadd_bb_string (string, perm_p) char *string; int perm_p;{ int len; struct bb_str *ptr = 0; if (!string) { string = "<unknown>"; perm_p = TRUE; } /* Allocate a new string if the current string isn't permanent. If the string is permanent search for the same string in other allocations. */ len = strlen (string) + 1; if (!perm_p) { char *p = (char *) permalloc (len); bcopy (string, p, len); string = p; } else for (ptr = sbb_head; ptr != (struct bb_str *)0; ptr = ptr->next) if (ptr->string == string) break; /* Allocate a new string block if we need to. */ if (!ptr) { ptr = (struct bb_str *) permalloc (sizeof (*ptr)); ptr->next = 0; ptr->length = len; ptr->label_num = sbb_label_num++; ptr->string = string; *sbb_tail = ptr; sbb_tail = &ptr->next; } return ptr->label_num;}/* Output assembler code for some insns: all or part of a function. For description of args, see `final_start_function', above. PRESCAN is 1 if we are not really outputting, just scanning as if we were outputting. Prescanning deletes and rearranges insns just like ordinary output. PRESCAN is -2 if we are outputting after having prescanned. In this case, don't try to delete or rearrange insns because that has already been done. Prescanning is done only on certain machines. */voidfinal (first, file, optimize, prescan) rtx first; FILE *file; int optimize; int prescan;{ register rtx insn; int max_line = 0; last_ignored_compare = 0; new_block = 1; /* Make a map indicating which line numbers appear in this function. When producing SDB debugging info, delete troublesome line number notes from inlined functions in other files as well as duplicate line number notes. */#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) { rtx last = 0; for (insn = first; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) { if ((RTX_INTEGRATED_P (insn) && strcmp (NOTE_SOURCE_FILE (insn), main_input_filename) != 0) || (last != 0 && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last) && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last))) { NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (insn) = 0; continue; } last = insn; if (NOTE_LINE_NUMBER (insn) > max_line) max_line = NOTE_LINE_NUMBER (insn); } } else#endif { for (insn = first; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line) max_line = NOTE_LINE_NUMBER (insn); } line_note_exists = (char *) oballoc (max_line + 1); bzero (line_note_exists, max_line + 1); for (insn = first; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) line_note_exists[NOTE_LINE_NUMBER (insn)] = 1; init_recog (); CC_STATUS_INIT; /* Output the insns. */ for (insn = NEXT_INSN (first); insn;) insn = final_scan_insn (insn, file, optimize, prescan, 0); /* Do basic-block profiling here if the last insn was a conditional branch. */ if (profile_block_flag && new_block) add_bb (file);}/* The final scan for one insn, INSN. Args are same as in `final', except that INSN is the insn being scanned. Value returned is the next insn to be scanned. NOPEEPHOLES is the flag to disallow peephole processing (currently used for within delayed branch sequence output). */rtxfinal_scan_insn (insn, file, optimize, prescan, nopeepholes) rtx insn; FILE *file; int optimize; int prescan; int nopeepholes;{ register int i; insn_counter++; /* Ignore deleted insns. These can occur when we split insns (due to a template of "#") while not optimizing. */ if (INSN_DELETED_P (insn)) return NEXT_INSN (insn); switch (GET_CODE (insn)) { case NOTE: if (prescan > 0) break; /* Align the beginning of a loop, for higher speed on certain machines. */ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0) {#ifdef ASM_OUTPUT_LOOP_ALIGN rtx next = next_nonnote_insn (insn); if (next && GET_CODE (next) == CODE_LABEL) { ASM_OUTPUT_LOOP_ALIGN (asm_out_file); }#endif break; } if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) break; if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) {#ifdef FUNCTION_END_PROLOGUE FUNCTION_END_PROLOGUE (file);#endif profile_after_prologue (file); break; }#ifdef FUNCTION_BEGIN_EPILOGUE if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) { FUNCTION_BEGIN_EPILOGUE (file); break; }#endif if (write_symbols == NO_DEBUG) break; if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) {#if defined(SDB_DEBUGGING_INFO) && defined(MIPS_DEBUGGING_INFO) /* MIPS stabs require the parameter descriptions to be after the function entry point rather than before. */ if (write_symbols == SDB_DEBUG) sdbout_begin_function (last_linenum); else#endif#ifdef DWARF_DEBUGGING_INFO /* This outputs a marker where the function body starts, so it must be after the prologue. */ if (write_symbols == DWARF_DEBUG) dwarfout_begin_function ();#endif break; } if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED) break; /* An insn that was "deleted" */ if (app_on) { fprintf (file, ASM_APP_OFF); app_on = 0; } if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG && (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE#ifdef DWARF_DEBUGGING_INFO || write_symbols == DWARF_DEBUG#endif ) ) { /* Beginning of a symbol-block. Assign it a sequence number and push the number onto the stack PENDING_BLOCKS. */ if (block_depth == max_block_depth) { /* PENDING_BLOCKS is full; make it longer. */ max_block_depth *= 2; pending_blocks = (int *) xrealloc (pending_blocks, max_block_depth * sizeof (int)); } pending_blocks[block_depth++] = next_block_index; high_block_linenum = last_linenum; /* Output debugging info about the symbol-block beginning. */#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) sdbout_begin_block (file, last_linenum, next_block_index);#endif#ifdef XCOFF_DEBUGGING_INFO if (write_symbols == XCOFF_DEBUG) xcoffout_begin_block (file, last_linenum, next_block_index);#endif#ifdef DBX_DEBUGGING_INFO if (write_symbols == DBX_DEBUG) ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);#endif#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG && block_depth > 1) dwarfout_begin_block (next_block_index);#endif next_block_index++; } else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END && (debug_info_level == DINFO_LEVEL_NORMAL || debug_info_level == DINFO_LEVEL_VERBOSE#ifdef DWARF_DEBUGGING_INFO || write_symbols == DWARF_DEBUG#endif ) ) { /* End of a symbol-block. Pop its sequence number off PENDING_BLOCKS and output debugging info based on that. */ --block_depth;#ifdef XCOFF_DEBUGGING_INFO if (write_symbols == XCOFF_DEBUG && block_depth >= 0) xcoffout_end_block (file, high_block_linenum, pending_blocks[block_depth]);#endif#ifdef DBX_DEBUGGING_INFO if (write_symbols == DBX_DEBUG && block_depth >= 0) ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", pending_blocks[block_depth]);#endif#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG && block_depth >= 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -