├── .gitignore ├── README.md ├── assets └── structure.svg └── src ├── Compiler.java ├── arg └── Arg.java ├── backend ├── CodeGen.java ├── FPRegAllocator.java ├── GPRegAllocator.java ├── MergeBlock.java ├── NaiveRegAllocator.java ├── Parallel.java ├── PeepHole.java └── RegAllocator.java ├── descriptor ├── Descriptor.java └── MIDescriptor.java ├── exception ├── SemanticException.java └── SyntaxException.java ├── frontend ├── Visitor.java ├── lexer │ ├── Lexer.java │ ├── Token.java │ ├── TokenList.java │ └── TokenType.java ├── semantic │ ├── Evaluate.java │ ├── Initial.java │ └── symbol │ │ ├── SymTable.java │ │ └── Symbol.java └── syntax │ ├── Ast.java │ └── Parser.java ├── lir ├── Arm.java ├── BJ.java ├── I.java ├── MC.java ├── MICall.java ├── MIComment.java ├── MachineInst.java ├── StackCtl.java └── V.java ├── manage └── Manager.java ├── midend ├── AggressiveFuncGCM.java ├── AggressiveFuncGVN.java ├── AggressiveMarkParallel.java ├── ArrayGVNGCM.java ├── ArrayLift.java ├── ArraySSA.java ├── BranchLift.java ├── BranchOptimize.java ├── CloneInfoMap.java ├── ConstFold.java ├── ConstTransFold.java ├── DeadCodeDelete.java ├── FuncInfo.java ├── FuncInline.java ├── GVNAndGCM.java ├── GepFuse.java ├── GepSplit.java ├── GlobalArrayGVN.java ├── GlobalValueLocalize.java ├── IfComb.java ├── InstrComb.java ├── LCSSA.java ├── LocalArrayGVN.java ├── LoopFold.java ├── LoopFuse.java ├── LoopIdcVarInfo.java ├── LoopInVarCodeLift.java ├── LoopInfo.java ├── LoopNest.java ├── LoopStrengthReduction.java ├── LoopUnRoll.java ├── MakeDFG.java ├── MarkParallel.java ├── MarkParallelForNormalLoop.java ├── MathOptimize.java ├── Mem2Reg.java ├── MemSetOptimize.java ├── MergeBB.java ├── MergeSimpleBB.java ├── MidEndRunner.java ├── MidPeepHole.java ├── OutParam.java ├── Rem2DivMulSub.java ├── RemovePhi.java ├── RemoveUselessStore.java ├── SimpleCalc.java └── TestMain.java ├── mir ├── BasicBlock.java ├── Constant.java ├── Function.java ├── GlobalVal.java ├── Instr.java ├── Loop.java ├── Use.java ├── Value.java └── type │ ├── DataType.java │ └── Type.java └── util ├── CenterControl.java ├── FileDealer.java ├── ILinkNode.java └── Ilist.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | out 3 | target 4 | *.iml 5 | *.MF 6 | *.c 7 | *.cpp 8 | *.h 9 | *.hpp 10 | *.sy 11 | *.ll 12 | *.txt 13 | *.s 14 | *.S 15 | *.elf 16 | *.in 17 | *.out 18 | *.err 19 | *.sh 20 | *.py 21 | *.ipynb 22 | /src/test 23 | /src/timeTest 24 | *.zip 25 | *.tar.* 26 | *.rar 27 | *.7z -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meow-Compiler 2 | 3 | 2022 [全国大学生计算机系统能力大赛编译系统设计赛(华为毕昇杯)](https://compiler.educg.net) 参赛作品。 4 | 5 | ## Build 6 | 7 | Requirements: Java (JDK >= 15) 8 | 9 | ```bash 10 | mkdir target 11 | javac -d target -encoding 'utf-8' \ 12 | $(find src -type f -name '*.java') 13 | cd target; mkdir -p META-INF; echo -e 'Manifest-Version: 1.0\r\nMain-Class: Compiler\r\n\r\n' > META-INF/MANIFEST.MF 14 | jar cfm compiler.jar META-INF/MANIFEST.MF * 15 | ``` 16 | 17 | Artifact will be stored at target/compiler.jar . 18 | 19 | ## Usage 20 | 21 | ``` 22 | java -jar compiler.jar {(-S|-emit-llvm) -o filename} filename [-On] 23 | 24 | Options: 25 | -S -o filename: generate armv7-a assembly to file. 26 | -emit-llvm -o filename: generate LLVM IR (.ll) to file. 27 | filename: source code file. 28 | -On: optimize level, possible value: -O0, -O1, -O2 29 | ``` 30 | 31 | Examples: 32 | 33 | - (Contest Official Functional Test) Generate assembly test.S from source test.sy without optimization 34 | ```bash 35 | java -jar compiler.jar -S test.S test.sy 36 | ``` 37 | - (Contest Official Performance Test) Generate assembly test.S from source test.sy with optimization 38 | ```bash 39 | java -jar compiler.jar -S test.S test.sy -O2 40 | ``` 41 | - Generate LLVM IR test.ll from source test.sy with optimization 42 | ```bash 43 | java -jar compiler.jar -emit-llvm -o test.ll test.sy -O2 44 | ``` 45 | - Generate both LLVM IR and assembly, without optimization and enable assertion 46 | ```bash 47 | java -ea -jar compiler.jar -emit-llvm -o test.ll -S -o test.S test.sy 48 | ``` 49 | 50 | ## Run target code 51 | 52 | Before running target code, [SysY Runtime Library](https://gitlab.eduxiji.net/nscscc/compiler2022/-/blob/master/SysY2022%E8%BF%90%E8%A1%8C%E6%97%B6%E5%BA%93-V1.pdf) is required first. 53 | 54 | - If target code (arm assembly) runs on raspberry pi, you should compile the runtime library on pi first; 55 | - If target code (llvm ir or arm assembly) runs on PC, you can use our [Docker Image](https://github.com/Meow-Twice/sysy-docker) as the environment. 56 | 57 | [Testcases](https://gitlab.eduxiji.net/nscscc/compiler2022/-/tree/master/%E5%85%AC%E5%BC%80%E6%A0%B7%E4%BE%8B%E4%B8%8E%E8%BF%90%E8%A1%8C%E6%97%B6%E5%BA%93) can be accessed from educg gitlab. 58 | 59 | ## Structure 60 | 61 | ![structure](assets/structure.svg) 62 | 63 | ## Optimization and Passes 64 | 65 | Mid-end optimization passed is managed at midend/MidEndRunner.java, and global control is managed at util/CenterControl.java . -------------------------------------------------------------------------------- /src/Compiler.java: -------------------------------------------------------------------------------- 1 | import arg.Arg; 2 | import backend.*; 3 | import frontend.Visitor; 4 | import frontend.lexer.Lexer; 5 | import frontend.lexer.Token; 6 | import frontend.lexer.TokenList; 7 | import frontend.syntax.Ast; 8 | import frontend.syntax.Parser; 9 | import lir.MC; 10 | import manage.Manager; 11 | import midend.MergeBB; 12 | import midend.MidEndRunner; 13 | import midend.RemovePhi; 14 | import util.CenterControl; 15 | import util.FileDealer; 16 | 17 | import java.io.*; 18 | 19 | import static midend.MidEndRunner.O2; 20 | import static util.CenterControl._ONLY_FRONTEND; 21 | 22 | public class Compiler { 23 | 24 | public static boolean OUTPUT_LEX = false; 25 | // public static boolean ONLY_FRONTEND = false; 26 | 27 | private static String input(InputStream in) throws IOException { 28 | BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 29 | StringBuilder builder = new StringBuilder(); 30 | String line; 31 | while ((line = reader.readLine()) != null) { 32 | builder.append(line).append("\n"); 33 | } 34 | reader.close(); 35 | return builder.toString(); 36 | } 37 | 38 | public static void main(String[] args) { 39 | Arg arg = Arg.parse(args); 40 | CenterControl._HEURISTIC_BASE = arg.heuristicBase; 41 | try { 42 | BufferedInputStream source = new BufferedInputStream(arg.srcStream); 43 | // System.err.println(source); // output source code via stderr; 44 | TokenList tokenList = new TokenList(); 45 | Lexer.getInstance().lex(source, tokenList); 46 | // OUTPUT_LEX = true; 47 | if (OUTPUT_LEX) { 48 | while (tokenList.hasNext()) { 49 | Token token = tokenList.consume(); 50 | System.err.println(token.getType() + " " + token.getContent()); 51 | } 52 | } 53 | System.err.println("AST out"); 54 | Ast ast = new Parser(tokenList).parseAst(); 55 | Visitor visitor = Visitor.VISITOR; 56 | // visitor.__ONLY_PARSE_OUTSIDE_DIM = false; 57 | visitor.visitAst(ast); 58 | System.err.println("visit end"); 59 | // Manager manager = visitor.getIr(); 60 | // GlobalValueLocalize globalValueLocalize = new GlobalValueLocalize(funcManager.globals); 61 | // globalValueLocalize.Run(); 62 | Manager.MANAGER.outputLLVM(); 63 | 64 | _ONLY_FRONTEND = !arg.outputAsm(); 65 | 66 | 67 | O2 = arg.optLevel == 2; 68 | MidEndRunner.O0 = arg.optLevel == 0; 69 | System.err.println("opt level = " + arg.optLevel); 70 | System.err.println("mid optimization begin"); 71 | long start = System.currentTimeMillis(); 72 | MidEndRunner midEndRunner = new MidEndRunner(Manager.MANAGER.getFunctionList()); 73 | midEndRunner.Run(); 74 | System.err.println("mid optimization end, Use Time: " + ((double) System.currentTimeMillis() - start) / 1000 + "s"); 75 | 76 | // DeadCodeDelete deadCodeDelete = new DeadCodeDelete(Manager.MANAGER.getFunctionList()); 77 | // deadCodeDelete.Run(); 78 | if (arg.outputLLVM()) { 79 | Manager.MANAGER.outputLLVM(arg.llvmStream); 80 | } 81 | if (_ONLY_FRONTEND) { 82 | return; 83 | } 84 | 85 | RemovePhi removePhi = new RemovePhi(midEndRunner.functions); 86 | removePhi.Run(); 87 | 88 | Manager.MANAGER.outputLLVM(); 89 | 90 | MergeBB mergeBB = new MergeBB(midEndRunner.functions); 91 | mergeBB.Run(); 92 | 93 | CenterControl.AlreadyBackend = true; 94 | System.err.println("code gen begin"); 95 | start = System.currentTimeMillis(); 96 | //Manager.MANAGER.outputLLVM(); 97 | CodeGen.CODEGEN.gen(); 98 | System.err.println("code gen end, Use Time: " + ((double) System.currentTimeMillis() - start) / 1000 + "s"); 99 | MC.Program p = MC.Program.PROGRAM; 100 | // 为 MI Descriptor 设置输入输出流 101 | // MIDescriptor.MI_DESCRIPTOR.setInput(arg.interpretInputStream); 102 | // MIDescriptor.MI_DESCRIPTOR.setOutput(arg.interpretOutputStream); 103 | // 用参数给定的输入输出流后,分配寄存器前和分配寄存器后只运行一遍解释器,否则后者的输出会覆盖前者 104 | // MIDescriptor.MI_DESCRIPTOR.run(); // 分配寄存器前 105 | // System.err.println("before"); 106 | // Manager.MANAGER.outputMI(); 107 | // System.err.println("before end"); 108 | // Manager.outputMI(true); 109 | System.err.println("Reg Alloc begin"); 110 | start = System.currentTimeMillis(); 111 | if (CenterControl._FAST_REG_ALLOCATE) { 112 | NaiveRegAllocator regAllocator = new NaiveRegAllocator(); 113 | regAllocator.AllocateRegister(p); 114 | } else { 115 | if (CodeGen.needFPU) { 116 | FPRegAllocator fpRegAllocator = new FPRegAllocator(); 117 | fpRegAllocator.AllocateRegister(p); 118 | } 119 | // System.err.println("middle"); 120 | // Manager.MANAGER.outputMI(); 121 | // System.err.println("middle end"); 122 | GPRegAllocator GPRegAllocator = new GPRegAllocator(); 123 | GPRegAllocator.AllocateRegister(p); 124 | } 125 | System.err.println("Reg Alloc end, Use Time: " + ((double) System.currentTimeMillis() - start) / 1000 + "s"); 126 | // Manager.outputMI(true); 127 | // System.err.println("after"); 128 | // Manager.MANAGER.outputMI(); 129 | // System.err.println("after end"); 130 | // System.err.println("BEGIN rerun"); 131 | // MIDescriptor.MI_DESCRIPTOR.setRegMode(); 132 | // MIDescriptor.MI_DESCRIPTOR.run(); // 分配寄存器后 133 | // File output_file = new File("output.S"); 134 | // PrintStream os = new PrintStream(output_file); 135 | // p.output(os); 136 | 137 | // System.err.println(p.getSTB()); 138 | // 139 | if (CenterControl._GLOBAL_BSS) 140 | MC.Program.PROGRAM.bssInit(); 141 | 142 | if (O2) { 143 | CenterControl._TAG = "O2_2"; 144 | if (CenterControl._FUNC_PARALLEL) { 145 | CenterControl._TAG = "O2_func"; 146 | } 147 | PeepHole peepHole = new PeepHole(p); 148 | peepHole.run(); 149 | // Manager.MANAGER.outputMI(); 150 | MergeBlock mergeBlock = new MergeBlock(); 151 | int i = 0; 152 | while (i++ < 2) { 153 | mergeBlock.run(true); 154 | } 155 | // Manager.MANAGER.outputMI(); 156 | if (CenterControl._OPEN_PARALLEL_BACKEND) { 157 | Parallel.PARALLEL.gen(); 158 | } 159 | } else { 160 | PeepHole peepHole = new PeepHole(p); 161 | peepHole.runOneStage(); 162 | } 163 | if (arg.outputAsm()) { 164 | FileDealer.outputToStream(p.getSTB(), arg.asmStream); 165 | // p.output(new PrintStream(arg.asmStream)); 166 | } 167 | } catch (Exception e) { 168 | e.printStackTrace(); 169 | System.exit(e.getClass().getSimpleName().length()); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/arg/Arg.java: -------------------------------------------------------------------------------- 1 | package arg; 2 | 3 | import java.io.*; 4 | 5 | public class Arg { 6 | public final String srcFilename; // 源代码文件名 e.g. "testcase.sy" 7 | public final int optLevel; // 优化等级,缺省值为 1 8 | 9 | public final String asmFilename; // 目标汇编代码文件名 e.g. "testcase.s" 10 | public final String llvmFilename; // LLVM IR 文件名 e.g. "testcase.ll" 11 | 12 | public final FileInputStream srcStream; // 源代码输入流 13 | public final OutputStream asmStream; // 汇编代码输出流 14 | public final OutputStream llvmStream; // LLVM IR 中间代码输出流 15 | 16 | public final boolean interpretMI; // 是否解释执行 17 | public final InputStream interpretInputStream; // 解释执行 stdin 18 | public final OutputStream interpretOutputStream; // 解释执行 stdout 19 | 20 | // options 21 | public double heuristicBase = 1.45; 22 | 23 | private Arg(String src, String asm, String llvm, 24 | boolean interpret, String interpretIn, String interpretOut, int optimize) throws FileNotFoundException { 25 | this.srcFilename = src; 26 | this.asmFilename = asm; 27 | this.llvmFilename = llvm; 28 | 29 | this.srcStream = new FileInputStream(srcFilename); 30 | this.asmStream = asm.isEmpty() ? null : new FileOutputStream(asmFilename); 31 | this.llvmStream = llvm.isEmpty() ? null : new FileOutputStream(llvmFilename); 32 | 33 | this.interpretMI = interpret; 34 | this.interpretInputStream = interpretIn.isEmpty() ? System.in : new FileInputStream(interpretIn); 35 | this.interpretOutputStream = interpretOut.isEmpty() ? System.out : new FileOutputStream(interpretOut); 36 | 37 | this.optLevel = optimize; 38 | } 39 | 40 | public boolean outputAsm() { 41 | return !asmFilename.isEmpty(); 42 | } 43 | 44 | public boolean outputLLVM() { return !llvmFilename.isEmpty(); } 45 | 46 | public static Arg parse(String[] args) { 47 | String src = "", asm = "", llvm = ""; 48 | int optLevel = 1; 49 | boolean interpret = false; 50 | String interpretIn = "", interpretOut = ""; 51 | // options 52 | double heuristicBase = 1.45; 53 | for (int i = 0; i < args.length; i++) { 54 | // detect "-Ox" 55 | if (args[i].startsWith("-O")) { 56 | if (optLevel != 1) { 57 | throw new RuntimeException("Optimize level should only have one."); 58 | } 59 | optLevel = Integer.parseInt(args[i].substring(2)); 60 | if (optLevel < 0 || optLevel > 2) { 61 | throw new RuntimeException("Optimize level should only be 0, 1, 2"); 62 | } 63 | continue; 64 | } 65 | // detect optimize options 66 | if (args[i].startsWith("--heuristic-base=")) { 67 | heuristicBase = Double.parseDouble(args[i].substring(17)); 68 | if (heuristicBase < 1 || heuristicBase > 2) { 69 | throw new RuntimeException("heuristic base should in range [1, 2]"); 70 | } 71 | continue; 72 | } 73 | // detect "-S" 74 | if ("-S".equals(args[i])) { 75 | if (i + 2 < args.length && "-o".equals(args[i + 1])) { 76 | if (!asm.isEmpty()) { 77 | throw new RuntimeException("We got more than one assemble file when we expected only one."); 78 | } 79 | asm = args[i + 2]; 80 | i += 2; 81 | continue; 82 | } else { 83 | throw new RuntimeException("-S expected -o filename"); 84 | } 85 | } 86 | // detect "-emit-llvm" 87 | if ("-emit-llvm".equals(args[i])) { 88 | if (i + 2 < args.length && "-o".equals(args[i + 1])) { 89 | if (!llvm.isEmpty()) { 90 | throw new RuntimeException("We got more than one llvm-ir file when we expected only one."); 91 | } 92 | llvm = args[i + 2]; 93 | i += 2; 94 | continue; 95 | } else { 96 | throw new RuntimeException("-emit-llvm expected -o filename"); 97 | } 98 | } 99 | // detect "-i" 100 | if ("-I".equals(args[i])) { 101 | if (interpret) { 102 | throw new RuntimeException("We got more than one interpret option."); 103 | } 104 | interpret = true; 105 | while (i + 1 < args.length && ("-i".equals(args[i + 1]) || "-o".equals(args[i + 1]))) { 106 | if (i + 2 < args.length && "-i".equals(args[i + 1])) { 107 | if (!interpretIn.isEmpty()) { 108 | throw new RuntimeException("We got more than one interpreter input."); 109 | } 110 | interpretIn = args[i + 2]; 111 | i += 2; 112 | } 113 | if (i + 2 < args.length && "-o".equals(args[i + 1])) { 114 | if (!interpretOut.isEmpty()) { 115 | throw new RuntimeException("We got more than one interpreter output."); 116 | } 117 | interpretOut = args[i + 2]; 118 | i += 2; 119 | } 120 | } 121 | continue; 122 | } 123 | // detect illegal flags 124 | if (args[i].startsWith("-")) { 125 | throw new RuntimeException("invalid flag: " + args[i]); 126 | } 127 | // source file 128 | if (!src.isEmpty()) { 129 | throw new RuntimeException("We got more than one source file when we expected only one."); 130 | } 131 | src = args[i]; 132 | } 133 | if (src.isEmpty()) { 134 | printHelp(); 135 | throw new RuntimeException("source file should be specified."); 136 | } 137 | try { 138 | Arg arg = new Arg(src, asm, llvm, interpret, interpretIn, interpretOut, optLevel); 139 | arg.heuristicBase = heuristicBase; 140 | return arg; 141 | } catch (FileNotFoundException e) { 142 | printHelp(); 143 | throw new RuntimeException(e); 144 | } 145 | } 146 | 147 | public static void printHelp() { 148 | System.err.println("Usage: compiler {(-S|-emit-llvm) -o filename} filename -On [options...]"); 149 | System.err.println("optimize level: 0, 1 (default), 2"); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/backend/NaiveRegAllocator.java: -------------------------------------------------------------------------------- 1 | package backend; 2 | 3 | import lir.*; 4 | import mir.type.DataType; 5 | 6 | import java.util.ArrayList; 7 | 8 | import static mir.type.DataType.F32; 9 | import static mir.type.DataType.I32; 10 | 11 | public class NaiveRegAllocator extends RegAllocator { 12 | public NaiveRegAllocator() { 13 | initPool(); 14 | } 15 | 16 | final int rRegNum = 8; 17 | final int sRegNum = 8; 18 | 19 | void initPool() { 20 | rRegPool[0] = Arm.Reg.getR(4); 21 | rRegPool[1] = Arm.Reg.getR(5); 22 | rRegPool[2] = Arm.Reg.getR(6); 23 | rRegPool[3] = Arm.Reg.getR(7); 24 | rRegPool[4] = Arm.Reg.getR(8); 25 | rRegPool[5] = Arm.Reg.getR(9); 26 | rRegPool[6] = Arm.Reg.getR(10); 27 | rRegPool[7] = Arm.Reg.getR(11); 28 | for (int i = 24; i < 32; i++) { 29 | sRegPool[i - 24] = Arm.Reg.getS(i); 30 | } 31 | } 32 | 33 | Arm.Reg[] rRegPool = new Arm.Reg[rRegNum]; 34 | Arm.Reg[] sRegPool = new Arm.Reg[sRegNum]; 35 | int rStackTop = rRegNum; 36 | int sStackTop = sRegNum; 37 | 38 | Arm.Reg rRegPop() { 39 | if (rStackTop <= 0) { 40 | throw new AssertionError(""); 41 | } 42 | return rRegPool[--rStackTop]; 43 | } 44 | 45 | Arm.Reg sRegPop() { 46 | return sRegPool[--sStackTop]; 47 | } 48 | 49 | void reset() { 50 | rStackTop = rRegNum; 51 | sStackTop = sRegNum; 52 | } 53 | 54 | public void AllocateRegister(MC.Program program) { 55 | 56 | for (MC.McFunction mf : program.funcList) { 57 | mf.setAllocStack(); 58 | mf.addVarStack(4 * mf.getVRSize()); 59 | // if (needFPU) 60 | mf.addVarStack(4 * mf.getSVRSize()); 61 | for (MC.Block mb : mf.mbList) { 62 | for (MachineInst mi : mb.miList) { 63 | if (mi.isCall()) { 64 | // TODO 可以放到CodeGen里 65 | mf.setUseLr(); 66 | } 67 | } 68 | } 69 | mf.alignTotalStackSize(); 70 | } 71 | 72 | fixStack(program.needFixList); 73 | /* 74 | Machine.McFunction mf = mi.getMb().mcFunc; 75 | I.Mov mv = (I.Mov) mi; 76 | Machine.Operand off = mv.getSrc(); 77 | assert off.is_I_Imm(); 78 | int newOff = switch (mv.getFixType()) { 79 | case INT_TOTAL_STACK, FLOAT_TOTAL_STACK -> off.getValue() + mf.getTotalStackSize(); 80 | case VAR_STACK -> mf.getVarStack(); 81 | case ONLY_PARAM -> mv.getCallee().getParamStack(); 82 | default -> throw new AssertionError("needFixType Wrong"); 83 | }; 84 | boolean flag = false; 85 | if (mv.hasNext()) { 86 | if ((mv.getNext() instanceof I.Binary)) { 87 | // TODO 可以启发式做一些优化 88 | if (((I.Binary) mv.getNext()).getLOpd().equals(rSP) && ((I.Binary) mv.getNext()).getDst().equals(rSP)) { 89 | flag = true; 90 | if (CodeGen.immCanCode(newOff)) { 91 | ((I.Binary) mv.getNext()).setROpd(new Machine.Operand(I32, newOff)); 92 | mv.remove(); 93 | } else { 94 | Arm.Reg reg = rRegPop(); 95 | mv.setSrc(new Machine.Operand(I32, newOff)); 96 | mv.setDst(reg); 97 | ((I.Binary) mv.getNext()).setROpd(reg); 98 | mv.clearNeedFix(); 99 | reset(); 100 | } 101 | } 102 | } 103 | } 104 | if (!flag) { 105 | mv.setSrc(new Machine.Operand(I32, newOff)); 106 | mv.clearNeedFix(); 107 | }*/ 108 | 109 | for (MC.McFunction mf : program.funcList) { 110 | int iVrBase = mf.getAllocStack(); 111 | int sVrBase = mf.getVRSize() * 4 + iVrBase; 112 | for (MC.Block mb : mf.mbList) { 113 | for (MachineInst mi : mb.miList) { 114 | ArrayList defs = mi.defOpds; 115 | ArrayList uses = mi.useOpds; 116 | if (mi.isComment() || mi.isCall()) continue; 117 | assert uses.size() < 4; 118 | int useIdx = 0; 119 | for (MC.Operand use : uses) { 120 | if (use.isVirtual(I32)) { 121 | int offset = iVrBase + 4 * use.getValue(); 122 | if (Math.abs(offset) < 4096) { 123 | Arm.Reg useReg = rRegPop(); 124 | new I.Ldr(useReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), new MC.Operand(DataType.I32, offset), mi); 125 | mi.setUse(useIdx, useReg); 126 | } else { 127 | Arm.Reg offReg = rRegPop(); 128 | new I.Mov(offReg, new MC.Operand(DataType.I32, offset), mi); 129 | Arm.Reg useReg = rRegPop(); 130 | new I.Ldr(useReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), offReg, mi); 131 | mi.setUse(useIdx, useReg); 132 | } 133 | } else if (use.isVirtual(F32)) { 134 | int offset = sVrBase + 4 * use.getValue(); 135 | if (Math.abs(offset) <= 1020) { 136 | Arm.Reg useReg = sRegPop(); 137 | new V.Ldr(useReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), new MC.Operand(DataType.I32, offset), mi); 138 | mi.setUse(useIdx, useReg); 139 | } else { 140 | Arm.Reg offReg = rRegPop(); 141 | new I.Mov(offReg, new MC.Operand(DataType.I32, offset), mi); 142 | new I.Binary(MachineInst.Tag.Add, offReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), offReg, mi); 143 | Arm.Reg useReg = sRegPop(); 144 | new V.Ldr(useReg, offReg, mi); 145 | mi.setUse(useIdx, useReg); 146 | } 147 | } 148 | useIdx++; 149 | } 150 | // reset(); 151 | if (defs.size() > 0) { 152 | assert defs.size() == 1; 153 | MC.Operand def = defs.get(0); 154 | if (def.isVirtual(I32)) { 155 | int offset = iVrBase + 4 * def.getValue(); 156 | if (Math.abs(offset) < 4096) { 157 | Arm.Reg useReg = rRegPop(); 158 | new I.Str(mi, useReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), new MC.Operand(DataType.I32, offset)); 159 | mi.setDef(useReg); 160 | } else { 161 | Arm.Reg offReg = rRegPop(); 162 | I.Mov mv = new I.Mov(mi, offReg, new MC.Operand(DataType.I32, offset)); 163 | Arm.Reg defReg = rRegPop(); 164 | new I.Str(mv, defReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), offReg); 165 | mi.setDef(defReg); 166 | } 167 | } else if (def.isVirtual(F32)) { 168 | int offset = sVrBase + 4 * def.getValue(); 169 | if (Math.abs(offset) <= 1020) { 170 | Arm.Reg defReg = sRegPop(); 171 | new V.Str(mi, defReg, rSP, new MC.Operand(DataType.I32, offset)); 172 | mi.setDef(defReg); 173 | } else { 174 | Arm.Reg offReg = rRegPop(); 175 | I.Mov mv = new I.Mov(mi, offReg, new MC.Operand(DataType.I32, offset)); 176 | I.Binary bino = new I.Binary(mv, MachineInst.Tag.Add, offReg, Arm.Reg.getR(Arm.Regs.GPRs.sp), offReg); 177 | Arm.Reg defReg = sRegPop(); 178 | new V.Str(bino, defReg, offReg); 179 | mi.setDef(defReg); 180 | } 181 | } 182 | } 183 | reset(); 184 | } 185 | } 186 | } 187 | 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/backend/Parallel.java: -------------------------------------------------------------------------------- 1 | package backend; 2 | 3 | import lir.*; 4 | 5 | import java.util.HashMap; 6 | 7 | import static lir.Arm.Reg.getRSReg; 8 | import static lir.Arm.Regs.GPRs.*; 9 | import static lir.BJ.*; 10 | import static lir.MC.Operand.I_ONE; 11 | import static lir.MC.Operand.I_ZERO; 12 | import static lir.MachineInst.Tag.Add; 13 | import static lir.MachineInst.Tag.Sub; 14 | import static mir.type.DataType.I32; 15 | 16 | public class Parallel { 17 | public static final Parallel PARALLEL = new Parallel(MC.Program.PROGRAM); 18 | MC.Program p; 19 | // TODO parallel的function都需要def r2 20 | MC.McFunction mf_parallel_start = new MC.McFunction("parallel_start"); 21 | MC.McFunction mf_parallel_end = new MC.McFunction("parallel_end"); 22 | private static MC.McFunction curMF; 23 | public final HashMap tmpGlob = new HashMap<>(); 24 | private String start_r5 = "$start_r5"; 25 | private String start_r7 = "$start_r7"; 26 | private String start_lr = "$start_lr"; 27 | private String end_r7 = "$end_r7"; 28 | private String end_lr = "$end_lr"; 29 | 30 | MC.Block mb_parallel_start; 31 | MC.Block mb_parallel_start1; 32 | MC.Block mb_parallel_start2; 33 | MC.Block mb_parallel_end; 34 | MC.Block mb_parallel_end1; 35 | MC.Block mb_parallel_end2; 36 | MC.Block mb_parallel_end3; 37 | MC.Block mb_parallel_end4; 38 | private Parallel(MC.Program p) { 39 | this.p = p; 40 | } 41 | 42 | public void gen() { 43 | p.funcList.insertAtEnd(mf_parallel_start); 44 | p.funcList.insertAtEnd(mf_parallel_end); 45 | Arm.Glob g = new Arm.Glob(start_r5); 46 | MC.Program.PROGRAM.globList.add(g); 47 | tmpGlob.put(start_r5, g); 48 | g = new Arm.Glob(start_r7); 49 | MC.Program.PROGRAM.globList.add(g); 50 | tmpGlob.put(start_r7, g); 51 | g = new Arm.Glob(start_lr); 52 | MC.Program.PROGRAM.globList.add(g); 53 | tmpGlob.put(start_lr, g); 54 | g = new Arm.Glob(end_r7); 55 | MC.Program.PROGRAM.globList.add(g); 56 | tmpGlob.put(end_r7, g); 57 | g = new Arm.Glob(end_lr); 58 | MC.Program.PROGRAM.globList.add(g); 59 | tmpGlob.put(end_lr, g); 60 | 61 | curMF = mf_parallel_start; 62 | mb_parallel_start = new MC.Block(".parallel_start", curMF); 63 | mb_parallel_start1 = new MC.Block(".parallel_start1", curMF); 64 | mb_parallel_start2 = new MC.Block(".parallel_start2", curMF); 65 | curMF = mf_parallel_end; 66 | mb_parallel_end = new MC.Block(".parallel_end", curMF); 67 | mb_parallel_end1 = new MC.Block(".parallel_end1", curMF); 68 | mb_parallel_end2 = new MC.Block(".parallel_end2", curMF); 69 | mb_parallel_end3 = new MC.Block(".parallel_end3", curMF); 70 | mb_parallel_end4 = new MC.Block(".parallel_end4", curMF); 71 | genStart(); 72 | genEnd(); 73 | } 74 | 75 | private static MC.Block curMB; 76 | private Arm.Glob getGlob(String name){ 77 | return tmpGlob.get(name); 78 | } 79 | 80 | /** 81 | * 82 | parallel_start: 83 | movw r2, :lower16:$start_r7 84 | movt r2, :upper16:$start_r7 85 | str r7, [r2] 86 | movw r2, :lower16:$start_r5 87 | movt r2, :upper16:$start_r5 88 | str r5, [r2] 89 | movw r2, :lower16:$start_lr 90 | movt r2, :upper16:$start_lr 91 | str lr, [r2] 92 | mov r5, #4 @4代表总共4个进程,因为处理器有4个核心 93 | .parallel_start1: 94 | sub r5, r5, #1 95 | cmp r5, #0 96 | beq .parallel_start2+0 @r2每次减一,到0的时候就跳到.__mtstart2 97 | mov r7, #120 @系统调用号 98 | mov r0, #273 @系统调用的第一个参数值 99 | mov r1, sp 100 | swi #0 @根据寄存器r7的值进行系统调用,r7中为120,所以进行120号系统调用,为clone 101 | cmp r0, #0 @clone调用者进程返回创建的子进程号,在创建的子进程里返回0 102 | bne .parallel_start1+0 @如果是clone出来的进程就继续执行.parallel_start2,主进程跳到.parallel_start1,继续开启下一个进程 103 | .parallel_start2: 104 | mov r0, r5 105 | movw r2, :lower16:$start_r7 106 | movt r2, :upper16:$start_r7 107 | ldr r7, [r2] 108 | movw r2, :lower16:$start_r5 109 | movt r2, :upper16:$start_r5 110 | ldr r5, [r2] 111 | movw r2, :lower16:$start_lr 112 | movt r2, :upper16:$start_lr 113 | ldr lr, [r2] 114 | bx lr 115 | */ 116 | private void genStart() { 117 | curMF = mf_parallel_start; 118 | curMB = mb_parallel_start; 119 | new I.Mov(getRSReg(r2), getGlob(start_r7), curMB); 120 | new I.Str(getRSReg(r7), getRSReg(r2), I_ZERO, curMB); 121 | 122 | new I.Mov(getRSReg(r2), getGlob(start_r5), curMB); 123 | new I.Str(getRSReg(r5), getRSReg(r2), I_ZERO, curMB); 124 | 125 | new I.Mov(getRSReg(r2), getGlob(start_lr), curMB); 126 | new I.Str(getRSReg(lr), getRSReg(r2), I_ZERO, curMB); 127 | 128 | new I.Mov(getRSReg(r5), new MC.Operand(I32, 4), curMB); 129 | curMB = mb_parallel_start1; 130 | new I.Binary(Sub, getRSReg(r5), getRSReg(r5), new MC.Operand(I32, 1), curMB); 131 | new I.Cmp(Arm.Cond.Eq, getRSReg(r5), I_ZERO, curMB); 132 | new GDBranch(Arm.Cond.Eq, mb_parallel_start2, curMB); 133 | new I.Mov(getRSReg(r7), new MC.Operand(I32, 120), curMB); 134 | new I.Mov(getRSReg(r0), new MC.Operand(I32, 273), curMB); 135 | new I.Mov(getRSReg(r1), getRSReg(sp), curMB); 136 | new I.Swi(curMB); 137 | new I.Cmp(Arm.Cond.Ne, getRSReg(r0), new MC.Operand(I32, 0), curMB); 138 | new GDBranch(Arm.Cond.Ne, mb_parallel_start1, curMB); 139 | curMB = mb_parallel_start2; 140 | new I.Mov(getRSReg(r0), getRSReg(r5), curMB); 141 | new I.Mov(getRSReg(r2), getGlob(start_r7), curMB); 142 | new I.Ldr(getRSReg(r7), getRSReg(r2), I_ZERO, curMB); 143 | 144 | new I.Mov(getRSReg(r2), getGlob(start_r5), curMB); 145 | new I.Ldr(getRSReg(r5), getRSReg(r2), I_ZERO, curMB); 146 | 147 | new I.Mov(getRSReg(r2), getGlob(start_lr), curMB); 148 | new I.Ldr(getRSReg(lr), getRSReg(r2), I_ZERO, curMB); 149 | new I.Ret(curMB); 150 | } 151 | 152 | private void genEnd() { 153 | curMF = mf_parallel_end; 154 | curMB = mb_parallel_end; 155 | new I.Cmp(Arm.Cond.Eq, getRSReg(r0), I_ZERO, curMB); 156 | new GDBranch(Arm.Cond.Eq, mb_parallel_end2, curMB); 157 | curMB = mb_parallel_end1; 158 | new I.Mov(getRSReg(r7), I_ONE, curMB); 159 | new I.Swi(curMB); 160 | curMB = mb_parallel_end2; 161 | new I.Mov(getRSReg(r2), getGlob(end_r7), curMB); 162 | new I.Str(getRSReg(r7), getRSReg(r2), I_ZERO, curMB); 163 | 164 | new I.Mov(getRSReg(r2), getGlob(end_lr), curMB); 165 | new I.Str(getRSReg(lr), getRSReg(r2), I_ZERO, curMB); 166 | 167 | new I.Mov(getRSReg(r7), new MC.Operand(I32, 4), curMB); 168 | 169 | curMB = mb_parallel_end3; 170 | new I.Binary(Sub, getRSReg(r7), getRSReg(r7), I_ONE, curMB); 171 | new I.Cmp(Arm.Cond.Eq, getRSReg(r7), I_ZERO, curMB); 172 | new GDBranch(Arm.Cond.Eq, mb_parallel_end4, curMB); 173 | new I.Binary(Sub, getRSReg(r0), getRSReg(sp), new MC.Operand(I32, 4), curMB); 174 | new I.Binary(Sub, getRSReg(sp), getRSReg(sp), new MC.Operand(I32, 4), curMB); 175 | new I.Wait(curMB); 176 | new I.Binary(Add, getRSReg(sp), getRSReg(sp), new MC.Operand(I32, 4), curMB); 177 | new GDJump(mb_parallel_end3, curMB); 178 | curMB = mb_parallel_end4; 179 | new I.Mov(getRSReg(r2), getGlob(end_r7), curMB); 180 | new I.Ldr(getRSReg(r7), getRSReg(r2), I_ZERO, curMB); 181 | 182 | new I.Mov(getRSReg(r2), getGlob(end_lr), curMB); 183 | new I.Ldr(getRSReg(lr), getRSReg(r2), I_ZERO, curMB); 184 | 185 | new I.Ret(curMB); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/descriptor/Descriptor.java: -------------------------------------------------------------------------------- 1 | package descriptor; 2 | 3 | public interface Descriptor { 4 | StringBuilder getOutput(); 5 | void clear(); 6 | } 7 | -------------------------------------------------------------------------------- /src/exception/SemanticException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | /** 4 | * 中端异常 5 | */ 6 | public class SemanticException extends Exception { 7 | public SemanticException() { super(); } 8 | 9 | public SemanticException(String message) { super(message); } 10 | } 11 | -------------------------------------------------------------------------------- /src/exception/SyntaxException.java: -------------------------------------------------------------------------------- 1 | package exception; 2 | 3 | /** 4 | * 编译器前端发生的异常(词法分析和语法分析阶段) 5 | */ 6 | public class SyntaxException extends Exception { 7 | public SyntaxException() { super(); } 8 | 9 | public SyntaxException(String message) { super(message); } 10 | } 11 | -------------------------------------------------------------------------------- /src/frontend/lexer/Token.java: -------------------------------------------------------------------------------- 1 | package frontend.lexer; 2 | 3 | public class Token { 4 | private final TokenType type; 5 | public final String content; 6 | 7 | public int lineNum = 0; 8 | 9 | private static final boolean[] IS_ALU_TYPE = new boolean[100]; 10 | private static final boolean[] IS_CMP_TYPE = new boolean[100]; 11 | 12 | static { 13 | for (int i = TokenType.ADD.ordinal(); i <= TokenType.MOD.ordinal(); i++) { 14 | IS_ALU_TYPE[i] = true; 15 | } 16 | for (int i = TokenType.LE.ordinal(); i <= TokenType.GT.ordinal(); i++) { 17 | IS_CMP_TYPE[i] = true; 18 | } 19 | } 20 | 21 | public Token(final TokenType type, final String content) { 22 | this.type = type; 23 | this.content = content; 24 | System.err.print(" " + content); 25 | } 26 | 27 | public TokenType getType() { 28 | return this.type; 29 | } 30 | 31 | public String getContent() { 32 | return this.content; 33 | } 34 | 35 | public boolean isOf(TokenType type) { 36 | return this.type.equals(type); 37 | } 38 | 39 | public boolean isOf(TokenType... types) { 40 | for (TokenType type : types) { 41 | if (this.type.equals(type)) { 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | 48 | public boolean isNumber() { 49 | return type.ordinal() <= TokenType.DEC_INT.ordinal() 50 | && type.ordinal() >= TokenType.HEX_FLOAT.ordinal(); 51 | } 52 | 53 | public boolean isIntConst() { 54 | return type.ordinal() <= TokenType.DEC_INT.ordinal() 55 | && type.ordinal() >= TokenType.HEX_INT.ordinal(); 56 | } 57 | 58 | public boolean isFloatConst() { 59 | return type.ordinal() <= TokenType.DEC_FLOAT.ordinal() 60 | && type.ordinal() >= TokenType.HEX_FLOAT.ordinal(); 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "<" + type + " " + content + ">"; 66 | } 67 | 68 | public static boolean isAlu(TokenType tokenType) { 69 | return IS_ALU_TYPE[tokenType.ordinal()]; 70 | } 71 | 72 | public static boolean isCmp(TokenType tokenType) { 73 | return IS_CMP_TYPE[tokenType.ordinal()]; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/frontend/lexer/TokenList.java: -------------------------------------------------------------------------------- 1 | package frontend.lexer; 2 | 3 | import exception.SyntaxException; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | 8 | public class TokenList { 9 | private static final boolean ENABLE_DEBUG = false; 10 | 11 | public final ArrayList tokens = new ArrayList<>(); 12 | private int index = 0; 13 | 14 | public void append(Token token) { 15 | // System.err.println(token); 16 | tokens.add(token); 17 | } 18 | 19 | public boolean hasNext() { 20 | return index < tokens.size(); 21 | } 22 | 23 | public Token get() { 24 | return ahead(0); 25 | } 26 | 27 | public Token ahead(int count) { 28 | return tokens.get(index + count); 29 | } 30 | 31 | private void detectEof() throws SyntaxException { 32 | if (!hasNext()) { 33 | throw new SyntaxException("Unexpected EOF"); 34 | } 35 | } 36 | 37 | public Token consume() throws SyntaxException { 38 | detectEof(); 39 | if (ENABLE_DEBUG) { 40 | System.err.println("consume: " + tokens.get(index)); 41 | } 42 | return tokens.get(index++); 43 | } 44 | 45 | // Usage: tokenList.consumeExpected(TokenType.INT, TokenType.VOID) 46 | public Token consumeExpected(TokenType... types) throws SyntaxException { 47 | detectEof(); 48 | Token token = tokens.get(index); 49 | for (TokenType type : types) { 50 | if (token.getType().equals(type)) { 51 | if (ENABLE_DEBUG) { 52 | System.err.println("consume: " + tokens.get(index)); 53 | } 54 | index++; 55 | return token; 56 | } 57 | } 58 | for (int i = 0; i < index; i++) { 59 | System.err.println(tokens.get(i)); 60 | } 61 | throw new SyntaxException("Expected " + Arrays.toString(types) + " but got " + token); 62 | } 63 | 64 | public Token consumeExpected(TokenType type) throws SyntaxException { 65 | detectEof(); 66 | Token token = tokens.get(index); 67 | if (token.getType().equals(type)) { 68 | if (ENABLE_DEBUG) { 69 | System.err.println("consume: " + tokens.get(index)); 70 | } 71 | index++; 72 | return token; 73 | } 74 | for (int i = 0; i < index; i++) { 75 | System.err.println(tokens.get(i)); 76 | } 77 | throw new SyntaxException("Expected " + type + " but got " + token); 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/frontend/lexer/TokenType.java: -------------------------------------------------------------------------------- 1 | package frontend.lexer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.regex.Pattern; 7 | 8 | public enum TokenType { 9 | // keyword (must have lookahead assertion) 10 | CONST("const", true), 11 | INT("int", true), 12 | FLOAT("float", true), 13 | BREAK("break", true), 14 | CONTINUE("continue", true), 15 | IF("if", true), 16 | ELSE("else", true), 17 | VOID("void", true), 18 | WHILE("while", true), 19 | RETURN("return", true), 20 | // ident 21 | IDENT("[A-Za-z_][A-Za-z0-9_]*"), 22 | // float const 23 | HEX_FLOAT("(0(x|X)[0-9A-Fa-f]*\\.[0-9A-Fa-f]*((p|P|e|E)(\\+|\\-)?[0-9A-Fa-f]*)?)|" + 24 | "(0(x|X)[0-9A-Fa-f]*[\\.]?[0-9A-Fa-f]*(p|P|e|E)((\\+|\\-)?[0-9A-Fa-f]*)?)"), 25 | DEC_FLOAT("([0-9]*\\.[0-9]*((p|P|e|E)(\\+|\\-)?[0-9]+)?)|" + 26 | "([0-9]*[\\.]?[0-9]*(p|P|e|E)((\\+|\\-)?[0-9]+)?)"), // decimal 27 | // DEC_FLOAT("(0|([1-9][0-9]*))\\.[0-9]*((p|P|e|E)(\\+|\\-)?[0-9]+)?"), // decimal 28 | // int const 29 | HEX_INT("0(x|X)[0-9A-Fa-f]+"), 30 | OCT_INT("0[0-7]+"), 31 | DEC_INT("0|([1-9][0-9]*)"), // decimal 32 | // operator (double char) 33 | LAND("&&"), 34 | LOR("\\|\\|"), 35 | LE("<="), 36 | GE(">="), 37 | EQ("=="), 38 | NE("!="), 39 | // operator (single char) 40 | LT("<"), 41 | GT(">"), 42 | ADD("\\+"), // regex 43 | SUB("-"), 44 | MUL("\\*"), 45 | DIV("/"), 46 | MOD("%"), 47 | NOT("!"), 48 | ASSIGN("="), 49 | SEMI(";"), 50 | COMMA(","), 51 | LPARENT("\\("), 52 | RPARENT("\\)"), 53 | LBRACK("\\["), 54 | RBRACK("]"), 55 | LBRACE("\\{"), 56 | RBRACE("}"), 57 | STR_CON(""), 58 | ; 59 | 60 | public static final ArrayList NUM_CON_LIST = new ArrayList<>(Arrays.asList(HEX_INT, DEC_INT, OCT_INT, HEX_FLOAT, DEC_FLOAT)); 61 | 62 | private final String pattern; // regex pattern 63 | 64 | private final boolean keyword; // keyword 65 | 66 | TokenType(final String pattern, final boolean keyword) { 67 | this.pattern = pattern; 68 | this.keyword = keyword; 69 | } 70 | 71 | TokenType(String pattern) { 72 | this(pattern, false); 73 | } 74 | 75 | public Pattern getPattern() { 76 | return Pattern.compile("^(" + pattern + ")" + (keyword ? "(?![A-Za-z0-9_])" : "")); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/frontend/semantic/Evaluate.java: -------------------------------------------------------------------------------- 1 | package frontend.semantic; 2 | 3 | import exception.SemanticException; 4 | import frontend.Visitor; 5 | import frontend.lexer.Token; 6 | import frontend.semantic.symbol.SymTable; 7 | import frontend.semantic.symbol.Symbol; 8 | import frontend.syntax.Ast; 9 | import mir.Constant; 10 | import mir.Value; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Iterator; 14 | 15 | /** 16 | * 编译期求值工具类 17 | */ 18 | public class Evaluate { 19 | private final SymTable symTable; // 当前的符号表 20 | private final boolean requireConst; // 是否是 ConstExp 21 | 22 | public Evaluate(SymTable symTable, boolean requireConst) { 23 | this.symTable = symTable; 24 | this.requireConst = requireConst; 25 | } 26 | 27 | public static int evalConstIntExp(Ast.Exp exp) throws SemanticException { 28 | return (int) evalConstExp(exp); 29 | } 30 | 31 | public static float evalConstFloatExp(Ast.Exp exp) throws SemanticException { 32 | return (float) evalConstExp(exp); 33 | } 34 | 35 | // 编译期求值 36 | public static Object evalConstExp(Ast.Exp exp) throws SemanticException { 37 | Object ret; 38 | if (exp instanceof Ast.BinaryExp) { 39 | ret = evalBinaryConstExp((Ast.BinaryExp) exp); 40 | } else if (exp instanceof Ast.UnaryExp) { 41 | ret = evalUnaryConstExp((Ast.UnaryExp) exp); 42 | } else { 43 | throw new AssertionError("Bad Exp:" + exp); 44 | } 45 | boolean isFloat = ret instanceof Float; 46 | boolean isInt = ret instanceof Integer; 47 | assert ret instanceof Float || ret instanceof Integer; 48 | return ret; 49 | } 50 | 51 | /*** 52 | * src1或src2中只要有Float,就将其提升为float运算,否则按照int运算 53 | * @param op 54 | * @param src1 55 | * @param src2 56 | * @return Integer或Float对象 57 | */ 58 | // 二元运算 59 | private static Object binaryCalcHelper(Token op, Object src1, Object src2) { 60 | if (src1 instanceof Float || src2 instanceof Float) { 61 | float f1 = src1 instanceof Integer ? (float) ((int) src1) : (float) src1; 62 | float f2 = src2 instanceof Integer ? (float) ((int) src2) : (float) src2; 63 | return switch (op.getType()) { 64 | case ADD -> f1 + f2; 65 | case SUB -> f1 - f2; 66 | case MUL -> f1 * f2; 67 | case DIV -> f1 / f2; 68 | case MOD -> f1 % f2; 69 | default -> throw new AssertionError("Bad Binary Operator"); 70 | }; 71 | } else { 72 | assert src1 instanceof Integer && src2 instanceof Integer; 73 | int i1 = (int) src1; 74 | int i2 = (int) src2; 75 | return switch (op.getType()) { 76 | case ADD -> i1 + i2; 77 | case SUB -> i1 - i2; 78 | case MUL -> i1 * i2; 79 | case DIV -> i1 / i2; 80 | case MOD -> i1 % i2; 81 | default -> throw new AssertionError("Bad Binary Operator"); 82 | }; 83 | } 84 | } 85 | 86 | // 一元运算 87 | private static Object unaryCalcHelper(Token op, Object src) { 88 | if (src instanceof Integer) { 89 | int intConst = (int) src; 90 | return switch (op.getType()) { 91 | case ADD -> intConst; 92 | case SUB -> -intConst; 93 | case NOT -> intConst == 0 ? 1 : 0; 94 | default -> throw new AssertionError("Bad Unary Operator"); 95 | }; 96 | } else if (src instanceof Float) { 97 | float floatConst = (float) src; 98 | return switch (op.getType()) { 99 | case ADD -> floatConst; 100 | case SUB -> -floatConst; 101 | case NOT -> floatConst == 0.0 ? 1.0 : 0.0; 102 | default -> throw new AssertionError("Bad Unary Operator"); 103 | }; 104 | } else { 105 | throw new AssertionError("Bad src: " + src); 106 | } 107 | } 108 | 109 | // 从左到右按顺序计算即可 110 | public static Object evalBinaryConstExp(Ast.BinaryExp exp) throws SemanticException { 111 | Ast.Exp first = exp.getFirst(); 112 | Iterator iterOp = exp.getOperators().listIterator(); 113 | Iterator iterExp = exp.getFollows().listIterator(); 114 | Object result = evalConstExp(first); 115 | while (iterExp.hasNext()) { 116 | assert iterOp.hasNext(); 117 | Token op = iterOp.next(); 118 | Ast.Exp follow = iterExp.next(); 119 | result = binaryCalcHelper(op, result, evalConstExp(follow)); 120 | } 121 | return result; 122 | } 123 | 124 | public static Object evalUnaryConstExp(Ast.UnaryExp exp) throws SemanticException { 125 | Object primary = evalPrimaryExp(exp.getPrimary()); 126 | // 从右向左结合 127 | ArrayList unaryOps = new ArrayList<>(exp.getUnaryOps()); 128 | for (int i = unaryOps.size() - 1; i >= 0; i--) { 129 | Token op = unaryOps.get(i); 130 | primary = unaryCalcHelper(op, primary); 131 | } 132 | return primary; 133 | } 134 | 135 | public static Object evalPrimaryExp(Ast.PrimaryExp exp) throws SemanticException { 136 | if (exp instanceof Ast.Number) { 137 | return evalNumber((Ast.Number) exp); 138 | } else if (exp instanceof Ast.Exp) { 139 | return evalConstExp((Ast.Exp) exp); 140 | } else if (exp instanceof Ast.LVal) { 141 | return evalLVal((Ast.LVal) exp); 142 | } else { 143 | // 编译期不能求函数调用的值 144 | throw new AssertionError("Bad Eval Primary Exp: " + exp.getClass().getSimpleName()); 145 | } 146 | } 147 | 148 | public static Object evalNumber(Ast.Number number) { 149 | Token num = number.getNumber(); 150 | String content = num.getContent(); 151 | return switch (num.getType()) { 152 | case HEX_INT -> Integer.parseInt(content.substring(2), 16); 153 | case OCT_INT -> Integer.parseInt(content.substring(1), 8); 154 | case DEC_INT -> Integer.parseInt(content); 155 | case HEX_FLOAT, DEC_FLOAT -> Float.parseFloat(content); 156 | default -> throw new AssertionError("Bad Number: " + number); 157 | }; 158 | } 159 | 160 | public static Object evalLVal(Ast.LVal lVal) throws SemanticException { 161 | String ident = lVal.getIdent().getContent(); 162 | // 查找符号表 163 | Symbol symbol = Visitor.currentSymTable.get(ident, true); 164 | // if (requireConst && !symbol.isConstant()) { 165 | // throw new SemanticException("Expected Const but got not Const."); 166 | // } 167 | // 必须初始化过,才可以编译期求值 168 | if (symbol.getInitial() == null) { 169 | throw new SemanticException("Symbol not initialized"); 170 | } 171 | // 如果是数组, 逐层找偏移量 172 | Initial init = symbol.getInitial(); 173 | ArrayList indexes = new ArrayList<>(); // eval indexes 174 | for (Ast.Exp index : lVal.getIndexes()) { 175 | indexes.add((int) evalConstExp(index)); 176 | } 177 | for (Integer index : indexes) { 178 | if (init instanceof Initial.ValueInit) { 179 | throw new SemanticException("Should be Array/Zero Init!"); 180 | } 181 | if (init instanceof Initial.ZeroInit) { 182 | return 0; 183 | } 184 | assert init instanceof Initial.ArrayInit; 185 | init = ((Initial.ArrayInit) init).get(index); 186 | } 187 | if (!(init instanceof Initial.ValueInit)) { 188 | throw new SemanticException("Should be Value Init"); 189 | } 190 | Value ret = ((Initial.ValueInit) init).getValue(); // 取出初始值 191 | assert ret instanceof Constant; 192 | return ((Constant) ret).getConstVal(); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/frontend/semantic/symbol/SymTable.java: -------------------------------------------------------------------------------- 1 | package frontend.semantic.symbol; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * 分层结构的符号表 8 | */ 9 | public class SymTable { 10 | private final HashMap symbolMap = new HashMap<>(); 11 | 12 | private final SymTable parent; 13 | 14 | public SymTable() { 15 | this(null); 16 | } 17 | 18 | public boolean hasParent() { 19 | return parent != null; 20 | } 21 | 22 | public SymTable(SymTable parent) { 23 | this.parent = parent; 24 | } 25 | 26 | public SymTable getParent() { 27 | return parent; 28 | } 29 | 30 | public void add(Symbol symbol) { 31 | assert !symbolMap.containsKey(symbol.getName()); 32 | symbolMap.putIfAbsent(symbol.getName(), symbol); 33 | } 34 | 35 | public Symbol get(String name, boolean recursive) { 36 | Symbol symbol = symbolMap.get(name); 37 | if (null == symbol && recursive && null != parent) { 38 | return parent.get(name, true); 39 | } 40 | return symbol; 41 | } 42 | 43 | public boolean contains(String name, boolean recursive) { 44 | return get(name, recursive) != null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/frontend/semantic/symbol/Symbol.java: -------------------------------------------------------------------------------- 1 | package frontend.semantic.symbol; 2 | 3 | import frontend.semantic.Initial; 4 | import mir.Value; 5 | import mir.type.Type; 6 | 7 | /** 8 | * 符号表中的一条符号信息 9 | */ 10 | public class Symbol { 11 | private final String name; // 变量名称 12 | private final Type type; // 变量类型 13 | private final Initial initial; // 初始值(可以为 null, 如果有则必须和变量匹配) 14 | private final boolean constant; // 是否为常量 15 | private final Value allocInst; // IR 中作为该变量地址的 Pointer 16 | 17 | public Symbol(final String name, final Type type, final Initial initial, final boolean constant, final Value allocInst) { 18 | this.name = name; 19 | this.type = type; 20 | this.initial = initial; 21 | this.constant = constant; 22 | this.allocInst = allocInst; 23 | } 24 | 25 | public String getName() { 26 | return this.name; 27 | } 28 | 29 | public Type getType() { 30 | return this.type; 31 | } 32 | 33 | public Initial getInitial() { 34 | return this.initial; 35 | } 36 | 37 | public boolean isConstant() { 38 | return this.constant; 39 | } 40 | 41 | public Value getValue() { 42 | return this.allocInst; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/lir/BJ.java: -------------------------------------------------------------------------------- 1 | package lir; 2 | 3 | import backend.CodeGen; 4 | 5 | import java.io.PrintStream; 6 | 7 | public class BJ extends MachineInst { 8 | public BJ(Tag tag, MC.Block insertAtEnd) { 9 | super(tag, insertAtEnd); 10 | } 11 | 12 | public BJ(Tag tag, MachineInst before) { 13 | super(tag, before); 14 | } 15 | 16 | public MC.Block getTrueBlock() { 17 | return null; 18 | } 19 | 20 | public MC.Block getFalseBlock() { 21 | return null; 22 | } 23 | 24 | public void setTarget(MC.Block onlySuccMB) { 25 | assert false; 26 | } 27 | 28 | 29 | public static class GDJump extends BJ { 30 | public MC.Block getTarget() { 31 | return target; 32 | } 33 | 34 | MC.Block target; 35 | 36 | public GDJump(MC.Block target, MC.Block insertAtEnd) { 37 | super(Tag.Jump, insertAtEnd); 38 | this.target = target; 39 | } 40 | 41 | public GDJump(MC.Block target, MachineInst before) { 42 | super(Tag.Jump, before); 43 | this.target = target; 44 | } 45 | 46 | // public GDJump(Arm.Cond cond, MC.Block target, MC.Block insertAtEnd) { 47 | // super(Tag.Jump, insertAtEnd); 48 | // this.target = target; 49 | // this.cond = cond; 50 | // } 51 | 52 | public MC.Block getTrueBlock() { 53 | return target; 54 | } 55 | 56 | public MC.Block getFalseBlock() { 57 | if (!(mb.getNext() instanceof MC.Block)) 58 | System.exit(123); 59 | return (MC.Block) this.mb.getNext(); 60 | } 61 | 62 | @Override 63 | public void output(PrintStream os, MC.McFunction f) { 64 | os.println("\t" + this); 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return tag.toString() + "\t" + target.getLabel(); 70 | } 71 | 72 | public void setTarget(MC.Block block) { 73 | target = block; 74 | } 75 | 76 | 77 | } 78 | 79 | 80 | public static class GDBranch extends BJ { 81 | public Arm.Cond getCond() { 82 | return cond; 83 | } 84 | 85 | public MC.Block getTrueTargetBlock() { 86 | return target; 87 | } 88 | 89 | public MC.Block getFalseTargetBlock() { 90 | return (MC.Block) mb.getNext(); 91 | } 92 | 93 | Arm.Cond cond; 94 | MC.Block target; 95 | // 条件不满足则跳这个块 96 | // MC.Block falseTargetBlock; 97 | boolean isIcmp = true; 98 | 99 | public GDBranch(Arm.Cond cond, MC.Block target, MC.Block insertAtEnd) { 100 | super(Tag.Branch, insertAtEnd); 101 | this.cond = cond; 102 | this.target = target; 103 | } 104 | 105 | public GDBranch(boolean isFcmp, Arm.Cond cond, MC.Block target, MC.Block insertAtEnd) { 106 | super(Tag.Branch, insertAtEnd); 107 | this.cond = cond; 108 | this.target = target; 109 | isIcmp = !isFcmp; 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return tag.toString() + cond + "\t" + target; 115 | } 116 | 117 | 118 | public MC.Block getTrueBlock() { 119 | return target; 120 | } 121 | 122 | // public MC.Block getFalseBlock() { 123 | // return falseTargetBlock; 124 | // } 125 | 126 | public void setTarget(MC.Block onlySuccMB) { 127 | target = onlySuccMB; 128 | } 129 | 130 | public Arm.Cond getOppoCond() { 131 | return isIcmp ? CodeGen.CODEGEN.getIcmpOppoCond(cond) : CodeGen.CODEGEN.getFcmpOppoCond(cond); 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/lir/MICall.java: -------------------------------------------------------------------------------- 1 | package lir; 2 | 3 | import lir.Arm.Reg; 4 | import lir.MC.McFunction; 5 | 6 | import java.io.PrintStream; 7 | 8 | import static backend.CodeGen.*; 9 | import static backend.CodeGen.needFPU; 10 | import static lir.Arm.Regs.FPRs.s0; 11 | import static lir.Arm.Regs.GPRs.*; 12 | 13 | public class MICall extends MachineInst { 14 | public McFunction callee; 15 | 16 | public MICall(McFunction callee, MC.Block insertAtEnd) { 17 | super(Tag.Call, insertAtEnd); 18 | this.callee = callee; 19 | genDefUse(); 20 | } 21 | 22 | public void genDefUse() { 23 | defOpds.add(Reg.getR(r12)); 24 | defOpds.add(Reg.getR(lr)); 25 | // if (callee.mFunc.isExternal) { 26 | // for (int i = 0; i < 2; i++) { 27 | // if(needFPU) { 28 | // useOpds.add(Reg.getS(i)); 29 | // } 30 | // useOpds.add(Reg.getR(i)); 31 | // } 32 | 33 | if (needFPU) { 34 | for (int i = 0; i < 2; i++) { 35 | useOpds.add(Reg.getS(i)); 36 | defOpds.add(Reg.getS(i)); 37 | } 38 | } 39 | // TODO: 区分自己定义的函数 40 | for (int i = r0.ordinal(); i < r0.ordinal() + rParamCnt; i++) { 41 | defOpds.add(Reg.getR(i)); 42 | } 43 | if (needFPU) { 44 | for (int i = s0.ordinal(); i < s0.ordinal() + sParamCnt; i++) { 45 | defOpds.add(Reg.getS(i)); 46 | } 47 | } 48 | // } else { 49 | for (int i = r0.ordinal(); i < r0.ordinal() + Math.min(callee.intParamCount, rParamCnt); i++) { 50 | useOpds.add(Reg.getR(i)); 51 | // defOpds.add(Reg.getR(i)); 52 | } 53 | if (needFPU) { 54 | for (int i = s0.ordinal(); i < s0.ordinal() + Math.min(callee.floatParamCount, sParamCnt); i++) { 55 | useOpds.add(Reg.getS(i)); 56 | // defOpds.add(Reg.getS(i)); 57 | } 58 | } 59 | // } 60 | // TODO for bug test!!! 61 | /* 62 | if (callee.mFunc.hasRet()) { 63 | if (callee.mFunc.getRetType().isInt32Type()) { 64 | defOpds.add(Reg.getR(r0)); 65 | useOpds.add(Reg.getR(r0)); 66 | } else if (callee.mFunc.getRetType().isFloatType()) { 67 | defOpds.add(Reg.getS(s0)); 68 | useOpds.add(Reg.getS(s0)); 69 | } else { 70 | throw new AssertionError("Wrong call func type: has ret but is type of " + callee.mFunc.getRetType()); 71 | } 72 | } 73 | */ 74 | } 75 | 76 | @Override 77 | public void output(PrintStream os, McFunction f) { 78 | os.println(this); 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return tag + "\t" + callee.mFunc.getName(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/lir/MIComment.java: -------------------------------------------------------------------------------- 1 | package lir; 2 | 3 | import java.io.PrintStream; 4 | 5 | public class MIComment extends MachineInst { 6 | String content; 7 | 8 | public MIComment(String content, MC.Block insertAtEnd) { 9 | super(Tag.Comment, insertAtEnd); 10 | this.content = content; 11 | } 12 | 13 | @Override 14 | public void output(PrintStream os, MC.McFunction f) { 15 | os.println(this); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return tag.toString() + content; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/lir/StackCtl.java: -------------------------------------------------------------------------------- 1 | package lir; 2 | 3 | import java.io.PrintStream; 4 | import java.util.Iterator; 5 | 6 | import static backend.CodeGen.sParamCnt; 7 | import static lir.Arm.Regs.GPRs.*; 8 | 9 | public class StackCtl extends MachineInst { 10 | public StackCtl(Tag tag, MC.Block mb) { 11 | super(tag, mb); 12 | } 13 | 14 | public static class Push extends StackCtl { 15 | MC.McFunction savedRegsMf; 16 | MC.Block mb; 17 | 18 | public Push(MC.McFunction savedRegsMf, MC.Block mb) { 19 | super(Tag.Push, mb); 20 | this.savedRegsMf = savedRegsMf; 21 | this.mb = mb; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | if (savedRegsMf.mFunc.isExternal) { 27 | // throw new AssertionError("push in external func"); 28 | // return "\tpush\t{r0,r1,r2,r3}"; 29 | return "push\t{r2,r3}"; 30 | } else { 31 | StringBuilder sb = new StringBuilder(); 32 | if (savedRegsMf.usedCalleeSavedGPRs.size() > 0) { 33 | sb.append("push\t{"); 34 | Iterator gprIter = savedRegsMf.usedCalleeSavedGPRs.iterator(); 35 | sb.append(gprIter.next()); 36 | while (gprIter.hasNext()) { 37 | sb.append(",").append(gprIter.next()); 38 | } 39 | sb.append("}"); 40 | } 41 | return sb.toString(); 42 | } 43 | } 44 | 45 | @Override 46 | public void output(PrintStream os, MC.McFunction f) { 47 | os.println(this); 48 | } 49 | } 50 | 51 | public static class Pop extends MachineInst { 52 | MC.McFunction savedRegsMf; 53 | MC.Block mb; 54 | 55 | public Pop(MC.McFunction savedRegsMf, MC.Block mb) { 56 | super(Tag.Pop, mb); 57 | this.savedRegsMf = savedRegsMf; 58 | this.mb = mb; 59 | } 60 | 61 | 62 | @Override 63 | public String toString() { 64 | if (savedRegsMf.mFunc.isExternal) { 65 | // throw new AssertionError("pop in external func"); 66 | // return "\tpop\t{r0,r1,r2,r3}"; 67 | return "\tpop\t{r2,r3}"; 68 | } else { 69 | StringBuilder sb = new StringBuilder(); 70 | if (savedRegsMf.usedCalleeSavedGPRs.size() > 0) { 71 | sb.append("\tpop\t{"); 72 | Iterator gprIter = savedRegsMf.usedCalleeSavedGPRs.iterator(); 73 | sb.append(gprIter.next()); 74 | while (gprIter.hasNext()) { 75 | GPRs gpr = gprIter.next(); 76 | sb.append(",").append(gpr); 77 | } 78 | sb.append("}"); 79 | } 80 | return sb.toString(); 81 | } 82 | } 83 | 84 | @Override 85 | public void output(PrintStream os, MC.McFunction f) { 86 | os.println(this); 87 | } 88 | } 89 | 90 | 91 | public static class VPush extends StackCtl { 92 | MC.McFunction savedRegsMf; 93 | MC.Block mb; 94 | 95 | public VPush(MC.McFunction savedRegsMf, MC.Block mb) { 96 | super(Tag.Push, mb); 97 | this.savedRegsMf = savedRegsMf; 98 | this.mb = mb; 99 | } 100 | 101 | @Override 102 | public void output(PrintStream os, MC.McFunction f) { 103 | os.println(this); 104 | } 105 | 106 | @Override 107 | public String toString() { 108 | StringBuilder sb = new StringBuilder(); 109 | if (savedRegsMf.mFunc.isExternal) { 110 | // throw new AssertionError("vpush in external func"); 111 | // sb.append(String.format("\tvpush\t{s0-s%d}", sParamCnt - 1)); 112 | sb.append(String.format("\tvpush\t{s2-s%d}", sParamCnt - 1)); 113 | } else { 114 | if (savedRegsMf.usedCalleeSavedFPRs.size() > 0) { 115 | int fprNum = FPRs.values().length; 116 | boolean[] fprBit = new boolean[fprNum]; 117 | for (FPRs fpr : savedRegsMf.usedCalleeSavedFPRs) { 118 | fprBit[fpr.ordinal()] = true; 119 | } 120 | int start = 0; 121 | while (start < fprNum) { 122 | while (start < fprNum && !fprBit[start]) 123 | start++; 124 | if (start == fprNum) 125 | break; 126 | int end = start; 127 | while (end < fprNum && fprBit[end]) 128 | end++; 129 | end--; 130 | if (end == start) { 131 | throw new AssertionError("illegal vpush"); 132 | // assert false; 133 | // sb.append(String.format("\tvpush\t{s%d}%n", start)); 134 | } else if (end > start) { 135 | if (end - start > 15) { 136 | end = start + 15; 137 | } 138 | sb.append(String.format("\tvpush\t{s%d-s%d}%n", start, end)); 139 | } 140 | start = end + 1; 141 | } 142 | } 143 | } 144 | return sb.toString(); 145 | } 146 | } 147 | 148 | public static class VPop extends MachineInst { 149 | MC.McFunction savedRegsMf; 150 | MC.Block mb; 151 | 152 | public VPop(MC.McFunction savedRegsMf, MC.Block mb) { 153 | super(Tag.Pop, mb); 154 | this.savedRegsMf = savedRegsMf; 155 | this.mb = mb; 156 | } 157 | 158 | 159 | @Override 160 | public void output(PrintStream os, MC.McFunction f) { 161 | os.println(this); 162 | } 163 | 164 | @Override 165 | public String toString() { 166 | StringBuilder sb = new StringBuilder(); 167 | if (savedRegsMf.mFunc.isExternal) { 168 | // throw new AssertionError("vpop in external func"); 169 | // sb.append(String.format("\tvpop\t{s0-s%d}%n", sParamCnt - 1)); 170 | sb.append(String.format("\tvpop\t{s2-s%d}", sParamCnt - 1)); 171 | } else { 172 | if (savedRegsMf.usedCalleeSavedFPRs.size() > 0) { 173 | int fprNum = FPRs.values().length; 174 | boolean[] fprBit = new boolean[fprNum]; 175 | for (FPRs fpr : savedRegsMf.usedCalleeSavedFPRs) { 176 | fprBit[fpr.ordinal()] = true; 177 | } 178 | int end = fprNum - 1; 179 | while (end > -1) { 180 | while (end > -1 && !fprBit[end]) 181 | end--; 182 | if (end == -1) 183 | break; 184 | int start = end; 185 | while (start > -1 && fprBit[start]) 186 | start--; 187 | start++; 188 | if (start == end) { 189 | throw new AssertionError("illegal vpop"); 190 | // sb.append(String.format("\tvpop\t{s%d}%n", end)); 191 | } else if (start < end) { 192 | if (end - start > 15) { 193 | start = end - 15; 194 | } 195 | sb.append(String.format("\tvpop\t{s%d-s%d}%n", start, end)); 196 | } 197 | end = start - 1; 198 | } 199 | } 200 | } 201 | return sb.toString(); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/manage/Manager.java: -------------------------------------------------------------------------------- 1 | package manage; 2 | 3 | import lir.MC; 4 | import frontend.semantic.Initial; 5 | import frontend.semantic.symbol.Symbol; 6 | import lir.*; 7 | import mir.Function; 8 | import mir.GlobalVal; 9 | import mir.type.Type; 10 | import util.FileDealer; 11 | 12 | import java.io.FileNotFoundException; 13 | import java.io.FileOutputStream; 14 | import java.io.OutputStream; 15 | import java.util.*; 16 | 17 | import static mir.Function.Param.wrapParam; 18 | import static mir.type.Type.BasicType.F32_TYPE; 19 | import static mir.type.Type.BasicType.I32_TYPE; 20 | 21 | /** 22 | * LLVM IR 23 | */ 24 | public class Manager { 25 | public static final Manager MANAGER = new Manager(); 26 | private static final String MAIN_FUNCTION = "main"; 27 | public static boolean external = false; 28 | public final HashMap globals = new HashMap<>(); 29 | private final HashMap functions = new HashMap<>(); // 函数定义 30 | 31 | public int RK = 12; 32 | public int SK = 5; 33 | 34 | 35 | public ArrayList getFunctionList() { 36 | ArrayList list = new ArrayList<>(); 37 | for (Function function : functions.values()) { 38 | if (function.hasBody()) { 39 | list.add(function); 40 | } 41 | } 42 | return list; 43 | } 44 | 45 | public static class ExternFunction { 46 | public static final Function GET_INT = new Function(true, "getint", new ArrayList<>(), I32_TYPE); 47 | public static final Function GET_CH = new Function(true, "getch", new ArrayList<>(), I32_TYPE); 48 | public static final Function GET_FLOAT = new Function(true, "getfloat", new ArrayList<>(), F32_TYPE); 49 | public static final Function GET_ARR = new Function(true, "getarray", wrapParam(new Type.PointerType(I32_TYPE)), I32_TYPE); 50 | public static final Function GET_FARR = new Function(true, "getfarray", wrapParam(new Type.PointerType(F32_TYPE)), I32_TYPE); 51 | public static final Function PUT_INT = new Function(true, "putint", wrapParam(I32_TYPE), Type.VoidType.getVoidType()); 52 | public static final Function PUT_CH = new Function(true, "putch", wrapParam(I32_TYPE), Type.VoidType.getVoidType()); 53 | public static final Function PUT_FLOAT = new Function(true, "putfloat", wrapParam(F32_TYPE), Type.VoidType.getVoidType()); 54 | public static final Function PUT_ARR = new Function(true, "putarray", wrapParam(I32_TYPE, new Type.PointerType(I32_TYPE)), Type.VoidType.getVoidType()); 55 | public static final Function PUT_FARR = new Function(true, "putfarray", wrapParam(I32_TYPE, new Type.PointerType(F32_TYPE)), Type.VoidType.getVoidType()); 56 | public static final Function MEM_SET = new Function(true, "memset", wrapParam(new Type.PointerType(I32_TYPE), I32_TYPE, I32_TYPE), Type.VoidType.getVoidType()); 57 | public static final Function START_TIME = new Function(true, "starttime", wrapParam(I32_TYPE), Type.VoidType.getVoidType()); 58 | public static final Function STOP_TIME = new Function(true, "stoptime", wrapParam(I32_TYPE), Type.VoidType.getVoidType()); 59 | public static final Function PARALLEL_START = new Function(true, "parallel_start", new ArrayList<>(), I32_TYPE); 60 | public static final Function PARALLEL_END = new Function(true, "parallel_end", wrapParam(I32_TYPE), Type.VoidType.getVoidType()); 61 | } 62 | 63 | public final ArrayList externalFuncList = new ArrayList<>(); 64 | 65 | private Manager() { 66 | external = true; 67 | addFunction(ExternFunction.GET_INT); 68 | addFunction(ExternFunction.GET_CH); 69 | addFunction(ExternFunction.GET_FLOAT); 70 | addFunction(ExternFunction.GET_ARR); 71 | addFunction(ExternFunction.GET_FARR); 72 | addFunction(ExternFunction.PUT_INT); 73 | addFunction(ExternFunction.PUT_CH); 74 | addFunction(ExternFunction.PUT_FLOAT); 75 | addFunction(ExternFunction.PUT_ARR); 76 | addFunction(ExternFunction.PUT_FARR); 77 | addFunction(ExternFunction.MEM_SET); 78 | addFunction(ExternFunction.START_TIME); 79 | ExternFunction.START_TIME.isTimeFunc = true; 80 | addFunction(ExternFunction.STOP_TIME); 81 | ExternFunction.STOP_TIME.isTimeFunc = true; 82 | 83 | addFunction(ExternFunction.PARALLEL_START); 84 | addFunction(ExternFunction.PARALLEL_END); 85 | external = false; 86 | } 87 | 88 | public void addGlobal(Symbol symbol) { 89 | assert symbol.getInitial() != null; 90 | assert symbol.getValue() instanceof GlobalVal.GlobalValue; 91 | globals.putIfAbsent((GlobalVal.GlobalValue) symbol.getValue(), symbol.getInitial()); 92 | } 93 | 94 | public void addFunction(Function function) { 95 | functions.putIfAbsent(function.getName(), function); 96 | externalFuncList.add(function); 97 | } 98 | 99 | public boolean hasMainFunction() { 100 | return functions.containsKey(MAIN_FUNCTION); 101 | } 102 | 103 | static int outputLLVMCnt = 0; 104 | 105 | public void outputLLVM() throws FileNotFoundException { 106 | outputLLVM("llvmOf-" + outputLLVMCnt++); 107 | } 108 | 109 | public void outputLLVM(String llvmFilename) throws FileNotFoundException { 110 | outputLLVM(new FileOutputStream(llvmFilename + ".ll")); 111 | } 112 | 113 | public void outputLLVM(OutputStream out) { 114 | FileDealer.outputClear(); 115 | // 全局变量 116 | for (HashMap.Entry entry : globals.entrySet()) { 117 | FileDealer.addOutputString(entry.getKey().getName() + " = dso_local global " + entry.getValue()); 118 | } 119 | // 函数声明 120 | for (Function function : functions.values()) { 121 | if (!function.hasBody()) { 122 | FileDealer.addOutputString(function.getDeclare()); 123 | } 124 | } 125 | // 函数定义 126 | for (Function function : functions.values()) { 127 | if (function.getDeleted()) { 128 | continue; 129 | } 130 | if (function.hasBody()) { 131 | FileDealer.addOutputString(function.output()); 132 | } 133 | } 134 | FileDealer.outputStringList(out); 135 | } 136 | 137 | static int outputMIcnt = 0; 138 | 139 | public void outputMI(){ 140 | try { 141 | outputMI("lirOutput-" + outputMIcnt++); 142 | } catch (FileNotFoundException e) { 143 | throw new RuntimeException(e); 144 | } 145 | } 146 | 147 | public static void outputMI(boolean flag) { 148 | MC.Program p = MC.Program.PROGRAM; 149 | for (MC.McFunction mcFunc : p.funcList) { 150 | System.err.println("\n"); 151 | System.err.println(mcFunc.mFunc.getName()); 152 | for (MC.Block mb : mcFunc.mbList) { 153 | System.err.println("\n"); 154 | System.err.println(mb.getLabel()); 155 | for (MachineInst mi : mb.miList) { 156 | // if(mi.isCall())continue; 157 | // if(mi.isBranch())continue; 158 | // if(mi instanceof MIBinary)continue; 159 | // if(mi instanceof MILoad)continue; 160 | // if(mi instanceof MIStore)continue; 161 | // if(mi.isMove())continue; 162 | String str = mi instanceof MIComment ? "" : "\t"; 163 | System.err.println(str + mi); 164 | } 165 | } 166 | } 167 | } 168 | 169 | public void outputMI(String miFilename) throws FileNotFoundException { 170 | outputMI(new FileOutputStream(miFilename + ".txt")); 171 | } 172 | 173 | public static void outputMI(OutputStream out) { 174 | FileDealer.outputClear(); 175 | MC.Program p = MC.Program.PROGRAM; 176 | for (MC.McFunction mcFunc : p.funcList) { 177 | FileDealer.addOutputString("\n"); 178 | FileDealer.addOutputString(mcFunc.mFunc.getName()+":"); 179 | for (MC.Block mb : mcFunc.mbList) { 180 | FileDealer.addOutputString("\n"); 181 | FileDealer.addOutputString(mb.getLabel()+":"); 182 | FileDealer.addOutputString("@ pred:\t"+mb.predMBs.toString()); 183 | FileDealer.addOutputString("@ succ:\t"+mb.succMBs.toString()); 184 | for (MachineInst mi : mb.miList) { 185 | if(!(mi.getNext() instanceof MachineInst ) && mi.getNext()!=mb.miList.tail){ 186 | int a = 0; 187 | } 188 | String str = mi instanceof MIComment ? "" : "\t"; 189 | FileDealer.addOutputString(str + mi); 190 | } 191 | } 192 | } 193 | 194 | FileDealer.outputStringList(out); 195 | } 196 | 197 | public HashMap getGlobals() { 198 | return this.globals; 199 | } 200 | 201 | 202 | public HashMap getFunctions() { 203 | HashMap ret = new HashMap<>(); 204 | for (String str: functions.keySet()) { 205 | if (!functions.get(str).getDeleted()) { 206 | ret.put(str, functions.get(str)); 207 | } 208 | } 209 | return ret; 210 | // return this.functions; 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/midend/AggressiveMarkParallel.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import manage.Manager; 4 | import mir.*; 5 | import mir.type.Type; 6 | import util.CenterControl; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | 12 | public class AggressiveMarkParallel { 13 | 14 | private ArrayList functions; 15 | private static int parallel_num = 4; 16 | HashSet know = new HashSet<>(); 17 | private HashSet goodFunc = new HashSet<>(); 18 | private HashMap> funcLoadArrays = new HashMap<>(); 19 | 20 | 21 | public AggressiveMarkParallel(ArrayList functions) { 22 | this.functions = functions; 23 | } 24 | 25 | public void Run() { 26 | init(); 27 | for (Function function: functions) { 28 | know.clear(); 29 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 30 | if (!know.contains(bb) && bb.isLoopHeader()) { 31 | markLoop(bb.getLoop()); 32 | } 33 | } 34 | } 35 | } 36 | 37 | private void init() { 38 | for (Function function: functions) { 39 | funcLoadArrays.put(function, new HashSet<>()); 40 | if (check(function)) { 41 | goodFunc.add(function); 42 | } 43 | } 44 | } 45 | 46 | private boolean check(Function function) { 47 | for (Value param: function.getParams()) { 48 | if (param.getType().isPointerType()) { 49 | return false; 50 | } 51 | } 52 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 53 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 54 | if (instr instanceof Instr.Call) { 55 | return false; 56 | } 57 | if (instr instanceof Instr.Store) { 58 | return false; 59 | } else if (instr instanceof Instr.Load) { 60 | Value array = ((Instr.Load) instr).getPointer(); 61 | while (array instanceof Instr.GetElementPtr) { 62 | array = ((Instr.GetElementPtr) array).getPtr(); 63 | } 64 | funcLoadArrays.get(function).add(array); 65 | } 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | private boolean isPureLoop(Loop loop) { 72 | if (!loop.hasChildLoop()) { 73 | return true; 74 | } 75 | if (loop.getChildrenLoops().size() > 1) { 76 | return false; 77 | } 78 | if (!loop.isSimpleLoop() || !loop.isIdcSet()) { 79 | return false; 80 | } 81 | return isPureLoop(loop.getChildrenLoops().iterator().next()); 82 | } 83 | 84 | private void markLoop(Loop loop) { 85 | //当前只考虑main函数内的循环 86 | // if (!loop.getHeader().getFunction().getName().equals("main")) { 87 | // return; 88 | // } 89 | if (!isPureLoop(loop)) { 90 | return; 91 | } 92 | if (loop.hasChildLoop()) { 93 | return; 94 | } 95 | HashSet bbs = new HashSet<>(); 96 | HashSet idcVars = new HashSet<>(); 97 | HashSet loops = new HashSet<>(); 98 | bbs.addAll(loop.getNowLevelBB()); 99 | idcVars.add(loop.getIdcPHI()); 100 | loops.add(loop); 101 | 102 | HashSet idcInstrs = new HashSet<>(); 103 | idcInstrs.add(loop.getIdcPHI()); 104 | idcInstrs.add(loop.getIdcCmp()); 105 | idcInstrs.add(loop.getIdcAlu()); 106 | idcInstrs.add(loop.getHeader().getEndInstr()); 107 | idcInstrs.add(loop.getLatchs().iterator().next().getEndInstr()); 108 | 109 | for (Instr instr = loop.getHeader().getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 110 | if (instr instanceof Instr.Phi && !instr.equals(loop.getIdcPHI())) { 111 | return; 112 | } 113 | } 114 | 115 | //只有一次调用函数, 读一个数组, 写一个数组 116 | Value loadArray = null, storeArray = null; 117 | Function func = null; 118 | 119 | for (BasicBlock bb: bbs) { 120 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 121 | if (useOutLoops(instr, loops)) { 122 | return; 123 | } 124 | if (idcInstrs.contains(instr)) { 125 | 126 | } else if (instr instanceof Instr.Call) { 127 | if (((Instr.Call) instr).getFunc().isExternal) { 128 | continue; 129 | } 130 | if (func != null) { 131 | return; 132 | } 133 | func = ((Instr.Call) instr).getFunc(); 134 | } else if (instr instanceof Instr.GetElementPtr) { 135 | //trivel写法 136 | if (!(((Instr.GetElementPtr) instr).getPtr() instanceof GlobalVal.GlobalValue)) { 137 | return; 138 | } 139 | for (Value idc: ((Instr.GetElementPtr) instr).getIdxList()) { 140 | if (idc instanceof Constant && (int) ((Constant) idc).getConstVal() == 0) { 141 | continue; 142 | } 143 | if (!idcVars.contains(idc)) { 144 | return; 145 | } 146 | } 147 | } else if (instr instanceof Instr.Load) { 148 | if (loadArray != null) { 149 | return; 150 | } 151 | Value array = ((Instr.Load) instr).getPointer(); 152 | while (array instanceof Instr.GetElementPtr) { 153 | array = ((Instr.GetElementPtr) array).getPtr(); 154 | } 155 | loadArray = array; 156 | } else if (instr instanceof Instr.Store) { 157 | if (storeArray != null) { 158 | return; 159 | } 160 | Value array = ((Instr.Store) instr).getPointer(); 161 | while (array instanceof Instr.GetElementPtr) { 162 | array = ((Instr.GetElementPtr) array).getPtr(); 163 | } 164 | storeArray = array; 165 | } else { 166 | return; 167 | } 168 | } 169 | } 170 | 171 | if (func == null || loadArray == null || storeArray == null) { 172 | return; 173 | } 174 | 175 | if (!(loadArray instanceof GlobalVal.GlobalValue) || !(storeArray instanceof GlobalVal.GlobalValue)) { 176 | return; 177 | } 178 | 179 | //很强的限制,可以考虑删除 180 | // if (funcLoadArrays.get(func).size() != 1) { 181 | // return; 182 | // } 183 | 184 | for (Value array: funcLoadArrays.get(func)) { 185 | if (!(array instanceof GlobalVal.GlobalValue)) { 186 | return; 187 | } 188 | } 189 | if (funcLoadArrays.get(func).contains(storeArray) || loadArray.equals(storeArray)) { 190 | return; 191 | } 192 | 193 | loop.setCanAggressiveParallel(true); 194 | CenterControl._FUNC_PARALLEL = true; 195 | } 196 | 197 | 198 | private boolean useOutLoops(Value value, HashSet loops) { 199 | for (Use use = value.getBeginUse(); use.getNext() != null; use = (Use) use.getNext()) { 200 | Instr user = use.getUser(); 201 | if (!loops.contains(user.parentBB().getLoop())) { 202 | return true; 203 | } 204 | } 205 | return false; 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/midend/ArrayLift.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import frontend.semantic.Initial; 4 | import mir.BasicBlock; 5 | import mir.Function; 6 | import mir.GlobalVal; 7 | import mir.Instr; 8 | import mir.type.Type; 9 | 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | 13 | public class ArrayLift { 14 | 15 | private ArrayList functions; 16 | private HashMap globalValues; 17 | private static final int length_low_line = 10; 18 | 19 | public ArrayLift(ArrayList functions, HashMap globalValues) { 20 | this.functions = functions; 21 | this.globalValues = globalValues; 22 | } 23 | 24 | public void Run() { 25 | for (Function function: functions) { 26 | if (function.getName().equals("main") || function.onlyOneUser()) { 27 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 28 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 29 | if (instr instanceof Instr.Alloc && instr.parentBB().getLoop().getLoopDepth() == 0) { 30 | //TODO: 31 | Type type = ((Type.PointerType) instr.getType()).getInnerType(); 32 | Initial.ZeroInit init = new Initial.ZeroInit(type); 33 | GlobalVal.GlobalValue val = new GlobalVal.GlobalValue(type, "lift_" + instr.getNameWithOutPrefix(), init); 34 | globalValues.put(val, init); 35 | instr.modifyAllUseThisToUseA(val); 36 | instr.remove(); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/midend/ArraySSA.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import frontend.semantic.Initial; 4 | import mir.BasicBlock; 5 | import mir.Function; 6 | import mir.GlobalVal; 7 | import mir.Instr; 8 | import mir.type.Type; 9 | 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.HashSet; 13 | 14 | public class ArraySSA { 15 | //只考虑局部数组 16 | //全局可以考虑 遍历支配树, 遇到一个Array的store就删除之前的GVNhash,达到GVN的目的 17 | private ArrayList functions; 18 | private HashMap globalValues; 19 | private HashSet allocs = new HashSet<>(); 20 | 21 | public ArraySSA(ArrayList functions, HashMap globalValues) { 22 | this.functions = functions; 23 | this.globalValues = globalValues; 24 | } 25 | 26 | //TODO:插入Def PHI和merge PHI 27 | private void Run() { 28 | GetAllocs(); 29 | //局部数组 30 | for (Instr.Alloc alloc: allocs) { 31 | 32 | } 33 | 34 | //全局数组 35 | for (GlobalVal.GlobalValue globalValue: globalValues.keySet()) { 36 | if (((Type.PointerType) globalValue.getType()).getInnerType().isArrType() && globalValue.canLocal()) { 37 | //认为入口块定义全局数组 38 | } 39 | } 40 | } 41 | 42 | private void GetAllocs() { 43 | for (Function function: functions) { 44 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 45 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 46 | if (instr instanceof Instr.Alloc) { 47 | allocs.add((Instr.Alloc) instr); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | private void insertPHIForLocalArray(Instr instr) { 55 | 56 | } 57 | 58 | private void insertPHIForGlobalArray(GlobalVal.GlobalValue globalValue) { 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/midend/BranchLift.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | 9 | public class BranchLift { 10 | 11 | private ArrayList functions; 12 | 13 | public BranchLift(ArrayList functions) { 14 | this.functions = functions; 15 | } 16 | 17 | public void Run() { 18 | branchLift(); 19 | } 20 | 21 | private void branchLift() { 22 | for (Function function: functions) { 23 | branchLiftForFunc(function); 24 | } 25 | } 26 | 27 | private void branchLiftForFunc(Function function) { 28 | //TODO:一次只能提升一个循环的一个Branch 29 | for (BasicBlock head: function.getLoopHeads()) { 30 | Loop loop = head.getLoop(); 31 | HashMap> conds = loop.getConds(); 32 | for (int key: conds.keySet()) { 33 | if (conds.get(key).size() == 1) { 34 | Instr br = null; 35 | for (Instr temp: conds.get(key)) { 36 | br = temp; 37 | } 38 | if (!(br instanceof Instr.Branch)) { 39 | continue; 40 | } 41 | // if (loop.getChildrenLoops().size() != 0) { 42 | // continue; 43 | // } 44 | liftBrOutLoop((Instr.Branch) br, loop); 45 | //TODO:只提升一个branch就直接return 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | 52 | private void liftBrOutLoop(Instr.Branch thenBr, Loop thenLoop) { 53 | CloneInfoMap.clear(); 54 | Function function = thenLoop.getHeader().getFunction(); 55 | BasicBlock thenHead = thenLoop.getHeader(); 56 | thenLoop.cloneToFunc(function); 57 | // for (BasicBlock bb: thenLoop.getNowLevelBB()) { 58 | // System.err.println(bb.getLabel() + " to " + ((BasicBlock) CloneInfoMap.getReflectedValue(bb)).getLabel()); 59 | // } 60 | 61 | thenLoop.fix(); 62 | Loop elseLoop = CloneInfoMap.getReflectedLoop(thenLoop); 63 | BasicBlock elseHead = elseLoop.getHeader(); 64 | 65 | BasicBlock transBB = new BasicBlock(function, thenLoop.getParentLoop()); 66 | HashSet enterings = thenLoop.getEnterings(); 67 | 68 | //entering --> transBB 69 | for (BasicBlock entering: enterings) { 70 | Instr instr = entering.getEndInstr(); 71 | if (instr instanceof Instr.Jump) { 72 | instr.modifyUse(transBB, 0); 73 | } else if (instr instanceof Instr.Branch){ 74 | ArrayList values = instr.getUseValueList(); 75 | if (values.size() == 1) { 76 | instr.modifyUse(transBB, 0); 77 | } else { 78 | int index = values.indexOf(thenHead); 79 | instr.modifyUse(transBB, index); 80 | } 81 | } else { 82 | System.err.println("error"); 83 | } 84 | entering.modifySuc(thenHead, transBB); 85 | transBB.addPre(entering); 86 | thenHead.modifyPre(entering, transBB); 87 | elseHead.modifyPre(entering, transBB); 88 | 89 | //transBB.addPre(entering); 90 | } 91 | 92 | //Clone br 93 | // entering --> transBB 94 | // transBB --> thenHead & elseHead 95 | transBB.addSuc(thenHead); 96 | transBB.addSuc(elseHead); 97 | 98 | 99 | Instr.Branch elseBr = (Instr.Branch) CloneInfoMap.getReflectedValue(thenBr); 100 | Instr brInTransBB = thenBr.cloneToBB(transBB); 101 | if (transBB.getLoopDep() > 0) { 102 | brInTransBB.setInLoopCond(); 103 | brInTransBB.setCondCount(thenBr.getCondCount()); 104 | } 105 | 106 | brInTransBB.modifyUse(thenHead, 1); 107 | brInTransBB.modifyUse(elseHead, 2); 108 | 109 | //修改thenLoop和elseLoop中的br为无条件转跳 110 | //thenBr.modifyUse(new Constant.ConstantInt(1), 0); 111 | Instr.Jump thenJump = new Instr.Jump((BasicBlock) thenBr.getUseValueList().get(1), thenBr.parentBB()); 112 | thenBr.insertBefore(thenJump); 113 | 114 | 115 | //elseBr.modifyUse(new Constant.ConstantInt(0), 0); 116 | Instr.Jump elseJump = new Instr.Jump((BasicBlock) elseBr.getUseValueList().get(2), elseBr.parentBB()); 117 | elseBr.insertBefore(elseJump); 118 | 119 | thenBr.remove(); 120 | elseBr.remove(); 121 | 122 | 123 | //修改exiting的数据流 124 | // 125 | //修改exits的(冗余)phi 126 | HashSet exits = thenLoop.getExits(); 127 | for (BasicBlock bb: exits) { 128 | ArrayList addBBs = new ArrayList<>(); 129 | for (BasicBlock pre: bb.getPrecBBs()) { 130 | if (CloneInfoMap.valueMap.containsKey(pre)) { 131 | addBBs.add((BasicBlock) CloneInfoMap.getReflectedValue(pre)); 132 | } 133 | } 134 | for (BasicBlock add: addBBs) { 135 | bb.addPre(add); 136 | } 137 | 138 | Instr instr = bb.getBeginInstr(); 139 | while (instr.getNext() != null) { 140 | if (instr instanceof Instr.Phi) { 141 | ArrayList adds = new ArrayList<>(); 142 | for (Value used: instr.getUseValueList()) { 143 | int index = instr.getUseValueList().indexOf(used); 144 | if (CloneInfoMap.valueMap.containsKey(bb.getPrecBBs().get(index))) { 145 | adds.add(CloneInfoMap.getReflectedValue(used)); 146 | } 147 | // if (CloneInfoMap.valueMap.containsKey(used)) { 148 | // adds.add(CloneInfoMap.getReflectedValue(used)); 149 | // } 150 | 151 | //adds.add(CloneInfoMap.getReflectedValue(used)); 152 | } 153 | for (Value add: adds) { 154 | ((Instr.Phi) instr).addOptionalValue(add); 155 | } 156 | assert instr.parentBB().getPrecBBs().size() == instr.getUseValueList().size(); 157 | } 158 | instr = (Instr) instr.getNext(); 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/midend/BranchOptimize.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import manage.Manager; 4 | import mir.*; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | 10 | public class BranchOptimize { 11 | 12 | private ArrayList functions; 13 | 14 | public BranchOptimize(ArrayList functions) { 15 | this.functions = functions; 16 | } 17 | 18 | public void Run() { 19 | if (!MidEndRunner.O2) { 20 | RemoveUselessPHI(); 21 | ModifyConstBranch(); 22 | } 23 | 24 | RemoveUselessPHI(); 25 | RemoveUselessJump(); 26 | remakeCFG(); 27 | ModifyConstBranch(); 28 | remakeCFG(); 29 | //fixme:check貌似是错的 30 | //RemoveBBOnlyJump(); 31 | } 32 | 33 | private void remakeCFG() { 34 | MakeDFG makeDFG = new MakeDFG(functions); 35 | makeDFG.Run(); 36 | } 37 | 38 | //删除只有一个use的PHI(冗余PHI) 39 | private void RemoveUselessPHI() { 40 | for (Function function: functions) { 41 | removeUselessPHIForFunc(function); 42 | } 43 | } 44 | 45 | private void RemoveUselessJump() { 46 | for (Function function: functions) { 47 | removeUselessJumpForFunc(function); 48 | } 49 | } 50 | 51 | //branch条件为恒定值的时候,变为JUMP 52 | private void ModifyConstBranch() { 53 | for (Function function: functions) { 54 | modifyConstBranchForFunc(function); 55 | } 56 | } 57 | 58 | private void RemoveBBOnlyJump() { 59 | for (Function function: functions) { 60 | removeBBOnlyJumpForFunc(function); 61 | } 62 | } 63 | 64 | private void removeUselessPHIForFunc(Function function) { 65 | BasicBlock bb = function.getBeginBB(); 66 | while (bb.getNext() != null) { 67 | Instr instr = bb.getBeginInstr(); 68 | while (instr.getNext() != null) { 69 | if (!(instr instanceof Instr.Phi)) { 70 | break; 71 | } 72 | if (instr.getUseValueList().size() == 1) { 73 | Value value = instr.getUseValueList().get(0); 74 | instr.modifyAllUseThisToUseA(value); 75 | instr.remove(); 76 | } 77 | 78 | instr = (Instr) instr.getNext(); 79 | } 80 | 81 | bb = (BasicBlock) bb.getNext(); 82 | } 83 | } 84 | 85 | private void removeUselessJumpForFunc(Function function) { 86 | HashSet bbCanRemove = new HashSet<>(); 87 | BasicBlock bb = function.getBeginBB(); 88 | while (bb.getNext() != null) { 89 | if (bb.getPrecBBs().size() == 1) { 90 | bbCanRemove.add(bb); 91 | } 92 | bb = (BasicBlock) bb.getNext(); 93 | } 94 | for (BasicBlock mid: bbCanRemove) { 95 | // bbs -> pre -> mid -> bbs 96 | // bbs -> pre -> bbs 97 | // move all instr in mid to pre 98 | BasicBlock pre = mid.getPrecBBs().get(0); 99 | if (pre.getSuccBBs().size() != 1) { 100 | continue; 101 | } 102 | pre.getEndInstr().remove(); 103 | ArrayList instrInMid = new ArrayList<>(); 104 | for (Instr instr = mid.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 105 | instrInMid.add(instr); 106 | } 107 | for (Instr instr: instrInMid) { 108 | instr.setBb(pre); 109 | pre.insertAtEnd(instr); 110 | } 111 | pre.setSuccBBs(mid.getSuccBBs()); 112 | for (BasicBlock temp: mid.getSuccBBs()) { 113 | temp.modifyPre(mid, pre); 114 | } 115 | mid.remove(); 116 | } 117 | } 118 | 119 | private void modifyConstBranchForFunc(Function function) { 120 | HashMap modifyBrMap = new HashMap<>(); 121 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 122 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 123 | if (instr instanceof Instr.Branch) { 124 | Value cond = ((Instr.Branch) instr).getCond(); 125 | if (cond instanceof Constant) { 126 | int val = (int) ((Constant) cond).getConstVal(); 127 | boolean tag = val == 1; 128 | modifyBrMap.put((Instr.Branch) instr, tag); 129 | } 130 | } 131 | } 132 | } 133 | 134 | for (Instr.Branch br: modifyBrMap.keySet()) { 135 | BasicBlock tagBB = null; 136 | BasicBlock parentBB = br.parentBB(); 137 | if (modifyBrMap.get(br)) { 138 | tagBB = br.getThenTarget(); 139 | } else { 140 | tagBB = br.getElseTarget(); 141 | } 142 | //br.remove(); 143 | Instr.Jump jump = new Instr.Jump(tagBB, parentBB); 144 | br.insertBefore(jump); 145 | //br.getCond().remove(); 146 | br.remove(); 147 | 148 | } 149 | } 150 | 151 | private void removeBBOnlyJumpForFunc(Function function) { 152 | HashSet removes = new HashSet<>(); 153 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 154 | if (function.entry.equals(bb)) { 155 | continue; 156 | } 157 | if (bb.getBeginInstr().equals(bb.getEndInstr())) { 158 | Instr instr = bb.getBeginInstr(); 159 | if (instr instanceof Instr.Jump) { 160 | //TODO: 161 | Value next = ((Instr.Jump) instr).getTarget(); 162 | BasicBlock target = ((Instr.Jump) instr).getTarget(); 163 | bb.modifyAllUseThisToUseA(next); 164 | for (BasicBlock pre: bb.getPrecBBs()) { 165 | pre.modifySuc(bb, target); 166 | target.modifyPre(bb, pre); 167 | } 168 | removes.add(bb); 169 | } 170 | } 171 | } 172 | for (BasicBlock bb: removes) { 173 | bb.remove(); 174 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 175 | instr.remove(); 176 | } 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/midend/CloneInfoMap.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.Loop; 4 | import mir.Value; 5 | 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | 9 | public class CloneInfoMap { 10 | 11 | public static HashMap loopMap = new HashMap<>(); 12 | public static HashMap loopCondCntMap = new HashMap<>(); 13 | public static HashMap valueMap = new HashMap<>(); 14 | //public static HashSet loopNeedFix = new HashSet<>(); 15 | //public static HashSet bbNeedFix = new HashSet<>(); 16 | 17 | public static void addLoopReflect(Loop srcLoop, Loop tagLoop) { 18 | //assert !loopMap.containsKey(srcLoop); 19 | loopMap.put(srcLoop, tagLoop); 20 | } 21 | // 22 | // public static boolean isReflected(Loop loop) { 23 | // return loopMap.containsKey(loop); 24 | // } 25 | 26 | public static Loop getReflectedLoop(Loop loop) { 27 | if (loopMap.containsKey(loop)) { 28 | return loopMap.get(loop); 29 | } else { 30 | return loop; 31 | } 32 | } 33 | 34 | public static void addLoopCondCntReflect(Integer src, Integer tag) { 35 | loopCondCntMap.put(src, tag); 36 | } 37 | 38 | public static Integer getLoopCondCntReflect(Integer cnt) { 39 | if (loopCondCntMap.containsKey(cnt)) { 40 | return loopCondCntMap.get(cnt); 41 | } else { 42 | return cnt; 43 | } 44 | } 45 | 46 | public static void addValueReflect(Value src, Value tag) { 47 | valueMap.put(src, tag); 48 | } 49 | 50 | public static Value getReflectedValue(Value value) { 51 | if (valueMap.containsKey(value)) { 52 | return valueMap.get(value); 53 | } 54 | return value; 55 | } 56 | 57 | // public static void addLoopNeedFix(Loop loop) { 58 | // loopNeedFix.add(loop); 59 | // } 60 | // 61 | // public static void rmBBNeedFix(BasicBlock bb) { 62 | // bbNeedFix.remove(bb); 63 | // } 64 | 65 | public static void clear() { 66 | loopMap.clear(); 67 | loopCondCntMap.clear(); 68 | valueMap.clear(); 69 | //loopNeedFix.clear(); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/midend/ConstTransFold.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | import mir.Constant; 5 | import mir.Function; 6 | import mir.Instr; 7 | 8 | import java.util.ArrayList; 9 | 10 | public class ConstTransFold { 11 | 12 | private ArrayList functions; 13 | 14 | public ConstTransFold(ArrayList functions) { 15 | this.functions = functions; 16 | } 17 | 18 | public void Run() { 19 | for (Function function: functions) { 20 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 21 | for (Instr instr = bb.getBeginInstr(); instr.getNext()!= null; instr = (Instr) instr.getNext()) { 22 | if (instr instanceof Instr.FPtosi && ((Instr.FPtosi) instr).getRVal1() instanceof Constant.ConstantFloat) { 23 | float val = (float) ((Constant.ConstantFloat) ((Instr.FPtosi) instr).getRVal1()).getConstVal(); 24 | int ret = (int) val; 25 | 26 | instr.modifyAllUseThisToUseA(new Constant.ConstantInt(ret)); 27 | instr.remove(); 28 | } else if (instr instanceof Instr.SItofp && ((Instr.SItofp) instr).getRVal1() instanceof Constant.ConstantInt) { 29 | int val = (int) ((Constant.ConstantInt) ((Instr.SItofp) instr).getRVal1()).getConstVal(); 30 | float ret = (float) val; 31 | 32 | instr.modifyAllUseThisToUseA(new Constant.ConstantFloat(ret)); 33 | instr.remove(); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/midend/FuncInfo.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class FuncInfo { 8 | 9 | private ArrayList functions; 10 | 11 | public FuncInfo(ArrayList functions) { 12 | this.functions = functions; 13 | } 14 | 15 | public void Run() { 16 | for (Function function: functions) { 17 | boolean ret = checkCanGVN(function); 18 | function.setCanGVN(ret); 19 | } 20 | } 21 | 22 | private boolean checkCanGVN(Function function) { 23 | for (Function.Param param: function.getParams()) { 24 | if (param.getType().isPointerType()) { 25 | return false; 26 | } 27 | } 28 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 29 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 30 | if (instr instanceof Instr.Call) { 31 | return false; 32 | } 33 | for (Value value: instr.getUseValueList()) { 34 | if (value instanceof GlobalVal.GlobalValue) { 35 | return false; 36 | } 37 | } 38 | } 39 | } 40 | return true; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/midend/GepFuse.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | import mir.type.Type; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.HashSet; 9 | 10 | public class GepFuse { 11 | 12 | //考虑不能融合的情况? 13 | //TODO:是否存在不能融合的情况? 14 | private ArrayList functions; 15 | private ArrayList Geps = new ArrayList<>(); 16 | 17 | public GepFuse(ArrayList functions) { 18 | this.functions = functions; 19 | } 20 | 21 | public void Run() { 22 | gepFuse(); 23 | } 24 | 25 | private void gepFuse() { 26 | for (Function function: functions) { 27 | gepFuseForFunc(function); 28 | } 29 | } 30 | 31 | private void gepFuseForFunc(Function function) { 32 | //删除冗余GEP 33 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 34 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 35 | if (instr instanceof Instr.GetElementPtr && isZeroOffsetGep((Instr.GetElementPtr) instr)) { 36 | instr.modifyAllUseThisToUseA(((Instr.GetElementPtr) instr).getPtr()); 37 | } 38 | } 39 | } 40 | 41 | //GEP融合 42 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 43 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 44 | if (instr instanceof Instr.GetElementPtr && !(((Instr.GetElementPtr) instr).getPtr() instanceof Instr.GetElementPtr)) { 45 | fuseDFS(instr); 46 | } 47 | } 48 | } 49 | 50 | } 51 | 52 | private boolean isZeroOffsetGep(Instr.GetElementPtr gep) { 53 | // if (!(gep.getPtr() instanceof Instr.GetElementPtr)) { 54 | // return false; 55 | // } 56 | ArrayList values = gep.getIdxList(); 57 | if (values.size() > 1) { 58 | return false; 59 | } 60 | for (Value value: values) { 61 | if (!(value instanceof Constant)) { 62 | return false; 63 | } 64 | int val = (int) ((Constant) value).getConstVal(); 65 | if (val != 0) { 66 | return false; 67 | } 68 | } 69 | return true; 70 | } 71 | 72 | private void fuseDFS(Instr instr) { 73 | Geps.add((Instr.GetElementPtr) instr); 74 | HashSet uses = new HashSet<>(); 75 | for (Use use = instr.getBeginUse(); use.getNext() != null; use = (Use) use.getNext()) { 76 | uses.add(use); 77 | } 78 | boolean tag = false; 79 | for (Use use: uses) { 80 | // boolean hasUse = false; 81 | // for (Value value: use.getUser().getUseValueList()) { 82 | // if (value.equals(instr)) { 83 | // hasUse = true; 84 | // break; 85 | // } 86 | // } 87 | // if (!hasUse) { 88 | // continue; 89 | // } 90 | //此处user use并没有被维护 91 | if (use.getUser() instanceof Instr.GetElementPtr) { 92 | fuseDFS(use.getUser()); 93 | } else if (use.getUser() instanceof Instr.Store || 94 | use.getUser() instanceof Instr.Load || 95 | use.getUser() instanceof Instr.Call) { 96 | if (!tag) { 97 | fuse(); 98 | tag = true; 99 | } 100 | } 101 | } 102 | Geps.remove(Geps.size() - 1); 103 | } 104 | 105 | private void fuse() { 106 | if (Geps.size() == 1) { 107 | return; 108 | } 109 | int begin_index = Geps.size() - 1; 110 | while (begin_index > 0) { 111 | if (Geps.get(begin_index).getPtr().equals(Geps.get(begin_index - 1))) { 112 | begin_index--; 113 | } else { 114 | break; 115 | } 116 | } 117 | Instr.GetElementPtr gep_0 = Geps.get(begin_index); 118 | Instr.GetElementPtr gep_end = Geps.get(Geps.size() - 1); 119 | int dim = ((Type.ArrayType) ((Type.PointerType) Geps.get(0).getPtr().getType()).getInnerType()).getDimSize(); 120 | int sum = 0; 121 | for (int i = begin_index; i < Geps.size(); i++) { 122 | //TODO:在过程中发现偏移相等了 123 | // if (sum == dim) { 124 | // return; 125 | // } 126 | Instr.GetElementPtr gep = Geps.get(i); 127 | sum += gep.getIdxList().size() - 1; 128 | } 129 | assert sum <= dim; 130 | if (sum < dim) { 131 | return; 132 | } 133 | 134 | 135 | ArrayList retIndexs = new ArrayList<>(); 136 | retIndexs.addAll(gep_0.getIdxList()); 137 | for (int i = begin_index + 1; i < Geps.size(); i++) { 138 | Instr.GetElementPtr gep = Geps.get(i); 139 | 140 | int num = retIndexs.size(); 141 | Value nowEndIndex = retIndexs.get(num - 1); 142 | Value baseOffset = gep.getIdxList().get(0); 143 | 144 | if (nowEndIndex instanceof Constant && baseOffset instanceof Constant) { 145 | int A = (int) ((Constant) nowEndIndex).getConstVal(); 146 | int B = (int) ((Constant) baseOffset).getConstVal(); 147 | //gep_0.modifyUse(new Constant.ConstantInt(A + B), num); 148 | retIndexs.set(num - 1, new Constant.ConstantInt(A + B)); 149 | } else { 150 | if (nowEndIndex instanceof Constant) { 151 | int A = (int) ((Constant) nowEndIndex).getConstVal(); 152 | if (A != 0) { 153 | return; 154 | } 155 | //gep_0.modifyUse(baseOffset, num); 156 | retIndexs.set(num - 1, baseOffset); 157 | } else if (baseOffset instanceof Constant) { 158 | int B = (int) ((Constant) baseOffset).getConstVal(); 159 | if (B != 0) { 160 | return; 161 | } 162 | } else { 163 | return; 164 | } 165 | } 166 | 167 | for (int j = 1; j < gep.getIdxList().size(); j++) { 168 | //gep_0.addIdx(gep.getIdxList().get(j)); 169 | retIndexs.add(gep.getIdxList().get(j)); 170 | } 171 | } 172 | //Geps.get(Geps.size() - 1).modifyAllUseThisToUseA(gep_0); 173 | //gep_0.delFromNowBB(); 174 | //Geps.get(Geps.size() - 1).insertAfter(gep_0); 175 | //Geps.get(0).modifyType(Geps.get(Geps.size() - 1).getType()); 176 | gep_end.modifyPtr(gep_0.getPtr()); 177 | gep_end.modifyIndexs(retIndexs); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/midend/GepSplit.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | import mir.type.Type; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class GepSplit { 9 | private ArrayList functions; 10 | public GepSplit(ArrayList functions) { 11 | this.functions = functions; 12 | } 13 | 14 | public void Run() { 15 | GepSplit(); 16 | RemoveUselessGep(); 17 | } 18 | 19 | private void GepSplit() { 20 | for (Function function: functions) { 21 | gepSplitForFunc(function); 22 | } 23 | } 24 | 25 | //TODO:GEP最终的格式? 26 | // %v30 = getelementptr inbounds [3 x [4 x [5 x i32]]], [3 x [4 x [5 x i32]]]* %f1, i32 1, i32 2 27 | // ---------------- 28 | // 是否需要保证index[0] == 0 ==> choose 29 | // %v30 = getelementptr inbounds [3 x [4 x [5 x i32]]], [3 x [4 x [5 x i32]]]* %f1, i32 %1 30 | // %v31 = getelementptr inbounds [3 x [4 x [5 x i32]]], [3 x [4 x [5 x i32]]]* %30, i32 0, i32 %2 31 | // 不允许强制类型转换 32 | // %v30 = getelementptr inbounds [3 x [4 x [5 x i32]]], [3 x [4 x [5 x i32]]]* %f1, i32 1 33 | // %v31 = getelementptr inbounds [4 x [5 x i32]], [4 x [5 x i32]]* %30, i32 2 34 | private void gepSplitForFunc(Function function) { 35 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 36 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 37 | if (instr instanceof Instr.GetElementPtr && ((Instr.GetElementPtr) instr).getIdxList().size() >= 2) { 38 | split((Instr.GetElementPtr) instr); 39 | } 40 | } 41 | } 42 | } 43 | 44 | private void split(Instr.GetElementPtr gep) { 45 | BasicBlock bb = gep.parentBB(); 46 | ArrayList indexs = new ArrayList<>(gep.getIdxList().subList(1, gep.getIdxList().size())); 47 | Value ptr = gep.getPtr(); 48 | Instr pos = gep; 49 | Value pre = gep.getIdxList().get(0); 50 | ArrayList preIndexs = new ArrayList<>(); 51 | preIndexs.add(pre); 52 | if (gep.getIdxList().size() == 2) { 53 | if (pre instanceof Constant && ((int) ((Constant) pre).getConstVal()) == 0) { 54 | return; 55 | } 56 | } 57 | Instr preOffset = new Instr.GetElementPtr(((Type.PointerType) ptr.getType()).getInnerType(), ptr, preIndexs, bb); 58 | pos.insertAfter(preOffset); 59 | pos = preOffset; 60 | ptr = preOffset; 61 | for (Value index: indexs) { 62 | ArrayList tempIndexs = new ArrayList<>(); 63 | tempIndexs.add(new Constant.ConstantInt(0)); 64 | tempIndexs.add(index); 65 | Instr.GetElementPtr temp = new Instr.GetElementPtr(((Type.ArrayType) ((Type.PointerType) ptr.getType()).getInnerType()).getBaseType(), ptr, tempIndexs, bb); 66 | pos.insertAfter(temp); 67 | pos = temp; 68 | ptr = temp; 69 | } 70 | gep.modifyAllUseThisToUseA(pos); 71 | } 72 | 73 | // private void splitA(Instr.GetElementPtr gep) { 74 | // BasicBlock bb = gep.parentBB(); 75 | // ArrayList indexs = new ArrayList<>(gep.getIdxList().subList(1, gep.getIdxList().size())); 76 | // Value ptr = gep.getPtr(); 77 | // Instr pos = gep; 78 | // for (Value index: indexs) { 79 | // ArrayList tempIndexs = new ArrayList<>(); 80 | // tempIndexs.add(new Constant.ConstantInt(0)); 81 | // tempIndexs.add(index); 82 | // Instr.GetElementPtr temp = new Instr.GetElementPtr(((Type.ArrayType) ((Type.PointerType) ptr.getType()).getInnerType()).getBaseType(), ptr, tempIndexs, bb); 83 | // pos.insertAfter(temp); 84 | // pos = temp; 85 | // ptr = temp; 86 | // } 87 | // gep.modifyAllUseThisToUseA(pos); 88 | // } 89 | 90 | private void RemoveUselessGep() { 91 | for (Function function: functions) { 92 | //删除冗余GEP 93 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 94 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 95 | if (instr instanceof Instr.GetElementPtr && isZeroOffsetGep((Instr.GetElementPtr) instr)) { 96 | instr.modifyAllUseThisToUseA(((Instr.GetElementPtr) instr).getPtr()); 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | private boolean isZeroOffsetGep(Instr.GetElementPtr gep) { 104 | ArrayList values = gep.getIdxList(); 105 | if (values.size() > 1) { 106 | return false; 107 | } 108 | for (Value value: values) { 109 | if (!(value instanceof Constant)) { 110 | return false; 111 | } 112 | int val = (int) ((Constant) value).getConstVal(); 113 | if (val != 0) { 114 | return false; 115 | } 116 | } 117 | return true; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/midend/GlobalArrayGVN.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import frontend.semantic.Initial; 4 | import manage.Manager; 5 | import mir.*; 6 | import mir.type.Type; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | 12 | public class GlobalArrayGVN { 13 | 14 | private ArrayList functions; 15 | 16 | private HashMap globalValues; 17 | 18 | private HashMap> defs = new HashMap<>(); 19 | private HashMap> loads = new HashMap<>(); 20 | 21 | HashMap GvnMap = new HashMap<>(); 22 | HashMap GvnCnt = new HashMap<>(); 23 | 24 | 25 | public GlobalArrayGVN(ArrayList functions, HashMap globalValues) { 26 | this.functions = functions; 27 | this.globalValues = globalValues; 28 | } 29 | 30 | public void Run() { 31 | init(); 32 | GVN(); 33 | } 34 | 35 | private void init() { 36 | for (Function function: functions) { 37 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 38 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 39 | if (instr instanceof Instr.Alloc) { 40 | ((Instr.Alloc) instr).clearLoads(); 41 | } else if (instr instanceof Instr.Load) { 42 | ((Instr.Load) instr).clear(); 43 | } else if (instr instanceof Instr.Store) { 44 | ((Instr.Store) instr).clear(); 45 | } 46 | } 47 | } 48 | for (Value param: function.getParams()) { 49 | if (param.getType() instanceof Type.PointerType) { 50 | ((Function.Param) param).clearLoads(); 51 | } 52 | } 53 | } 54 | 55 | for (GlobalVal.GlobalValue val: globalValues.keySet()) { 56 | if (((Type.PointerType) val.getType()).getInnerType() instanceof Type.ArrayType) { 57 | for (Use use = val.getBeginUse(); use.getNext() != null; use = (Use) use.getNext()) { 58 | DFS(val, use.getUser()); 59 | } 60 | } 61 | } 62 | 63 | 64 | } 65 | 66 | private void DFS(GlobalVal.GlobalValue array, Instr instr) { 67 | if (instr instanceof Instr.GetElementPtr) { 68 | for (Use use = instr.getBeginUse(); use.getNext() != null; use = (Use) use.getNext()) { 69 | Instr user = use.getUser(); 70 | DFS(array, user); 71 | } 72 | } else if (instr instanceof Instr.Load) { 73 | ((Instr.Load) instr).setAlloc(array); 74 | if (!loads.containsKey(array)) { 75 | loads.put(array, new HashSet<>()); 76 | } 77 | loads.get(array).add(instr); 78 | } else if (instr instanceof Instr.Store) { 79 | ((Instr.Store) instr).setAlloc(array); 80 | } else { 81 | //assert false; 82 | } 83 | } 84 | 85 | private void GVN() { 86 | GvnMap.clear(); 87 | GvnCnt.clear(); 88 | for (Function function: functions) { 89 | globalArrayGVN(function); 90 | } 91 | } 92 | 93 | private void globalArrayGVN(Function function) { 94 | BasicBlock bb = function.getBeginBB(); 95 | RPOSearch(bb); 96 | } 97 | 98 | private void RPOSearch(BasicBlock bb) { 99 | HashMap tempGvnCnt = new HashMap<>(); 100 | HashMap tempGvnMap = new HashMap<>(); 101 | for (String key: GvnCnt.keySet()) { 102 | tempGvnCnt.put(key, GvnCnt.get(key)); 103 | } 104 | for (String key: GvnMap.keySet()) { 105 | tempGvnMap.put(key, GvnMap.get(key)); 106 | } 107 | 108 | 109 | Instr instr = bb.getBeginInstr(); 110 | while (instr.getNext() != null) { 111 | if (instr instanceof Instr.Load && ((Instr.Load) instr).getAlloc() != null) { 112 | addLoadToGVN(instr); 113 | } else if (instr instanceof Instr.Store && ((Instr.Store) instr).getAlloc() != null) { 114 | Value array = ((Instr.Store) instr).getAlloc(); 115 | assert array instanceof GlobalVal.GlobalValue; 116 | if (loads.containsKey(array)) { 117 | for (Instr load : loads.get(array)) { 118 | assert load instanceof Instr.Load; 119 | removeLoadFromGVN(load); 120 | } 121 | } else { 122 | //这是正常的,因为单一函数中可能没有load全局数组,只是store了它 123 | //System.err.println("no_use"); 124 | } 125 | 126 | } else if (instr instanceof Instr.Call) { 127 | //TODO:待强化,根据函数传入的指针,判断修改了哪个Alloc/参数 128 | GvnMap.clear(); 129 | GvnCnt.clear(); 130 | } 131 | instr = (Instr) instr.getNext(); 132 | } 133 | 134 | for (BasicBlock next : bb.getIdoms()) { 135 | RPOSearch(next); 136 | } 137 | 138 | GvnMap.clear(); 139 | GvnCnt.clear(); 140 | GvnMap.putAll(tempGvnMap); 141 | GvnCnt.putAll(tempGvnCnt); 142 | } 143 | 144 | private void add(String str, Instr instr) { 145 | if (!GvnCnt.containsKey(str)) { 146 | GvnCnt.put(str, 1); 147 | } else { 148 | GvnCnt.put(str, GvnCnt.get(str) + 1); 149 | } 150 | if (!GvnMap.containsKey(str)) { 151 | GvnMap.put(str, instr); 152 | } 153 | } 154 | 155 | private void remove(String str) { 156 | if (!GvnCnt.containsKey(str) || GvnCnt.get(str) == 0) { 157 | return; 158 | } 159 | GvnCnt.put(str, GvnCnt.get(str) - 1); 160 | if (GvnCnt.get(str) == 0) { 161 | GvnMap.remove(str); 162 | } 163 | } 164 | 165 | private boolean addLoadToGVN(Instr load) { 166 | //进行替换 167 | assert load instanceof Instr.Load; 168 | String hash = ((Instr.Load) load).getPointer().getName(); 169 | if (GvnMap.containsKey(hash)) { 170 | load.modifyAllUseThisToUseA(GvnMap.get(hash)); 171 | //load.remove(); 172 | return true; 173 | } 174 | add(hash, load); 175 | return false; 176 | } 177 | 178 | private void removeLoadFromGVN(Instr load) { 179 | assert load instanceof Instr.Load; 180 | String hash = ((Instr.Load) load).getPointer().getName(); 181 | remove(hash); 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/midend/GlobalValueLocalize.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import frontend.semantic.Initial; 4 | import mir.*; 5 | import mir.type.Type; 6 | 7 | import java.util.*; 8 | 9 | public class GlobalValueLocalize { 10 | private HashMap globalValues; 11 | private ArrayList functions; 12 | 13 | private HashSet removedGlobal; 14 | 15 | public GlobalValueLocalize(ArrayList functions, HashMap globalValues) { 16 | this.functions = functions; 17 | this.globalValues = globalValues; 18 | this.removedGlobal = new HashSet<>(); 19 | } 20 | 21 | public void Run() { 22 | for (Value value: globalValues.keySet()) { 23 | if (!globalValues.get(value).getType().isInt32Type() && !globalValues.get(value).getType().isFloatType()) { 24 | continue; 25 | } 26 | localizeSingleValue(value); 27 | } 28 | for (Value value: removedGlobal) { 29 | globalValues.remove(value); 30 | value.remove(); 31 | } 32 | } 33 | 34 | private void localizeSingleValue(Value value) { 35 | boolean hasStore = false; 36 | HashSet useFunctions = new HashSet<>(); 37 | Use use = value.getBeginUse(); 38 | HashSet useInstrs = new HashSet<>(); 39 | while (use.getNext() != null) { 40 | if (use.getUser() instanceof Instr.Store) { 41 | hasStore = true; 42 | } 43 | useInstrs.add(use.getUser()); 44 | useFunctions.add(use.getUser().parentBB().getFunction()); 45 | use = (Use) use.getNext(); 46 | } 47 | 48 | 49 | // 没有被store的全局变量, 50 | if (!hasStore) { 51 | for (Instr instr : useInstrs) { 52 | Constant constant = null; 53 | Initial.ValueInit initValue = (Initial.ValueInit) globalValues.get(value); 54 | assert initValue.getValue() instanceof Constant; 55 | if (initValue.getType().isFloatType()) { 56 | constant = new Constant.ConstantFloat((float) ((Constant) initValue.getValue()).getConstVal()); 57 | } else if (globalValues.get(value).getType().isInt32Type()) { 58 | constant = new Constant.ConstantInt((int) ((Constant) initValue.getValue()).getConstVal()); 59 | } else { 60 | System.err.println("error"); 61 | } 62 | instr.modifyAllUseThisToUseA(constant); 63 | instr.remove(); 64 | } 65 | removedGlobal.add(value); 66 | return; 67 | } 68 | 69 | //只在main中调用的 70 | if (useFunctions.size() == 1) { 71 | Function function = null; 72 | for (Function tmp: useFunctions) { 73 | function = tmp; 74 | } 75 | if (!function.getName().equals("main")) { 76 | return; 77 | } 78 | BasicBlock entry = function.getBeginBB(); 79 | 80 | Initial.ValueInit initValue = (Initial.ValueInit) globalValues.get(value); 81 | assert initValue.getValue() instanceof Constant; 82 | 83 | if (initValue.getType().isFloatType()) { 84 | Instr.Alloc alloc = new Instr.Alloc(Type.BasicType.getF32Type(), entry, true); 85 | Instr.Store store = new Instr.Store(initValue.getValue(), alloc, entry); 86 | value.modifyAllUseThisToUseA(alloc); 87 | entry.insertAtHead(store); 88 | entry.insertAtHead(alloc); 89 | } else if (globalValues.get(value).getType().isInt32Type()) { 90 | Instr.Alloc alloc = new Instr.Alloc(Type.BasicType.getI32Type(), entry, true); 91 | Instr.Store store = new Instr.Store(initValue.getValue(), alloc, entry); 92 | value.modifyAllUseThisToUseA(alloc); 93 | entry.insertAtHead(store); 94 | entry.insertAtHead(alloc); 95 | } else { 96 | System.err.println("error"); 97 | } 98 | removedGlobal.add(value); 99 | } 100 | 101 | // 只在一个函数中被load,store 102 | // 只要有store,就不能直接替换为初始值, 103 | // 即使一个函数内没有store,但是因为另外的函数存在store,不明函数的调用逻辑,仍不能在没有store 的函数内替换为初始值 104 | // 即使只在一个函数内被load,store,仍然不能局部化,因为局部化后,每次调用函数对变量的修改是无法保留的 105 | // 如: 106 | // int a = 0; 107 | // int func() { 108 | // a = a + 1; 109 | // } 110 | //TODO:获取函数被调用的次数,次数为1则可局部化:只在非递归函数的循环深度为一的位置被调用一次? 111 | //fixme:上述条件是否正确 112 | //TODO:main不可能被递归调用,纳入考虑 113 | // if (useFunctions.size() == 1) { 114 | // Function function = null; 115 | // for (Function tmp: useFunctions) { 116 | // function = tmp; 117 | // } 118 | // BasicBlock entry = function.getBeginBB(); 119 | // 120 | // Initial.ValueInit initValue = (Initial.ValueInit) globalValues.get(value); 121 | // assert initValue.getValue() instanceof Constant; 122 | // 123 | // if (initValue.getType().isFloatType()) { 124 | // Instr.Alloc alloc = new Instr.Alloc(Type.BasicType.getF32Type(), entry, true); 125 | // Instr.Store store = new Instr.Store(initValue.getValue(), alloc, entry); 126 | // value.modifyAllUseThisToUseA(alloc); 127 | // entry.insertAtHead(store); 128 | // entry.insertAtHead(alloc); 129 | // } else if (globalValues.get(value).getType().isInt32Type()) { 130 | // Instr.Alloc alloc = new Instr.Alloc(Type.BasicType.getI32Type(), entry, true); 131 | // Instr.Store store = new Instr.Store(initValue.getValue(), alloc, entry); 132 | // value.modifyAllUseThisToUseA(alloc); 133 | // entry.insertAtHead(store); 134 | // entry.insertAtHead(alloc); 135 | // } else { 136 | // System.err.println("error"); 137 | // } 138 | // removedGlobal.add(value); 139 | // } 140 | } 141 | 142 | 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/midend/LCSSA.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.Stack; 9 | 10 | public class LCSSA { 11 | 12 | private ArrayList functions; 13 | 14 | public LCSSA(ArrayList functions) { 15 | this.functions = functions; 16 | } 17 | 18 | public void Run() { 19 | addPhi(); 20 | } 21 | 22 | private void addPhi() { 23 | for (Function function: functions) { 24 | addPhiForFunc(function); 25 | } 26 | } 27 | 28 | private void addPhiForFunc(Function function) { 29 | for (BasicBlock bb: function.getLoopHeads()) { 30 | addPhiForLoop(bb.getLoop()); 31 | } 32 | } 33 | 34 | private void addPhiForLoop(Loop loop) { 35 | HashSet exits = loop.getExits(); 36 | for (BasicBlock bb: loop.getNowLevelBB()) { 37 | // if (bb.getLabel().equals("b472")) { 38 | // System.err.println("b472"); 39 | // } 40 | Instr instr = bb.getBeginInstr(); 41 | while (instr.getNext() != null) { 42 | if (usedOutLoop(instr, loop)) { 43 | for (BasicBlock exit: exits) { 44 | addPhiAtExitBB(instr, exit, loop); 45 | } 46 | } 47 | instr = (Instr) instr.getNext(); 48 | } 49 | } 50 | } 51 | 52 | private void addDef(HashSet defs, Instr instr) { 53 | if (defs.contains(instr)) { 54 | return; 55 | } 56 | defs.add(instr); 57 | if (instr instanceof Instr.Phi) { 58 | for (Value value: instr.getUseValueList()) { 59 | if (value instanceof Instr) { 60 | defs.add((Instr) value); 61 | } 62 | } 63 | } 64 | } 65 | 66 | private void addPhiAtExitBB(Value value, BasicBlock bb, Loop loop) { 67 | ArrayList optionalValues = new ArrayList<>(); 68 | for (int i = 0; i < bb.getPrecBBs().size(); i++) { 69 | optionalValues.add(value); 70 | } 71 | Instr.Phi phi = new Instr.Phi(value.getType(), optionalValues, bb); 72 | //Instr.Phi phi = new Instr.Phi(value.getType(), optionalValues, bb, true); 73 | //TODO:ReName 74 | // HashSet domBB = getDomBB(bb); 75 | // Use use = value.getBeginUse(); 76 | // while (use.getNext() != null) { 77 | // Instr user = use.getUser(); 78 | // if (!user.parentBB().getLoop().equals(loop) && !(user instanceof Instr.Phi) && domBB.contains(user.parentBB())) { 79 | // user.modifyUse(value, phi, use.getIdx()); 80 | // } 81 | // use = (Use) use.getNext(); 82 | // } 83 | HashMap useInstrMap = new HashMap<>(); 84 | HashSet defInstrs = new HashSet<>(); 85 | Stack S = new Stack<>(); 86 | //defInstrs.add(phi); 87 | //defInstrs.add((Instr) value); 88 | addDef(defInstrs, phi); 89 | addDef(defInstrs, (Instr) value); 90 | Use use = value.getBeginUse(); 91 | while (use.getNext() != null) { 92 | Instr user = use.getUser(); 93 | BasicBlock userBB = user.parentBB(); 94 | //fixme:time 07-18-00:15 考虑正确性 95 | //PHI对其的使用其实是在PHI的前驱对它的使用 96 | //与GCM的scheduleLate采用同一思想 97 | //对于正常的PHI不能重新计算到达定义,因为有些定义已经没有了 98 | //初始化S? 99 | // if (user instanceof Instr.Phi) { 100 | // if (!user.equals(phi)) { 101 | // use = (Use) use.getNext(); 102 | // continue; 103 | // } 104 | // } 105 | // 106 | // useInstrMap.put(use.getUser(), use.getIdx()); 107 | 108 | if (user instanceof Instr.Phi) { 109 | if (userBB.getLoop().equals(loop)) { 110 | use = (Use) use.getNext(); 111 | continue; 112 | } 113 | } 114 | 115 | if (user instanceof Instr.Phi) { 116 | int index = use.getIdx(); 117 | userBB = userBB.getPrecBBs().get(index); 118 | } 119 | if (!userBB.getLoop().equals(loop)) { 120 | useInstrMap.put(use.getUser(), use.getIdx()); 121 | } 122 | 123 | //useInstrMap.put(use.getUser(), use.getIdx()); 124 | use = (Use) use.getNext(); 125 | } 126 | // for (int i = 0; i < bb.getPrecBBs().size(); i++) { 127 | // useInstrMap.put(phi, i); 128 | // } 129 | useInstrMap.put(phi, -1); 130 | RenameDFS(S, bb.getFunction().getBeginBB(), useInstrMap, defInstrs); 131 | //RenameDFS(S, bb.getLoop().getHeader(), useInstrMap, defInstrs); 132 | } 133 | 134 | public void RenameDFS(Stack S, BasicBlock X, HashMap useInstrMap, HashSet defInstrs) { 135 | int cnt = 0; 136 | Instr A = X.getBeginInstr(); 137 | while (A.getNext() != null) { 138 | if (!(A instanceof Instr.Phi) && useInstrMap.containsKey(A)) { 139 | A.modifyUse(getStackTopValue(S), useInstrMap.get(A)); 140 | } 141 | if (defInstrs.contains(A)) { 142 | S.push(A); 143 | cnt++; 144 | } 145 | A = (Instr) A.getNext(); 146 | } 147 | 148 | ArrayList Succ = X.getSuccBBs(); 149 | for (int i = 0; i < Succ.size(); i++) { 150 | BasicBlock bb = Succ.get(i); 151 | Instr instr = Succ.get(i).getBeginInstr(); 152 | while (instr.getNext() != null) { 153 | if (!(instr instanceof Instr.Phi)) { 154 | break; 155 | } 156 | if (useInstrMap.containsKey(instr)) { 157 | if (useInstrMap.get(instr) == -1) { 158 | instr.modifyUse(getStackTopValue(S), bb.getPrecBBs().indexOf(X)); 159 | } else if (bb.getPrecBBs().indexOf(X) == useInstrMap.get(instr)) { 160 | instr.modifyUse(getStackTopValue(S), useInstrMap.get(instr)); 161 | } 162 | //instr.modifyUse(getStackTopValue(S), bb.getPrecBBs().indexOf(X)); 163 | } 164 | instr = (Instr) instr.getNext(); 165 | } 166 | } 167 | 168 | for (BasicBlock next: X.getIdoms()) { 169 | RenameDFS(S, next, useInstrMap, defInstrs); 170 | } 171 | 172 | for (int i = 0; i < cnt; i++) { 173 | S.pop(); 174 | } 175 | } 176 | 177 | public Value getStackTopValue(Stack S) { 178 | if (S.empty()) { 179 | return new GlobalVal.UndefValue(); 180 | } 181 | return S.peek(); 182 | } 183 | 184 | 185 | //判断value是否在loop外被使用 186 | private boolean usedOutLoop(Value value, Loop loop) { 187 | // if (value instanceof Instr.Load 188 | // || value instanceof Instr.GetElementPtr || value instanceof Instr.Store) { 189 | // return false; 190 | // } 191 | Use use = value.getBeginUse(); 192 | while (use.getNext() != null) { 193 | Instr user = use.getUser(); 194 | BasicBlock userBB = user.parentBB(); 195 | //PHI对其的使用其实是在PHI的前驱对它的使用 196 | //与GCM的scheduleLate采用同一思想 197 | if (user instanceof Instr.Phi) { 198 | int index = use.getIdx(); 199 | userBB = userBB.getPrecBBs().get(index); 200 | } 201 | if (!userBB.getLoop().equals(loop)) { 202 | return true; 203 | } 204 | use = (Use) use.getNext(); 205 | } 206 | return false; 207 | } 208 | 209 | 210 | } 211 | -------------------------------------------------------------------------------- /src/midend/LoopFold.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import lir.V; 4 | import mir.*; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashSet; 8 | 9 | public class LoopFold { 10 | 11 | //折叠重复计算的循环 12 | //对于calc循环,如果可以优化,替换 -- 除法->位移 13 | private ArrayList functions; 14 | private HashSet loops = new HashSet<>(); 15 | private HashSet removes = new HashSet<>(); 16 | 17 | public LoopFold(ArrayList functions) { 18 | this.functions = functions; 19 | } 20 | 21 | public void Run() { 22 | for (Function function: functions) { 23 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 24 | if (bb.isLoopHeader()) { 25 | // if (bb.getLabel().equals("b61")) { 26 | // System.err.println("b61"); 27 | // } 28 | loops.add(bb.getLoop()); 29 | calcLoopInit(bb.getLoop()); 30 | } 31 | } 32 | } 33 | for (Loop loop: loops) { 34 | if (!removes.contains(loop)) { 35 | tryFoldLoop(loop); 36 | } 37 | } 38 | for (Loop loop: removes) { 39 | BasicBlock entering = null; 40 | for (BasicBlock bb: loop.getEnterings()) { 41 | entering = bb; 42 | } 43 | BasicBlock exit = null; 44 | for (BasicBlock bb: loop.getExits()) { 45 | exit = bb; 46 | } 47 | loop.getParentLoop().getChildrenLoops().remove(loop); 48 | entering.modifyBrAToB(loop.getHeader(), exit); 49 | exit.modifyPre(loop.getHeader(), entering); 50 | } 51 | } 52 | 53 | private void calcLoopInit(Loop loop) { 54 | loop.clearCalcLoopInfo(); 55 | if (!loop.isSimpleLoop() || !loop.isIdcSet()) { 56 | return; 57 | } 58 | if (loop.hasChildLoop()) { 59 | return; 60 | } 61 | //只有head和latch的简单循环 62 | for (BasicBlock bb: loop.getNowLevelBB()) { 63 | if (!bb.isLoopHeader() && !bb.isLoopLatch()) { 64 | return; 65 | } 66 | } 67 | if (!loop.getHeader().isLoopExiting()) { 68 | return; 69 | } 70 | BasicBlock latch = null; 71 | for (BasicBlock bb: loop.getLatchs()) { 72 | latch = bb; 73 | } 74 | BasicBlock head = loop.getHeader(); 75 | HashSet idcInstrs = new HashSet<>(); 76 | Instr.Alu alu = null; 77 | Instr.Phi phi = null; 78 | int alu_cnt = 0, phi_cnt = 0; 79 | idcInstrs.add((Instr) loop.getIdcPHI()); 80 | idcInstrs.add((Instr) loop.getIdcCmp()); 81 | idcInstrs.add((Instr) loop.getIdcAlu()); 82 | idcInstrs.add(head.getEndInstr()); 83 | idcInstrs.add(latch.getEndInstr()); 84 | for (Instr idcInstr: idcInstrs) { 85 | if (useOutLoop(idcInstr, loop)) { 86 | return; 87 | } 88 | } 89 | for (BasicBlock bb: loop.getNowLevelBB()) { 90 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 91 | if (!idcInstrs.contains(instr)) { 92 | if (instr instanceof Instr.Alu) { 93 | alu = (Instr.Alu) instr; 94 | alu_cnt++; 95 | } else if (instr instanceof Instr.Phi) { 96 | phi = (Instr.Phi) instr; 97 | phi_cnt++; 98 | } else { 99 | return; 100 | } 101 | } 102 | } 103 | } 104 | if (alu_cnt != 1 || phi_cnt != 1) { 105 | return; 106 | } 107 | if (useOutLoop(alu, loop) || !useOutLoop(phi, loop)) { 108 | return; 109 | } 110 | int latchIndex = head.getPrecBBs().indexOf(latch); 111 | int enteringIndex = 1 - latchIndex; 112 | if (!phi.getUseValueList().get(latchIndex).equals(alu)) { 113 | return; 114 | } 115 | if (!alu.getUseValueList().contains(phi)) { 116 | return; 117 | } 118 | int aluOtherIndex = 1 - alu.getUseValueList().indexOf(phi); 119 | //TODO:待强化,使用的只要是同一个值就可以? 120 | // 且当前没有考虑float!!! 121 | if (!(alu.getUseValueList().get(aluOtherIndex) instanceof Constant.ConstantInt)) { 122 | return; 123 | } 124 | Value aluPhiEnterValue = phi.getUseValueList().get(enteringIndex); 125 | loop.setCalcLoopInfo(aluPhiEnterValue, alu, phi, aluOtherIndex); 126 | } 127 | 128 | private void tryFoldLoop(Loop loop) { 129 | if (!loop.isCalcLoop()) { 130 | return; 131 | } 132 | if (loop.getExits().size() != 1) { 133 | return; 134 | } 135 | BasicBlock exit = null; 136 | for (BasicBlock bb: loop.getExits()) { 137 | exit = bb; 138 | } 139 | if (exit.getSuccBBs().size() != 1) { 140 | return; 141 | } 142 | BasicBlock exitNext = exit.getSuccBBs().get(0); 143 | if (!exitNext.isLoopHeader()) { 144 | return; 145 | } 146 | Loop nextLoop = exitNext.getLoop(); 147 | if (!nextLoop.isCalcLoop()) { 148 | return; 149 | } 150 | if (nextLoop.getEnterings().size() != 1) { 151 | return; 152 | } 153 | if (!loop.getIdcInit().equals(nextLoop.getIdcInit()) || 154 | !loop.getIdcStep().equals(nextLoop.getIdcStep()) || 155 | !loop.getIdcEnd().equals(nextLoop.getIdcEnd())) { 156 | return; 157 | } 158 | if (loop.getIdcCmp() instanceof Instr.Icmp) { 159 | if (!((Instr.Icmp) loop.getIdcCmp()).getOp().equals(((Instr.Icmp) loop.getIdcCmp()).getOp())) { 160 | return; 161 | } 162 | } else if (loop.getIdcCmp() instanceof Instr.Fcmp) { 163 | if (!((Instr.Fcmp) loop.getIdcCmp()).getOp().equals(((Instr.Fcmp) loop.getIdcCmp()).getOp())) { 164 | return; 165 | } 166 | } else { 167 | assert false; 168 | } 169 | Instr.Alu preLoopAlu = (Instr.Alu) loop.getCalcAlu(); 170 | Instr.Phi preLoopPhi = (Instr.Phi) loop.getCalcPhi(); 171 | Value preLoopEnterValue = loop.getAluPhiEnterValue(); 172 | int index1 = loop.getAluOtherIndex(); 173 | 174 | Instr.Alu sucLoopAlu = (Instr.Alu) nextLoop.getCalcAlu(); 175 | Instr.Phi sucLoopPhi = (Instr.Phi) nextLoop.getCalcPhi(); 176 | Value sucLoopEnterValue = nextLoop.getAluPhiEnterValue(); 177 | int index2 = loop.getAluOtherIndex(); 178 | 179 | if (!preLoopEnterValue.equals(sucLoopEnterValue)) { 180 | return; 181 | } 182 | 183 | int val1 = (int) ((Constant.ConstantInt) preLoopAlu.getUseValueList().get(index1)).getConstVal(); 184 | int val2 = (int) ((Constant.ConstantInt) sucLoopAlu.getUseValueList().get(index2)).getConstVal(); 185 | 186 | if (!preLoopAlu.getOp().equals(sucLoopAlu.getOp()) || val1 != val2 || index1 != index2) { 187 | return; 188 | } 189 | 190 | sucLoopPhi.modifyAllUseThisToUseA(preLoopPhi); 191 | removes.add(nextLoop); 192 | 193 | } 194 | 195 | private boolean useOutLoop(Instr instr, Loop loop) { 196 | for (Use use = instr.getBeginUse(); use.getNext() != null; use = (Use) use.getNext()) { 197 | Instr user = use.getUser(); 198 | if (!user.parentBB().getLoop().equals(loop)) { 199 | return true; 200 | } 201 | } 202 | return false; 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /src/midend/LoopIdcVarInfo.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | 8 | public class LoopIdcVarInfo { 9 | 10 | private ArrayList functions; 11 | 12 | public LoopIdcVarInfo(ArrayList functions) { 13 | this.functions = functions; 14 | } 15 | 16 | public void Run() { 17 | GetInductionVar(); 18 | } 19 | 20 | private void GetInductionVar() { 21 | for (Function function: functions) { 22 | GetInductionVarForFunc(function); 23 | } 24 | } 25 | 26 | private void GetInductionVarForFunc(Function function) { 27 | HashSet loops = new HashSet<>(); 28 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 29 | loops.add(bb.getLoop()); 30 | } 31 | for (Loop loop: loops) { 32 | GetInductionVarForLoop(loop); 33 | } 34 | } 35 | 36 | private void GetInductionVarForLoop(Loop loop) { 37 | if (!loop.isSimpleLoop()) { 38 | return; 39 | } 40 | //fixme:认为函数的Head和exiting是一个块的时候再进行展开 41 | if (!loop.getExitings().contains(loop.getHeader())) { 42 | return; 43 | } 44 | 45 | Instr headBr = loop.getHeader().getEndInstr(); // br i1 %v6, label %b3, label %b4 46 | if (!(headBr instanceof Instr.Branch)) { 47 | return; 48 | } 49 | assert headBr instanceof Instr.Branch; 50 | Value headBrCond = ((Instr.Branch) headBr).getCond(); // %v6 = icmp slt i32 %v19, 10 51 | Value idcPHI, idcEnd; 52 | if (headBrCond instanceof Instr.Icmp) { 53 | if (((Instr.Icmp) headBrCond).getRVal1() instanceof Instr.Phi) { 54 | idcPHI = ((Instr.Icmp) headBrCond).getRVal1(); 55 | idcEnd = ((Instr.Icmp) headBrCond).getRVal2(); 56 | } else if ((((Instr.Icmp) headBrCond).getRVal2() instanceof Instr.Phi)) { 57 | idcPHI = ((Instr.Icmp) headBrCond).getRVal2(); 58 | idcEnd = ((Instr.Icmp) headBrCond).getRVal1(); 59 | } else { 60 | return; 61 | } 62 | } else if (headBrCond instanceof Instr.Fcmp) { 63 | if (((Instr.Fcmp) headBrCond).getRVal1() instanceof Instr.Phi) { 64 | idcPHI = ((Instr.Fcmp) headBrCond).getRVal1(); 65 | idcEnd = ((Instr.Fcmp) headBrCond).getRVal2(); 66 | } else if ((((Instr.Fcmp) headBrCond).getRVal2() instanceof Instr.Phi)) { 67 | idcPHI = ((Instr.Fcmp) headBrCond).getRVal2(); 68 | idcEnd = ((Instr.Fcmp) headBrCond).getRVal1(); 69 | } else { 70 | return; 71 | } 72 | } else { 73 | return; 74 | } 75 | 76 | if (!((Instr) idcPHI).parentBB().equals(loop.getHeader())) { 77 | return; 78 | } 79 | 80 | 81 | assert idcPHI instanceof Instr.Phi; 82 | Value phiRVal1 = ((Instr.Phi) idcPHI).getUseValueList().get(0); 83 | Value phiRVal2 = ((Instr.Phi) idcPHI).getUseValueList().get(1); 84 | BasicBlock head = loop.getHeader(); 85 | Value idcAlu, idcInit; 86 | if (loop.getLatchs().contains(head.getPrecBBs().get(0))) { 87 | idcAlu = phiRVal1; 88 | idcInit = phiRVal2; 89 | } else { 90 | idcAlu = phiRVal2; 91 | idcInit = phiRVal1; 92 | } 93 | if (!(idcAlu instanceof Instr.Alu)) { 94 | return; 95 | } 96 | Value idcStep; 97 | if (((Instr.Alu) idcAlu).getRVal1().equals(idcPHI)) { 98 | idcStep = ((Instr.Alu) idcAlu).getRVal2(); 99 | } else if (((Instr.Alu) idcAlu).getRVal2().equals(idcPHI)) { 100 | idcStep = ((Instr.Alu) idcAlu).getRVal1(); 101 | } else { 102 | return; 103 | } 104 | 105 | if (!(((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.ADD) || 106 | ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.SUB) || 107 | ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.FADD) || 108 | ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.FSUB) || 109 | ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.MUL) || 110 | ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.FMUL))) { 111 | return; 112 | } 113 | assert idcAlu.getType().equals(idcPHI.getType()); 114 | assert idcPHI.getType().equals(idcInit.getType()); 115 | assert idcInit.getType().equals(idcEnd.getType()); 116 | assert idcEnd.getType().equals(idcStep.getType()); 117 | //i = 10 - i; i = 10 / i; 118 | //fixme:上述归纳方式,暂时不考虑 119 | if (((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.SUB) || ((Instr.Alu) idcAlu).getOp().equals(Instr.Alu.Op.DIV)) { 120 | if (((Instr.Alu) idcAlu).getRVal2() instanceof Instr.Phi) { 121 | return; 122 | } 123 | } 124 | loop.setIdc(idcAlu, idcPHI, headBrCond, idcInit, idcEnd, idcStep); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/midend/LoopInfo.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | import mir.Function; 5 | import mir.Instr; 6 | import mir.Loop; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashSet; 10 | 11 | public class LoopInfo { 12 | 13 | //TODO: 14 | 15 | private ArrayList functions; 16 | private Function nowFunc; 17 | 18 | public LoopInfo(ArrayList functions) { 19 | this.functions = functions; 20 | } 21 | 22 | public void Run() { 23 | clearLoopInfo(); 24 | makeInfo(); 25 | } 26 | 27 | private void clearLoopInfo() { 28 | for (Function function: functions) { 29 | for (BasicBlock head: function.getLoopHeads()) { 30 | Loop loop = head.getLoop(); 31 | loop.clearCond(); 32 | loop.clear(); 33 | loop.clearIdcInfo(); 34 | } 35 | } 36 | } 37 | 38 | private void makeInfo() { 39 | for (Function function: functions) { 40 | makeInfoForFunc(function); 41 | } 42 | } 43 | 44 | //标记loop的 entering header exiting latch exit 45 | private void makeInfoForFunc(Function function) { 46 | nowFunc = function; 47 | HashSet know = new HashSet<>(); 48 | BasicBlock entry = function.getBeginBB(); 49 | DFS(entry, know); 50 | } 51 | 52 | private void DFS(BasicBlock bb, HashSet know) { 53 | if (bb.isLoopHeader()) { 54 | nowFunc.addLoopHead(bb); 55 | } 56 | 57 | if (know.contains(bb)) { 58 | return; 59 | } 60 | 61 | know.add(bb); 62 | //bb.getLoop().addBB(bb); 63 | 64 | //clear 65 | if (bb.getLoopDep() > 0) { 66 | Instr instr = bb.getBeginInstr(); 67 | Loop loop = bb.getLoop(); 68 | while (instr.getNext() != null) { 69 | if (instr.isInLoopCond()) { 70 | loop.addCond(instr); 71 | } 72 | instr = (Instr) instr.getNext(); 73 | } 74 | } 75 | 76 | //entering 77 | if (bb.isLoopHeader()) { 78 | for (BasicBlock pre: bb.getPrecBBs()) { 79 | Loop loop = bb.getLoop(); 80 | if (!loop.getNowLevelBB().contains(pre)) { 81 | loop.addEntering(pre); 82 | } 83 | } 84 | } 85 | 86 | for (BasicBlock next:bb.getSuccBBs()) { 87 | //后向边 latch 88 | if (know.contains(next) && next.isLoopHeader()) { 89 | //assert next.isLoopHeader(); 90 | Loop loop = bb.getLoop(); 91 | loop.addLatch(bb); 92 | } 93 | //出循环的边 exiting和exit 94 | //next.getLoopDep() == bb.getLoopDep() - 1 95 | if (next.getLoopDep() < bb.getLoopDep()) { 96 | Loop loop = bb.getLoop(); 97 | loop.addExiting(bb); 98 | loop.addExit(next); 99 | } 100 | DFS(next, know); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/midend/LoopNest.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class LoopNest { 8 | 9 | private BasicBlock entryBB; 10 | private ArrayList BBs; 11 | private BasicBlock next; 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/midend/MergeBB.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | import mir.Function; 5 | import mir.Instr; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashSet; 9 | 10 | public class MergeBB { 11 | 12 | private ArrayList functions; 13 | 14 | public MergeBB(ArrayList functions) { 15 | this.functions = functions; 16 | } 17 | 18 | public void Run() { 19 | HashSet removes = new HashSet<>(); 20 | for (Function function: functions) { 21 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 22 | if (bb.getBeginInstr().equals(bb.getEndInstr()) && bb.getBeginInstr() instanceof Instr.Jump && !bb.getFunction().getBeginBB().equals(bb)) { 23 | removes.add(bb); 24 | } 25 | } 26 | } 27 | for (BasicBlock bb: removes) { 28 | Instr.Jump jump = (Instr.Jump) bb.getBeginInstr(); 29 | BasicBlock target = jump.getTarget(); 30 | for (BasicBlock pre: bb.getPrecBBs()) { 31 | pre.modifyBrAToB(bb, target); 32 | target.getPrecBBs().add(pre); 33 | } 34 | target.getPrecBBs().remove(bb); 35 | bb.remove(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/midend/MergeSimpleBB.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | import mir.Function; 5 | import mir.Instr; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.HashSet; 10 | 11 | public class MergeSimpleBB { 12 | 13 | private ArrayList functions; 14 | HashMap> preMap = new HashMap<>(); 15 | HashMap> sucMap = new HashMap<>(); 16 | 17 | public MergeSimpleBB(ArrayList functions) { 18 | this.functions = functions; 19 | } 20 | 21 | public void Run() { 22 | for (Function function: functions) { 23 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 24 | if (bb.getBeginInstr().equals(bb.getEndInstr()) && bb.getBeginInstr() instanceof Instr.Jump) { 25 | BasicBlock suc = bb.getSuccBBs().get(0); 26 | suc.getPrecBBs().remove(bb); 27 | for (BasicBlock pre: bb.getPrecBBs()) { 28 | pre.modifyBrAToB(bb, suc); 29 | pre.modifySuc(bb, suc); 30 | suc.addPre(pre); 31 | } 32 | bb.getBeginInstr().remove(); 33 | bb.remove(); 34 | } 35 | } 36 | } 37 | RemoveDeadBB(); 38 | MakeCFG(); 39 | } 40 | 41 | private void RemoveDeadBB() { 42 | //TODO:优化删除基本块的算法 43 | for (Function function: functions) { 44 | removeFuncDeadBB(function); 45 | } 46 | } 47 | 48 | private void MakeCFG() { 49 | for (Function function: functions) { 50 | makeSingleFuncCFG(function); 51 | } 52 | } 53 | 54 | private void removeFuncDeadBB(Function function) { 55 | BasicBlock beginBB = function.getBeginBB(); 56 | BasicBlock end = function.getEnd(); 57 | 58 | preMap = new HashMap<>(); 59 | sucMap = new HashMap<>(); 60 | HashSet BBs = new HashSet<>(); 61 | 62 | //初始化前驱后继图 63 | BasicBlock pos = beginBB; 64 | while (!pos.equals(end)) { 65 | preMap.put(pos, new ArrayList<>()); 66 | sucMap.put(pos, new ArrayList<>()); 67 | BBs.add(pos); 68 | pos = (BasicBlock) pos.getNext(); 69 | 70 | //remove useless br 71 | Instr instr = pos.getEndInstr(); 72 | while (instr.getPrev() instanceof Instr.Branch || instr.getPrev() instanceof Instr.Jump) { 73 | Instr temp = instr; 74 | temp.remove(); 75 | instr = (Instr) instr.getPrev(); 76 | } 77 | } 78 | 79 | //添加前驱和后继 80 | pos = beginBB; 81 | while (!pos.equals(end)) { 82 | Instr lastInstr = pos.getEndInstr(); 83 | if (lastInstr instanceof Instr.Branch) { 84 | BasicBlock elseTarget = ((Instr.Branch) lastInstr).getElseTarget(); 85 | BasicBlock thenTarget = ((Instr.Branch) lastInstr).getThenTarget(); 86 | sucMap.get(pos).add(thenTarget); 87 | sucMap.get(pos).add(elseTarget); 88 | preMap.get(thenTarget).add(pos); 89 | preMap.get(elseTarget).add(pos); 90 | } else if (lastInstr instanceof Instr.Jump) { 91 | BasicBlock target = ((Instr.Jump) lastInstr).getTarget(); 92 | sucMap.get(pos).add(target); 93 | preMap.get(target).add(pos); 94 | } 95 | pos = (BasicBlock) pos.getNext(); 96 | } 97 | 98 | //回写基本块和函数 99 | HashSet needRemove = new HashSet<>(); 100 | HashSet know = new HashSet<>(); 101 | DFS(function.getBeginBB(), know); 102 | 103 | pos = beginBB; 104 | while (!pos.equals(end)) { 105 | if (!know.contains(pos)) { 106 | needRemove.add(pos); 107 | } 108 | pos = (BasicBlock) pos.getNext(); 109 | } 110 | 111 | 112 | for (BasicBlock bb: needRemove) { 113 | //System.err.println("remove:" + bb.getLabel()); 114 | bb.remove(); 115 | Instr instr = bb.getBeginInstr(); 116 | while (instr.getNext() != null) { 117 | instr.remove(); 118 | instr = (Instr) instr.getNext(); 119 | } 120 | } 121 | } 122 | 123 | private void DFS(BasicBlock bb, HashSet know) { 124 | if (know.contains(bb)) { 125 | return; 126 | } 127 | know.add(bb); 128 | for (BasicBlock next: sucMap.get(bb)) { 129 | DFS(next, know); 130 | } 131 | } 132 | 133 | //计算单个函数的控制流图 134 | private void makeSingleFuncCFG(Function function) { 135 | BasicBlock beginBB = function.getBeginBB(); 136 | BasicBlock end = function.getEnd(); 137 | 138 | preMap = new HashMap<>(); 139 | sucMap = new HashMap<>(); 140 | HashSet BBs = new HashSet<>(); 141 | 142 | //初始化前驱后继图 143 | BasicBlock pos = beginBB; 144 | while (!pos.equals(end)) { 145 | preMap.put(pos, new ArrayList<>()); 146 | sucMap.put(pos, new ArrayList<>()); 147 | BBs.add(pos); 148 | pos = (BasicBlock) pos.getNext(); 149 | } 150 | 151 | //添加前驱和后继 152 | pos = beginBB; 153 | while (!pos.equals(end)) { 154 | Instr lastInstr = pos.getEndInstr(); 155 | if (lastInstr instanceof Instr.Branch) { 156 | BasicBlock elseTarget = ((Instr.Branch) lastInstr).getElseTarget(); 157 | BasicBlock thenTarget = ((Instr.Branch) lastInstr).getThenTarget(); 158 | sucMap.get(pos).add(thenTarget); 159 | sucMap.get(pos).add(elseTarget); 160 | preMap.get(thenTarget).add(pos); 161 | preMap.get(elseTarget).add(pos); 162 | } else if (lastInstr instanceof Instr.Jump) { 163 | BasicBlock target = ((Instr.Jump) lastInstr).getTarget(); 164 | sucMap.get(pos).add(target); 165 | preMap.get(target).add(pos); 166 | } 167 | pos = (BasicBlock) pos.getNext(); 168 | } 169 | 170 | //回写基本块和函数 171 | pos = beginBB; 172 | while (!pos.equals(end)) { 173 | // if (pos.getLabel().equals("b242")) { 174 | // System.err.println("err"); 175 | // } 176 | pos.modifyPres(preMap.get(pos)); 177 | pos.modifySucs(sucMap.get(pos)); 178 | pos = (BasicBlock) pos.getNext(); 179 | } 180 | function.setPreMap(preMap); 181 | function.setSucMap(sucMap); 182 | function.setBBs(BBs); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/midend/OutParam.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | public class OutParam { 4 | 5 | public static final boolean ONLY_OUTPUT_PRE_SUC = false; 6 | public static final boolean BB_NEED_CFG_INFO = false; 7 | public static final boolean BB_NEED_LOOP_INFO = false; 8 | public static final boolean COND_CNT_DEBUG_FOR_LC = false; 9 | 10 | public static final boolean NEED_BB_USE_IN_BR_INFO = false; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/midend/Rem2DivMulSub.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | import mir.type.Type; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashSet; 8 | import java.util.IntSummaryStatistics; 9 | 10 | public class Rem2DivMulSub { 11 | 12 | private ArrayList functions; 13 | private HashSet rems = new HashSet<>(); 14 | private HashSet frems = new HashSet<>(); 15 | 16 | 17 | public Rem2DivMulSub(ArrayList functions) { 18 | this.functions = functions; 19 | } 20 | 21 | public void Run() { 22 | init(); 23 | transRemToDivMulSub(); 24 | } 25 | 26 | private void init() { 27 | for (Function function: functions) { 28 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 29 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 30 | if (instr instanceof Instr.Alu) { 31 | if (((Instr.Alu) instr).getOp().equals(Instr.Alu.Op.REM)) { 32 | rems.add((Instr.Alu) instr); 33 | } else if (((Instr.Alu) instr).getOp().equals(Instr.Alu.Op.FREM)) { 34 | frems.add((Instr.Alu) instr); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | private void transRemToDivMulSub() { 43 | for (Instr.Alu rem: rems) { 44 | Value A = rem.getRVal1(); 45 | Value B = rem.getRVal2(); 46 | if (B instanceof Constant.ConstantInt) { 47 | int val = (int) ((Constant.ConstantInt) B).getConstVal(); 48 | if (val > 0 && ((int) Math.pow(2, ((int) (Math.log(val) / Math.log(2))))) == val) { 49 | continue; 50 | } 51 | } 52 | Instr div = new Instr.Alu(Type.BasicType.getI32Type(), Instr.Alu.Op.DIV, A, B, rem.parentBB()); 53 | rem.insertBefore(div); 54 | Instr mul = new Instr.Alu(Type.BasicType.getI32Type(), Instr.Alu.Op.MUL, div, B, rem.parentBB()); 55 | rem.insertBefore(mul); 56 | Instr mod = new Instr.Alu(Type.BasicType.getI32Type(), Instr.Alu.Op.SUB, A, mul, rem.parentBB()); 57 | rem.insertBefore(mod); 58 | 59 | rem.modifyAllUseThisToUseA(mod); 60 | } 61 | 62 | for (Instr.Alu frem: frems) { 63 | Value A = frem.getRVal1(); 64 | Value B = frem.getRVal2(); 65 | Instr div = new Instr.Alu(Type.BasicType.getF32Type(), Instr.Alu.Op.FDIV, A, B, frem.parentBB()); 66 | frem.insertBefore(div); 67 | Instr mul = new Instr.Alu(Type.BasicType.getF32Type(), Instr.Alu.Op.FMUL, div, B, frem.parentBB()); 68 | frem.insertBefore(mul); 69 | Instr mod = new Instr.Alu(Type.BasicType.getF32Type(), Instr.Alu.Op.FSUB, A, mul, frem.parentBB()); 70 | frem.insertBefore(mod); 71 | 72 | frem.modifyAllUseThisToUseA(mod); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/midend/RemovePhi.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | 8 | public class RemovePhi { 9 | 10 | private ArrayList functions; 11 | 12 | public RemovePhi(ArrayList functions) { 13 | this.functions = functions; 14 | } 15 | 16 | public void Run() { 17 | RemovePhiAddPCopy(); 18 | ReplacePCopy(); 19 | } 20 | 21 | private void RemovePhiAddPCopy() { 22 | for (Function function: functions) { 23 | removeFuncPhi(function); 24 | } 25 | } 26 | 27 | private void ReplacePCopy() { 28 | for (Function function: functions) { 29 | replacePCopyForFunc(function); 30 | } 31 | } 32 | 33 | 34 | private void removeFuncPhi(Function function) { 35 | BasicBlock bb = function.getBeginBB(); 36 | while (bb.getNext() != null) { 37 | if (!(bb.getBeginInstr() instanceof Instr.Phi)) { 38 | bb = (BasicBlock) bb.getNext(); 39 | continue; 40 | } 41 | ArrayList pres = new ArrayList<>(); 42 | for (BasicBlock b:bb.getPrecBBs()) { 43 | pres.add(b); 44 | } 45 | ArrayList PCopys = new ArrayList<>(); 46 | //TODO:使用迭代器遍历会导致报错:遍历中修改元素 ? 47 | for (int i = 0; i < pres.size(); i++) { 48 | BasicBlock incomeBB = pres.get(i); 49 | 50 | if (incomeBB.getSuccBBs().size() > 1) { 51 | // TODO: 这里不知道优化的时候, incomeBB的loop是不是null 52 | BasicBlock mid = new BasicBlock(function, incomeBB.loop); 53 | Instr.PCopy pCopy = new Instr.PCopy(new ArrayList<>(), new ArrayList<>(), mid); 54 | PCopys.add(pCopy); 55 | addMidBB(incomeBB, mid, bb); 56 | } else { 57 | Instr endInstr = incomeBB.getEndInstr(); 58 | Instr.PCopy pCopy = new Instr.PCopy(new ArrayList<>(), new ArrayList<>(), incomeBB); 59 | endInstr.insertBefore(pCopy); 60 | PCopys.add(pCopy); 61 | } 62 | 63 | } 64 | 65 | Instr instr = bb.getBeginInstr(); 66 | while (instr instanceof Instr.Phi) { 67 | ArrayList phiRHS = instr.getUseValueList(); 68 | for (int i = 0; i < phiRHS.size(); i++) { 69 | PCopys.get(i).addToPC(instr, phiRHS.get(i)); 70 | } 71 | instr = (Instr) instr.getNext(); 72 | } 73 | 74 | instr = bb.getBeginInstr(); 75 | while (instr instanceof Instr.Phi) { 76 | Instr temp = instr; 77 | instr = (Instr) instr.getNext(); 78 | //temp.remove(); 79 | temp.delFromNowBB(); 80 | } 81 | 82 | bb = (BasicBlock) bb.getNext(); 83 | } 84 | } 85 | 86 | private void addMidBB(BasicBlock src, BasicBlock mid, BasicBlock tag) { 87 | src.getSuccBBs().remove(tag); 88 | src.getSuccBBs().add(mid); 89 | mid.getPrecBBs().add(src); 90 | mid.getSuccBBs().add(tag); 91 | tag.getPrecBBs().remove(src); 92 | tag.getPrecBBs().add(mid); 93 | 94 | Instr instr = src.getEndInstr(); 95 | assert instr instanceof Instr.Branch; 96 | BasicBlock thenBB = ((Instr.Branch) instr).getThenTarget(); 97 | BasicBlock elseBB = ((Instr.Branch) instr).getElseTarget(); 98 | 99 | if (tag.equals(thenBB)) { 100 | ((Instr.Branch) instr).setThenTarget(mid); 101 | Instr.Jump jump = new Instr.Jump(tag, mid); 102 | } else if (tag.equals(elseBB)) { 103 | ((Instr.Branch) instr).setElseTarget(mid); 104 | Instr.Jump jump = new Instr.Jump(tag, mid); 105 | } else { 106 | System.err.println("Panic At Remove PHI addMidBB"); 107 | } 108 | 109 | } 110 | 111 | private void replacePCopyForFunc(Function function) { 112 | BasicBlock bb = function.getBeginBB(); 113 | while (bb.getNext() != null) { 114 | Instr instr = bb.getBeginInstr(); 115 | ArrayList moves = new ArrayList<>(); 116 | ArrayList PCopys = new ArrayList<>(); 117 | while (instr.getNext() != null) { 118 | if (!(instr instanceof Instr.PCopy)) { 119 | instr = (Instr) instr.getNext(); 120 | continue; 121 | } 122 | PCopys.add(instr); 123 | ArrayList tags = ((Instr.PCopy) instr).getLHS(); 124 | ArrayList srcs = ((Instr.PCopy) instr).getRHS(); 125 | 126 | HashSet tagNameSet = new HashSet<>(); 127 | HashSet srcNameSet = new HashSet<>(); 128 | 129 | removeUndefCopy(tags, srcs, tagNameSet, srcNameSet); 130 | 131 | while (!checkPCopy(tags, srcs)) { 132 | boolean temp = false; 133 | for (int i = 0; i < tags.size(); i++) { 134 | String tagName = tags.get(i).getName(); 135 | if (!srcNameSet.contains(tagName)) { 136 | Instr move = new Instr.Move(tags.get(i).getType(), tags.get(i), srcs.get(i), bb); 137 | moves.add(move); 138 | 139 | tagNameSet.remove(tags.get(i).getName()); 140 | srcNameSet.remove(srcs.get(i).getName()); 141 | 142 | tags.remove(i); 143 | srcs.remove(i); 144 | 145 | temp = true; 146 | break; 147 | } 148 | } 149 | //temp = true 表示存在a,b 满足b <- a 且b没有被使用过,且已经处理过 150 | //否则需要执行操作 151 | if (!temp) { 152 | for (int i = 0; i < tags.size(); i++) { 153 | String srcName = srcs.get(i).getName(); 154 | Value src = srcs.get(i); 155 | Value tag = tags.get(i); 156 | if (!srcs.get(i).getName().equals(tags.get(i).getName())) { 157 | GlobalVal.VirtualValue newSrc = new GlobalVal.VirtualValue(tag.getType()); 158 | Instr move = new Instr.Move(tag.getType(), newSrc, src, bb); 159 | moves.add(move); 160 | srcs.set(i, newSrc); 161 | 162 | srcNameSet.remove(srcName); 163 | srcNameSet.add(move.getName()); 164 | } 165 | } 166 | } 167 | 168 | } 169 | instr = (Instr) instr.getNext(); 170 | } 171 | for (Instr instr1: PCopys) { 172 | instr1.remove(); 173 | } 174 | for (Instr instr1: moves) { 175 | bb.getEndInstr().insertBefore(instr1); 176 | } 177 | 178 | bb = (BasicBlock) bb.getNext(); 179 | } 180 | } 181 | 182 | private boolean checkPCopy(ArrayList tag, ArrayList src) { 183 | for (int i = 0; i < tag.size(); i++) { 184 | if (!tag.get(i).getName().equals(src.get(i).getName())) { 185 | return false; 186 | } 187 | } 188 | return true; 189 | } 190 | 191 | private void removeUndefCopy(ArrayList tag, ArrayList src, 192 | HashSet tagNames, HashSet srcNames) { 193 | ArrayList tempTag = new ArrayList<>(); 194 | ArrayList tempSrc = new ArrayList<>(); 195 | for (int i = 0; i < tag.size(); i++) { 196 | if (src.get(i) instanceof GlobalVal.UndefValue) { 197 | continue; 198 | } 199 | tempTag.add(tag.get(i)); 200 | tempSrc.add(src.get(i)); 201 | } 202 | tag.clear(); 203 | src.clear(); 204 | tag.addAll(tempTag); 205 | src.addAll(tempSrc); 206 | for (Value value: tag) { 207 | tagNames.add(value.getName()); 208 | } 209 | for (Value value: src) { 210 | srcNames.add(value.getName()); 211 | } 212 | 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/midend/RemoveUselessStore.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.BasicBlock; 4 | import mir.Function; 5 | import mir.Instr; 6 | import mir.Value; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | 12 | public class RemoveUselessStore { 13 | 14 | //如果想跨基本快做,需要当一个store所有的idoms都没有在下一次store前use的时候,才能删除 15 | private ArrayList functions; 16 | 17 | public RemoveUselessStore(ArrayList functions) { 18 | this.functions = functions; 19 | } 20 | 21 | public void Run() { 22 | HashSet removes = new HashSet<>(); 23 | HashMap storeAddress = new HashMap<>(); 24 | for (Function function: functions) { 25 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 26 | storeAddress.clear(); 27 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 28 | if (instr instanceof Instr.Store) { 29 | if (storeAddress.containsKey(((Instr.Store) instr).getPointer())) { 30 | removes.add(storeAddress.get(((Instr.Store) instr).getPointer())); 31 | } 32 | storeAddress.put(((Instr.Store) instr).getPointer(), instr); 33 | } else if (!(instr instanceof Instr.Alu)) { 34 | storeAddress.clear(); 35 | } 36 | } 37 | } 38 | } 39 | for (Instr instr: removes) { 40 | instr.remove(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/midend/SimpleCalc.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import mir.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | 9 | public class SimpleCalc { 10 | 11 | private ArrayList functions; 12 | 13 | public SimpleCalc(ArrayList functions) { 14 | this.functions = functions; 15 | } 16 | 17 | public void Run() { 18 | for (Function function: functions) { 19 | for (BasicBlock bb = function.getBeginBB(); bb.getNext() != null; bb = (BasicBlock) bb.getNext()) { 20 | HashMap> eq = new HashMap<>(); 21 | HashMap> inverse = new HashMap<>(); 22 | for (Instr instr = bb.getBeginInstr(); instr.getNext() != null; instr = (Instr) instr.getNext()) { 23 | Instr A = instr; 24 | if (A.getNext().getNext() != null) { 25 | Instr B = (Instr) instr.getNext(); 26 | if (A instanceof Instr.Alu && ((Instr.Alu) A).getOp().equals(Instr.Alu.Op.ADD) && 27 | B instanceof Instr.Alu && ((Instr.Alu) B).getOp().equals(Instr.Alu.Op.SUB) && 28 | ((Instr.Alu) A).getRVal1().equals(((Instr.Alu) B).getRVal1()) && 29 | ((Instr.Alu) B).getRVal2().equals(A)) { 30 | 31 | inverse.putIfAbsent(B, new HashSet<>()); 32 | inverse.get(B).add(((Instr.Alu) A).getRVal2()); 33 | } 34 | } 35 | if (A instanceof Instr.Alu && ((Instr.Alu) A).getOp().equals(Instr.Alu.Op.ADD)) { 36 | Value val1 = ((Instr.Alu) A).getRVal1(), val2 = ((Instr.Alu) A).getRVal2(); 37 | if (inverse.getOrDefault(val1, new HashSet<>()).contains(val2) || 38 | inverse.getOrDefault(val2, new HashSet<>()).contains(val1)) { 39 | A.modifyAllUseThisToUseA(new Constant.ConstantInt(0)); 40 | } else if (val1 instanceof Constant.ConstantInt && (int) ((Constant.ConstantInt) val1).getConstVal() == 0) { 41 | A.modifyAllUseThisToUseA(val2); 42 | eq.putIfAbsent(A, new HashSet<>()); 43 | eq.get(A).add(val2); 44 | } else if (val2 instanceof Constant.ConstantInt && (int) ((Constant.ConstantInt) val2).getConstVal() == 0) { 45 | A.modifyAllUseThisToUseA(val1); 46 | eq.putIfAbsent(A, new HashSet<>()); 47 | eq.get(A).add(val1); 48 | } 49 | } else if (A instanceof Instr.Alu && ((Instr.Alu) A).getOp().equals(Instr.Alu.Op.SUB)) { 50 | Value val1 = ((Instr.Alu) A).getRVal1(), val2 = ((Instr.Alu) A).getRVal2(); 51 | if (val1.equals(val2)) { 52 | A.modifyAllUseThisToUseA(new Constant.ConstantInt(0)); 53 | } else if (eq.getOrDefault(val1, new HashSet<>()).contains(val2) || 54 | eq.getOrDefault(val2, new HashSet<>()).contains(val1)) { 55 | A.modifyAllUseThisToUseA(new Constant.ConstantInt(0)); 56 | } else if (val1 instanceof Constant.ConstantInt && (int) ((Constant.ConstantInt) val1).getConstVal() == 0) { 57 | inverse.putIfAbsent(A, new HashSet<>()); 58 | inverse.get(A).add(val2); 59 | } else if (val2 instanceof Constant.ConstantInt && (int) ((Constant.ConstantInt) val2).getConstVal() == 0) { 60 | A.modifyAllUseThisToUseA(val1); 61 | eq.putIfAbsent(A, new HashSet<>()); 62 | eq.get(A).add(val1); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/midend/TestMain.java: -------------------------------------------------------------------------------- 1 | package midend; 2 | 3 | import lir.Arm; 4 | import lir.MC; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashSet; 8 | import java.util.LinkedHashSet; 9 | 10 | import static lir.Arm.Regs.GPRs.sp; 11 | import static mir.type.DataType.I32; 12 | 13 | public class TestMain { 14 | public static class A implements Cloneable{ 15 | public ArrayList opdList = new ArrayList<>(); 16 | public HashSet aSet = new HashSet<>(); 17 | 18 | @Override 19 | public String toString() { 20 | return "A{" + 21 | "opdList=" + opdList + 22 | ", aSet=" + aSet + 23 | '}'; 24 | } 25 | 26 | @Override 27 | public A clone() { 28 | try { 29 | A clone = (A) super.clone(); 30 | // TODO: copy mutable state here, so the clone can't change the internals of the original 31 | clone.opdList = new ArrayList<>(this.opdList); 32 | clone.aSet = new HashSet<>(this.aSet); 33 | return clone; 34 | } catch (CloneNotSupportedException e) { 35 | throw new AssertionError(); 36 | } 37 | } 38 | } 39 | //fixme:test 40 | public static void main(String[] args) { 41 | // A a = new A(); 42 | // a.opdList = new ArrayList<>(); 43 | // a.opdList.add(new MC.Operand(I32, 0)); 44 | // a.aSet.add(0); 45 | // System.out.println(a); 46 | // A b = a.clone(); 47 | // b.aSet.add(1); 48 | // b.opdList.add(new MC.Operand(I32, 1)); 49 | // System.out.println(a); 50 | // System.out.println(b); 51 | MC.Operand o = Arm.Reg.getRSReg(sp); 52 | System.out.println(o.reg); 53 | } 54 | 55 | // public static Value Jump(){ 56 | // return new Instr.Jump(new BasicBlock(), new BasicBlock()); 57 | // } 58 | } 59 | -------------------------------------------------------------------------------- /src/mir/Constant.java: -------------------------------------------------------------------------------- 1 | package mir; 2 | 3 | import mir.type.Type; 4 | import util.CenterControl; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.Objects; 9 | 10 | public class Constant extends Value { 11 | private static int const_num = 0; 12 | 13 | private int hash = const_num++; 14 | 15 | public Constant(Type type) { 16 | this.type = type; 17 | } 18 | 19 | public Object getConstVal() { 20 | return null; 21 | } 22 | 23 | @Override 24 | public boolean equals(Object o) { 25 | if (this == o) return true; 26 | if (o == null || getClass() != o.getClass()) return false; 27 | if (!super.equals(o)) return false; 28 | Constant constant = (Constant) o; 29 | return hash == constant.hash; 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | return Objects.hash(super.hashCode(), hash); 35 | } 36 | 37 | public static class ConstantInt extends Constant { 38 | public int constIntVal; 39 | 40 | private static final HashMap constIntMap = new HashMap<>(); 41 | public static final ConstantInt CONST_0/* = new ConstantInt(0)*/; 42 | public static final ConstantInt CONST_1/* = new ConstantInt(1)*/; 43 | 44 | static { 45 | CONST_0 = new ConstantInt(0); 46 | CONST_1 = new ConstantInt(1); 47 | constIntMap.put(0, CONST_0); 48 | constIntMap.put(1, CONST_1); 49 | } 50 | 51 | public ConstantInt(int val) { 52 | super(Type.BasicType.getI32Type()); 53 | constIntVal = val; 54 | } 55 | 56 | public static ConstantInt getConstInt(int intVal) { 57 | ConstantInt ret = constIntMap.get(intVal); 58 | if (ret == null) { 59 | ret = new ConstantInt(intVal); 60 | constIntMap.put(intVal, ret); 61 | } 62 | return ret; 63 | } 64 | 65 | @Override 66 | public Object getConstVal() { 67 | return constIntVal; 68 | } 69 | 70 | @Override 71 | public String getName() { 72 | return String.valueOf(constIntVal); 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return String.valueOf(constIntVal); 78 | } 79 | } 80 | 81 | public static class ConstantFloat extends Constant { 82 | float constFloatVal; 83 | private static final HashMap constFloatMap = new HashMap<>(); 84 | public static final ConstantFloat CONST_0F/* = new ConstantInt(0)*/; 85 | public static final ConstantFloat CONST_1F/* = new ConstantInt(1)*/; 86 | 87 | static { 88 | CONST_0F = new ConstantFloat(0); 89 | CONST_1F = new ConstantFloat(1); 90 | constFloatMap.put((float) 0.0, CONST_0F); 91 | constFloatMap.put((float) 1.0, CONST_1F); 92 | } 93 | 94 | public ConstantFloat(float val) { 95 | super(Type.BasicType.getF32Type()); 96 | constFloatVal = val; 97 | } 98 | 99 | String asmName = null; 100 | static int floatConstCnt = 1; 101 | 102 | public String getAsmName() { 103 | if (asmName == null) { 104 | asmName = "_F_CONST_" + floatConstCnt++; 105 | } 106 | return asmName; 107 | } 108 | 109 | @Override 110 | public Object getConstVal() { 111 | return constFloatVal; 112 | } 113 | 114 | @Override 115 | public String getName() { 116 | return String.format("0x%x", Double.doubleToRawLongBits((constFloatVal))); 117 | } 118 | 119 | public boolean isZero() { 120 | return getName().equals("0x0"); 121 | } 122 | 123 | @Override 124 | public boolean equals(Object o) { 125 | if (this == o) return true; 126 | if (o == null || getClass() != o.getClass()) return false; 127 | if (!super.equals(o)) return false; 128 | ConstantFloat that = (ConstantFloat) o; 129 | return this.getName().equals(that.getName()); 130 | } 131 | 132 | @Override 133 | public int hashCode() { 134 | return Objects.hash(super.hashCode(), constFloatVal); 135 | } 136 | 137 | @Override 138 | public String toString() { 139 | if (CenterControl.AlreadyBackend) { 140 | return String.valueOf(getIntBits()); 141 | } 142 | return String.format("0x%x", Double.doubleToRawLongBits((constFloatVal))); 143 | } 144 | 145 | public int getIntBits() { 146 | return Float.floatToIntBits(constFloatVal); 147 | } 148 | } 149 | 150 | public static class ConstantArray extends Constant { 151 | private ArrayList constArray; 152 | // private ArrayList arrayInt1D = new ArrayList<>(); 153 | // private ArrayList arrayFloat1D = new ArrayList<>(); 154 | private Type baseEleType; 155 | 156 | public ConstantArray(Type type, Type baseEleType, ArrayList arrayList) { 157 | super(type); 158 | assert type instanceof Type.ArrayType; 159 | this.baseEleType = baseEleType; 160 | constArray = arrayList; 161 | } 162 | 163 | public Constant getBaseConst(ArrayList dims) { 164 | int idx = 0; 165 | Type.ArrayType type = (Type.ArrayType) this.type; 166 | for (int i = 0; i < dims.size() - 1; i++) { 167 | assert type.getBaseType() instanceof Type.ArrayType; 168 | type = (Type.ArrayType) type.getBaseType(); 169 | idx += type.getSize(); 170 | } 171 | assert idx < constArray.size() + dims.get(dims.size() - 1); 172 | return constArray.get(idx); 173 | } 174 | } 175 | 176 | public static class ConstantBool extends Constant { 177 | 178 | private int constBoolVal; 179 | 180 | public ConstantBool(int val) { 181 | super(Type.BasicType.getI1Type()); 182 | assert val == 0 || val == 1; 183 | constBoolVal = val; 184 | } 185 | 186 | 187 | @Override 188 | public Object getConstVal() { 189 | return constBoolVal; 190 | } 191 | 192 | @Override 193 | public String getName() { 194 | return String.valueOf(constBoolVal); 195 | } 196 | 197 | @Override 198 | public String toString() { 199 | return String.valueOf(constBoolVal); 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/mir/GlobalVal.java: -------------------------------------------------------------------------------- 1 | package mir; 2 | 3 | import frontend.semantic.Initial; 4 | import frontend.syntax.Ast; 5 | import mir.type.Type; 6 | 7 | public class GlobalVal extends Value { 8 | public GlobalVal(Type type) { 9 | super(type); 10 | } 11 | 12 | public GlobalVal() { 13 | 14 | } 15 | 16 | public static class GlobalValue extends GlobalVal { 17 | // private static int GLOBAL_COUNT = 0; 18 | public Ast.Def def; 19 | public Initial initial; 20 | public boolean local = false; 21 | 22 | public GlobalValue(Type pointeeType, Ast.Def def, Initial initial) { 23 | super(new Type.PointerType(pointeeType)); 24 | prefix = GLOBAL_PREFIX; 25 | name = "g_" + def.ident.getContent(); 26 | // name = GLOBAL_NAME_PREFIX + GLOBAL_COUNT++; 27 | this.def = def; 28 | this.initial = initial; 29 | } 30 | 31 | public GlobalValue(Type pointeeType, String name, Initial initial) { 32 | super(new Type.PointerType(pointeeType)); 33 | prefix = GLOBAL_PREFIX; 34 | this.name = name; 35 | this.initial = initial; 36 | } 37 | 38 | public void setCanLocal() { 39 | this.local = true; 40 | } 41 | 42 | public boolean canLocal() { 43 | return this.local; 44 | } 45 | } 46 | 47 | public static class UndefValue extends GlobalVal { 48 | private static int undefValueCnt = 0; 49 | 50 | private String label; 51 | private String name; 52 | 53 | public UndefValue() { 54 | super(); 55 | } 56 | 57 | public UndefValue(Type type) { 58 | super(type); 59 | } 60 | 61 | 62 | @Override 63 | public String getName() { 64 | return "undef"; 65 | } 66 | 67 | public String getLabel() { 68 | return label; 69 | } 70 | } 71 | 72 | public static class VirtualValue extends GlobalVal{ 73 | private static int virtual_value_cnt = 0; 74 | 75 | public VirtualValue(Type type) { 76 | super(type); 77 | prefix = LOCAL_PREFIX; 78 | name = GLOBAL_NAME_PREFIX + virtual_value_cnt++; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/mir/Use.java: -------------------------------------------------------------------------------- 1 | package mir; 2 | 3 | import util.ILinkNode; 4 | 5 | import java.util.Objects; 6 | 7 | public class Use extends ILinkNode { 8 | private Instr user; 9 | private Value used; 10 | private int idx; 11 | 12 | private static int use_num = 0; 13 | 14 | private int hash = ++use_num; 15 | 16 | public Use(){ 17 | super(); 18 | } 19 | 20 | public Use(Instr user, Value used, int idx) { 21 | super(); 22 | this.user = user; 23 | this.used = used; 24 | this.idx = idx; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | if (this == o) return true; 30 | if (o == null || getClass() != o.getClass()) return false; 31 | Use use = (Use) o; 32 | return hash == use.hash; 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | return Objects.hash(hash); 38 | } 39 | 40 | public Value getUsed() { 41 | return used; 42 | } 43 | 44 | public Instr getUser() { 45 | return user; 46 | } 47 | 48 | public int getIdx() { 49 | return idx; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/mir/Value.java: -------------------------------------------------------------------------------- 1 | package mir; 2 | 3 | import mir.type.Type; 4 | import util.ILinkNode; 5 | 6 | import java.util.Objects; 7 | 8 | public class Value extends ILinkNode { 9 | 10 | public enum AmaTag { 11 | value, 12 | func, 13 | bb, 14 | bino, 15 | ashr, 16 | icmp, 17 | fcmp, 18 | fneg, 19 | zext, 20 | fptosi, 21 | sitofp, 22 | alloc, 23 | load, 24 | store, 25 | gep, 26 | bitcast, 27 | call, 28 | phi, 29 | pcopy, 30 | move, 31 | branch, 32 | jump, 33 | ret, 34 | } 35 | 36 | public AmaTag tag = AmaTag.value; 37 | 38 | public static final String GLOBAL_PREFIX = "@"; 39 | public static final String LOCAL_PREFIX = "%"; 40 | public static final String GLOBAL_NAME_PREFIX = "g"; 41 | public static final String LOCAL_NAME_PREFIX = "v"; 42 | public static final String FPARAM_NAME_PREFIX = "f"; 43 | public static int value_num = 0; 44 | 45 | private int hash = value_num++; 46 | public String prefix; 47 | public String name; 48 | 49 | public static boolean debug = true; 50 | 51 | private Use beginUse = new Use(); 52 | private Use endUse = new Use(); 53 | 54 | protected Type type; 55 | 56 | public Value() { 57 | super(); 58 | // if(debug){ 59 | // System.err.println("fuck"); 60 | // } 61 | beginUse.setNext(endUse); 62 | endUse.setPrev(beginUse); 63 | } 64 | 65 | public Value(Type type) { 66 | super(); 67 | // if(debug){ 68 | // System.err.println("fuck"); 69 | // } 70 | this.type = type; 71 | beginUse.setNext(endUse); 72 | endUse.setPrev(beginUse); 73 | } 74 | 75 | public void insertAtEnd(Use use) { 76 | //end.insertAfter(use); 77 | //end = use; 78 | endUse.insertBefore(use); 79 | } 80 | 81 | public String getName() { 82 | return prefix + name; 83 | } 84 | 85 | public String getNameWithOutPrefix() { 86 | return name; 87 | } 88 | 89 | public Type getType() { 90 | return type; 91 | } 92 | 93 | public Use getBeginUse() { 94 | assert beginUse.getNext() instanceof Use; 95 | return (Use) beginUse.getNext(); 96 | } 97 | 98 | public Use getEndUse() { 99 | assert endUse.getPrev() instanceof Use; 100 | return (Use) endUse.getPrev(); 101 | } 102 | 103 | public boolean onlyOneUser() { 104 | return getBeginUse().equals(getEndUse()); 105 | } 106 | 107 | public void modifyAllUseThisToUseA(Value A) { 108 | Use use = (Use) beginUse.getNext(); 109 | while (use.getNext() != null) { 110 | Instr user = use.getUser(); 111 | user.modifyUse(this, A, use.getIdx()); 112 | use = (Use) use.getNext(); 113 | } 114 | } 115 | 116 | public String getDescriptor() { 117 | return getType() + " " + getName(); 118 | } 119 | 120 | public boolean isNoUse() { 121 | return beginUse.getNext().equals(endUse); 122 | } 123 | 124 | public boolean isAlu() { 125 | return tag == AmaTag.bino; 126 | } 127 | 128 | public boolean isStore() { 129 | return tag == AmaTag.store; 130 | } 131 | 132 | public boolean isLoad() { 133 | return tag == AmaTag.load; 134 | } 135 | 136 | public boolean isAlloc() { 137 | return tag == AmaTag.alloc; 138 | } 139 | 140 | public boolean isGep() { 141 | return tag == AmaTag.gep; 142 | } 143 | 144 | public boolean isCall() { 145 | return tag == AmaTag.call; 146 | } 147 | 148 | public boolean isPhi() { 149 | return tag == AmaTag.phi; 150 | } 151 | 152 | public boolean isIcmp() { 153 | return tag == AmaTag.icmp; 154 | } 155 | 156 | public boolean isFcmp() { 157 | return tag == AmaTag.fcmp; 158 | } 159 | 160 | public boolean isBranch() { 161 | return tag == AmaTag.branch; 162 | } 163 | 164 | public boolean isBJ(){ 165 | return tag == AmaTag.branch || tag == AmaTag.jump; 166 | } 167 | 168 | public boolean isConstant() { 169 | return this instanceof Constant; 170 | } 171 | public boolean isConstantInt() { 172 | return this instanceof Constant.ConstantInt; 173 | } 174 | 175 | public boolean isConstantFloat() { 176 | return this instanceof Constant.ConstantFloat; 177 | } 178 | 179 | @Override 180 | public boolean equals(Object o) { 181 | if (this == o) return true; 182 | if (o == null || getClass() != o.getClass()) return false; 183 | Value value = (Value) o; 184 | return hash == value.hash; 185 | } 186 | 187 | @Override 188 | public int hashCode() { 189 | return Objects.hash(hash); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/mir/type/DataType.java: -------------------------------------------------------------------------------- 1 | package mir.type; 2 | 3 | public enum DataType{ 4 | I32("i32"), F32("float"), I1("i1"); 5 | 6 | private String dataTypeName; 7 | 8 | DataType(String dataTypeName) { 9 | this.dataTypeName = dataTypeName; 10 | } 11 | 12 | @Override 13 | public String toString() { 14 | return dataTypeName; 15 | } 16 | 17 | public String getDataTypeName() { 18 | return dataTypeName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/mir/type/Type.java: -------------------------------------------------------------------------------- 1 | package mir.type; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Objects; 5 | 6 | /** 7 | * LLVM IR 中的变量类型系统 8 | */ 9 | public class Type { 10 | 11 | public static VoidType getVoidType() { 12 | return VoidType.getVoidType(); 13 | } 14 | 15 | // public static BasicType getInt1Type(){ 16 | // return BasicType.getInt1Type(); 17 | // } 18 | // 19 | // public static BasicType getInt32Type(){ 20 | // return BasicType.getInt32Type(); 21 | // } 22 | 23 | public boolean isVoidType() { 24 | return this == VoidType.VOID_TYPE; 25 | } 26 | 27 | // public boolean isInt1Type() { 28 | // return this instanceof BasicType && ((BasicType) this).dataType == DataType.BOOL; 29 | // } 30 | // 31 | // public boolean isInt32Type() { 32 | // return this instanceof BasicType && ((BasicType) this).dataType == DataType.INT; 33 | // } 34 | 35 | public boolean isInt1Type() { 36 | return this == BasicType.getI1Type(); 37 | } 38 | 39 | public boolean isInt32Type() { 40 | return this == BasicType.getI32Type(); 41 | } 42 | 43 | public boolean isFloatType() { 44 | return this == BasicType.getF32Type(); 45 | } 46 | 47 | public boolean isPointerType() { 48 | return this instanceof PointerType; 49 | } 50 | 51 | public boolean isBasicType() { 52 | return this instanceof BasicType; 53 | } 54 | 55 | public static class BasicType extends Type { 56 | public DataType dataType; 57 | public static final BasicType I32_TYPE = new BasicType(DataType.I32); 58 | public static final BasicType I1_TYPE = new BasicType(DataType.I1); 59 | public static final BasicType F32_TYPE = new BasicType(DataType.F32); 60 | 61 | public static BasicType getF32Type() { 62 | return F32_TYPE; 63 | } 64 | 65 | public static BasicType getI1Type() { 66 | return I1_TYPE; 67 | } 68 | 69 | public static BasicType getI32Type() { 70 | return I32_TYPE; 71 | } 72 | 73 | private BasicType(DataType dataType) { 74 | this.dataType = dataType; 75 | } 76 | 77 | // @Override 78 | // public boolean equals(Object obj) { 79 | // if(obj == null)return false; 80 | // return obj instanceof BasicType && ((BasicType) obj).dataType == dataType; 81 | // } 82 | 83 | @Override 84 | public boolean equals(Object obj) { 85 | return this == obj; 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return dataType.toString(); 91 | } 92 | } 93 | 94 | // Call可能是VoidType 95 | // 认为Store是VoidType 96 | // Terminator(Return, Jump, Branch)都是VoidType 97 | public static class VoidType extends Type { 98 | private final static VoidType VOID_TYPE = new VoidType(); 99 | 100 | private VoidType() { 101 | } 102 | 103 | public static VoidType getVoidType() { 104 | return VOID_TYPE; 105 | } 106 | 107 | @Override 108 | public boolean equals(Object obj) { 109 | return obj == VOID_TYPE; 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return "void"; 115 | } 116 | } 117 | 118 | 119 | public static class BBType extends Type { 120 | private final static BBType BB_TYPE = new BBType(); 121 | 122 | private BBType() { 123 | } 124 | 125 | public static BBType getBBType() { 126 | return BB_TYPE; 127 | } 128 | 129 | @Override 130 | public boolean equals(Object obj) { 131 | return obj == BB_TYPE; 132 | } 133 | 134 | @Override 135 | public String toString() { 136 | return "b "; 137 | } 138 | } 139 | 140 | public static class ArrayType extends Type { 141 | private final int size; 142 | private final Type baseType; 143 | private BasicType baseEleType = null; 144 | private ArrayList dims = new ArrayList<>(); 145 | 146 | @Override 147 | public boolean equals(Object o) { 148 | if (this == o) return true; 149 | if (o == null || getClass() != o.getClass()) return false; 150 | ArrayType arrayType = (ArrayType) o; 151 | return size == arrayType.size && Objects.equals(baseType, arrayType.baseType); 152 | } 153 | 154 | @Override 155 | public int hashCode() { 156 | return Objects.hash(size, baseType); 157 | } 158 | 159 | @Override 160 | public String toString() { 161 | return String.format("[%d x %s]", size, baseType); 162 | } 163 | 164 | public ArrayType(final int size, final Type baseType) { 165 | this.size = size; 166 | this.baseType = baseType; 167 | dims.add(size); 168 | if (baseType.isArrType()) { 169 | dims.addAll(((ArrayType) baseType).dims); 170 | } 171 | } 172 | 173 | public int getSize() { 174 | return this.size; 175 | } 176 | 177 | public int getFlattenSize() { 178 | // TODO: 没有做高速缓存, 保证更改后不会出问题 179 | if (baseType instanceof BasicType) { 180 | return size; 181 | } 182 | assert baseType.isArrType(); 183 | return ((ArrayType) baseType).getFlattenSize() * size; 184 | } 185 | 186 | public Type getBaseType() { 187 | return this.baseType; 188 | } 189 | 190 | public BasicType getBaseEleType() { 191 | if (baseEleType != null) { 192 | return baseEleType; 193 | } 194 | if (baseType instanceof BasicType) { 195 | return (BasicType) baseType; 196 | } 197 | assert baseType instanceof ArrayType; 198 | return ((ArrayType) baseType).getBaseEleType(); 199 | } 200 | 201 | public ArrayList getDims() { 202 | // TODO: 没有用高速缓存, 每次都新建 203 | dims.clear(); 204 | dims.add(size); 205 | if(baseType.isArrType()){ 206 | dims.addAll(((ArrayType) baseType).dims); 207 | } 208 | return dims; 209 | } 210 | 211 | public int getDimSize(){ 212 | if(baseType.isArrType()){ 213 | return ((ArrayType) baseType).getDimSize() + 1; 214 | } 215 | return 1; 216 | } 217 | 218 | public int getBaseFlattenSize(){ 219 | if(baseType.isArrType()){ 220 | return ((ArrayType) baseType).getFlattenSize(); 221 | } 222 | return 4; 223 | } 224 | } 225 | 226 | public boolean isArrType() { 227 | return this instanceof ArrayType; 228 | } 229 | 230 | public static class PointerType extends Type { 231 | private final Type innerType; 232 | 233 | @Override 234 | public boolean equals(Object o) { 235 | if (this == o) return true; 236 | if (o == null || getClass() != o.getClass()) return false; 237 | PointerType that = (PointerType) o; 238 | return Objects.equals(innerType, that.innerType); 239 | } 240 | 241 | @Override 242 | public int hashCode() { 243 | return Objects.hash(innerType); 244 | } 245 | 246 | @Override 247 | public String toString() { 248 | return innerType + "*"; 249 | } 250 | 251 | public PointerType(Type innerType) { 252 | this.innerType = innerType; 253 | } 254 | 255 | public Type getInnerType() { 256 | return this.innerType; 257 | } 258 | 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/util/CenterControl.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class CenterControl { 4 | public static final boolean _FAST_REG_ALLOCATE = false; 5 | public static final boolean _IMM_TRY = false; 6 | public static final boolean STABLE = true; 7 | public static final boolean _BACKEND_COMMENT_OUTPUT = false; 8 | public static boolean _ONLY_FRONTEND = false; 9 | public static final boolean _cutLiveNessShortest = false; 10 | public static final boolean _FixStackWithPeepHole = true; 11 | public static boolean _GPRMustToStack = true; 12 | public static boolean _FPRMustToStack = true; 13 | public static boolean _GPR_NOT_RESPILL = true; 14 | public static boolean _FPR_NOT_RESPILL = true; 15 | public static final boolean _AGGRESSIVE_ADD_MOD_OPT = false; 16 | public static final boolean _OPEN_PARALLEL = true; 17 | public static final boolean _OPEN_PARALLEL_BACKEND = true; 18 | public static final boolean _GLOBAL_BSS = true; 19 | public static boolean AlreadyBackend = false; 20 | 21 | public static String _TAG = "1"; 22 | public static boolean _FUNC_PARALLEL = false; 23 | public static final boolean _initAll = false; 24 | 25 | 26 | //O2-control 27 | public static final boolean _CLOSE_ALL_FLOAT_OPT = false; 28 | public static final boolean _OPEN_CONST_TRANS_FOLD = _CLOSE_ALL_FLOAT_OPT? false : true; 29 | public static final boolean _OPEN_FLOAT_INSTR_COMB = _CLOSE_ALL_FLOAT_OPT? false : true; 30 | public static final boolean _OPEN_FLOAT_LOOP_STRENGTH_REDUCTION = _CLOSE_ALL_FLOAT_OPT? false : true; 31 | public static final boolean _OPEN_FTOI_ITOF_GVN = _CLOSE_ALL_FLOAT_OPT? false : true; 32 | 33 | 34 | public static final boolean _STRONG_FUNC_INLINE = true; 35 | public static final boolean _STRONG_FUNC_GCM = true; 36 | 37 | public static double _HEURISTIC_BASE = 1.45; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/util/FileDealer.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.io.*; 4 | import java.nio.charset.StandardCharsets; 5 | import java.util.ArrayList; 6 | 7 | public class FileDealer { 8 | // private static final File inputFile = new File("testcase.sy"); 9 | private static InputStream inputStream; 10 | private static BufferedInputStream bufferedInputStream; 11 | private static final FileDealer fileDealer = new FileDealer(); 12 | private static ArrayList outputStringList = new ArrayList<>(); 13 | public static boolean ParserTryOut = false; 14 | private static ArrayList tryOutputStringList = new ArrayList<>(); 15 | private static ArrayList mipsStringList = new ArrayList<>(); 16 | private static ArrayList ansTxtList = new ArrayList<>(); 17 | 18 | private FileDealer() { 19 | // try { 20 | // inputStream = new FileInputStream(inputFile); 21 | // bufferedInputStream = new BufferedInputStream(inputStream); 22 | // } catch (FileNotFoundException e) { 23 | // e.printStackTrace(); 24 | // } 25 | 26 | // try { 27 | // bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("testfile.txt"))); 28 | // } catch (FileNotFoundException e) { 29 | // e.printStackTrace(); 30 | // } 31 | } 32 | 33 | public static FileDealer getInstance() { 34 | return fileDealer; 35 | } 36 | 37 | // public static File getInputFile() { 38 | // return inputFile; 39 | // } 40 | 41 | public static BufferedInputStream getNewBufferedInputStream(InputStream in) { 42 | bufferedInputStream = new BufferedInputStream(in); 43 | return bufferedInputStream; 44 | } 45 | 46 | public static void tryClearOutputString(String s) { 47 | tryOutputStringList.clear(); 48 | } 49 | 50 | public static void tryAddOutputString(String s) { 51 | tryOutputStringList.add(s); 52 | } 53 | 54 | public static void outputToStream(StringBuilder strBD, OutputStream s) { 55 | try { 56 | s.write(strBD.toString().getBytes(StandardCharsets.UTF_8)); 57 | } catch (IOException e) { 58 | throw new RuntimeException(e); 59 | } 60 | } 61 | 62 | public static void outputToFile(StringBuilder strBD, String s) { 63 | File f = new File(s); 64 | FileOutputStream fop = null; 65 | try { 66 | fop = new FileOutputStream(f); 67 | } catch (FileNotFoundException e) { 68 | e.printStackTrace(); 69 | } 70 | 71 | assert fop != null; 72 | OutputStreamWriter writer = new OutputStreamWriter(fop, StandardCharsets.UTF_8); 73 | try { 74 | writer.append(strBD.toString()); 75 | } catch (IOException e) { 76 | e.printStackTrace(); 77 | } 78 | try { 79 | writer.close(); 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | } 83 | try { 84 | fop.close(); 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | 90 | public static void outputClear() { 91 | outputStringList.clear(); 92 | } 93 | 94 | // public BufferedInputStream getBufferedInputStream(){ 95 | // return bufferedInputStream; 96 | // } 97 | 98 | public static void addOutputString(String s) { 99 | outputStringList.add(s); 100 | } 101 | 102 | public static void addOutputMips(String s) { 103 | mipsStringList.add(s); 104 | } 105 | 106 | public static void addOutputTxt(String s) { 107 | ansTxtList.add(s); 108 | } 109 | 110 | // public void output(String s){ 111 | // 112 | // } 113 | public static void outputStringList(OutputStream out) { 114 | streamOutput(out, outputStringList); 115 | } 116 | 117 | private static void streamOutput(OutputStream fop, ArrayList outputStringList) { 118 | OutputStreamWriter writer; 119 | writer = new OutputStreamWriter(fop, StandardCharsets.UTF_8); 120 | for (String t : outputStringList) { 121 | try { 122 | writer.append(t).append("\n"); 123 | } catch (IOException e) { 124 | e.printStackTrace(); 125 | } 126 | } 127 | try { 128 | writer.close(); 129 | } catch (IOException e) { 130 | e.printStackTrace(); 131 | } 132 | try { 133 | fop.close(); 134 | } catch (IOException e) { 135 | e.printStackTrace(); 136 | } 137 | } 138 | 139 | private static void streamOutput(OutputStream fop, StringBuilder stb) { 140 | OutputStreamWriter writer; 141 | writer = new OutputStreamWriter(fop, StandardCharsets.UTF_8); 142 | try { 143 | writer.append(stb); 144 | } catch (IOException e) { 145 | e.printStackTrace(); 146 | } 147 | try { 148 | writer.close(); 149 | } catch (IOException e) { 150 | e.printStackTrace(); 151 | } 152 | try { 153 | fop.close(); 154 | } catch (IOException e) { 155 | e.printStackTrace(); 156 | } 157 | } 158 | 159 | public static void outputMips(String str) { 160 | File f; 161 | f = new File(str); 162 | FileOutputStream fop = null; 163 | try { 164 | fop = new FileOutputStream(f); 165 | } catch (FileNotFoundException e) { 166 | e.printStackTrace(); 167 | } 168 | 169 | OutputStreamWriter writer = null; 170 | streamOutput(fop, mipsStringList); 171 | } 172 | 173 | 174 | public static void outputAnsTxt(String str) { 175 | File f; 176 | f = new File(str); 177 | FileOutputStream fop = null; 178 | try { 179 | fop = new FileOutputStream(f); 180 | } catch (FileNotFoundException e) { 181 | e.printStackTrace(); 182 | } 183 | 184 | OutputStreamWriter writer = null; 185 | streamOutput(fop, ansTxtList); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/util/ILinkNode.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | /** 4 | * 自定义的链表节点 5 | */ 6 | public class ILinkNode { 7 | private ILinkNode prev; 8 | private ILinkNode next; 9 | 10 | public boolean hasPrev() { 11 | return prev != null; 12 | } 13 | 14 | public boolean hasNext() { 15 | return next != null; 16 | } 17 | 18 | // remove the node itself from the linked list 19 | public void remove() { 20 | // prev.next = next 21 | if (hasPrev()) { 22 | getPrev().setNext(getNext()); 23 | } 24 | // next.prev = prev 25 | if (hasNext()) { 26 | getNext().setPrev(getPrev()); 27 | } 28 | } 29 | 30 | // this -> node 31 | public void insertAfter(ILinkNode node) { 32 | node.setPrev(this); 33 | node.setNext(getNext()); 34 | if (hasNext()) { 35 | getNext().setPrev(node); 36 | } 37 | setNext(node); 38 | } 39 | 40 | // insert another node before this 41 | // -> node -> this-> 42 | public void insertBefore(ILinkNode node) { 43 | node.setNext(this); 44 | node.setPrev(getPrev()); 45 | if (hasPrev()) { 46 | getPrev().setNext(node); 47 | } 48 | setPrev(node); 49 | } 50 | 51 | public ILinkNode() { 52 | } 53 | 54 | public ILinkNode getPrev() { 55 | return this.prev; 56 | } 57 | 58 | public void setPrev(final ILinkNode prev) { 59 | this.prev = prev; 60 | } 61 | 62 | public ILinkNode getNext() { 63 | return this.next; 64 | } 65 | 66 | public void setNext(final ILinkNode next) { 67 | this.next = next; 68 | } 69 | 70 | public static class EmptyNode extends ILinkNode { 71 | 72 | } 73 | 74 | 75 | } -------------------------------------------------------------------------------- /src/util/Ilist.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Iterator; 4 | 5 | public class Ilist implements Iterable { 6 | // 此种写法head和tail仍然是ILinkNode类 7 | // public E head; 8 | // public E tail; 9 | // public int size = 0; 10 | // 11 | // public Ilist() { 12 | // head = (E) new ILinkNode(); 13 | // tail = (E) new ILinkNode(); 14 | // head.setNext(tail); 15 | // tail.setPrev(head); 16 | // size = 0; 17 | // } 18 | public ILinkNode head; 19 | public ILinkNode tail; 20 | public int size = 0; 21 | 22 | public Ilist() { 23 | head = new ILinkNode(); 24 | tail = new ILinkNode(); 25 | head.setNext(tail); 26 | tail.setPrev(head); 27 | size = 0; 28 | } 29 | 30 | public void clear() { 31 | size = 0; 32 | head.setNext(tail); 33 | tail.setPrev(head); 34 | } 35 | 36 | public E getBegin() { 37 | assert head.getNext() != null; 38 | return (E) head.getNext(); 39 | } 40 | 41 | public E getEnd() { 42 | return (E) tail.getPrev(); 43 | } 44 | 45 | public void insertBefore(E node, E insertBefore) { 46 | node.setPrev(insertBefore.getPrev()); 47 | node.setNext(insertBefore); 48 | insertBefore.getPrev().setNext(node); 49 | insertBefore.setPrev(node); 50 | size++; 51 | } 52 | 53 | public void insertAfter(E node, E insertAfter) { 54 | node.setNext(insertAfter.getNext()); 55 | node.setPrev(insertAfter); 56 | insertAfter.getNext().setPrev(node); 57 | insertAfter.setNext(node); 58 | size++; 59 | } 60 | 61 | public void insertAtEnd(E node) { 62 | node.setPrev(tail.getPrev()); 63 | node.setNext(tail); 64 | tail.getPrev().setNext(node); 65 | tail.setPrev(node); 66 | size++; 67 | } 68 | 69 | public void insertAtBegin(E node) { 70 | node.setNext(head.getNext()); 71 | node.setPrev(head); 72 | head.getNext().setPrev(node); 73 | head.setNext(node); 74 | size++; 75 | } 76 | 77 | public void remove(E node) { 78 | node.getPrev().setNext(node.getNext()); 79 | node.getNext().setPrev(node.getPrev()); 80 | size--; 81 | } 82 | 83 | @Override 84 | public Iterator iterator() { 85 | return new IIterator(); 86 | } 87 | 88 | class IIterator implements Iterator { 89 | 90 | ILinkNode cur = head; 91 | 92 | IIterator() { 93 | } 94 | 95 | @Override 96 | public boolean hasNext() { 97 | return cur.getNext() != tail; 98 | } 99 | 100 | @Override 101 | public E next() { 102 | cur = cur.getNext(); 103 | return (E) cur; 104 | } 105 | 106 | @Override 107 | public void remove() { 108 | cur.getPrev().setNext(cur.getNext()); 109 | cur.getNext().setPrev(cur.getPrev()); 110 | size--; 111 | } 112 | 113 | } 114 | 115 | } 116 | --------------------------------------------------------------------------------