You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

255 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "def.h"
#include <fstream>
#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 <IRCode> 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 <FuncSymbol *>(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();
}