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

有了中间代码,后面生成汇编就好办了。需要支持什么cpu,就将中间代码生成对应的汇编代码就好了。这部分的工作不复杂,但是比较琐碎。

1、函数入口

void EmitTranslationUnit(AstTranslationUnit transUnit)

2、涉及到的文件

emit.c,主要是告诉我们怎么生成一个gcc认识的汇编文件

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

x86.c,真正用来生成汇编指令

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

3、emit.c分析

3.1 EmitTranslationUnit会调用各个接口,创建一个合适的s文件

/*** Emit  assembly code for the translation unit*/
void EmitTranslationUnit(AstTranslationUnit transUnit)
{if(ASMFileName){ASMFile = fopen(ASMFileName, "w");ASMFileName = NULL;}else{ASMFile = CreateOutput(Input.filename, ExtName);}SwitchTableNum = 1;// "# Code auto-generated by UCC\n\n"BeginProgram();// ".data\n\n"Segment(DATA);/**.str0: .string "%d \012".str1:   .string "a + b + c + d = %d.\012"*/EmitStrings();EmitFloatConstants();EmitGlobals();// ".text\n\n"Segment(CODE);ImportFunctions();/**The key function is void EmitFunction(FunctionSymbol fsym)in x86.c*/EmitFunctions(transUnit);EndProgram();fclose(ASMFile);
}

这个函数里面,Segement、Strings、FloatConstants、Globals、ImportFuncions这些都是为了创建汇编文件的格式基础,为后续的EmitFunctions做铺垫。在这些函数中调用的子函数,部分内容需要具体的cpu来实现,比如Segment这种函数。

3.2 emit.c和x86.c最重要的连接EmitFunction

/*** Emit all the functions*/
static void EmitFunctions(AstTranslationUnit transUnit)
{AstNode p;FunctionSymbol fsym;p = transUnit->extDecls;while (p != NULL){if (p->kind == NK_Function){fsym = ((AstFunction)p)->fsym;if (fsym->sclass != TK_STATIC || fsym->ref > 0){EmitFunction(fsym);}}p = p->next;}
}

4、x86.c分析

4.1 EmitFunction->EmitBBlock->EmitIRInst,这是最重要的翻译流程

static void EmitIRInst(IRInst inst)
{struct irinst instc = *inst;(* Emitter[inst->opcode])(&instc);return;
}

4.2 opcode.h一对一翻译

/**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)*/
static void (* Emitter[])(IRInst inst) =
{
#define OPCODE(code, name, func) Emit##func,
#include "opcode.h"
#undef OPCODE
};

4.3 最简单的翻译,Jump跳转

/**(1)   the target of Jump is a BBlock, not Variable.So no DST->ref -- here.(2)  X87 top is saved in EmitBlock(),because Jump must be the last IL in a basic block.*/
static void EmitJump(IRInst inst)
{BBlock p = (BBlock)DST;DST = p->sym;assert(DST->kind == SK_Label);ClearRegs();PutASMCode(X86_JMP, inst->opds);
}

4.4 另外一个最简单的翻译,获取地址

static void EmitAddress(IRInst inst)
{assert(DST->kind == SK_Temp && SRC1->kind != SK_Temp);AllocateReg(inst, 0);PutASMCode(X86_ADDR, inst->opds);ModifyVar(DST);
}

4.5 中间语言和汇编语言之间的映射

enum ASMCode
{
#define TEMPLATE(code, str) code,
#include "x86win32.tpl"
#undef TEMPLATE
};static const char * asmCodeName[] = {
#define TEMPLATE(code, str) #code,
#include "x86win32.tpl"
#undef TEMPLATE
};

4.6 tpl内容,比如x86linux.tpl

#ifndef TEMPLATE
#error "You must define TEMPLATE macro before include this file"
#endifTEMPLATE(X86_BORI4,     "orl %2, %0")
TEMPLATE(X86_BORU4,     "orl %2, %0")
TEMPLATE(X86_BORF4,     NULL)
TEMPLATE(X86_BORF8,     NULL)TEMPLATE(X86_BXORI4,    "xorl %2, %0")
TEMPLATE(X86_BXORU4,    "xorl %2, %0")
TEMPLATE(X86_BXORF4,    NULL)
TEMPLATE(X86_BXORF8,    NULL)TEMPLATE(X86_BANDI4,    "andl %2, %0")
TEMPLATE(X86_BANDU4,    "andl %2, %0")
TEMPLATE(X86_BANDF4,    NULL)
TEMPLATE(X86_BANDF8,    NULL)TEMPLATE(X86_LSHI4,    "shll %2, %0")
TEMPLATE(X86_LSHU4,    "shll %2, %0")
TEMPLATE(X86_LSHF4,    NULL)
TEMPLATE(X86_LSHF8,    NULL)TEMPLATE(X86_RSHI4,    "sarl %2, %0")
TEMPLATE(X86_RSHU4,    "shrl %2, %0")
TEMPLATE(X86_RSHF4,    NULL)
TEMPLATE(X86_RSHF8,    NULL)TEMPLATE(X86_ADDI4,    "addl %2, %0")
TEMPLATE(X86_ADDU4,    "addl %2, %0")
TEMPLATE(X86_ADDF4,    "fadds %2")
TEMPLATE(X86_ADDF8,    "faddl %2")TEMPLATE(X86_SUBI4,    "subl %2, %0")
TEMPLATE(X86_SUBU4,    "subl %2, %0")
TEMPLATE(X86_SUBF4,    "fsubs %2")
TEMPLATE(X86_SUBF8,    "fsubl %2")TEMPLATE(X86_MULI4,    "imull %2, %0")
TEMPLATE(X86_MULU4,    "mull %2")
TEMPLATE(X86_MULF4,    "fmuls %2")
TEMPLATE(X86_MULF8,    "fmull %2")TEMPLATE(X86_DIVI4,    "cdq;idivl %2")
TEMPLATE(X86_DIVU4,    "movl $0, %%edx;divl %2")
TEMPLATE(X86_DIVF4,    "fdivs %2")
TEMPLATE(X86_DIVF8,    "fdivl %2")TEMPLATE(X86_MODI4,    "cdq;idivl %2")
TEMPLATE(X86_MODU4,    "movl $0, %%edx; divl %2")
TEMPLATE(X86_MODF4,    NULL)
TEMPLATE(X86_MODF8,    NULL)TEMPLATE(X86_NEGI4,    "negl %0")
TEMPLATE(X86_NEGU4,    "negl %0")
TEMPLATE(X86_NEGF4,    "fchs")
TEMPLATE(X86_NEGF8,    "fchs")TEMPLATE(X86_COMPI4,   "notl %0")
TEMPLATE(X86_COMPU4,   "notl %0")
TEMPLATE(X86_COMPF4,   NULL)
TEMPLATE(X86_COMPF8,   NULL)TEMPLATE(X86_JZI4,     "cmpl $0, %1;je %0")
TEMPLATE(X86_JZU4,     "cmpl $0, %1;je %0")
TEMPLATE(X86_JZF4,     "fldz;fucompp;fnstsw %%ax;test $0x44, %%ah;jnp %0")
TEMPLATE(X86_JZF8,     "fldz;fucompp;fnstsw %%ax;test $0x44, %%ah;jnp %0")TEMPLATE(X86_JNZI4,    "cmpl $0, %1;jne %0")
TEMPLATE(X86_JNZU4,    "cmpl $0, %1;jne %0")
TEMPLATE(X86_JNZF4,    "fldz;fucompp;fnstsw %%ax;test $0x44, %%ah;jp %0")
TEMPLATE(X86_JNZF8,    "fldz;fucompp;fnstsw %%ax;test $0x44, %%ah;jp %0")TEMPLATE(X86_JEI4,     "cmpl %2, %1;je %0")
TEMPLATE(X86_JEU4,     "cmpl %2, %1;je %0")
TEMPLATE(X86_JEF4,     "flds %2;fucompp;fnstsw %%ax;test $0x44, %%ah;jnp %0")
TEMPLATE(X86_JEF8,     "fldl %2;fucompp;fnstsw %%ax;test $0x44, %%ah;jnp %0")TEMPLATE(X86_JNEI4,    "cmpl %2, %1;jne %0")
TEMPLATE(X86_JNEU4,    "cmpl %2, %1;jne %0")
TEMPLATE(X86_JNEF4,    "flds %2;fucompp;fnstsw %%ax;test $0x44, %%ah;jp %0")
TEMPLATE(X86_JNEF8,    "fldl %2;fucompp;fnstsw %%ax;test $0x44, %%ah;jp %0")TEMPLATE(X86_JGI4,     "cmpl %2, %1;jg %0")
TEMPLATE(X86_JGU4,     "cmpl %2, %1;ja %0")
TEMPLATE(X86_JGF4,     "flds %2;fucompp;fnstsw %%ax;test $0x1, %%ah;jne %0")
TEMPLATE(X86_JGF8,     "fldl %2;fucompp;fnstsw %%ax;test $0x1, %%ah;jne %0")TEMPLATE(X86_JLI4,     "cmpl %2, %1;jl %0")
TEMPLATE(X86_JLU4,     "cmpl %2, %1;jb %0")
TEMPLATE(X86_JLF4,     "flds %2;fucompp;fnstsw %%ax;test $0x41, %%ah;jp %0")
TEMPLATE(X86_JLF8,     "fldl %2;fucompp;fnstsw %%ax;test $0x41, %%ah;jp %0")TEMPLATE(X86_JGEI4,    "cmpl %2, %1;jge %0")
TEMPLATE(X86_JGEU4,    "cmpl %2, %1;jae %0")
TEMPLATE(X86_JGEF4,    "flds %2;fucompp;fnstsw %%ax;test $0x41, %%ah;jne %0")
TEMPLATE(X86_JGEF8,    "fldl %2;fucompp;fnstsw %%ax;test $0x41, %%ah;jne %0")TEMPLATE(X86_JLEI4,    "cmpl %2, %1;jle %0")
TEMPLATE(X86_JLEU4,    "cmpl %2, %1;jbe %0")
TEMPLATE(X86_JLEF4,    "flds %2;fucompp;fnstsw %%ax;test $0x5, %%ah;jp %0")
TEMPLATE(X86_JLEF8,    "fldl %2;fucompp;fnstsw %%ax;test $0x5, %%ah;jp %0")TEMPLATE(X86_EXTI1,    "movsbl %1, %0")
TEMPLATE(X86_EXTU1,    "movzbl %1, %0")
TEMPLATE(X86_EXTI2,    "movswl %1, %0")
TEMPLATE(X86_EXTU2,    "movzwl %1, %0")
TEMPLATE(X86_TRUI1,    "movb %%al, %0")
TEMPLATE(X86_TRUI2,    "movb %%al, %0")TEMPLATE(X86_CVTI4F4,  "pushl %1;fildl (%%esp);fstps %0;addl $4, %%esp")
TEMPLATE(X86_CVTI4F8,  "pushl %1;fildl (%%esp);fstpl %0;addl $4, %%esp")
TEMPLATE(X86_CVTU4F4,  "pushl $0;pushl %1;fildq (%%esp);fstps %0;addl $8, %%esp")
TEMPLATE(X86_CVTU4F8,  "pushl $0;pushl %1;fildq (%%esp);fstpl %0;addl $8, %%esp")TEMPLATE(X86_CVTF4,    "flds %1;fstpl %0") TEMPLATE(X86_CVTF4I4,  "flds %1;subl $16, %%esp;fnstcw (%%esp);movzwl (%%esp), %%eax;""orl $0x0c00, %%eax;movl %%eax, 4(%%esp);fldcw 4(%%esp);fistpl 8(%%esp);""fldcw (%%esp);movl 8(%%esp), %%eax;addl $16, %%esp")TEMPLATE(X86_CVTF4U4,  "flds %1;subl $16, %%esp;fnstcw (%%esp);movzwl (%%esp), %%eax;""orl $0x0c00, %%eax;movl %%eax, 4(%%esp);fldcw 4(%%esp);fistpll 8(%%esp);""fldcw (%%esp);movl 8(%%esp), %%eax;addl $16, %%esp")
TEMPLATE(X86_CVTF8,    "fldl %1;fstps %0")TEMPLATE(X86_CVTF8I4,  "fldl %1;subl $16, %%esp;fnstcw (%%esp);movzwl (%%esp), %%eax;""orl $0x0c00, %%eax;movl %%eax, 4(%%esp);fldcw 4(%%esp);fistpl 8(%%esp);""fldcw (%%esp);movl 8(%%esp), %%eax; addl $16, %%esp")TEMPLATE(X86_CVTF8U4,  "fldl %1;subl $16, %%esp;fnstcw (%%esp);movzwl (%%esp), %%eax;""orl $0x0c00, %%eax;movl %%eax, 4(%%esp);fldcw 4(%%esp);fistpll 8(%%esp);""fldcw (%%esp);movl 8(%%esp), %%eax;addl $16, %%esp")TEMPLATE(X86_INCI1,    "incb %0")
TEMPLATE(X86_INCU1,    "incb %0")
TEMPLATE(X86_INCI2,    "incw %0")
TEMPLATE(X86_INCU2,    "incw %0")
TEMPLATE(X86_INCI4,    "incl %0")
TEMPLATE(X86_INCU4,    "incl %0")
TEMPLATE(X86_INCF4,    "fld1;fadds %0;fstps %0")TEMPLATE(X86_INCF8,    "fld1;faddl %0;fstpl %0")TEMPLATE(X86_DECI1,    "decb %0")
TEMPLATE(X86_DECU1,    "decb %0")
TEMPLATE(X86_DECI2,    "decw %0")
TEMPLATE(X86_DECU2,    "decw %0")
TEMPLATE(X86_DECI4,    "decl %0")
TEMPLATE(X86_DECU4,    "decl %0")TEMPLATE(X86_DECF4,    "fld1;fsubs %0;fchs;fstps %0")
TEMPLATE(X86_DECF8,    "fld1;fsubl %0;fchs;fstpl %0")TEMPLATE(X86_ADDR,     "leal %1, %0")TEMPLATE(X86_MOVI1,    "movb %1, %0")
TEMPLATE(X86_MOVI2,    "movw %1, %0")
TEMPLATE(X86_MOVI4,    "movl %1, %0")
TEMPLATE(X86_MOVB,     "leal %0, %%edi;leal %1, %%esi;movl %2, %%ecx;rep movsb")TEMPLATE(X86_JMP,      "jmp %0")
TEMPLATE(X86_IJMP,     "jmp *%0(,%1,4)")TEMPLATE(X86_PROLOGUE, "pushl %%ebp;pushl %%ebx;pushl %%esi;pushl %%edi;movl %%esp, %%ebp")
TEMPLATE(X86_PUSH,     "pushl %0")
TEMPLATE(X86_PUSHF4,   "pushl %%ecx;flds %0;fstps (%%esp)")
TEMPLATE(X86_PUSHF8,   "subl $8, %%esp;fldl %0;fstpl (%%esp)")
TEMPLATE(X86_PUSHB,    "leal %0, %%esi;subl %2, %%esp;movl %%esp, %%edi;movl %1, %%ecx;rep movsb")
TEMPLATE(X86_EXPANDF,  "subl %0, %%esp")
TEMPLATE(X86_CALL,     "call %1")
TEMPLATE(X86_ICALL,    "call *%1")
TEMPLATE(X86_REDUCEF,  "addl %0, %%esp")
TEMPLATE(X86_EPILOGUE, "movl %%ebp, %%esp;popl %%edi;popl %%esi;popl %%ebx;popl %%ebp;ret")TEMPLATE(X86_CLEAR,    "pushl %1;pushl $0;leal %0, %%eax;pushl %%eax;call memset;addl $12, %%esp")TEMPLATE(X86_LDF4,     "flds %0")
TEMPLATE(X86_LDF8,     "fldl %0")
TEMPLATE(X86_STF4,     "fstps %0")
TEMPLATE(X86_STF8,     "fstpl %0")TEMPLATE(X86_STF4_NO_POP,     "fsts %0")
TEMPLATE(X86_STF8_NO_POP,     "fstl %0")TEMPLATE(X86_X87_POP,     "fstp %%st(0)")

4.7 汇编语言的打印

目前主要是PutASMCode实现,

这个函数在x86linux.c & x86win32.c都进行了实现

这就看自己需要实现哪一种os下的汇编代码了

4.8 函数翻译过程中涉及到其他问题

Export,函数输出

LayoutFrame & EmitPrologue,堆栈处理

EmitEpilogue,堆栈复原

4.9 寄存器的处理

reg.c

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

4.10 总结

相对而言,后端移植涉及到很多文件,比如emit.c、x86.c、reg.c、x86win32.c、x86linux.c,还涉及到opinfo.h、x86linux.tpl、x86win32.tpl,作为阅读代码同学,要了解每一个文件的作用,至少需要知道里面的处理流程。评价自己是否真正理解了这个理解,就看自己是不是可以把ucc移植到另外一个cpu架构上了,这是最好的判别方法。

ucc编译器(汇编生成)相关推荐

  1. 编译hotspot_从Hotspot JIT编译器打印生成的汇编代码

    编译hotspot 有时,在对Java应用程序进行性能分析时,有必要了解Hotspot JIT编译器生成的汇编代码. 这对于确定已做出的优化决策以及我们的代码更改如何影响生成的汇编代码非常有用. 在调 ...

  2. ucc编译器(优化)

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

  3. ucc编译器(入门)

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

  4. Effective C++ 之 Item 6 : 若不想使用编译器自动生成的函数,就该明确拒绝

    Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 6 ...

  5. C++若不想使用编译器自动生成的函数,就该明确拒绝

    C++若不想使用编译器自动生成的函数,就该明确拒绝 为什么要拒绝? 将copy构造函数或copy assignment操作符声明为private,并且不定义 使用delete(C++11 ) 为什么要 ...

  6. 条款6:若不想使用编译器自动生成的函数,就该明确拒绝

    如果自己定义的类中并不需要copy assignment操作符或者copy构造函数,为了避免编译器自动生成 因为编译器自动生成的没什么用,一般是按照顺序进行赋值或者拷贝,对于有对象内含有指针的话可能会 ...

  7. keil编译器如何生成二进制bin文件

    keil编译器默认生成的是16进制的hex文件,但是有时候需要生成二进制的bin文件,可以使用kei自带的二进制转换工具来实现. 首先在keil安装目录中找到 ARMCC文件夹,然后打开里面bin文件 ...

  8. 红白机 编译6502汇编生成NES文件的通用Makefile

    6502汇编生成NES的通用Makefile #依赖sudo apt install cc65 #DIR_INC = ./include DIR_SRC = . DIR_OBJ = . DIR_BIN ...

  9. 从Hotspot JIT编译器打印生成的汇编代码

    有时,在对Java应用程序进行性能分析时,有必要了解Hotspot JIT编译器生成的汇编代码. 这对于确定已做出的优化决策以及我们的代码更改如何影响生成的汇编代码非常有用. 在调试并行算法以确保已按 ...

  10. ucc编译器(x86移植)

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

最新文章

  1. Eclipse 创建 Java 项目概述
  2. java 取数组的前90位,LeetCode 面试题21. 调整数组顺序使奇数位于偶数前面
  3. can t connect to mysql server on ‘localhost‘解决方法
  4. Ubuntu下千千静听Audacious的安装步骤详解
  5. 使用Recast.AI创建具有人工智能的聊天机器人
  6. Python locals 函数 - Python零基础入门教程
  7. POJ 1252 Euro Efficiency
  8. 利用计算机发布调度命令时必须严格遵守,调度命令规范格式(22页)-原创力文档...
  9. idea卸载不干净怎么办_卸载删除面具(Magisk)后,手机不开机怎么办
  10. 用 Python 分析某医院药品销售案例!
  11. 计算机网络管理员试题实操,网络管理员试题(实操).doc
  12. 微博奥运营销策略复盘,探索双十一微博品牌营销新手法!!
  13. 在python中,计算Sum = m + mm + mmm +mmmm+.....+mmmmm.....,输入两个数m,n。m的位数累加到n的值,列出算式并计算出结果:
  14. python zip压缩文件
  15. Hybrid Trajectory Planning for Autonomous Driving in On-Road Dynamic Scenarios文章解读
  16. Git-版本控制-创建远程仓库
  17. 自动升降压PD快充方案 30W快充TYPE-C方案
  18. Java练习案例之输入一个字符串统计每个字母出现次数
  19. sourcegraph/conc: Better structured concurrency for go
  20. 全国计算机二级上机模拟考试,全国计算机二级上机模拟考试习题集(01-50)解答..doc...

热门文章

  1. Vue 中使用 codemirror
  2. 有密码的压缩包怎么解密
  3. 验证离散数学中的关系的相关性质(自反性,对称性,反自反性,发对称性,传递性)通过关系矩阵的方法
  4. 桥本木分式(使用回溯法求解)
  5. 【11-13】A股主要指数的市盈率(PE)估值高度
  6. 计算机无法连接网络打印机,电脑无法连接网络打印机。怎么办?
  7. 2017网易校招:Fibonacci数列
  8. android微信图片编辑带滤镜,美图APP的小程序版 微信里一键P图自动加滤镜贴图和文字模版...
  9. Windows下PuTTY远程连接Linux服务器并上传文件/更改默认端口号
  10. 物联网毕业设计 单片机指纹识别考勤系统设计与实现