在完成了IR-RTL的优化与寄存器分配后
就来到汇编代码的输出:
实现如下:
class pass_final : public rtl_opt_pass
{
public:
pass_final (gcc::context *ctxt)
: rtl_opt_pass (pass_data_final, ctxt)
{}
/* opt_pass methods: */
unsigned int execute (function *) final override
{
return rest_of_handle_final ();
}
}; // class pass_final
} // anon namespace
rest_of_handle_final (void)
{
const char *fnname = get_fnname_from_decl (current_function_decl);
/* Turn debug markers into notes if the var-tracking pass has not
been invoked. */
if (!flag_var_tracking && MAY_HAVE_DEBUG_MARKER_INSNS)
delete_vta_debug_insns (false);
assemble_start_function (current_function_decl, fnname);
rtx_insn *first = get_insns ();
int seen = 0;
final_start_function_1 (&first, asm_out_file, &seen, optimize);
final_1 (first, asm_out_file, seen, optimize);
if (flag_ipa_ra
&& !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))
/* Functions with naked attributes are supported only with basic asm
statements in the body, thus for supported use cases the information
on clobbered registers is not available. */
&& !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)))
collect_fn_hard_reg_usage ();
final_end_function ();
/* The IA-64 ".handlerdata" directive must be issued before the ".endp"
directive that closes the procedure descriptor. Similarly, for x64 SEH.
Otherwise it's not strictly necessary, but it doesn't hurt either. */
output_function_exception_table (crtl->has_bb_partition ? 1 : 0);
assemble_end_function (current_function_decl, fnname);
/* Free up reg info memory. */
free_reg_info ();
if (! quiet_flag)
fflush (asm_out_file);
/* Note that for those inline functions where we don't initially
know for certain that we will be generating an out-of-line copy,
the first invocation of this routine (rest_of_compilation) will
skip over this code by doing a `goto exit_rest_of_compilation;'.
Later on, wrapup_global_declarations will (indirectly) call
rest_of_compilation again for those inline functions that need
to have out-of-line copies generated. During that call, we
*will* be routed past here. */
timevar_push (TV_SYMOUT);
if (!DECL_IGNORED_P (current_function_decl))
debug_hooks->function_decl (current_function_decl);
timevar_pop (TV_SYMOUT);
/* Release the blocks that are linked to DECL_INITIAL() to free the memory. */
DECL_INITIAL (current_function_decl) = error_mark_node;
if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
&& targetm.have_ctors_dtors)
targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0),
decl_init_priority_lookup
(current_function_decl));
if (DECL_STATIC_DESTRUCTOR (current_function_decl)
&& targetm.have_ctors_dtors)
targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
decl_fini_priority_lookup
(current_function_decl));
return 0;
}
static void
final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)
{
rtx_insn *insn, *next;
/* Used for -dA dump. */
basic_block *start_to_bb = NULL;
basic_block *end_to_bb = NULL;
int bb_map_size = 0;
int bb_seqn = 0;
last_ignored_compare = 0;
init_recog ();
CC_STATUS_INIT;
if (flag_debug_asm)
{
basic_block bb;
bb_map_size = get_max_uid () + 1;
start_to_bb = XCNEWVEC (basic_block, bb_map_size);
end_to_bb = XCNEWVEC (basic_block, bb_map_size);
/* There is no cfg for a thunk. */
if (!cfun->is_thunk)
FOR_EACH_BB_REVERSE_FN (bb, cfun)
{
start_to_bb[INSN_UID (BB_HEAD (bb))] = bb;
end_to_bb[INSN_UID (BB_END (bb))] = bb;
}
}
/* Output the insns. */
for (insn = first; insn;)
{
if (HAVE_ATTR_length)
{
if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
{
/* This can be triggered by bugs elsewhere in the compiler if
new insns are created after init_insn_lengths is called. */
gcc_assert (NOTE_P (insn));
insn_current_address = -1;
}
else
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
/* final can be seen as an iteration of shorten_branches that
does nothing (since a fixed point has already been reached). */
insn_last_address = insn_current_address;
}
dump_basic_block_info (file, insn, start_to_bb, end_to_bb,
bb_map_size, &bb_seqn);
insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
}
maybe_output_next_view (&seen);
if (flag_debug_asm)
{
free (start_to_bb);
free (end_to_bb);
}
/* Remove CFI notes, to avoid compare-debug failures. */
for (insn = first; insn; insn = next)
{
next = NEXT_INSN (insn);
if (NOTE_P (insn)
&& (NOTE_KIND (insn) == NOTE_INSN_CFI
|| NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL))
delete_insn (insn);
}
}
rtx_insn *
final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
int nopeepholes, int *seen)
{
static int *enclosing_seen;
static int recursion_counter;
gcc_assert (seen || recursion_counter);
gcc_assert (!recursion_counter || !seen || seen == enclosing_seen);
if (!recursion_counter++)
enclosing_seen = seen;
else if (!seen)
seen = enclosing_seen;
rtx_insn *ret = final_scan_insn_1 (insn, file, optimize_p, nopeepholes, seen);
if (!--recursion_counter)
enclosing_seen = NULL;
return ret;
}
static rtx_insn *
final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
int nopeepholes ATTRIBUTE_UNUSED, int *seen)
{
rtx_insn *next;
rtx_jump_table_data *table;
insn_counter++;
/* Ignore deleted insns. These can occur when we split insns (due to a
template of "#") while not optimizing. */
if (insn->deleted ())
return NEXT_INSN (insn);
switch (GET_CODE (insn))
{
case NOTE:
switch (NOTE_KIND (insn))
{
case NOTE_INSN_DELETED:
case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
maybe_output_next_view (seen);
output_function_exception_table (0);
if (targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
in_cold_section_p = !in_cold_section_p;
gcc_checking_assert (in_cold_section_p);
if (in_cold_section_p)
cold_function_name
&n

最低0.47元/天 解锁文章
1390

被折叠的 条评论
为什么被折叠?



