gcc 源码分析--从gimple 到IR-RTL

gcc 源码分析:机器描述文件 GCC后端机器描述文件位于gcc/config目录中,各硬件平台有独立子目录,如xtensa平台包含xtensa.md(机器描述)、xtensa.h和xtensa.c三个核心文件。其中.h/.c文件定义目标机器的存储布局、调用规范等结构体targetm;.md文件则通过指令模板、属性定义等将机器特性引入编译器,指导IR-RTL到汇编的转换。关键转换过程分为两个阶段:GIMPLE到SPN的机器无关映射,以及SPN到IR-RTL的机器相关转换(通过匹配.md文件中命名的define_insn模板)。optabs 阅读详情

这个转换是由gcc 一个pass 来完成的

class pass_expand : public rtl_opt_pass

具体在:

unsigned int
pass_expand::execute (function *fun)
{

  basic_block bb, init_block;
  edge_iterator ei;
  edge e;
  rtx_insn *var_seq, *var_ret_seq;
  unsigned i;

  timevar_push (TV_OUT_OF_SSA);
  rewrite_out_of_ssa (&SA);
  timevar_pop (TV_OUT_OF_SSA);
  SA.partition_to_pseudo = XCNEWVEC (rtx, SA.map->num_partitions);

  if (MAY_HAVE_DEBUG_BIND_STMTS && flag_tree_ter)
    {
      gimple_stmt_iterator gsi;
      FOR_EACH_BB_FN (bb, cfun)
    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
      if (gimple_debug_bind_p (gsi_stmt (gsi)))
        avoid_deep_ter_for_debug (gsi_stmt (gsi), 0);
    }

  /* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE.  */
  auto_bitmap forced_stack_vars;
  discover_nonconstant_array_refs (forced_stack_vars);

  /* Make sure all values used by the optimization passes have sane
     defaults.  */
  reg_renumber = 0;

  /* Some backends want to know that we are expanding to RTL.  */
  currently_expanding_to_rtl = 1;
  /* Dominators are not kept up-to-date as we may create new basic-blocks.  */
  free_dominance_info (CDI_DOMINATORS);

  rtl_profile_for_bb (ENTRY_BLOCK_PTR_FOR_FN (fun));

  insn_locations_init ();
  if (!DECL_IS_UNDECLARED_BUILTIN (current_function_decl))
    {
      /* Eventually, all FEs should explicitly set function_start_locus.  */
      if (LOCATION_LOCUS (fun->function_start_locus) == UNKNOWN_LOCATION)
    set_curr_insn_location
      (DECL_SOURCE_LOCATION (current_function_decl));
      else
    set_curr_insn_location (fun->function_start_locus);
    }
  else
    set_curr_insn_location (UNKNOWN_LOCATION);
  prologue_location = curr_insn_location ();

#ifdef INSN_SCHEDULING
  init_sched_attrs ();
#endif

  /* Make sure first insn is a note even if we don't want linenums.
     This makes sure the first insn will never be deleted.
     Also, final expects a note to appear there.  */
  emit_note (NOTE_INSN_DELETED);

  targetm.expand_to_rtl_hook ();
  crtl->init_stack_alignment ();
  fun->cfg->max_jumptable_ents = 0;

  /* Resovle the function section.  Some targets, like ARM EABI rely on knowledge
     of the function section at exapnsion time to predict distance of calls.  */
  resolve_unique_section (current_function_decl, 0, flag_function_sections);

  /* Expand the variables recorded during gimple lowering.  */
  timevar_push (TV_VAR_EXPAND);
  start_sequence ();

  var_ret_seq = expand_used_vars (forced_stack_vars);

  var_seq = get_insns ();
  end_sequence ();
  timevar_pop (TV_VAR_EXPAND);

  /* Honor stack protection warnings.  */
  if (warn_stack_protect)
    {
      if (fun->calls_alloca)
    warning (OPT_Wstack_protector,
         "stack protector not protecting local variables: "
         "variable length buffer");
      if (has_short_buffer && !crtl->stack_protect_guard)
    warning (OPT_Wstack_protector,
         "stack protector not protecting function: "
         "all local arrays are less than %d bytes long",
         (int) param_ssp_buffer_size);
    }

  /* Temporarily mark PARM_DECLs and RESULT_DECLs we need to expand to
     memory addressable so expand_function_start can emit the required
     copies.  */
  auto_vec<tree, 16> marked_parms;
  for (tree parm = DECL_ARGUMENTS (current_function_decl); parm;
       parm = DECL_CHAIN (parm))
    if (!TREE_ADDRESSABLE (parm)
    && bitmap_bit_p (forced_stack_vars, DECL_UID (parm)))
      {
    TREE_ADDRESSABLE (parm) = 1;
    marked_parms.safe_push (parm);
      }
  if (DECL_RESULT (current_function_decl)
      && !TREE_ADDRESSABLE (DECL_RESULT (current_function_decl))
      && bitmap_bit_p (forced_stack_vars,
               DECL_UID (DECL_RESULT (current_function_decl))))
    {
      TREE_ADDRESSABLE (DECL_RESULT (current_function_decl)) = 1;
      marked_parms.safe_push (DECL_RESULT (current_function_decl));
    }

  /* Set up parameters and prepare for return, for the function.  */
  expand_function_start (current_function_decl);

  /* Clear TREE_ADDRESSABLE again.  */
  while (!marked_parms.is_empty ())
    TREE_ADDRESSABLE (marked_parms.pop ()) = 0;

  /* If we emitted any instructions for setting up the variables,
     emit them before the FUNCTION_START note.  */
  if (var_seq)
    {
      emit_insn_before (var_seq, parm_birth_insn);

      /* In expand_function_end we'll insert the alloca save/restore
     before parm_birth_insn.  We've just insertted an alloca call.
     Adjust the pointer to match.  */
      parm_birth_insn = var_seq;
    }

  /* Now propagate the RTL assignment of each partition to the
     underlying var of each SSA_NAME.  */
  tree name;

  FOR_EACH_SSA_NAME (i, name, cfun)
    {
      /* We might have generated new SSA names in
     update_alias_info_with_stack_vars.  They will have a NULL
     defining statements, and won't be part of the partitioning,
     so ignore those.  */
      if (!SSA_NAME_DEF_STMT (name))
    continue;

      adjust_one_expanded_partition_var (name);
    }

  /* Clean up RTL of variables that straddle across multiple
     partitions, and check that the rtl of any PARM_DECLs that are not
     cleaned up is that of their default defs.  */
  FOR_EACH_SSA_NAME (i, name, cfun)
    {
      int part;

      /* We might have generated new SSA names in
     update_alias_info_with_stack_vars.  They will have a NULL
     defining statements, and won't be part of the partitioning,
     so ignore those.  */
      if (!SSA_NAME_DEF_STMT (name))
    continue;
      part = var_to_partition (SA.map, name);
      if (part == NO_PARTITION)
    continue;

      /* If this decl was marked as living in multiple places, reset
     this now to NULL.  */
      tree var = SSA_NAME_VAR (name);
      if (var && DECL_RTL_IF_SET (var) == pc_rtx)
    SET_DECL_RTL (var, NULL);
      /* Check that the pseudos chosen by assign_parms are those of
     the corresponding default defs.  */
      else if (SSA_NAME_IS_DEFAULT_DEF (name)
           && (TREE_CODE (var) == PARM_DECL
           || TREE_CODE (var) == RESULT_DECL))
    {
      rtx in = DECL_RTL_IF_SET (var);
      gcc_assert (in);
      rtx out = SA.partition_to_pseudo[part];
      gcc_assert (in == out);

      /* Now reset VAR's RTL to IN, so that the _EXPR attrs match
         those expected by debug backends for each parm and for
         the result.  This is particularly important for stabs,
         whose register elimination from parm's DECL_RTL may cause
         -fcompare-debug differences as SET_DECL_RTL changes reg's
         attrs.  So, make sure the RTL already has the parm as the
         EXPR, so that it won't change.  */
      SET_DECL_RTL (var, NULL_RTX);
      if (MEM_P (in))
        set_mem_attributes (in, var, true);
      SET_DECL_RTL (var, in);
    }
    }

  /* If this function is `main', emit a call to `__main'
     to run global initializers, etc.  */
  if (DECL_NAME (current_function_decl)
      && MAIN_NAME_P (DECL_NAME (current_function_decl))
      && DECL_FILE_SCOPE_P (current_function_decl))
    expand_main_function ();

  /* Initialize the stack_protect_guard field.  This must happen after the
     call to __main (if any) so that the external decl is initialized.  */
  if (crtl->stack_protect_guard && targetm.stack_protect_runtime_enabled_p ())
    stack_protect_prologue ();

  expand_phi_nodes (&SA);

  /* Release any stale SSA redirection data.  */
  redirect_edge_var_map_empty ();

  /* Register rtl specific functions for cfg.  */
  rtl_register_cfg_hooks ();

  init_block = construct_init_block ();

  /* Clear EDGE_EXECUTABLE on the entry edge(s).  It is cleaned from the
     remaining edges later.  */
  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs)
    e->flags &= ~EDGE_EXECUTABLE;

  /* If the function has too many markers, drop them while expanding.  */
  if (cfun->debug_marker_count
      >= param_max_debug_marker_count)
    cfun->debug_nonbind_markers = false;

  lab_rtx_for_bb = new hash_map<basic_block, rtx_code_label *>;
  FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR_FOR_FN (fun),
          next_bb)
    bb = expand_gimple_basic_block (bb, var_ret_seq != NULL_RTX);

  if (MAY_HAVE_DEBUG_BIND_INSNS)
    expand_debug_locations ();

  if (deep_ter_debug_map)
    {
      delete deep_ter_debug_map;
      deep_ter_debug_map = NULL;
    }

  /* Free stuff we no longer need after GIMPLE optimizations.  */
  free_dominance_info (CDI_DOMINATORS);
  free_dominance_info (CDI_POST_DOMINATORS);
  delete_tree_cfg_annotations (fun);

  timevar_push (TV_OUT_OF_SSA);
  finish_out_of_ssa (&SA);
  timevar_pop (TV_OUT_OF_SSA);

  timevar_push (TV_POST_EXPAND);
  /* We are no longer in SSA form.  */
  fun->gimple_df->in_ssa_p = false;
  loops_state_clear (LOOP_CLOSED_SSA);

  /* Expansion is used by optimization passes too, set maybe_hot_insn_p
     conservatively to true until they are all profile aware.  */
  delete lab_rtx_for_bb;
  free_histograms (fun);

  construct_exit_block ();
  insn_locations_finalize ();

  if (var_ret_seq)
    {
      rtx_insn *after = return_label;
      rtx_insn *next = NEXT_INSN (after);
      if (next && NOTE_INSN_BASIC_BLOCK_P (next))
    after = next;
      emit_insn_after (var_ret_seq, after);
    }

  if (hwasan_sanitize_stack_p ())
    hwasan_maybe_emit_frame_base_init ();

  /* Zap the tree EH table.  */
  set_eh_throw_stmt_table (fun, NULL);

  /* We need JUMP_LABEL be set in order to redirect jumps, and hence
     split edges which edge insertions might do.  */
  rebuild_jump_labels (get_insns ());

  /* If we have a single successor to the entry block, put the pending insns
     after parm birth, but before NOTE_INSNS_FUNCTION_BEG.  */
  if (single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (fun)))
    {
      edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (fun));
      if (e->insns.r)
    {
      rtx_insn *insns = e->insns.r;
      e->insns.r = NULL;
      rebuild_jump_labels_chain (insns);
      if (NOTE_P (parm_birth_insn)
          && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
        emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
      else
        emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
    }
    }

  /* Otherwise, as well as for other edges, take the usual way.  */
  commit_edge_insertions ();

  /* We're done expanding trees to RTL.  */
  currently_expanding_to_rtl = 0;

  flush_mark_addressable_queue ();

  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (fun)->next_bb,
          EXIT_BLOCK_PTR_FOR_FN (fun), next_bb)
    {
      edge e;
      edge_iterator ei;
      for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
    {
      /* Clear EDGE_EXECUTABLE.  This flag is never used in the backend.  */
      e->flags &= ~EDGE_EXECUTABLE;

      /* At the moment not all abnormal edges match the RTL
         representation.  It is safe to remove them here as
         find_many_sub_basic_blocks will rediscover them.
         In the future we should get this fixed properly.  */
      if ((e->flags & EDGE_ABNORMAL)
          && !(e->flags & EDGE_SIBCALL))
        remove_edge (e);
      else
        ei_next (&ei);
    }
    }

  auto_sbitmap blocks (last_basic_block_for_fn (fun));
  bitmap_ones (blocks);
  find_many_sub_basic_blocks (blocks);
  purge_all_dead_edges ();

  /* After initial rtl generation, call back to finish generating
     exception support code.  We need to do this before cleaning up
     the CFG as the code does not expect dead landing pads.  */
  if (fun->eh->region_tree != NULL)
    finish_eh_generation ();

  /* Call expand_stack_alignment after finishing all
     updates to crtl->preferred_stack_boundary.  */
  expand_stack_alignment ();

  /* Fixup REG_EQUIV notes in the prologue if there are tailcalls in this
     function.  */
  if (crtl->tail_call_emit)
    fixup_tail_calls ();

  HOST_WIDE_INT patch_area_size, patch_area_entry;
  parse_and_check_patch_area (flag_patchable_function_entry, false,
                  &patch_area_size, &patch_area_entry);

  tree patchable_function_entry_attr
    = lookup_attribute ("patchable_function_entry",
            DECL_ATTRIBUTES (cfun->decl));
  if (patchable_function_entry_attr)
    {
      tree pp_val = TREE_VALUE (patchable_function_entry_attr);
      tree patchable_function_entry_value1 = TREE_VALUE (pp_val);

      patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
      patch_area_entry = 0;
      if (TREE_CHAIN (pp_val) != NULL_TREE)
    {
      tree patchable_function_entry_value2
        = TREE_VALUE (TREE_CHAIN (pp_val));
      patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
    }
    }

  if (patch_area_entry > patch_area_size)
    {
      if (patch_area_size > 0)
    warning (OPT_Wattributes,
         "patchable function entry %wu exceeds size %wu",
         patch_area_entry, patch_area_size);
      patch_area_entry = 0;
    }

  crtl->patch_area_size = patch_area_size;
  crtl->patch_area_entry = patch_area_entry;

  /* BB subdivision may have created basic blocks that are only reachable
     from unlikely bbs but not marked as such in the profile.  */
  if (optimize)
 

【源码解析】C/C++开源代码解析引擎 C/C++代码解析,代码重构或后处理 阅读详情

相关推荐

LVGL v8.3 图片显示与解码缓存实战:PNG 上屏、C 数组与文件双方案

LVGL v8.3 图片两种存储方式、PNG/JPG 上屏解码器挂载、LV_IMG_CACHE_DEF_SIZE 缓存调优、手动预解码头像有效性判断,及"缓存被动画清空"真实踩坑。

汪同学的博客 408

GCC:堆栈溢出保护

因此在开发阶段最好使用-fstack-protector-all编译选项已便于早期捕捉到堆栈溢出问题。-fstack-protector:启用堆栈保护,不过只为局部变量中含有 char。-fstack-protector-all:启用堆栈保护,为所有函数插入保护代码。-fstack-protector-strong:提供更广泛的堆栈保护。-fno-stack-protector:禁用堆栈保护。已放弃 (核心已转储)的函数插入保护代码。

风静如云的博客 5349

YOLO26算法心电图十二导联目标检测+训练好的模型+368张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[导联I(I), 导联II(II), 导联III(III), 胸导联V1(V1), 胸导联V2(V2), 胸导联V3(V3), 胸导联V4(V4), 胸导联V5(V5), 胸导联V6(V6), 加压肢体导联aVF(aVF), 加压肢体导联aVL(aVL), 加压肢体导联aVR(aVR)] · 训练集:313 张 · 验证集:37 张 · 测试集:18 张 · 总计:368 张 该数据集聚焦于临床心电图信号的精准识别与定位,其核心检测目标为标准12导联心电图中的各个独立导联波形区域,涵盖肢体导联(I、II、III)与加压肢体导联(aVR、aVL、aVF),以及胸前导联(V1至V6),适用于心电图自动分析系统中对各导联位置的快速准确标注与分类。数据采集场景真实还原了医院心电图室或急诊监护环境下的标准心电图记录纸,波形清晰、基线稳定,具有高度临床参考价值。... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 57 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.9708** mAP50-95 | 0.6344 Precision | 0.8990 Recall | 0.9191 train/box_loss | 1.2231 train/cls_loss | 0.9703 val/box_loss | 1.2779 val/cls_loss | 0.... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

企业级AI助手平台 开箱即用的全栈AI平台,支持多智能体协同、Supervisor模式编排、多种决策模式、RAG技术和流程编排能力 支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化

企业级AI应用开发框架,支持多厂商大模型统一接入与管理,安全可控的企业知识库与高精度检索优化能力,提供可视化流程编排、自主决策智能体与多智能体协同调度,兼容主流 Agent Skill 协议,帮助企业与开发者零门槛快速构建安全、高效、可落地的AI智能体应用与行业解决方案。

不只是CPU主频:深入解析英飞凌Aurix TC3xx各外设时钟树(CAN、以太网、Flash时序如何配置)

本文深入解析英飞凌Aurix TC3xx系列微控制器的外设时钟树配置,涵盖CAN、以太网和Flash时序的优化方法。通过详细分析时钟系统架构、关键外设配置及多外设协同设计策略,帮助工程师实现高性能汽车电子控制单元(ECU)开发。特别关注系统时钟的灵活配置与EMC优化技巧,提升系统实时性和可靠性。

weixin_29189373的博客 400

我用WorkBuddy“克隆“了一个我,从此每句话像我自己说的

各位,做这件事花了多长时间?准备样本可能要半小时,提炼风格十分钟,保存固化再花十分钟。加起来不到一个小时。但这一个小时之后呢?你就拥有了一个"永远在线的文字替身"。以后写口播稿,打开WorkBuddy跟它说;写课程逐字稿,跟它说;写公众号文章,也跟它说。写出来的东西,你的学员一看——“嘿,这不就是翟猛老师说的嘛。说到这儿,可能有人会问:老师,我的风格有那么重要吗?AI写的不都挺好的吗?各位你想想看,你为什么愿意听某个老师的课?不只是因为他讲的内容好,更是因为你喜欢他讲话的方式。

weixin_39284145的博客 818

Reality Capture控制点修复/合并模型

通过增加控制点/修改对齐设置参数来修复模型被分为两个部分的解决方法

草履虫建模的博客 5239

深入CRSF协议数据包:手撕STM32代码,教你像调试串口一样分析ELRS遥控数据流

本文深入解析CRSF协议数据包,通过手撕STM32代码,教你如何像调试串口一样分析ELRS遥控数据流。从硬件准备到数据包捕获状态机设计,再到高级数据分析技巧和实战应用,全面覆盖CRSF协议的解析与优化,帮助开发者构建稳定可靠的通信系统。

weixin_29194693的博客 337

WPF实战案例 | C# WPF实现大学选课系统

WPF实战案例_C# WPF实现大学选课系统, C# WPF实现大学选课系统,大作业,毕业设计,该系统实现多身份登录、修改密码、课程的管理,个人信息的管理等功能。这个源码让你快速搭建自己的应用程序,注释完整,代码规范,各种风格都有,代码上手简单,代码独立,可以直接用程序打开,运行使用。也可直接点击EXE运行程序。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 4623

信息安全管理与评估赛题解析-单机取证(含环境)

链接:https://pan.baidu.com/s/1OMzIq884dW2vAiUp0k2Ppg。链接:https://pan.baidu.com/s/1i5daMqhD53wYeQ6hYzRK6Q。链接:https://pan.baidu.com/s/1QFAjdQZK4sJ-gGRP42XPKA。链接:https://pan.baidu.com/s/1BSXvqN2ZGCQXewgFULoeyQ。链接:https://pan.baidu.com/s/1g9zu5ngBz_KMjW1eBMkJAw。

Brucye 1834

SAP_PP模块定额工艺路线简介

在 SAP PP(生产计划)模块中,定额工艺路线(Routing) 是生产制造流程中的核心主数据之一,用于定义制造一个产品所需的标准操作步骤。工艺路线详细描述了生产过程中的各个工序、使用的工作中心、标准作业时间、资源分配等信息,是进行生产计划、成本核算、排产控制、车间执行等功能的基础。

我小时候很黑的博客 763

YOLOv8 模型进化全解析:百种创新模块集成方法与实战部署指南(附资料链接)

动态网络 | DeformableConv/DynamicHead| +2.8% || 轻量化卷积 | GhostConv/MobileConv | +1.2% || 多尺度融合 | AFPN/ASFF | +3.5% || 注意力机制 | CA/EMA/SimAM | +1.8-4.2% |

FJN110的博客 111

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: gcc 源码分析:机器描述文件
下一篇: gcc 源码分析:从IR-RTL 到汇编输出
GoldKey
博客等级 码龄25年 82粉丝 27原创
评论
成就一亿技术人!
拼手气红包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、付费专栏及课程。

余额充值