?? midcode.cpp
字號:
/****************************************************/
/* 文件 midcode.cpp */
/* 說明 TINY編譯器中間代碼生成實現 */
/****************************************************/
#include "globals.h" /* 該頭文件定義全局類型和變量 */
#include "util.h" /*該頭文件定義了一些實用函數*/
#include "symbTable.h"
#include "midcode.h" /* 該頭文件聲明了中間代碼生成文件的界面函數*/
/*臨時變量編號,全局變量,每個過程開始都對TempOffset進行
初始化,注:所以,不同過程中,可能有編號相同的臨時變量,但是
由于他們互不相干,所以不會有問題;而且優化部分是對基本塊進行優化,
每個基本塊最大是一個過程,也不會有問題*/
int TempOffset ;
/*標號值,全局變量*/
int Label = 0;
/*指向第一條中間代碼*/
CodeFile *firstCode = NULL ;
/*指向當前最后一條中間代碼*/
CodeFile *lastCode = NULL ;
/***********函數聲明******************/
CodeFile *GenMidCode(TreeNode *t);
void GenProcDec(TreeNode *t);
void GenBody(TreeNode *t);
void GenStatement(TreeNode *t);
void GenAssignS(TreeNode *t);
ArgRecord *GenVar(TreeNode *t);
ArgRecord *GenArray(ArgRecord *V1arg,TreeNode *t,int low ,int size);
ArgRecord *GenField(ArgRecord *V1arg,TreeNode *t ,fieldChain *head );
ArgRecord *GenExpr(TreeNode *t);
void GenCallS(TreeNode *t );
void GenReadS (TreeNode *t );
void GenWriteS(TreeNode *t );
void GenIfS(TreeNode *t );
void GenWhileS(TreeNode *t);
/********************************************************/
/* 函數名 GenMidCode */
/* 功 能 中間代碼生成主函數 */
/* 說 明 若有過程聲明,調用過程聲明的代碼聲明函數; */
/* 調用程序體的代碼生成函數 */
/********************************************************/
CodeFile * GenMidCode(TreeNode *t)
{
/*若有過程聲明,調用相應函數,產生過程聲明的中間代碼*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*display表相對于sp的偏移*/
ArgRecord *Noff = ARGValue(StoreNoff);
/*生成主程序入口聲明代碼*/
CodeFile *code = GenCode(MENTRY,NULL,NULL,Noff);
/*初始化臨時變量的開始編號,為臨時變量區的第一個地址*/
TempOffset = StoreNoff + 1;
/*調用語句序列的代碼生成函數*/
GenBody(t->child[2]);
/*回填主程序的AR的大小到主程序入口中間代碼*/
int size = TempOffset;
ArgRecord *sizeArg = ARGValue(size);
code->codeR.arg2= sizeArg;
return (firstCode) ;
}
/****************************************************/
/* 函數名 GenProcDec */
/* 功 能 過程聲明中間代碼生成函數 */
/* 說 明 生成過程入口中間代碼,生成過程體的中間 */
/* 代碼,生成過程出口的中間代碼 */
/****************************************************/
void GenProcDec(TreeNode *t)
{
/*得到過程的入口標號*/
int ProcEntry = NewLabel( );
/*過程名在符號表中的地址*/
SymbTable *Entry = t->table[0];
/*過程入口標號,回填入節點中*/
Entry->attrIR.More.ProcAttr.codeEntry = ProcEntry;
/*過程的display表的偏移量*/
int noff = Entry->attrIR.More.ProcAttr.nOff;
/*得到過程的層數及其ARG結構*/
int procLevel = Entry->attrIR.More.ProcAttr.level;
ArgRecord *levelArg = ARGValue(procLevel);
/*若過程內部仍有過程聲明,調用相應函數,產生過程聲明的中間代碼*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*產生過程入口中間代碼*/
ArgRecord *arg1=ARGLabel(ProcEntry);
CodeFile *code = GenCode(PENTRY,arg1,NULL,levelArg);
/*初始化臨時變量的開始編號,為過程臨時變量區的第一個地址*/
TempOffset = noff + procLevel+1;
/*調用語句序列的代碼生成函數處理過程體*/
GenBody(t->child[2]);
/*得到過程的AR的大小,回填入過程入口中間代碼*/
int size = TempOffset;
ArgRecord *sizeArg = ARGValue(size);
code->codeR.arg2 = sizeArg;
/*產生過程出口中間代碼*/
GenCode(ENDPROC,NULL,NULL,NULL);
}
/****************************************************/
/* 函數名 GenBody */
/* 功 能 語句序列中間代碼生成函數 */
/* 說 明 用于處理過程體或者程序體, */
/* 循環處理各個語句 */
/****************************************************/
void GenBody(TreeNode *t)
{
TreeNode *t1 = t;
/*令指針指向第一條語句*/
if (t1->nodekind==StmLK)
t1=t1->child[0];
while (t1!=NULL)
{ /*調用語句處理函數*/
GenStatement(t1);
t1= t1->sibling;
}
}
/****************************************************/
/* 函數名 GenStatement */
/* 功 能 語句處理函數 */
/* 說 明 根據語句的具體類型,分別調用相應的 */
/* 語句處理函數 */
/****************************************************/
void GenStatement(TreeNode *t)
{
switch(t->kind.stmt)
{ case AssignK : GenAssignS(t); break;
case CallK: GenCallS(t); break;
case ReadK: GenReadS(t); break;
case WriteK: GenWriteS(t); break;
case IfK : GenIfS (t); break;
case WhileK: GenWhileS(t); break;
case ReturnK: /*直接生成中間代碼*/
GenCode(RETURNC,NULL,NULL,NULL);
break;
default : break;
}
}
/****************************************************/
/* 函數名 GenAssignS */
/* 功 能 賦值語句處理函數 */
/* 說 明 處理左部變量,處理右部表達式,生成 */
/* 賦值語句中間代碼 */
/****************************************************/
void GenAssignS(TreeNode *t)
{ /*調用賦值左部變量的處理函數*/
ArgRecord *Larg = GenVar(t->child[0]);
/*調用賦值右部表達式的處理函數*/
ArgRecord *Rarg = GenExpr(t->child[1]);
/*生成賦值語句中間代碼*/
GenCode(ASSIG,Rarg,Larg,NULL);
}
/****************************************************/
/* 函數名 GenVar */
/* 功 能 變量處理 函數 */
/* 說 明 */
/****************************************************/
ArgRecord *GenVar(TreeNode *t)
{
int low ,size;
fieldChain *head = NULL ;
/*生成變量名的ARG結構, Entry為標識符在符號表中的地址*/
SymbTable *Entry = t->table[0];
ArgRecord *V1arg = ARGAddr(t->name[0],
Entry->attrIR.More.VarAttr.level,
Entry->attrIR.More.VarAttr.off,
Entry->attrIR.More.VarAttr.access);
/*返回的ARG結構*/
ArgRecord * Varg = NULL;
switch(t->attr.ExpAttr.varkind)
{ /*標識符變量情形*/
case IdV: Varg = V1arg; break;
/*數組成員變量情形*/
case ArrayMembV:
/*構造數組下屆和數組大小的ARG結構*/
low = Entry->attrIR.idtype->More.ArrayAttr.low;
size = Entry->attrIR.idtype->More.ArrayAttr.elemTy->size;
Varg = GenArray(V1arg, t , low, size);
break;
/*域變量情形*/
case FieldMembV:
head = Entry->attrIR.idtype->More.body;
Varg = GenField(V1arg,t ,head);
break;
default : break;
}
return (Varg);
}
/****************************************************/
/* 函數名 GenArray */
/* 功 能 數組成員變量處理函數 */
/* 說 明 由函數GenVar或函數GenField調用 */
/****************************************************/
ArgRecord *GenArray(ArgRecord *V1arg,TreeNode *t,int low ,int size)
{ /*處理下標表達式*/
ArgRecord *Earg= GenExpr(t->child[0]);
ArgRecord *lowArg = ARGValue(low);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -