寄存器传输语言表示具有 无限数量的寄存器。类型 rtx 描述指令。每个 RTL 表达式都有一个代码和机器模式。 与 AST 类似,代码分为多个类。它们在 mode-classes.def 中定义。
文件 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()。
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 生成的: 最后发出许多跳转指令: |
说点什么...