mips without optimize
This commit is contained in:
67
midend/Midend.java
Normal file → Executable file
67
midend/Midend.java
Normal file → Executable file
@@ -1,31 +1,36 @@
|
||||
package midend;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import frontend.ast.CompUnit;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.IrModule;
|
||||
import midend.visit.Visitor;
|
||||
|
||||
public class Midend {
|
||||
private IrModule module;
|
||||
private Visitor visitor;
|
||||
|
||||
public Midend(CompUnit compUnit) {
|
||||
this.module = new IrModule();
|
||||
this.visitor = new Visitor(compUnit);
|
||||
}
|
||||
|
||||
public void generateLLvmIr() {
|
||||
IrBuilder.setCurrentModule(module);
|
||||
visitor.visit();
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
Files.write(Paths.get(fileName), module.toString().getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import frontend.ast.CompUnit;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.IrModule;
|
||||
import midend.visit.Visitor;
|
||||
|
||||
public class Midend {
|
||||
private IrModule module;
|
||||
private Visitor visitor;
|
||||
|
||||
public Midend(CompUnit compUnit) {
|
||||
this.module = new IrModule();
|
||||
this.visitor = new Visitor(compUnit);
|
||||
}
|
||||
|
||||
public void generateLLvmIr() {
|
||||
IrBuilder.setCurrentModule(module);
|
||||
visitor.visit();
|
||||
}
|
||||
|
||||
public IrModule getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
Files.write(Paths.get(fileName), module.toString().getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
64
midend/errorhandle/ErrorHandler.java
Normal file → Executable file
64
midend/errorhandle/ErrorHandler.java
Normal file → Executable file
@@ -1,32 +1,32 @@
|
||||
package midend.errorhandle;
|
||||
|
||||
import frontend.ast.CompUnit;
|
||||
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
import error.Errors;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class ErrorHandler {
|
||||
private CompUnit compUnit;
|
||||
|
||||
public ErrorHandler(CompUnit compUnit) {
|
||||
this.compUnit = compUnit;
|
||||
SymbolManager.init();
|
||||
}
|
||||
|
||||
public void visit(Errors errors) {
|
||||
compUnit.fillSymbolTable(false, false, errors);
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
String info = SymbolManager.getSymbolTableInfo();
|
||||
Files.write(Paths.get(fileName), info.getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.errorhandle;
|
||||
|
||||
import frontend.ast.CompUnit;
|
||||
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
import error.Errors;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class ErrorHandler {
|
||||
private CompUnit compUnit;
|
||||
|
||||
public ErrorHandler(CompUnit compUnit) {
|
||||
this.compUnit = compUnit;
|
||||
SymbolManager.init();
|
||||
}
|
||||
|
||||
public void visit(Errors errors) {
|
||||
compUnit.fillSymbolTable(false, false, errors);
|
||||
}
|
||||
|
||||
public void writeToFile(String fileName) {
|
||||
try {
|
||||
String info = SymbolManager.getSymbolTableInfo();
|
||||
Files.write(Paths.get(fileName), info.getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
286
midend/llvm/IrBuilder.java
Normal file → Executable file
286
midend/llvm/IrBuilder.java
Normal file → Executable file
@@ -1,143 +1,143 @@
|
||||
package midend.llvm;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Stack;
|
||||
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrLoop;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.constant.IrConstant;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.instr.IrInstr;
|
||||
|
||||
public class IrBuilder {
|
||||
private static final String prebb = "b_";
|
||||
private static final String prestr = "@s_";
|
||||
private static final String prefunc = "@f_";
|
||||
private static final String preglobal = "@g_";
|
||||
private static final String prelocal = "%v_";
|
||||
|
||||
private static IrModule module = null;
|
||||
private static IrFuncValue currentFunc = null;
|
||||
private static IrBasicBlock currentBB = null;
|
||||
private static int strId = 0;
|
||||
private static int globalId = 0;
|
||||
private static int bblockId = 0;
|
||||
private static HashMap<IrFuncValue, Integer> funcIdMap = new HashMap<>(); // func, localId
|
||||
private static Stack<IrLoop> loopStack = new Stack<>();
|
||||
|
||||
public static void setCurrentModule(IrModule module) {
|
||||
IrBuilder.module = module;
|
||||
}
|
||||
|
||||
public static void addNewFunc(String name, IrType retType) {
|
||||
IrFuncValue func = new IrFuncValue(geFuncName(name), retType);
|
||||
module.addFunc(func);
|
||||
funcIdMap.put(func, 0);
|
||||
currentFunc = func;
|
||||
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||
func.addBBlock(entryBB);
|
||||
currentBB = entryBB;
|
||||
}
|
||||
|
||||
public static void addNewFunc(IrFuncValue func) {
|
||||
module.addFunc(func);
|
||||
funcIdMap.put(func, 0);
|
||||
currentFunc = func;
|
||||
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||
func.addBBlock(entryBB);
|
||||
currentBB = entryBB;
|
||||
}
|
||||
|
||||
public static void addNewBB() {
|
||||
IrBasicBlock bb = new IrBasicBlock(getBlockName(), currentFunc);
|
||||
currentFunc.addBBlock(bb);
|
||||
}
|
||||
|
||||
public static void addNewBB(IrBasicBlock bb) {
|
||||
currentFunc.addBBlock(bb);
|
||||
}
|
||||
|
||||
public static void setCurrentBBlock(IrBasicBlock bb) {
|
||||
currentBB = bb;
|
||||
}
|
||||
|
||||
public static void addNewGlobal(IrType type, boolean isConstant, IrConstant initVal) {
|
||||
IrGlobalValue global = new IrGlobalValue(type, getGlobalName(), isConstant, initVal);
|
||||
module.addGlobalVar(global);
|
||||
}
|
||||
|
||||
public static void addNewGlobal(IrGlobalValue global) {
|
||||
module.addGlobalVar(global);
|
||||
}
|
||||
|
||||
public static void addNewStr(String str) {
|
||||
if (module.containStr(str)) {
|
||||
return;
|
||||
}
|
||||
module.addStr(new IrConstantStr(str, getStrName()));
|
||||
}
|
||||
|
||||
public static void addNewStr(IrConstantStr str) {
|
||||
module.addStr(str);
|
||||
}
|
||||
|
||||
public static void addInstr(IrInstr instr) {
|
||||
currentBB.addInstr(instr);
|
||||
instr.setBBlock(currentBB);
|
||||
}
|
||||
|
||||
public static String geFuncName(String name) {
|
||||
return name.equals("main") ? "@main" : prefunc + name;
|
||||
}
|
||||
|
||||
public static String getBlockName() {
|
||||
return prebb + bblockId++;
|
||||
}
|
||||
|
||||
public static String getStrName() {
|
||||
return prestr + strId++;
|
||||
}
|
||||
|
||||
public static String getGlobalName() {
|
||||
return preglobal + globalId++;
|
||||
}
|
||||
|
||||
public static String getLocalName() {
|
||||
int id = funcIdMap.get(currentFunc);
|
||||
funcIdMap.put(currentFunc, id + 1);
|
||||
return prelocal + id;
|
||||
}
|
||||
|
||||
public static String getLocalName(IrFuncValue func) {
|
||||
int id = funcIdMap.get(func);
|
||||
funcIdMap.put(func, id + 1);
|
||||
return prelocal + id;
|
||||
}
|
||||
|
||||
public static IrModule getCurrentModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public static IrFuncValue getCurrentFunc() {
|
||||
return currentFunc;
|
||||
}
|
||||
|
||||
public static IrBasicBlock getCurrentBB() {
|
||||
return currentBB;
|
||||
}
|
||||
|
||||
public static void pushLoop(IrLoop loop) {
|
||||
loopStack.push(loop);
|
||||
}
|
||||
|
||||
public static IrLoop popLoop() {
|
||||
return loopStack.pop();
|
||||
}
|
||||
|
||||
public static IrLoop getCurrentLoop() {
|
||||
return loopStack.peek();
|
||||
}
|
||||
}
|
||||
package midend.llvm;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Stack;
|
||||
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrLoop;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.constant.IrConstant;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.instr.IrInstr;
|
||||
|
||||
public class IrBuilder {
|
||||
private static final String prebb = "b_";
|
||||
private static final String prestr = "@s_";
|
||||
private static final String prefunc = "@f_";
|
||||
private static final String preglobal = "@g_";
|
||||
private static final String prelocal = "%v_";
|
||||
|
||||
private static IrModule module = null;
|
||||
private static IrFuncValue currentFunc = null;
|
||||
private static IrBasicBlock currentBB = null;
|
||||
private static int strId = 0;
|
||||
private static int globalId = 0;
|
||||
private static int bblockId = 0;
|
||||
private static HashMap<IrFuncValue, Integer> funcIdMap = new HashMap<>(); // func, localId
|
||||
private static Stack<IrLoop> loopStack = new Stack<>();
|
||||
|
||||
public static void setCurrentModule(IrModule module) {
|
||||
IrBuilder.module = module;
|
||||
}
|
||||
|
||||
public static void addNewFunc(String name, IrType retType) {
|
||||
IrFuncValue func = new IrFuncValue(geFuncName(name), retType);
|
||||
module.addFunc(func);
|
||||
funcIdMap.put(func, 0);
|
||||
currentFunc = func;
|
||||
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||
func.addBBlock(entryBB);
|
||||
currentBB = entryBB;
|
||||
}
|
||||
|
||||
public static void addNewFunc(IrFuncValue func) {
|
||||
module.addFunc(func);
|
||||
funcIdMap.put(func, 0);
|
||||
currentFunc = func;
|
||||
IrBasicBlock entryBB = new IrBasicBlock(getBlockName(), func);
|
||||
func.addBBlock(entryBB);
|
||||
currentBB = entryBB;
|
||||
}
|
||||
|
||||
public static void addNewBB() {
|
||||
IrBasicBlock bb = new IrBasicBlock(getBlockName(), currentFunc);
|
||||
currentFunc.addBBlock(bb);
|
||||
}
|
||||
|
||||
public static void addNewBB(IrBasicBlock bb) {
|
||||
currentFunc.addBBlock(bb);
|
||||
}
|
||||
|
||||
public static void setCurrentBBlock(IrBasicBlock bb) {
|
||||
currentBB = bb;
|
||||
}
|
||||
|
||||
public static void addNewGlobal(IrType type, boolean isConstant, IrConstant initVal) {
|
||||
IrGlobalValue global = new IrGlobalValue(type, getGlobalName(), isConstant, initVal);
|
||||
module.addGlobalVar(global);
|
||||
}
|
||||
|
||||
public static void addNewGlobal(IrGlobalValue global) {
|
||||
module.addGlobalVar(global);
|
||||
}
|
||||
|
||||
public static void addNewStr(String str) {
|
||||
if (module.containStr(str)) {
|
||||
return;
|
||||
}
|
||||
module.addStr(new IrConstantStr(str, getStrName()));
|
||||
}
|
||||
|
||||
public static void addNewStr(IrConstantStr str) {
|
||||
module.addStr(str);
|
||||
}
|
||||
|
||||
public static void addInstr(IrInstr instr) {
|
||||
currentBB.addInstr(instr);
|
||||
instr.setBBlock(currentBB);
|
||||
}
|
||||
|
||||
public static String geFuncName(String name) {
|
||||
return name.equals("main") ? "@main" : prefunc + name;
|
||||
}
|
||||
|
||||
public static String getBlockName() {
|
||||
return prebb + bblockId++;
|
||||
}
|
||||
|
||||
public static String getStrName() {
|
||||
return prestr + strId++;
|
||||
}
|
||||
|
||||
public static String getGlobalName() {
|
||||
return preglobal + globalId++;
|
||||
}
|
||||
|
||||
public static String getLocalName() {
|
||||
int id = funcIdMap.get(currentFunc);
|
||||
funcIdMap.put(currentFunc, id + 1);
|
||||
return prelocal + id;
|
||||
}
|
||||
|
||||
public static String getLocalName(IrFuncValue func) {
|
||||
int id = funcIdMap.get(func);
|
||||
funcIdMap.put(func, id + 1);
|
||||
return prelocal + id;
|
||||
}
|
||||
|
||||
public static IrModule getCurrentModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public static IrFuncValue getCurrentFunc() {
|
||||
return currentFunc;
|
||||
}
|
||||
|
||||
public static IrBasicBlock getCurrentBB() {
|
||||
return currentBB;
|
||||
}
|
||||
|
||||
public static void pushLoop(IrLoop loop) {
|
||||
loopStack.push(loop);
|
||||
}
|
||||
|
||||
public static IrLoop popLoop() {
|
||||
return loopStack.pop();
|
||||
}
|
||||
|
||||
public static IrLoop getCurrentLoop() {
|
||||
return loopStack.peek();
|
||||
}
|
||||
}
|
||||
|
||||
225
midend/llvm/IrModule.java
Normal file → Executable file
225
midend/llvm/IrModule.java
Normal file → Executable file
@@ -1,100 +1,125 @@
|
||||
package midend.llvm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.instr.GetIntInstr;
|
||||
import midend.llvm.instr.PutChInstr;
|
||||
import midend.llvm.instr.PutIntInstr;
|
||||
import midend.llvm.instr.PutStrInstr;
|
||||
|
||||
public class IrModule {
|
||||
private ArrayList<String> decls;
|
||||
private HashMap<String, IrConstantStr> strs;
|
||||
private ArrayList<IrGlobalValue> globalVars;
|
||||
private ArrayList<IrFuncValue> funcs;
|
||||
|
||||
public IrModule() {
|
||||
decls = new ArrayList<>();
|
||||
strs = new HashMap<>();
|
||||
globalVars = new ArrayList<>();
|
||||
funcs = new ArrayList<>();
|
||||
decls.add(GetIntInstr.getIntDecl());
|
||||
decls.add(PutChInstr.putChDecl());
|
||||
decls.add(PutIntInstr.putIntDecl());
|
||||
decls.add(PutStrInstr.putStrDecl());
|
||||
}
|
||||
|
||||
public ArrayList<String> getDecls() {
|
||||
return decls;
|
||||
}
|
||||
|
||||
public HashMap<String, IrConstantStr> getStrs() {
|
||||
return strs;
|
||||
}
|
||||
|
||||
public ArrayList<IrGlobalValue> getGlobalVars() {
|
||||
return globalVars;
|
||||
}
|
||||
|
||||
public ArrayList<IrFuncValue> getFuncs() {
|
||||
return funcs;
|
||||
}
|
||||
|
||||
public void addFunc(IrFuncValue func) {
|
||||
funcs.add(func);
|
||||
}
|
||||
|
||||
public void addStr(IrConstantStr str) {
|
||||
if (strs.containsKey(str.getValue())) {
|
||||
return;
|
||||
}
|
||||
strs.put(str.getValue(), str);
|
||||
}
|
||||
|
||||
public boolean containStr(String str) {
|
||||
return strs.containsKey(str);
|
||||
}
|
||||
|
||||
public IrConstantStr getStr(String str) {
|
||||
if (containStr(str)) {
|
||||
return strs.get(str);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addGlobalVar(IrGlobalValue globalVar) {
|
||||
globalVars.add(globalVar);
|
||||
}
|
||||
|
||||
public IrFuncValue getMainFunc() {
|
||||
for (IrFuncValue func : funcs) {
|
||||
if (func.isMain()) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//TODO: toString()方法编写
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String decl : decls) {
|
||||
sb.append(decl).append("\n");
|
||||
}
|
||||
for (IrConstantStr str : strs.values()) {
|
||||
sb.append(str.toString()).append("\n");
|
||||
}
|
||||
for (IrGlobalValue globalVar : globalVars) {
|
||||
sb.append(globalVar.toString()).append("\n");
|
||||
}
|
||||
for (IrFuncValue func : funcs) {
|
||||
sb.append(func.toString()).append("\n");
|
||||
}
|
||||
// System.out.println(funcs.size());
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
package midend.llvm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAnnotation;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.MipsLabel;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.instr.GetIntInstr;
|
||||
import midend.llvm.instr.PutChInstr;
|
||||
import midend.llvm.instr.PutIntInstr;
|
||||
import midend.llvm.instr.PutStrInstr;
|
||||
|
||||
public class IrModule {
|
||||
private ArrayList<String> decls;
|
||||
private HashMap<String, IrConstantStr> strs;
|
||||
private ArrayList<IrGlobalValue> globalVars;
|
||||
private ArrayList<IrFuncValue> funcs;
|
||||
|
||||
public IrModule() {
|
||||
decls = new ArrayList<>();
|
||||
strs = new HashMap<>();
|
||||
globalVars = new ArrayList<>();
|
||||
funcs = new ArrayList<>();
|
||||
decls.add(GetIntInstr.getIntDecl());
|
||||
decls.add(PutChInstr.putChDecl());
|
||||
decls.add(PutIntInstr.putIntDecl());
|
||||
decls.add(PutStrInstr.putStrDecl());
|
||||
}
|
||||
|
||||
public ArrayList<String> getDecls() {
|
||||
return decls;
|
||||
}
|
||||
|
||||
public HashMap<String, IrConstantStr> getStrs() {
|
||||
return strs;
|
||||
}
|
||||
|
||||
public ArrayList<IrGlobalValue> getGlobalVars() {
|
||||
return globalVars;
|
||||
}
|
||||
|
||||
public ArrayList<IrFuncValue> getFuncs() {
|
||||
return funcs;
|
||||
}
|
||||
|
||||
public void addFunc(IrFuncValue func) {
|
||||
funcs.add(func);
|
||||
}
|
||||
|
||||
public void addStr(IrConstantStr str) {
|
||||
if (strs.containsKey(str.getValue())) {
|
||||
return;
|
||||
}
|
||||
strs.put(str.getValue(), str);
|
||||
}
|
||||
|
||||
public boolean containStr(String str) {
|
||||
return strs.containsKey(str);
|
||||
}
|
||||
|
||||
public IrConstantStr getStr(String str) {
|
||||
if (containStr(str)) {
|
||||
return strs.get(str);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addGlobalVar(IrGlobalValue globalVar) {
|
||||
globalVars.add(globalVar);
|
||||
}
|
||||
|
||||
public IrFuncValue getMainFunc() {
|
||||
for (IrFuncValue func : funcs) {
|
||||
if (func.isMain()) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String decl : decls) {
|
||||
sb.append(decl).append("\n");
|
||||
}
|
||||
for (IrConstantStr str : strs.values()) {
|
||||
sb.append(str.toString()).append("\n");
|
||||
}
|
||||
for (IrGlobalValue globalVar : globalVars) {
|
||||
sb.append(globalVar.toString()).append("\n");
|
||||
}
|
||||
for (IrFuncValue func : funcs) {
|
||||
sb.append(func.toString()).append("\n");
|
||||
}
|
||||
// System.out.println(funcs.size());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
for (IrGlobalValue globalVar : this.globalVars) {
|
||||
globalVar.toMips();
|
||||
}
|
||||
for (IrConstantStr str : this.strs.values()) {
|
||||
str.toMips(str.getMipsLabel());
|
||||
}
|
||||
new MipsAnnotation("jump to main");
|
||||
new MipsJump(MipsJumpType.JAL, "main");
|
||||
new MipsJump(MipsJumpType.J, "end");
|
||||
|
||||
for (IrFuncValue irFunction : this.funcs) {
|
||||
irFunction.toMips();
|
||||
}
|
||||
new MipsLabel("end");
|
||||
new MipsLi(Register.V0, 10);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
4
midend/llvm/constant/IrConstant.java
Normal file → Executable file
4
midend/llvm/constant/IrConstant.java
Normal file → Executable file
@@ -11,4 +11,8 @@ public class IrConstant extends IrValue {
|
||||
public String toString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
17
midend/llvm/constant/IrConstantArray.java
Normal file → Executable file
17
midend/llvm/constant/IrConstantArray.java
Normal file → Executable file
@@ -2,6 +2,8 @@ package midend.llvm.constant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.instr.data.MipsSpace;
|
||||
import backend.mips.instr.data.MipsWord;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
|
||||
@@ -44,4 +46,19 @@ public class IrConstantArray extends IrConstant {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
ArrayList<Integer> values = new ArrayList<>();
|
||||
if (elements.size() == 0) {
|
||||
new MipsSpace(size * 4, label);
|
||||
} else {
|
||||
for (IrConstant element : elements) {
|
||||
values.add(((IrConstantInt) element).getValue());
|
||||
}
|
||||
for (int i = 0; i < size - elements.size(); i++) {
|
||||
values.add(0);
|
||||
}
|
||||
new MipsWord(label, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
midend/llvm/constant/IrConstantInt.java
Normal file → Executable file
5
midend/llvm/constant/IrConstantInt.java
Normal file → Executable file
@@ -1,5 +1,6 @@
|
||||
package midend.llvm.constant;
|
||||
|
||||
import backend.mips.instr.data.MipsWord;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class IrConstantInt extends IrConstant {
|
||||
@@ -17,4 +18,8 @@ public class IrConstantInt extends IrConstant {
|
||||
public String toString() {
|
||||
return "i32 " + value;
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
new MipsWord(label, value);
|
||||
}
|
||||
}
|
||||
|
||||
111
midend/llvm/constant/IrConstantStr.java
Normal file → Executable file
111
midend/llvm/constant/IrConstantStr.java
Normal file → Executable file
@@ -1,53 +1,58 @@
|
||||
package midend.llvm.constant;
|
||||
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class IrConstantStr extends IrConstant {
|
||||
private String value;
|
||||
|
||||
public IrConstantStr(String value, String name) {
|
||||
super(new IrPointerType(
|
||||
new IrArrayType(IrInterType.INT8, getLen(value) + 1)), name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int getLen(String value) {
|
||||
int len = 0;
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
if (value.charAt(i) == '\\') {
|
||||
i++;
|
||||
} else if (value.charAt(i) == '"') {
|
||||
continue;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public static String getRealStr(String str) {
|
||||
boolean start = str.charAt(0) == '"';
|
||||
boolean end = str.charAt(str.length() - 1) == '"';
|
||||
if (start && end) {
|
||||
return str.substring(1, str.length() - 1);
|
||||
} else if (start) {
|
||||
return str.substring(1);
|
||||
} else if (end) {
|
||||
return str.substring(0, str.length() - 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName() + " = constant " + ((IrPointerType) getType()).getPointeeType());
|
||||
sb.append(" c\"" + getRealStr(value).replace("\\n", "\\0A"));
|
||||
sb.append("\\00\"");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
package midend.llvm.constant;
|
||||
|
||||
import backend.mips.instr.data.MipsAsciiz;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class IrConstantStr extends IrConstant {
|
||||
private String value;
|
||||
|
||||
public IrConstantStr(String value, String name) {
|
||||
super(new IrPointerType(
|
||||
new IrArrayType(IrInterType.INT8, getLen(value) + 1)), name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int getLen(String value) {
|
||||
int len = 0;
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
if (value.charAt(i) == '\\') {
|
||||
i++;
|
||||
} else if (value.charAt(i) == '"') {
|
||||
continue;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
public static String getRealStr(String str) {
|
||||
boolean start = str.charAt(0) == '"';
|
||||
boolean end = str.charAt(str.length() - 1) == '"';
|
||||
if (start && end) {
|
||||
return str.substring(1, str.length() - 1);
|
||||
} else if (start) {
|
||||
return str.substring(1);
|
||||
} else if (end) {
|
||||
return str.substring(0, str.length() - 1);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName() + " = constant " + ((IrPointerType) getType()).getPointeeType());
|
||||
sb.append(" c\"" + getRealStr(value).replace("\\n", "\\0A"));
|
||||
sb.append("\\00\"");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void toMips(String label) {
|
||||
new MipsAsciiz(label, getRealStr(value));
|
||||
}
|
||||
}
|
||||
|
||||
70
midend/llvm/instr/AllocateInstr.java
Normal file → Executable file
70
midend/llvm/instr/AllocateInstr.java
Normal file → Executable file
@@ -1,21 +1,49 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrType;
|
||||
|
||||
public class AllocateInstr extends IrInstr {
|
||||
private IrType pointeeType;
|
||||
|
||||
public AllocateInstr(IrType pointeeType, String name) { // name即为局部变量的name,因为要声明一个局部变量
|
||||
super(new IrPointerType(pointeeType), name, IrInstrType.ALLOCA);
|
||||
this.pointeeType = pointeeType;
|
||||
}
|
||||
|
||||
public IrType getPointeeType() {
|
||||
return pointeeType;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = alloca " + this.pointeeType;
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrType;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
|
||||
public class AllocateInstr extends IrInstr {
|
||||
private IrType pointeeType;
|
||||
|
||||
public AllocateInstr(IrType pointeeType, String name) { // name即为局部变量的name,因为要声明一个局部变量
|
||||
super(new IrPointerType(pointeeType), name, IrInstrType.ALLOCA);
|
||||
this.pointeeType = pointeeType;
|
||||
}
|
||||
|
||||
public IrType getPointeeType() {
|
||||
return pointeeType;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = alloca " + this.pointeeType;
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
// 想法:在栈上分配数据所需要的空间,再分配四字节的指针,这就是个指针,将其当作指针就好理解了
|
||||
if (pointeeType instanceof IrArrayType) {
|
||||
MipsBuilder.allocaOffset(4 * ((IrArrayType) pointeeType).getSize());
|
||||
} else {
|
||||
MipsBuilder.allocaOffset(4);
|
||||
}
|
||||
|
||||
Register reg = MipsBuilder.getRegister(this);
|
||||
if (reg == null) { // 未分配寄存器情况
|
||||
int offset = MipsBuilder.getOffset();
|
||||
new MipsAlu(MipsAluType.ADDI, Register.K0, Register.SP, offset);
|
||||
MipsBuilder.allocaOffset(this); // 将该变量的偏移量设置为其指针的偏移量,后续取值先取指针,再根据指针取值
|
||||
offset = MipsBuilder.getOffset();
|
||||
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset);
|
||||
} else {
|
||||
int offset = MipsBuilder.getOffset();
|
||||
new MipsAlu(MipsAluType.ADDI, reg, Register.SP, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
85
midend/llvm/instr/AluInstr.java
Normal file → Executable file
85
midend/llvm/instr/AluInstr.java
Normal file → Executable file
@@ -1,24 +1,61 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class AluInstr extends IrInstr {
|
||||
private AluType alutype;
|
||||
|
||||
public AluInstr(String name, String op, IrValue left, IrValue right) {
|
||||
super(IrInterType.INT32, name, IrInstrType.ALU);
|
||||
this.alutype = AluType.getAluType(op);
|
||||
addUse(left);
|
||||
addUse(right);
|
||||
}
|
||||
|
||||
public AluType getAluType() {
|
||||
return alutype;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = " + alutype.toString() + " " + getType()
|
||||
+ " " + getUse(0).getName() + ", " + getUse(1).getName();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsMd;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsMdType;
|
||||
import backend.mips.Register;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class AluInstr extends IrInstr {
|
||||
private AluType alutype;
|
||||
|
||||
public AluInstr(String name, String op, IrValue left, IrValue right) {
|
||||
super(IrInterType.INT32, name, IrInstrType.ALU);
|
||||
this.alutype = AluType.getAluType(op);
|
||||
addUse(left);
|
||||
addUse(right);
|
||||
}
|
||||
|
||||
public AluType getAluType() {
|
||||
return alutype;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = " + alutype.toString() + " " + getType()
|
||||
+ " " + getUse(0).getName() + ", " + getUse(1).getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
IrValue left = getUse(0);
|
||||
IrValue right = getUse(1);
|
||||
Register leftReg = MipsBuilder.getRegister(left) != null ? MipsBuilder.getRegister(left) : Register.K0;
|
||||
Register rightReg = MipsBuilder.getRegister(right) != null ? MipsBuilder.getRegister(right) : Register.K1;
|
||||
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
|
||||
loadValueToReg(left, leftReg);
|
||||
loadValueToReg(right, rightReg);
|
||||
|
||||
if (getAluType() == AluType.ADD) {
|
||||
new MipsAlu(MipsAluType.ADDU, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.SUB) {
|
||||
new MipsAlu(MipsAluType.SUBU, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.AND) {
|
||||
new MipsAlu(MipsAluType.AND, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.OR) {
|
||||
new MipsAlu(MipsAluType.OR, resultReg, leftReg, rightReg);
|
||||
} else if (getAluType() == AluType.MUL) {
|
||||
new MipsMd(MipsMdType.MULT, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFLO, resultReg);
|
||||
} else if (getAluType() == AluType.SDIV) {
|
||||
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFLO, resultReg);
|
||||
} else if (getAluType() == AluType.SREM) {
|
||||
new MipsMd(MipsMdType.DIV, leftReg, rightReg);
|
||||
new MipsMd(MipsMdType.MFHI, resultReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
104
midend/llvm/instr/AluType.java
Normal file → Executable file
104
midend/llvm/instr/AluType.java
Normal file → Executable file
@@ -1,53 +1,53 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum AluType {
|
||||
ADD,
|
||||
SUB,
|
||||
MUL,
|
||||
SDIV,
|
||||
SREM,
|
||||
AND,
|
||||
OR;
|
||||
|
||||
public static AluType getAluType(String op) {
|
||||
switch (op) {
|
||||
case "+":
|
||||
return ADD;
|
||||
case "-":
|
||||
return SUB;
|
||||
case "*":
|
||||
return MUL;
|
||||
case "/":
|
||||
return SDIV;
|
||||
case "%":
|
||||
return SREM;
|
||||
case "&":
|
||||
return AND;
|
||||
case "|":
|
||||
return OR;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case SUB:
|
||||
return "sub";
|
||||
case MUL:
|
||||
return "mul";
|
||||
case SDIV:
|
||||
return "sdiv";
|
||||
case SREM:
|
||||
return "srem";
|
||||
case AND:
|
||||
return "and";
|
||||
case OR:
|
||||
return "or";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum AluType {
|
||||
ADD,
|
||||
SUB,
|
||||
MUL,
|
||||
SDIV,
|
||||
SREM,
|
||||
AND,
|
||||
OR;
|
||||
|
||||
public static AluType getAluType(String op) {
|
||||
switch (op) {
|
||||
case "+":
|
||||
return ADD;
|
||||
case "-":
|
||||
return SUB;
|
||||
case "*":
|
||||
return MUL;
|
||||
case "/":
|
||||
return SDIV;
|
||||
case "%":
|
||||
return SREM;
|
||||
case "&":
|
||||
return AND;
|
||||
case "|":
|
||||
return OR;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case SUB:
|
||||
return "sub";
|
||||
case MUL:
|
||||
return "mul";
|
||||
case SDIV:
|
||||
return "sdiv";
|
||||
case SREM:
|
||||
return "srem";
|
||||
case AND:
|
||||
return "and";
|
||||
case OR:
|
||||
return "or";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
81
midend/llvm/instr/BranchInstr.java
Normal file → Executable file
81
midend/llvm/instr/BranchInstr.java
Normal file → Executable file
@@ -1,33 +1,48 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class BranchInstr extends IrInstr {
|
||||
public BranchInstr(String name, IrValue cond, IrBasicBlock trueBB, IrBasicBlock falseBB) {
|
||||
super(IrInterType.VOID, name, IrInstrType.BR);
|
||||
addUse(cond);
|
||||
addUse(trueBB);
|
||||
addUse(falseBB);
|
||||
}
|
||||
|
||||
public IrValue getCond() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrBasicBlock getTrueBB() {
|
||||
return (IrBasicBlock) getUse(1);
|
||||
}
|
||||
|
||||
public IrBasicBlock getFalseBB() {
|
||||
return (IrBasicBlock) getUse(2);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "br i1 " + getCond().getName() +
|
||||
", label %" + getTrueBB().getName() +
|
||||
", label %" + getFalseBB().getName();
|
||||
}
|
||||
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsBranch;
|
||||
import backend.mips.instr.type.MipsBranchType;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class BranchInstr extends IrInstr {
|
||||
public BranchInstr(String name, IrValue cond, IrBasicBlock trueBB, IrBasicBlock falseBB) {
|
||||
super(IrInterType.VOID, name, IrInstrType.BR);
|
||||
addUse(cond);
|
||||
addUse(trueBB);
|
||||
addUse(falseBB);
|
||||
}
|
||||
|
||||
public IrValue getCond() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrBasicBlock getTrueBB() {
|
||||
return (IrBasicBlock) getUse(1);
|
||||
}
|
||||
|
||||
public IrBasicBlock getFalseBB() {
|
||||
return (IrBasicBlock) getUse(2);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "br i1 " + getCond().getName() +
|
||||
", label %" + getTrueBB().getName() +
|
||||
", label %" + getFalseBB().getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register condReg = MipsBuilder.getRegister(getCond());
|
||||
if (condReg == null) {
|
||||
condReg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getCond(), condReg);
|
||||
new MipsBranch(MipsBranchType.BNE, condReg, Register.ZERO, getTrueBB().getMipsLabel());
|
||||
new MipsJump(MipsJumpType.J, getFalseBB().getMipsLabel());
|
||||
}
|
||||
}
|
||||
|
||||
165
midend/llvm/instr/CallInstr.java
Normal file → Executable file
165
midend/llvm/instr/CallInstr.java
Normal file → Executable file
@@ -1,48 +1,117 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class CallInstr extends IrInstr {
|
||||
public CallInstr(String name, IrFuncValue func, ArrayList<IrValue> args) {
|
||||
super(func.getRetType(), name, IrInstrType.CALL);
|
||||
addUse(func);
|
||||
for (IrValue arg : args) {
|
||||
addUse(arg);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean callVoid() {
|
||||
return getType().isVoid();
|
||||
}
|
||||
|
||||
public IrFuncValue getCalledFunc() {
|
||||
return (IrFuncValue) getUse(0);
|
||||
}
|
||||
|
||||
public ArrayList<IrValue> getArgs() {
|
||||
ArrayList<IrValue> args = new ArrayList<>();
|
||||
for (int i = 1; i < getNumUses(); i++) {
|
||||
args.add(getUse(i));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!callVoid()) {
|
||||
sb.append(getName() + " = ");
|
||||
}
|
||||
sb.append("call " + getType() + " " + getCalledFunc().getName() + "(");
|
||||
for (int i = 1; i < getNumUses(); i++) {
|
||||
sb.append(getUse(i).getType() + " " + getUse(i).getName());
|
||||
if (i < getNumUses() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
import backend.mips.MipsBuilder;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class CallInstr extends IrInstr {
|
||||
public CallInstr(String name, IrFuncValue func, ArrayList<IrValue> args) {
|
||||
super(func.getRetType(), name, IrInstrType.CALL);
|
||||
addUse(func);
|
||||
for (IrValue arg : args) {
|
||||
addUse(arg);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean callVoid() {
|
||||
return getType().isVoid();
|
||||
}
|
||||
|
||||
public IrFuncValue getCalledFunc() {
|
||||
return (IrFuncValue) getUse(0);
|
||||
}
|
||||
|
||||
public ArrayList<IrValue> getArgs() {
|
||||
ArrayList<IrValue> args = new ArrayList<>();
|
||||
for (int i = 1; i < getNumUses(); i++) {
|
||||
args.add(getUse(i));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!callVoid()) {
|
||||
sb.append(getName() + " = ");
|
||||
}
|
||||
sb.append("call " + getType() + " " + getCalledFunc().getName() + "(");
|
||||
for (int i = 1; i < getNumUses(); i++) {
|
||||
sb.append(getUse(i).getType() + " " + getUse(i).getName());
|
||||
if (i < getNumUses() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
ArrayList<Register> usedRegisters = MipsBuilder.getUsedRegisters();
|
||||
int offset = MipsBuilder.getOffset();
|
||||
save(usedRegisters, offset);
|
||||
ArrayList<IrValue> args = getArgs();
|
||||
saveArgs(args, offset, usedRegisters);
|
||||
offset -= (usedRegisters.size() + 2) * 4;
|
||||
new MipsAlu(MipsAluType.ADDI, Register.SP, Register.SP, offset);
|
||||
new MipsJump(MipsJumpType.JAL, getCalledFunc().getMipsLabel());
|
||||
offset += (usedRegisters.size() + 2) * 4;
|
||||
recover(usedRegisters, offset);
|
||||
saveResult(this, Register.V0);
|
||||
}
|
||||
|
||||
public void save(ArrayList<Register> usedRegisters, int offset) {
|
||||
int num = 0;
|
||||
for (Register reg : usedRegisters) {
|
||||
num++;
|
||||
new MipsLs(MipsLsType.SW, reg, Register.SP, offset - num * 4);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, Register.SP, Register.SP, offset - (num + 1) * 4);
|
||||
new MipsLs(MipsLsType.SW, Register.RA, Register.SP, offset - (num + 2) * 4);
|
||||
}
|
||||
|
||||
public void saveArgs(ArrayList<IrValue> args, int offset, ArrayList<Register> usedRegisters) {
|
||||
int num = 0;
|
||||
ArrayList<Register> argRegs = new ArrayList<>();
|
||||
argRegs.add(Register.A1);
|
||||
argRegs.add(Register.A2);
|
||||
argRegs.add(Register.A3);
|
||||
for (IrValue arg : args) {
|
||||
num++;
|
||||
if (num <= 3) { // 分配到A1、A2、A3
|
||||
if (argRegs.contains(MipsBuilder.getRegister(arg))) {
|
||||
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
|
||||
new MipsLs(MipsLsType.LW, argRegs.get(num - 1), Register.SP, offset - (index + 1) * 4);
|
||||
} else {
|
||||
loadValueToReg(arg, argRegs.get(num - 1));
|
||||
}
|
||||
} else {
|
||||
if (MipsBuilder.getRegister(arg) == Register.K0 || argRegs.contains(MipsBuilder.getRegister(arg))) {
|
||||
int index = usedRegisters.indexOf(MipsBuilder.getRegister(arg));
|
||||
new MipsLs(MipsLsType.LW, Register.K0, Register.SP, offset - (index + 1) * 4);
|
||||
} else {
|
||||
loadValueToReg(arg, Register.K0);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, Register.K0, Register.SP, offset - (usedRegisters.size() + num + 2) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void recover(ArrayList<Register> usedRegisters, int offset) {
|
||||
new MipsLs(MipsLsType.LW, Register.RA, Register.SP, 0);
|
||||
new MipsLs(MipsLsType.LW, Register.SP, Register.SP, 4);
|
||||
int num = 0;
|
||||
for (Register reg : usedRegisters) {
|
||||
num++;
|
||||
new MipsLs(MipsLsType.LW, reg, Register.SP, offset - num * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
90
midend/llvm/instr/CmpInstr.java
Normal file → Executable file
90
midend/llvm/instr/CmpInstr.java
Normal file → Executable file
@@ -1,32 +1,58 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class CmpInstr extends IrInstr {
|
||||
private CmpType cmpType;
|
||||
|
||||
public CmpInstr(String name, String op, IrValue lhs, IrValue rhs) {
|
||||
super(IrInterType.BOOL, name, IrInstrType.CMP);
|
||||
cmpType = CmpType.getCmpType(op);
|
||||
addUse(lhs);
|
||||
addUse(rhs);
|
||||
}
|
||||
|
||||
public CmpType getCmpType() {
|
||||
return cmpType;
|
||||
}
|
||||
|
||||
public IrValue getLhs() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getRhs() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = " + "icmp " + cmpType.toString()
|
||||
+ " i32 " + getLhs().getName() + ", " + getRhs().getName();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsComp;
|
||||
import backend.mips.instr.type.MipsCompareType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import backend.mips.MipsBuilder;
|
||||
|
||||
public class CmpInstr extends IrInstr {
|
||||
private CmpType cmpType;
|
||||
|
||||
public CmpInstr(String name, String op, IrValue lhs, IrValue rhs) {
|
||||
super(IrInterType.BOOL, name, IrInstrType.CMP);
|
||||
cmpType = CmpType.getCmpType(op);
|
||||
addUse(lhs);
|
||||
addUse(rhs);
|
||||
}
|
||||
|
||||
public CmpType getCmpType() {
|
||||
return cmpType;
|
||||
}
|
||||
|
||||
public IrValue getLhs() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getRhs() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = " + "icmp " + cmpType.toString()
|
||||
+ " i32 " + getLhs().getName() + ", " + getRhs().getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register leftReg = MipsBuilder.getRegister(getLhs()) != null ? MipsBuilder.getRegister(getLhs()) : Register.K0;
|
||||
Register rightReg = MipsBuilder.getRegister(getRhs()) != null ? MipsBuilder.getRegister(getRhs()) : Register.K1;
|
||||
Register resultReg = MipsBuilder.getRegister(this) != null ? MipsBuilder.getRegister(this) : Register.K1;
|
||||
loadValueToReg(getLhs(), leftReg);
|
||||
loadValueToReg(getRhs(), rightReg);
|
||||
if (getCmpType() == CmpType.EQ) {
|
||||
new MipsComp(MipsCompareType.SEQ, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.NE) {
|
||||
new MipsComp(MipsCompareType.SNE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SGE) {
|
||||
new MipsComp(MipsCompareType.SGE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SLE) {
|
||||
new MipsComp(MipsCompareType.SLE, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SGT) {
|
||||
new MipsComp(MipsCompareType.SGT, resultReg, leftReg, rightReg);
|
||||
} else if (getCmpType() == CmpType.SLT) {
|
||||
new MipsComp(MipsCompareType.SLT, resultReg, leftReg, rightReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
96
midend/llvm/instr/CmpType.java
Normal file → Executable file
96
midend/llvm/instr/CmpType.java
Normal file → Executable file
@@ -1,48 +1,48 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum CmpType {
|
||||
EQ,
|
||||
NE,
|
||||
SGT,
|
||||
SGE,
|
||||
SLT,
|
||||
SLE;
|
||||
|
||||
public static CmpType getCmpType(String op) {
|
||||
switch (op) {
|
||||
case "==":
|
||||
return EQ;
|
||||
case "!=":
|
||||
return NE;
|
||||
case ">":
|
||||
return SGT;
|
||||
case ">=":
|
||||
return SGE;
|
||||
case "<":
|
||||
return SLT;
|
||||
case "<=":
|
||||
return SLE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case EQ:
|
||||
return "eq";
|
||||
case NE:
|
||||
return "ne";
|
||||
case SGT:
|
||||
return "sgt";
|
||||
case SGE:
|
||||
return "sge";
|
||||
case SLT:
|
||||
return "slt";
|
||||
case SLE:
|
||||
return "sle";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum CmpType {
|
||||
EQ,
|
||||
NE,
|
||||
SGT,
|
||||
SGE,
|
||||
SLT,
|
||||
SLE;
|
||||
|
||||
public static CmpType getCmpType(String op) {
|
||||
switch (op) {
|
||||
case "==":
|
||||
return EQ;
|
||||
case "!=":
|
||||
return NE;
|
||||
case ">":
|
||||
return SGT;
|
||||
case ">=":
|
||||
return SGE;
|
||||
case "<":
|
||||
return SLT;
|
||||
case "<=":
|
||||
return SLE;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case EQ:
|
||||
return "eq";
|
||||
case NE:
|
||||
return "ne";
|
||||
case SGT:
|
||||
return "sgt";
|
||||
case SGE:
|
||||
return "sge";
|
||||
case SLT:
|
||||
return "slt";
|
||||
case SLE:
|
||||
return "sle";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
73
midend/llvm/instr/ExtendInstr.java
Normal file → Executable file
73
midend/llvm/instr/ExtendInstr.java
Normal file → Executable file
@@ -1,31 +1,42 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class ExtendInstr extends IrInstr {
|
||||
private IrType targetType;
|
||||
|
||||
public ExtendInstr(String name, IrType targetType, IrValue src) {
|
||||
super(targetType, name, IrInstrType.EXTEND);
|
||||
this.targetType = targetType;
|
||||
addUse(src);
|
||||
}
|
||||
|
||||
public IrValue getSrc() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrType getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
public IrType getSrcType() {
|
||||
return getSrc().getType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = zext " + getSrc().getType()
|
||||
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class ExtendInstr extends IrInstr {
|
||||
private IrType targetType;
|
||||
|
||||
public ExtendInstr(String name, IrType targetType, IrValue src) {
|
||||
super(targetType, name, IrInstrType.EXTEND);
|
||||
this.targetType = targetType;
|
||||
addUse(src);
|
||||
}
|
||||
|
||||
public IrValue getSrc() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrType getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
public IrType getSrcType() {
|
||||
return getSrc().getType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = zext " + getSrc().getType()
|
||||
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register reg = MipsBuilder.getRegister(this);
|
||||
if (reg == null) {
|
||||
reg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getSrc(), reg);
|
||||
saveResult(this, reg);
|
||||
}
|
||||
}
|
||||
|
||||
143
midend/llvm/instr/GepInstr.java
Normal file → Executable file
143
midend/llvm/instr/GepInstr.java
Normal file → Executable file
@@ -1,57 +1,86 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class GepInstr extends IrInstr {
|
||||
public GepInstr(IrValue pointer, IrValue offset, String name) {
|
||||
super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP);
|
||||
addUse(pointer);
|
||||
addUse(offset);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getOffset() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
IrValue pointer = this.getPointer();
|
||||
IrValue offset = this.getOffset();
|
||||
|
||||
IrPointerType pointerType = (IrPointerType) pointer.getType();
|
||||
IrType targetType = pointerType.getPointeeType();
|
||||
|
||||
if (targetType instanceof IrArrayType arrayType) {
|
||||
return getName() + " = getelementptr inbounds " +
|
||||
arrayType + ", " +
|
||||
pointerType + " " +
|
||||
pointer.getName() + ", i32 0, " +
|
||||
offset.getType() + " " +
|
||||
offset.getName();
|
||||
} else {
|
||||
return getName() + " = getelementptr inbounds " +
|
||||
targetType + ", " +
|
||||
pointerType + " " +
|
||||
pointer.getName() + ", " +
|
||||
offset.getType() + " " +
|
||||
offset.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static IrType getTargetType(IrValue pointer) {
|
||||
IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType();
|
||||
if (targetType instanceof IrArrayType arrayType) {
|
||||
return arrayType.getElementType();
|
||||
} else if (targetType instanceof IrPointerType pointerType) {
|
||||
return pointerType.getPointeeType();
|
||||
} else {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
import midend.llvm.type.IrArrayType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class GepInstr extends IrInstr {
|
||||
public GepInstr(IrValue pointer, IrValue offset, String name) {
|
||||
super(new IrPointerType(getTargetType(pointer)), name, IrInstrType.GEP);
|
||||
addUse(pointer);
|
||||
addUse(offset);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getOffset() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
IrValue pointer = this.getPointer();
|
||||
IrValue offset = this.getOffset();
|
||||
|
||||
IrPointerType pointerType = (IrPointerType) pointer.getType();
|
||||
IrType targetType = pointerType.getPointeeType();
|
||||
|
||||
if (targetType instanceof IrArrayType arrayType) {
|
||||
return getName() + " = getelementptr inbounds " +
|
||||
arrayType + ", " +
|
||||
pointerType + " " +
|
||||
pointer.getName() + ", i32 0, " +
|
||||
offset.getType() + " " +
|
||||
offset.getName();
|
||||
} else {
|
||||
return getName() + " = getelementptr inbounds " +
|
||||
targetType + ", " +
|
||||
pointerType + " " +
|
||||
pointer.getName() + ", " +
|
||||
offset.getType() + " " +
|
||||
offset.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static IrType getTargetType(IrValue pointer) {
|
||||
IrType targetType = ((IrPointerType) pointer.getType()).getPointeeType();
|
||||
if (targetType instanceof IrArrayType arrayType) {
|
||||
return arrayType.getElementType();
|
||||
} else if (targetType instanceof IrPointerType pointerType) {
|
||||
return pointerType.getPointeeType();
|
||||
} else {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register pointerReg = MipsBuilder.getRegister(getPointer());
|
||||
if (pointerReg == null) {
|
||||
pointerReg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getPointer(), pointerReg);
|
||||
Register offsetReg = MipsBuilder.getRegister(getOffset());
|
||||
if (offsetReg == null) {
|
||||
offsetReg = Register.K1;
|
||||
}
|
||||
Register resultReg = MipsBuilder.getRegister(this);
|
||||
if (resultReg == null) {
|
||||
resultReg = Register.K1;
|
||||
}
|
||||
if (getOffset() instanceof IrConstantInt intOffset) {
|
||||
new MipsAlu(MipsAluType.ADDI, resultReg, pointerReg, 4 * intOffset.getValue());
|
||||
} else {
|
||||
loadValueToReg(getOffset(), offsetReg);
|
||||
new MipsAlu(MipsAluType.SLL, resultReg, offsetReg, 2);
|
||||
new MipsAlu(MipsAluType.ADDU, resultReg, resultReg, pointerReg);
|
||||
}
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
43
midend/llvm/instr/GetIntInstr.java
Normal file → Executable file
43
midend/llvm/instr/GetIntInstr.java
Normal file → Executable file
@@ -1,17 +1,26 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class GetIntInstr extends IrInstr {
|
||||
public GetIntInstr(String name) {
|
||||
super(IrInterType.INT32, name, IrInstrType.IO);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = call i32 @getint()";
|
||||
}
|
||||
|
||||
public static String getIntDecl() {
|
||||
return "declare i32 @getint()";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class GetIntInstr extends IrInstr {
|
||||
public GetIntInstr(String name) {
|
||||
super(IrInterType.INT32, name, IrInstrType.IO);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = call i32 @getint()";
|
||||
}
|
||||
|
||||
public static String getIntDecl() {
|
||||
return "declare i32 @getint()";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLi(Register.V0, 5);
|
||||
new MipsSyscall();
|
||||
saveResult(this, Register.V0);
|
||||
}
|
||||
}
|
||||
|
||||
103
midend/llvm/instr/IrInstr.java
Normal file → Executable file
103
midend/llvm/instr/IrInstr.java
Normal file → Executable file
@@ -1,28 +1,75 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.use.IrUser;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.type.IrType;
|
||||
|
||||
public class IrInstr extends IrUser {
|
||||
private IrInstrType type;
|
||||
private IrBasicBlock block;
|
||||
|
||||
public IrInstr(IrType type, String name, IrInstrType instrType) {
|
||||
super(type, name);
|
||||
this.type = instrType;
|
||||
this.block = null;
|
||||
}
|
||||
|
||||
public IrInstrType getInstrType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public void setBBlock(IrBasicBlock block) {
|
||||
this.block = block;
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.use.IrUser;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrGlobalValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.fake.MipsLa;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.fake.MipsMove;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
import midend.llvm.type.IrType;
|
||||
|
||||
public class IrInstr extends IrUser {
|
||||
private IrInstrType type;
|
||||
private IrBasicBlock block;
|
||||
|
||||
public IrInstr(IrType type, String name, IrInstrType instrType) {
|
||||
super(type, name);
|
||||
this.type = instrType;
|
||||
this.block = null;
|
||||
}
|
||||
|
||||
public IrInstrType getInstrType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public void setBBlock(IrBasicBlock block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void saveResult(IrValue value, Register reg) {
|
||||
Register valueReg = MipsBuilder.getRegister(value);
|
||||
if (valueReg == null) {
|
||||
Integer offset = MipsBuilder.getOffset(value);
|
||||
if (offset == null) {
|
||||
MipsBuilder.allocaOffset(value);
|
||||
offset = MipsBuilder.getOffset(value);
|
||||
}
|
||||
new MipsLs(MipsLsType.SW, reg, Register.SP, offset);
|
||||
} else {
|
||||
new MipsMove(valueReg, reg);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadValueToReg(IrValue value, Register reg) {
|
||||
if (value instanceof IrGlobalValue) {
|
||||
new MipsLa(reg, value.getMipsLabel());
|
||||
return;
|
||||
}
|
||||
if (value instanceof IrConstantInt) {
|
||||
new MipsLi(reg, ((IrConstantInt) value).getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
Register valueReg = MipsBuilder.getRegister(value);
|
||||
if (valueReg != null) {
|
||||
new MipsMove(reg, valueReg);
|
||||
return;
|
||||
}
|
||||
Integer offset = MipsBuilder.getOffset(value);
|
||||
if (offset == null) {
|
||||
MipsBuilder.allocaOffset(value);
|
||||
offset = MipsBuilder.getOffset(value);
|
||||
}
|
||||
new MipsLs(MipsLsType.LW, reg, Register.SP, offset);
|
||||
}
|
||||
}
|
||||
|
||||
36
midend/llvm/instr/IrInstrType.java
Normal file → Executable file
36
midend/llvm/instr/IrInstrType.java
Normal file → Executable file
@@ -1,18 +1,18 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum IrInstrType {
|
||||
ALU,
|
||||
CMP,
|
||||
CALL,
|
||||
ALLOCA,
|
||||
LOAD,
|
||||
STORE,
|
||||
GEP,
|
||||
PHI,
|
||||
EXTEND,
|
||||
TRUNC,
|
||||
BR,
|
||||
RET,
|
||||
JUMP,
|
||||
IO
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
public enum IrInstrType {
|
||||
ALU,
|
||||
CMP,
|
||||
CALL,
|
||||
ALLOCA,
|
||||
LOAD,
|
||||
STORE,
|
||||
GEP,
|
||||
PHI,
|
||||
EXTEND,
|
||||
TRUNC,
|
||||
BR,
|
||||
RET,
|
||||
JUMP,
|
||||
IO
|
||||
}
|
||||
|
||||
45
midend/llvm/instr/JumpInstr.java
Normal file → Executable file
45
midend/llvm/instr/JumpInstr.java
Normal file → Executable file
@@ -1,20 +1,25 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class JumpInstr extends IrInstr {
|
||||
public JumpInstr(IrBasicBlock targetBlock) {
|
||||
super(IrInterType.VOID, "jump", IrInstrType.JUMP);
|
||||
addUse(targetBlock);
|
||||
}
|
||||
|
||||
public IrBasicBlock getTargetBlock() {
|
||||
return (IrBasicBlock) getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "br label " + "%" + getTargetBlock().getName();
|
||||
}
|
||||
}
|
||||
// TODO:所有的指令的基本块设置还需完善
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class JumpInstr extends IrInstr {
|
||||
public JumpInstr(IrBasicBlock targetBlock) {
|
||||
super(IrInterType.VOID, "jump", IrInstrType.JUMP);
|
||||
addUse(targetBlock);
|
||||
}
|
||||
|
||||
public IrBasicBlock getTargetBlock() {
|
||||
return (IrBasicBlock) getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "br label " + "%" + getTargetBlock().getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsJump(MipsJumpType.J, getTargetBlock().getMipsLabel()); //TODO: 该用JAL吗?
|
||||
}
|
||||
}
|
||||
|
||||
59
midend/llvm/instr/LoadInstr.java
Normal file → Executable file
59
midend/llvm/instr/LoadInstr.java
Normal file → Executable file
@@ -1,20 +1,39 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class LoadInstr extends IrInstr {
|
||||
public LoadInstr(IrValue pointer, String name) {
|
||||
super(((IrPointerType) pointer.getType()).getPointeeType(), name, IrInstrType.LOAD);
|
||||
addUse(pointer);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = load " + getType() + ", "
|
||||
+ getPointer().getType() + " " + getPointer().getName();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class LoadInstr extends IrInstr {
|
||||
public LoadInstr(IrValue pointer, String name) {
|
||||
super(((IrPointerType) pointer.getType()).getPointeeType(), name, IrInstrType.LOAD);
|
||||
addUse(pointer);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = load " + getType() + ", "
|
||||
+ getPointer().getType() + " " + getPointer().getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
IrValue pointer = getPointer();
|
||||
Register reg = MipsBuilder.getRegister(pointer);
|
||||
if (reg == null) { // 未分配寄存器情况
|
||||
reg = Register.K0;
|
||||
}
|
||||
loadValueToReg(pointer, reg);
|
||||
Register resultReg = MipsBuilder.getRegister(this);
|
||||
if (resultReg == null) {
|
||||
resultReg = Register.K1;
|
||||
}
|
||||
new MipsLs(MipsLsType.LW, resultReg, reg, 0);
|
||||
saveResult(this, resultReg);
|
||||
}
|
||||
}
|
||||
|
||||
47
midend/llvm/instr/PutChInstr.java
Normal file → Executable file
47
midend/llvm/instr/PutChInstr.java
Normal file → Executable file
@@ -1,19 +1,28 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class PutChInstr extends IrInstr {
|
||||
public PutChInstr(String name, IrValue putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "call void @putch(i32 " + getUses().get(0).getName() + ")";
|
||||
}
|
||||
|
||||
public static String putChDecl() {
|
||||
return "declare void @putch(i32)";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
|
||||
public class PutChInstr extends IrInstr {
|
||||
public PutChInstr(String name, IrValue putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "call void @putch(i32 " + getUses().get(0).getName() + ")";
|
||||
}
|
||||
|
||||
public static String putChDecl() {
|
||||
return "declare void @putch(i32)";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
loadValueToReg(getUse(0), Register.A0);
|
||||
new MipsLi(Register.V0, 11);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
47
midend/llvm/instr/PutIntInstr.java
Normal file → Executable file
47
midend/llvm/instr/PutIntInstr.java
Normal file → Executable file
@@ -1,19 +1,28 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class PutIntInstr extends IrInstr {
|
||||
public PutIntInstr(String name, IrValue putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "call void @putint(i32 " + getUses().get(0).getName() + ")";
|
||||
}
|
||||
|
||||
public static String putIntDecl() {
|
||||
return "declare void @putint(i32)";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
|
||||
public class PutIntInstr extends IrInstr {
|
||||
public PutIntInstr(String name, IrValue putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "call void @putint(i32 " + getUses().get(0).getName() + ")";
|
||||
}
|
||||
|
||||
public static String putIntDecl() {
|
||||
return "declare void @putint(i32)";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
loadValueToReg(getUse(0), Register.A0);
|
||||
new MipsLi(Register.V0, 1);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
62
midend/llvm/instr/PutStrInstr.java
Normal file → Executable file
62
midend/llvm/instr/PutStrInstr.java
Normal file → Executable file
@@ -1,26 +1,36 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
|
||||
public class PutStrInstr extends IrInstr {
|
||||
private IrConstantStr strVal;
|
||||
|
||||
public PutStrInstr(String name, IrConstantStr putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
strVal = putValue;
|
||||
}
|
||||
|
||||
public static String putStrDecl() {
|
||||
return "declare void @putstr(i8*)";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
IrPointerType ptrType = (IrPointerType) strVal.getType();
|
||||
return "call void @putstr(i8* getelementptr inbounds ("
|
||||
+ ptrType.getPointeeType() + ", " + ptrType +
|
||||
" " + strVal.getName() + ", i32 0, i32 0))";
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import backend.mips.instr.fake.MipsLa;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import backend.mips.instr.fake.MipsLi;
|
||||
import backend.mips.instr.MipsSyscall;
|
||||
import backend.mips.Register;
|
||||
|
||||
public class PutStrInstr extends IrInstr {
|
||||
private IrConstantStr strVal;
|
||||
|
||||
public PutStrInstr(String name, IrConstantStr putValue) {
|
||||
super(IrInterType.VOID, name, IrInstrType.IO);
|
||||
addUse(putValue);
|
||||
strVal = putValue;
|
||||
}
|
||||
|
||||
public static String putStrDecl() {
|
||||
return "declare void @putstr(i8*)";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
IrPointerType ptrType = (IrPointerType) strVal.getType();
|
||||
return "call void @putstr(i8* getelementptr inbounds ("
|
||||
+ ptrType.getPointeeType() + ", " + ptrType +
|
||||
" " + strVal.getName() + ", i32 0, i32 0))";
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLa(Register.A0, strVal.getMipsLabel());
|
||||
new MipsLi(Register.V0, 4);
|
||||
new MipsSyscall();
|
||||
}
|
||||
}
|
||||
|
||||
58
midend/llvm/instr/ReturnInstr.java
Normal file → Executable file
58
midend/llvm/instr/ReturnInstr.java
Normal file → Executable file
@@ -1,20 +1,38 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class ReturnInstr extends IrInstr {
|
||||
public ReturnInstr(IrValue retValue) {
|
||||
super(IrInterType.VOID, "ret", IrInstrType.RET);
|
||||
addUse(retValue);
|
||||
}
|
||||
|
||||
public IrValue getRetValue() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + (getRetValue() == null ? " void" :
|
||||
" " + getRetValue().getType() + " " + getRetValue().getName());
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsJump;
|
||||
import backend.mips.instr.fake.MipsMove;
|
||||
import backend.mips.instr.type.MipsJumpType;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class ReturnInstr extends IrInstr {
|
||||
public ReturnInstr(IrValue retValue) {
|
||||
super(IrInterType.VOID, "ret", IrInstrType.RET);
|
||||
addUse(retValue);
|
||||
}
|
||||
|
||||
public IrValue getRetValue() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName()
|
||||
+ (getRetValue() == null ? " void" : " " + getRetValue().getType() + " " + getRetValue().getName());
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
if (getRetValue() != null) {
|
||||
Register reg = MipsBuilder.getRegister(getRetValue());
|
||||
if (reg == null) {
|
||||
loadValueToReg(getRetValue(), Register.V0);
|
||||
} else {
|
||||
new MipsMove(Register.V0, reg);
|
||||
}
|
||||
}
|
||||
new MipsJump(MipsJumpType.JR, Register.RA);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
68
midend/llvm/instr/StoreInstr.java
Normal file → Executable file
68
midend/llvm/instr/StoreInstr.java
Normal file → Executable file
@@ -1,25 +1,43 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.type.IrInterType;
|
||||
|
||||
public class StoreInstr extends IrInstr {
|
||||
public StoreInstr(IrValue value, IrValue pointer) {
|
||||
super(IrInterType.VOID, "store", IrInstrType.STORE);
|
||||
addUse(value);
|
||||
addUse(pointer);
|
||||
}
|
||||
|
||||
public IrValue getValue() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " " + getValue().getType() + " " + getValue().getName()
|
||||
+ ", " + getPointer().getType() + " " + getPointer().getName();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import backend.mips.instr.MipsLs;
|
||||
import backend.mips.instr.type.MipsLsType;
|
||||
|
||||
public class StoreInstr extends IrInstr {
|
||||
public StoreInstr(IrValue value, IrValue pointer) {
|
||||
super(IrInterType.VOID, "store", IrInstrType.STORE);
|
||||
addUse(value);
|
||||
addUse(pointer);
|
||||
}
|
||||
|
||||
public IrValue getValue() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrValue getPointer() {
|
||||
return getUse(1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " " + getValue().getType() + " " + getValue().getName()
|
||||
+ ", " + getPointer().getType() + " " + getPointer().getName();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register valueReg = MipsBuilder.getRegister(getValue());
|
||||
if (valueReg == null) {
|
||||
valueReg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getValue(), valueReg);
|
||||
Register pointerReg = MipsBuilder.getRegister(getPointer());
|
||||
if (pointerReg == null) {
|
||||
pointerReg = Register.K1;
|
||||
}
|
||||
loadValueToReg(getPointer(), pointerReg);
|
||||
new MipsLs(MipsLsType.SW, valueReg, pointerReg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
81
midend/llvm/instr/TruncInstr.java
Normal file → Executable file
81
midend/llvm/instr/TruncInstr.java
Normal file → Executable file
@@ -1,31 +1,50 @@
|
||||
package midend.llvm.instr;
|
||||
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class TruncInstr extends IrInstr {
|
||||
private IrType targetType;
|
||||
|
||||
public TruncInstr(IrType targetType, IrValue value, String name) {
|
||||
super(targetType, name, IrInstrType.TRUNC);
|
||||
addUse(value);
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public IrValue getSrc() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrType getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public IrType getSrcType() {
|
||||
return getSrc().getType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = trunc " + getSrcType()
|
||||
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||
}
|
||||
}
|
||||
package midend.llvm.instr;
|
||||
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsAlu;
|
||||
import backend.mips.instr.type.MipsAluType;
|
||||
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class TruncInstr extends IrInstr {
|
||||
private IrType targetType;
|
||||
|
||||
public TruncInstr(IrType targetType, IrValue value, String name) {
|
||||
super(targetType, name, IrInstrType.TRUNC);
|
||||
addUse(value);
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public IrValue getSrc() {
|
||||
return getUse(0);
|
||||
}
|
||||
|
||||
public IrType getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public IrType getSrcType() {
|
||||
return getSrc().getType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + " = trunc " + getSrcType()
|
||||
+ " " + getSrc().getName() + " to " + getTargetType();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
Register reg = MipsBuilder.getRegister(getSrc());
|
||||
if (reg == null) {
|
||||
reg = Register.K0;
|
||||
}
|
||||
loadValueToReg(getSrc(), reg);
|
||||
if (this.targetType.isInt8()) {
|
||||
new MipsAlu(MipsAluType.ANDI, reg, reg, 0xFF);
|
||||
} else if (this.targetType.isBool()) {
|
||||
new MipsAlu(MipsAluType.ANDI, reg, reg, 0x1);
|
||||
}
|
||||
saveResult(this, reg);
|
||||
}
|
||||
}
|
||||
|
||||
0
midend/llvm/type/IrArrayType.java
Normal file → Executable file
0
midend/llvm/type/IrArrayType.java
Normal file → Executable file
0
midend/llvm/type/IrBasicBlockType.java
Normal file → Executable file
0
midend/llvm/type/IrBasicBlockType.java
Normal file → Executable file
0
midend/llvm/type/IrFuncType.java
Normal file → Executable file
0
midend/llvm/type/IrFuncType.java
Normal file → Executable file
0
midend/llvm/type/IrInterType.java
Normal file → Executable file
0
midend/llvm/type/IrInterType.java
Normal file → Executable file
0
midend/llvm/type/IrPointerType.java
Normal file → Executable file
0
midend/llvm/type/IrPointerType.java
Normal file → Executable file
2
midend/llvm/type/IrType.java
Normal file → Executable file
2
midend/llvm/type/IrType.java
Normal file → Executable file
@@ -4,9 +4,7 @@ import midend.llvm.IrBuilder;
|
||||
import midend.llvm.constant.IrConstantInt;
|
||||
import midend.llvm.instr.CmpInstr;
|
||||
import midend.llvm.instr.ExtendInstr;
|
||||
import midend.llvm.instr.TruncInstr;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.instr.ExtendInstr;
|
||||
|
||||
public class IrType {
|
||||
public boolean isInt32() {
|
||||
|
||||
0
midend/llvm/use/IrUse.java
Normal file → Executable file
0
midend/llvm/use/IrUse.java
Normal file → Executable file
0
midend/llvm/use/IrUser.java
Normal file → Executable file
0
midend/llvm/use/IrUser.java
Normal file → Executable file
248
midend/llvm/value/IrBasicBlock.java
Normal file → Executable file
248
midend/llvm/value/IrBasicBlock.java
Normal file → Executable file
@@ -1,120 +1,128 @@
|
||||
package midend.llvm.value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.type.IrBasicBlockType;
|
||||
|
||||
public class IrBasicBlock extends IrValue {
|
||||
private ArrayList<IrInstr> instrs;
|
||||
private IrFuncValue func;
|
||||
private ArrayList<IrBasicBlock> preds; //前驱
|
||||
private ArrayList<IrBasicBlock> succs; //后继
|
||||
private HashSet<IrBasicBlock> domied; //支配该节点
|
||||
private IrBasicBlock directDomi;
|
||||
private HashSet<IrBasicBlock> directDomies; //该节点直接支配
|
||||
private HashSet<IrBasicBlock> domiFrontier;
|
||||
|
||||
public IrBasicBlock(String name, IrFuncValue func) {
|
||||
super(new IrBasicBlockType(), name);
|
||||
this.func = func;
|
||||
instrs = new ArrayList<>();
|
||||
preds = new ArrayList<>();
|
||||
succs = new ArrayList<>();
|
||||
domied = new HashSet<>();
|
||||
directDomi = null;
|
||||
directDomies = new HashSet<>();
|
||||
domiFrontier = new HashSet<>();
|
||||
}
|
||||
|
||||
public void addInstr(IrInstr instr) {
|
||||
instrs.add(instr);
|
||||
instr.setBBlock(this);
|
||||
}
|
||||
|
||||
public IrFuncValue getFunc() {
|
||||
return func;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return instrs.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEntry() {
|
||||
return this.func.getBBlock(0) == this;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getPreds() {
|
||||
return preds;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getSuccs() {
|
||||
return succs;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName() + ":\n\t");
|
||||
for (IrInstr instr : instrs) {
|
||||
sb.append(instr.toString());
|
||||
if (instr != instrs.get(instrs.size() - 1)) {
|
||||
sb.append("\n\t");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean lastIsReturn() {
|
||||
if (instrs.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return instrs.get(instrs.size() - 1) instanceof ReturnInstr;
|
||||
}
|
||||
|
||||
public void clearCfg() {
|
||||
this.preds.clear();
|
||||
this.succs.clear();
|
||||
domied.clear();
|
||||
directDomi = null;
|
||||
directDomies.clear();
|
||||
domiFrontier.clear();
|
||||
}
|
||||
|
||||
public ArrayList<IrInstr> getInstrs() {
|
||||
return instrs;
|
||||
}
|
||||
|
||||
public void addPred(IrBasicBlock bb) {
|
||||
this.preds.add(bb);
|
||||
}
|
||||
|
||||
public void addSucc(IrBasicBlock bb) {
|
||||
this.succs.add(bb);
|
||||
}
|
||||
|
||||
public void addDomied(IrBasicBlock bb) {
|
||||
this.domied.add(bb);
|
||||
}
|
||||
|
||||
public void addDirectDomies(IrBasicBlock bb) {
|
||||
this.directDomies.add(bb);
|
||||
}
|
||||
|
||||
public void addDomiFrontier(IrBasicBlock bb) {
|
||||
this.domiFrontier.add(bb);
|
||||
}
|
||||
|
||||
public void setDirectDomi(IrBasicBlock bb) {
|
||||
this.directDomi = bb;
|
||||
}
|
||||
|
||||
public HashSet<IrBasicBlock> getDomied() {
|
||||
return domied;
|
||||
}
|
||||
|
||||
public IrBasicBlock getDirectDomi() {
|
||||
return this.directDomi;
|
||||
}
|
||||
}
|
||||
package midend.llvm.value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import backend.mips.instr.MipsLabel;
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.type.IrBasicBlockType;
|
||||
|
||||
public class IrBasicBlock extends IrValue {
|
||||
private ArrayList<IrInstr> instrs;
|
||||
private IrFuncValue func;
|
||||
private ArrayList<IrBasicBlock> preds; //前驱
|
||||
private ArrayList<IrBasicBlock> succs; //后继
|
||||
private HashSet<IrBasicBlock> domied; //支配该节点
|
||||
private IrBasicBlock directDomi;
|
||||
private HashSet<IrBasicBlock> directDomies; //该节点直接支配
|
||||
private HashSet<IrBasicBlock> domiFrontier;
|
||||
|
||||
public IrBasicBlock(String name, IrFuncValue func) {
|
||||
super(new IrBasicBlockType(), name);
|
||||
this.func = func;
|
||||
instrs = new ArrayList<>();
|
||||
preds = new ArrayList<>();
|
||||
succs = new ArrayList<>();
|
||||
domied = new HashSet<>();
|
||||
directDomi = null;
|
||||
directDomies = new HashSet<>();
|
||||
domiFrontier = new HashSet<>();
|
||||
}
|
||||
|
||||
public void addInstr(IrInstr instr) {
|
||||
instrs.add(instr);
|
||||
instr.setBBlock(this);
|
||||
}
|
||||
|
||||
public IrFuncValue getFunc() {
|
||||
return func;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return instrs.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEntry() {
|
||||
return this.func.getBBlock(0) == this;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getPreds() {
|
||||
return preds;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getSuccs() {
|
||||
return succs;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getName() + ":\n\t");
|
||||
for (IrInstr instr : instrs) {
|
||||
sb.append(instr.toString());
|
||||
if (instr != instrs.get(instrs.size() - 1)) {
|
||||
sb.append("\n\t");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean lastIsReturn() {
|
||||
if (instrs.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return instrs.get(instrs.size() - 1) instanceof ReturnInstr;
|
||||
}
|
||||
|
||||
public void clearCfg() {
|
||||
this.preds.clear();
|
||||
this.succs.clear();
|
||||
domied.clear();
|
||||
directDomi = null;
|
||||
directDomies.clear();
|
||||
domiFrontier.clear();
|
||||
}
|
||||
|
||||
public ArrayList<IrInstr> getInstrs() {
|
||||
return instrs;
|
||||
}
|
||||
|
||||
public void addPred(IrBasicBlock bb) {
|
||||
this.preds.add(bb);
|
||||
}
|
||||
|
||||
public void addSucc(IrBasicBlock bb) {
|
||||
this.succs.add(bb);
|
||||
}
|
||||
|
||||
public void addDomied(IrBasicBlock bb) {
|
||||
this.domied.add(bb);
|
||||
}
|
||||
|
||||
public void addDirectDomies(IrBasicBlock bb) {
|
||||
this.directDomies.add(bb);
|
||||
}
|
||||
|
||||
public void addDomiFrontier(IrBasicBlock bb) {
|
||||
this.domiFrontier.add(bb);
|
||||
}
|
||||
|
||||
public void setDirectDomi(IrBasicBlock bb) {
|
||||
this.directDomi = bb;
|
||||
}
|
||||
|
||||
public HashSet<IrBasicBlock> getDomied() {
|
||||
return domied;
|
||||
}
|
||||
|
||||
public IrBasicBlock getDirectDomi() {
|
||||
return this.directDomi;
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLabel(getMipsLabel());
|
||||
for (IrInstr instr : instrs) {
|
||||
instr.toMips();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
195
midend/llvm/value/IrFuncValue.java
Normal file → Executable file
195
midend/llvm/value/IrFuncValue.java
Normal file → Executable file
@@ -1,71 +1,124 @@
|
||||
package midend.llvm.value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.type.IrFuncType;
|
||||
|
||||
public class IrFuncValue extends IrValue {
|
||||
private ArrayList<IrValue> params;
|
||||
private ArrayList<IrBasicBlock> bblocks;
|
||||
|
||||
public IrFuncValue(String name, IrType retType) {
|
||||
super(new IrFuncType(retType), name);
|
||||
params = new ArrayList<>();
|
||||
bblocks = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ArrayList<IrValue> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getBBlocks() {
|
||||
return bblocks;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBBlock(int index) {
|
||||
return bblocks.get(index);
|
||||
}
|
||||
|
||||
public void addParam(IrValue param) {
|
||||
params.add(param);
|
||||
}
|
||||
|
||||
public void addBBlock(IrBasicBlock bblock) {
|
||||
bblocks.add(bblock);
|
||||
}
|
||||
|
||||
public boolean isMain() {
|
||||
return getName().equals("@main");
|
||||
}
|
||||
|
||||
public IrType getRetType() {
|
||||
return ((IrFuncType) getType()).getReturnType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("define dso_local " + this.getRetType() + " " + this.getName() + "(");
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
sb.append(params.get(i).getType() + " " + params.get(i).getName());
|
||||
if (i < params.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(") {\n");
|
||||
for (IrBasicBlock bblock : bblocks) {
|
||||
sb.append(bblock.toString() + "\n");
|
||||
}
|
||||
sb.append("}\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void checkReturn() {
|
||||
IrBasicBlock currentBB = IrBuilder.getCurrentBB();
|
||||
if (!currentBB.lastIsReturn()) {
|
||||
ReturnInstr returnInstr = new ReturnInstr(null); // 确保没有return的情况只有void
|
||||
IrBuilder.addInstr(returnInstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.llvm.value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.type.IrFuncType;
|
||||
import backend.mips.MipsBuilder;
|
||||
import backend.mips.Register;
|
||||
import backend.mips.instr.MipsLabel;
|
||||
|
||||
public class IrFuncValue extends IrValue {
|
||||
private ArrayList<IrValue> params;
|
||||
private ArrayList<IrBasicBlock> bblocks;
|
||||
private HashMap<IrValue, Register> valueRegisterMap;
|
||||
private HashMap<IrValue, Integer> valueOffsetMap;
|
||||
|
||||
public IrFuncValue(String name, IrType retType) {
|
||||
super(new IrFuncType(retType), name);
|
||||
params = new ArrayList<>();
|
||||
bblocks = new ArrayList<>();
|
||||
valueRegisterMap = new HashMap<>();
|
||||
valueOffsetMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public ArrayList<IrValue> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public ArrayList<IrBasicBlock> getBBlocks() {
|
||||
return bblocks;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBBlock(int index) {
|
||||
return bblocks.get(index);
|
||||
}
|
||||
|
||||
public void addParam(IrValue param) {
|
||||
params.add(param);
|
||||
}
|
||||
|
||||
public void addBBlock(IrBasicBlock bblock) {
|
||||
bblocks.add(bblock);
|
||||
}
|
||||
|
||||
public Register getRegister(IrValue value) {
|
||||
return valueRegisterMap.get(value);
|
||||
}
|
||||
|
||||
public int getOffset(IrValue value) {
|
||||
return valueOffsetMap.get(value);
|
||||
}
|
||||
|
||||
public void setRegister(IrValue value, Register reg) {
|
||||
valueRegisterMap.put(value, reg);
|
||||
}
|
||||
|
||||
public void setOffset(IrValue value, int offset) {
|
||||
valueOffsetMap.put(value, offset);
|
||||
}
|
||||
|
||||
public HashMap<IrValue, Register> getValueRegisterMap() {
|
||||
return valueRegisterMap;
|
||||
}
|
||||
|
||||
public HashMap<IrValue, Integer> getValueOffsetMap() {
|
||||
return valueOffsetMap;
|
||||
}
|
||||
|
||||
public boolean isMain() {
|
||||
return getName().equals("@main");
|
||||
}
|
||||
|
||||
public IrType getRetType() {
|
||||
return ((IrFuncType) getType()).getReturnType();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("define dso_local " + this.getRetType() + " " + this.getName() + "(");
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
sb.append(params.get(i).getType() + " " + params.get(i).getName());
|
||||
if (i < params.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(") {\n");
|
||||
for (IrBasicBlock bblock : bblocks) {
|
||||
sb.append(bblock.toString() + "\n");
|
||||
}
|
||||
sb.append("}\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void checkReturn() {
|
||||
IrBasicBlock currentBB = IrBuilder.getCurrentBB();
|
||||
if (!currentBB.lastIsReturn()) {
|
||||
ReturnInstr returnInstr = new ReturnInstr(null); // 确保没有return的情况只有void
|
||||
IrBuilder.addInstr(returnInstr);
|
||||
}
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
new MipsLabel(getMipsLabel());
|
||||
MipsBuilder.enterNewFunc(this);
|
||||
int num = 0;
|
||||
ArrayList<Register> paramRegs = new ArrayList<>();
|
||||
paramRegs.add(Register.A1);
|
||||
paramRegs.add(Register.A2);
|
||||
paramRegs.add(Register.A3);
|
||||
for (IrValue param : params) {
|
||||
num++;
|
||||
if (num <= 3) {
|
||||
MipsBuilder.allocaRegister(param, paramRegs.get(num - 1));
|
||||
}
|
||||
MipsBuilder.allocaOffset(param);
|
||||
}
|
||||
for (IrBasicBlock bblock : bblocks) {
|
||||
bblock.toMips();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
midend/llvm/value/IrGlobalValue.java
Normal file → Executable file
4
midend/llvm/value/IrGlobalValue.java
Normal file → Executable file
@@ -25,4 +25,8 @@ public class IrGlobalValue extends IrValue {
|
||||
return isConstant ? getName() + " = dso_local constant " + initVal.toString() :
|
||||
getName() + " = dso_local global " + initVal.toString();
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
initVal.toMips(getMipsLabel());
|
||||
}
|
||||
}
|
||||
|
||||
64
midend/llvm/value/IrLoop.java
Normal file → Executable file
64
midend/llvm/value/IrLoop.java
Normal file → Executable file
@@ -1,32 +1,32 @@
|
||||
package midend.llvm.value;
|
||||
|
||||
public class IrLoop {
|
||||
private IrBasicBlock condBB;
|
||||
private IrBasicBlock bodyBB;
|
||||
private IrBasicBlock stepBB;
|
||||
private IrBasicBlock followBB;
|
||||
|
||||
public IrLoop(IrBasicBlock condBB, IrBasicBlock bodyBB,
|
||||
IrBasicBlock stepBB, IrBasicBlock followBB) {
|
||||
this.condBB = condBB;
|
||||
this.bodyBB = bodyBB;
|
||||
this.stepBB = stepBB;
|
||||
this.followBB = followBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getCondBB() {
|
||||
return condBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBodyBB() {
|
||||
return bodyBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getStepBB() {
|
||||
return stepBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getFollowBB() {
|
||||
return followBB;
|
||||
}
|
||||
}
|
||||
package midend.llvm.value;
|
||||
|
||||
public class IrLoop {
|
||||
private IrBasicBlock condBB;
|
||||
private IrBasicBlock bodyBB;
|
||||
private IrBasicBlock stepBB;
|
||||
private IrBasicBlock followBB;
|
||||
|
||||
public IrLoop(IrBasicBlock condBB, IrBasicBlock bodyBB,
|
||||
IrBasicBlock stepBB, IrBasicBlock followBB) {
|
||||
this.condBB = condBB;
|
||||
this.bodyBB = bodyBB;
|
||||
this.stepBB = stepBB;
|
||||
this.followBB = followBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getCondBB() {
|
||||
return condBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getBodyBB() {
|
||||
return bodyBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getStepBB() {
|
||||
return stepBB;
|
||||
}
|
||||
|
||||
public IrBasicBlock getFollowBB() {
|
||||
return followBB;
|
||||
}
|
||||
}
|
||||
|
||||
8
midend/llvm/value/IrValue.java
Normal file → Executable file
8
midend/llvm/value/IrValue.java
Normal file → Executable file
@@ -35,4 +35,12 @@ public class IrValue {
|
||||
public String toString() {
|
||||
return type.toString() + " " + name;
|
||||
}
|
||||
|
||||
public void toMips() {
|
||||
// 子类实现
|
||||
}
|
||||
|
||||
public String getMipsLabel() {
|
||||
return name.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
224
midend/optimize/CfgMake.java
Normal file → Executable file
224
midend/optimize/CfgMake.java
Normal file → Executable file
@@ -1,112 +1,112 @@
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.IrInstrType;
|
||||
import midend.llvm.instr.JumpInstr;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.instr.BranchInstr;
|
||||
|
||||
public class CfgMake extends Optimizer {
|
||||
public void optimize() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
bb.clearCfg();
|
||||
}
|
||||
}
|
||||
makeCfg();
|
||||
}
|
||||
|
||||
public void makeCfg() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrInstr instr : bb.getInstrs()) {
|
||||
if (instr.getInstrType() == IrInstrType.BR) {
|
||||
BranchInstr branchInstr = (BranchInstr) instr;
|
||||
IrBasicBlock trueBlock = branchInstr.getTrueBB();
|
||||
IrBasicBlock falseBlock = branchInstr.getFalseBB();
|
||||
bb.addSucc(trueBlock);
|
||||
bb.addSucc(falseBlock);
|
||||
trueBlock.addPred(bb);
|
||||
falseBlock.addPred(bb);
|
||||
} else if (instr.getInstrType() == IrInstrType.JUMP) {
|
||||
JumpInstr jumpInstr = (JumpInstr) instr;
|
||||
IrBasicBlock jumpBlock = jumpInstr.getTargetBlock();
|
||||
bb.addSucc(jumpBlock);
|
||||
jumpBlock.addPred(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDomination() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
HashSet<IrBasicBlock> canArrive = new HashSet<>();
|
||||
handleArrive(func.getBBlock(0), bb, canArrive);
|
||||
for (IrBasicBlock block : func.getBBlocks()) {
|
||||
if (!canArrive.contains(block)) {
|
||||
block.addDomied(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleArrive(IrBasicBlock entryBlock,
|
||||
IrBasicBlock deleteBlock, HashSet<IrBasicBlock> canArrive) {
|
||||
if (entryBlock == deleteBlock) {
|
||||
return;
|
||||
} else {
|
||||
if (!canArrive.contains(entryBlock)) {
|
||||
canArrive.add(entryBlock);
|
||||
}
|
||||
for (IrBasicBlock succ : entryBlock.getSuccs()) {
|
||||
if (succ != deleteBlock && !canArrive.contains(succ)) {
|
||||
handleArrive(succ, deleteBlock, canArrive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDirectDomi() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrBasicBlock domi : bb.getDomied()) {
|
||||
HashSet<IrBasicBlock> bbDomi = bb.getDomied();
|
||||
HashSet<IrBasicBlock> domiDomi = domi.getDomied();
|
||||
for (IrBasicBlock domiDomiBB : domiDomi) {
|
||||
if (bbDomi.contains(domiDomiBB)) {
|
||||
bbDomi.remove(domiDomiBB);
|
||||
}
|
||||
}
|
||||
if (bbDomi.size() == 1 && bbDomi.contains(bb)) {
|
||||
bb.setDirectDomi(domi);
|
||||
domi.addDirectDomies(bb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDomiFrontier() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrBasicBlock succ : bb.getSuccs()) {
|
||||
IrBasicBlock currentBB = bb;
|
||||
while (!succ.getDomied().contains(currentBB) || currentBB == succ) {
|
||||
currentBB.addDomiFrontier(succ);
|
||||
currentBB = currentBB.getDirectDomi();
|
||||
if (currentBB == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.optimize;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import midend.llvm.instr.IrInstr;
|
||||
import midend.llvm.instr.IrInstrType;
|
||||
import midend.llvm.instr.JumpInstr;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.instr.BranchInstr;
|
||||
|
||||
public class CfgMake extends Optimizer {
|
||||
public void optimize() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
bb.clearCfg();
|
||||
}
|
||||
}
|
||||
makeCfg();
|
||||
}
|
||||
|
||||
public void makeCfg() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrInstr instr : bb.getInstrs()) {
|
||||
if (instr.getInstrType() == IrInstrType.BR) {
|
||||
BranchInstr branchInstr = (BranchInstr) instr;
|
||||
IrBasicBlock trueBlock = branchInstr.getTrueBB();
|
||||
IrBasicBlock falseBlock = branchInstr.getFalseBB();
|
||||
bb.addSucc(trueBlock);
|
||||
bb.addSucc(falseBlock);
|
||||
trueBlock.addPred(bb);
|
||||
falseBlock.addPred(bb);
|
||||
} else if (instr.getInstrType() == IrInstrType.JUMP) {
|
||||
JumpInstr jumpInstr = (JumpInstr) instr;
|
||||
IrBasicBlock jumpBlock = jumpInstr.getTargetBlock();
|
||||
bb.addSucc(jumpBlock);
|
||||
jumpBlock.addPred(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDomination() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
HashSet<IrBasicBlock> canArrive = new HashSet<>();
|
||||
handleArrive(func.getBBlock(0), bb, canArrive);
|
||||
for (IrBasicBlock block : func.getBBlocks()) {
|
||||
if (!canArrive.contains(block)) {
|
||||
block.addDomied(bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleArrive(IrBasicBlock entryBlock,
|
||||
IrBasicBlock deleteBlock, HashSet<IrBasicBlock> canArrive) {
|
||||
if (entryBlock == deleteBlock) {
|
||||
return;
|
||||
} else {
|
||||
if (!canArrive.contains(entryBlock)) {
|
||||
canArrive.add(entryBlock);
|
||||
}
|
||||
for (IrBasicBlock succ : entryBlock.getSuccs()) {
|
||||
if (succ != deleteBlock && !canArrive.contains(succ)) {
|
||||
handleArrive(succ, deleteBlock, canArrive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDirectDomi() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrBasicBlock domi : bb.getDomied()) {
|
||||
HashSet<IrBasicBlock> bbDomi = bb.getDomied();
|
||||
HashSet<IrBasicBlock> domiDomi = domi.getDomied();
|
||||
for (IrBasicBlock domiDomiBB : domiDomi) {
|
||||
if (bbDomi.contains(domiDomiBB)) {
|
||||
bbDomi.remove(domiDomiBB);
|
||||
}
|
||||
}
|
||||
if (bbDomi.size() == 1 && bbDomi.contains(bb)) {
|
||||
bb.setDirectDomi(domi);
|
||||
domi.addDirectDomies(bb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void makeDomiFrontier() {
|
||||
for (IrFuncValue func : getIrModule().getFuncs()) {
|
||||
for (IrBasicBlock bb : func.getBBlocks()) {
|
||||
for (IrBasicBlock succ : bb.getSuccs()) {
|
||||
IrBasicBlock currentBB = bb;
|
||||
while (!succ.getDomied().contains(currentBB) || currentBB == succ) {
|
||||
currentBB.addDomiFrontier(succ);
|
||||
currentBB = currentBB.getDirectDomi();
|
||||
if (currentBB == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
midend/optimize/Optimizer.java
Normal file → Executable file
38
midend/optimize/Optimizer.java
Normal file → Executable file
@@ -1,19 +1,19 @@
|
||||
package midend.optimize;
|
||||
|
||||
import midend.llvm.IrModule;
|
||||
|
||||
public class Optimizer {
|
||||
private static IrModule irModule;
|
||||
|
||||
public void setIrModule(IrModule irModule) {
|
||||
Optimizer.irModule = irModule;
|
||||
}
|
||||
|
||||
public static IrModule getIrModule() {
|
||||
return irModule;
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
|
||||
}
|
||||
}
|
||||
package midend.optimize;
|
||||
|
||||
import midend.llvm.IrModule;
|
||||
|
||||
public class Optimizer {
|
||||
private static IrModule irModule;
|
||||
|
||||
public void setIrModule(IrModule irModule) {
|
||||
Optimizer.irModule = irModule;
|
||||
}
|
||||
|
||||
public static IrModule getIrModule() {
|
||||
return irModule;
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
40
midend/symbol/ArraySymbol.java
Normal file → Executable file
40
midend/symbol/ArraySymbol.java
Normal file → Executable file
@@ -1,20 +1,20 @@
|
||||
package midend.symbol;
|
||||
|
||||
public class ArraySymbol extends Symbol {
|
||||
private int dim; // -1 means unknown
|
||||
|
||||
public ArraySymbol(String name, SymbolType type, int line, int dim) {
|
||||
super(name, type, line);
|
||||
this.dim = dim;
|
||||
}
|
||||
|
||||
public int getDim() {
|
||||
return dim;
|
||||
}
|
||||
|
||||
public void fullValue() {
|
||||
for (int i = getValueList().size(); i < dim; i++) {
|
||||
addValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
public class ArraySymbol extends Symbol {
|
||||
private int dim; // -1 means unknown
|
||||
|
||||
public ArraySymbol(String name, SymbolType type, int line, int dim) {
|
||||
super(name, type, line);
|
||||
this.dim = dim;
|
||||
}
|
||||
|
||||
public int getDim() {
|
||||
return dim;
|
||||
}
|
||||
|
||||
public void fullValue() {
|
||||
for (int i = getValueList().size(); i < dim; i++) {
|
||||
addValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
midend/symbol/FuncSymbol.java
Normal file → Executable file
100
midend/symbol/FuncSymbol.java
Normal file → Executable file
@@ -1,50 +1,50 @@
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FuncSymbol extends Symbol {
|
||||
private int returnType; // 0 for void, 1 for int
|
||||
private ArrayList<Integer> paramList; // 0 for var, 1 for array
|
||||
private ArrayList<Symbol> paramSymbolList;
|
||||
|
||||
public FuncSymbol(String name, SymbolType type, int line, int returnType) {
|
||||
super(name, type, line);
|
||||
paramList = new ArrayList<>();
|
||||
paramSymbolList = new ArrayList<>();
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
public void addParam(int param) {
|
||||
paramList.add(param);
|
||||
}
|
||||
|
||||
public void addParamSymbol(Symbol paramSymbol) {
|
||||
paramSymbolList.add(paramSymbol);
|
||||
}
|
||||
|
||||
public int getParamNum() {
|
||||
return paramList.size();
|
||||
}
|
||||
|
||||
public int getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public int getParamType(int index) {
|
||||
return paramList.get(index);
|
||||
}
|
||||
|
||||
public void printParams() {
|
||||
for (int i = 0; i < paramList.size(); i++) {
|
||||
System.out.print(paramList.get(i) + " ");
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getParamList() {
|
||||
return paramList;
|
||||
}
|
||||
|
||||
public ArrayList<Symbol> getParamSymbolList() {
|
||||
return paramSymbolList;
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FuncSymbol extends Symbol {
|
||||
private int returnType; // 0 for void, 1 for int
|
||||
private ArrayList<Integer> paramList; // 0 for var, 1 for array
|
||||
private ArrayList<Symbol> paramSymbolList;
|
||||
|
||||
public FuncSymbol(String name, SymbolType type, int line, int returnType) {
|
||||
super(name, type, line);
|
||||
paramList = new ArrayList<>();
|
||||
paramSymbolList = new ArrayList<>();
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
public void addParam(int param) {
|
||||
paramList.add(param);
|
||||
}
|
||||
|
||||
public void addParamSymbol(Symbol paramSymbol) {
|
||||
paramSymbolList.add(paramSymbol);
|
||||
}
|
||||
|
||||
public int getParamNum() {
|
||||
return paramList.size();
|
||||
}
|
||||
|
||||
public int getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public int getParamType(int index) {
|
||||
return paramList.get(index);
|
||||
}
|
||||
|
||||
public void printParams() {
|
||||
for (int i = 0; i < paramList.size(); i++) {
|
||||
System.out.print(paramList.get(i) + " ");
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getParamList() {
|
||||
return paramList;
|
||||
}
|
||||
|
||||
public ArrayList<Symbol> getParamSymbolList() {
|
||||
return paramSymbolList;
|
||||
}
|
||||
}
|
||||
|
||||
154
midend/symbol/Symbol.java
Normal file → Executable file
154
midend/symbol/Symbol.java
Normal file → Executable file
@@ -1,77 +1,77 @@
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class Symbol {
|
||||
private String name;
|
||||
private SymbolType type;
|
||||
private int line;
|
||||
private ArrayList<Integer> valueList;
|
||||
private IrValue irValue;
|
||||
|
||||
public Symbol(String name, SymbolType type, int line) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.line = line;
|
||||
valueList = new ArrayList<>();
|
||||
irValue = null;
|
||||
}
|
||||
|
||||
public void setIrValue(IrValue irValue) {
|
||||
this.irValue = irValue;
|
||||
}
|
||||
|
||||
public IrValue getIrValue() {
|
||||
return irValue;
|
||||
}
|
||||
|
||||
public void addValue(int value) {
|
||||
valueList.add(value);
|
||||
}
|
||||
|
||||
public void addValue(ArrayList<Integer> valueList) {
|
||||
this.valueList.addAll(valueList);
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getValueList() {
|
||||
return valueList;
|
||||
}
|
||||
|
||||
public int getValue(int index) {
|
||||
return valueList.get(index);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTypeStr() {
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + " " + type.toString() + "\n";
|
||||
}
|
||||
|
||||
public boolean isThatType(int type) { // 0 for normal var, 1 for array, 2 for func
|
||||
if (type == 1) {
|
||||
return this.type == SymbolType.INT_ARRAY || this.type == SymbolType.CONST_INT_ARRAY
|
||||
|| this.type == SymbolType.STATIC_INT_ARRAY;
|
||||
} else if (type == 2) {
|
||||
return this.type == SymbolType.INT_FUNC || this.type == SymbolType.VOID_FUNC;
|
||||
} else {
|
||||
return this.type == SymbolType.INT || this.type == SymbolType.CONST_INT
|
||||
|| this.type == SymbolType.STATIC_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
public class Symbol {
|
||||
private String name;
|
||||
private SymbolType type;
|
||||
private int line;
|
||||
private ArrayList<Integer> valueList;
|
||||
private IrValue irValue;
|
||||
|
||||
public Symbol(String name, SymbolType type, int line) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.line = line;
|
||||
valueList = new ArrayList<>();
|
||||
irValue = null;
|
||||
}
|
||||
|
||||
public void setIrValue(IrValue irValue) {
|
||||
this.irValue = irValue;
|
||||
}
|
||||
|
||||
public IrValue getIrValue() {
|
||||
return irValue;
|
||||
}
|
||||
|
||||
public void addValue(int value) {
|
||||
valueList.add(value);
|
||||
}
|
||||
|
||||
public void addValue(ArrayList<Integer> valueList) {
|
||||
this.valueList.addAll(valueList);
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getValueList() {
|
||||
return valueList;
|
||||
}
|
||||
|
||||
public int getValue(int index) {
|
||||
return valueList.get(index);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTypeStr() {
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + " " + type.toString() + "\n";
|
||||
}
|
||||
|
||||
public boolean isThatType(int type) { // 0 for normal var, 1 for array, 2 for func
|
||||
if (type == 1) {
|
||||
return this.type == SymbolType.INT_ARRAY || this.type == SymbolType.CONST_INT_ARRAY
|
||||
|| this.type == SymbolType.STATIC_INT_ARRAY;
|
||||
} else if (type == 2) {
|
||||
return this.type == SymbolType.INT_FUNC || this.type == SymbolType.VOID_FUNC;
|
||||
} else {
|
||||
return this.type == SymbolType.INT || this.type == SymbolType.CONST_INT
|
||||
|| this.type == SymbolType.STATIC_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
272
midend/symbol/SymbolManager.java
Normal file → Executable file
272
midend/symbol/SymbolManager.java
Normal file → Executable file
@@ -1,136 +1,136 @@
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import error.Errors;
|
||||
|
||||
public class SymbolManager {
|
||||
public static ArrayList<SymbolTable> symbolTableList;
|
||||
public static ArrayList<Integer> sequence;
|
||||
public static SymbolTable currentTable;
|
||||
public static int currentSequence;
|
||||
|
||||
public static void init() {
|
||||
symbolTableList = new ArrayList<>();
|
||||
sequence = new ArrayList<>();
|
||||
currentTable = null;
|
||||
currentSequence = -1;
|
||||
}
|
||||
|
||||
public static void addSymbolTable() {
|
||||
SymbolTable symbolTable = new SymbolTable(symbolTableList.size() + 1);
|
||||
symbolTableList.add(symbolTable);
|
||||
sequence.add(symbolTable.getTableId());
|
||||
currentSequence++;
|
||||
if (currentTable != null) {
|
||||
symbolTable.setParentTable(currentTable);
|
||||
}
|
||||
currentTable = symbolTable;
|
||||
}
|
||||
|
||||
public static ArrayList<SymbolTable> getSymbolTableList() {
|
||||
return symbolTableList;
|
||||
}
|
||||
|
||||
public static void releaseSymbolTable(int tableId) {
|
||||
symbolTableList.get(tableId - 1).release();
|
||||
currentTable = null;
|
||||
for (int i = symbolTableList.size() - 1; i >= 0; i--) {
|
||||
if (!symbolTableList.get(i).isReleased()) {
|
||||
currentTable = symbolTableList.get(i);
|
||||
currentSequence++;
|
||||
sequence.add(currentTable.getTableId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void releaseSymbolTable() {
|
||||
releaseSymbolTable(currentTable.getTableId());
|
||||
}
|
||||
|
||||
public static int getSymbolTableSize() {
|
||||
return symbolTableList.size();
|
||||
}
|
||||
|
||||
public static void addSymbol(Symbol symbol, Errors errors) {
|
||||
currentTable.addSymbol(symbol, errors);
|
||||
}
|
||||
|
||||
public static String getSymbolTableInfo() {
|
||||
String info = "";
|
||||
for (SymbolTable symbolTable : symbolTableList) {
|
||||
info += symbolTable.toString();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public static Symbol getSymbol(String name) {
|
||||
SymbolTable stable = currentTable;
|
||||
Symbol symbol = null;
|
||||
while (stable != null) {
|
||||
symbol = stable.getSymbol(name);
|
||||
if (symbol != null) {
|
||||
break;
|
||||
}
|
||||
stable = stable.getParentTable();
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static Symbol getSymbol(String name, boolean defined) {
|
||||
SymbolTable stable = currentTable;
|
||||
Symbol symbol = null;
|
||||
while (stable != null) {
|
||||
symbol = stable.getSymbol(name);
|
||||
if (symbol != null && symbol.getIrValue() != null) {
|
||||
break;
|
||||
}
|
||||
stable = stable.getParentTable();
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static void nextTable() {
|
||||
currentSequence++;
|
||||
if (currentSequence >= sequence.size()) {
|
||||
return;
|
||||
}
|
||||
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||
}
|
||||
|
||||
public static void lastTable() {
|
||||
currentSequence--;
|
||||
if (currentSequence < 0) {
|
||||
currentSequence = 0;
|
||||
currentTable = symbolTableList.get(0);
|
||||
return;
|
||||
}
|
||||
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
currentSequence = -1;
|
||||
currentTable = null;
|
||||
}
|
||||
|
||||
public static boolean IsGlobal() {
|
||||
return currentTable.getTableId() == 1;
|
||||
}
|
||||
|
||||
public static ArrayList<Integer> getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public static int getCurrentSequence() {
|
||||
return currentSequence;
|
||||
}
|
||||
|
||||
public static int getCurrentTableId() {
|
||||
return sequence.get(currentSequence);
|
||||
}
|
||||
|
||||
public static SymbolTable getCurrentTable() {
|
||||
return currentTable;
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import error.Errors;
|
||||
|
||||
public class SymbolManager {
|
||||
public static ArrayList<SymbolTable> symbolTableList;
|
||||
public static ArrayList<Integer> sequence;
|
||||
public static SymbolTable currentTable;
|
||||
public static int currentSequence;
|
||||
|
||||
public static void init() {
|
||||
symbolTableList = new ArrayList<>();
|
||||
sequence = new ArrayList<>();
|
||||
currentTable = null;
|
||||
currentSequence = -1;
|
||||
}
|
||||
|
||||
public static void addSymbolTable() {
|
||||
SymbolTable symbolTable = new SymbolTable(symbolTableList.size() + 1);
|
||||
symbolTableList.add(symbolTable);
|
||||
sequence.add(symbolTable.getTableId());
|
||||
currentSequence++;
|
||||
if (currentTable != null) {
|
||||
symbolTable.setParentTable(currentTable);
|
||||
}
|
||||
currentTable = symbolTable;
|
||||
}
|
||||
|
||||
public static ArrayList<SymbolTable> getSymbolTableList() {
|
||||
return symbolTableList;
|
||||
}
|
||||
|
||||
public static void releaseSymbolTable(int tableId) {
|
||||
symbolTableList.get(tableId - 1).release();
|
||||
currentTable = null;
|
||||
for (int i = symbolTableList.size() - 1; i >= 0; i--) {
|
||||
if (!symbolTableList.get(i).isReleased()) {
|
||||
currentTable = symbolTableList.get(i);
|
||||
currentSequence++;
|
||||
sequence.add(currentTable.getTableId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void releaseSymbolTable() {
|
||||
releaseSymbolTable(currentTable.getTableId());
|
||||
}
|
||||
|
||||
public static int getSymbolTableSize() {
|
||||
return symbolTableList.size();
|
||||
}
|
||||
|
||||
public static void addSymbol(Symbol symbol, Errors errors) {
|
||||
currentTable.addSymbol(symbol, errors);
|
||||
}
|
||||
|
||||
public static String getSymbolTableInfo() {
|
||||
String info = "";
|
||||
for (SymbolTable symbolTable : symbolTableList) {
|
||||
info += symbolTable.toString();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public static Symbol getSymbol(String name) {
|
||||
SymbolTable stable = currentTable;
|
||||
Symbol symbol = null;
|
||||
while (stable != null) {
|
||||
symbol = stable.getSymbol(name);
|
||||
if (symbol != null) {
|
||||
break;
|
||||
}
|
||||
stable = stable.getParentTable();
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static Symbol getSymbol(String name, boolean defined) {
|
||||
SymbolTable stable = currentTable;
|
||||
Symbol symbol = null;
|
||||
while (stable != null) {
|
||||
symbol = stable.getSymbol(name);
|
||||
if (symbol != null && symbol.getIrValue() != null) {
|
||||
break;
|
||||
}
|
||||
stable = stable.getParentTable();
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public static void nextTable() {
|
||||
currentSequence++;
|
||||
if (currentSequence >= sequence.size()) {
|
||||
return;
|
||||
}
|
||||
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||
}
|
||||
|
||||
public static void lastTable() {
|
||||
currentSequence--;
|
||||
if (currentSequence < 0) {
|
||||
currentSequence = 0;
|
||||
currentTable = symbolTableList.get(0);
|
||||
return;
|
||||
}
|
||||
currentTable = symbolTableList.get(sequence.get(currentSequence) - 1);
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
currentSequence = -1;
|
||||
currentTable = null;
|
||||
}
|
||||
|
||||
public static boolean IsGlobal() {
|
||||
return currentTable.getTableId() == 1;
|
||||
}
|
||||
|
||||
public static ArrayList<Integer> getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public static int getCurrentSequence() {
|
||||
return currentSequence;
|
||||
}
|
||||
|
||||
public static int getCurrentTableId() {
|
||||
return sequence.get(currentSequence);
|
||||
}
|
||||
|
||||
public static SymbolTable getCurrentTable() {
|
||||
return currentTable;
|
||||
}
|
||||
}
|
||||
|
||||
136
midend/symbol/SymbolTable.java
Normal file → Executable file
136
midend/symbol/SymbolTable.java
Normal file → Executable file
@@ -1,68 +1,68 @@
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import error.Error;
|
||||
import error.ErrorType;
|
||||
import error.Errors;
|
||||
|
||||
public class SymbolTable {
|
||||
private ArrayList<Symbol> symbolList;
|
||||
private HashMap<String, Symbol> symbolMap;
|
||||
private int tableId;
|
||||
private boolean isReleased;
|
||||
private SymbolTable parentTable;
|
||||
|
||||
public SymbolTable(int tableId) {
|
||||
this.tableId = tableId;
|
||||
isReleased = false;
|
||||
symbolList = new ArrayList<>();
|
||||
symbolMap = new HashMap<>();
|
||||
parentTable = null;
|
||||
}
|
||||
|
||||
public int getTableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public boolean isReleased() {
|
||||
return isReleased;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
isReleased = true;
|
||||
}
|
||||
|
||||
public void addSymbol(Symbol symbol, Errors errors) {
|
||||
if (symbolMap.containsKey(symbol.getName())) {
|
||||
errors.addError(new Error(symbol.getLine(), ErrorType.b));
|
||||
return;
|
||||
}
|
||||
symbolList.add(symbol);
|
||||
symbolMap.put(symbol.getName(), symbol);
|
||||
}
|
||||
|
||||
public void setParentTable(SymbolTable parentTable) {
|
||||
this.parentTable = parentTable;
|
||||
}
|
||||
|
||||
public SymbolTable getParentTable() {
|
||||
return parentTable;
|
||||
}
|
||||
|
||||
public Symbol getSymbol(String name) {
|
||||
if (symbolMap.containsKey(name)) {
|
||||
return symbolMap.get(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String info = "";
|
||||
for (Symbol symbol : symbolList) {
|
||||
info += tableId + " " + symbol.toString();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import error.Error;
|
||||
import error.ErrorType;
|
||||
import error.Errors;
|
||||
|
||||
public class SymbolTable {
|
||||
private ArrayList<Symbol> symbolList;
|
||||
private HashMap<String, Symbol> symbolMap;
|
||||
private int tableId;
|
||||
private boolean isReleased;
|
||||
private SymbolTable parentTable;
|
||||
|
||||
public SymbolTable(int tableId) {
|
||||
this.tableId = tableId;
|
||||
isReleased = false;
|
||||
symbolList = new ArrayList<>();
|
||||
symbolMap = new HashMap<>();
|
||||
parentTable = null;
|
||||
}
|
||||
|
||||
public int getTableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public boolean isReleased() {
|
||||
return isReleased;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
isReleased = true;
|
||||
}
|
||||
|
||||
public void addSymbol(Symbol symbol, Errors errors) {
|
||||
if (symbolMap.containsKey(symbol.getName())) {
|
||||
errors.addError(new Error(symbol.getLine(), ErrorType.b));
|
||||
return;
|
||||
}
|
||||
symbolList.add(symbol);
|
||||
symbolMap.put(symbol.getName(), symbol);
|
||||
}
|
||||
|
||||
public void setParentTable(SymbolTable parentTable) {
|
||||
this.parentTable = parentTable;
|
||||
}
|
||||
|
||||
public SymbolTable getParentTable() {
|
||||
return parentTable;
|
||||
}
|
||||
|
||||
public Symbol getSymbol(String name) {
|
||||
if (symbolMap.containsKey(name)) {
|
||||
return symbolMap.get(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String info = "";
|
||||
for (Symbol symbol : symbolList) {
|
||||
info += tableId + " " + symbol.toString();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
44
midend/symbol/SymbolType.java
Normal file → Executable file
44
midend/symbol/SymbolType.java
Normal file → Executable file
@@ -1,22 +1,22 @@
|
||||
package midend.symbol;
|
||||
|
||||
public enum SymbolType {
|
||||
CONST_INT("ConstInt"),
|
||||
CONST_INT_ARRAY("ConstIntArray"),
|
||||
STATIC_INT("StaticInt"),
|
||||
INT("Int"),
|
||||
INT_ARRAY("IntArray"),
|
||||
STATIC_INT_ARRAY("StaticIntArray"),
|
||||
VOID_FUNC("VoidFunc"),
|
||||
INT_FUNC("IntFunc");
|
||||
|
||||
private final String type;
|
||||
SymbolType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
package midend.symbol;
|
||||
|
||||
public enum SymbolType {
|
||||
CONST_INT("ConstInt"),
|
||||
CONST_INT_ARRAY("ConstIntArray"),
|
||||
STATIC_INT("StaticInt"),
|
||||
INT("Int"),
|
||||
INT_ARRAY("IntArray"),
|
||||
STATIC_INT_ARRAY("StaticIntArray"),
|
||||
VOID_FUNC("VoidFunc"),
|
||||
INT_FUNC("IntFunc");
|
||||
|
||||
private final String type;
|
||||
SymbolType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
72
midend/visit/Visitor.java
Normal file → Executable file
72
midend/visit/Visitor.java
Normal file → Executable file
@@ -1,36 +1,36 @@
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.CompUnit;
|
||||
import frontend.ast.decl.Decl;
|
||||
import frontend.ast.func.FuncDef;
|
||||
import frontend.ast.func.MainFuncDef;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class Visitor {
|
||||
private CompUnit compUnit;
|
||||
|
||||
public Visitor(CompUnit compUnit) {
|
||||
this.compUnit = compUnit;
|
||||
SymbolManager.reset();
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
|
||||
public void visit() {
|
||||
ArrayList<Decl> decls = this.compUnit.GetDecls();
|
||||
ArrayList<FuncDef> funcDefs = this.compUnit.GetFuncDefs();
|
||||
MainFuncDef mainFuncDef = this.compUnit.GetMainFuncDef();
|
||||
|
||||
for (Decl decl : decls) {
|
||||
VisitorDecl.visitDecl(decl);
|
||||
}
|
||||
|
||||
for (FuncDef funcDef : funcDefs) {
|
||||
VisitorFuncDef.visitFuncDef(funcDef);
|
||||
}
|
||||
|
||||
VisitorFuncDef.visitMainFuncDef(mainFuncDef);
|
||||
}
|
||||
//:TODO:符号表的变换,什么时候往前进一个符号表,这需要人工手工来操作
|
||||
}
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.CompUnit;
|
||||
import frontend.ast.decl.Decl;
|
||||
import frontend.ast.func.FuncDef;
|
||||
import frontend.ast.func.MainFuncDef;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class Visitor {
|
||||
private CompUnit compUnit;
|
||||
|
||||
public Visitor(CompUnit compUnit) {
|
||||
this.compUnit = compUnit;
|
||||
SymbolManager.reset();
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
|
||||
public void visit() {
|
||||
ArrayList<Decl> decls = this.compUnit.GetDecls();
|
||||
ArrayList<FuncDef> funcDefs = this.compUnit.GetFuncDefs();
|
||||
MainFuncDef mainFuncDef = this.compUnit.GetMainFuncDef();
|
||||
|
||||
for (Decl decl : decls) {
|
||||
VisitorDecl.visitDecl(decl);
|
||||
}
|
||||
|
||||
for (FuncDef funcDef : funcDefs) {
|
||||
VisitorFuncDef.visitFuncDef(funcDef);
|
||||
}
|
||||
|
||||
VisitorFuncDef.visitMainFuncDef(mainFuncDef);
|
||||
}
|
||||
//:TODO:符号表的变换,什么时候往前进一个符号表,这需要人工手工来操作
|
||||
}
|
||||
|
||||
70
midend/visit/VisitorBlock.java
Normal file → Executable file
70
midend/visit/VisitorBlock.java
Normal file → Executable file
@@ -1,35 +1,35 @@
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.block.BlockItem;
|
||||
import frontend.ast.block.Stmt;
|
||||
import frontend.ast.decl.Decl;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class VisitorBlock {
|
||||
public static void visitBlock(Block block) {
|
||||
if (!block.isFuncBlock()) {
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());
|
||||
// System.out.println("bsequence: " + SymbolManager.getCurrentSequence());//TODO:debug
|
||||
ArrayList<BlockItem> blockItems = block.getBlockItems();
|
||||
for (BlockItem blockItem : blockItems) {
|
||||
visitBlockItem(blockItem);
|
||||
}
|
||||
if (!block.isFuncBlock()) {
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
}
|
||||
|
||||
public static void visitBlockItem(BlockItem blockItem) {
|
||||
if (blockItem.getChild(0) instanceof Decl) {
|
||||
VisitorDecl.visitDecl((Decl) blockItem.getChild(0));
|
||||
} else {
|
||||
VisitorStmt.visitStmt((Stmt) blockItem.getChild(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.block.BlockItem;
|
||||
import frontend.ast.block.Stmt;
|
||||
import frontend.ast.decl.Decl;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class VisitorBlock {
|
||||
public static void visitBlock(Block block) {
|
||||
if (!block.isFuncBlock()) {
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());
|
||||
// System.out.println("bsequence: " + SymbolManager.getCurrentSequence());//TODO:debug
|
||||
ArrayList<BlockItem> blockItems = block.getBlockItems();
|
||||
for (BlockItem blockItem : blockItems) {
|
||||
visitBlockItem(blockItem);
|
||||
}
|
||||
if (!block.isFuncBlock()) {
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
// System.out.println("(block)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
}
|
||||
|
||||
public static void visitBlockItem(BlockItem blockItem) {
|
||||
if (blockItem.getChild(0) instanceof Decl) {
|
||||
VisitorDecl.visitDecl((Decl) blockItem.getChild(0));
|
||||
} else {
|
||||
VisitorStmt.visitStmt((Stmt) blockItem.getChild(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
334
midend/visit/VisitorDecl.java
Normal file → Executable file
334
midend/visit/VisitorDecl.java
Normal file → Executable file
@@ -1,167 +1,167 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
528
midend/visit/VisitorExp.java
Normal file → Executable file
528
midend/visit/VisitorExp.java
Normal file → Executable file
@@ -1,264 +1,264 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
158
midend/visit/VisitorFuncDef.java
Normal file → Executable file
158
midend/visit/VisitorFuncDef.java
Normal file → Executable file
@@ -1,80 +1,80 @@
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.func.FuncDef;
|
||||
import frontend.ast.func.MainFuncDef;
|
||||
import frontend.ast.token.TokenNode;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.instr.AllocateInstr;
|
||||
import midend.llvm.instr.StoreInstr;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
import midend.symbol.Symbol;
|
||||
import midend.symbol.FuncSymbol;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class VisitorFuncDef {
|
||||
public static void visitFuncDef(FuncDef funcDef) {
|
||||
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(
|
||||
((TokenNode) funcDef.getChild(1)).getName());
|
||||
IrInterType returnType = funcSymbol.getReturnType() == 1
|
||||
? IrInterType.INT32
|
||||
: IrInterType.VOID;
|
||||
IrFuncValue funcValue = new IrFuncValue(
|
||||
IrBuilder.geFuncName(funcSymbol.getName()), returnType);
|
||||
IrBuilder.addNewFunc(funcValue);
|
||||
funcSymbol.setIrValue(funcValue);
|
||||
// 进入函数作用域
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
ArrayList<Integer> paramList = funcSymbol.getParamList();
|
||||
ArrayList<Symbol> paramSymbolList = funcSymbol.getParamSymbolList();
|
||||
ArrayList<IrValue> irParamList = new ArrayList<>();
|
||||
for (int i = 0; i < paramList.size(); i++) {
|
||||
if (paramList.get(i) == 0) {
|
||||
IrValue param = new IrValue(IrInterType.INT32, IrBuilder.getLocalName());
|
||||
irParamList.add(param);
|
||||
funcValue.addParam(param);
|
||||
} else {
|
||||
IrValue param = new IrValue(
|
||||
new IrPointerType(IrInterType.INT32), IrBuilder.getLocalName());
|
||||
irParamList.add(param);
|
||||
funcValue.addParam(param);
|
||||
paramSymbolList.get(i).setIrValue(param);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < irParamList.size(); i++) {
|
||||
if (paramList.get(i) == 1) {
|
||||
continue; // 数组参数不分配内存
|
||||
}
|
||||
AllocateInstr allocateInstr = new AllocateInstr(
|
||||
irParamList.get(i).getType(), IrBuilder.getLocalName());
|
||||
IrBuilder.addInstr(allocateInstr);
|
||||
StoreInstr storeInstr = new StoreInstr(irParamList.get(i), allocateInstr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
paramSymbolList.get(i).setIrValue(allocateInstr);
|
||||
} //这里貌似可以不用allocate?函数形参似乎可以直接拿来用?
|
||||
Block block = (Block) funcDef.getChild(funcDef.getChildren().size() - 1);
|
||||
VisitorBlock.visitBlock(block);
|
||||
// TODO:check return?
|
||||
funcValue.checkReturn();
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
}
|
||||
|
||||
public static void visitMainFuncDef(MainFuncDef mainFuncDef) {
|
||||
IrFuncValue mainFuncValue = new IrFuncValue(
|
||||
IrBuilder.geFuncName("main"), IrInterType.INT32);
|
||||
IrBuilder.addNewFunc(mainFuncValue);
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(mainfunc)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
Block block = (Block) mainFuncDef.getChild(mainFuncDef.getChildren().size() - 1);
|
||||
VisitorBlock.visitBlock(block);
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.func.FuncDef;
|
||||
import frontend.ast.func.MainFuncDef;
|
||||
import frontend.ast.token.TokenNode;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.instr.AllocateInstr;
|
||||
import midend.llvm.instr.StoreInstr;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrPointerType;
|
||||
import midend.llvm.value.IrFuncValue;
|
||||
import midend.llvm.value.IrValue;
|
||||
|
||||
import midend.symbol.Symbol;
|
||||
import midend.symbol.FuncSymbol;
|
||||
import midend.symbol.SymbolManager;
|
||||
|
||||
public class VisitorFuncDef {
|
||||
public static void visitFuncDef(FuncDef funcDef) {
|
||||
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(
|
||||
((TokenNode) funcDef.getChild(1)).getName());
|
||||
IrInterType returnType = funcSymbol.getReturnType() == 1
|
||||
? IrInterType.INT32
|
||||
: IrInterType.VOID;
|
||||
IrFuncValue funcValue = new IrFuncValue(
|
||||
IrBuilder.geFuncName(funcSymbol.getName()), returnType);
|
||||
IrBuilder.addNewFunc(funcValue);
|
||||
funcSymbol.setIrValue(funcValue);
|
||||
// 进入函数作用域
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
ArrayList<Integer> paramList = funcSymbol.getParamList();
|
||||
ArrayList<Symbol> paramSymbolList = funcSymbol.getParamSymbolList();
|
||||
ArrayList<IrValue> irParamList = new ArrayList<>();
|
||||
for (int i = 0; i < paramList.size(); i++) {
|
||||
if (paramList.get(i) == 0) {
|
||||
IrValue param = new IrValue(IrInterType.INT32, IrBuilder.getLocalName());
|
||||
irParamList.add(param);
|
||||
funcValue.addParam(param);
|
||||
} else {
|
||||
IrValue param = new IrValue(
|
||||
new IrPointerType(IrInterType.INT32), IrBuilder.getLocalName());
|
||||
irParamList.add(param);
|
||||
funcValue.addParam(param);
|
||||
paramSymbolList.get(i).setIrValue(param);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < irParamList.size(); i++) {
|
||||
if (paramList.get(i) == 1) {
|
||||
continue; // 数组参数不分配内存
|
||||
}
|
||||
AllocateInstr allocateInstr = new AllocateInstr(
|
||||
irParamList.get(i).getType(), IrBuilder.getLocalName());
|
||||
IrBuilder.addInstr(allocateInstr);
|
||||
StoreInstr storeInstr = new StoreInstr(irParamList.get(i), allocateInstr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
paramSymbolList.get(i).setIrValue(allocateInstr);
|
||||
} //这里貌似可以不用allocate?函数形参似乎可以直接拿来用?
|
||||
Block block = (Block) funcDef.getChild(funcDef.getChildren().size() - 1);
|
||||
VisitorBlock.visitBlock(block);
|
||||
// TODO:check return?
|
||||
funcValue.checkReturn();
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(func)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
}
|
||||
|
||||
public static void visitMainFuncDef(MainFuncDef mainFuncDef) {
|
||||
IrFuncValue mainFuncValue = new IrFuncValue(
|
||||
IrBuilder.geFuncName("main"), IrInterType.INT32);
|
||||
IrBuilder.addNewFunc(mainFuncValue);
|
||||
SymbolManager.nextTable();
|
||||
// System.out.println("(mainfunc)now table: " + SymbolManager.getCurrentTableId());//TODO:debug
|
||||
Block block = (Block) mainFuncDef.getChild(mainFuncDef.getChildren().size() - 1);
|
||||
VisitorBlock.visitBlock(block);
|
||||
SymbolManager.nextTable();
|
||||
}
|
||||
}
|
||||
542
midend/visit/VisitorStmt.java
Normal file → Executable file
542
midend/visit/VisitorStmt.java
Normal file → Executable file
@@ -1,271 +1,271 @@
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.block.ForStmt;
|
||||
import frontend.ast.block.Stmt;
|
||||
import frontend.ast.exp.Cond;
|
||||
import frontend.ast.exp.Exp;
|
||||
import frontend.ast.exp.LVal;
|
||||
import frontend.ast.token.TokenNode;
|
||||
import frontend.lexer.Token;
|
||||
import midend.symbol.SymbolManager;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.instr.GetIntInstr;
|
||||
import midend.llvm.instr.JumpInstr;
|
||||
import midend.llvm.instr.PutIntInstr;
|
||||
import midend.llvm.instr.PutStrInstr;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.instr.StoreInstr;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.value.IrLoop;
|
||||
|
||||
public class VisitorStmt {
|
||||
public static void visitStmt(Stmt stmt) {
|
||||
if (stmt.getChild(0) instanceof LVal) {
|
||||
visitAssign(stmt);
|
||||
} else if (stmt.getChild(0) instanceof Exp
|
||||
|| (stmt.getChild(0) instanceof TokenNode
|
||||
&& ((TokenNode) stmt.getChild(0)).getValue().equals(";"))) {
|
||||
visitExp(stmt);
|
||||
} else if (stmt.getChild(0) instanceof Block) {
|
||||
visitBlock(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("if")) {
|
||||
visitIf(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("for")) {
|
||||
visitFor(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("break")) {
|
||||
visitBreak(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("continue")) {
|
||||
visitContinue(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("return")) {
|
||||
visitReturn(stmt);
|
||||
} else {
|
||||
visitPrintf(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitBlock(Stmt stmt) {
|
||||
Block block = (Block) stmt.getChild(0);
|
||||
VisitorBlock.visitBlock(block);
|
||||
}
|
||||
|
||||
public static void visitExp(Stmt stmt) {
|
||||
if (stmt.getChild(0) instanceof Exp) {
|
||||
VisitorExp.visitExp((Exp) stmt.getChild(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitAssign(Stmt stmt) {
|
||||
if (!stmt.isGetint()) {
|
||||
LVal lval = (LVal) stmt.getChild(0);
|
||||
Exp exp = (Exp) stmt.getChild(2);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
IrValue expIr = VisitorExp.visitExp(exp);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
} else {
|
||||
LVal lval = (LVal) stmt.getChild(0);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
GetIntInstr getIntInstr = new GetIntInstr(IrBuilder.getLocalName());
|
||||
IrBuilder.addInstr(getIntInstr);
|
||||
StoreInstr storeInstr = new StoreInstr(getIntInstr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitPrintf(Stmt stmt) {
|
||||
// System.out.println(((TokenNode)stmt.getChild(0)).getValue());//TODO:debug
|
||||
String strconst = ((TokenNode) stmt.getChild(2)).getValue();
|
||||
ArrayList<Exp> expList = stmt.getExpList();
|
||||
ArrayList<IrValue> expIrList = new ArrayList<>();
|
||||
for (Exp exp : expList) {
|
||||
expIrList.add(VisitorExp.visitExp(exp));
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int expnum = 0;
|
||||
ArrayList<IrValue> printValue = new ArrayList<>();
|
||||
for (int i = 0; i < strconst.length(); i++) {
|
||||
if (strconst.charAt(i) == '%') {
|
||||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||||
// System.out.println(sb.toString());//TODO:debug
|
||||
if (str == null) {
|
||||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||||
IrBuilder.addNewStr(str);
|
||||
}
|
||||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||||
// IrBuilder.addInstr(putStrInstr);
|
||||
sb.setLength(0);
|
||||
} else if (sb.toString().equals("\"")) {
|
||||
sb.setLength(0);
|
||||
}
|
||||
IrValue expIr = expIrList.get(expnum++);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
printValue.add(expIr); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), expIr);
|
||||
// IrBuilder.addInstr(putIntInstr);
|
||||
i++;
|
||||
} else {
|
||||
sb.append(strconst.charAt(i));
|
||||
}
|
||||
}
|
||||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||||
// System.out.println(sb.toString());//TODO:debug
|
||||
if (str == null) {
|
||||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||||
IrBuilder.addNewStr(str);
|
||||
}
|
||||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||||
// IrBuilder.addInstr(putStrInstr);
|
||||
sb.setLength(0);
|
||||
}
|
||||
for (IrValue irValue : printValue) {
|
||||
if (irValue instanceof IrConstantStr) {
|
||||
PutStrInstr putStrInstr = new PutStrInstr(
|
||||
IrBuilder.getLocalName(), (IrConstantStr) irValue);
|
||||
IrBuilder.addInstr(putStrInstr);
|
||||
} else {
|
||||
PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), irValue);
|
||||
IrBuilder.addInstr(putIntInstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitReturn(Stmt stmt) {
|
||||
IrValue retValue = null;
|
||||
if (stmt.getChild(1) instanceof Exp) {
|
||||
retValue = VisitorExp.visitExp((Exp) stmt.getChild(1));
|
||||
retValue = IrType.convertType(retValue, IrInterType.INT32);
|
||||
}
|
||||
ReturnInstr returnInstr = new ReturnInstr(retValue);
|
||||
IrBuilder.addInstr(returnInstr);
|
||||
}
|
||||
|
||||
public static void visitIf(Stmt stmt) {
|
||||
Cond cond = (Cond) stmt.getChild(2);
|
||||
Stmt ifStmt = (Stmt) stmt.getChild(4);
|
||||
if (stmt.getChildren().size() == 7) {
|
||||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(ifBlock);
|
||||
IrBasicBlock elseBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(elseBlock);
|
||||
VisitorExp.visitCond(cond, ifBlock, elseBlock);
|
||||
// ifblock解析
|
||||
IrBuilder.setCurrentBBlock(ifBlock);
|
||||
VisitorStmt.visitStmt(ifStmt);
|
||||
IrBasicBlock followBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBlock);
|
||||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//elseblock解析
|
||||
IrBuilder.setCurrentBBlock(elseBlock);
|
||||
Stmt elseStmt = (Stmt) stmt.getChild(6);
|
||||
VisitorStmt.visitStmt(elseStmt);
|
||||
jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//跳转至followblock
|
||||
IrBuilder.setCurrentBBlock(followBlock);
|
||||
} else {
|
||||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(ifBlock);
|
||||
IrBasicBlock followBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBlock);
|
||||
VisitorExp.visitCond(cond, ifBlock, followBlock);
|
||||
IrBuilder.setCurrentBBlock(ifBlock);
|
||||
VisitorStmt.visitStmt(ifStmt);
|
||||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//跳转至followblock
|
||||
IrBuilder.setCurrentBBlock(followBlock);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitFor(Stmt stmt) {
|
||||
IrBasicBlock condBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(condBB);
|
||||
IrBasicBlock bodyBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(bodyBB);
|
||||
IrBasicBlock stepBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(stepBB);
|
||||
IrBasicBlock followBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBB);
|
||||
IrLoop loop = new IrLoop(condBB, bodyBB, stepBB, followBB);
|
||||
IrBuilder.pushLoop(loop);
|
||||
ForStmt initStmt = stmt.getinitStmt();
|
||||
if (initStmt != null) {
|
||||
VisitorStmt.visitForStmt(initStmt);
|
||||
}
|
||||
JumpInstr jumpInstr = new JumpInstr(condBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
IrBuilder.setCurrentBBlock(condBB);
|
||||
Cond cond = stmt.getCond();
|
||||
if (cond != null) {
|
||||
VisitorExp.visitCond(cond, bodyBB, followBB);
|
||||
} else {
|
||||
JumpInstr jumpBody = new JumpInstr(bodyBB);
|
||||
IrBuilder.addInstr(jumpBody);
|
||||
}
|
||||
IrBuilder.setCurrentBBlock(bodyBB);
|
||||
Stmt bodyStmt = stmt.getBodyStmt();
|
||||
VisitorStmt.visitStmt(bodyStmt);
|
||||
jumpInstr = new JumpInstr(stepBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
IrBuilder.setCurrentBBlock(stepBB);
|
||||
ForStmt stepStmt = stmt.getStepStmt();
|
||||
if (stepStmt != null) {
|
||||
VisitorStmt.visitForStmt(stepStmt);
|
||||
}
|
||||
JumpInstr jumpCond = new JumpInstr(condBB);
|
||||
IrBuilder.addInstr(jumpCond);
|
||||
IrBuilder.popLoop();
|
||||
IrBuilder.setCurrentBBlock(followBB);
|
||||
} /*TODO:此处可能还有问题,循环体和条件、步长表达式等可能不在一个符号表,应该修改,应该比较好改,判断一下stmt是否为block再决定是否last
|
||||
细想应该不用,如果body是一个block,那visit的时候符号表next,visit完之后符号表还会next,相当于再解析step的时候还是原来的符号表*/
|
||||
|
||||
public static void visitForStmt(ForStmt stmt) {
|
||||
ArrayList<LVal> lvalList = stmt.getLValList();
|
||||
ArrayList<Exp> expList = stmt.getExpList();
|
||||
for (int i = 0; i < lvalList.size(); i++) {
|
||||
LVal lval = lvalList.get(i);
|
||||
Exp exp = expList.get(i);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
IrValue expIr = VisitorExp.visitExp(exp);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitBreak(Stmt stmt) {
|
||||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||||
IrBasicBlock followBB = loop.getFollowBB();
|
||||
JumpInstr jumpInstr = new JumpInstr(followBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
}
|
||||
|
||||
public static void visitContinue(Stmt stmt) {
|
||||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||||
IrBasicBlock stepBB = loop.getStepBB();
|
||||
JumpInstr jumpInstr = new JumpInstr(stepBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
}
|
||||
}
|
||||
package midend.visit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import frontend.ast.block.Block;
|
||||
import frontend.ast.block.ForStmt;
|
||||
import frontend.ast.block.Stmt;
|
||||
import frontend.ast.exp.Cond;
|
||||
import frontend.ast.exp.Exp;
|
||||
import frontend.ast.exp.LVal;
|
||||
import frontend.ast.token.TokenNode;
|
||||
import frontend.lexer.Token;
|
||||
import midend.symbol.SymbolManager;
|
||||
import midend.llvm.IrBuilder;
|
||||
import midend.llvm.constant.IrConstantStr;
|
||||
import midend.llvm.instr.GetIntInstr;
|
||||
import midend.llvm.instr.JumpInstr;
|
||||
import midend.llvm.instr.PutIntInstr;
|
||||
import midend.llvm.instr.PutStrInstr;
|
||||
import midend.llvm.instr.ReturnInstr;
|
||||
import midend.llvm.instr.StoreInstr;
|
||||
import midend.llvm.type.IrInterType;
|
||||
import midend.llvm.type.IrType;
|
||||
import midend.llvm.value.IrBasicBlock;
|
||||
import midend.llvm.value.IrValue;
|
||||
import midend.llvm.value.IrLoop;
|
||||
|
||||
public class VisitorStmt {
|
||||
public static void visitStmt(Stmt stmt) {
|
||||
if (stmt.getChild(0) instanceof LVal) {
|
||||
visitAssign(stmt);
|
||||
} else if (stmt.getChild(0) instanceof Exp
|
||||
|| (stmt.getChild(0) instanceof TokenNode
|
||||
&& ((TokenNode) stmt.getChild(0)).getValue().equals(";"))) {
|
||||
visitExp(stmt);
|
||||
} else if (stmt.getChild(0) instanceof Block) {
|
||||
visitBlock(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("if")) {
|
||||
visitIf(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("for")) {
|
||||
visitFor(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("break")) {
|
||||
visitBreak(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("continue")) {
|
||||
visitContinue(stmt);
|
||||
} else if (((TokenNode) stmt.getChild(0)).getValue().equals("return")) {
|
||||
visitReturn(stmt);
|
||||
} else {
|
||||
visitPrintf(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitBlock(Stmt stmt) {
|
||||
Block block = (Block) stmt.getChild(0);
|
||||
VisitorBlock.visitBlock(block);
|
||||
}
|
||||
|
||||
public static void visitExp(Stmt stmt) {
|
||||
if (stmt.getChild(0) instanceof Exp) {
|
||||
VisitorExp.visitExp((Exp) stmt.getChild(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitAssign(Stmt stmt) {
|
||||
if (!stmt.isGetint()) {
|
||||
LVal lval = (LVal) stmt.getChild(0);
|
||||
Exp exp = (Exp) stmt.getChild(2);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
IrValue expIr = VisitorExp.visitExp(exp);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
} else {
|
||||
LVal lval = (LVal) stmt.getChild(0);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
GetIntInstr getIntInstr = new GetIntInstr(IrBuilder.getLocalName());
|
||||
IrBuilder.addInstr(getIntInstr);
|
||||
StoreInstr storeInstr = new StoreInstr(getIntInstr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitPrintf(Stmt stmt) {
|
||||
// System.out.println(((TokenNode)stmt.getChild(0)).getValue());//TODO:debug
|
||||
String strconst = ((TokenNode) stmt.getChild(2)).getValue();
|
||||
ArrayList<Exp> expList = stmt.getExpList();
|
||||
ArrayList<IrValue> expIrList = new ArrayList<>();
|
||||
for (Exp exp : expList) {
|
||||
expIrList.add(VisitorExp.visitExp(exp));
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int expnum = 0;
|
||||
ArrayList<IrValue> printValue = new ArrayList<>();
|
||||
for (int i = 0; i < strconst.length(); i++) {
|
||||
if (strconst.charAt(i) == '%') {
|
||||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||||
// System.out.println(sb.toString());//TODO:debug
|
||||
if (str == null) {
|
||||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||||
IrBuilder.addNewStr(str);
|
||||
}
|
||||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||||
// IrBuilder.addInstr(putStrInstr);
|
||||
sb.setLength(0);
|
||||
} else if (sb.toString().equals("\"")) {
|
||||
sb.setLength(0);
|
||||
}
|
||||
IrValue expIr = expIrList.get(expnum++);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
printValue.add(expIr); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), expIr);
|
||||
// IrBuilder.addInstr(putIntInstr);
|
||||
i++;
|
||||
} else {
|
||||
sb.append(strconst.charAt(i));
|
||||
}
|
||||
}
|
||||
if (!sb.isEmpty() && !sb.toString().equals("\"")) {
|
||||
IrConstantStr str = IrBuilder.getCurrentModule().getStr(sb.toString());
|
||||
// System.out.println(sb.toString());//TODO:debug
|
||||
if (str == null) {
|
||||
str = new IrConstantStr(sb.toString(), IrBuilder.getStrName());
|
||||
IrBuilder.addNewStr(str);
|
||||
}
|
||||
printValue.add(str); // 修改为到最后统一输出,而不是立即输出
|
||||
// PutStrInstr putStrInstr = new PutStrInstr(IrBuilder.getLocalName(), str);
|
||||
// IrBuilder.addInstr(putStrInstr);
|
||||
sb.setLength(0);
|
||||
}
|
||||
for (IrValue irValue : printValue) {
|
||||
if (irValue instanceof IrConstantStr) {
|
||||
PutStrInstr putStrInstr = new PutStrInstr(
|
||||
IrBuilder.getLocalName(), (IrConstantStr) irValue);
|
||||
IrBuilder.addInstr(putStrInstr);
|
||||
} else {
|
||||
PutIntInstr putIntInstr = new PutIntInstr(IrBuilder.getLocalName(), irValue);
|
||||
IrBuilder.addInstr(putIntInstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitReturn(Stmt stmt) {
|
||||
IrValue retValue = null;
|
||||
if (stmt.getChild(1) instanceof Exp) {
|
||||
retValue = VisitorExp.visitExp((Exp) stmt.getChild(1));
|
||||
retValue = IrType.convertType(retValue, IrInterType.INT32);
|
||||
}
|
||||
ReturnInstr returnInstr = new ReturnInstr(retValue);
|
||||
IrBuilder.addInstr(returnInstr);
|
||||
}
|
||||
|
||||
public static void visitIf(Stmt stmt) {
|
||||
Cond cond = (Cond) stmt.getChild(2);
|
||||
Stmt ifStmt = (Stmt) stmt.getChild(4);
|
||||
if (stmt.getChildren().size() == 7) {
|
||||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(ifBlock);
|
||||
IrBasicBlock elseBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(elseBlock);
|
||||
VisitorExp.visitCond(cond, ifBlock, elseBlock);
|
||||
// ifblock解析
|
||||
IrBuilder.setCurrentBBlock(ifBlock);
|
||||
VisitorStmt.visitStmt(ifStmt);
|
||||
IrBasicBlock followBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBlock);
|
||||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//elseblock解析
|
||||
IrBuilder.setCurrentBBlock(elseBlock);
|
||||
Stmt elseStmt = (Stmt) stmt.getChild(6);
|
||||
VisitorStmt.visitStmt(elseStmt);
|
||||
jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//跳转至followblock
|
||||
IrBuilder.setCurrentBBlock(followBlock);
|
||||
} else {
|
||||
IrBasicBlock ifBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(ifBlock);
|
||||
IrBasicBlock followBlock = new IrBasicBlock(
|
||||
IrBuilder.getBlockName(), IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBlock);
|
||||
VisitorExp.visitCond(cond, ifBlock, followBlock);
|
||||
IrBuilder.setCurrentBBlock(ifBlock);
|
||||
VisitorStmt.visitStmt(ifStmt);
|
||||
JumpInstr jumpInstr = new JumpInstr(followBlock);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
//跳转至followblock
|
||||
IrBuilder.setCurrentBBlock(followBlock);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitFor(Stmt stmt) {
|
||||
IrBasicBlock condBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(condBB);
|
||||
IrBasicBlock bodyBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(bodyBB);
|
||||
IrBasicBlock stepBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(stepBB);
|
||||
IrBasicBlock followBB = new IrBasicBlock(IrBuilder.getBlockName(),
|
||||
IrBuilder.getCurrentFunc());
|
||||
IrBuilder.addNewBB(followBB);
|
||||
IrLoop loop = new IrLoop(condBB, bodyBB, stepBB, followBB);
|
||||
IrBuilder.pushLoop(loop);
|
||||
ForStmt initStmt = stmt.getinitStmt();
|
||||
if (initStmt != null) {
|
||||
VisitorStmt.visitForStmt(initStmt);
|
||||
}
|
||||
JumpInstr jumpInstr = new JumpInstr(condBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
IrBuilder.setCurrentBBlock(condBB);
|
||||
Cond cond = stmt.getCond();
|
||||
if (cond != null) {
|
||||
VisitorExp.visitCond(cond, bodyBB, followBB);
|
||||
} else {
|
||||
JumpInstr jumpBody = new JumpInstr(bodyBB);
|
||||
IrBuilder.addInstr(jumpBody);
|
||||
}
|
||||
IrBuilder.setCurrentBBlock(bodyBB);
|
||||
Stmt bodyStmt = stmt.getBodyStmt();
|
||||
VisitorStmt.visitStmt(bodyStmt);
|
||||
jumpInstr = new JumpInstr(stepBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
IrBuilder.setCurrentBBlock(stepBB);
|
||||
ForStmt stepStmt = stmt.getStepStmt();
|
||||
if (stepStmt != null) {
|
||||
VisitorStmt.visitForStmt(stepStmt);
|
||||
}
|
||||
JumpInstr jumpCond = new JumpInstr(condBB);
|
||||
IrBuilder.addInstr(jumpCond);
|
||||
IrBuilder.popLoop();
|
||||
IrBuilder.setCurrentBBlock(followBB);
|
||||
} /*TODO:此处可能还有问题,循环体和条件、步长表达式等可能不在一个符号表,应该修改,应该比较好改,判断一下stmt是否为block再决定是否last
|
||||
细想应该不用,如果body是一个block,那visit的时候符号表next,visit完之后符号表还会next,相当于再解析step的时候还是原来的符号表*/
|
||||
|
||||
public static void visitForStmt(ForStmt stmt) {
|
||||
ArrayList<LVal> lvalList = stmt.getLValList();
|
||||
ArrayList<Exp> expList = stmt.getExpList();
|
||||
for (int i = 0; i < lvalList.size(); i++) {
|
||||
LVal lval = lvalList.get(i);
|
||||
Exp exp = expList.get(i);
|
||||
IrValue lvalIr = VisitorExp.visitLVal(lval, true);
|
||||
IrValue expIr = VisitorExp.visitExp(exp);
|
||||
expIr = IrType.convertType(expIr, IrInterType.INT32);
|
||||
StoreInstr storeInstr = new StoreInstr(expIr, lvalIr);
|
||||
IrBuilder.addInstr(storeInstr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void visitBreak(Stmt stmt) {
|
||||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||||
IrBasicBlock followBB = loop.getFollowBB();
|
||||
JumpInstr jumpInstr = new JumpInstr(followBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
}
|
||||
|
||||
public static void visitContinue(Stmt stmt) {
|
||||
IrLoop loop = IrBuilder.getCurrentLoop();
|
||||
IrBasicBlock stepBB = loop.getStepBB();
|
||||
JumpInstr jumpInstr = new JumpInstr(stepBB);
|
||||
IrBuilder.addInstr(jumpInstr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user