Files
MY_COMPILER/midend/visit/VisitorStmt.java
2025-12-10 17:58:17 +08:00

272 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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的时候符号表nextvisit完之后符号表还会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);
}
}