📄 genstmt.c
字号:
#include <stdio.h>
#include "genasm.h"
#include "syntax.h"
#include "utility.h"
void gen_stmt(//the main routine of generate a stmt
struct _stmtnode *stmt //auto tackle the next stmt
)
{
Symbol *tmpsym;
while( stmt != 0 )
{
if(stmt->labelno != UNKNOWN)
gen_label(stmt->labelno);
switch( stmt->stmtype )
{
case stmt_compound:
// case stmt_label:
gen_stmt(stmt->ss);
break;
case stmt_goto:
tmpsym = stmt->exp->val.label;
if(tmpsym->value.labelno==UNKNOWN)
generror(ERR_NOT_FOUND, tmpsym->name);
else
gen_code(op_jmp, 4, newLabel(tmpsym->value.labelno),0);
break;
case stmt_exp:
initstack();
gen_exp(stmt->exp, F_NOVALUE, stmt->exp->datatype->size);
break;
case stmt_return:
gen_return(stmt);
break;
case stmt_if:
gen_if(stmt);
break;
case stmt_while:
gen_while(stmt);
break;
case stmt_do:
gen_do(stmt);
break;
case stmt_for:
gen_for(stmt);
break;
case stmt_continue:
if(continuelabel != UNKNOWN)
gen_code(op_jmp, 4, newLabel(continuelabel),0);
else
genwarning(ERR_NOT_LOOP, "continue");
break;
case stmt_break:
if(continuelabel != UNKNOWN)
gen_code(op_jmp, 4, newLabel(breaklabel),0);
else
genwarning(ERR_NOT_LOOP, "break");
break;
case stmt_switch:
gen_switch(stmt);
break;
// case stmt_asm://no support this moment
///????????
break;
default:
debug("debug--unknown statement.\n");
break;
}
stmt = stmt->next;
}
}
void gen_funcbody(struct _stmtnode *stmt)
{
if(error_count)
return ;
current_func->value.localdata = (current_func->value.localdata+3)&~3;
asm_func_begin(current_func->name, current_func->value.localdata);
returnlabel = newlabelno++;
gen_stmt(stmt);
gen_label(returnlabel);
flush_queue();
asm_func_end(current_func->name);
returnlabel = UNKNOWN;
}
//map case to labelno;
/*typedef struct _casemap
{
int key;
int labelno;
}CaseMap;
*/
//so sorry, binary search optimization not ready
void gen_switch(struct _stmtnode *stmt)
{
int defaultlabel=UNKNOWN;
int oldbreak = breaklabel;
// int casecount = 0; // for opt
StmtNode *casestmt=stmt->s1, *defaultstmt = stmt->s2, *contentstmt = stmt->ss;
// CaseMap *onecase;
// List caselist = {0};
AddrMode *key;
breaklabel = newlabelno++;
initstack();
key = gen_exp(stmt->exp, F_DREG, 4);
while(casestmt)
{
gen_code(op_cmp, 4, key, newImme(NULL, casestmt->exp->val.i));
gen_code(op_jz, 4, newLabel(casestmt->labelno), NULL);
casestmt= casestmt->next;
}
if(defaultstmt&&defaultstmt->labelno != stmt->ss->labelno)
gen_code(op_jmp, 4, newLabel(defaultstmt->labelno), NULL);
gen_stmt(stmt->ss);
gen_label(breaklabel);
breaklabel = oldbreak;
return ;
}
void gen_for(struct _stmtnode *stmt)
{
int oldbreak, oldcont, enterlabel;
oldbreak = breaklabel;
oldcont = continuelabel;
enterlabel = newlabelno++;
breaklabel = newlabelno++;
continuelabel = newlabelno++;
initstack();
if(stmt->s1 != NULL)
gen_exp(stmt->s1->exp, F_NOVALUE, UNKNOWN);
gen_label(enterlabel);
if(stmt->exp->exptype != exp_void)
{
initstack();
falsejp(stmt->exp, breaklabel);
}
if(stmt->ss->stmtype != stmt_exp || stmt->ss->exp->exptype != exp_void)
{
gen_stmt(stmt->ss);
gen_label(continuelabel);
}
gen_stmt(stmt->s2);
gen_code(op_jmp, 4, newLabel(enterlabel),0);
gen_label(breaklabel);
breaklabel = oldbreak;
continuelabel = oldcont;
}
void gen_while(struct _stmtnode *stmt)
{
int oldcont, oldbreak;
oldcont = continuelabel; /* save old continue label */
continuelabel = newlabelno++; /* new continue label */
gen_label(continuelabel);
if( stmt->ss->stmtype == stmt_exp &&stmt->ss->exp->exptype ==exp_void ) /* no body*/
{
initstack();
truejp(stmt->exp,continuelabel);
}
else
{
oldbreak = breaklabel; /* save old break label */
breaklabel = newlabelno++;
initstack();
falsejp(stmt->exp,breaklabel);
gen_stmt(stmt->ss);
gen_code(op_jmp, 4, newLabel(continuelabel),0);
gen_label(breaklabel);
breaklabel = oldbreak; /* restore old break label */
}
continuelabel = oldcont; /* restore old continue label */
}
//do-while routine
void gen_do(struct _stmtnode *stmt)
{
int oldcont, oldbreak;
oldcont = continuelabel;//keep
continuelabel = newlabelno++;
gen_label(continuelabel);
if( stmt->ss->stmtype == stmt_compound )
{
oldbreak = breaklabel;
breaklabel = newlabelno++;
gen_stmt(stmt->ss); /* generate body */
initstack();
truejp(stmt->exp,continuelabel);
gen_label(breaklabel);
breaklabel = oldbreak;
}
else
{
gen_stmt(stmt->ss);
initstack();
truejp(stmt->exp,continuelabel);
}
continuelabel = oldcont;
}
void gen_if(struct _stmtnode *stmt)
{
int elselab, exitlab;
elselab = newlabelno++;
initstack();
falsejp(stmt->exp,elselab);
gen_stmt(stmt->s1);
if( stmt->s2 != 0 )
{
exitlab = newlabelno++;
gen_code(op_jmp, 4, newLabel(exitlab),NULL);
gen_label(elselab);
gen_stmt(stmt->s2);
gen_label(exitlab);
}
else
gen_label(elselab);
}
void gen_return(struct _stmtnode *stmt)
{
//now we don't support user defined type
ExpNode *exp = stmt->exp;
AddrMode *res ,*eax = newDreg(EAX);
initstack();
res = gen_exp(exp, F_ALL, exp->datatype->size);
if(!res)
return;
if(res->mode == am_dreg&&EAX == res->base_reg)
goto end;
if(exp->datatype->basic_type == bt_struct
||exp->datatype->basic_type == bt_union)
{
gen_code(op_lea, 4, eax, res);
}
else
{
gen_code(op_mov, 4, eax, res);
}
end:
gen_code(op_jmp, 4, newLabel(returnlabel), NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -