?? cgen.cpp
字號(hào):
/****************************************************/
/* 文件 cgen.cpp */
/* 說明 類PASCAL語言編譯器代碼生成程序 */
/* 主題 編譯器結(jié)構(gòu):原理和實(shí)例 */
/****************************************************/
/*********** 該文件所包含的頭文件 ****************/
#include "globals.h"
#include "util.h"
#include "symbTable.h"
#include "scanner.h"
#include "parse.h"
#include "analyze.h"
#include "string.h"
#include "cgen.h"
#include "code.h"
static int tmpOffset = 0; /*臨時(shí)變量區(qū)的偏移*/
static void genStmt(TreeNode * t);
/*************************************************************/
/* 函數(shù)名 genProc */
/* 功 能 該函數(shù)生成過程節(jié)點(diǎn)的代碼 */
/* 說 明 該函數(shù)處理過程聲明部分的代碼生成,在過程信息表中填 */
/* 寫過程入口地址,結(jié)束是在pc中存入返回地址 */
/*************************************************************/
void genProc(TreeNode * t)
{
int savedLoc1; /*處理過程入口時(shí)所需的代碼地址*/
/*處理過程體部分*/
int currentLoc = emitSkip(0);
/*在過程信息表中填寫過程入口地址*/
t->table[0]->attrIR.More.ProcAttr.procEntry = currentLoc;
/*初始化寄存器displayOff*/
emitRM("LDC",displayOff,t->table[0]->attrIR.More.ProcAttr.nOff,0,"noff value");
/*提示信息,過程處理部分開始*/
if(TraceCode) emitComment("->procedure");
TreeNode * p1 = t->child[1];
TreeNode * p2 = t->child[2];
while(p1!=NULL)
{
/*處理過程聲明部分*/
if(p1->nodekind==ProcDecK)
{
savedLoc1 = emitSkip(1);
genProc(p1);
/*待過程處理完成,回填指令執(zhí)行地址*/
currentLoc = emitSkip(0);
emitBackup(savedLoc1);
emitRM("LDC",pc,currentLoc,0," procedure entry");
//emitRM_Abs("JEQ",ac,currentLoc," jump to outside procedure");
emitRestore();
}
p1 = p1->sibling;
}
if(p2!=NULL)
p2 = p2->child[0];
/*處理語句部分*/
while (p2!=NULL)
{
genStmt(p2);
p2 = p2->sibling;
}
/*指令寄存器pc的值置為返回地址*/
emitRM("LD",ac2,1,sp," fetch return address");
/*******注:此處的數(shù)字應(yīng)該為0,而不是1*******/
emitRM("LDA",pc,0,ac2," return old procedure");
/*提示信息,當(dāng)前過程處理部分結(jié)束*/
if(TraceCode) emitComment("<-procedure");
}
/*************************************************************/
/* 函數(shù)名 genStmt */
/* 功 能 該函數(shù)生成一個(gè)語句節(jié)點(diǎn)的代碼 */
/* 說 明 根據(jù)不同的語法樹節(jié)點(diǎn)產(chǎn)生不同的語句代碼 */
/*************************************************************/
void genStmt(TreeNode * t)
{
/*用于控制轉(zhuǎn)移display表的各項(xiàng)sp值*/
int ss;
/*用于存儲(chǔ)語法樹的各個(gè)節(jié)點(diǎn)*/
TreeNode * p0 = NULL;
TreeNode * p1 = NULL;
TreeNode * pp = NULL;
TreeNode * p2 = NULL;
SymbTable * entry = NULL;
/*用于記錄形參地址*/
int FormParam;
/*用于記錄跳轉(zhuǎn)回填時(shí)的地址*/
int savedLoc1,savedLoc2,currentLoc;
/*指向域變量的指針*/
fieldChain * fieldMem = NULL;
/*指向?qū)崊⒌闹羔?/
ParamTable * curParam = NULL;
switch(t->kind.stmt)
{
/*處理if語句*/
case IfK:
if(TraceCode) emitComment("->if");
p0 = t->child[0]; /*條件表達(dá)式部分*/
p1 = t->child[1]; /*then語句序列部分*/
p2 = t->child[2]; /*else語句序列部分*/
cGen(p0); /*產(chǎn)生測(cè)試表達(dá)式的代碼*/
/* savedLoc1賦值為當(dāng)前指令的tm地址號(hào)(emitLoc),emitLoc加1, *
/* 為if條件表達(dá)式為假時(shí),產(chǎn)生跳轉(zhuǎn)地址回填所留一代碼空位 */
savedLoc1 = emitSkip(1);
/* 指令回填地址savedLoc1記錄當(dāng)前生成代碼寫入地址, *
* 再將當(dāng)前生成代碼寫入地址emitLoc加1 *
* 為條件表達(dá)式為假的跳轉(zhuǎn)指令留一條指令寫入空位,用于代碼回填 *
* 將注釋寫入目標(biāo)代碼文件code,此處為向else跳轉(zhuǎn)指令位置 */
emitComment("if: jump to else belongs here");
/*產(chǎn)生then語句部分的代碼*/
cGen(p1);
/* 指令回填地址savedLoc2記錄當(dāng)前生成代碼寫入地址, *
* 再將當(dāng)前生成代碼寫入地址emitLoc加1 *
* 為跳轉(zhuǎn)到判斷語句結(jié)束位置的指令留一條代碼空位,用于代碼回填 *
* 將注釋寫入目標(biāo)代碼文件code,此處為向end跳轉(zhuǎn)指令位置 */
savedLoc2 = emitSkip(1);
emitComment("if: jump to end belongs here");
/* 指令回填地址currentLoc為當(dāng)前生成代碼寫入地址 *
* 當(dāng)前地址為條件為假的處理指令開始地址 */
currentLoc = emitSkip(0);
/*退回到指令回填地址savedLoc1,此處已經(jīng)預(yù)留了一個(gè)指令空位*/
emitBackup(savedLoc1);
/* 寫入跳轉(zhuǎn)到else的指令,此時(shí)跳轉(zhuǎn)位置currentLoc已經(jīng)得到 *
* 指令的跳轉(zhuǎn)地址為相對(duì)地址 */
emitRM_Abs("JEQ",ac,currentLoc,"if : jmp to else");
/* 恢復(fù)當(dāng)前生成代碼寫入地址emitLoc為指令回填地址currentLoc, *
* 恢復(fù)后地址為條件為假處理指令開始地址,即else開始位置 */
emitRestore();
/* 處理else語句部分的代碼 */
cGen(p2);
/* 指令回填地址currentLoc作為當(dāng)前生成代碼寫入地址 *
* 當(dāng)前地址為判斷語句結(jié)束位置 */
currentLoc = emitSkip(0);
/* 回退到指令回填地址savedLoc2,此處已經(jīng)預(yù)留了一個(gè)指令空間 */
emitBackup(savedLoc2);
/* 寫入跳轉(zhuǎn)到end的指令,此時(shí)跳轉(zhuǎn)位置currentLoc已經(jīng)得到地址 */
emitRM_Abs("LDA",pc,currentLoc,"jmp to end");
/* 恢復(fù)當(dāng)前生成代碼寫入地址emitLoc為指令回填地址currentLoc, *
* 恢復(fù)后地址為判斷語句結(jié)束地址,即end位置 */
emitRestore();
if (TraceCode) emitComment("<- if"); /*if語句結(jié)束*/
break;
/*處理while語句*/
case WhileK:
if ( TraceCode ) emitComment("->while");
p0 = t->child[0]; /*p0為while語句的條件表達(dá)式部分*/
p1 = t->child[1]; /*p1為while語句的語句序列部分*/
currentLoc = emitSkip(0);
cGen(p0); /*生成條件表達(dá)式部分代碼*/
/* 如果條件表達(dá)式為假,則跳轉(zhuǎn)至while語句結(jié)束 *
/* 此處為地址回填預(yù)留一個(gè)指令空間 */
savedLoc1 = emitSkip(1);
emitComment(" while : jump out while ");
cGen(p1); /*生成語句序列部分代碼*/
/*跳到條件表達(dá)式處,進(jìn)入下一次循環(huán)*/
emitRM("LDC",pc,currentLoc,0," jump to start ");
emitComment(" return to condition exp");
/*條件為假時(shí),跳出while循環(huán)*/
currentLoc = emitSkip(0);
emitBackup(savedLoc1);
emitRM_Abs("JEQ",ac,currentLoc," jump out while ");
emitRestore();
if(TraceCode) emitComment("<-while");
break;
/*處理賦值語句*/
case AssignK:
if(TraceCode) emitComment("->assign");
p0 = t->child[0]; /*賦值號(hào)左側(cè)的部分*/
p1 = t->child[1]; /*賦值號(hào)右側(cè)的部分*/
FindAdd(p0);
/*ac中存為賦值號(hào)左側(cè)變量的絕對(duì)偏移*/
/*先把a(bǔ)c存到ac2中*/
emitRM("LDA",ac2,0,ac,"save ac");
cGen(p1); /*處理賦值號(hào)右側(cè)的表達(dá)式部分*/
/*結(jié)果存入ac中*/
if(p0->table[0]->attrIR.More.VarAttr.access==dir)
/*賦值*/
emitRM("ST",ac,0,ac2,"var assign : store value");
else
{
/*ac2中為該變量的實(shí)際存儲(chǔ)位置*/
emitRM("LD",ac2,0,ac2," indir var assign");
emitRM("ST",ac,0,ac2," store value");
}
/* 如果代碼生成追蹤標(biāo)志TraceCode為TRUE,寫入注釋,assign語句結(jié)束 */
if (TraceCode) emitComment("<- assign") ;
break;
/*處理輸入語句*/
case ReadK:
/*生成讀指令,該指令完成讀入外部數(shù)值到累加器ac的動(dòng)作*/
emitRO("IN",ac,0,0,"read integer value");
emitRM("LDA",ac2,0,ac,"save ac");
/*計(jì)算變量的絕對(duì)偏移,ac中存為變量的絕對(duì)偏移*/
FindAdd(t);
if(t->table[0]->attrIR.More.VarAttr.access==dir)
{
/*直接存*/
/*最后生成存儲(chǔ)指令*/
emitRM("ST",ac2,0,ac," var read : store value");
}
else
{
/*以ac內(nèi)容作為地址找變量單元,再存*/
/*ac內(nèi)容放入ac1中*/
emitRM("LD",ac1,0,ac,"");
emitRM("ST",ac2,0,ac1," var read : store value");
}
break;
/* 處理write語句類型 */
case WriteK:
p0 = t->child[0];
cGen(p0); /*處理write語句部分的表達(dá)式部分*/
emitRO("OUT",ac,0,0,"write ac");
break;
/* 處理過程調(diào)用語句 */
case CallK:
p0 = t->child[0]; /*過程名*/
p1 = t->child[1]; /*過程的實(shí)參*/
pp = p0;
if(TraceCode) emitComment("->procedure call");
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*@@@@@@ 參數(shù)傳遞 @@@@@@@@*/
/*curParam是指向該過程形參表的指針*/
curParam = p0->table[0]->attrIR.More.ProcAttr.param;
while ((curParam!=NULL)&&(p1!=NULL))/*p1是實(shí)參*/
{
/*該形參的偏移*/
FormParam = curParam->entry->attrIR.More.VarAttr.off;
/*形參是變參時(shí)有三種情況*/
if(curParam->entry->attrIR.More.VarAttr.access==indir)
//{
/*實(shí)參是非形參,第一種*/
//if(!p1->table[0]->attrIR.More.VarAttr.isParam)
//{
/*計(jì)算該實(shí)參的絕對(duì)地址*/
// FindAdd(p1);
/*ac中現(xiàn)在存放的是實(shí)參的絕對(duì)地址*/
/*將實(shí)參地址送入currentAR的行參單元中*/
/*參數(shù)傳遞*/
// emitRM("ST",ac,FormParam,top," store actParam");
//}
/*實(shí)參是形參,分為兩種情況:dir,indir處理*/
//else
//{
/*實(shí)參是值參*/
if(p1->table[0]->attrIR.More.VarAttr.access==dir)
{
FindAdd(p1);
/*ac中為實(shí)參的絕對(duì)地址*/
/*將實(shí)參地址入currentAR的行參單元中*/
/*參數(shù)傳遞*/
emitRM("ST",ac,FormParam,top," store actParam");
}
/*實(shí)參是變參*/
else
{
/*此時(shí)將實(shí)參的單元內(nèi)容傳送入currentAR的行參單元中*/
FindAdd(p1);
/*ac中為p1的絕對(duì)偏移*/
/******ac中存的是實(shí)參單元地址******/
emitRM("LD",ac,0,ac," ActParam value");
/******ac中存的是實(shí)參單元內(nèi)容******/
/*參數(shù)傳遞*/
emitRM("ST",ac,FormParam,top," formal and act link ");
}
//}
//}
/*形參是值參時(shí)有四種情況*/
else
{
switch(p1->kind.exp)
{
/*第一種,數(shù)值或表達(dá)式,直接送值*/
case OpK:
case ConstK:
/*ac中存有表達(dá)式的值*/
genExp(p1);
emitRM("ST",ac,FormParam,top," formal and act link");
break;
case VariK:
/*該函數(shù)使ac中存儲(chǔ)為實(shí)參的絕對(duì)地址*/
FindAdd(p1);
/*該形參的偏移*/
FormParam = curParam->entry->attrIR.More.VarAttr.off;
/*該實(shí)參是形參,不能是a.b或a[b]的形式*/
//if(p1->table[0]->attrIR.More.VarAttr.isParam)
//{
/*第二種,值參,送值*/
if(p1->table[0]->attrIR.More.VarAttr.access==dir)
{
/*以ac中的值作為絕對(duì)地址,找出其對(duì)應(yīng)的存儲(chǔ)單元,*
*取出其內(nèi)容,作為實(shí)參 */
emitRM("LD",ac2,0,ac,"");
/*ac2中存放的是該變量?jī)?nèi)容*/
emitRM("ST",ac2,FormParam,top," Act and Formal link");
}
/*第三種,變參,取內(nèi)容作為地址,再取內(nèi)容送入*/
else
{
/*以ac中的內(nèi)容作為絕對(duì)地址*/
emitRM("LD",ac2,0,ac,"");
/*以ac2中的內(nèi)容作為絕對(duì)地址*/
emitRM("LD",ac2,0,ac2,"");
/*以ac2中的內(nèi)容作為實(shí)參*/
emitRM("ST",ac2,FormParam,top," Act and Formal link");
}
//}
/*該實(shí)參是普通變量*/
//else
//{
/*以ac中的值作為絕對(duì)地址*/
// emitRM("LD",ac2,0,ac,"");
/*以ac2的內(nèi)容作為實(shí)參*/
// emitRM("ST",ac2,FormParam,top," Act and Formal link");
//}
break;
}
}
curParam = curParam->next;
p1 = p1->sibling;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -