#include "def.h" #include #define YYSTYPE int //此行是为了包含parser.tab.hpp不引起错误而加,可以在后面使用相关常量 #include "parser.tab.hpp" string LoadFromMem(const string& Reg1, const Opn& opn, string Reg2) { string load; if (!(Reg2 != "$sp" || (Reg2 == "$sp" && opn.isGolbal == 0))) Reg2 = "$gp"; load = " lw " + Reg1 + ", " + to_string(opn.Offset) + "(" + Reg2 + ")"; return load; } string LoadFromMem(const string& Reg1, const Opn& opn1, const Opn& opn2, string Reg2) { string load; if (!(Reg2 != "$sp" || (Reg2 == "$sp" && opn1.isGolbal == 0))) Reg2 = "$gp"; load = " lw $t4, " + to_string(opn2.Offset) + "(" + "$sp" + ")\n" + " add " + Reg2 + ", " + Reg2 + ", " + "$t4\n" + " lw " + Reg1 + ", " + to_string(opn1.Offset) + "(" + Reg2 + ")\n" + " sub " + Reg2 + ", " + Reg2 + ", $t4"; return load; } string StoreToMem(const string& Reg1, const Opn& opn, string Reg2) { string store; if (!(Reg2 != "$sp" || (Reg2 == "$sp" && opn.isGolbal == 0))) Reg2 = "$gp"; store = " sw " + Reg1 + ", " + to_string(opn.Offset) + "(" + Reg2 + ")"; return store; } string StoreToMem(const string& Reg1, const Opn& opn1, const Opn& opn2, string Reg2) { string store; if (!(Reg2 != "$sp" || (Reg2 == "$sp" && opn1.isGolbal == 0))) Reg2 = "$gp"; store = " lw $t4, " + to_string(opn2.Offset) + "(" + "$sp" + ")\n" + " add " + Reg2 + ", " + Reg2 + ", " + "$t4\n" + " sw " + Reg1 + ", " + to_string(opn1.Offset) + "(" + Reg2 + ")\n" + " sub " + Reg2 + ", " + Reg2 + ", $t4"; return store; } void GenObject(list IRCodes) { fstream ObjectFile; ObjectFile.open("ObjectFile.s", ios::out); /*预先给出read和write的目标代码*/ ObjectFile << ".data\n"; ObjectFile << "_Prompt: .asciiz \"Enter an integer: \"\n"; ObjectFile << "_ret: .asciiz \"\\n\"\n"; ObjectFile << ".globl main\n"; ObjectFile << ".text\n\n"; ObjectFile << "read:\n"; ObjectFile << " li $v0,4\n"; ObjectFile << " la $a0,_Prompt\n"; ObjectFile << " syscall\n"; ObjectFile << " li $v0,5\n"; ObjectFile << " syscall\n"; ObjectFile << " jr $ra\n\n"; ObjectFile << "write:\n"; ObjectFile << " li $v0,1\n"; ObjectFile << " syscall\n"; ObjectFile << " li $v0,4\n"; ObjectFile << " la $a0,_ret\n"; ObjectFile << " syscall\n"; ObjectFile << " move $v0,$0\n"; ObjectFile << " jr $ra\n"; for (auto it = IRCodes.begin(); it != IRCodes.end(); it++) { switch (it->Op) { case ASSIGN: if (it->Opn1.Name == string("_CONST")) //这里只考虑了整常数 ObjectFile << " li $t1, " << it->Opn1.constINT << endl; else //这里只考虑了简单变量,数组则需要扩充 ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << StoreToMem("$t1", it->Result, "$sp") << endl; break; case ARRLOAD: ObjectFile << LoadFromMem("$t1", it->Opn1, it->Opn2, "$sp") << endl; ObjectFile << StoreToMem("$t1", it->Result, "$sp") << endl; break; case ARRASSIGN: ObjectFile << LoadFromMem("$t1", it->Opn2, "$sp") << endl; ObjectFile << StoreToMem("$t1", it->Result, it->Opn1, "$sp") << endl; break; case PLUS: case MINUS: case STAR: case DIV: case MOD: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << LoadFromMem("$t2", it->Opn2, "$sp") << endl; if (it->Op == PLUS) ObjectFile << " add $t3,$t1,$t2" << endl; else if (it->Op == MINUS) ObjectFile << " sub $t3,$t1,$t2" << endl; else if (it->Op == STAR) ObjectFile << " mul $t3,$t1,$t2" << endl; else if (it->Op == DIV) { ObjectFile << " div $t1, $t2" << endl; ObjectFile << " mflo $t3" << endl; } else { ObjectFile << " div $t1, $t2" << endl; ObjectFile << " mfhi $t3" << endl; } ObjectFile << StoreToMem("$t3", it->Result, "$sp") << endl; break; case AND: case OR: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << " sne $t1, $t1, $zero" << endl; ObjectFile << LoadFromMem("$t2", it->Opn2, "$sp") << endl; ObjectFile << " sne $t2, $t2, $zero" << endl; if (it->Op == AND) ObjectFile << " and $t3,$t1,$t2" << endl; else if (it->Op == OR) ObjectFile << " or $t3,$t1,$t2" << endl; ObjectFile << StoreToMem("$t3", it->Result, "$sp") << endl; break; case NOT: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << " sne $t1, $t1, $zero" << endl; ObjectFile << " seq $t1, $t1, $zero" << endl; ObjectFile << StoreToMem("$t1", it->Result, "$sp") << endl; break; case DPLUS: case DMINUS: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; if (it->Op == DPLUS) ObjectFile << " addi $t3,$t1,1" << endl; else if (it->Op == DMINUS) ObjectFile << " addi $t3,$t1,-1" << endl; ObjectFile << StoreToMem("$t3", it->Opn1, "$sp") << endl; ObjectFile << StoreToMem("$t3", it->Result, "$sp") << endl; break; case PLUSD: case MINUSD: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << StoreToMem("$t1", it->Result, "$sp") << endl; if (it->Op == PLUSD) ObjectFile << " addi $t3,$t1,1" << endl; else if (it->Op == MINUSD) ObjectFile << " addi $t3,$t1,-1" << endl; ObjectFile << StoreToMem("$t3", it->Opn1, "$sp") << endl; break; case UMINUS: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << " li $t2,-1" << endl; ObjectFile << " mul $t3,$t1,$t2" << endl; ObjectFile << StoreToMem("$t3", it->Result, "$sp") << endl; break; case ARRDPLUS: case ARRDMINUS: ObjectFile << LoadFromMem("$t1", it->Opn1, it->Opn2, "$sp") << endl; if (it->Op == ARRDPLUS) ObjectFile << " addi $t3,$t1,1" << endl; else if (it->Op == ARRDMINUS) ObjectFile << " addi $t3,$t1,-1" << endl; ObjectFile << StoreToMem("$t3", it->Opn1, it->Opn2, "$sp") << endl; ObjectFile << StoreToMem("$t3", it->Result, "$sp") << endl; break; case ARRPLUSD: case ARRMINUSD: ObjectFile << LoadFromMem("$t1", it->Opn1, it->Opn2, "$sp") << endl; ObjectFile << StoreToMem("$t1", it->Result, "$sp") << endl; if (it->Op == ARRPLUSD) ObjectFile << " addi $t3,$t1,1" << endl; else if (it->Op == ARRMINUSD) ObjectFile << " addi $t3,$t1,-1" << endl; ObjectFile << StoreToMem("$t3", it->Opn1, it->Opn2, "$sp") << endl; break; case RETURN: ObjectFile << LoadFromMem("$v0", it->Result, "$sp") << endl; ObjectFile << " jr $ra" << endl; break; case FUNCTION: ObjectFile << "\n" << it->Result.Name << ":\n"; if (it->Result.Name == string("main")) //特殊处理main ObjectFile << " addi $sp, $sp, -" << it->Result.Offset << endl; break; case PARAM: break; //直接跳到后面一条 case ARG: break; //直接跳到后面一条,直到函数调用,回头提取实参值,传送到形参单元。 case LABEL: ObjectFile << it->Result.Name << ":" << endl; break; case GOTO: ObjectFile << " j " << it->Result.Name << endl; break; case END: ObjectFile << " li $v0,10\n syscall" << endl; break; case JLE: case JLT: case JGE: case JGT: case JEQ: case JNE: ObjectFile << LoadFromMem("$t1", it->Opn1, "$sp") << endl; ObjectFile << LoadFromMem("$t2", it->Opn2, "$sp") << endl; if (it->Op == JLE) ObjectFile << " ble $t1,$t2," << it->Result.Name << endl; else if (it->Op == JLT) ObjectFile << " blt $t1,$t2," << it->Result.Name << endl; else if (it->Op == JGE) ObjectFile << " bge $t1,$t2," << it->Result.Name << endl; else if (it->Op == JGT) ObjectFile << " bgt $t1,$t2," << it->Result.Name << endl; else if (it->Op == JEQ) ObjectFile << " beq $t1,$t2," << it->Result.Name << endl; else ObjectFile << " bne $t1,$t2," << it->Result.Name << endl; break; case CALL: case CALL0: auto it0 = it; it0--; //it0指向前面可能的ARG if (it->Opn1.Name == string("read"))//特殊处理read { ObjectFile << " addi $sp, $sp, -4\n"; ObjectFile << " sw $ra,0($sp)\n"; //保留返回地址 ObjectFile << " jal read\n"; //保留返回地址 ObjectFile << " lw $ra,0($sp)\n"; //恢复返回地址 ObjectFile << " addi $sp, $sp, 4\n"; ObjectFile << StoreToMem("$v0", it->Result, "$sp") << endl; break; } if (it->Opn1.Name == string("write"))//特殊处理write { ObjectFile << LoadFromMem("$a0", it0->Result, "$sp") << endl; //前面ARG的偏移量 ObjectFile << " addi $sp, $sp, -4\n"; ObjectFile << " sw $ra,0($sp)\n"; ObjectFile << " jal write\n"; ObjectFile << " lw $ra,0($sp)\n"; ObjectFile << " addi $sp, $sp, 4\n"; break; } ObjectFile << " move $t0,$sp" << endl; //保存当前函数的sp到$t0中,为了取实参表达式的值 ObjectFile << " addi $sp, $sp, -" << static_cast (it->Opn1.SymPtr)->ARSize << endl; //开活动记录空间 ObjectFile << " sw $ra,0($sp)" << endl; //保留返回地址 while (it0->Op == ARG) //依次取参数值传递到形参单元中 { //将原栈帧的偏移it0->Result.Offset数据取出,送到新栈帧的it0->Opn1.Offset ObjectFile << LoadFromMem("$t1", it0->Result, "$t0") << endl; ObjectFile << StoreToMem("$t1", it0->Opn1, "$sp") << endl; it0--; } ObjectFile << " jal " << it->Opn1.Name << endl; //跳转到被调用函数 ObjectFile << " lw $ra,0($sp)" << endl; //恢复返回地址 ObjectFile << " addi $sp,$sp," << ((FuncSymbol *) (it->Opn1.SymPtr))->ARSize << endl; //释放活动记录空间 ObjectFile << StoreToMem("$v0", it->Result, "$sp") << endl; //取返回值,如void函数,不需要取值 break; } } ObjectFile.close(); }