gcc 源码分析:从IR-RTL 到汇编输出

在完成了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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoldKey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值