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