当前位置: 首页 > article >正文

中间表示- 三地址码

使用三地址码的编译器结构

三地址码的基本思想

(1)给每个中间变量和计算结果命名,没有复合表达式

(2)只有最基本的控制流,没有各种控制结构(if、do、while、for等等),只有goto,call等

(3)所以三地址码可以看成是抽象的指令集,如通用的RISC

 我们来看一个例子

a = 3 + 4 * 5;

if (x < y)
    z = 6;
else
    z = 7;

把上述程序翻译为三地址码后,程序如下:

x_1 = 4;
x_2 = 5;
x_3 = x_1 * x_2;
x_4 = 3;
x_5 = x_4 + x_3;
a = x_5;

Cjmp (x < y, L_1, L_2);  // 条件跳转
L_1:
    z = 6 ;
    jmp L_3;
L_2:
    z = 7;
    jmp L_3;
L_3:
    ...

三地址码的定义

如何定义三地址码数据结构?

enum instr_kind {INSTR_CONST, INSTR_MOVE, ...};
struct Instr_t
{
    enum instr_kind kind;
};

struct Instr_Add
{
    enum instr_kind kind;
    char *x;
    char *y;
    char *z;
};

struct Instr_Move
{
    /* data */
};

如何生成三地址码?

以 C--生成三地址码 为例

要写如下几个递归函数来生成三地址码

Gen_P(P);Gen_F (F) ;Gen_T(T);Gen_S(S); Gen_E(E);

我们重点关注语句的代码生成,其余的可参考代码生成- 寄存器计算机_青衫客36的博客-CSDN博客

 

Gen_S(S s)
{
    switch (s)
    {
        case x = e:
            x1 = Gen_E(e);  // 每个表达式的值要放在一个变量里
            emit("x = x1");
            break;

        case printi(e):
            x = Gen_E(e);
            emit("printi(x)");
            break;
        
        case printb(e):
            x = Gen_E(e);
            emit("printb(x)");
            break;

        case x(e1, ..., en):
            x1 = Gen_E(e1);
            ...;
            xn = Gen_E(en);
            emit("x(x1, ..., xn)");
            break;

        case return e:
            x = Gen_E(e);
            emit("return x");
            break;

        case if (e, s1, s2):
            x = Gen_E(e);
            emit("Cjmp(x, L1, L2)");
            emit("Label L1:");
            Gen_SList(s1);
            emit("jmp L3");
            emit("Label L2:");
            Gen_SList(s2);
            emit("jmp L3");
            emit("Label L3:");
            break;

        case while (e, s):
            emit("Label L1:");
            x = Gen_E(e);
            emit("Cjmp(x, L2, L3)");
            emit("Label L2:");
            Gen_SList(s);
            emit("jmp L1");
            emit("Label L3:");
            break;

        default:
            break;
    }
}

小结

(1)三地址码的优点:

  • 所有的操作都是原子的,变量!没有复合结构
  • 控制流结构被简化了,只有跳转
  • 是抽象的机器代码,向后做代码生成更容易

(2)三地址码的不足:

  • 程序的控制流信息是隐式的
  • 可以做进一步的控制流分析

http://www.kler.cn/a/7433.html

相关文章:

  • g++与gdb简单学习
  • ODC 如何精确呈现SQL耗时 | OceanBase 开发者工具解析
  • 【linux学习指南】VSCode部署Ubantu云服务器,与Xshell进行本地通信文件编写
  • Nginx: 实现Websocket代理
  • SQL Server Service Broker完整示例
  • 一文学会docker中搭建kali
  • 从零开始实现一个C++高性能服务器框架----环境变量模块
  • 2 新建工程步骤
  • 045:cesium加载OpenStreetMap地图
  • 第十四届蓝桥杯模拟赛(第一期)——C语言版
  • 详解如何使用Nginx搭建文件服务器及实现文件服务
  • 询问ChatGPT的高质量答案艺术——提示工程指南(更新中……)
  • 什么是服务架构?微服务架构的优势又是什么?
  • 聚会Party
  • 剪枝与重参第四课:NVIDIA的2:4剪枝方案
  • 做了个springboot接口参数解密的工具,我给它命名为万能钥匙(已上传maven中央仓库,附详细使用说明)
  • 4.5--计算机网络之基础篇--1.模型分层--(复习+深入)---好好沉淀,加油呀
  • Elasticsearch:索引状态是红色还是黄色?为什么?
  • C++ 数组与字符串详解
  • 51单片机-LED篇
  • erpnext--指令
  • 多个硬盘挂载到同一个目录
  • 重新理解一个类中的forward()和__init__()函数
  • MyBatisPlus-DML编程控制
  • Muduo库源码剖析(八)——TcpServer类
  • 腾讯云轻量应用服务器价格表(2023版)