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

265 lines
11 KiB
Java

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);
}
}