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

168 lines
7.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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));
}
}
}