168 lines
7.1 KiB
Java
168 lines
7.1 KiB
Java
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));
|
||
}
|
||
}
|
||
}
|