<编译器> 7. 中间代码 | 3. 核心模块

中间树语言: Tree.c
抽象语法 -> 树语言: Frame.c, MyFrame.c
树语言 (T_xxx) -> IR 中间代码 (Tr_xxx):Translate.c

IR 代码中 符号代码( label )沿用不变
int 调用 T_Const(int i )

Tree 模块:


1. patchList:真值/假值 回填表

这里是 patchList 的生成, 至于具体怎么回填后面才会讲

struct patchList_ {
    Temp_label *head; 
    patchList tail
    };

// 生成 stm
stm = T_Cjump(T_ge, unEx(left), unEx(right), NULL, NULL);
   or
stm = T_Cjump(T_eq, callEq, T_Const(1), NULL, NULL);

// 通过 stm 生成 真/假值 回填表
patchList tlist;
patchList rList;
tlist = PatchList(&stm->u.CJUMP.true, NULL);
flist = PatchList(&stm->u.CJUMP.false, NULL);

// 最后通过 stm, 真/假值 回填表 生成 Tr_Exp
Tr_Exp e = Tr_Cx(tlist, flist, stm);

Frame 模块:


1. 片段相关的代码
都在 Frame 模块中, translate 调用 Frame 模块获取

struct F_frag ;
struct F_fragList ;

F_frag F_StringFrag(Temp_label, string); // 字符串片段
F_frag F_ProcFrag(T_stm, F_frame); // 流程片段: 栈帧+函数体

static F_frag* extendFragList(); // 扫描到新的元素,扩容并返回全局片段表
F_fragList F_getFragList(void); // 获取全局片段表

*2. static F_frag extendFragList(); **
扫描到新的元素,扩容并返回全局片段表

// 重置全局片段表, 返回 head
static F_frag* extendFragList(){
  // 创建指针变量
  if (fragList == NULL){
    fragList = (F_fragList*) checked_malloc(sizeof(F_fragList*));
  }
  // 指针变量赋值为一个 fragList 对象
  *fragList = (F_fragList) checked_malloc(sizeof (struct F_fragList_));

  if (fragList_head == NULL){
    fragList_head = *fragList;
  }

  // 把全局片段表的 head 拿出来返回,然后全局片段片更新为 NULL
  F_frag  *curf = &((*fragList)->head);

  // 除了 head 外剩于的片段表设为 NULL
  fragList = &((*fragList)->tail);
  *fragList = NULL;

  return curf;
}

3. 字符串片段

void F_String(Temp_label label, string str){
    // 先获取当前片段
	F_frag *currentFrag = extendFragList();
    // 再更新片段
	*currentFrag = F_StringFrag(label, str);
}

4. 调用外部函数: F_externalCall
如 printf, checked_malloc 等

// 调用外部函数,如 printf, checked_malloc 等
T_exp F_externalCall(string funName, T_expList args){
  return T_Call(T_Name(Temp_namedlabel(funName)), args);
}

5. F_Exp(F_access acc, T_exp framePtr);
在栈帧 framePtr 中 找到 access 对应的地址: frame 地址 + offset 地址

// 生成 access 的*访问地址*
T_exp F_Exp(F_access acc, T_exp framePtr){
  // 判断目标 access 在栈帧中 / 寄存器中
  if (acc->kind == inFrame){
    // 地址 = 栈帧地址 + offset(位移)
    return T_Mem(T_Binop(T_plus, framePtr, T_Const(acc->u.offset)));
  }else{
    // 寄存器
    return T_Temp(acc->u.reg);
  }
}

Translate 模块

1. 沿静态链往上找变量

Tr_exp Tr_simpleVar(Tr_access acc, Tr_level level){
  debug("Tr_simpleVar");

  T_exp texp;
  F_access access = acc->access;
  // 判断当前 level 是否和 变量访问的level (acc->level) 一致,一致就直接用, 不一致就沿着***静态连*** 找
  if (level != acc->level){
    // 沿着静态链往上找对应的 level
    texp = F_Exp(F_staticLink(), T_Temp(F_FP()));
    level = level->parent;

    while (level != acc->level){
      // 静态链是一个指向其**外部函数**栈帧的指针链
      // ... todo ...
      texp = F_Exp(F_staticLink(),texp);
      // level 没有找到,再往上找父level
      level = level->parent;
    }
    texp = F_Exp(acc->access,texp);
  }else{
    texp = F_Exp(acc->access, T_Temp(F_FP()))
  }

}

所谓的静态链,就是对栈帧的链式寻址,静态链就是栈帧链!

// texp = F_Exp(F_staticLink(), T_Temp(F_FP()));
// 静态链,就是全局的那个栈帧
F_access F_staticLink(){
    // 静态链默认在栈帧中
    if (static_link == NULL){
        static_link = InFrame(0);
    }
    return static_link;
}

2. doPatch

struct Cx {
	patchList trues; 
	patchList falses; 
	T_stm stm;
};
// patchList 就是 label 的 list, 
struct patchList_ {
	Temp_label *head;
	patchList tail;
};
static void doPatch(patchList list, Temp_label label){
	Temp_label *l;
	for(; list!=NULL; list=list->tail){
		l = list->head;
		if(l!=NULL){
			*l = label; // 将 label 内容复制到 l 中
		}
	}
}

Semant 模块:

Semant 模块只调用 Translate 模块的接口,将 AST 结构的抽象 转化为 中间代码结构 struct expty

将代码翻译为 Tr_exp, 过程中写入全局 片段 表

struct expty result = transExp(mainLevel, v, t, exp);

// 结构体 expty:
struct expty expTy(Tr_exp e, Ty_ty t)

transExp(): 将 表达式 A_exp 转化为 中间代码
static struct expty transExp(Tr_level level, S_table v, S_table t, A_exp e)

transVar(): 将 表达式 A_exp 转化为 中间代码
static struct expty transVar(Tr_level level, S_table venv, S_table tenv, A_var v)

posted @ 2024-06-06 17:45  Leon大帝  阅读(24)  评论(0)    收藏  举报