编译实验(三)目标代码生成

2023-10-30

通过词法分析,语法分析,语义分析,最后产生了四元式。而代码生成则是通过四元式来完成。我们先从简单开始做起。

编译实验项目下载链接:http://download.csdn.net/download/supersmart_dong/10224159

例如四元式(j,0,0,7)这样的,代码生成只需要一个goto语句;(j=,A,B,7)代码生成为:

CMP A,B

JE .....     

目标代码如果是汇编语言的话,则代码生成对汇编要有一定了解。

指令码

意义

条件

JZ, JE

结果为0或相等则转

Z=1(A) = (B)

JNZ, JNE

结果不为0或不相等则转

Z=0(A)(B)

JNL, JGE

大于等于转

(SO)=0(A)(B)

JL, JNGE

小于转

(SO)=1(A)<(B)

JG, JNLE

大于转

(SOZ)=0(A)>(B)

JMP

无条件转移


CMP 为比较,实际上是两个变量相减只影响标志位。

所以当(J<,A,B,7)这样的只需要一个比较语句和一个跳转语句就行。跳转到哪?当然是跳转到对应四元式所对应的代码了,我们需要引进基本块的概念,块也就是一堆顺序执行的语句序列。首先要就四元式进行划分基本块。

(1)程序第一个四元式为基本块入口

(2)跳转四元式的下一个四元式为基本块入口

(3)跳转语句要跳转到的四元式,该四元式为基本块入口

最后,相邻两个基本块入口之间的四元式构成一个基本块(其中包含前者入口,不包含后者入口)。跳转语句的跳转位置也就是基本块的名字。

首先第一步,设置基本块路口,我们四元式需要一个属性来标记是否为某基本块入口(0为否,1为是),按照上面的三步骤,遍历四元式判断是不是第一个四元式,是不是跳转语句的四元式,是的话相应四元式属性置为1就可以。

第二步就是初始化基本块集合。遍历四元式将四元式加入基本块,直到下一个入口四元式为止,再把基本块加到集合中。

做完这些,所有跳转语句就可以完成了,跳转目的地也就是四元式对应的基本块名称。


接下来完成加减乘除的四元式代码生成。假如有ax,bx,dx寄存器可用

像(+,A,B,T1) (:=,T1,0,A)对应汇编代码应该是:

MOV  AX,A

ADD   AX,B

MOV  C,AX 

假如B的值存在了bx寄存器中:

MOV  AX,A

ADD   AX,BX

MOV  C,AX 

首先定义寄存器的数据结构,起码要有name(寄存器名称),Rvalue(寄存器存放的值),例如上面的代码,AX寄存器最后存放了T1和C的值。

struct registers
{
	string	name;
	vector<string> Rvalue;
	registers(string n){ name = n; }
	registers(){};
	void clearPush(string n)
	{
		Rvalue.clear();
		Rvalue.push_back(n);
	}
	bool isinReg(string n)
	{
		bool flag = false;
		for (int i = 0; i < Rvalue.size(); i++)
		{
			if (Rvalue[i] == n)
				flag = true;
		}
		return flag;
	}
};
vector<registers> regs = { registers("AX"), registers("BX"), registers("DX") };
registers M("M");
registers findreg(string arg,int &index)
{
	//如果找到原本有的
	for (int i = 0; i < regs.size(); i++)
	{
		if (regs[i].isinReg(arg))
		{
			index = i;
			return regs[i];
		}
	}
	//没有则返回空寄存器
	for (int i = 0; i < regs.size(); i++)
	{
		if (regs[i].Rvalue.size()==0)
		{
			index = i;
			return regs[i];
		}
	}

	return NULL;
}
bool isExistRvalue(string arg)
{
	for (int i = 0; i < regs.size(); i++)
	{		
			if (regs[i].isinReg(arg))
				return true;		
	}
	return false;
}

在进行加减乘除的代码生成的时候,首先遍历所有寄存器的Rvalue查询是否存在Rvalue中,是的话返回对应寄存器。

例如进行计算A+B时,对应四元式 (+,A,B,T),如果A和B分别在ax,bx寄存器中,对应代码:

ADD ax,bx

如果A在寄存器ax中b不在寄存器,则:

ADD ax,B

如果A在不在寄存器b在寄存器bx,则:

ADD bx,A

A和B都不在寄存器中时,返回空寄存器(假如是AX):

mov  ax,A

add ax ,B

目标代码生成参考代码:

#include <string>
#include <vector>
#include "register.h"
//定义基本块的数据结构,定义代码表的基本结构,找到四元式的入口,划分基本块,遍历基本块进行代码生成(首先完成根据四元式地址找到基本块,完成操作符代码表),精化代码表用到寄存器分配
static int nameNum;
struct basicBlock
{
	string name;
	vector<GenStruct> gens;	
	vector <string> codes;
	basicBlock()
	{
		string str;
		int2str(nameNum,str);
		name = "L" + str;
		nameNum++;
	}
	void add(GenStruct g)
	{
		gens.push_back(g);
	}
};
class codeTable
{
private:
	vector<basicBlock> block; //基本块
	void initblock();  //初始化基本块
	int findblocknameByGen(int index);  //根据四元式地址找到基本块
	string findblocknameByGen(string index){
		int i = stoi(index);
		i=findblocknameByGen(i);
		if (i >= block.size()) return "End";
		return block[i].name;		
	}
	vector<string> createcode(GenStruct);
	void initblockcodes();
	bool stringisinGen(string,int);  //判断string 是否在index后四元式中存在
public:	
	vector<basicBlock> getBasicBlock(){ return block; }
	codeTable(){ initblock(); initblockcodes(); }
	void clearNotUse(GenStruct);
	void printcodes();
};
void codeTable::initblock()
{
	for (int i = 0; i < genStructs.size()-1; i++)
	{
		if (i == 0) {   //程序第一条为入口
			changeOut_port(0); 
		}
		if (genStructs[i].code <= 58 && genStructs[i].code >= 52) //跳转语句
		{
			changeOut_port(genStructs[i].result);//跳转到的语句为入口语句
			changeOut_port(i+1); //跳转语句的下一行,为入口语句
		}
	}
	for (int i = 0; i < genStructs.size() ; ) //把入口语句加入到基本块
	{
		basicBlock bl;
		bl.add(genStructs[i]);
		i++;
		for (; i < genStructs.size(); i++)
		{
			if (genStructs[i].out_port == 1)
			{
				block.push_back(bl);
				break;
			}
			else 
				bl.add(genStructs[i]);
		}
		if (i==genStructs.size())
			block.push_back(bl);
	}
}
int codeTable::findblocknameByGen(int index)
{
	for (int i = 0; i < block.size(); i++) //i为block索引
	{
		for (int j = 0; j < block[i].gens.size(); j++)
		{
			if (block[i].gens[j].label == index)
			{
				return i;
			}
		}
	}
	return -1;
}
void codeTable::initblockcodes()
{
	for (int blockindex = 0; blockindex < block.size(); blockindex++)
	{
		for (int i = 0; i < block[blockindex].gens.size(); i++)
		{
			block[blockindex].codes = merge(block[blockindex].codes, createcode(block[blockindex].gens[i]));
		}
	}
}
void codeTable::printcodes()
{
	for (int blockindex = 0; blockindex < block.size(); blockindex++)
	{
		cout << block[blockindex].name << ":\n";
		for (int i = 0; i < block[blockindex].codes.size(); i++)
		{
			cout << "      "<<block[blockindex].codes[i] << endl;
		}
	}
}
vector<string> codeTable::createcode(GenStruct gen)
{
	vector<string> codes;
	int code = gen.code;
	clearNotUse(gen);
	registers reg; int regindex,temp;
	switch (code)
	{

	case 41://op = "*";
		if (isExistRvalue(gen.addr1) && isExistRvalue(gen.addr2))
		{
			codes.push_back("MUL " + findreg(gen.addr1, regindex).name + "," + findreg(gen.addr2, temp).name);
			regs[regindex].clearPush(gen.result);
		}
		else if (isExistRvalue(gen.addr1) && !isExistRvalue(gen.addr2))
		{
			codes.push_back("MUL " + findreg(gen.addr1, regindex).name + "," + gen.addr2);
			regs[regindex].clearPush(gen.result);
		}
		else if (!isExistRvalue(gen.addr1) && isExistRvalue(gen.addr2))
		{
			codes.push_back("MUL " + findreg(gen.addr2, regindex).name + "," + gen.addr1);
			regs[regindex].clearPush(gen.result);
		}
		else{
			reg = findreg(gen.addr1, regindex);
			codes.push_back("MOV " + reg.name + "," + gen.addr1);
			codes.push_back("MUL " + reg.name + "," + gen.addr2);
			regs[regindex].clearPush(gen.result);
		}
		break;
	case 43://op = "+"; 
		
		if (isExistRvalue(gen.addr1) && isExistRvalue(gen.addr2))
		{
			codes.push_back("ADD " + findreg(gen.addr1, regindex).name + "," + findreg(gen.addr2, temp).name);
			regs[regindex].clearPush(gen.result);
		}
		else if (isExistRvalue(gen.addr1) && !isExistRvalue(gen.addr2))
		{
			codes.push_back("ADD " + findreg(gen.addr1, regindex).name + "," + gen.addr2);
			regs[regindex].clearPush(gen.result);
		}
		else if (!isExistRvalue(gen.addr1) && isExistRvalue(gen.addr2))
		{
			codes.push_back("ADD " + findreg(gen.addr2, regindex).name + "," + gen.addr1);
			regs[regindex].clearPush(gen.result);
		}
		else{
			reg = findreg(gen.addr1, regindex);
			codes.push_back("MOV " + reg.name + "," + gen.addr1);
			codes.push_back("Add " + reg.name + "," + gen.addr2);
			regs[regindex].clearPush(gen.result);
		}
		break;
	case 45://op = "-";
		codes.push_back("MOV " + findreg(gen.addr1, regindex).name + ",-" + gen.addr2);
		regs[regindex].clearPush(gen.result);
		break;
	case 48://op = "/"; 没有这个文法
		codes.push_back("DIV " + gen.addr1 + "," + gen.addr2);
		break;
	case 51://op = ":="; 
		reg = findreg(gen.addr1, regindex);
		codes.push_back("MOV " + gen.result + "," + reg.name);
		regs[regindex].Rvalue.push_back(gen.result);
		break;
	case 52://op = "j";
		codes.push_back("GOTO " + findblocknameByGen(gen.result));
		break;
	case 53://op = "j<"; 
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JL " + findblocknameByGen(gen.result));
		break;
	case 54://op = "j<=";
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JLE " + findblocknameByGen(gen.result));
		break;
	case 55://op = "j<>";
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JNE " + findblocknameByGen(gen.result));
		break;
	case 56://op = "j="; 
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JE " + findblocknameByGen(gen.result));
		break;
	case 57://op = "j>";
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JG " + findblocknameByGen(gen.result));
		break;
	case 58://op = "j>=";
		codes.push_back("CMP " + gen.addr1 + "," + gen.addr2);
		codes.push_back("JGE " + findblocknameByGen(gen.result));
		break;
	default:
		break;
	}
	return codes;
}
bool codeTable::stringisinGen(string str,int index)
{
	for (int i = genStructs.size() - 1; i >= index; i--)   //因为先删除后操作,所以要把iindex是加进去
	{
		if (genStructs[i].addr1 == str || genStructs[i].addr2 == str)
			return true;
	}
	return false;
}
//遍历所有基本块,把非待用的寄存器里值给删了,把基本块里的Rvalue
void codeTable::clearNotUse(GenStruct gen)//运行到四元式的值
{
	int index = gen.label;
	//遍历所有寄存器的Rvalue 看看后没有在index之后的四元式出现
	for (int i = 0; i < regs.size(); i++)
	{
		for (int j = 0; j < regs[i].Rvalue.size(); j++)
		{
			if (!stringisinGen(regs[i].Rvalue[j], index))
			{
				//删除
				regs[i].Rvalue.erase(regs[i].Rvalue.begin() + j);
			}
		}
	}
}

到此为止,差不多就结束了。不过有个缺陷,就是计算一旦多起来寄存器可能就不够用了,所以在每次生成代码前还要把寄存器里非待用的给删了。何为非待用?例如:

1:  T1 :=A+B

2:   C :=T1+A

当执行完第一句时此时T1 和A是待用的因为之后的运算用到了他们,B是非待用的因为之后的运算没用到B。

实现非待用判断不难,首先从尾至当前,遍历四元式看看第二元素,第三元素是否与之相等。

实现非待用的删除,遍历每个寄存的RValue中的值,判断该值是否非待用,是则删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编译实验(三)目标代码生成 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • DOTA:用于航拍图像目标检测的大规模数据集

    目录 论文下载地址 论文作者 模型讲解 背景介绍 论文解读 DOTA数据集信息 类别信息 标注方式 数据集拆分 目标大小 目标宽高比 目标密度 结果分析 评估方法 水平HBB检测Baseline 定向OBB检测Baseline 论文下载地址
  • 没有微信和QQ,用记事本也能在线聊天

    很多公司因为安全的原因 并不允许员工装QQ或者微信等聊天软件 只能装公司内部的聊天软件 但是你的朋友不是同事的话也不可能会装你公司的内部软件 如果这个时候想要跟朋友聊一聊 那怎么办呢 很多人会说用手机啊 不过用手机太多也会带上工作时候聊天的
  • Unity实现账号登录,注册功能

    制作了用户登录界面 关于弹窗使用了DOTween插件 实现渐隐渐显效果 关于账号使用了本地Json读取 默认账号 YSQS YSQS1 密码 admin admin1 注册功能其实应该重构的因为有二次读流的问题存在 账号注册加入了邀请码 其
  • eNSP配置数据中心网络

    需求 由于接入备份的需要 用户部署了冗余链路 冗余备份链路的存在导致出现环网 可能会引起广播风暴和MAC地址表项被破坏 用户希望在有冗余备份链路的同时消除网络中的环路 在一条上行链路断开时 流量能切换到另外一条上行链路转发 还能合理利用网络
  • B-树和B+树的区别

    首先 B 树的应用最多的就是在MySQL中的索引 是InnoDB存储引擎的默认索引 那么这个在面试中也是经常被问到的 那么就做一个总结吧 概念 要了解B 树那么就不得不提一下的是B 树 因为B 树和B 树是由很大的联系 B树 B tree
  • 介绍一款HCIA、HCIP、HCIE的刷题软件

    华为认证考试分为三个等级 分别为工程师HCIA 高级工程师HCIP 专家HCIE 等级越高 考试难度越大 本篇带大家详细了解华为数通题库刷题工具的详细操作步骤 操作须知 本款刷题工具为一款刷题小程序 无需安装即可在线使用 一 界面认知 从主
  • nginx配置文件

    1 文件格式 Nginx 的配置文件是 个普通的纯文本文件 使用了 Nginx 自定义的 一套 配置语法 更接近于 脚本语言 混合了 Shell Perl C 的部分特性 要点叙述如 1 配置指令 以分号结束 可以接受多个参数 用空白字符分
  • 算法序列----线性表

    线性表 由零个或多个数据元素组成的有限序列 1 属于一个序列 2 第一个元素没有前驱 最后一个没有后继 3 有限的 两种物理存储结构 1 顺序存储 2 链式存储 顺序存储 1 存储位置就是顺序的位置 2 数组的最大长度 3 当前长度 len
  • Mac Os下安装Myeclipse提示insufficient memory

    如图所示 搞了两天终于解决来 发现网上对此问题的解决办法也是说的不清不楚对 总的来说有三种方法 当然我只用了其中都一种 方法一 Mac OS中用虚拟内存来提高性能 可是我用的macbook 有8g内存 要用上虚拟内存还是比较少的 所以你可以
  • 【hive】分组求排名

    分组求排名 相信好多使用Mysql的用户一定对分组求排名的需求感到发怵 但是在hive或者oracle来说就能简单实现 采用窗口函数 rank over row number over dense rank over 函数就能轻松完成 窗口
  • SSL certificate problem: unable to get local issuer certificate 错误解决

    今天公司换服务器域名 用了一个本地的服务器 然后我切换远程仓库拉代码的时候 终端报了如下错误git SSL certificate problem unable to get local issuer certificate 这个问题是由于
  • 大数据毕设 opencv python 深度学习垃圾图像分类系统

    文章目录 0 前言 课题简介 一 识别效果 二 实现 1 数据集 2 实现原理和方法 3 网络结构 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉
  • python星座分析

    python数据分析 python数据分析是一个非常好用的 虽然python数据分析只是刚刚起步 有些功能还未开发完成 但是用来做数据分析是绰绰有余了 本人也是专门研究和学习python数据分析的 星座数据爬虫 作为一个学习数据分析的人 爬
  • 在Apifox中,使用后置脚本显示响应结果reponse中的base64图片

    背景 在使用Apifox去请求有图片的接口时 我想要请求成功的同时 可以显示出来图片 这个时候就开始百度找官方文档 最终发现可以使用后置脚本显示reponse中的图片 方案 如下图所示 接口请求成功后 返回的json结构为 images p
  • 简单了解Linux图形界面

    之前曾经发生过启动虚拟机进入不了图形界面的情况 关于RedHat开启失败的解决方法 m0 48788975的博客 CSDN博客 在我看书的过程中总算搞清楚这是怎么一回事了 下面就和大家唠两句Linux视图 一 Linux操作界面主要分为传统
  • 机器学习_数据处理及模型评估相关资料

    基于sklearn 的auc 计算方法 训练模型填充空值 fill null 的几种方法 在Pandas中像写SQL一样做数据分析
  • Java通过freemarker实现导出PDF

    制作模板 引入依赖 引入所需字体文件 工具类的编写 业务实现 一 模板制作 1 编写html代码 需要替换的值与内容预留出来 用 name 代替 需循环处 表格前加上 lt list listKey as t gt t name 2 将写好
  • 浅谈React浏览器渲染流程

    当浏览器发送一个请求 会得到对应的响应 浏览器会通过HTML解析器去解析HTML会构建DOM树 会通过CSS解析器去解析CSS生成CSS规则树 如果页面中拥有一些JS逻辑 那么往往会通过JS将CSS HTML进行修改的操作 往往造成重排重绘
  • SPADE: Semantic Image Synthesis with Spatially-Adaptive Normalization

    目录 介绍 相关工作 1 Unconditional normalization layers 2 Conditional normalization layers 这一部分挺重要的 方法 3 1 Spatially adaptive de
  • 编译实验(三)目标代码生成

    通过词法分析 语法分析 语义分析 最后产生了四元式 而代码生成则是通过四元式来完成 我们先从简单开始做起 编译实验项目下载链接 http download csdn net download supersmart dong 10224159