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