lcc源代码解析之interface

我们都知道lcc是一个可指定目标的编译器,具体目标平台可以用-target指定,有点类似嵌入式开发中的交叉编译器的味道。

我们知道编译器通常分为前端和后端,前端复制词法和语法的解析,后端负责具体平台上的执行代码的生成,

对于lcc而言,编译器启动时会依据用户的输入-target来识别目标,做好相关初始化,这个初始化实际上就是初始化一个结构体,填充其中的函数指针。

填充的数据来源于src文件夹中的*.md文件。

这个结构就是本文即将分析的interface及一些关联结构,对于不同的平台不见得会使用所有的接口。

同时对于编译性语言,在编译器获取一些重要的调试信息对于程序后期的debug至关重要,而lcc为debugger提供的结构也包含在interface(c.h)结构中。

具体如下:

/*
前端和后端的相互调用:
前端调用后端生成并发送执行代码
后端调用前端完成输出,分配空间,类型查询,以及节点,符号,串的管理
*/
#include "config.h"//定义了Xinterface结构
//为了方便注释,下面这个结构体稍微改了一下,与源代码并不一致
typedef struct metrics {
	unsigned char size;
	unsigned char align;//对齐字节数
	unsigned char outofline;//控制相关类型的常量的放置,如果为1,则该类型的常量不放入dag而是存放在一个匿名的static中。
} Metrics;

//定义了输出汇编目标代码需要的函数和数据成员
typedef struct interface {
	Metrics charmetric;
	Metrics shortmetric;
	Metrics intmetric;
	Metrics longmetric;
	Metrics longlongmetric;
	Metrics floatmetric;
	Metrics doublemetric;
	Metrics longdoublemetric;
	Metrics ptrmetric;
	Metrics structmetric;
	//以上为数据类型,不同类型的数组度量,包括对齐等信息
	
	unsigned little_endian:1;小端格式,还是大端格式. 1是小端格式
	unsigned mulops_calls:1;//硬件实现乘法,除法和取余数为1
	unsigned wants_callb:1;//设置为1时,要求前端生成CALL+B节点,否则后端自己实现
	unsigned wants_argb:1;//设置为1时,要求前端生成ARG+B节点
	unsigned left_to_right:1;//设置为1时,传递参数的顺序为从左到右,否则为从右到左
	unsigned wants_dag:1;//设置为1时,后端自己处理DAG节点.否则前端改引用次数大于1的节点
	unsigned unsigned_char:1;//设置为1时,char类型为无符号数,否则char为有符号数
	
void (*address)(Symbol p, Symbol q, long n);//生成地址符号.
void (*blockbeg)(Env *);//块初始化.
void (*blockend)(Env *); //块结束处理
void (*defaddress)(Symbol);//定义指针地址
void (*defconst)  (int suffix, int size, Value v);//定义常量
void (*defstring)(int n, char *s); //定义字符串
void (*defsymbol)(Symbol);//定义常量,标号,全局变量,或者静态变量的符号
void (*emit)    (Node);//从中间代码生成最终代码
void (*export)(Symbol);//输出处理函数
void (*function)(Symbol, Symbol[], Symbol[], int);//生成函数的代码
Node (*gen)     (Node);//生成代码
void (*global)(Symbol);//生成全局变量的代码
void (*import)(Symbol);//输入处理函数
void (*local)(Symbol);//局部变量声明
void (*progbeg)(int argc, char *argv[]);//整个编译开始,argv[*]通常为前端不能识别的选项
void (*progend)(void);//编译结束
void (*segment)(int);//设置到相应的段代码
void (*space)(int);//按字节分配储存空间

//一下函数接口提供给调试器,编译器前端通过这些函数给debugger提供符号表
void (*stabblock)(int, int, Symbol*);
void (*stabend)  (Coordinate *, Symbol, Coordinate **, Symbol *, Symbol *);
void (*stabfend) (Symbol, int);
void (*stabinit) (char *, int, char *[]);
void (*stabline) (Coordinate *);
void (*stabsym)  (Symbol);
void (*stabtype) (Symbol);
	Xinterface x;//对interface的扩展,用于后端存放和目标机器相关的接口数据和函数,为后端私有,各个后端不同
} Interface;


//后端绑定结构,通过-target指定
typedef struct binding {
	char *name;
	Interface *ir;
} Binding;

extern Binding bindings[];
extern Interface *IR;//-target指定


以x86为例,x86.md中初始化的代码如下

Interface x86IR = {
        1, 1, 0,  /* char */
        2, 2, 0,  /* short */
        4, 4, 0,  /* int */
        4, 4, 0,  /* long */
        4, 4, 0,  /* long long */
        4, 4, 1,  /* float */
        8, 4, 1,  /* double */
        8, 4, 1,  /* long double */
        4, 4, 0,  /* T * */
        0, 1, 0,  /* struct */
        1,        /* little_endian */
        0,        /* mulops_calls */
        0,        /* wants_callb */
        1,        /* wants_argb */
        0,        /* left_to_right */
        0,        /* wants_dag */
        0,        /* unsigned_char */
        address,
        blockbeg,
        blockend,
        defaddress,
        defconst,
        defstring,
        defsymbol,
        emit,
        export,
        function,
        gen,
        global,
        import,
        local,
        progbeg,
        progend,
        segment,
        space,
        0, 0, 0, 0, 0, 0, 0,
        {1, rmap,
            blkfetch, blkstore, blkloop,
            _label,
            _rule,
            _nts,
            _kids,
            _string,
            _templates,
            _isinstruction,
            _ntname,
            emit2,
            doarg,
            target,
            clobber,
}
};



//有向无环图(dag)节点,可执行代码的的描述结构
struct node {
	short op;//dag操作符,
	short count;//节点的值被使用或被其他节点引用的引用的次数,只有来之kids的引用才计数。
	//count大于1的为共享节点,
 	Symbol syms[3];//一些dag操作也使用一个或两个符号表指针作为操作数,
 	//即syms[0] syms[1],后端可能会使用syms[2],前端也有可能临时使用
	Node kids[2];//指向操作数节点
	Node link;//指向森林中下一个dag的根
	Xnode x;//后端对节点的扩展
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值