猿代码 — 科研/AI模型/高性能计算
0

GCC:从GIMPLE到RTL

摘要: 寄存器传输语言表示具有 无限数量的寄存器。类型rtx描述指令。每个 RTL 表达式都有一个代码和机器模式。与 AST 类似,代码分为多个类。它们在 mode-classes.def 中定义。RTL 表达式的类类解释RTX_CONST_OBJ表示一个 ...

寄存器传输语言表示具有 无限数量的寄存器。类型 rtx 描述指令。每个 RTL 表达式都有一个代码和机器模式。

与 AST 类似,代码分为多个类。它们在 mode-classes.def 中定义。

RTL 表达式的类
解释
RTX_CONST_OBJ表示一个常量对象(例如,CONST_INT)
RTX_OBJ表示对象(例如,REG、MEM)
RTX_COMPARE比较(例如,LT、GT)
RTX_COMM_COMPARE交换比较(例如,EQ、NE、ORDERED)
RTX_UNARY一元算术表达式(例如,NEG、NOT)
RTX_COMM_ARITH交换二进制运算(例如,、PLUS、MULT)
RTX_TERNARY非位域三输入操作 (IF_THEN_ELSE)
RTX_BIN_ARITH非交换二进制运算(例如,MINUS、DIV)
RTX_BITFIELD_OPS位字段操作(ZERO_EXTRACT、SIGN_EXTRACT)
RTX_INSN机器 insn (INSN, JUMP_INSN, CALL_INSN)
RTX_MATCH在 INSNS 中匹配的内容(例如,MATCH_DUP)
RTX_AUTOINC自动增量寻址模式(例如POST_DEC)
RTX_EXTRA一切

文件 machmode.def 中列出的计算机模式指定计算机级别的数据大小和格式。在语法树级别,每个..._TYPE和每个..._DECL节点都有一个机器模式,用于描述该类型的数据或声明的变量的数据。

编译函数时会生成指令列表。函数 emit_insn() 将指令添加到列表中。变量声明 AST 已生成其 RTL。使用DECL_RTL 以访问它。函数 emit_cmp_and_jump_insns() 输出一个条件 陈述。emit_label() 打印出标签。这些函数链指令 一个接一个。宏 PREV_INSN 和 NEXT_INSN 用于遍历 列表。

可以使用以下方法访问第一个和最后一个指令 first_insn和last_insn。get_insns() 给出当前序列或当前函数的第一个 insn。

使用 debug_rtx() 在屏幕上打印出 RTL 指令,然后 函数 print_rtl() 打印 RTL 表达式列表。

许多函数创建节点。例如,gen_label_rtx() 构建标签。最通用的函数位于 特定于目标的目录。例如,x86 架构 rtl 生成文件 genrtl.c 和 genrtl.h 位于 ./host-i686-pc-linux-gnu 中。

从RTL到对象[编辑源代码]

每个目标体系结构都有其描述为结构 gcc_target targetm.默认初始值设定项在文件中可用 targhooks.c网站

后端为指定的目标平台生成汇编代码。函数 output_asm_insn() 为写入汇编文件的每条指令调用。函数 final_start_function() 在将函数保存到程序集文件之前生成函数的序言。

降低通行证[编辑源代码]

函数的处理包括当多个 优化刀路在函数中应用于它 tree_lowering_passes()。由于降低了函数,其 生成控制流图。对函数的后续调用 cgraph_create_edges() 使用基本的块信息来增强 调用当前函数的调用图 执行。对尚未定义的函数的引用保存在函数中 record_references()。

所有下降刀路
名字意义
remove_useless_stmts不适用
mudflap_1窄指针边界-通过树重写进行检查
lower_cf将 GIMPLE 降低为非结构化形式
pass_lower_eh树的异常处理语义和分解
pass_build_cfg创建基本块
pass_lower_complex_O0操作复杂,无需优化
pass_lower_vector将矢量运算降低到标量运算
pass_warn_function_return发出返回警告
pass_early_tree_profile为基于树的分析设置挂钩

Switch 语句[编辑源代码]

让我们考虑一下 switch 语句是如何从源翻译的 代码到 GIMPLE 到 RTL。

函数 c_parser_switch_statement() 在语句 在源代码中遇到。典型的 switch 语句具有 可能有中断的 case 语句数。因此, 解析器c_break_label树,用于标记 switch 的位置 结束。该函数解析语句的正文并生成 LABEL_EXPR中断标签的树(如果至少有一个中断是 发现。函数 c_finish_case() 将主体附加到SWITCH_EXPR tree 作为其操作数之一。此外,这棵树还有另外两个 操作数:切换条件和切换标签。操作数是 使用宏 SWITCH_COND()、SWITCH_BODY() 和 SWITCH_LABELS()。在分析时不会填充标签。

switch 语句在函数中被简化 gimplify_switch_expr()。这个想法是将身体与身体分开 决策部分并生成开关标签,使其成为可能 在验证 条件。我们将考虑默认标签存在的情况。这 函数有两个指向 语句列表:pre_p是副作用和expr_p的列表 这是声明本身。

开关的主体在 gimplify_to_stmt_list()。案例标签保存在字段case_labels 变量结构gimplify_ctx gimplify_ctxp。然后函数创建 标签和初始化的TREE_VEC 它们带有相应的大小写标签。分配TREE_VEC SWITCH_LABELS switch 语句的操作数,然后将其附加到 pre_p列表。然后,原始语句是 使用指针expr_p SWITCH_BODY覆盖。最后, 副作用列表中 switch 语句的SWITCH_BODY操作数是 擦除,使其仅包含标签。

从这一点来看,很明显编译器试图表示 使用映射每个可能索引的跳转表的原始语句 值设置为相应案例的地址。函数 expand_case() 实现这个想法。它生成一个跳跃table_label 将生成每个可能的索引值的指令。然后 调用函数 try_tablejump() 将索引树扩展为索引 RTL 并调用 do_tablejump()。此函数生成绝对值 索引 RTL,它结合了基址table_label和索引 抵消。它向跳跃的正确入口发出跳转指令 表后。执行继续功能 expand_case()。跳转表是使用 SWITCH_LABELS 生成的:

labelvec[i] = gen_rtx_LABEL_REF (Pmode, label_rtx (n->code_label));

最后发出许多跳转指令:

if (CASE_VECTOR_PC_RELATIVE || flag_pic)
  emit_jump_insn (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
                                         gen_rtx_LABEL_REF (Pmode, table_label),
                                         gen_rtvec_v (ncases, labelvec),
                                         const0_rtx, const0_rtx));
上一篇:GCC:从AST到GIMPLE下一篇:GCC:SSA,RTL

说点什么...

已有0条评论

最新评论...

本文作者
2024-2-14 01:49
  • 0
    粉丝
  • 222
    阅读
  • 0
    回复
资讯幻灯片
热门评论
热门专题
排行榜
Copyright   ©2015-2023   猿代码-超算人才智造局 高性能计算|并行计算|人工智能      ( 京ICP备2021026424号-2 )