265 lines
11 KiB
Java
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|