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 constDefs = constDecl.GetConstDefs(); for (ConstDef constDef : constDefs) { visitConstDef(constDef); } } public static void visitVarDecl(VarDecl varDecl) { ArrayList 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 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 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 valueList = symbol.getValueList(); if (symbol instanceof ArraySymbol) { ArrayList 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)); } } }