272 lines
12 KiB
Java
272 lines
12 KiB
Java
package midend.visit;
|
||
|
||
import java.util.ArrayList;
|
||
|
||
import frontend.ast.block.Block;
|
||
import frontend.ast.block.ForStmt;
|
||
import frontend.ast.block.Stmt;
|
||
import frontend.ast.exp.Cond;
|
||
import frontend.ast.exp.Exp;
|
||
import frontend.ast.exp.LVal;
|
||
import frontend.ast.token.TokenNode;
|
||
import frontend.lexer.Token;
|
||
import midend.symbol.SymbolManager;
|
||
import midend.llvm.IrBuilder;
|
||
import midend.llvm.constant.IrConstantStr;
|
||
import midend.llvm.instr.GetIntInstr;
|
||
import midend.llvm.instr.JumpInstr;
|
||
import midend.llvm.instr.PutIntInstr;
|
||
import midend.llvm.instr.PutStrInstr;
|
||
import midend.llvm.instr.ReturnInstr;
|
||
import midend.llvm.instr.StoreInstr;
|
||
import midend.llvm.type.IrInterType;
|
||
import midend.llvm.type.IrType;
|
||
import midend.llvm.value.IrBasicBlock;
|
||
import midend.llvm.value.IrValue;
|
||
import midend.llvm.value.IrLoop;
|
||
|
||
public class VisitorStmt {
|
||
public static void visitStmt(Stmt stmt) {
|
||
if (stmt.getChild(0) instanceof LVal) {
|
||
visitAssign(stmt);
|
||
} else if (stmt.getChild(0) instanceof Exp
|
||
|| (stmt.getChild(0) instanceof TokenNode
|
||
&& ((TokenNode) stmt.getChild(0)).getValue().equals(";"))) {
|
||
visitExp(stmt);
|
||
} else if (stmt.getChild(0) instanceof Block) {
|
||
visitBlock(stmt);
|
||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("if")) {
|
||
visitIf(stmt);
|
||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("for")) {
|
||
visitFor(stmt);
|
||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("break")) {
|
||
visitBreak(stmt);
|
||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("continue")) {
|
||
visitContinue(stmt);
|
||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("return")) {
|
||
visitReturn(stmt);
|
||
} else {
|
||
visitPrintf(stmt);
|
||
}
|
||
}
|
||
|
||
public static void visitBlock(Stmt stmt) {
|
||
Block block = (Block) stmt.getChild(0);
|
||
VisitorBlock.visitBlock(block);
|
||
}
|
||
|
||
public static void visitExp(Stmt stmt) {
|
||
if (stmt.getChild(0) instanceof Exp) {
|
||
VisitorExp.visitExp((Exp) stmt.getChild(0));
|
||
}
|
||
}
|
||
|
||
public static void visitAssign(Stmt stmt) {
|
||
if (!stmt.isGetint()) {
|
||
LVal lval = (LVal) stmt.getChild(0);
|
||
Exp exp = (Exp) stmt.getChild(2);
|
||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||
IrValue expIr = VisitorExp.visitExp(exp);
|
||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||
IrBuilder.addInstr(storeInstr);
|
||
} else {
|
||
LVal lval = (LVal) stmt.getChild(0);
|
||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||
GetIntInstr getIntInstr = new GetIntInstr(IrBuilder.getLocalName());
|
||
IrBuilder.addInstr(getIntInstr);
|
||
StoreInstr storeInstr = new StoreInstr(getIntInstr, lvalIr);
|
||
IrBuilder.addInstr(storeInstr);
|
||
}
|
||
}
|
||
|
||
public static void visitPrintf(Stmt stmt) {
|
||
// System.out.println(((TokenNode)stmt.getChild(0)).getValue());//TODO:debug
|
||
String strconst = ((TokenNode) stmt.getChild(2)).getValue();
|
||
ArrayList<Exp> expList = stmt.getExpList();
|
||
ArrayList<IrValue> expIrList = new ArrayList<>();
|
||
for (Exp exp : expList) {
|
||
expIrList.add(VisitorExp.visitExp(exp));
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
int expnum = 0;
|
||
ArrayList<IrValue> printValue = new ArrayList<>();
|
||
for (int i = 0; i < strconst.length(); i++) {
|
||
if (strconst.charAt(i) == '%') {
|
||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||
// System.out.println(sb.toString());//TODO:debug
|
||
if (str == null) {
|
||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||
IrBuilder.addNewStr(str);
|
||
}
|
||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||
// IrBuilder.addInstr(putStrInstr);
|
||
sb.setLength(0);
|
||
} else if (sb.toString().equals("\"")) {
|
||
sb.setLength(0);
|
||
}
|
||
IrValue expIr = expIrList.get(expnum++);
|
||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||
printValue.add(expIr); // 修改为到最后统一输出,而不是立即输出
|
||
// PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), expIr);
|
||
// IrBuilder.addInstr(putIntInstr);
|
||
i++;
|
||
} else {
|
||
sb.append(strconst.charAt(i));
|
||
}
|
||
}
|
||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||
// System.out.println(sb.toString());//TODO:debug
|
||
if (str == null) {
|
||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||
IrBuilder.addNewStr(str);
|
||
}
|
||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||
// IrBuilder.addInstr(putStrInstr);
|
||
sb.setLength(0);
|
||
}
|
||
for (IrValue irValue : printValue) {
|
||
if (irValue instanceof IrConstantStr) {
|
||
PutStrInstr putStrInstr = new PutStrInstr(
|
||
IrBuilder.getLocalName(), (IrConstantStr) irValue);
|
||
IrBuilder.addInstr(putStrInstr);
|
||
} else {
|
||
PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), irValue);
|
||
IrBuilder.addInstr(putIntInstr);
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void visitReturn(Stmt stmt) {
|
||
IrValue retValue = null;
|
||
if (stmt.getChild(1) instanceof Exp) {
|
||
retValue = VisitorExp.visitExp((Exp) stmt.getChild(1));
|
||
retValue = IrType.convertType(retValue, IrInterType.INT32);
|
||
}
|
||
ReturnInstr returnInstr = new ReturnInstr(retValue);
|
||
IrBuilder.addInstr(returnInstr);
|
||
}
|
||
|
||
public static void visitIf(Stmt stmt) {
|
||
Cond cond = (Cond) stmt.getChild(2);
|
||
Stmt ifStmt = (Stmt) stmt.getChild(4);
|
||
if (stmt.getChildren().size() == 7) {
|
||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(ifBlock);
|
||
IrBasicBlock elseBlock = new IrBasicBlock(
|
||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(elseBlock);
|
||
VisitorExp.visitCond(cond, ifBlock, elseBlock);
|
||
// ifblock解析
|
||
IrBuilder.setCurrentBBlock(ifBlock);
|
||
VisitorStmt.visitStmt(ifStmt);
|
||
IrBasicBlock followBlock = new IrBasicBlock(
|
||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(followBlock);
|
||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
//elseblock解析
|
||
IrBuilder.setCurrentBBlock(elseBlock);
|
||
Stmt elseStmt = (Stmt) stmt.getChild(6);
|
||
VisitorStmt.visitStmt(elseStmt);
|
||
jumpInstr = new JumpInstr(followBlock);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
//跳转至followblock
|
||
IrBuilder.setCurrentBBlock(followBlock);
|
||
} else {
|
||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(ifBlock);
|
||
IrBasicBlock followBlock = new IrBasicBlock(
|
||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(followBlock);
|
||
VisitorExp.visitCond(cond, ifBlock, followBlock);
|
||
IrBuilder.setCurrentBBlock(ifBlock);
|
||
VisitorStmt.visitStmt(ifStmt);
|
||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
//跳转至followblock
|
||
IrBuilder.setCurrentBBlock(followBlock);
|
||
}
|
||
}
|
||
|
||
public static void visitFor(Stmt stmt) {
|
||
IrBasicBlock condBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||
IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(condBB);
|
||
IrBasicBlock bodyBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||
IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(bodyBB);
|
||
IrBasicBlock stepBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||
IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(stepBB);
|
||
IrBasicBlock followBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||
IrBuilder.getCurrentFunc());
|
||
IrBuilder.addNewBB(followBB);
|
||
IrLoop loop = new IrLoop(condBB, bodyBB, stepBB, followBB);
|
||
IrBuilder.pushLoop(loop);
|
||
ForStmt initStmt = stmt.getinitStmt();
|
||
if (initStmt != null) {
|
||
VisitorStmt.visitForStmt(initStmt);
|
||
}
|
||
JumpInstr jumpInstr = new JumpInstr(condBB);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
IrBuilder.setCurrentBBlock(condBB);
|
||
Cond cond = stmt.getCond();
|
||
if (cond != null) {
|
||
VisitorExp.visitCond(cond, bodyBB, followBB);
|
||
} else {
|
||
JumpInstr jumpBody = new JumpInstr(bodyBB);
|
||
IrBuilder.addInstr(jumpBody);
|
||
}
|
||
IrBuilder.setCurrentBBlock(bodyBB);
|
||
Stmt bodyStmt = stmt.getBodyStmt();
|
||
VisitorStmt.visitStmt(bodyStmt);
|
||
jumpInstr = new JumpInstr(stepBB);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
IrBuilder.setCurrentBBlock(stepBB);
|
||
ForStmt stepStmt = stmt.getStepStmt();
|
||
if (stepStmt != null) {
|
||
VisitorStmt.visitForStmt(stepStmt);
|
||
}
|
||
JumpInstr jumpCond = new JumpInstr(condBB);
|
||
IrBuilder.addInstr(jumpCond);
|
||
IrBuilder.popLoop();
|
||
IrBuilder.setCurrentBBlock(followBB);
|
||
} /*TODO:此处可能还有问题,循环体和条件、步长表达式等可能不在一个符号表,应该修改,应该比较好改,判断一下stmt是否为block再决定是否last
|
||
细想应该不用,如果body是一个block,那visit的时候符号表next,visit完之后符号表还会next,相当于再解析step的时候还是原来的符号表*/
|
||
|
||
public static void visitForStmt(ForStmt stmt) {
|
||
ArrayList<LVal> lvalList = stmt.getLValList();
|
||
ArrayList<Exp> expList = stmt.getExpList();
|
||
for (int i = 0; i < lvalList.size(); i++) {
|
||
LVal lval = lvalList.get(i);
|
||
Exp exp = expList.get(i);
|
||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||
IrValue expIr = VisitorExp.visitExp(exp);
|
||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||
IrBuilder.addInstr(storeInstr);
|
||
}
|
||
}
|
||
|
||
public static void visitBreak(Stmt stmt) {
|
||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||
IrBasicBlock followBB = loop.getFollowBB();
|
||
JumpInstr jumpInstr = new JumpInstr(followBB);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
}
|
||
|
||
public static void visitContinue(Stmt stmt) {
|
||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||
IrBasicBlock stepBB = loop.getStepBB();
|
||
JumpInstr jumpInstr = new JumpInstr(stepBB);
|
||
IrBuilder.addInstr(jumpInstr);
|
||
}
|
||
}
|