llvmir some opt

This commit is contained in:
邓智航
2025-12-10 17:58:17 +08:00
commit 84827838e2
103 changed files with 5838 additions and 0 deletions

36
midend/visit/Visitor.java Normal file
View File

@@ -0,0 +1,36 @@
package midend.visit;
import java.util.ArrayList;
import frontend.ast.CompUnit;
import frontend.ast.decl.Decl;
import frontend.ast.func.FuncDef;
import frontend.ast.func.MainFuncDef;
import midend.symbol.SymbolManager;
public class Visitor {
private CompUnit compUnit;
public Visitor(CompUnit compUnit) {
this.compUnit = compUnit;
SymbolManager.reset();
SymbolManager.nextTable();
}
public void visit() {
ArrayList<Decl> decls = this.compUnit.GetDecls();
ArrayList<FuncDef> funcDefs = this.compUnit.GetFuncDefs();
MainFuncDef mainFuncDef = this.compUnit.GetMainFuncDef();
for (Decl decl : decls) {
VisitorDecl.visitDecl(decl);
}
for (FuncDef funcDef : funcDefs) {
VisitorFuncDef.visitFuncDef(funcDef);
}
VisitorFuncDef.visitMainFuncDef(mainFuncDef);
}
//:TODO:符号表的变换,什么时候往前进一个符号表,这需要人工手工来操作
}

View File

@@ -0,0 +1,35 @@
package midend.visit;
import java.util.ArrayList;
import frontend.ast.block.Block;
import frontend.ast.block.BlockItem;
import frontend.ast.block.Stmt;
import frontend.ast.decl.Decl;
import midend.symbol.SymbolManager;
public class VisitorBlock {
public static void visitBlock(Block block) {
if (!block.isFuncBlock()) {
SymbolManager.nextTable();
}
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());
// System.out.println("bsequence: " + SymbolManager.getCurrentSequence());//TODO:debug
ArrayList<BlockItem> blockItems = block.getBlockItems();
for (BlockItem blockItem : blockItems) {
visitBlockItem(blockItem);
}
if (!block.isFuncBlock()) {
SymbolManager.nextTable();
}
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
}
public static void visitBlockItem(BlockItem blockItem) {
if (blockItem.getChild(0) instanceof Decl) {
VisitorDecl.visitDecl((Decl) blockItem.getChild(0));
} else {
VisitorStmt.visitStmt((Stmt) blockItem.getChild(0));
}
}
}

View File

@@ -0,0 +1,167 @@
package midend.visit;
import java.util.ArrayList;
import frontend.ast.decl.ConstDecl;
import frontend.ast.decl.ConstDef;
import frontend.ast.decl.Decl;
import frontend.ast.decl.VarDecl;
import frontend.ast.decl.VarDef;
import frontend.ast.exp.ConstExp;
import frontend.ast.exp.Exp;
import frontend.ast.token.TokenNode;
import frontend.lexer.Token;
import midend.llvm.IrBuilder;
import midend.llvm.constant.IrConstant;
import midend.llvm.constant.IrConstantArray;
import midend.llvm.constant.IrConstantInt;
import midend.llvm.instr.AllocateInstr;
import midend.llvm.instr.StoreInstr;
import midend.llvm.instr.GepInstr;
import midend.llvm.type.IrArrayType;
import midend.llvm.type.IrFuncType;
import midend.llvm.type.IrInterType;
import midend.llvm.type.IrPointerType;
import midend.llvm.type.IrType;
import midend.llvm.value.IrGlobalValue;
import midend.llvm.value.IrValue;
import midend.symbol.SymbolType;
import midend.symbol.ArraySymbol;
import midend.symbol.Symbol;
import midend.symbol.SymbolManager;
public class VisitorDecl {
public static void visitDecl(Decl decl) {
if (decl.getChild(0) instanceof ConstDecl) {
visitConstDecl((ConstDecl) decl.getChild(0));
} else {
visitVarDecl((VarDecl) decl.getChild(0));
}
}
public static void visitConstDecl(ConstDecl constDecl) {
ArrayList<ConstDef> constDefs = constDecl.GetConstDefs();
for (ConstDef constDef : constDefs) {
visitConstDef(constDef);
}
}
public static void visitVarDecl(VarDecl varDecl) {
ArrayList<VarDef> varDefs = varDecl.GetVarDefs();
for (VarDef varDef : varDefs) {
visitVarDef(varDef);
}
}
public static void visitConstDef(ConstDef constDef) {
Symbol symbol = SymbolManager.getSymbol(((TokenNode) constDef.getChild(0)).getValue());
if (SymbolManager.IsGlobal()) { // 全局变量下直接声明
IrGlobalValue irGlobalValue = new IrGlobalValue(
new IrPointerType(getSymbolIrType(symbol)),
IrBuilder.getGlobalName(), true, getSymbolIrConst(symbol));
IrBuilder.addNewGlobal(irGlobalValue);
symbol.setIrValue(irGlobalValue);
} else { // 局部变量需要分配地址再存值
AllocateInstr allocateInstr = new AllocateInstr(getSymbolIrType(symbol),
IrBuilder.getLocalName());
IrBuilder.addInstr(allocateInstr);
symbol.setIrValue(allocateInstr);
ArrayList<Integer> valueList = symbol.getValueList();
if (!(symbol instanceof ArraySymbol)) {
StoreInstr storeInstr = new StoreInstr(getSymbolIrConst(symbol),
allocateInstr);
IrBuilder.addInstr(storeInstr);
} else {
for (int i = 0; i < valueList.size(); i++) {
GepInstr gepInstr = new GepInstr(allocateInstr,
new IrConstantInt(i), IrBuilder.getLocalName());
IrBuilder.addInstr(gepInstr);
IrValue initValue = new IrConstantInt(valueList.get(i));
StoreInstr storeInstr = new StoreInstr(initValue, gepInstr);
IrBuilder.addInstr(storeInstr);
}
}
}
}
private static void visitVarDef(VarDef varDef) {
Symbol symbol = SymbolManager.getSymbol(((TokenNode) varDef.getChild(0)).getValue());
if (SymbolManager.IsGlobal()) {
IrGlobalValue irGlobalValue = new IrGlobalValue(
new IrPointerType(getSymbolIrType(symbol)),
IrBuilder.getGlobalName(), false, getSymbolIrConst(symbol));
IrBuilder.addNewGlobal(irGlobalValue);
symbol.setIrValue(irGlobalValue);
} else { // Think:static修饰的变量该如何实现
visitLocalVarDef(varDef, symbol);
}
}
private static void visitLocalVarDef(VarDef varDef, Symbol symbol) {
if (symbol.getType().equals(SymbolType.STATIC_INT) ||
symbol.getType().equals(SymbolType.STATIC_INT_ARRAY)) {
// 当为局部变量且为static修饰的变量的时候将其作为全局变量处理
IrGlobalValue irGlobalValue = new IrGlobalValue(
new IrPointerType(getSymbolIrType(symbol)),
IrBuilder.getGlobalName(), false, getSymbolIrConst(symbol));
IrBuilder.addNewGlobal(irGlobalValue);
symbol.setIrValue(irGlobalValue);
return;
}
AllocateInstr allocateInstr = new AllocateInstr(
getSymbolIrType(symbol), IrBuilder.getLocalName());
IrBuilder.addInstr(allocateInstr);
if (!(symbol instanceof ArraySymbol)) { // 非数组变量
if (varDef.HaveInitVal()) {
Exp exp = varDef.getInitVal().getExpList().get(0);
IrValue irExp = VisitorExp.visitExp(exp);
StoreInstr storeInstr = new StoreInstr(irExp, allocateInstr);
IrBuilder.addInstr(storeInstr);
}
} else { // 数组变量
if (varDef.HaveInitVal()) {
ArrayList<Exp> expList = varDef.getInitVal().getExpList();
for (int i = 0; i < expList.size(); i++) {
IrValue irExp = VisitorExp.visitExp(expList.get(i));
irExp = IrType.convertType(irExp, IrInterType.INT32);
GepInstr gepInstr = new GepInstr(allocateInstr,
new IrConstantInt(i), IrBuilder.getLocalName());
IrBuilder.addInstr(gepInstr);
StoreInstr storeInstr = new StoreInstr(irExp, gepInstr);
IrBuilder.addInstr(storeInstr);
}
}
}
symbol.setIrValue(allocateInstr);
}
public static IrType getSymbolIrType(Symbol symbol) {
SymbolType st = symbol.getType();
if (st.equals(SymbolType.INT) || st.equals(SymbolType.CONST_INT)
|| st.equals(SymbolType.STATIC_INT)) {
return IrInterType.INT32;
} else if (st.equals(SymbolType.INT_ARRAY) || st.equals(SymbolType.CONST_INT_ARRAY)
|| st.equals(SymbolType.STATIC_INT_ARRAY)) {
return new IrArrayType(IrInterType.INT32, ((ArraySymbol) symbol).getDim());
} else {
if (st.equals(SymbolType.INT_FUNC)) {
return new IrFuncType(IrInterType.INT32);
} else {
return new IrFuncType(IrInterType.VOID);
}
}
}
public static IrConstant getSymbolIrConst(Symbol symbol) {
ArrayList<Integer> valueList = symbol.getValueList();
if (symbol instanceof ArraySymbol) {
ArrayList<IrConstant> elements = new ArrayList<>();
for (int i = 0; i < valueList.size(); i++) {
elements.add(new IrConstantInt(valueList.get(i)));
}
return new IrConstantArray(symbol.getName(), elements, ((ArraySymbol) symbol).getDim());
} else {
return valueList.isEmpty() ? new IrConstantInt(0) : new IrConstantInt(valueList.get(0));
}
}
}

View File

@@ -0,0 +1,264 @@
package midend.visit;
import frontend.ast.exp.Exp;
import frontend.ast.exp.LAndExp;
import frontend.ast.exp.LOrExp;
import frontend.ast.exp.LVal;
import java.util.ArrayList;
import frontend.ast.exp.AddExp;
import frontend.ast.exp.EqExp;
import frontend.ast.exp.MulExp;
import frontend.ast.exp.NumberExp;
import frontend.ast.exp.PrimaryExp;
import frontend.ast.exp.RelExp;
import frontend.ast.exp.UnaryExp;
import frontend.ast.exp.UnaryOp;
import frontend.ast.exp.Cond;
import frontend.ast.token.TokenNode;
import midend.llvm.IrBuilder;
import midend.llvm.constant.IrConstantInt;
import midend.llvm.instr.AluInstr;
import midend.llvm.instr.BranchInstr;
import midend.llvm.instr.CallInstr;
import midend.llvm.instr.CmpInstr;
import midend.llvm.instr.ExtendInstr;
import midend.llvm.instr.GepInstr;
import midend.llvm.instr.GetIntInstr;
import midend.llvm.instr.LoadInstr;
import midend.llvm.type.IrInterType;
import midend.llvm.type.IrType;
import midend.llvm.value.IrBasicBlock;
import midend.llvm.value.IrFuncValue;
import midend.llvm.value.IrValue;
import midend.symbol.*;
public class VisitorExp {
public static IrValue visitExp(Exp exp) {
return visitAddExp((AddExp) exp.getChild(0));
}
public static IrValue visitAddExp(AddExp addExp) {
if (addExp.getChildren().size() == 1) {
return visitMulExp((MulExp) addExp.getChild(0));
} else {
IrValue left = visitAddExp((AddExp) addExp.getChild(0));
TokenNode op = (TokenNode) addExp.getChild(1);
IrValue right = visitMulExp((MulExp) addExp.getChild(2));
left = IrType.convertType(left, IrInterType.INT32);
right = IrType.convertType(right, IrInterType.INT32);
AluInstr aluInstr = new AluInstr(IrBuilder.getLocalName(), op.getValue(), left, right);
IrBuilder.addInstr(aluInstr);
return aluInstr;
}
}
public static IrValue visitMulExp(MulExp mulExp) {
if (mulExp.getChildren().size() == 1) {
return visitUnaryExp((UnaryExp) mulExp.getChild(0));
} else {
IrValue left = visitMulExp((MulExp) mulExp.getChild(0));
TokenNode op = (TokenNode) mulExp.getChild(1);
IrValue right = visitUnaryExp((UnaryExp) mulExp.getChild(2));
left = IrType.convertType(left, IrInterType.INT32);
right = IrType.convertType(right, IrInterType.INT32);
AluInstr aluInstr = new AluInstr(IrBuilder.getLocalName(), op.getValue(), left, right);
IrBuilder.addInstr(aluInstr);
return aluInstr;
}
}
public static IrValue visitUnaryExp(UnaryExp unaryExp) {
if (unaryExp.getChild(0) instanceof PrimaryExp) {
return visitPrimaryExp((PrimaryExp) unaryExp.getChild(0));
} else if (unaryExp.getChild(0) instanceof TokenNode) {
return visitFuncCall((TokenNode) unaryExp.getChild(0), unaryExp.getParamList());
} else {
return visitOpUnaryExp((UnaryOp) unaryExp.getChild(0), (UnaryExp) unaryExp.getChild(1));
}
}
public static IrValue visitOpUnaryExp(UnaryOp uop, UnaryExp unaryExp) {
String op = ((TokenNode) uop.getChild(0)).getValue();
IrValue operand = visitUnaryExp(unaryExp);
IrConstantInt zero = new IrConstantInt(0);
if (op.equals("+")) {
return operand;
} else if (op.equals("-")) {
AluInstr aluInstr = new AluInstr(IrBuilder.getLocalName(), op, zero, operand);
IrBuilder.addInstr(aluInstr);
return aluInstr;
} else {
operand = IrType.convertType(operand, IrInterType.INT32);
CmpInstr cmpInstr = new CmpInstr(IrBuilder.getLocalName(), "==", zero, operand);
IrBuilder.addInstr(cmpInstr);
ExtendInstr extendInstr = new ExtendInstr(
IrBuilder.getLocalName(), IrInterType.INT32, cmpInstr);
IrBuilder.addInstr(extendInstr);
return extendInstr;
}
}
public static IrValue visitPrimaryExp(PrimaryExp primaryExp) {
if (primaryExp.getChild(0) instanceof TokenNode) {
return visitExp((Exp) primaryExp.getChild(1));
} else if (primaryExp.getChild(0) instanceof LVal) {
return visitLVal((LVal) primaryExp.getChild(0), false);
} else {
return new IrConstantInt(((NumberExp) primaryExp.getChild(0)).getValue());
}
}
public static IrValue visitFuncCall(TokenNode funcName, ArrayList<Exp> paramList) {
if (funcName.getValue().equals("getint")) {
GetIntInstr getIntInstr = new GetIntInstr(IrBuilder.getLocalName());
IrBuilder.addInstr(getIntInstr);
return getIntInstr;
}
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(funcName.getName(), true);
IrFuncValue irFunction = (IrFuncValue) funcSymbol.getIrValue();
ArrayList<IrValue> args = new ArrayList<>();
for (Exp param : paramList) {
args.add(visitExp(param));
}
CallInstr callInstr = new CallInstr(IrBuilder.getLocalName(), irFunction, args);
IrBuilder.addInstr(callInstr);
return callInstr;
}
public static IrValue visitLVal(LVal lval, boolean assign) {
if (assign) {
Symbol symbol = SymbolManager.getSymbol(((TokenNode) lval.getChild(0)).getName(), true);
if (!(symbol instanceof ArraySymbol)) {
return symbol.getIrValue();
} else {
Exp exp = (Exp) lval.getChild(2);
IrValue pointer = symbol.getIrValue();
GepInstr gepInstr = new GepInstr(
pointer, visitExp(exp), IrBuilder.getLocalName());
IrBuilder.addInstr(gepInstr);
return gepInstr;
}
} else {
Symbol symbol = SymbolManager.getSymbol(((TokenNode) lval.getChild(0)).getName(), true);
// if (symbol == null) {
// System.out.println(((TokenNode)lval.getChild(0)).getLine() + " " +
// ((TokenNode)lval.getChild(0)).getValue());
// SymbolTable table = SymbolManager.getCurrentTable();
// System.out.println(table.toString());
// // TODO:报错
// }
if (!(symbol instanceof ArraySymbol)) {
LoadInstr loadInstr = new LoadInstr(symbol.getIrValue(), IrBuilder.getLocalName());
IrBuilder.addInstr(loadInstr);
return loadInstr;
} else {
if (lval.getChildren().size() == 1) {
GepInstr gepInstr = new GepInstr(
symbol.getIrValue(), new IrConstantInt(0), IrBuilder.getLocalName());
IrBuilder.addInstr(gepInstr);
return gepInstr;
} else {
Exp exp = (Exp) lval.getChild(2);
GepInstr gepInstr = new GepInstr(
symbol.getIrValue(), visitExp(exp), IrBuilder.getLocalName());
IrBuilder.addInstr(gepInstr);
LoadInstr loadInstr = new LoadInstr(gepInstr, IrBuilder.getLocalName());
IrBuilder.addInstr(loadInstr);
return loadInstr;
}
}
}
}
// TODO:条件表达式的实现
public static IrValue visitRelExp(RelExp relExp) {
if (relExp.getChildren().size() == 1) {
return visitAddExp((AddExp) relExp.getChild(0));
} else {
IrValue left = visitRelExp((RelExp) relExp.getChild(0));
IrValue right = visitAddExp((AddExp) relExp.getChild(2));
String op = ((TokenNode) relExp.getChild(1)).getValue();
left = IrType.convertType(left, IrInterType.INT32);
right = IrType.convertType(right, IrInterType.INT32);
CmpInstr cmpInstr = new CmpInstr(IrBuilder.getLocalName(), op, left, right);
IrBuilder.addInstr(cmpInstr);
return cmpInstr;
}
}
public static IrValue visitEqExp(EqExp eqExp) {
if (eqExp.getChildren().size() == 1) {
return visitRelExp((RelExp) eqExp.getChild(0));
} else {
IrValue left = visitEqExp((EqExp) eqExp.getChild(0));
IrValue right = visitRelExp((RelExp) eqExp.getChild(2));
String op = ((TokenNode) eqExp.getChild(1)).getValue();
left = IrType.convertType(left, IrInterType.INT32);
right = IrType.convertType(right, IrInterType.INT32);
CmpInstr cmpInstr = new CmpInstr(IrBuilder.getLocalName(), op, left, right);
IrBuilder.addInstr(cmpInstr);
return cmpInstr;
}
}
public static IrValue visitLAndExp(LAndExp landExp,
IrBasicBlock trueBlock, IrBasicBlock falseBlock) {
if (landExp.getChildren().size() == 1) {
IrValue eqIrValue = visitEqExp((EqExp) landExp.getChild(0));
eqIrValue = IrType.convertType(eqIrValue, IrInterType.BOOL);
BranchInstr branchInstr = new BranchInstr(
IrBuilder.getLocalName(), eqIrValue, trueBlock, falseBlock);
IrBuilder.addInstr(branchInstr);
return eqIrValue;
} else {
IrBasicBlock nextBB = new IrBasicBlock(
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
IrBuilder.addNewBB(nextBB);
IrValue left = visitLAndExp((LAndExp) landExp.getChild(0), nextBB, falseBlock);
IrBuilder.setCurrentBBlock(nextBB);
IrValue right = visitEqExp((EqExp) landExp.getChild(2));
right = IrType.convertType(right, IrInterType.BOOL);
BranchInstr branchInstr2 = new BranchInstr(
IrBuilder.getLocalName(), right, trueBlock, falseBlock);
IrBuilder.addInstr(branchInstr2);
return right;
}
}
public static void visitLOrExp(LOrExp lorExp, IrBasicBlock trueBB, IrBasicBlock falseBB) {
if (lorExp.getChildren().size() == 1) {
IrValue landIrValue = visitLAndExp((LAndExp) lorExp.getChild(0), trueBB, falseBB);
} else {
IrBasicBlock nextBB = new IrBasicBlock(
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
IrBuilder.addNewBB(nextBB);
visitLOrExp((LOrExp) lorExp.getChild(0), trueBB, nextBB);
IrBuilder.setCurrentBBlock(nextBB);
IrValue right = visitLAndExp((LAndExp) lorExp.getChild(2), trueBB, falseBB);
}
}
public static void visitCond(Cond cond, IrBasicBlock trueBB, IrBasicBlock falseBB) {
visitLOrExp((LOrExp) cond.getChild(0), trueBB, falseBB);
}
}

View File

@@ -0,0 +1,80 @@
package midend.visit;
import java.util.ArrayList;
import frontend.ast.block.Block;
import frontend.ast.func.FuncDef;
import frontend.ast.func.MainFuncDef;
import frontend.ast.token.TokenNode;
import midend.llvm.IrBuilder;
import midend.llvm.instr.AllocateInstr;
import midend.llvm.instr.StoreInstr;
import midend.llvm.type.IrInterType;
import midend.llvm.type.IrPointerType;
import midend.llvm.value.IrFuncValue;
import midend.llvm.value.IrValue;
import midend.symbol.Symbol;
import midend.symbol.FuncSymbol;
import midend.symbol.SymbolManager;
public class VisitorFuncDef {
public static void visitFuncDef(FuncDef funcDef) {
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(
((TokenNode) funcDef.getChild(1)).getName());
IrInterType returnType = funcSymbol.getReturnType() == 1
? IrInterType.INT32
: IrInterType.VOID;
IrFuncValue funcValue = new IrFuncValue(
IrBuilder.geFuncName(funcSymbol.getName()), returnType);
IrBuilder.addNewFunc(funcValue);
funcSymbol.setIrValue(funcValue);
// 进入函数作用域
SymbolManager.nextTable();
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
ArrayList<Integer> paramList = funcSymbol.getParamList();
ArrayList<Symbol> paramSymbolList = funcSymbol.getParamSymbolList();
ArrayList<IrValue> irParamList = new ArrayList<>();
for (int i = 0; i < paramList.size(); i++) {
if (paramList.get(i) == 0) {
IrValue param = new IrValue(IrInterType.INT32, IrBuilder.getLocalName());
irParamList.add(param);
funcValue.addParam(param);
} else {
IrValue param = new IrValue(
new IrPointerType(IrInterType.INT32), IrBuilder.getLocalName());
irParamList.add(param);
funcValue.addParam(param);
paramSymbolList.get(i).setIrValue(param);
}
}
for (int i = 0; i < irParamList.size(); i++) {
if (paramList.get(i) == 1) {
continue; // 数组参数不分配内存
}
AllocateInstr allocateInstr = new AllocateInstr(
irParamList.get(i).getType(), IrBuilder.getLocalName());
IrBuilder.addInstr(allocateInstr);
StoreInstr storeInstr = new StoreInstr(irParamList.get(i), allocateInstr);
IrBuilder.addInstr(storeInstr);
paramSymbolList.get(i).setIrValue(allocateInstr);
} //这里貌似可以不用allocate?函数形参似乎可以直接拿来用?
Block block = (Block) funcDef.getChild(funcDef.getChildren().size() - 1);
VisitorBlock.visitBlock(block);
// TODO:check return?
funcValue.checkReturn();
SymbolManager.nextTable();
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
}
public static void visitMainFuncDef(MainFuncDef mainFuncDef) {
IrFuncValue mainFuncValue = new IrFuncValue(
IrBuilder.geFuncName("main"), IrInterType.INT32);
IrBuilder.addNewFunc(mainFuncValue);
SymbolManager.nextTable();
// System.out.println("(mainfunc)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
Block block = (Block) mainFuncDef.getChild(mainFuncDef.getChildren().size() - 1);
VisitorBlock.visitBlock(block);
SymbolManager.nextTable();
}
}

View File

@@ -0,0 +1,271 @@
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);
}
}