struct InstrSeq * doPrintsp(struct ExprRes * Expr){ if(Expr->Type != TYPE_INT){ TypeError(); } struct InstrSeq * code; code = Expr->Instrs; char * end = GenLabel(); char * next = GenLabel(); int i = AvailTmpReg(); int one = AvailTmpReg(); AppendSeq(code, GenInstr(NULL, "addi", TmpRegName(one), "$0", "1")); AppendSeq(code, GenInstr(NULL, "blt", TmpRegName(Expr->Reg), "$0", end)); AppendSeq(code, GenInstr(NULL, "li", TmpRegName(i), "0", NULL)); AppendSeq(code, GenInstr(next, NULL,NULL,NULL,NULL)); AppendSeq(code, GenInstr(NULL, "li", "$v0", "4", NULL)); AppendSeq(code, GenInstr(NULL, "la", "$a0", "_sp", NULL)); AppendSeq(code, GenInstr(NULL, "syscall", NULL, NULL,NULL)); AppendSeq(code, GenInstr(NULL, "addi", TmpRegName(i), TmpRegName(i), "1")); AppendSeq(code, GenInstr(NULL, "blt", TmpRegName(i), TmpRegName(Expr->Reg), next)); AppendSeq(code, GenInstr(end, NULL,NULL,NULL,NULL)); ReleaseTmpReg(i); ReleaseTmpReg(one); ReleaseTmpReg(Expr->Reg); free(Expr); free(end); free(next); return code; }
extern struct ExprRes * doRelOp(struct ExprRes * Res1, struct ExprRes * Res2, int op){ if(Res1->Type != TYPE_INT || Res2->Type != TYPE_INT){ TypeError(); } struct InstrSeq * iseq; char * t_res = GenLabel(); char * end = GenLabel(); int reg = AvailTmpReg(); if (op == 0 ){ iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res); } else if (op == 1){ iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res); AppendSeq(iseq, GenInstr(NULL, "bgt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res)); } else if (op == 2) { iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res); AppendSeq(iseq, GenInstr(NULL, "blt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res)); } else if (op == 3) { iseq = GenInstr(NULL, "bne", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res); } else if (op == 4) { iseq = GenInstr(NULL, "blt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg),t_res); } else if (op == 5) { iseq = GenInstr(NULL, "bgt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res); } AppendSeq(iseq, GenInstr(NULL, "li", TmpRegName(reg), "0", NULL)); AppendSeq(iseq, GenInstr(NULL, "b", end, NULL,NULL)); AppendSeq(iseq, GenInstr(t_res, NULL,NULL,NULL,NULL)); AppendSeq(iseq, GenInstr(NULL, "li", TmpRegName(reg), "1", NULL)); AppendSeq(iseq, GenInstr(end, NULL,NULL,NULL,NULL)); AppendSeq(Res1->Instrs, Res2->Instrs); AppendSeq(Res1->Instrs, iseq); ReleaseTmpReg(Res1->Reg); ReleaseTmpReg(Res2->Reg); free(t_res); free(end); free(Res2); Res1->Reg = reg; Res1->Type = TYPE_BOOL; return Res1; }
int CodeGenerator::GenDoStart() { GenBlockHeader( "Do loop" ); int newLabel = CreateLabel(); GenLabel( newLabel ); return newLabel; }
struct ExprRes * doNot(struct ExprRes * Res){ if(Res->Type != TYPE_BOOL){ TypeError(); } char * fal = GenLabel(); char * end = GenLabel(); AppendSeq(Res->Instrs, GenInstr(NULL, "beq", "$0", TmpRegName(Res->Reg), fal)); AppendSeq(Res->Instrs, GenInstr(NULL, "li", TmpRegName(Res->Reg), "0", NULL )); AppendSeq(Res->Instrs, GenInstr(NULL, "b", end, NULL,NULL)); AppendSeq(Res->Instrs, GenInstr(fal, NULL, NULL, NULL, NULL)); AppendSeq(Res->Instrs, GenInstr(NULL, "li", TmpRegName(Res->Reg), "1", NULL )); AppendSeq(Res->Instrs, GenInstr(end, NULL,NULL,NULL,NULL)); return Res; }
extern struct InstrSeq * doWhile(struct ExprRes *res, struct InstrSeq *seq){ if( res->Type != TYPE_BOOL){ TypeError(); } struct InstrSeq * code; char * loop = GenLabel(); char * end = GenLabel(); code = GenInstr(loop, NULL, NULL, NULL, NULL); AppendSeq(code, res->Instrs); AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0", end)); AppendSeq(code, seq); AppendSeq(code, GenInstr(NULL, "b", loop, NULL, NULL)); AppendSeq(code, GenInstr(end, NULL, NULL, NULL, NULL)); ReleaseTmpReg(res->Reg); free(res); free(loop); free(end); return code; }
void CodeGenerator::GenFuncEnd( std::string funcName, int retLabel ) { funcName = '_' + funcName; GenLine(); GenLabel( retLabel ); GenMov( "esp", "ebp" ); GenPop( "ebp" ); GenLine( "RET" ); GenLine( funcName + " ENDP" ); }
void CodeGenerator::GenNot() { GenBlockHeader( "Not" ); GenPop( "eax" ); GenMov( "edx", "0" ); GenLine( "cmp eax, 0" ); GenLine( "JNE L" + toString( ++mLabelCount ) ); GenLine( "inc edx" ); GenLabel( mLabelCount ); GenPush( "edx" ); }
struct InstrSeq * doPrint(struct ExprRes * Expr) { struct InstrSeq *code; code = Expr->Instrs; char * end = GenLabel(); if (Expr->Type == TYPE_BOOL){ char * fal = GenLabel(); AppendSeq(code,GenInstr(NULL,"li","$v0","4",NULL)); AppendSeq(code, GenInstr(NULL, "beq", "$0", TmpRegName(Expr->Reg), fal)); AppendSeq(code,GenInstr(NULL,"la","$a0","_tru",NULL)); AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL)); AppendSeq(code, GenInstr(NULL, "b", end, NULL, NULL)); AppendSeq(code, GenInstr(fal, NULL, NULL, NULL, NULL)); AppendSeq(code,GenInstr(NULL,"la","$a0","_fal",NULL)); AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL)); } else if(Expr->Type == TYPE_INT){ AppendSeq(code,GenInstr(NULL,"li","$v0","1",NULL)); AppendSeq(code,GenInstr(NULL,"move","$a0",TmpRegName(Expr->Reg),NULL)); AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL)); } else if (Expr->Type == TYPE_STR){ AppendSeq(code, GenInstr(NULL, "li", "$v0", "4", NULL)); AppendSeq(code, GenInstr(NULL, "move", "$a0", TmpRegName(Expr->Reg), NULL)); AppendSeq(code, GenInstr(NULL, "syscall", NULL, NULL, NULL)); } AppendSeq(code, GenInstr(end,NULL,NULL,NULL,NULL)); ReleaseTmpReg(Expr->Reg); free(Expr); return code; }
void CodeGenerator::GenOr() { GenBlockHeader( "Or" ); GenPop( "ecx" ); GenPop( "eax" ); GenMov( "edx", "0" ); GenLine( "or eax, ecx" ); GenLine( "cmp eax, 0" ); GenLine( "JE L" + toString( ++mLabelCount ) ); GenLine( "inc edx" ); GenLabel( mLabelCount ); GenPush( "edx" ); }
void CodeGenerator::GenAnd() { GenBlockHeader( "And" ); GenPop( "ecx" ); GenPop( "eax" ); GenLine( "imul ecx" ); GenMov( "edx", "0" ); GenLine( "cmp eax, 0" ); mAsmCode += "JE"; mAsmCode += " L" + toString( ++mLabelCount ) + "\n"; GenLine( "inc edx" ); GenLabel( mLabelCount ); GenPush( "edx" ); }
struct ExprRes * doStrLit(char * str){ struct ExprRes *res; struct StrLabels * strl; strl = malloc(sizeof(struct StrLabels)); strl->SLabel = GenLabel(); strl->Str = strdup( str); strl->next = slabels; slabels = strl; res = (struct ExprRes *) malloc(sizeof(struct ExprRes)); res->Reg = AvailTmpReg(); res->Instrs = GenInstr(NULL, "la", TmpRegName(res->Reg),strl->SLabel, NULL); res->Type = TYPE_STR; return res; }
extern struct InstrSeq * doIfElse(struct ExprRes *res, struct InstrSeq * iseq, struct InstrSeq *eseq){ if(res->Type != TYPE_BOOL){ TypeError(); } struct InstrSeq * code; code = res->Instrs; char * else_label = GenLabel(); char *end = GenLabel(); AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0", else_label)); AppendSeq(code, iseq); AppendSeq(code, GenInstr(NULL, "b", end,NULL,NULL)); AppendSeq(code, GenInstr(else_label, NULL,NULL,NULL,NULL)); AppendSeq(code, eseq); AppendSeq(code, GenInstr(end, NULL,NULL,NULL,NULL)); ReleaseTmpReg(res->Reg); free(res); free(else_label); free(end); return code; }
struct ExprRes * doPower(struct ExprRes * Res1, struct ExprRes * Res2) { if(Res1->Type != TYPE_INT || Res2->Type != TYPE_INT){ TypeError(); } int reg; reg = AvailTmpReg(); struct InstrSeq* iseq; int pow = AvailTmpReg(); int current = AvailTmpReg(); char * l1 = GenLabel(); char * l2 = GenLabel(); iseq = GenInstr(NULL, "move", TmpRegName(pow), "$0", NULL); AppendSeq(iseq, GenInstr(NULL, "addi", TmpRegName(current), "$0", "1")); AppendSeq(iseq, GenInstr(NULL, "beq", TmpRegName(Res2->Reg), "$0", l2)); AppendSeq(iseq, GenInstr(l1, NULL, NULL, NULL, NULL)); AppendSeq(iseq, GenInstr(NULL, "mul", TmpRegName(current), TmpRegName(current), TmpRegName(Res1->Reg))); AppendSeq(iseq, GenInstr(NULL, "addi", TmpRegName(pow), TmpRegName(pow), "1")); AppendSeq(iseq, GenInstr(NULL, "blt", TmpRegName(pow), TmpRegName(Res2->Reg), l1)); AppendSeq(iseq, GenInstr(l2, NULL, NULL, NULL, NULL)); AppendSeq(Res1->Instrs, Res2->Instrs); AppendSeq(Res1->Instrs, iseq); ReleaseTmpReg(Res1->Reg); ReleaseTmpReg(Res2->Reg); ReleaseTmpReg(pow); Res1->Reg = current; free(l1); free(l2); free(Res2); return Res1; }
void CodeGenerator::GenCompare( std::string sign ) { GenBlockHeader( "Compare" ); GenPop( "ecx" ); GenPop( "eax" ); GenMov( "edx", "0" ); GenLine( "cmp eax, ecx" ); if( sign == "==" ) mAsmCode += "JNE "; if( sign == "!=" ) mAsmCode += "JE"; if( sign == ">" ) mAsmCode += "JLE"; if( sign == "<" ) mAsmCode += "JGE"; if( sign == ">=" ) mAsmCode += "JL"; if( sign == "<=" ) mAsmCode += "JG"; mAsmCode += " L" + toString( ++mLabelCount ) + "\n"; GenLine( "inc edx" ); GenLabel( mLabelCount ); GenPush( "edx" ); }
extern struct InstrSeq * doIf(struct ExprRes *res, struct InstrSeq *seq){ if(res->Type != TYPE_BOOL){ TypeError(); } struct InstrSeq *code; code = res->Instrs; char * label; label = GenLabel(); AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0",label )); AppendSeq(code, seq); AppendSeq(code, GenInstr(label, NULL,NULL,NULL,NULL)); ReleaseTmpReg(res->Reg); free(res); free(label); return code; }
void GenFin(void) { if (StructCpyLabel) { char s[1 + 2 + (2 + CHAR_BIT * sizeof StructCpyLabel) / 3]; char *p = s + sizeof s; int lbl = LabelCnt++; *--p = '\0'; p = lab2str(p, StructCpyLabel); *--p = '_'; *--p = '_'; if (OutputFormat != FormatFlat) puts2(CodeHeader); GenLabel(p, 1); puts2("\tmove\t$2, $6\n" "\tmove\t$3, $6"); GenNumLabel(lbl); puts2("\tlbu\t$6, 0($5)\n" "\taddiu\t$5, $5, 1\n" "\taddiu\t$4, $4, -1\n" "\tsb\t$6, 0($3)\n" "\taddiu\t$3, $3, 1"); printf2("\tbne\t$4, $0, "); GenPrintNumLabel(lbl); puts2(""); #ifndef NO_REORDER_WORKAROUND GenNop(); #endif puts2("\tj\t$31"); #ifndef NO_REORDER_WORKAROUND GenNop(); #endif if (OutputFormat != FormatFlat) puts2(CodeFooter); } }
/* * PreProcess - pre-process source file */ vi_rc PreProcess( const char *fn, sfile **sf, labels *lab ) { GENERIC_FILE gf; int i, token, k, len; sfile *tsf; char tmp[MAX_SRC_LINE], tmp2[MAX_SRC_LINE]; char tmp3[MAX_SRC_LINE]; bool ret; #ifdef VICOMP bool AppendingFlag = FALSE; #else #define AppendingFlag EditFlags.Appending #endif /* * get source file */ #ifdef VICOMP ret = SpecialOpen( fn, &gf ); #else if( EditFlags.CompileScript ) { EditFlags.OpeningFileToCompile = TRUE; ret = SpecialOpen( fn, &gf, FALSE ); EditFlags.OpeningFileToCompile = FALSE; } else { ret = SpecialOpen( fn, &gf, EditFlags.BoundData ); } #endif if( !ret ) { return( ERR_FILE_NOT_FOUND ); } /* * init control */ CSInit(); CurrentSrcLine = 0L; tsf = MemAlloc( sizeof( sfile ) ); tsf->next = NULL; tsf->prev = NULL; tsf->arg1 = NULL; tsf->arg2 = NULL; tsf->data = NULL; tsf->token = SRC_T_NULL; *sf = tmpTail = tsf; cLab = lab; /* * set up error handler */ i = setjmp( genExit ); if( i != 0 ) { SpecialFclose( &gf ); return( (vi_rc)i ); } /* * process each line */ while( SpecialFgets( tmp, MAX_SRC_LINE - 1, &gf ) >= 0 ) { /* * prepare this line */ CurrentSrcLine++; #ifndef VICOMP if( !EditFlags.ScriptIsCompiled ) { #endif RemoveLeadingSpaces( tmp ); k = strlen( tmp ); memcpy( tmp3, tmp, k + 1 ); if( (len = NextWord1( tmp, tmp2 )) <= 0 ) { continue; } if( tmp2[0] == '#' ) { continue; } hasVar = FALSE; for( i = 0; i < k; i++ ){ if( tmp3[i] == '%' ) { hasVar = TRUE; break; } } /* * if we are appending (ie, an append token was encounterd * before, stop tokenizing */ if( !AppendingFlag ) { token = Tokenize( SourceTokens, tmp2, TRUE ); #ifndef VICOMP if( token == SRC_T_VBJ__ ) { EditFlags.ScriptIsCompiled = TRUE; continue; } #endif } else { token = TOK_INVALID; } #ifndef VICOMP } else { len = NextWord1( tmp, tmp2 ); hasVar = (bool) tmp2[0] - '0'; token = atoi( &tmp2[1] ); } #endif /* * process recognized tokens */ if( token != TOK_INVALID ) { RemoveLeadingSpaces( tmp ); if( token > SRC_T_NULL ) { genItem( token, tmp ); continue; } /* * get parm */ AddString( &CurrentSrcData, tmp ); freeSrcData = TRUE; /* * process token */ switch( token ) { case SRC_T_EXPR: genExpr(); break; case SRC_T_LABEL: GenLabel( tmp ); break; case SRC_T_IF: CSIf(); break; case SRC_T_QUIF: CSQuif(); break; case SRC_T_ELSEIF: CSElseIf(); break; case SRC_T_ELSE: CSElse(); break; case SRC_T_ENDIF: CSEndif(); break; case SRC_T_LOOP: CSLoop(); break; case SRC_T_ENDLOOP: case SRC_T_ENDWHILE: CSEndLoop(); break; case SRC_T_WHILE: CSWhile(); break; case SRC_T_UNTIL: CSUntil(); break; case SRC_T_BREAK: CSBreak(); break; case SRC_T_CONTINUE: CSContinue(); break; default: genItem( token, NULL ); if( token == SRC_T_GOTO ) { #ifndef VICOMP if( EditFlags.ScriptIsCompiled ) { NextWord1( CurrentSrcData, tmp ); tmpTail->branchcond = atoi( CurrentSrcData ); strcpy( CurrentSrcData, tmp ); } else { #endif tmpTail->branchcond = COND_JMP; #ifndef VICOMP } #endif } tmpTail->data = CurrentSrcData; freeSrcData = FALSE; break; } if( freeSrcData ) { MemFree( CurrentSrcData ); } /* * set all other tokens to be processed at run time */ } else { #ifndef VICOMP if( EditFlags.ScriptIsCompiled ) { RemoveLeadingSpaces( tmp ); genItem( token, tmp ); continue; } #endif if( !AppendingFlag ) { token = Tokenize( TokensCmdLine, tmp2, TRUE ); } else { token = TOK_INVALID; } switch( token ) { case PCL_T_COMMANDWINDOW: case PCL_T_STATUSWINDOW: case PCL_T_COUNTWINDOW: case PCL_T_EDITWINDOW: case PCL_T_EXTRAINFOWINDOW: case PCL_T_FILECWINDOW: case PCL_T_LINENUMBERWINDOW: case PCL_T_DIRWINDOW: case PCL_T_FILEWINDOW: case PCL_T_SETWINDOW: case PCL_T_SETVALWINDOW: case PCL_T_MESSAGEWINDOW: case PCL_T_MENUWINDOW: case PCL_T_MENUBARWINDOW: case PCL_T_ENDWINDOW: case PCL_T_SETCOLOR: case PCL_T_MATCH: case PCL_T_DIMENSION: case PCL_T_BORDER: case PCL_T_HILIGHT: case PCL_T_TEXT: case PCL_T_ALIAS: case PCL_T_ABBREV: case PCL_T_MENU: case PCL_T_MENUITEM: case PCL_T_ENDMENU: case PCL_T_WHITESPACE: case PCL_T_SELECTION: case PCL_T_EOFTEXT: case PCL_T_KEYWORD: case PCL_T_OCTAL: case PCL_T_HEX: case PCL_T_INTEGER: case PCL_T_CHAR: case PCL_T_PREPROCESSOR: case PCL_T_SYMBOL: case PCL_T_INVALIDTEXT: case PCL_T_IDENTIFIER: case PCL_T_JUMPLABEL: case PCL_T_COMMENT: case PCL_T_FLOAT: case PCL_T_STRING: case PCL_T_VARIABLE: case PCL_T_FILETYPESOURCE: case PCL_T_ENDFILETYPESOURCE: case PCL_T_LOCATE: case PCL_T_MAP: case PCL_T_MAP_DMT: case PCL_T_MENUFILELIST: case PCL_T_MENULASTFILES: case PCL_T_DEFAULTWINDOW: case PCL_T_ACTIVEMENUWINDOW: case PCL_T_GREYEDMENUWINDOW: case PCL_T_ACTIVEGREYEDMENUWINDOW: RemoveLeadingSpaces( tmp ); token += SRC_T_NULL + 1; genItem( token, tmp ); break; case PCL_T_SET: token += SRC_T_NULL + 1; #ifdef VICOMP WorkLine->data[0] = 0; Set( tmp ); genItem( token, WorkLine->data ); #else if( EditFlags.CompileScript ) { vi_rc rc; WorkLine->data[0] = 0; rc = Set( tmp ); if( rc != ERR_NO_ERR ) { Error( GetErrorMsg( rc ) ); } genItem( token, WorkLine->data ); } else { genItem( token, tmp ); } #endif break; default: if( AppendingFlag ) { if( tmp3[0] == '.' && tmp3[1] == 0 ) { AppendingFlag = FALSE; } } else if( token == TOK_INVALID ) { /* * see if the current token is a Ex token. If * it isn't, then see if the next one is * (i.e., look for <n> append) */ token = Tokenize( TokensEx, tmp2, FALSE ); if( token == TOK_INVALID ) { if( NextWord1( tmp, tmp2 ) >= 0 ) { token = Tokenize( TokensEx, tmp2, FALSE ); if( token == EX_T_APPEND ) { AppendingFlag = TRUE; } } } } if( tmp3[0] == '>' ) { tmp3[0] = ' '; } genItem( TOK_INVALID, tmp3 ); break; } } } SpecialFclose( &gf ); AppendingFlag = FALSE; return( CSFini() ); } /* PreProcess */
void GenExportLabel( instruction *lbl ) { GenLabel( lbl ); lbl->operand++; /* so it never gets deleted */ }