【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

所谓中间代码生成,就是生成一种和具体汇编语言无关的中间代码。生成中间代码有很多的好处,一方面它可以转化成不同的汇编语言,使得后端移植变得很容易;另外一方面,中间代码可以做很多优化工作,剔除大量的冗余代码、无效代码、垃圾代码。

之间在语法分析、语义分析的时候,我们一直提到declaration、expression、statement这三种语句。等真正走到中间代码生成这个环节的时候,其实只需要处理expression和statement的翻译就可以了,declaration本身只是申明,这一部分其实可以省略了。

1、函数入口

void Translate(AstTranslationUnit transUnit)

2、语句翻译

tranexpr.c

https://github.com/sheisc/ucc162.3/blob/a92719fff0ab7eb5b0c45768acedabb3cd70ca05/ucc/ucl/tranexpr.c

transtmt.c

https://github.com/sheisc/ucc162.3/blob/a92719fff0ab7eb5b0c45768acedabb3cd70ca05/ucc/ucl/transtmt.c

3、打印生成的中间代码

uildasm.c

https://github.com/sheisc/ucc162.3/blob/a92719fff0ab7eb5b0c45768acedabb3cd70ca05/ucc/ucl/uildasm.c

4、中间代码格式

opcode.h

#ifndef OPCODE
#error "You must define OPCODE macro before include this file"
#endif
/**opcode here is used by UIL*/
OPCODE(BOR,     "|",                    Assign)
OPCODE(BXOR,    "^",                    Assign)
OPCODE(BAND,    "&",                    Assign)
OPCODE(LSH,     "<<",                   Assign)
OPCODE(RSH,     ">>",                   Assign)
OPCODE(ADD,     "+",                    Assign)
OPCODE(SUB,     "-",                    Assign)
OPCODE(MUL,     "*",                    Assign)
OPCODE(DIV,     "/",                    Assign)
OPCODE(MOD,     "%",                    Assign)
OPCODE(NEG,     "-",                    Assign)
OPCODE(BCOM,    "~",                    Assign)
OPCODE(JZ,      "",                     Branch)
OPCODE(JNZ,     "!",                    Branch)
OPCODE(JE,      "==",                   Branch)
OPCODE(JNE,     "!=",                   Branch)
OPCODE(JG,      ">",                    Branch)
OPCODE(JL,      "<",                    Branch)
OPCODE(JGE,     ">=",                   Branch)
OPCODE(JLE,     "<=",                   Branch)
OPCODE(JMP,     "jmp",                  Jump)
OPCODE(IJMP,    "ijmp",                 IndirectJump)
OPCODE(INC,     "++",                   Inc)
OPCODE(DEC,     "--",                   Dec)
OPCODE(ADDR,    "&",                    Address)
OPCODE(DEREF,   "*",                    Deref)
OPCODE(EXTI1,   "(int)(char)",          Cast)
OPCODE(EXTU1,   "(int)(unsigned char)", Cast)
OPCODE(EXTI2,   "(int)(short)",         Cast)
OPCODE(EXTU2,   "(int)(unsigned short)",Cast)
OPCODE(TRUI1,   "(char)(int)",          Cast)
OPCODE(TRUI2,   "(short)(int)",         Cast)
OPCODE(CVTI4F4, "(float)(int)",         Cast)
OPCODE(CVTI4F8, "(double)(int)",        Cast)
OPCODE(CVTU4F4, "(float)(unsigned)",    Cast)
OPCODE(CVTU4F8, "(double)(unsigned)",   Cast)
OPCODE(CVTF4,   "(double)(float)",      Cast)
OPCODE(CVTF4I4, "(int)(float)",         Cast)
OPCODE(CVTF4U4, "(unsigned)(float)",    Cast)
OPCODE(CVTF8,   "(float)(double)",      Cast)
OPCODE(CVTF8I4, "(int)(double)",        Cast)
OPCODE(CVTF8U4, "(unsigned)(double)",   Cast)
OPCODE(MOV,     "=",                    Move)
OPCODE(IMOV,    "*=",                   IndirectMove)
OPCODE(CALL,    "call",                 Call)
OPCODE(RET,     "ret",                  Return)
OPCODE(CLR,     "",                     Clear)
OPCODE(NOP,     "NOP",                  NOP)

对应结构体,

/**
//Intermediate Representation Instruction
see uildasm.c
#define DST  inst->opds[0]
#define SRC1 inst->opds[1]
#define SRC2 inst->opds[2]prev:  pointer to previous instructionnext:    pointer to next instructionty:      instruction operating typeopcode:   operation codeopds: operands, at most three*/
typedef struct irinst
{struct irinst *prev;struct irinst *next;Type ty;int opcode;Symbol opds[3];
} *IRInst;

5、gen.c

这是文件是中间代码生成最基础的一个文件,中间代码需要处理的很多基础工作都是在这里完成的。比如创建临时变量、创建跳转、创建返回值、创建函数调用等等。

6、不失一般性,我们以statment的翻译作为举例说明,

6.1 入口函数

static void TranslateStatement(AstStatement stmt)
{(* StmtTrans[stmt->kind - NK_ExpressionStatement])(stmt);
}

6.2 if-statement翻译

/*** This function translates an if statement.** if (expr) stmt is translated into:*     if ! expr goto nextBB* trueBB:*     stmt* nextBB:*     ...     ** if (expr) stmt1 else stmt2 is translated into:*     if ! expr goto falseBB* trueBB:*     stmt1*     goto nextBB* falseBB:*     stmt2* nextBB:*     ...*/
static void TranslateIfStatement(AstStatement stmt)
{AstIfStatement ifStmt = AsIf(stmt);BBlock nextBB;BBlock trueBB;BBlock falseBB;nextBB = CreateBBlock();trueBB = CreateBBlock();if (ifStmt->elseStmt == NULL){TranslateBranch(Not(ifStmt->expr), nextBB, trueBB);StartBBlock(trueBB);TranslateStatement(ifStmt->thenStmt);}else{falseBB = CreateBBlock();TranslateBranch(Not(ifStmt->expr), falseBB, trueBB);StartBBlock(trueBB);TranslateStatement(ifStmt->thenStmt);GenerateJump(nextBB);StartBBlock(falseBB);TranslateStatement(ifStmt->elseStmt);}StartBBlock(nextBB);
}

6.3 while-statement翻译

/*** This function translates a while statement.** while (expr) stmt is translated into:* goto contBB* loopBB:*     stmt* contBB:*     if (expr) goto loopBB* nextBB:*     ...*/
static void TranslateWhileStatement(AstStatement stmt)
{AstLoopStatement whileStmt = AsLoop(stmt);whileStmt->loopBB = CreateBBlock();whileStmt->contBB = CreateBBlock();whileStmt->nextBB = CreateBBlock();GenerateJump(whileStmt->contBB);StartBBlock(whileStmt->loopBB);TranslateStatement(whileStmt->stmt);StartBBlock(whileStmt->contBB);TranslateBranch(whileStmt->expr, whileStmt->loopBB, whileStmt->nextBB);StartBBlock(whileStmt->nextBB);
}

6.4 break-statement翻译

/*** This function translates a break statement.* A break statement terminates the execution of associated* switch or loop.** break is translated into:*     goto switch or loop's nextBB* nextBB:*     ...*/
static void TranslateBreakStatement(AstStatement stmt)
{AstBreakStatement brkStmt = AsBreak(stmt);if (brkStmt->target->kind == NK_SwitchStatement){GenerateJump(AsSwitch(brkStmt->target)->nextBB);}else{GenerateJump(AsLoop(brkStmt->target)->nextBB);}StartBBlock(CreateBBlock());
}

6.6 return-statement翻译

/*** Translates a return statement.* A return statement terminates execution of current function.*/
static void TranslateReturnStatement(AstStatement stmt)
{AstReturnStatement retStmt = AsRet(stmt);if (retStmt->expr){GenerateReturn(retStmt->expr->ty, TranslateExpression(retStmt->expr));}GenerateJump(FSYM->exitBB);StartBBlock(CreateBBlock());
}

6.7 switch-statment翻译

switch-statement翻译几乎是statement翻译里面最复杂的一部分。整个处理过程由TranslateSwitchStatement、TranslateSwitchBuckets、MergeSwitchBucket这三个部分组成。

TranslateSwitchStatement是总的入口,TranslateSwitchBuckets负责排序,MergeSwitchBucket负责每个case前后的拼接,这部分可以专门写一篇文章介绍下。

6.8 和expression的对接

/*** This function translates an expression statement*/
static void TranslateExpressionStatement(AstStatement stmt)
{AstExpressionStatement exprStmt = AsExpr(stmt);if (exprStmt->expr != NULL){TranslateExpression(exprStmt->expr);}
}

6.9 可开可关的优化

{// do some optimizations for every basic block, only at the IR level, not ASM level.#if 1Optimize(FSYM);#endif}

6.10 总结

中间代码的生成其实有很多的套路。比如说if语言、for语言、while语言、do{}while()语言翻译,这些都是套路。如果同学们有兴趣实现一套自己的语言,这部分完全可以直接拿过来使用。

另外一个需要重点掌握的,就是opcode.h。这部分和汇编语言基本是一一对应的。中间语言生成对应的汇编指令,本质上寻找合适的寄存器、查表获取对应的汇编指令,这样其实就可以完成汇编代码生成了。

ucc编译器(中间代码生成)相关推荐

  1. ucc编译器(优化)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 编译器优化几乎是现代编译器最重要的工作.一般编译器的优化有这么几层,a,中间代码生成前的优化,比 ...

  2. ucc编译器(入门)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 要说开源编译器,一般大家想到的都是gcc.但是现在gcc的代码量太大了,不太适合学习.代码量比较 ...

  3. 编译器设计-代码生成

    编译器设计-代码生成 Compiler Design - Code Generation 代码生成可以看作是编译的最后阶段.通过后代码生成,优化过程可以应用到代码上,但这可以看作是代码生成阶段本身的一 ...

  4. ucc编译器(语法解析)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 做完词法分析,后面紧接着就是语法分析.对于一个编程语言而言,语法解析才是语言和语言之间最大的区别 ...

  5. ucc编译器(词法分析)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 学过编译器的同学都知道,词法分析是编译器里面最基础的一条.之前,在学校读书的时候,老师也会告诉我 ...

  6. ucc编译器(x86移植)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 之前写过一篇ucc的文章,也就是这一篇.这篇文章对ucc的流程说了挺多,但是怎么把ucc移植到新 ...

  7. 自己动手写编译器:中间代码生成1

    我们到了简单编译器开发的最后一个阶段,也就是生成中间代码.以前我们提到过编译器分为两部分,分别为前端和后端,所谓前端就是将代码转译成中间语言,后端负责进行优化和转译成目标平台的机器指令,现在我们来到了 ...

  8. ucc编译器(语义分析)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 符合语法的代码,不一定符合语义.这句话听上去很拗口,我们不妨举个例子,假设我们定义了一个变量in ...

  9. C编译器剖析_5.3.2 中间代码生成及优化_switch语句的翻译

    5.3.2.Switch语句的翻译 在这一小节中,我们来讨论一下switch语句的翻译,switch语句的产生式如下所示. SwitchStatement: switch( expr ) statem ...

最新文章

  1. 定时从linux获取文件,Linux 使用scp命令定时将文件备份到另一台服务器
  2. 修改Chrome的UserAgent
  3. C语言 | 用51单片机实现公历与农历星期的转换(完整源代码)
  4. *【ZOJ - 3781】Paint the Grid Reloaded(dfs求连通块缩点,bfs求最短路,建图技巧)
  5. mysql数据库后台命令备份_使用MySQL命令行备份及恢复数据库
  6. 计算机教室要配备空调吗,教室里不安装空调吗?如何正确安装空调?
  7. Python深度学习基于PyTorch (附完整PPT下载)
  8. 自动量程万用表的实现原理_万用表的工作原理是怎样的?看完终于懂了
  9. AntDesign Upload组件上传图片
  10. 你对软件测试了解多少?这篇文章会给你不一样的启示!
  11. WINCE 矩阵键盘 介绍
  12. 今日早报 每天一分钟知晓天下事 3-13
  13. 国产Linux系统UOS安装
  14. mysql 空间数据操作,MySQL 空间数据 简单操作
  15. 数据分析从0到1之AARRR模型 - Blog2
  16. scratch(图形化编程工具)使用漩涡和马赛克特效做一个酷酷的背景动画
  17. 他山之石、可以攻玉 - 我的2015年总结
  18. C语言程序设计--订餐系统
  19. B站用户视频观看记录的存储方案
  20. 利用ASP显示当前在线人数

热门文章

  1. 什么是面向对象,为什么要面向对象
  2. topcoder srm 708 div1 -3
  3. Linux网络服务之DNS(2)
  4. 几个交换问题的咨询?
  5. 2019年春第四次课程设计实验报告
  6. C#/VB.NET与西门子PLC进行ModbusTcp通信
  7. Mail.Ru Cup 2018 Round 1 virtual participate记
  8. 结构型模式-装饰模式(扩展系统功能)
  9. 如何用 JavaScript 下载文件
  10. Eclipse build launcher 3具体步骤