├── LICENSE ├── README.md └── src ├── Compiler.java ├── emit └── EmitLLVM.java ├── frontend ├── Scope.java ├── Visitor.java ├── miniSysY.g4 ├── miniSysYBaseVisitor.java ├── miniSysYLexer.java ├── miniSysYParser.java └── miniSysYVisitor.java ├── ir ├── IRBuilder.java ├── Module.java ├── User.java ├── Value.java ├── type │ ├── ArrayType.java │ ├── FunctionType.java │ ├── IntegerType.java │ ├── PointerType.java │ └── Type.java └── values │ ├── BasicBlock.java │ ├── Constant.java │ ├── Function.java │ ├── GlobalVariable.java │ ├── UndefValue.java │ └── instructions │ ├── BinaryInst.java │ ├── Inst.java │ ├── MemInst.java │ └── TerminatorInst.java └── util └── IList.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 GeneraluseAI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miniSysY_example_compiler 2 | 使用 java + antlr4 实现的编译器 3 | 源语言为 miniSysY(一种用于教育用途的类似于c语言的高级语言) 4 | 目标语言为 LLVM IR 5 | 6 | 是北京航空航天大学软件学院编译原理课程的示例编译器 7 | 8 | ## 警告 9 | 10 | 我们在期末进行代码查重的时候会将这个编译器的源代码放入查重集合中,请不要抄袭。 -------------------------------------------------------------------------------- /src/Compiler.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | 3 | import emit.EmitLLVM; 4 | import ir.Module; 5 | import org.antlr.v4.runtime.BailErrorStrategy; 6 | import org.antlr.v4.runtime.BaseErrorListener; 7 | import org.antlr.v4.runtime.CharStream; 8 | import org.antlr.v4.runtime.CharStreams; 9 | import frontend.*; 10 | import org.antlr.v4.runtime.CommonTokenStream; 11 | import org.antlr.v4.runtime.RecognitionException; 12 | import org.antlr.v4.runtime.Recognizer; 13 | import org.antlr.v4.runtime.tree.ParseTree; 14 | 15 | public class Compiler { 16 | //这个编译器仅作为示例用,你可以参考实现架构,但不允许直接抄写代码 17 | public static void main(String[] args) throws IOException { 18 | if (args.length < 1) { 19 | System.err.println("args are required."); 20 | } 21 | var source = args[0];// .sy 22 | // var target = args[1];// .ll 23 | CharStream input = CharStreams.fromFileName(source);//read file context from source 24 | miniSysYLexer lexer = new miniSysYLexer(input);//生成一个 lexer 25 | lexer.addErrorListener(new BaseErrorListener() { 26 | @Override 27 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, 28 | int pos, String msg, RecognitionException e) { 29 | throw new RuntimeException("Lex Error in line: " + line + "pos: " + pos); 30 | } 31 | });//给 lexer 加上错误监听 32 | CommonTokenStream tokens = new CommonTokenStream(lexer);//产生token stream 33 | miniSysYParser parser = new miniSysYParser(tokens);//将 token stream 作为输入,生成 parser 34 | parser.setErrorHandler( 35 | new BailErrorStrategy());//因为我们对错误处理的要求并不高,所以使用 bailErrorStrategy 意思是出现异常以后不进行恢复,仅 throw 一个 runtime exception 36 | ParseTree tree = parser.program();//解析 tokens, "program"相当于开始符号,在这个解析结束后 parser 会生成一棵完整的 AST,也就四 tree 37 | Visitor visitor = new Visitor(); 38 | visitor.visit(tree);//通过访问者模式去 "visit" 由 parser 生成的 ast 39 | var emit = new EmitLLVM(); 40 | emit.run(Module.module); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/emit/EmitLLVM.java: -------------------------------------------------------------------------------- 1 | package emit; 2 | 3 | import ir.Module; 4 | import ir.values.instructions.BinaryInst; 5 | 6 | import java.io.FileWriter; 7 | import java.util.logging.Logger; 8 | 9 | import ir.*; 10 | 11 | 12 | public class EmitLLVM { 13 | 14 | public EmitLLVM(String outputName) { 15 | this.outputName = outputName; 16 | sb = new StringBuilder(); 17 | } 18 | 19 | public EmitLLVM() { 20 | sb = new StringBuilder(); 21 | } 22 | 23 | String outputName = "out.ll"; 24 | StringBuilder sb; 25 | private int vnc = 0;//value name counter 26 | 27 | 28 | private String newName() { 29 | var v = String.valueOf(vnc); 30 | vnc++; 31 | return v; 32 | } 33 | 34 | private void nameVariable(Module m) { 35 | m.globalVariables.forEach(gv -> { 36 | if (!gv.name.startsWith("@")) { 37 | gv.name = "@" + gv.name; 38 | } 39 | }); 40 | m.functions.forEach( 41 | f -> { 42 | vnc = 0; 43 | var func = f.getVal(); 44 | if (!func.isBuiltin()) { 45 | func.getParamList().forEach(arg -> { 46 | arg.name = "%" + newName(); 47 | }); 48 | func.list.forEach(bbInode -> { 49 | // if (!bbInode.equals(func.getList_().getEntry())) { 50 | bbInode.getVal().name = newName(); 51 | //} 52 | bbInode.getVal().list.forEach( 53 | instNode -> { 54 | if (instNode.getVal().needName) { 55 | instNode.getVal().name = "%" + newName(); 56 | } 57 | } 58 | ); 59 | }); 60 | } else { 61 | sb.append("declare ") 62 | .append(func) 63 | .append("\n"); 64 | 65 | } 66 | } 67 | ); 68 | } 69 | 70 | public void run(Module m) { 71 | nameVariable(m); 72 | m.globalVariables.forEach(gb -> { 73 | sb.append(gb).append("\n"); 74 | }); 75 | m.functions.forEach(func -> { 76 | var val = func.getVal(); 77 | if (!val.isBuiltin()) { 78 | sb.append("define dso_local ") 79 | .append(val) 80 | .append("{"); 81 | sb.append("\n"); 82 | 83 | val.list.forEach( 84 | bbNode -> { 85 | var bbval = bbNode.getVal(); 86 | if (!val.list.getEntry().equals(bbNode)) { 87 | sb.append(bbval.name); 88 | sb.append(":"); 89 | sb.append("\n"); 90 | } 91 | bbval.list.forEach( 92 | instNode -> { 93 | var instVal = instNode.getVal(); 94 | sb.append(instVal.toString()); 95 | sb.append("\n"); 96 | 97 | } 98 | ); 99 | } 100 | ); 101 | sb.append("}\n"); 102 | } else { 103 | 104 | } 105 | }); 106 | try { 107 | FileWriter fw = new FileWriter(outputName); 108 | // System.out.println(sb); 109 | fw.append(sb); 110 | fw.close(); 111 | } catch (Exception e) { 112 | e.printStackTrace(); 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/frontend/Scope.java: -------------------------------------------------------------------------------- 1 | package frontend; 2 | 3 | import ir.Value; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | 8 | public class Scope { 9 | private final ArrayList> tables; 10 | public boolean preEnter = false; 11 | public HashMaptop(){return tables.get(tables.size()-1);} 12 | public void addLayer() { 13 | if (preEnter) { 14 | preEnter = false; 15 | return; 16 | } 17 | tables.add(new HashMap<>()); 18 | } 19 | //弹出一层Scope,这通常意味着完成了一片作用域的visit 20 | public void popLayer() {tables.remove(tables.size() - 1);} 21 | //最外层的Scope是Global的 22 | public boolean isGlobal() {return this.tables.size() == 1;} 23 | public Value find(String name) {//从里到外搜索变量名,找到就返回,找不到就返回 null 24 | for (int i = tables.size() - 1; i >= 0; i--) { 25 | Value t = tables.get(i).get(name); 26 | if (t != null)return t; 27 | } 28 | return null; 29 | } 30 | public void put(String name, Value v) { 31 | if (top().get(name) != null) { 32 | throw new RuntimeException("name already exists"); 33 | } else { 34 | top().put(name, v); 35 | } 36 | } 37 | Scope() { 38 | tables = new ArrayList<>(); 39 | tables.add(new HashMap<>()); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/frontend/Visitor.java: -------------------------------------------------------------------------------- 1 | package frontend; 2 | 3 | import ir.IRBuilder; 4 | import ir.Module; 5 | import ir.Value; 6 | import ir.type.*; 7 | import ir.values.BasicBlock; 8 | import ir.values.Constant; 9 | import ir.values.Function; 10 | import ir.values.GlobalVariable; 11 | import ir.values.instructions.Inst; 12 | import ir.values.instructions.TerminatorInst.*; 13 | 14 | import java.math.BigInteger; 15 | import java.util.*; 16 | import java.util.List; 17 | 18 | import ir.values.instructions.Inst.*; 19 | import frontend.miniSysYParser.*; 20 | 21 | import javax.script.ScriptEngineManager; 22 | import javax.swing.*; 23 | 24 | public class Visitor extends miniSysYBaseVisitor { 25 | // visit*函数返回的值都是Value, 26 | // 所以一些值能够直接通过visit函数的返回值进行传递,但有一些额外的值没办法这么搞,我就通过全局变量传了。 27 | Module m = Module.module; //module 是单例的 28 | private final IRBuilder builder = IRBuilder.getInstance();//builder也是单例 29 | private final Scope scope = new Scope();//和作用域相匹配的符号表 30 | // singleton variables 31 | private final Constant.ConstantInt CONST0 = Constant.ConstantInt.get(0); 32 | private final Type i32Type_ = IntegerType.getI32(); 33 | private final Type voidType_ = Type.VoidType.getType(); 34 | //status word 35 | private boolean usingInt_ = false;//常量初始化要对表达式求值,并且用的Ident也要是常量 36 | private boolean globalInit_ = false;//初始化全局变量 37 | private boolean buildCall = false; //用于检查是否在生成 call 指令 38 | private boolean expInRel = false; //用于短路求值 39 | //用于回填 40 | private final BasicBlock breakMark = new BasicBlock(""); 41 | private final BasicBlock continueMark = new BasicBlock(""); 42 | //回填的用到的数据结构,每解析一层WhileStmt都会push一个ArrayList到Stack中 43 | //用于处理嵌套循环的break与continue 44 | Stack> backPatchRecord = new Stack<>(); 45 | /** 46 | * 我使用全局变量来在函数间进行参数的传递,这么做是为了方便理解代码 47 | * 你也可以把上面 `extends miniSysYBaseVisitor` 部分的 `Void`改成`Value` 48 | * 这样当你在调用函数 visitXXX(abcExp)的时候,能够通过对应的visit函数的返回值来在函数之间传递Value 49 | */ 50 | private Value tmp_; 51 | private int tmpInt_; 52 | private Type tmpTy_; 53 | private ArrayList tmpTyArr; 54 | private ArrayList tmpArr_; 55 | 56 | /** 57 | * program : compUnit ; 58 | *

59 | * 初始化 module,定义内置函数 60 | */ 61 | @Override 62 | public Void visitProgram(miniSysYParser.ProgramContext ctx) { 63 | builder.setModule(m); 64 | //先把库函数都加到 scope 里 65 | IntegerType i32Type = IntegerType.getI32(); 66 | Type.VoidType voidType = Type.VoidType.getType(); 67 | PointerType ptri32Type = PointerType.getPointTy(i32Type); 68 | ArrayList params_empty = new ArrayList<>(Collections.emptyList()); 69 | ArrayList params_int = new ArrayList<>(Collections.singletonList(i32Type_)); 70 | ArrayList params_array = new ArrayList<>(Collections.singletonList(ptri32Type)); 71 | ArrayList params_int_and_array = new ArrayList<>(Arrays.asList(i32Type, ptri32Type)); 72 | ArrayList param_memset = new ArrayList<>(Arrays.asList(ptri32Type, i32Type, i32Type)); 73 | scope.put("memset", builder.buildFunction("memset", new FunctionType(voidType_, param_memset), true)); 74 | ; 75 | scope.put("getint", builder.buildFunction("getint", new FunctionType(i32Type, params_empty), true)); 76 | scope.put("getarray", builder.buildFunction("getarray", new FunctionType(i32Type, params_array), true)); 77 | scope.put("getch", builder.buildFunction("getch", new FunctionType(i32Type, params_empty), true)); 78 | scope.put("putint", builder.buildFunction("putint", new FunctionType(voidType, params_int), true)); 79 | scope.put("putch", builder.buildFunction("putch", new FunctionType(voidType, params_int), true)); 80 | scope.put("putarray", builder.buildFunction("putarray", new FunctionType(voidType, params_int_and_array), true)); 81 | return super.visitProgram(ctx); 82 | } 83 | 84 | public Constant genConstArr(ArrayList dims, ArrayList inits) { 85 | var curDimLength = dims.get(0); 86 | var curDimArr = new ArrayList(); 87 | var length = inits.size() / curDimLength; 88 | var arrTy = i32Type_; 89 | if (length == 1) { 90 | for (int i = 0; i < curDimLength; i++) { 91 | curDimArr.add((Constant) inits.get(i)); 92 | } 93 | } else { 94 | for (int i = 0; i < curDimLength; i++) { 95 | //fix subDims and add to curDimArr 96 | curDimArr.add( 97 | genConstArr( 98 | new ArrayList<>(dims.subList(1, dims.size())), 99 | new ArrayList<>(inits.subList(length * i, length * (i + 1))))); 100 | 101 | } 102 | } 103 | 104 | for (int i = dims.size(); i > 0; i--) { 105 | arrTy = new ArrayType(arrTy, dims.get(i - 1)); 106 | } 107 | return builder.getConstantArray(arrTy, curDimArr); 108 | } 109 | 110 | // TODO: 2021/12/21 111 | @Override 112 | public Void visitConstDef(miniSysYParser.ConstDefContext ctx) { 113 | var name = ctx.IDENT().getText(); 114 | if (scope.top().get(name) != null) throw new RuntimeException("name already exists"); 115 | if (ctx.constExp().isEmpty()) {//not array 116 | if (ctx.constInitVal() != null) { 117 | visit(ctx.constInitVal()); 118 | scope.put(ctx.IDENT().getText(), tmp_); 119 | } 120 | } else { 121 | var arrTy = i32Type_; 122 | var dims = new ArrayList(); 123 | ctx.constExp().forEach(context -> { 124 | visit(context); 125 | dims.add(((Constant.ConstantInt) tmp_).getVal()); 126 | }); 127 | for (var i = dims.size(); i > 0; i--) arrTy = new ArrayType(arrTy, dims.get(i - 1)); 128 | if (scope.isGlobal()) { 129 | if (ctx.constInitVal() != null) { 130 | ctx.constInitVal().dimInfo_ = dims; 131 | globalInit_ = true; 132 | visit(ctx.constInitVal()); 133 | globalInit_ = false; 134 | var arr = tmpArr_; 135 | ArrayList g = new ArrayList<>(); 136 | arr.forEach(i -> g.add((Constant.ConstantInt) i)); 137 | var init = new Constant.ConstantArray(arrTy, g); 138 | var variable = builder.getGlobalVariable(ctx.IDENT().getText(), arrTy, init); 139 | variable.setConst(); 140 | scope.put(ctx.IDENT().getText(), variable); 141 | } else { 142 | var variable = builder.getGlobalVariable(ctx.IDENT().getText(), arrTy, null); 143 | scope.put(ctx.IDENT().getText(), variable); 144 | } 145 | } else { 146 | var allocatedArray = builder.buildAlloca(arrTy); 147 | scope.put(ctx.IDENT().getText(), allocatedArray); 148 | if (ctx.constInitVal() != null) { 149 | allocatedArray.setInit(); 150 | ctx.constInitVal().dimInfo_ = dims; 151 | visit(ctx.constInitVal()); 152 | var arr = tmpArr_; 153 | var ptr = builder.buildGEP(allocatedArray, new ArrayList<>() {{ 154 | add(CONST0); 155 | add(CONST0); 156 | }}); 157 | for (int i = 1; i < ctx.constInitVal().dimInfo_.size(); i++) { 158 | ptr = builder.buildGEP(ptr, new ArrayList<>() {{ 159 | add(CONST0); 160 | add(CONST0); 161 | }}); 162 | } 163 | for (int i = 0; i < arr.size(); i++) { 164 | if (i == 0) { 165 | builder.buildStore(arr.get(0), ptr); 166 | } else { 167 | int finalI = i; 168 | var p = builder.buildGEP(ptr, new ArrayList<>() {{ 169 | add(Constant.ConstantInt.get(finalI)); 170 | }}); 171 | builder.buildStore(arr.get(i), p); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | return null; 178 | } 179 | 180 | 181 | /** 182 | * constInitVal : constExp | (L_BRACE (constInitVal (COMMA constInitVal)*)? R_BRACE) ; 183 | */ 184 | @Override 185 | public Void visitConstInitVal(miniSysYParser.ConstInitValContext ctx) { 186 | if ((ctx.constExp() != null) && ctx.dimInfo_ == null) { 187 | visit(ctx.constExp()); 188 | } else { 189 | var curDimLength = ctx.dimInfo_.get(0); 190 | var sizeOfEachEle = 1;//每个元素(i32或者是数组)的长度 191 | var arrOfCurDim = new ArrayList();// 192 | //calculate Size of Ele in cur dim 193 | for (int i = 1; i < ctx.dimInfo_.size(); i++) { 194 | sizeOfEachEle *= ctx.dimInfo_.get(i); 195 | } 196 | for (ConstInitValContext constInitValContext : ctx.constInitVal()) { 197 | if (constInitValContext.constExp() == null) { 198 | var pos = arrOfCurDim.size(); 199 | for (int i = 0; i < (sizeOfEachEle - (pos % sizeOfEachEle)) % sizeOfEachEle; i++) { 200 | arrOfCurDim.add(CONST0);//长度不足一个ele的补0为一个ele长 201 | } 202 | constInitValContext.dimInfo_ = new ArrayList<>( 203 | ctx.dimInfo_.subList(1, ctx.dimInfo_.size())); 204 | visit(constInitValContext); 205 | arrOfCurDim.addAll(tmpArr_); 206 | } else { 207 | visit(constInitValContext); 208 | arrOfCurDim.add(tmp_); 209 | } 210 | } 211 | for (int i = arrOfCurDim.size(); i < curDimLength * sizeOfEachEle; i++) { 212 | arrOfCurDim.add(CONST0); 213 | }//长度不足一个ele*dimsize 的补0 214 | tmpArr_ = arrOfCurDim; 215 | } 216 | return null; 217 | } 218 | 219 | 220 | @Override 221 | public Void visitVarDef(miniSysYParser.VarDefContext ctx) { 222 | var varName = ctx.IDENT().getText(); 223 | if (scope.top().get(varName) != null) throw new RuntimeException("name exists"); 224 | if (ctx.constExp().isEmpty()) { 225 | if (scope.isGlobal()) { 226 | if (ctx.initVal() != null) { 227 | globalInit_ = true; 228 | visit(ctx.initVal()); 229 | globalInit_ = false; 230 | var initializer = (Constant) tmp_; 231 | var v = builder.getGlobalVariable(varName, i32Type_, initializer); 232 | scope.put(varName, v); 233 | } else { 234 | var initializer = CONST0; 235 | var v = builder.getGlobalVariable(varName, i32Type_, initializer); 236 | scope.put(varName, v); 237 | } 238 | } else { 239 | var allocator = builder.buildAlloca(i32Type_); 240 | scope.put(varName, allocator); 241 | if (ctx.initVal() != null) { 242 | visit(ctx.initVal()); 243 | builder.buildStore(tmp_, allocator); 244 | } 245 | } 246 | } else {//array 247 | var arrTy = i32Type_; 248 | var dims = new ArrayList(); 249 | ctx.constExp().forEach(context -> { 250 | visit(context); 251 | dims.add(((Constant.ConstantInt) tmp_).getVal()); 252 | }); 253 | for (var i = dims.size(); i > 0; i--) { 254 | arrTy = new ArrayType(arrTy, dims.get(i - 1)); 255 | } 256 | if (scope.isGlobal()) { 257 | if (ctx.initVal() != null) { 258 | ctx.initVal().dimInfo_ = dims; 259 | globalInit_ = true; 260 | visit(ctx.initVal()); 261 | globalInit_ = false; 262 | var arr = tmpArr_; 263 | ArrayList g = new ArrayList<>(); 264 | arr.forEach(i -> g.add(((Constant.ConstantInt) i))); 265 | var init = genConstArr(dims, arr); 266 | var glo = builder.getGlobalVariable(ctx.IDENT().getText(), arrTy, init); 267 | scope.put(ctx.IDENT().getText(), glo); 268 | } else { 269 | var v = builder.getGlobalVariable(ctx.IDENT().getText(), arrTy, null); 270 | scope.put(ctx.IDENT().getText(), v); 271 | } 272 | } else { 273 | var alloc = builder.buildAlloca(arrTy); 274 | scope.put(ctx.IDENT().getText(), alloc); 275 | if (ctx.initVal() != null && !ctx.initVal().initVal().isEmpty()) { 276 | alloc.setInit(); 277 | ctx.initVal().dimInfo_ = dims; 278 | visit(ctx.initVal()); 279 | var arr = tmpArr_; 280 | var pointer = builder.buildGEP(alloc, new ArrayList<>() {{ 281 | add(CONST0); 282 | add(CONST0); 283 | }}); 284 | for (var i = 1; i < dims.size(); i++) { 285 | pointer = builder.buildGEP(pointer, new ArrayList<>() {{ 286 | add(CONST0); 287 | add(CONST0); 288 | }}); 289 | } 290 | builder.buildCall(((Function) scope.find("memset")), new ArrayList<>(Arrays.asList(pointer, CONST0, Constant.ConstantInt.get(arr.size() * 4)))); 291 | for (int i = 0; i < arr.size(); i++) { 292 | var t = arr.get(i); 293 | if (t instanceof Constant.ConstantInt o && o.getVal() == 0) continue; 294 | if (i != 0) { 295 | int finalI = i; 296 | var ptr = builder.buildGEP(pointer, new ArrayList<>() {{ 297 | add(Constant.ConstantInt.get(finalI)); 298 | }}); 299 | builder.buildStore(t, ptr); 300 | } else { 301 | builder.buildStore(t, pointer); 302 | } 303 | } 304 | } else if (ctx.initVal() != null && ctx.initVal().initVal().isEmpty()) { 305 | var size = 1; 306 | for (Integer dim : dims) size *= dim; 307 | var pointer = builder.buildGEP(alloc, new ArrayList<>() {{ 308 | add(CONST0); 309 | add(CONST0); 310 | }}); 311 | for (int i = 1; i < dims.size(); i++) { 312 | pointer = builder.buildGEP(pointer, new ArrayList<>() {{ 313 | add(CONST0); 314 | add(CONST0); 315 | }}); 316 | } 317 | builder.buildCall((Function) scope.find("memset"), new ArrayList<>( 318 | Arrays.asList(pointer, CONST0, Constant.ConstantInt.get(size * 4)))); 319 | } 320 | } 321 | 322 | } 323 | return null; 324 | } 325 | 326 | @Override 327 | public Void visitInitVal(miniSysYParser.InitValContext ctx) { 328 | if (ctx.exp() != null && ctx.dimInfo_ == null) { 329 | if (globalInit_) { 330 | usingInt_ = true; 331 | visit(ctx.exp()); 332 | usingInt_ = false; 333 | tmp_ = Constant.ConstantInt.get(tmpInt_); 334 | } else visit(ctx.exp()); 335 | } else { 336 | var curDimLength = ctx.dimInfo_.get(0); 337 | var sizeOfEachELe = 1; 338 | var arrOfCurDim = new ArrayList(); 339 | for (int i = 1; i < ctx.dimInfo_.size(); i++) { 340 | sizeOfEachELe *= ctx.dimInfo_.get(i); 341 | } 342 | for (InitValContext context : ctx.initVal()) { 343 | if (context.exp() == null) { 344 | var pos = arrOfCurDim.size(); 345 | for (int i = 0; i < (sizeOfEachELe - (pos % sizeOfEachELe)) % sizeOfEachELe; i++) { 346 | arrOfCurDim.add(CONST0); 347 | } 348 | context.dimInfo_ = new ArrayList<>(ctx.dimInfo_.subList(1, ctx.dimInfo_.size())); 349 | visit(context); 350 | arrOfCurDim.addAll(tmpArr_); 351 | } else { 352 | if (globalInit_) { 353 | usingInt_ = true; 354 | visit(context.exp()); 355 | usingInt_ = false; 356 | tmp_ = Constant.ConstantInt.get(tmpInt_); 357 | } else { 358 | visit(context.exp()); 359 | } 360 | arrOfCurDim.add(tmp_); 361 | } 362 | } 363 | for (int i = arrOfCurDim.size(); i < curDimLength * sizeOfEachELe; i++) { 364 | arrOfCurDim.add(CONST0); 365 | } 366 | tmpArr_ = arrOfCurDim; 367 | } 368 | return null; 369 | } 370 | 371 | /** 372 | * funcDef : funcType IDENT L_PAREN funcFParams? R_PAREN block ; 373 | *

374 | * 初始化函数类型;初始化函数参数,并对参数插入 alloca 和 store;初始化基本块 375 | */ 376 | @Override 377 | public Void visitFuncDef(miniSysYParser.FuncDefContext ctx) { 378 | var funcName = ctx.IDENT().getText(); 379 | var retType = voidType_; 380 | var typeStr = ctx.getChild(0).getText(); 381 | if (typeStr.equals("int")) retType = i32Type_;//返回值类型 382 | ArrayList paramTyList = new ArrayList<>(); 383 | if (ctx.funcFParams() != null) { 384 | visit(ctx.funcFParams()); 385 | paramTyList.addAll(tmpTyArr); 386 | } 387 | FunctionType functionType = new FunctionType(retType, paramTyList); 388 | var func = builder.buildFunction(funcName, functionType, false); 389 | builder.setFunc(func); 390 | scope.put(funcName, func); 391 | var bb = builder.buildBB(func.name + "_ENTRY"); 392 | scope.addLayer(); 393 | scope.preEnter = true; 394 | builder.setInsertPoint(bb); 395 | if (ctx.funcFParams() != null) { 396 | ctx.funcFParams().initBB = true; 397 | visit(ctx.funcFParams()); 398 | } 399 | visit(ctx.block()); 400 | var last = builder.curBB().list.getLast().getVal(); 401 | if (last.tag != TAG.Br && last.tag != TAG.Ret) { 402 | if (func.type instanceof FunctionType o) { 403 | if (o.getRetTType().isVoidTy()) builder.buildRet(); 404 | if (o.getRetTType().isIntegerType()) builder.buildRet(CONST0); 405 | } 406 | } 407 | return null; 408 | } 409 | 410 | //这个context 会被 visit 两遍,一遍用来生成在编译时所需要的信息,一遍用来生成 IR 411 | @Override 412 | public Void visitFuncFParams(miniSysYParser.FuncFParamsContext ctx) { 413 | if (ctx.initBB) { 414 | ctx.initBB = false; 415 | var paramList = builder.curFunc().getParamList(); 416 | if (paramList.size() != 0) { 417 | for (int i = 0; i < ctx.funcFParam().size(); i++) { 418 | var context = ctx.funcFParam(i); 419 | if (!context.L_BRACKT().isEmpty()) {//这是个数组参数 420 | var dimList = new ArrayList(); 421 | var type = i32Type_; 422 | dimList.add(CONST0); 423 | for (int j = 0; j < context.exp().size(); j++) { 424 | usingInt_ = true; 425 | visit(context.exp(context.exp().size() - (j + 1))); 426 | usingInt_ = false; 427 | dimList.add(tmp_); 428 | type = new ArrayType(type, tmpInt_); 429 | } 430 | //alloca 一个 和 param 相同的 type 的值,然后把 param store 到这个 alloca 里 431 | var arrAlloca = builder.buildAlloca(new PointerType(type)); 432 | builder.buildStore(paramList.get(i), arrAlloca); 433 | scope.put(context.IDENT().getText(), arrAlloca); 434 | paramList.get(i).setBounds(dimList); 435 | } else {//int参数 436 | var alloca = builder.buildAlloca(i32Type_); 437 | builder.buildStore(paramList.get(i), alloca); 438 | scope.put(ctx.funcFParam().get(i).IDENT().getText(), alloca); 439 | } 440 | } 441 | } 442 | } else { 443 | //这个信息是保存给scope来提供给生成 call 指令使用的 444 | ArrayList types = new ArrayList<>(); 445 | ctx.funcFParam().forEach(param -> { 446 | visit(param); 447 | types.add(tmpTy_); 448 | }); 449 | tmpTyArr = types; 450 | } 451 | return null; 452 | } 453 | 454 | @Override 455 | public Void visitFuncFParam(miniSysYParser.FuncFParamContext ctx) { 456 | //这个 param 是数组 457 | if (!ctx.L_BRACKT().isEmpty()) { 458 | var type = i32Type_; 459 | for (int i = 0; i < ctx.exp().size(); i++) { 460 | usingInt_ = true; 461 | visit(ctx.exp(ctx.exp().size() - (i + 1))); 462 | usingInt_ = false; 463 | type = new ArrayType(type, tmpInt_); 464 | } 465 | tmpTy_ = new PointerType(type); 466 | } else {//这个param是int值 467 | tmpTy_ = i32Type_; 468 | } 469 | return null; 470 | } 471 | 472 | @Override 473 | public Void visitBlock(miniSysYParser.BlockContext ctx) { 474 | scope.addLayer(); 475 | ctx.blockItem().forEach(this::visit); 476 | scope.popLayer(); 477 | return null; 478 | } 479 | 480 | @Override 481 | public Void visitAssignStmt(miniSysYParser.AssignStmtContext ctx) { 482 | visit(ctx.lVal()); 483 | var rhs = tmp_; 484 | visit(ctx.exp()); 485 | var lhs = tmp_; 486 | builder.buildStore(lhs, rhs); 487 | return null; 488 | } 489 | 490 | /** 491 | * conditionStmt : IF_KW L_PAREN cond R_PAREN stmt (ELSE_KW stmt)? ; 492 | */ 493 | @Override 494 | public Void visitConditionStmt(miniSysYParser.ConditionStmtContext ctx) { 495 | var parentBB = builder.curBB(); 496 | var trueBlock = builder.buildBB("_then"); 497 | var nxtblock = builder.buildBB("_nxtBLock"); 498 | var falseBlock = ctx.ELSE_KW() == null ? nxtblock : builder.buildBB("_else"); 499 | var ifEndWithRet = false; 500 | ctx.cond().falseblock = falseBlock; 501 | ctx.cond().trueblock = trueBlock; 502 | visit(ctx.cond()); 503 | builder.setInsertPoint(trueBlock); 504 | visit(ctx.stmt(0)); 505 | builder.buildBr(nxtblock); 506 | //解析完stmt后的最后一个块的末尾语句是ret(), 507 | //在 有 if 有 else 且 if 条件块和 else 条件块的最后一条语句都是 ret 的时候,就将nxtblock删去,不然会产生一个空的块 508 | if (builder.curBB().list.getLast().getVal() instanceof Ret) ifEndWithRet = true; 509 | if (ctx.ELSE_KW() != null) { 510 | builder.setInsertPoint(falseBlock); 511 | visit(ctx.stmt(1)); 512 | builder.buildBr(nxtblock); 513 | if (ifEndWithRet && builder.curBB().list.getLast().getVal() instanceof Ret) nxtblock.node.removeSelf(); 514 | } 515 | builder.setInsertPoint(nxtblock); 516 | return null; 517 | } 518 | 519 | 520 | @Override 521 | public Void visitWhileStmt(miniSysYParser.WhileStmtContext ctx) { 522 | var parentBB = builder.curBB(); 523 | //如果最后的时候输出正常,这些名字是不会出现在导出的文件里的,如果输出不正常,这些名字可以辅助debug 524 | var whileCondEntryBlock = builder.buildBB("_whileCondition"); 525 | var trueBlock = builder.buildBB("_body"); 526 | var nxtBlock = builder.buildBB("_nxtBlock"); 527 | backPatchRecord.push(new ArrayList<>());//每解析一个whileStmt都push一层进去,记录这个while的break和continue 528 | builder.setInsertPoint(parentBB); 529 | builder.buildBr(whileCondEntryBlock);//在parentBB末尾插入一个跳转到whileCond的Br 530 | ctx.cond().falseblock = nxtBlock; 531 | ctx.cond().trueblock = trueBlock; 532 | builder.setInsertPoint(whileCondEntryBlock); 533 | visit(ctx.cond()); 534 | builder.setInsertPoint(trueBlock); 535 | visit(ctx.stmt()); 536 | builder.buildBr(whileCondEntryBlock); 537 | for (Br br : backPatchRecord.pop()) { 538 | if (br.getOP(0) == breakMark) { 539 | br.setOperand(nxtBlock, 0); 540 | } else if (br.getOP(0) == continueMark) { 541 | br.setOperand(whileCondEntryBlock, 0); 542 | } 543 | } 544 | builder.setInsertPoint(nxtBlock); 545 | return null; 546 | } 547 | 548 | @Override 549 | public Void visitBreakStmt(miniSysYParser.BreakStmtContext ctx) { 550 | backPatchRecord.peek().add(builder.buildBr(continueMark)); 551 | return null; 552 | } 553 | 554 | @Override 555 | public Void visitContinueStmt(miniSysYParser.ContinueStmtContext ctx) { 556 | backPatchRecord.peek().add(builder.buildBr(breakMark)); 557 | return null; 558 | } 559 | 560 | /** 561 | * returnStmt : RETURN_KW (exp)? SEMICOLON ; 562 | */ 563 | @Override 564 | public Void visitReturnStmt(miniSysYParser.ReturnStmtContext ctx) { 565 | if (ctx.exp() != null) { 566 | //有返回值 567 | visit(ctx.exp()); 568 | builder.buildRet(tmp_); 569 | } else { 570 | //没有返回值 571 | builder.buildRet(); 572 | } 573 | return null; 574 | } 575 | 576 | /** 577 | * lVal : IDENT (L_BRACKT exp R_BRACKT)* ; 578 | */ 579 | @Override 580 | public Void visitLVal(miniSysYParser.LValContext ctx) { 581 | var name = ctx.IDENT().getText(); 582 | var val = scope.find(name); 583 | if (val == null) throw new RuntimeException("undefined value name :" + name); 584 | if (val.type.isIntegerType()) {//是在编译时就知道值的 int 类型, 585 | tmp_ = val; 586 | return null; 587 | } 588 | boolean INT = false, PTR = false, ARR = false; 589 | if (val.type.isPointerTy()) { 590 | //alloca i32 591 | INT = ((PointerType) val.type).getContained().isIntegerType(); 592 | //函数传参传入的数组 593 | PTR = ((PointerType) val.type).getContained().isPointerTy(); 594 | //指向别的数组 595 | ARR = ((PointerType) val.type).getContained().isArrayTy(); 596 | } 597 | if (INT) { 598 | if (ctx.exp().isEmpty()) { 599 | tmp_ = val; 600 | return null; 601 | } else { 602 | for (ExpContext expContext : ctx.exp()) { 603 | visit(expContext); 604 | var fromExp = tmp_; 605 | val = builder.getGEP(val, new ArrayList<>() {{ 606 | add(fromExp); 607 | }}); 608 | } 609 | tmp_ = val; 610 | return null; 611 | } 612 | } 613 | if (PTR) { 614 | if (ctx.exp().isEmpty()) { 615 | //作为参数传递给 Call 616 | tmp_ = builder.buildLoad(((PointerType) val.type).getContained(), val); 617 | } else { 618 | PointerType allocatedTy = (PointerType) val.type; 619 | var containedTy = (PointerType) allocatedTy.getContained(); 620 | var load = builder.buildLoad(containedTy, val); 621 | visit(ctx.exp(0)); 622 | var gep = builder.buildGEP(load, new ArrayList<>() {{ 623 | add(tmp_); 624 | }}); 625 | for (int i = 1; i < ctx.exp().size(); i++) { 626 | visit(ctx.exp(i)); 627 | gep = builder.buildGEP(gep, new ArrayList<>() {{ 628 | add(CONST0); 629 | add(tmp_); 630 | }}); 631 | } 632 | tmp_ = gep; 633 | } 634 | } 635 | if (ARR) { 636 | if (ctx.exp().isEmpty()) { 637 | tmp_ = builder.buildGEP(val, new ArrayList<>() {{ 638 | add(CONST0); 639 | add(CONST0); 640 | }}); 641 | } else { 642 | for (ExpContext expContext : ctx.exp()) { 643 | visit(expContext); 644 | val = builder.buildGEP(val, new ArrayList<>() {{ 645 | add(CONST0); 646 | add(tmp_); 647 | }}); 648 | } 649 | tmp_ = val; 650 | } 651 | } 652 | return null; 653 | } 654 | 655 | @Override 656 | public Void visitPrimaryExp(miniSysYParser.PrimaryExpContext ctx) { 657 | if (usingInt_) { 658 | if (ctx.exp() != null) visit(ctx.exp()); 659 | if (ctx.lVal() != null) { 660 | visit(ctx.lVal()); 661 | tmpInt_ = ((Constant.ConstantInt) tmp_).getVal(); 662 | } 663 | if (ctx.number() != null) visit(ctx.number()); 664 | } else { 665 | if (ctx.exp() != null) visit(ctx.exp()); 666 | if (ctx.lVal() != null) { 667 | if (buildCall) {//正在生成 call 指令 668 | buildCall = false; 669 | visit(ctx.lVal()); 670 | return null; 671 | } else { 672 | visit(ctx.lVal()); 673 | if (tmp_.type.isIntegerType()) return null;//如果是Integer类型的就不用load 674 | //要Load的类型是 Integer* 675 | tmp_ = builder.buildLoad(((PointerType) tmp_.type).getContained(), tmp_); 676 | } 677 | } 678 | if (ctx.number() != null) visit(ctx.number()); 679 | } 680 | return null; 681 | } 682 | 683 | @Override 684 | public Void visitNumber(miniSysYParser.NumberContext ctx) { 685 | visit(ctx.intConst()); 686 | if (!usingInt_) tmp_ = builder.getConstantInt(tmpInt_); 687 | return null; 688 | } 689 | 690 | 691 | @Override 692 | public Void visitIntConst(miniSysYParser.IntConstContext ctx) { 693 | if (ctx.DECIMAL_CONST() != null) tmpInt_ = (new BigInteger(ctx.DECIMAL_CONST().getText(), 10).intValue()); 694 | if (ctx.HEXADECIMAL_CONST() != null) 695 | tmpInt_ = (new BigInteger(ctx.HEXADECIMAL_CONST().getText().substring(2), 16).intValue()); 696 | if (ctx.OCTAL_CONST() != null) tmpInt_ = (new BigInteger(ctx.OCTAL_CONST().getText(), 8)).intValue(); 697 | return null; 698 | } 699 | 700 | /** 701 | * unaryExp 702 | * : primaryExp 703 | * | callee 704 | * | (unaryOp unaryExp) 705 | * ; 706 | */ 707 | @Override 708 | public Void visitUnaryExp(miniSysYParser.UnaryExpContext ctx) { 709 | if (usingInt_) {//如果需要折叠常量 710 | if (ctx.unaryExp() != null) {//如果有unaryExp作为子结点,就先visit这个子结点 711 | visit(ctx.unaryExp()); 712 | //负号,正号和取反 713 | if (ctx.unaryOp().MINUS() != null) tmpInt_ = -tmpInt_; 714 | if (ctx.unaryOp().PLUS() != null) tmpInt_ = +tmpInt_; 715 | if (ctx.unaryOp().NOT() != null) tmpInt_ = tmpInt_ == 0 ? 1 : 0; 716 | } else { 717 | if (ctx.primaryExp() != null) return visit(ctx.primaryExp()); 718 | if (ctx.callee() != null) throw new RuntimeException("Func call in constExp"); 719 | } 720 | } else { 721 | if (ctx.unaryExp() != null) { 722 | visit(ctx.unaryExp()); 723 | if (tmp_.type.isI1()) builder.buildZext(tmp_); 724 | if (ctx.unaryOp().NOT() != null) tmp_ = builder.buildBinary(Inst.TAG.Eq, CONST0, tmp_); 725 | if (ctx.unaryOp().PLUS() != null) { 726 | //do nothing; 727 | } 728 | if (ctx.unaryOp().MINUS() != null) { 729 | if (tmp_.type.isI1()) tmp_ = builder.buildZext(tmp_); 730 | tmp_ = builder.buildBinary(Inst.TAG.Sub, CONST0, tmp_); 731 | } 732 | } 733 | if (ctx.callee() != null) { 734 | visit(ctx.callee()); 735 | } 736 | if (ctx.primaryExp() != null) { 737 | visit(ctx.primaryExp()); 738 | } 739 | } 740 | return null; 741 | } 742 | 743 | /** 744 | * 函数调用 745 | * callee : IDENT L_PAREN funcRParams? R_PAREN ; 746 | */ 747 | @Override 748 | public Void visitCallee(miniSysYParser.CalleeContext ctx) { 749 | //函数 750 | var func = scope.find(ctx.IDENT().getText()); 751 | //实参 752 | var args = new ArrayList(); 753 | List argsCtx; 754 | if (ctx.funcRParams() != null && func instanceof Function f) { 755 | argsCtx = ctx.funcRParams().param(); 756 | var paramTys = ((FunctionType) func.type).getParamsTypes(); 757 | for (int i = 0; i < argsCtx.size(); i++) { 758 | var argument = argsCtx.get(i); 759 | var paramTy = paramTys.get(i); 760 | buildCall = !paramTy.isIntegerType(); 761 | visit(argument.exp()); 762 | buildCall = false; 763 | args.add(tmp_); 764 | } 765 | } 766 | tmp_ = builder.buildCall((Function) func, args); 767 | return null; 768 | } 769 | 770 | /** 771 | * mulExp : unaryExp (mulOp unaryExp)* ; 772 | */ 773 | @Override 774 | public Void visitMulExp(miniSysYParser.MulExpContext ctx) { 775 | if (usingInt_) { 776 | visit(ctx.unaryExp(0)); 777 | var s = tmpInt_; 778 | for (var i = 1; i < ctx.unaryExp().size(); i++) { 779 | visit(ctx.unaryExp(i)); 780 | if (ctx.mulOp(i - 1).MUL() != null) s *= tmpInt_; 781 | if (ctx.mulOp(i - 1).DIV() != null) s /= tmpInt_; 782 | if (ctx.mulOp(i - 1).MOD() != null) s %= tmpInt_; 783 | } 784 | tmpInt_ = s; 785 | } else { 786 | visit(ctx.unaryExp(0)); 787 | var lhs = tmp_; 788 | for (int i = 1; i < ctx.unaryExp().size(); i++) { 789 | visit(ctx.unaryExp(i)); 790 | var rhs = tmp_; 791 | if (lhs.type.isI1()) lhs = builder.buildZext(lhs); 792 | if (rhs.type.isI1()) rhs = builder.buildZext(rhs); 793 | if (ctx.mulOp(i - 1).MUL() != null) lhs = builder.buildBinary(TAG.Mul, lhs, rhs); 794 | if (ctx.mulOp(i - 1).DIV() != null) lhs = builder.buildBinary(TAG.Div, lhs, rhs); 795 | if (ctx.mulOp(i - 1).MOD() != null) { 796 | //x%y=x - (x/y)*y 797 | var a = builder.buildBinary(TAG.Div, lhs, rhs); 798 | var b = builder.buildBinary(TAG.Mul, a, rhs); 799 | lhs = builder.buildBinary(TAG.Sub, lhs, b); 800 | } 801 | } 802 | tmp_ = lhs; 803 | } 804 | return null; 805 | 806 | 807 | } 808 | 809 | /** 810 | * @value : 811 | *

812 | * addExp : mulExp (addOp mulExp)* ; 813 | */ 814 | @Override 815 | public Void visitAddExp(miniSysYParser.AddExpContext ctx) { 816 | if (usingInt_) {//所有值包括ident都必须是常量 817 | visit(ctx.mulExp(0)); 818 | var s = tmpInt_; 819 | for (var i = 1; i < ctx.mulExp().size(); i++) { 820 | visit(ctx.mulExp(i)); 821 | if (ctx.addOp(i - 1).PLUS() != null) s += tmpInt_; 822 | if (ctx.addOp(i - 1).MINUS() != null) s -= tmpInt_; 823 | } 824 | tmpInt_ = s; 825 | return null; 826 | } else { 827 | visit(ctx.mulExp(0)); 828 | var lhs = tmp_; 829 | for (int i = 1; i < ctx.mulExp().size(); i++) { 830 | visit(ctx.mulExp(i)); 831 | var rhs = tmp_; 832 | if (lhs.type.isI1()) lhs = builder.buildZext(lhs); 833 | if (rhs.type.isI1()) rhs = builder.buildZext(rhs); 834 | if (ctx.addOp(i - 1).PLUS() != null) lhs = builder.buildBinary(TAG.Add, lhs, rhs); 835 | if (ctx.addOp(i - 1).MINUS() != null) lhs = builder.buildBinary(TAG.Sub, lhs, rhs); 836 | } 837 | tmp_ = lhs; 838 | } 839 | return null; 840 | } 841 | 842 | /** 843 | * relExp : addExp (relOp addExp)* ; 844 | */ 845 | @Override 846 | public Void visitRelExp(miniSysYParser.RelExpContext ctx) { 847 | visit(ctx.addExp(0)); 848 | var lhs = tmp_; 849 | for (int i = 1; i < ctx.addExp().size(); i++) { 850 | expInRel = false; 851 | visit(ctx.addExp(i)); 852 | var rhs = tmp_; 853 | if (ctx.relOp(i - 1).LE() != null) lhs = builder.buildBinary(TAG.Le, lhs, rhs); 854 | if (ctx.relOp(i - 1).GE() != null) lhs = builder.buildBinary(TAG.Ge, lhs, rhs); 855 | if (ctx.relOp(i - 1).GT() != null) lhs = builder.buildBinary(TAG.Gt, lhs, rhs); 856 | if (ctx.relOp(i - 1).LT() != null) lhs = builder.buildBinary(TAG.Lt, lhs, rhs); 857 | } 858 | tmp_ = lhs; 859 | return null; 860 | } 861 | 862 | /** 863 | * eqExp : relExp (eqOp relExp)* ; 864 | */ 865 | @Override 866 | public Void visitEqExp(miniSysYParser.EqExpContext ctx) { 867 | visit(ctx.relExp(0)); 868 | var lhs = tmp_; 869 | for (int i = 1; i < ctx.relExp().size(); i++) { 870 | expInRel = false; 871 | visit(ctx.relExp(i)); 872 | if (ctx.eqOp(i - 1).EQ() != null) lhs = builder.buildBinary(TAG.Eq, lhs, tmp_); 873 | if (ctx.eqOp(i - 1).NEQ() != null) lhs = builder.buildBinary(TAG.Ne, lhs, tmp_); 874 | } 875 | tmp_ = lhs; 876 | return null; 877 | } 878 | 879 | @Override 880 | public Void visitLAndExp(miniSysYParser.LAndExpContext ctx) { 881 | ctx.eqExp().forEach(exp -> { 882 | var newBB = builder.buildBB(""); 883 | expInRel = true; 884 | visit(exp); 885 | if (expInRel) { 886 | expInRel = false; 887 | tmp_ = builder.buildBinary(TAG.Ne, tmp_, CONST0); 888 | } 889 | builder.buildBr(tmp_, newBB, ctx.falseblock); 890 | builder.setInsertPoint(newBB); 891 | }); 892 | builder.buildBr(ctx.trueblock); 893 | return null; 894 | } 895 | 896 | @Override 897 | public Void visitLOrExp(miniSysYParser.LOrExpContext ctx) { 898 | ctx.lAndExp(0).isFirstBlock = true; 899 | for (int i = 0; i < ctx.lAndExp().size() - 1; i++) { 900 | var newBB = builder.buildBB(""); 901 | ctx.lAndExp(i).trueblock = ctx.trueblock;//向下传递继承属性,记录要跳转的块从而实现短路求值 902 | ctx.lAndExp(i).falseblock = newBB; 903 | visit(ctx.lAndExp(i)); 904 | builder.setInsertPoint(newBB); 905 | } 906 | ctx.lAndExp(ctx.lAndExp().size() - 1).falseblock = ctx.falseblock; 907 | ctx.lAndExp(ctx.lAndExp().size() - 1).trueblock = ctx.trueblock; 908 | visit(ctx.lAndExp(ctx.lAndExp().size() - 1)); 909 | return null; 910 | } 911 | 912 | @Override 913 | public Void visitCond(miniSysYParser.CondContext ctx) { 914 | ctx.lOrExp().falseblock = ctx.falseblock; 915 | ctx.lOrExp().trueblock = ctx.trueblock; 916 | visit(ctx.lOrExp()); 917 | return null; 918 | } 919 | 920 | /** 921 | * constExp : addExp ; 922 | *

923 | * tmpint_ -> res of exp 924 | *

925 | * 表达式求和 926 | */ 927 | @Override 928 | public Void visitConstExp(miniSysYParser.ConstExpContext ctx) { 929 | usingInt_ = true; 930 | visit(ctx.addExp()); 931 | tmp_ = builder.getConstantInt(tmpInt_); 932 | usingInt_ = false; 933 | return null; 934 | } 935 | 936 | } 937 | -------------------------------------------------------------------------------- /src/frontend/miniSysY.g4: -------------------------------------------------------------------------------- 1 | grammar miniSysY; 2 | 3 | program 4 | : compUnit 5 | ; 6 | 7 | compUnit 8 | : (funcDef | decl)+ 9 | ; 10 | 11 | decl 12 | : constDecl 13 | | varDecl 14 | ; 15 | 16 | constDecl 17 | : CONST_KW bType constDef (COMMA constDef)* SEMICOLON 18 | ; 19 | 20 | bType 21 | : INT_KW 22 | ; 23 | 24 | constDef 25 | : IDENT (L_BRACKT constExp R_BRACKT)* ASSIGN constInitVal 26 | ; 27 | 28 | constInitVal 29 | : constExp 30 | | (L_BRACE (constInitVal (COMMA constInitVal)*)? R_BRACE) 31 | ; 32 | 33 | varDecl 34 | : bType varDef (COMMA varDef)* SEMICOLON 35 | ; 36 | 37 | varDef 38 | : IDENT (L_BRACKT constExp R_BRACKT)* (ASSIGN initVal)? 39 | ; 40 | 41 | initVal 42 | : exp 43 | | (L_BRACE (initVal (COMMA initVal)*)? R_BRACE) 44 | ; 45 | 46 | funcDef 47 | : funcType IDENT L_PAREN funcFParams? R_PAREN block 48 | ; 49 | 50 | funcType 51 | : VOID_KW 52 | | INT_KW 53 | ; 54 | 55 | funcFParams 56 | : funcFParam (COMMA funcFParam)* 57 | ; 58 | 59 | funcFParam 60 | : bType IDENT (L_BRACKT R_BRACKT (L_BRACKT exp R_BRACKT)*)? 61 | ; 62 | 63 | block 64 | : L_BRACE blockItem* R_BRACE 65 | ; 66 | 67 | blockItem 68 | : constDecl 69 | | varDecl 70 | | stmt 71 | ; 72 | 73 | stmt 74 | : assignStmt 75 | | expStmt 76 | | block 77 | | conditionStmt 78 | | whileStmt 79 | | breakStmt 80 | | continueStmt 81 | | returnStmt 82 | ; 83 | 84 | assignStmt 85 | : lVal ASSIGN exp SEMICOLON 86 | ; 87 | 88 | expStmt 89 | : exp? SEMICOLON 90 | ; 91 | 92 | conditionStmt 93 | : IF_KW L_PAREN cond R_PAREN stmt (ELSE_KW stmt)? 94 | ; 95 | 96 | whileStmt 97 | : WHILE_KW L_PAREN cond R_PAREN stmt 98 | ; 99 | 100 | breakStmt 101 | : BREAK_KW SEMICOLON 102 | ; 103 | 104 | continueStmt 105 | : CONTINUE_KW SEMICOLON 106 | ; 107 | 108 | returnStmt 109 | : RETURN_KW (exp)? SEMICOLON 110 | ; 111 | 112 | exp 113 | : addExp 114 | ; 115 | 116 | cond 117 | : lOrExp 118 | ; 119 | 120 | lVal 121 | : IDENT (L_BRACKT exp R_BRACKT)* 122 | ; 123 | 124 | primaryExp 125 | : (L_PAREN exp R_PAREN) 126 | | lVal 127 | | number 128 | ; 129 | 130 | number 131 | : intConst 132 | ; 133 | 134 | intConst 135 | : DECIMAL_CONST 136 | | OCTAL_CONST 137 | | HEXADECIMAL_CONST 138 | ; 139 | 140 | unaryExp 141 | : primaryExp 142 | | callee 143 | | (unaryOp unaryExp) 144 | ; 145 | 146 | callee 147 | : IDENT L_PAREN funcRParams? R_PAREN 148 | ; 149 | 150 | unaryOp 151 | : PLUS 152 | | MINUS 153 | | NOT 154 | ; 155 | 156 | funcRParams 157 | : param (COMMA param)* 158 | ; 159 | 160 | param 161 | : exp 162 | | STRING 163 | ; 164 | 165 | mulExp 166 | : unaryExp (mulOp unaryExp)* 167 | ; // eliminate left-recursive 168 | 169 | mulOp 170 | : MUL 171 | | DIV 172 | | MOD 173 | ; 174 | 175 | addExp 176 | : mulExp (addOp mulExp)* 177 | ; // eliminate left-recursive 178 | 179 | addOp 180 | : PLUS 181 | | MINUS 182 | ; 183 | 184 | relExp 185 | : addExp (relOp addExp)* 186 | ; // eliminate left-recursive 187 | 188 | relOp 189 | : LT 190 | | GT 191 | | LE 192 | | GE 193 | ; 194 | 195 | eqExp 196 | : relExp (eqOp relExp)* 197 | ; 198 | 199 | eqOp 200 | : EQ 201 | | NEQ 202 | ; 203 | 204 | lAndExp 205 | : eqExp (AND eqExp)* 206 | ; 207 | 208 | lOrExp 209 | : lAndExp (OR lAndExp)* 210 | ; 211 | 212 | constExp 213 | : addExp 214 | ; 215 | 216 | CONST_KW 217 | : 'const' 218 | ; 219 | 220 | INT_KW 221 | : 'int' 222 | ; 223 | 224 | VOID_KW 225 | : 'void' 226 | ; 227 | 228 | IF_KW 229 | : 'if' 230 | ; 231 | 232 | ELSE_KW 233 | : 'else' 234 | ; 235 | 236 | WHILE_KW 237 | : 'while' 238 | ; 239 | 240 | BREAK_KW 241 | : 'break' 242 | ; 243 | 244 | CONTINUE_KW 245 | : 'continue' 246 | ; 247 | 248 | RETURN_KW 249 | : 'return' 250 | ; 251 | 252 | IDENT 253 | : [_a-zA-Z] 254 | | [_a-zA-Z] [_a-zA-Z0-9]+ 255 | ; 256 | 257 | DECIMAL_CONST 258 | : [1-9] 259 | | [1-9] [0-9]+ 260 | ; 261 | 262 | OCTAL_CONST 263 | : '0' 264 | | ('0' [0-7]+) 265 | ; 266 | 267 | HEXADECIMAL_CONST 268 | : ('0x' | '0X') [a-fA-F0-9]+ 269 | ; 270 | 271 | STRING 272 | : DOUBLE_QUOTE REGULAR_CHAR*? DOUBLE_QUOTE 273 | ; 274 | 275 | fragment REGULAR_CHAR 276 | : (ESC | .) 277 | ; 278 | 279 | fragment ESC 280 | : '\\"' | '\\\\' 281 | ; 282 | 283 | PLUS 284 | : '+' 285 | ; 286 | 287 | MINUS 288 | : '-' 289 | ; 290 | 291 | NOT 292 | : '!' 293 | ; 294 | 295 | MUL 296 | : '*' 297 | ; 298 | 299 | DIV 300 | : '/' 301 | ; 302 | 303 | MOD 304 | : '%' 305 | ; 306 | 307 | ASSIGN 308 | : '=' 309 | ; 310 | 311 | EQ 312 | : '==' 313 | ; 314 | 315 | NEQ 316 | : '!=' 317 | ; 318 | 319 | LT 320 | : '<' 321 | ; 322 | 323 | GT 324 | : '>' 325 | ; 326 | 327 | LE 328 | : '<=' 329 | ; 330 | 331 | GE 332 | : '>=' 333 | ; 334 | 335 | AND 336 | : '&&' 337 | ; 338 | 339 | OR 340 | : '||' 341 | ; 342 | 343 | L_PAREN 344 | : '(' 345 | ; 346 | 347 | R_PAREN 348 | : ')' 349 | ; 350 | 351 | L_BRACE 352 | : '{' 353 | ; 354 | 355 | R_BRACE 356 | : '}' 357 | ; 358 | 359 | L_BRACKT 360 | : '[' 361 | ; 362 | 363 | R_BRACKT 364 | : ']' 365 | ; 366 | 367 | COMMA 368 | : ',' 369 | ; 370 | 371 | SEMICOLON 372 | : ';' 373 | ; 374 | 375 | DOUBLE_QUOTE 376 | : '"' 377 | ; 378 | 379 | WS 380 | : [ \r\n\t]+ -> skip 381 | ; 382 | 383 | LINE_COMMENT 384 | : '//' ~ [\r\n]* -> skip 385 | ; 386 | 387 | MULTILINE_COMMENT 388 | : '/*' .*? '*/' -> skip 389 | ; 390 | -------------------------------------------------------------------------------- /src/frontend/miniSysYBaseVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from miniSysY.g4 by ANTLR 4.9.2 2 | package frontend; 3 | 4 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; 5 | 6 | /** 7 | * This class provides an empty implementation of {@link miniSysYVisitor}, 8 | * which can be extended to create a visitor which only needs to handle a subset 9 | * of the available methods. 10 | * 11 | * @param The return type of the visit operation. Use {@link Void} for 12 | * operations with no return type. 13 | */ 14 | public class miniSysYBaseVisitor extends AbstractParseTreeVisitor implements miniSysYVisitor { 15 | /** 16 | * {@inheritDoc} 17 | * 18 | *

The default implementation returns the result of calling 19 | * {@link #visitChildren} on {@code ctx}.

20 | */ 21 | @Override 22 | public T visitProgram(miniSysYParser.ProgramContext ctx) {return visitChildren(ctx);} 23 | 24 | /** 25 | * {@inheritDoc} 26 | * 27 | *

The default implementation returns the result of calling 28 | * {@link #visitChildren} on {@code ctx}.

29 | */ 30 | @Override 31 | public T visitCompUnit(miniSysYParser.CompUnitContext ctx) {return visitChildren(ctx);} 32 | 33 | /** 34 | * {@inheritDoc} 35 | * 36 | *

The default implementation returns the result of calling 37 | * {@link #visitChildren} on {@code ctx}.

38 | */ 39 | @Override 40 | public T visitDecl(miniSysYParser.DeclContext ctx) {return visitChildren(ctx);} 41 | 42 | /** 43 | * {@inheritDoc} 44 | * 45 | *

The default implementation returns the result of calling 46 | * {@link #visitChildren} on {@code ctx}.

47 | */ 48 | @Override 49 | public T visitConstDecl(miniSysYParser.ConstDeclContext ctx) {return visitChildren(ctx);} 50 | 51 | /** 52 | * {@inheritDoc} 53 | * 54 | *

The default implementation returns the result of calling 55 | * {@link #visitChildren} on {@code ctx}.

56 | */ 57 | @Override 58 | public T visitBType(miniSysYParser.BTypeContext ctx) {return visitChildren(ctx);} 59 | 60 | /** 61 | * {@inheritDoc} 62 | * 63 | *

The default implementation returns the result of calling 64 | * {@link #visitChildren} on {@code ctx}.

65 | */ 66 | @Override 67 | public T visitConstDef(miniSysYParser.ConstDefContext ctx) {return visitChildren(ctx);} 68 | 69 | /** 70 | * {@inheritDoc} 71 | * 72 | *

The default implementation returns the result of calling 73 | * {@link #visitChildren} on {@code ctx}.

74 | */ 75 | @Override 76 | public T visitConstInitVal(miniSysYParser.ConstInitValContext ctx) {return visitChildren(ctx);} 77 | 78 | /** 79 | * {@inheritDoc} 80 | * 81 | *

The default implementation returns the result of calling 82 | * {@link #visitChildren} on {@code ctx}.

83 | */ 84 | @Override 85 | public T visitVarDecl(miniSysYParser.VarDeclContext ctx) {return visitChildren(ctx);} 86 | 87 | /** 88 | * {@inheritDoc} 89 | * 90 | *

The default implementation returns the result of calling 91 | * {@link #visitChildren} on {@code ctx}.

92 | */ 93 | @Override 94 | public T visitVarDef(miniSysYParser.VarDefContext ctx) {return visitChildren(ctx);} 95 | 96 | /** 97 | * {@inheritDoc} 98 | * 99 | *

The default implementation returns the result of calling 100 | * {@link #visitChildren} on {@code ctx}.

101 | */ 102 | @Override 103 | public T visitInitVal(miniSysYParser.InitValContext ctx) {return visitChildren(ctx);} 104 | 105 | /** 106 | * {@inheritDoc} 107 | * 108 | *

The default implementation returns the result of calling 109 | * {@link #visitChildren} on {@code ctx}.

110 | */ 111 | @Override 112 | public T visitFuncDef(miniSysYParser.FuncDefContext ctx) {return visitChildren(ctx);} 113 | 114 | /** 115 | * {@inheritDoc} 116 | * 117 | *

The default implementation returns the result of calling 118 | * {@link #visitChildren} on {@code ctx}.

119 | */ 120 | @Override 121 | public T visitFuncType(miniSysYParser.FuncTypeContext ctx) {return visitChildren(ctx);} 122 | 123 | /** 124 | * {@inheritDoc} 125 | * 126 | *

The default implementation returns the result of calling 127 | * {@link #visitChildren} on {@code ctx}.

128 | */ 129 | @Override 130 | public T visitFuncFParams(miniSysYParser.FuncFParamsContext ctx) {return visitChildren(ctx);} 131 | 132 | /** 133 | * {@inheritDoc} 134 | * 135 | *

The default implementation returns the result of calling 136 | * {@link #visitChildren} on {@code ctx}.

137 | */ 138 | @Override 139 | public T visitFuncFParam(miniSysYParser.FuncFParamContext ctx) {return visitChildren(ctx);} 140 | 141 | /** 142 | * {@inheritDoc} 143 | * 144 | *

The default implementation returns the result of calling 145 | * {@link #visitChildren} on {@code ctx}.

146 | */ 147 | @Override 148 | public T visitBlock(miniSysYParser.BlockContext ctx) {return visitChildren(ctx);} 149 | 150 | /** 151 | * {@inheritDoc} 152 | * 153 | *

The default implementation returns the result of calling 154 | * {@link #visitChildren} on {@code ctx}.

155 | */ 156 | @Override 157 | public T visitBlockItem(miniSysYParser.BlockItemContext ctx) {return visitChildren(ctx);} 158 | 159 | /** 160 | * {@inheritDoc} 161 | * 162 | *

The default implementation returns the result of calling 163 | * {@link #visitChildren} on {@code ctx}.

164 | */ 165 | @Override 166 | public T visitStmt(miniSysYParser.StmtContext ctx) {return visitChildren(ctx);} 167 | 168 | /** 169 | * {@inheritDoc} 170 | * 171 | *

The default implementation returns the result of calling 172 | * {@link #visitChildren} on {@code ctx}.

173 | */ 174 | @Override 175 | public T visitAssignStmt(miniSysYParser.AssignStmtContext ctx) {return visitChildren(ctx);} 176 | 177 | /** 178 | * {@inheritDoc} 179 | * 180 | *

The default implementation returns the result of calling 181 | * {@link #visitChildren} on {@code ctx}.

182 | */ 183 | @Override 184 | public T visitExpStmt(miniSysYParser.ExpStmtContext ctx) {return visitChildren(ctx);} 185 | 186 | /** 187 | * {@inheritDoc} 188 | * 189 | *

The default implementation returns the result of calling 190 | * {@link #visitChildren} on {@code ctx}.

191 | */ 192 | @Override 193 | public T visitConditionStmt(miniSysYParser.ConditionStmtContext ctx) {return visitChildren(ctx);} 194 | 195 | /** 196 | * {@inheritDoc} 197 | * 198 | *

The default implementation returns the result of calling 199 | * {@link #visitChildren} on {@code ctx}.

200 | */ 201 | @Override 202 | public T visitWhileStmt(miniSysYParser.WhileStmtContext ctx) {return visitChildren(ctx);} 203 | 204 | /** 205 | * {@inheritDoc} 206 | * 207 | *

The default implementation returns the result of calling 208 | * {@link #visitChildren} on {@code ctx}.

209 | */ 210 | @Override 211 | public T visitBreakStmt(miniSysYParser.BreakStmtContext ctx) {return visitChildren(ctx);} 212 | 213 | /** 214 | * {@inheritDoc} 215 | * 216 | *

The default implementation returns the result of calling 217 | * {@link #visitChildren} on {@code ctx}.

218 | */ 219 | @Override 220 | public T visitContinueStmt(miniSysYParser.ContinueStmtContext ctx) {return visitChildren(ctx);} 221 | 222 | /** 223 | * {@inheritDoc} 224 | * 225 | *

The default implementation returns the result of calling 226 | * {@link #visitChildren} on {@code ctx}.

227 | */ 228 | @Override 229 | public T visitReturnStmt(miniSysYParser.ReturnStmtContext ctx) {return visitChildren(ctx);} 230 | 231 | /** 232 | * {@inheritDoc} 233 | * 234 | *

The default implementation returns the result of calling 235 | * {@link #visitChildren} on {@code ctx}.

236 | */ 237 | @Override 238 | public T visitExp(miniSysYParser.ExpContext ctx) {return visitChildren(ctx);} 239 | 240 | /** 241 | * {@inheritDoc} 242 | * 243 | *

The default implementation returns the result of calling 244 | * {@link #visitChildren} on {@code ctx}.

245 | */ 246 | @Override 247 | public T visitCond(miniSysYParser.CondContext ctx) {return visitChildren(ctx);} 248 | 249 | /** 250 | * {@inheritDoc} 251 | * 252 | *

The default implementation returns the result of calling 253 | * {@link #visitChildren} on {@code ctx}.

254 | */ 255 | @Override 256 | public T visitLVal(miniSysYParser.LValContext ctx) {return visitChildren(ctx);} 257 | 258 | /** 259 | * {@inheritDoc} 260 | * 261 | *

The default implementation returns the result of calling 262 | * {@link #visitChildren} on {@code ctx}.

263 | */ 264 | @Override 265 | public T visitPrimaryExp(miniSysYParser.PrimaryExpContext ctx) {return visitChildren(ctx);} 266 | 267 | /** 268 | * {@inheritDoc} 269 | * 270 | *

The default implementation returns the result of calling 271 | * {@link #visitChildren} on {@code ctx}.

272 | */ 273 | @Override 274 | public T visitNumber(miniSysYParser.NumberContext ctx) {return visitChildren(ctx);} 275 | 276 | /** 277 | * {@inheritDoc} 278 | * 279 | *

The default implementation returns the result of calling 280 | * {@link #visitChildren} on {@code ctx}.

281 | */ 282 | @Override 283 | public T visitIntConst(miniSysYParser.IntConstContext ctx) {return visitChildren(ctx);} 284 | 285 | /** 286 | * {@inheritDoc} 287 | * 288 | *

The default implementation returns the result of calling 289 | * {@link #visitChildren} on {@code ctx}.

290 | */ 291 | @Override 292 | public T visitUnaryExp(miniSysYParser.UnaryExpContext ctx) {return visitChildren(ctx);} 293 | 294 | /** 295 | * {@inheritDoc} 296 | * 297 | *

The default implementation returns the result of calling 298 | * {@link #visitChildren} on {@code ctx}.

299 | */ 300 | @Override 301 | public T visitCallee(miniSysYParser.CalleeContext ctx) {return visitChildren(ctx);} 302 | 303 | /** 304 | * {@inheritDoc} 305 | * 306 | *

The default implementation returns the result of calling 307 | * {@link #visitChildren} on {@code ctx}.

308 | */ 309 | @Override 310 | public T visitUnaryOp(miniSysYParser.UnaryOpContext ctx) {return visitChildren(ctx);} 311 | 312 | /** 313 | * {@inheritDoc} 314 | * 315 | *

The default implementation returns the result of calling 316 | * {@link #visitChildren} on {@code ctx}.

317 | */ 318 | @Override 319 | public T visitFuncRParams(miniSysYParser.FuncRParamsContext ctx) {return visitChildren(ctx);} 320 | 321 | /** 322 | * {@inheritDoc} 323 | * 324 | *

The default implementation returns the result of calling 325 | * {@link #visitChildren} on {@code ctx}.

326 | */ 327 | @Override 328 | public T visitParam(miniSysYParser.ParamContext ctx) {return visitChildren(ctx);} 329 | 330 | /** 331 | * {@inheritDoc} 332 | * 333 | *

The default implementation returns the result of calling 334 | * {@link #visitChildren} on {@code ctx}.

335 | */ 336 | @Override 337 | public T visitMulExp(miniSysYParser.MulExpContext ctx) {return visitChildren(ctx);} 338 | 339 | /** 340 | * {@inheritDoc} 341 | * 342 | *

The default implementation returns the result of calling 343 | * {@link #visitChildren} on {@code ctx}.

344 | */ 345 | @Override 346 | public T visitMulOp(miniSysYParser.MulOpContext ctx) {return visitChildren(ctx);} 347 | 348 | /** 349 | * {@inheritDoc} 350 | * 351 | *

The default implementation returns the result of calling 352 | * {@link #visitChildren} on {@code ctx}.

353 | */ 354 | @Override 355 | public T visitAddExp(miniSysYParser.AddExpContext ctx) {return visitChildren(ctx);} 356 | 357 | /** 358 | * {@inheritDoc} 359 | * 360 | *

The default implementation returns the result of calling 361 | * {@link #visitChildren} on {@code ctx}.

362 | */ 363 | @Override 364 | public T visitAddOp(miniSysYParser.AddOpContext ctx) {return visitChildren(ctx);} 365 | 366 | /** 367 | * {@inheritDoc} 368 | * 369 | *

The default implementation returns the result of calling 370 | * {@link #visitChildren} on {@code ctx}.

371 | */ 372 | @Override 373 | public T visitRelExp(miniSysYParser.RelExpContext ctx) {return visitChildren(ctx);} 374 | 375 | /** 376 | * {@inheritDoc} 377 | * 378 | *

The default implementation returns the result of calling 379 | * {@link #visitChildren} on {@code ctx}.

380 | */ 381 | @Override 382 | public T visitRelOp(miniSysYParser.RelOpContext ctx) {return visitChildren(ctx);} 383 | 384 | /** 385 | * {@inheritDoc} 386 | * 387 | *

The default implementation returns the result of calling 388 | * {@link #visitChildren} on {@code ctx}.

389 | */ 390 | @Override 391 | public T visitEqExp(miniSysYParser.EqExpContext ctx) {return visitChildren(ctx);} 392 | 393 | /** 394 | * {@inheritDoc} 395 | * 396 | *

The default implementation returns the result of calling 397 | * {@link #visitChildren} on {@code ctx}.

398 | */ 399 | @Override 400 | public T visitEqOp(miniSysYParser.EqOpContext ctx) {return visitChildren(ctx);} 401 | 402 | /** 403 | * {@inheritDoc} 404 | * 405 | *

The default implementation returns the result of calling 406 | * {@link #visitChildren} on {@code ctx}.

407 | */ 408 | @Override 409 | public T visitLAndExp(miniSysYParser.LAndExpContext ctx) {return visitChildren(ctx);} 410 | 411 | /** 412 | * {@inheritDoc} 413 | * 414 | *

The default implementation returns the result of calling 415 | * {@link #visitChildren} on {@code ctx}.

416 | */ 417 | @Override 418 | public T visitLOrExp(miniSysYParser.LOrExpContext ctx) {return visitChildren(ctx);} 419 | 420 | /** 421 | * {@inheritDoc} 422 | * 423 | *

The default implementation returns the result of calling 424 | * {@link #visitChildren} on {@code ctx}.

425 | */ 426 | @Override 427 | public T visitConstExp(miniSysYParser.ConstExpContext ctx) {return visitChildren(ctx);} 428 | } -------------------------------------------------------------------------------- /src/frontend/miniSysYLexer.java: -------------------------------------------------------------------------------- 1 | // Generated from miniSysY.g4 by ANTLR 4.9.2 2 | package frontend; 3 | import org.antlr.v4.runtime.Lexer; 4 | import org.antlr.v4.runtime.CharStream; 5 | import org.antlr.v4.runtime.Token; 6 | import org.antlr.v4.runtime.TokenStream; 7 | import org.antlr.v4.runtime.*; 8 | import org.antlr.v4.runtime.atn.*; 9 | import org.antlr.v4.runtime.dfa.DFA; 10 | import org.antlr.v4.runtime.misc.*; 11 | 12 | @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) 13 | public class miniSysYLexer extends Lexer { 14 | static { RuntimeMetaData.checkVersion("4.9.2", RuntimeMetaData.VERSION); } 15 | 16 | protected static final DFA[] _decisionToDFA; 17 | protected static final PredictionContextCache _sharedContextCache = 18 | new PredictionContextCache(); 19 | public static final int 20 | CONST_KW=1, INT_KW=2, VOID_KW=3, IF_KW=4, ELSE_KW=5, WHILE_KW=6, BREAK_KW=7, 21 | CONTINUE_KW=8, RETURN_KW=9, IDENT=10, DECIMAL_CONST=11, OCTAL_CONST=12, 22 | HEXADECIMAL_CONST=13, STRING=14, PLUS=15, MINUS=16, NOT=17, MUL=18, DIV=19, 23 | MOD=20, ASSIGN=21, EQ=22, NEQ=23, LT=24, GT=25, LE=26, GE=27, AND=28, 24 | OR=29, L_PAREN=30, R_PAREN=31, L_BRACE=32, R_BRACE=33, L_BRACKT=34, R_BRACKT=35, 25 | COMMA=36, SEMICOLON=37, DOUBLE_QUOTE=38, WS=39, LINE_COMMENT=40, MULTILINE_COMMENT=41; 26 | public static String[] channelNames = { 27 | "DEFAULT_TOKEN_CHANNEL", "HIDDEN" 28 | }; 29 | 30 | public static String[] modeNames = { 31 | "DEFAULT_MODE" 32 | }; 33 | 34 | private static String[] makeRuleNames() { 35 | return new String[] { 36 | "CONST_KW", "INT_KW", "VOID_KW", "IF_KW", "ELSE_KW", "WHILE_KW", "BREAK_KW", 37 | "CONTINUE_KW", "RETURN_KW", "IDENT", "DECIMAL_CONST", "OCTAL_CONST", 38 | "HEXADECIMAL_CONST", "STRING", "REGULAR_CHAR", "ESC", "PLUS", "MINUS", 39 | "NOT", "MUL", "DIV", "MOD", "ASSIGN", "EQ", "NEQ", "LT", "GT", "LE", 40 | "GE", "AND", "OR", "L_PAREN", "R_PAREN", "L_BRACE", "R_BRACE", "L_BRACKT", 41 | "R_BRACKT", "COMMA", "SEMICOLON", "DOUBLE_QUOTE", "WS", "LINE_COMMENT", 42 | "MULTILINE_COMMENT" 43 | }; 44 | } 45 | public static final String[] ruleNames = makeRuleNames(); 46 | 47 | private static String[] makeLiteralNames() { 48 | return new String[] { 49 | null, "'const'", "'int'", "'void'", "'if'", "'else'", "'while'", "'break'", 50 | "'continue'", "'return'", null, null, null, null, null, "'+'", "'-'", 51 | "'!'", "'*'", "'/'", "'%'", "'='", "'=='", "'!='", "'<'", "'>'", "'<='", 52 | "'>='", "'&&'", "'||'", "'('", "')'", "'{'", "'}'", "'['", "']'", "','", 53 | "';'", "'\"'" 54 | }; 55 | } 56 | private static final String[] _LITERAL_NAMES = makeLiteralNames(); 57 | private static String[] makeSymbolicNames() { 58 | return new String[] { 59 | null, "CONST_KW", "INT_KW", "VOID_KW", "IF_KW", "ELSE_KW", "WHILE_KW", 60 | "BREAK_KW", "CONTINUE_KW", "RETURN_KW", "IDENT", "DECIMAL_CONST", "OCTAL_CONST", 61 | "HEXADECIMAL_CONST", "STRING", "PLUS", "MINUS", "NOT", "MUL", "DIV", 62 | "MOD", "ASSIGN", "EQ", "NEQ", "LT", "GT", "LE", "GE", "AND", "OR", "L_PAREN", 63 | "R_PAREN", "L_BRACE", "R_BRACE", "L_BRACKT", "R_BRACKT", "COMMA", "SEMICOLON", 64 | "DOUBLE_QUOTE", "WS", "LINE_COMMENT", "MULTILINE_COMMENT" 65 | }; 66 | } 67 | private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); 68 | public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); 69 | 70 | /** 71 | * @deprecated Use {@link #VOCABULARY} instead. 72 | */ 73 | @Deprecated 74 | public static final String[] tokenNames; 75 | static { 76 | tokenNames = new String[_SYMBOLIC_NAMES.length]; 77 | for (int i = 0; i < tokenNames.length; i++) { 78 | tokenNames[i] = VOCABULARY.getLiteralName(i); 79 | if (tokenNames[i] == null) { 80 | tokenNames[i] = VOCABULARY.getSymbolicName(i); 81 | } 82 | 83 | if (tokenNames[i] == null) { 84 | tokenNames[i] = ""; 85 | } 86 | } 87 | } 88 | 89 | @Override 90 | @Deprecated 91 | public String[] getTokenNames() { 92 | return tokenNames; 93 | } 94 | 95 | @Override 96 | 97 | public Vocabulary getVocabulary() { 98 | return VOCABULARY; 99 | } 100 | 101 | 102 | public miniSysYLexer(CharStream input) { 103 | super(input); 104 | _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); 105 | } 106 | 107 | @Override 108 | public String getGrammarFileName() { return "miniSysY.g4"; } 109 | 110 | @Override 111 | public String[] getRuleNames() { return ruleNames; } 112 | 113 | @Override 114 | public String getSerializedATN() { return _serializedATN; } 115 | 116 | @Override 117 | public String[] getChannelNames() { return channelNames; } 118 | 119 | @Override 120 | public String[] getModeNames() { return modeNames; } 121 | 122 | @Override 123 | public ATN getATN() { return _ATN; } 124 | 125 | public static final String _serializedATN = 126 | "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2+\u011b\b\1\4\2\t"+ 127 | "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ 128 | "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ 129 | "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ 130 | "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ 131 | "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ 132 | ",\t,\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3"+ 133 | "\5\3\5\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b"+ 134 | "\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3"+ 135 | "\13\3\13\3\13\6\13\u0090\n\13\r\13\16\13\u0091\5\13\u0094\n\13\3\f\3\f"+ 136 | "\3\f\6\f\u0099\n\f\r\f\16\f\u009a\5\f\u009d\n\f\3\r\3\r\3\r\6\r\u00a2"+ 137 | "\n\r\r\r\16\r\u00a3\5\r\u00a6\n\r\3\16\3\16\3\16\3\16\5\16\u00ac\n\16"+ 138 | "\3\16\6\16\u00af\n\16\r\16\16\16\u00b0\3\17\3\17\7\17\u00b5\n\17\f\17"+ 139 | "\16\17\u00b8\13\17\3\17\3\17\3\20\3\20\5\20\u00be\n\20\3\21\3\21\3\21"+ 140 | "\3\21\5\21\u00c4\n\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26"+ 141 | "\3\27\3\27\3\30\3\30\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\34\3\34"+ 142 | "\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3\"\3\"\3"+ 143 | "#\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\6*\u00fd\n*\r*\16*\u00fe"+ 144 | "\3*\3*\3+\3+\3+\3+\7+\u0107\n+\f+\16+\u010a\13+\3+\3+\3,\3,\3,\3,\7,\u0112"+ 145 | "\n,\f,\16,\u0115\13,\3,\3,\3,\3,\3,\4\u00b6\u0113\2-\3\3\5\4\7\5\t\6\13"+ 146 | "\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\2!\2#\21%\22\'\23"+ 147 | ")\24+\25-\26/\27\61\30\63\31\65\32\67\339\34;\35=\36?\37A C!E\"G#I$K%"+ 148 | "M&O\'Q(S)U*W+\3\2\n\5\2C\\aac|\6\2\62;C\\aac|\3\2\63;\3\2\62;\3\2\629"+ 149 | "\5\2\62;CHch\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u0126\2\3\3\2\2\2\2\5"+ 150 | "\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2"+ 151 | "\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33"+ 152 | "\3\2\2\2\2\35\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+"+ 153 | "\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2"+ 154 | "\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2"+ 155 | "C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3"+ 156 | "\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\3Y\3\2\2\2\5_\3\2\2"+ 157 | "\2\7c\3\2\2\2\th\3\2\2\2\13k\3\2\2\2\rp\3\2\2\2\17v\3\2\2\2\21|\3\2\2"+ 158 | "\2\23\u0085\3\2\2\2\25\u0093\3\2\2\2\27\u009c\3\2\2\2\31\u00a5\3\2\2\2"+ 159 | "\33\u00ab\3\2\2\2\35\u00b2\3\2\2\2\37\u00bd\3\2\2\2!\u00c3\3\2\2\2#\u00c5"+ 160 | "\3\2\2\2%\u00c7\3\2\2\2\'\u00c9\3\2\2\2)\u00cb\3\2\2\2+\u00cd\3\2\2\2"+ 161 | "-\u00cf\3\2\2\2/\u00d1\3\2\2\2\61\u00d3\3\2\2\2\63\u00d6\3\2\2\2\65\u00d9"+ 162 | "\3\2\2\2\67\u00db\3\2\2\29\u00dd\3\2\2\2;\u00e0\3\2\2\2=\u00e3\3\2\2\2"+ 163 | "?\u00e6\3\2\2\2A\u00e9\3\2\2\2C\u00eb\3\2\2\2E\u00ed\3\2\2\2G\u00ef\3"+ 164 | "\2\2\2I\u00f1\3\2\2\2K\u00f3\3\2\2\2M\u00f5\3\2\2\2O\u00f7\3\2\2\2Q\u00f9"+ 165 | "\3\2\2\2S\u00fc\3\2\2\2U\u0102\3\2\2\2W\u010d\3\2\2\2YZ\7e\2\2Z[\7q\2"+ 166 | "\2[\\\7p\2\2\\]\7u\2\2]^\7v\2\2^\4\3\2\2\2_`\7k\2\2`a\7p\2\2ab\7v\2\2"+ 167 | "b\6\3\2\2\2cd\7x\2\2de\7q\2\2ef\7k\2\2fg\7f\2\2g\b\3\2\2\2hi\7k\2\2ij"+ 168 | "\7h\2\2j\n\3\2\2\2kl\7g\2\2lm\7n\2\2mn\7u\2\2no\7g\2\2o\f\3\2\2\2pq\7"+ 169 | "y\2\2qr\7j\2\2rs\7k\2\2st\7n\2\2tu\7g\2\2u\16\3\2\2\2vw\7d\2\2wx\7t\2"+ 170 | "\2xy\7g\2\2yz\7c\2\2z{\7m\2\2{\20\3\2\2\2|}\7e\2\2}~\7q\2\2~\177\7p\2"+ 171 | "\2\177\u0080\7v\2\2\u0080\u0081\7k\2\2\u0081\u0082\7p\2\2\u0082\u0083"+ 172 | "\7w\2\2\u0083\u0084\7g\2\2\u0084\22\3\2\2\2\u0085\u0086\7t\2\2\u0086\u0087"+ 173 | "\7g\2\2\u0087\u0088\7v\2\2\u0088\u0089\7w\2\2\u0089\u008a\7t\2\2\u008a"+ 174 | "\u008b\7p\2\2\u008b\24\3\2\2\2\u008c\u0094\t\2\2\2\u008d\u008f\t\2\2\2"+ 175 | "\u008e\u0090\t\3\2\2\u008f\u008e\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u008f"+ 176 | "\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0094\3\2\2\2\u0093\u008c\3\2\2\2\u0093"+ 177 | "\u008d\3\2\2\2\u0094\26\3\2\2\2\u0095\u009d\t\4\2\2\u0096\u0098\t\4\2"+ 178 | "\2\u0097\u0099\t\5\2\2\u0098\u0097\3\2\2\2\u0099\u009a\3\2\2\2\u009a\u0098"+ 179 | "\3\2\2\2\u009a\u009b\3\2\2\2\u009b\u009d\3\2\2\2\u009c\u0095\3\2\2\2\u009c"+ 180 | "\u0096\3\2\2\2\u009d\30\3\2\2\2\u009e\u00a6\7\62\2\2\u009f\u00a1\7\62"+ 181 | "\2\2\u00a0\u00a2\t\6\2\2\u00a1\u00a0\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3"+ 182 | "\u00a1\3\2\2\2\u00a3\u00a4\3\2\2\2\u00a4\u00a6\3\2\2\2\u00a5\u009e\3\2"+ 183 | "\2\2\u00a5\u009f\3\2\2\2\u00a6\32\3\2\2\2\u00a7\u00a8\7\62\2\2\u00a8\u00ac"+ 184 | "\7z\2\2\u00a9\u00aa\7\62\2\2\u00aa\u00ac\7Z\2\2\u00ab\u00a7\3\2\2\2\u00ab"+ 185 | "\u00a9\3\2\2\2\u00ac\u00ae\3\2\2\2\u00ad\u00af\t\7\2\2\u00ae\u00ad\3\2"+ 186 | "\2\2\u00af\u00b0\3\2\2\2\u00b0\u00ae\3\2\2\2\u00b0\u00b1\3\2\2\2\u00b1"+ 187 | "\34\3\2\2\2\u00b2\u00b6\5Q)\2\u00b3\u00b5\5\37\20\2\u00b4\u00b3\3\2\2"+ 188 | "\2\u00b5\u00b8\3\2\2\2\u00b6\u00b7\3\2\2\2\u00b6\u00b4\3\2\2\2\u00b7\u00b9"+ 189 | "\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b9\u00ba\5Q)\2\u00ba\36\3\2\2\2\u00bb"+ 190 | "\u00be\5!\21\2\u00bc\u00be\13\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00bc\3"+ 191 | "\2\2\2\u00be \3\2\2\2\u00bf\u00c0\7^\2\2\u00c0\u00c4\7$\2\2\u00c1\u00c2"+ 192 | "\7^\2\2\u00c2\u00c4\7^\2\2\u00c3\u00bf\3\2\2\2\u00c3\u00c1\3\2\2\2\u00c4"+ 193 | "\"\3\2\2\2\u00c5\u00c6\7-\2\2\u00c6$\3\2\2\2\u00c7\u00c8\7/\2\2\u00c8"+ 194 | "&\3\2\2\2\u00c9\u00ca\7#\2\2\u00ca(\3\2\2\2\u00cb\u00cc\7,\2\2\u00cc*"+ 195 | "\3\2\2\2\u00cd\u00ce\7\61\2\2\u00ce,\3\2\2\2\u00cf\u00d0\7\'\2\2\u00d0"+ 196 | ".\3\2\2\2\u00d1\u00d2\7?\2\2\u00d2\60\3\2\2\2\u00d3\u00d4\7?\2\2\u00d4"+ 197 | "\u00d5\7?\2\2\u00d5\62\3\2\2\2\u00d6\u00d7\7#\2\2\u00d7\u00d8\7?\2\2\u00d8"+ 198 | "\64\3\2\2\2\u00d9\u00da\7>\2\2\u00da\66\3\2\2\2\u00db\u00dc\7@\2\2\u00dc"+ 199 | "8\3\2\2\2\u00dd\u00de\7>\2\2\u00de\u00df\7?\2\2\u00df:\3\2\2\2\u00e0\u00e1"+ 200 | "\7@\2\2\u00e1\u00e2\7?\2\2\u00e2<\3\2\2\2\u00e3\u00e4\7(\2\2\u00e4\u00e5"+ 201 | "\7(\2\2\u00e5>\3\2\2\2\u00e6\u00e7\7~\2\2\u00e7\u00e8\7~\2\2\u00e8@\3"+ 202 | "\2\2\2\u00e9\u00ea\7*\2\2\u00eaB\3\2\2\2\u00eb\u00ec\7+\2\2\u00ecD\3\2"+ 203 | "\2\2\u00ed\u00ee\7}\2\2\u00eeF\3\2\2\2\u00ef\u00f0\7\177\2\2\u00f0H\3"+ 204 | "\2\2\2\u00f1\u00f2\7]\2\2\u00f2J\3\2\2\2\u00f3\u00f4\7_\2\2\u00f4L\3\2"+ 205 | "\2\2\u00f5\u00f6\7.\2\2\u00f6N\3\2\2\2\u00f7\u00f8\7=\2\2\u00f8P\3\2\2"+ 206 | "\2\u00f9\u00fa\7$\2\2\u00faR\3\2\2\2\u00fb\u00fd\t\b\2\2\u00fc\u00fb\3"+ 207 | "\2\2\2\u00fd\u00fe\3\2\2\2\u00fe\u00fc\3\2\2\2\u00fe\u00ff\3\2\2\2\u00ff"+ 208 | "\u0100\3\2\2\2\u0100\u0101\b*\2\2\u0101T\3\2\2\2\u0102\u0103\7\61\2\2"+ 209 | "\u0103\u0104\7\61\2\2\u0104\u0108\3\2\2\2\u0105\u0107\n\t\2\2\u0106\u0105"+ 210 | "\3\2\2\2\u0107\u010a\3\2\2\2\u0108\u0106\3\2\2\2\u0108\u0109\3\2\2\2\u0109"+ 211 | "\u010b\3\2\2\2\u010a\u0108\3\2\2\2\u010b\u010c\b+\2\2\u010cV\3\2\2\2\u010d"+ 212 | "\u010e\7\61\2\2\u010e\u010f\7,\2\2\u010f\u0113\3\2\2\2\u0110\u0112\13"+ 213 | "\2\2\2\u0111\u0110\3\2\2\2\u0112\u0115\3\2\2\2\u0113\u0114\3\2\2\2\u0113"+ 214 | "\u0111\3\2\2\2\u0114\u0116\3\2\2\2\u0115\u0113\3\2\2\2\u0116\u0117\7,"+ 215 | "\2\2\u0117\u0118\7\61\2\2\u0118\u0119\3\2\2\2\u0119\u011a\b,\2\2\u011a"+ 216 | "X\3\2\2\2\21\2\u0091\u0093\u009a\u009c\u00a3\u00a5\u00ab\u00b0\u00b6\u00bd"+ 217 | "\u00c3\u00fe\u0108\u0113\3\b\2\2"; 218 | public static final ATN _ATN = 219 | new ATNDeserializer().deserialize(_serializedATN.toCharArray()); 220 | static { 221 | _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; 222 | for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { 223 | _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); 224 | } 225 | } 226 | } -------------------------------------------------------------------------------- /src/frontend/miniSysYVisitor.java: -------------------------------------------------------------------------------- 1 | package frontend;// Generated from miniSysY.g4 by ANTLR 4.9.2 2 | import org.antlr.v4.runtime.tree.ParseTreeVisitor; 3 | 4 | /** 5 | * This interface defines a complete generic visitor for a parse tree produced 6 | * by {@link miniSysYParser}. 7 | * 8 | * @param The return type of the visit operation. Use {@link Void} for 9 | * operations with no return type. 10 | */ 11 | public interface miniSysYVisitor extends ParseTreeVisitor { 12 | /** 13 | * Visit a parse tree produced by {@link miniSysYParser#program}. 14 | * @param ctx the parse tree 15 | * @return the visitor result 16 | */ 17 | T visitProgram(miniSysYParser.ProgramContext ctx); 18 | /** 19 | * Visit a parse tree produced by {@link miniSysYParser#compUnit}. 20 | * @param ctx the parse tree 21 | * @return the visitor result 22 | */ 23 | T visitCompUnit(miniSysYParser.CompUnitContext ctx); 24 | /** 25 | * Visit a parse tree produced by {@link miniSysYParser#decl}. 26 | * @param ctx the parse tree 27 | * @return the visitor result 28 | */ 29 | T visitDecl(miniSysYParser.DeclContext ctx); 30 | /** 31 | * Visit a parse tree produced by {@link miniSysYParser#constDecl}. 32 | * @param ctx the parse tree 33 | * @return the visitor result 34 | */ 35 | T visitConstDecl(miniSysYParser.ConstDeclContext ctx); 36 | /** 37 | * Visit a parse tree produced by {@link miniSysYParser#bType}. 38 | * @param ctx the parse tree 39 | * @return the visitor result 40 | */ 41 | T visitBType(miniSysYParser.BTypeContext ctx); 42 | /** 43 | * Visit a parse tree produced by {@link miniSysYParser#constDef}. 44 | * @param ctx the parse tree 45 | * @return the visitor result 46 | */ 47 | T visitConstDef(miniSysYParser.ConstDefContext ctx); 48 | /** 49 | * Visit a parse tree produced by {@link miniSysYParser#constInitVal}. 50 | * @param ctx the parse tree 51 | * @return the visitor result 52 | */ 53 | T visitConstInitVal(miniSysYParser.ConstInitValContext ctx); 54 | /** 55 | * Visit a parse tree produced by {@link miniSysYParser#varDecl}. 56 | * @param ctx the parse tree 57 | * @return the visitor result 58 | */ 59 | T visitVarDecl(miniSysYParser.VarDeclContext ctx); 60 | /** 61 | * Visit a parse tree produced by {@link miniSysYParser#varDef}. 62 | * @param ctx the parse tree 63 | * @return the visitor result 64 | */ 65 | T visitVarDef(miniSysYParser.VarDefContext ctx); 66 | /** 67 | * Visit a parse tree produced by {@link miniSysYParser#initVal}. 68 | * @param ctx the parse tree 69 | * @return the visitor result 70 | */ 71 | T visitInitVal(miniSysYParser.InitValContext ctx); 72 | /** 73 | * Visit a parse tree produced by {@link miniSysYParser#funcDef}. 74 | * @param ctx the parse tree 75 | * @return the visitor result 76 | */ 77 | T visitFuncDef(miniSysYParser.FuncDefContext ctx); 78 | /** 79 | * Visit a parse tree produced by {@link miniSysYParser#funcType}. 80 | * @param ctx the parse tree 81 | * @return the visitor result 82 | */ 83 | T visitFuncType(miniSysYParser.FuncTypeContext ctx); 84 | /** 85 | * Visit a parse tree produced by {@link miniSysYParser#funcFParams}. 86 | * @param ctx the parse tree 87 | * @return the visitor result 88 | */ 89 | T visitFuncFParams(miniSysYParser.FuncFParamsContext ctx); 90 | /** 91 | * Visit a parse tree produced by {@link miniSysYParser#funcFParam}. 92 | * @param ctx the parse tree 93 | * @return the visitor result 94 | */ 95 | T visitFuncFParam(miniSysYParser.FuncFParamContext ctx); 96 | /** 97 | * Visit a parse tree produced by {@link miniSysYParser#block}. 98 | * @param ctx the parse tree 99 | * @return the visitor result 100 | */ 101 | T visitBlock(miniSysYParser.BlockContext ctx); 102 | /** 103 | * Visit a parse tree produced by {@link miniSysYParser#blockItem}. 104 | * @param ctx the parse tree 105 | * @return the visitor result 106 | */ 107 | T visitBlockItem(miniSysYParser.BlockItemContext ctx); 108 | /** 109 | * Visit a parse tree produced by {@link miniSysYParser#stmt}. 110 | * @param ctx the parse tree 111 | * @return the visitor result 112 | */ 113 | T visitStmt(miniSysYParser.StmtContext ctx); 114 | /** 115 | * Visit a parse tree produced by {@link miniSysYParser#assignStmt}. 116 | * @param ctx the parse tree 117 | * @return the visitor result 118 | */ 119 | T visitAssignStmt(miniSysYParser.AssignStmtContext ctx); 120 | /** 121 | * Visit a parse tree produced by {@link miniSysYParser#expStmt}. 122 | * @param ctx the parse tree 123 | * @return the visitor result 124 | */ 125 | T visitExpStmt(miniSysYParser.ExpStmtContext ctx); 126 | /** 127 | * Visit a parse tree produced by {@link miniSysYParser#conditionStmt}. 128 | * @param ctx the parse tree 129 | * @return the visitor result 130 | */ 131 | T visitConditionStmt(miniSysYParser.ConditionStmtContext ctx); 132 | /** 133 | * Visit a parse tree produced by {@link miniSysYParser#whileStmt}. 134 | * @param ctx the parse tree 135 | * @return the visitor result 136 | */ 137 | T visitWhileStmt(miniSysYParser.WhileStmtContext ctx); 138 | /** 139 | * Visit a parse tree produced by {@link miniSysYParser#breakStmt}. 140 | * @param ctx the parse tree 141 | * @return the visitor result 142 | */ 143 | T visitBreakStmt(miniSysYParser.BreakStmtContext ctx); 144 | /** 145 | * Visit a parse tree produced by {@link miniSysYParser#continueStmt}. 146 | * @param ctx the parse tree 147 | * @return the visitor result 148 | */ 149 | T visitContinueStmt(miniSysYParser.ContinueStmtContext ctx); 150 | /** 151 | * Visit a parse tree produced by {@link miniSysYParser#returnStmt}. 152 | * @param ctx the parse tree 153 | * @return the visitor result 154 | */ 155 | T visitReturnStmt(miniSysYParser.ReturnStmtContext ctx); 156 | /** 157 | * Visit a parse tree produced by {@link miniSysYParser#exp}. 158 | * @param ctx the parse tree 159 | * @return the visitor result 160 | */ 161 | T visitExp(miniSysYParser.ExpContext ctx); 162 | /** 163 | * Visit a parse tree produced by {@link miniSysYParser#cond}. 164 | * @param ctx the parse tree 165 | * @return the visitor result 166 | */ 167 | T visitCond(miniSysYParser.CondContext ctx); 168 | /** 169 | * Visit a parse tree produced by {@link miniSysYParser#lVal}. 170 | * @param ctx the parse tree 171 | * @return the visitor result 172 | */ 173 | T visitLVal(miniSysYParser.LValContext ctx); 174 | /** 175 | * Visit a parse tree produced by {@link miniSysYParser#primaryExp}. 176 | * @param ctx the parse tree 177 | * @return the visitor result 178 | */ 179 | T visitPrimaryExp(miniSysYParser.PrimaryExpContext ctx); 180 | /** 181 | * Visit a parse tree produced by {@link miniSysYParser#number}. 182 | * @param ctx the parse tree 183 | * @return the visitor result 184 | */ 185 | T visitNumber(miniSysYParser.NumberContext ctx); 186 | /** 187 | * Visit a parse tree produced by {@link miniSysYParser#intConst}. 188 | * @param ctx the parse tree 189 | * @return the visitor result 190 | */ 191 | T visitIntConst(miniSysYParser.IntConstContext ctx); 192 | /** 193 | * Visit a parse tree produced by {@link miniSysYParser#unaryExp}. 194 | * @param ctx the parse tree 195 | * @return the visitor result 196 | */ 197 | T visitUnaryExp(miniSysYParser.UnaryExpContext ctx); 198 | /** 199 | * Visit a parse tree produced by {@link miniSysYParser#callee}. 200 | * @param ctx the parse tree 201 | * @return the visitor result 202 | */ 203 | T visitCallee(miniSysYParser.CalleeContext ctx); 204 | /** 205 | * Visit a parse tree produced by {@link miniSysYParser#unaryOp}. 206 | * @param ctx the parse tree 207 | * @return the visitor result 208 | */ 209 | T visitUnaryOp(miniSysYParser.UnaryOpContext ctx); 210 | /** 211 | * Visit a parse tree produced by {@link miniSysYParser#funcRParams}. 212 | * @param ctx the parse tree 213 | * @return the visitor result 214 | */ 215 | T visitFuncRParams(miniSysYParser.FuncRParamsContext ctx); 216 | /** 217 | * Visit a parse tree produced by {@link miniSysYParser#param}. 218 | * @param ctx the parse tree 219 | * @return the visitor result 220 | */ 221 | T visitParam(miniSysYParser.ParamContext ctx); 222 | /** 223 | * Visit a parse tree produced by {@link miniSysYParser#mulExp}. 224 | * @param ctx the parse tree 225 | * @return the visitor result 226 | */ 227 | T visitMulExp(miniSysYParser.MulExpContext ctx); 228 | /** 229 | * Visit a parse tree produced by {@link miniSysYParser#mulOp}. 230 | * @param ctx the parse tree 231 | * @return the visitor result 232 | */ 233 | T visitMulOp(miniSysYParser.MulOpContext ctx); 234 | /** 235 | * Visit a parse tree produced by {@link miniSysYParser#addExp}. 236 | * @param ctx the parse tree 237 | * @return the visitor result 238 | */ 239 | T visitAddExp(miniSysYParser.AddExpContext ctx); 240 | /** 241 | * Visit a parse tree produced by {@link miniSysYParser#addOp}. 242 | * @param ctx the parse tree 243 | * @return the visitor result 244 | */ 245 | T visitAddOp(miniSysYParser.AddOpContext ctx); 246 | /** 247 | * Visit a parse tree produced by {@link miniSysYParser#relExp}. 248 | * @param ctx the parse tree 249 | * @return the visitor result 250 | */ 251 | T visitRelExp(miniSysYParser.RelExpContext ctx); 252 | /** 253 | * Visit a parse tree produced by {@link miniSysYParser#relOp}. 254 | * @param ctx the parse tree 255 | * @return the visitor result 256 | */ 257 | T visitRelOp(miniSysYParser.RelOpContext ctx); 258 | /** 259 | * Visit a parse tree produced by {@link miniSysYParser#eqExp}. 260 | * @param ctx the parse tree 261 | * @return the visitor result 262 | */ 263 | T visitEqExp(miniSysYParser.EqExpContext ctx); 264 | /** 265 | * Visit a parse tree produced by {@link miniSysYParser#eqOp}. 266 | * @param ctx the parse tree 267 | * @return the visitor result 268 | */ 269 | T visitEqOp(miniSysYParser.EqOpContext ctx); 270 | /** 271 | * Visit a parse tree produced by {@link miniSysYParser#lAndExp}. 272 | * @param ctx the parse tree 273 | * @return the visitor result 274 | */ 275 | T visitLAndExp(miniSysYParser.LAndExpContext ctx); 276 | /** 277 | * Visit a parse tree produced by {@link miniSysYParser#lOrExp}. 278 | * @param ctx the parse tree 279 | * @return the visitor result 280 | */ 281 | T visitLOrExp(miniSysYParser.LOrExpContext ctx); 282 | /** 283 | * Visit a parse tree produced by {@link miniSysYParser#constExp}. 284 | * @param ctx the parse tree 285 | * @return the visitor result 286 | */ 287 | T visitConstExp(miniSysYParser.ConstExpContext ctx); 288 | } -------------------------------------------------------------------------------- /src/ir/IRBuilder.java: -------------------------------------------------------------------------------- 1 | package ir; 2 | 3 | import ir.type.FunctionType; 4 | import ir.type.IntegerType; 5 | import ir.type.Type; 6 | import ir.values.BasicBlock; 7 | import ir.values.Constant; 8 | import ir.values.Constant.ConstantInt; 9 | import ir.values.Constant.ConstantArray; 10 | import ir.values.Function; 11 | import ir.values.GlobalVariable; 12 | import ir.values.instructions.BinaryInst; 13 | import ir.values.instructions.Inst; 14 | import ir.values.instructions.MemInst; 15 | import ir.values.instructions.TerminatorInst; 16 | 17 | import java.util.ArrayList; 18 | 19 | public class IRBuilder { 20 | 21 | private static final IRBuilder b = new IRBuilder(); 22 | 23 | public static IRBuilder getInstance() {return b;} 24 | 25 | private BasicBlock curBB; 26 | private Function curFunc; 27 | private Module m;//其实是不会变的 28 | 29 | public void setModule(Module m) {this.m = m;} 30 | 31 | public void setFunc(Function f) {curFunc = f;} 32 | 33 | public Function curFunc() {return curFunc;} 34 | 35 | public void setInsertPoint(BasicBlock bb) { 36 | curBB = bb; 37 | } 38 | 39 | public BasicBlock curBB() {return curBB;} 40 | 41 | private IRBuilder() { 42 | } 43 | 44 | public ConstantInt getConstantInt(int val) { 45 | return ConstantInt.get(val); 46 | } 47 | 48 | public ConstantArray getConstantArray(Type ty, ArrayList constants) {return new ConstantArray(ty, constants);} 49 | 50 | public GlobalVariable getGlobalVariable(String name, Type type, Constant initValue) { 51 | return new GlobalVariable(name, type) {{ 52 | init = initValue; 53 | }}; 54 | } 55 | 56 | public Function buildFunction(String Fname, FunctionType type, boolean isBuiltin) { 57 | return new Function(type, isBuiltin) {{ 58 | this.name = Fname; 59 | node.setParent(m.functions); 60 | node.insertAtEnd(m.functions); 61 | }}; 62 | } 63 | 64 | public BasicBlock getBB(String name) {return new BasicBlock(name);} 65 | 66 | public BasicBlock buildBB(String name) { 67 | return new BasicBlock(name) {{ 68 | node.insertAtEnd(curFunc.list); 69 | }}; 70 | } 71 | 72 | public BinaryInst getBinary(Inst.TAG tag, Value lhs, Value rhs) { 73 | return new BinaryInst(lhs.type, tag, lhs, rhs); 74 | } 75 | 76 | public BinaryInst buildBinary(Inst.TAG tag, Value lhs, Value rhs) { 77 | return new BinaryInst(lhs.type, tag, lhs, rhs) {{ 78 | this.node.insertAtEnd(curBB.list); 79 | }}; 80 | } 81 | 82 | public TerminatorInst.Br getBr(BasicBlock trueblock) { 83 | return new TerminatorInst.Br(trueblock); 84 | } 85 | 86 | public TerminatorInst.Br getBr(Value cond, BasicBlock trueblock, BasicBlock falseblock) { 87 | return new TerminatorInst.Br(cond, trueblock, falseblock); 88 | } 89 | 90 | 91 | public TerminatorInst.Br buildBr(BasicBlock tureblock) { 92 | if ( curBB.list.getLast().getVal() != null && (curBB.list.getLast().getVal().tag == Inst.TAG.Ret 93 | || curBB.list.getLast().getVal().tag == Inst.TAG.Br)) { 94 | return null; 95 | //防止下面这种情况出现 96 | //ret i32 1 97 | //br label %4 98 | } 99 | return new TerminatorInst.Br(tureblock) {{ 100 | this.node.insertAtEnd(curBB.list); 101 | }}; 102 | } 103 | 104 | public TerminatorInst.Br buildBr(Value cond, BasicBlock trueblock, BasicBlock falseblock) { 105 | 106 | if (curBB.list.getLast().getVal() != null && (curBB.list.getLast().getVal().tag == Inst.TAG.Ret 107 | || curBB.list.getLast().getVal().tag == Inst.TAG.Br)) { 108 | return null; 109 | //防止下面这种情况出现 110 | //ret i32 1 111 | //br label %4 112 | } 113 | return new TerminatorInst.Br(cond, trueblock, falseblock) {{ 114 | this.node.insertAtEnd(curBB.list); 115 | }}; 116 | } 117 | 118 | public TerminatorInst.Ret getRet() {return new TerminatorInst.Ret();} 119 | 120 | public TerminatorInst.Ret getRet(Value val) {return new TerminatorInst.Ret(val);} 121 | 122 | public TerminatorInst.Ret buildRet() { 123 | return new TerminatorInst.Ret() {{ 124 | node.insertAtEnd(curBB.list); 125 | }}; 126 | } 127 | 128 | public TerminatorInst.Ret buildRet(Value val) { 129 | return new TerminatorInst.Ret(val) {{ 130 | node.insertAtEnd(curBB.list); 131 | }}; 132 | } 133 | 134 | public MemInst.Alloca getAlloca(Type type) {return new MemInst.Alloca(type);} 135 | 136 | public MemInst.Alloca buildAlloca(Type type) { 137 | return new MemInst.Alloca(type) {{ 138 | node.insertAtEntry(curBB.node.getParent().getVal().list.getEntry().getVal().list); 139 | }}; 140 | } 141 | 142 | 143 | public MemInst.Load getLoad(Type type, Value value) {return new MemInst.Load(type, value);} 144 | 145 | public MemInst.Load buildLoad(Type type, Value value) { 146 | return new MemInst.Load(type, value) {{ 147 | node.insertAtEnd(curBB.list); 148 | }}; 149 | } 150 | 151 | public MemInst.Store getStore(Value value, Value pointer) {return new MemInst.Store(value, pointer);} 152 | 153 | public MemInst.Store buildStore(Value value, Value pointer) { 154 | return new MemInst.Store(value, pointer) {{ 155 | node.insertAtEnd(curBB.list); 156 | }}; 157 | } 158 | 159 | public MemInst.Zext getZext(Value val) {return new MemInst.Zext(val, IntegerType.i32);} 160 | 161 | public MemInst.Zext buildZext(Value value) { 162 | return 163 | new MemInst.Zext(value, IntegerType.i32) {{ 164 | node.insertAtEnd(curBB.list); 165 | }}; 166 | } 167 | 168 | public MemInst.GetElementPtr getGEP(Value ptr, ArrayList idxs) { 169 | return new MemInst.GetElementPtr(ptr, idxs); 170 | } 171 | 172 | public MemInst.GetElementPtr buildGEP(Value ptr, ArrayList idxs) { 173 | return new MemInst.GetElementPtr(ptr, idxs) {{ 174 | node.insertAtEnd(curBB.list); 175 | }}; 176 | } 177 | 178 | public TerminatorInst.Call getCall(Function func, ArrayList args) { 179 | 180 | return new TerminatorInst.Call(func, args); 181 | } 182 | 183 | public TerminatorInst.Call buildCall(Function func, ArrayList args) { 184 | return new TerminatorInst.Call(func, args) {{ 185 | node.insertAtEnd(curBB.list); 186 | }}; 187 | } 188 | } 189 | 190 | -------------------------------------------------------------------------------- /src/ir/Module.java: -------------------------------------------------------------------------------- 1 | package ir; 2 | 3 | import ir.values.Function; 4 | import ir.values.GlobalVariable; 5 | import util.IList; 6 | 7 | import java.util.ArrayList; 8 | 9 | public class Module { 10 | public ArrayList globalVariables; 11 | public IList functions; 12 | public static final Module module = new Module();//SysY是单文件的,所以module直接单例了 13 | 14 | private Module() { 15 | functions = new IList<>(this); 16 | globalVariables = new ArrayList<>(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ir/User.java: -------------------------------------------------------------------------------- 1 | package ir; 2 | 3 | import ir.type.Type; 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedList; 7 | import java.util.Optional; 8 | 9 | public class User extends Value { 10 | private LinkedList operands = new LinkedList<>();//联系 User 与 Value 的 Use list,是乱序的,顺序通过 Use 的成员变量 operandRank 来体现 11 | private int numOP = 0;//操作数的数量 12 | 13 | public Value getOP(int i) {//这是个 O(n) 的操作,所幸 n 不会太大,而且operands是基本有序的 14 | for (Use use : operands) { 15 | if (use.Rank() == i) { 16 | return use.V(); 17 | } 18 | } 19 | return null; 20 | } 21 | 22 | public void addOperand(Value v) { 23 | operands.add(new Use(v, this, numOP++)); 24 | } 25 | 26 | public void setOperand(Value v, int i) { 27 | assert i < numOP && i >= 0; 28 | //有就替换,无就分一个新的对象 29 | for (Use use : operands) { 30 | if (use.Rank() == i) { 31 | use.V().uses.removeIf(h -> h.equals(use));//从原Value中删去这条use 32 | use.setV(v); 33 | v.uses.add(use); 34 | return; 35 | } 36 | } 37 | Use newUse = new Use(v, this, i); 38 | } 39 | 40 | public int getNumOP() {return numOP;} 41 | 42 | public User(Type type) { 43 | super(type); 44 | } 45 | 46 | public User(Type type, int numOp) { 47 | super(type); 48 | this.numOP = numOp; 49 | } 50 | 51 | //因为JAVA没有友元,所以我把Use作为User的内部类来绕过一些限制 52 | public static class Use { 53 | //Value在User中是第几个操作数, 54 | // 比如 add i32 %a,%b 中 %a 是第0个,记录这个关系的Use的operandRank就是0,%b是第1个 55 | private int operandRank; 56 | private User u; 57 | private Value v; 58 | 59 | public Use(Value v, User u, int operandRank) { 60 | this.v = v; 61 | this.u = u; 62 | this.operandRank = operandRank; 63 | v.uses.add(this); 64 | u.operands.add(this); 65 | } 66 | 67 | public void setV(Value v) {this.v = v;} 68 | 69 | public int Rank() {return operandRank;} 70 | 71 | public Value V() {return v;} 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/ir/Value.java: -------------------------------------------------------------------------------- 1 | package ir; 2 | 3 | import ir.type.Type; 4 | import ir.User.Use; 5 | 6 | import java.util.LinkedList; 7 | 8 | /* 9 | * LLVM 中 Value Use User 的关系介绍 10 | * https://buaa-se-compiling.github.io/miniSysY-tutorial/pre/design_hints.html 11 | */ 12 | 13 | /* 14 | * Value 类,几乎所有实体都是Value的子类 15 | * 16 | */ 17 | public class Value { 18 | public Value(Type type) { 19 | this.type = type; 20 | uses = new LinkedList<>(); 21 | } 22 | 23 | public Type type; 24 | public String name = ""; 25 | protected LinkedList uses; 26 | public boolean needName = true; 27 | 28 | //将所有对 this 的使用换为对v的使用 29 | public void replaceAllUseWith(Value v) { 30 | for (Use use : uses) { 31 | use.setV(v); 32 | v.uses.add(use); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ir/type/ArrayType.java: -------------------------------------------------------------------------------- 1 | package ir.type; 2 | 3 | public class ArrayType extends Type { 4 | private int intContains; //有几个int型的值(因为sysy的base type只有int) 5 | private Type contained; //ArrayType contain的是什么type 6 | private int num_elements;//有几个元素,值得一提的是,LLVM IR 是通过多层嵌套的关系来表示多维数组的,比如一个三位数组可能是[2 x[2 x [2 x i32]]] 7 | 8 | public Type getEleType() {return contained;} 9 | 10 | public int getNumEle() {return num_elements;} 11 | 12 | public int getIntContains() {return intContains;} 13 | 14 | public ArrayType(Type contained, int num_elements) { 15 | assert num_elements > 0; 16 | this.contained = contained; 17 | this.num_elements = num_elements; 18 | if (contained.isIntegerType()) { 19 | intContains = num_elements; 20 | } else { 21 | intContains = ((ArrayType) contained).intContains * num_elements; 22 | } 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "[" + num_elements + " x " + contained.toString() + "]"; 28 | } 29 | } -------------------------------------------------------------------------------- /src/ir/type/FunctionType.java: -------------------------------------------------------------------------------- 1 | package ir.type; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class FunctionType extends Type { 6 | private Type retTy;//函数的返回类型,只有 void 或者 int 7 | private ArrayList paramsTypes;//形参类型的列表 8 | 9 | public FunctionType(Type retTy, ArrayList paramsTypes) { 10 | this.retTy = retTy; 11 | this.paramsTypes = paramsTypes; 12 | } 13 | 14 | public Type getRetTType() {return retTy;} 15 | 16 | public ArrayList getParamsTypes() {return paramsTypes;} 17 | 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/ir/type/IntegerType.java: -------------------------------------------------------------------------------- 1 | package ir.type; 2 | 3 | 4 | /** 5 | * Integer 类型 6 | * numBits是包含的位数 7 | * **/ 8 | public class IntegerType extends Type { 9 | public static final IntegerType i32 = new IntegerType(32);//i32 type,仅携带类型信息,因此用单例 10 | public static final IntegerType i1 = new IntegerType(1);//同上 11 | 12 | public static IntegerType getI32() {return i32;} 13 | 14 | public static IntegerType getI1() {return i1;} 15 | 16 | private IntegerType(int numBits) { 17 | assert numBits > 0; 18 | this.numBits = numBits; 19 | } 20 | 21 | public int getNumBits() { 22 | return numBits; 23 | } 24 | 25 | private int numBits; 26 | 27 | @Override 28 | public String toString() { 29 | if (this.numBits == 32) return "i32"; 30 | if (this.numBits == 1) return "i1"; 31 | return "impossible"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/ir/type/PointerType.java: -------------------------------------------------------------------------------- 1 | package ir.type; 2 | 3 | public class PointerType extends Type { 4 | private Type contained;//指针类型,gv,alloca,getElementPtr 指令都是指针类型的 5 | 6 | public static PointerType getPointTy(Type contained){return new PointerType(contained);} 7 | public PointerType(Type contained) {this.contained = contained;} 8 | 9 | public Type getContained() {return contained;} 10 | 11 | @Override 12 | public String toString() { 13 | return contained.toString() + "* "; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ir/type/Type.java: -------------------------------------------------------------------------------- 1 | package ir.type; 2 | 3 | import java.util.ArrayList; 4 | 5 | /* 6 | * Type 是所有类型的基类 7 | * LLVM IR 是强类型的语言,不允许隐式转换 8 | */ 9 | 10 | 11 | public class Type { 12 | 13 | //给没有Type的Value 14 | public static class NonType extends Type { 15 | private static NonType type = new NonType(); 16 | 17 | public static NonType getType() {return type;} 18 | 19 | private NonType() {} 20 | } 21 | 22 | //Void类型并没有其他额外的信息,所以单例就行 23 | public static class VoidType extends Type { 24 | private static VoidType type = new VoidType(); 25 | 26 | public static VoidType getType() {return type;} 27 | 28 | @Override 29 | public String toString() { 30 | return "void"; 31 | } 32 | 33 | private VoidType() {} 34 | } 35 | 36 | //同上,Label也没有其他额外信息,LabelTyoe是BasicBlock的类型 37 | public static class LabelType extends Type { 38 | public static LabelType getType() { 39 | return type; 40 | } 41 | 42 | private static LabelType type = new LabelType(); 43 | 44 | @Override 45 | public String toString() { 46 | return "label "; 47 | } 48 | 49 | private LabelType() {} 50 | } 51 | 52 | public boolean isLabelTy() {return this instanceof LabelType;} 53 | 54 | public boolean isNonTy() {return this instanceof NonType;} 55 | 56 | public boolean isVoidTy() {return this instanceof VoidType;} 57 | 58 | public boolean isFunctionTy() {return this instanceof FunctionType;} 59 | 60 | public boolean isArrayTy() {return this instanceof ArrayType;} 61 | 62 | public boolean isPointerTy() {return this instanceof PointerType;} 63 | 64 | public boolean isIntegerType() {return this instanceof IntegerType;} 65 | 66 | public boolean isI1() { 67 | if (this instanceof IntegerType o) return o.getNumBits() == 1; 68 | return false; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ir/values/BasicBlock.java: -------------------------------------------------------------------------------- 1 | package ir.values; 2 | 3 | import ir.Value; 4 | import ir.type.Type; 5 | import ir.values.instructions.Inst; 6 | import util.IList; 7 | 8 | import java.util.ArrayList; 9 | 10 | //基本块类 11 | public class BasicBlock extends Value { 12 | private ArrayList predecessors;//这个基本块的前驱结点(能够跳转到这个基本块的基本块) 13 | private ArrayList successors;//这个基本块的后继结点(这个基本块能够跳转到的基本块) 14 | public IList list;// src/util/IList 15 | public IList.INode node;// src/util/IList 16 | private boolean dirty;//标记是否处理过,后面会用到,现在摸了 17 | 18 | public BasicBlock(String name) { 19 | super(Type.LabelType.getType()); 20 | this.predecessors = new ArrayList<>(); 21 | this.successors = new ArrayList<>(); 22 | list = new IList<>(this); 23 | node = new IList.INode<>(this); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/ir/values/Constant.java: -------------------------------------------------------------------------------- 1 | package ir.values; 2 | 3 | import ir.User; 4 | import ir.type.IntegerType; 5 | import ir.type.Type; 6 | 7 | import java.util.ArrayList; 8 | //常量类型,分为常量数值和常量数组 9 | public class Constant extends User { 10 | public Constant(Type type) { 11 | super(type); 12 | } 13 | 14 | public Constant(Type type, int numOp) { 15 | super(type, numOp); 16 | } 17 | 18 | public static class ConstantInt extends Constant { 19 | private int val; 20 | private static final ConstantInt zero = new ConstantInt(IntegerType.getI32(), 0); 21 | 22 | public ConstantInt zero() { 23 | return zero; 24 | } 25 | 26 | @Override 27 | public String toString() {return "i32 " + this.val;} 28 | 29 | public void setVal(int val) {this.val = val;} 30 | 31 | public int getVal() {return val;} 32 | 33 | public ConstantInt(Type type, int val) { 34 | super(type); 35 | this.val = val; 36 | this.name=String.valueOf(this.getVal()); 37 | } 38 | 39 | public static ConstantInt get(int val) { 40 | return new ConstantInt(IntegerType.getI32(), val); 41 | } 42 | } 43 | 44 | public static class ConstantArray extends Constant { 45 | private ArrayList constants; 46 | 47 | public ConstantArray(Type type, ArrayList arr) { 48 | super(type, arr.size()); 49 | for (int i = 0; i < arr.size(); i++) { 50 | setOperand(arr.get(i), i); 51 | } 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/ir/values/Function.java: -------------------------------------------------------------------------------- 1 | package ir.values; 2 | 3 | import ir.Module; 4 | import ir.Value; 5 | import ir.type.FunctionType; 6 | import ir.type.Type; 7 | import util.IList; 8 | import util.IList.INode; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | // 函数类 14 | public class Function extends Value { 15 | private boolean isBuiltin = false;//是否是库函数 16 | public IList list;//src/util/IList 17 | public INode node; 18 | private ArrayList caller;//会在函数内联的时候被用到,用来记录调用自己的函数 19 | private ArrayList callee;//用来记录自己调用的函数 20 | private ArrayList paramList;//形参列表 21 | 22 | public Function(Type type, boolean isBuiltin) { 23 | super(type); 24 | list = new IList<>(this); 25 | node = new INode<>(this); 26 | paramList = new ArrayList<>(); 27 | caller = new ArrayList<>(); 28 | callee = new ArrayList<>(); 29 | this.isBuiltin = isBuiltin; 30 | buildParams(); 31 | } 32 | 33 | private void buildParams() { 34 | var funcTy = this.type; 35 | var arr = ((FunctionType) funcTy).getParamsTypes(); 36 | for (int i = 0; i < arr.size(); i++) { 37 | paramList.add(new Param(arr.get(i), i)); 38 | } 39 | } 40 | 41 | public ArrayList getParamList() { 42 | return paramList; 43 | } 44 | 45 | public boolean isBuiltin() { 46 | return isBuiltin; 47 | } 48 | 49 | 50 | //形参,记录各位置类型,不含值 51 | public class Param extends Value { 52 | private List bounds; 53 | private int rank; 54 | 55 | public Param(Type type, int rank) { 56 | super(type); 57 | this.rank = rank; 58 | } 59 | 60 | public void setBounds(List bounds) {this.bounds = bounds;} 61 | 62 | @Override 63 | public String toString() { 64 | return this.type + " " + this.name; 65 | } 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | StringBuilder sb = new StringBuilder(); 71 | sb.append(((FunctionType) this.type).getRetTType()) 72 | .append(" @") 73 | .append(this.name) 74 | .append("("); 75 | this.paramList.forEach( 76 | param -> { 77 | sb.append(param).append(","); 78 | } 79 | ); 80 | if (paramList.size() != 0) sb.deleteCharAt(sb.length() - 1);//把最后一个逗号删掉 81 | sb.append(")"); 82 | return sb.toString(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ir/values/GlobalVariable.java: -------------------------------------------------------------------------------- 1 | package ir.values; 2 | 3 | import ir.Module; 4 | import ir.User; 5 | import ir.type.PointerType; 6 | import ir.type.Type; 7 | 8 | //全局变量,所有全局变量都是 PointerType的 9 | public class GlobalVariable extends User { 10 | public boolean isConst = false; 11 | public Constant init;//初始化时候的值是需要存储的,但之后进行值的变动就不需要存储了。是体现在指令中的 12 | 13 | public void setConst() {this.isConst = true;} 14 | 15 | public GlobalVariable(String name, Type type) { 16 | super(new PointerType(type));//是地址 17 | this.name = name; 18 | Module.module.globalVariables.add(this); 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | StringBuilder sb = new StringBuilder(); 24 | sb.append(this.name).append(" = dso_local ");//gv 肯定有一个名字 25 | if (isConst) sb.append("constant ");//如果是 constant 26 | else sb.append("global "); 27 | var tmp = ((PointerType) this.type); 28 | if (tmp.getContained().isIntegerType()) {// 这个gv指向的是一个 i32 29 | sb.append(tmp.getContained().toString()); 30 | sb.append(" "); 31 | //没有初始化的值默认其为0 32 | sb.append(this.init == null ? "0 " : ((Constant.ConstantInt) this.init).getVal()); 33 | } else if (tmp.getContained().isArrayTy()) { 34 | if (this.init == null) { 35 | //如果是空的初始化,那么会由 zeroinitializer 代替初始化值 36 | sb.append(tmp.getContained().toString()); 37 | sb.append(" "); 38 | sb.append("zeroinitializer "); 39 | } else sb.append(init); 40 | } 41 | return sb.toString(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ir/values/UndefValue.java: -------------------------------------------------------------------------------- 1 | package ir.values; 2 | 3 | public class UndefValue { 4 | // TODO: 2021/10/25 5 | } 6 | -------------------------------------------------------------------------------- /src/ir/values/instructions/BinaryInst.java: -------------------------------------------------------------------------------- 1 | package ir.values.instructions; 2 | 3 | import ir.Value; 4 | import ir.type.IntegerType; 5 | import ir.type.Type; 6 | // 二元操作指令,加减乘除比较都能够通过这个类来表达,lhs是左手元素,rhs是右手元素 7 | public class BinaryInst extends Inst { 8 | 9 | public BinaryInst(Type type, TAG tag, Value lhs, Value rhs) { 10 | super(type, tag, 2); 11 | if (this.isLogicalBinary()) this.type = IntegerType.getI1(); 12 | if (this.isArithmeticBinary()) this.type = IntegerType.getI32(); 13 | this.setOperand(lhs, 0); 14 | this.setOperand(rhs, 1); 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | StringBuilder sb = new StringBuilder(); 20 | sb.append(this.name).append(" = "); 21 | sb.append(switch (this.tag) { 22 | case Add -> "add i32 "; 23 | case Sub -> "sub i32 "; 24 | case Mul -> "mul i32 "; 25 | case Div -> "sdiv i32 "; 26 | case Lt -> "icmp slt " + this.getOP(0).type + " "; 27 | case Le -> "icmp sle " + this.getOP(0).type + " "; 28 | case Ge -> "icmp sge " + this.getOP(0).type + " "; 29 | case Gt -> "icmp sgt " + this.getOP(0).type + " "; 30 | case Eq -> "icmp eq " + this.getOP(0).type + " "; 31 | case Ne -> "icmp ne " + this.getOP(0).type + " "; 32 | default -> ""; 33 | }); 34 | sb.append(this.getOP(0).name).append(",").append(getOP(1).name); 35 | return sb.toString(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/ir/values/instructions/Inst.java: -------------------------------------------------------------------------------- 1 | package ir.values.instructions; 2 | 3 | import ir.User; 4 | import ir.Value; 5 | import ir.type.Type; 6 | import ir.values.BasicBlock; 7 | import util.IList; 8 | import util.IList.INode; 9 | /* 10 | * Instruction 类,是所有 Inst 的父类 11 | * 它本身是 User 的子类,可见所有的 Inst 都是 User 12 | * 我们通过指令的 TAG 来判断指令的种类 13 | * Inode 的介绍请看 src/util/IList,这是一个侵入式链表的设计,用来挂载到其所在的BB上 14 | * */ 15 | public class Inst extends User { 16 | public TAG tag; 17 | public INode node; 18 | public boolean needname = true; 19 | public BasicBlock getBB() {return this.node.getParent().getVal();} 20 | 21 | public Inst(Type type, TAG tag, int numOP) { 22 | super(type, numOP); 23 | this.tag = tag; 24 | this.node = new INode<>(this); 25 | } 26 | 27 | public enum TAG { 28 | Add,// + 29 | Sub,// - 30 | Mul,// * 31 | Div,// / 32 | Lt, // < 33 | Le, // <= 34 | Ge, // >= 35 | Gt, // > 36 | Eq, // == 37 | Ne, // != 38 | And,// & 39 | Or, // | 40 | //terminator 41 | Br, 42 | Call, 43 | Ret, 44 | //mem op 45 | Alloca, 46 | Load, 47 | Store, 48 | GEP, 49 | Zext, 50 | Phi,//用于 mem2reg 51 | } 52 | 53 | public boolean isBinary() { 54 | return this.tag.ordinal() <= TAG.Or.ordinal() 55 | && this.tag.ordinal() <= TAG.Ge.ordinal(); 56 | } 57 | 58 | public boolean isRelBinary() { 59 | return this.tag.ordinal() >= TAG.Lt.ordinal() && 60 | this.tag.ordinal() <= TAG.Ne.ordinal(); 61 | } 62 | 63 | public boolean isArithmeticBinary() { 64 | return this.tag.ordinal() >= TAG.Add.ordinal() 65 | && this.tag.ordinal() <= TAG.Div.ordinal(); 66 | } 67 | 68 | public boolean isLogicalBinary() { 69 | return this.tag.ordinal() >= TAG.Lt.ordinal() 70 | && this.tag.ordinal() <= TAG.Or.ordinal(); 71 | } 72 | 73 | public boolean isTerminator() { 74 | return this.tag.ordinal() >= TAG.Br.ordinal() 75 | && this.tag.ordinal() <= TAG.Ret.ordinal(); 76 | } 77 | 78 | public boolean isMemOP() { 79 | return this.tag.ordinal() >= TAG.Alloca.ordinal() 80 | && this.tag.ordinal() <= TAG.Phi.ordinal(); 81 | } 82 | 83 | //为了方便 84 | public boolean isAdd() {return this.tag == TAG.Add;} 85 | 86 | public boolean isSub() {return this.tag == TAG.Sub;} 87 | 88 | public boolean isMul() {return this.tag == TAG.Mul;} 89 | 90 | public boolean isDiv() {return this.tag == TAG.Div;} 91 | 92 | public boolean isLt() {return this.tag == TAG.Lt;} 93 | 94 | public boolean isLe() {return this.tag == TAG.Le;} 95 | 96 | public boolean isGe() {return this.tag == TAG.Ge;} 97 | 98 | public boolean isGt() {return this.tag == TAG.Gt;} 99 | 100 | public boolean isEq() {return this.tag == TAG.Eq;} 101 | 102 | public boolean isNe() {return this.tag == TAG.Ne;} 103 | 104 | public boolean isAnd() {return this.tag == TAG.And;} 105 | 106 | public boolean isOr() {return this.tag == TAG.Or;} 107 | 108 | public boolean isGEP() {return this.tag == TAG.GEP;} 109 | 110 | public boolean isLoad() {return this.tag == TAG.Load;} 111 | 112 | public boolean isStore() {return this.tag == TAG.Store;} 113 | 114 | public boolean isPhi() {return this.tag == TAG.Phi;} 115 | 116 | public boolean isRet() {return this.tag == TAG.Ret;} 117 | 118 | public boolean isBr() {return this.tag == TAG.Br;} 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/ir/values/instructions/MemInst.java: -------------------------------------------------------------------------------- 1 | package ir.values.instructions; 2 | 3 | import ir.Value; 4 | import ir.type.ArrayType; 5 | import ir.type.PointerType; 6 | import ir.type.Type; 7 | 8 | import java.util.ArrayList; 9 | 10 | public class MemInst { 11 | // alloca 指令是 pointer 类型的,用来向内存中申请一块空间 12 | public static class Alloca extends Inst { 13 | private boolean isInit = false; 14 | public final Type allocated; 15 | 16 | public Alloca(Type allocated) { 17 | super(new PointerType(allocated), TAG.Alloca, 0); 18 | this.allocated = allocated; 19 | } 20 | 21 | public void setInit() {isInit = true;} 22 | 23 | public boolean isInit() {return isInit;} 24 | 25 | @Override 26 | public String toString() { 27 | return this.name + " = " + "alloca " + allocated; 28 | } 29 | } 30 | 31 | // load指令用于从内存的某个位置中读出值,它的类型是不确定的(当然在本实验中是确定的,只有i32) 32 | public static class Load extends Inst { 33 | 34 | public Load(Type type, Value v) { 35 | super(type, TAG.Load, 1); 36 | this.setOperand(v, 0); 37 | } 38 | 39 | public Value getPointer() {return this.getOP(0);} 40 | 41 | @Override 42 | public String toString() { 43 | return this.name 44 | + " = load " 45 | + this.type 46 | + "," 47 | + this.getOP(0).type 48 | + " " 49 | + this.getOP(0).name; 50 | } 51 | } 52 | 53 | //store 指令用于将某个值存入某个内存位置,store指令是不需要名字的 54 | public static class Store extends Inst { 55 | public Store(Value val, Value pointer) { 56 | super(Type.VoidType.getType(), TAG.Store, 2); 57 | setOperand(val, 0); 58 | setOperand(pointer, 1); 59 | this.needName = false; 60 | } 61 | 62 | 63 | @Override 64 | public String toString() { 65 | StringBuilder sb = new StringBuilder(); 66 | var lhs = getOP(0); 67 | var rhs = getOP(1); 68 | sb.append("store "). 69 | append(lhs.type.toString()). 70 | append(" "). 71 | append(lhs.name). 72 | append(", "). 73 | append(rhs.type.toString()). 74 | append(" "). 75 | append(rhs.name); 76 | return sb.toString(); 77 | } 78 | 79 | public Value getVal() {return this.getOP(0);} 80 | 81 | public Value getPointer() {return this.getOP(1);} 82 | } 83 | //zext 是用于进行类型转换的指令,用于进行 0 拓展,LLVM IR 中不允许隐式类型转换的存在,从 i1(通常出现在比较结果中转换到 i32 需要用到 zext 84 | 85 | public static class Zext extends Inst { 86 | private Type destTy;//will only be i32 in miniSysY 87 | 88 | public Zext(Value val, Type destTy) { 89 | super(destTy, TAG.Zext, 1); 90 | this.destTy = destTy; 91 | this.setOperand(val, 0); 92 | } 93 | 94 | @Override 95 | public String toString() { 96 | //只有从 i1 zext 到 i32 的情况 97 | return this.name 98 | + " = " 99 | + "zext i1 " 100 | + this.getOP(0).name 101 | + " to i32"; 102 | } 103 | } 104 | 105 | //**计算**这个指针指向的元素的**类型** 106 | private static Type getElementType(Value ptr, ArrayList indices) { 107 | assert ptr.type.isPointerTy(); 108 | Type type = ((PointerType) ptr.type).getContained(); 109 | if (type.isIntegerType()) return type; 110 | else if (type.isArrayTy()) { 111 | for (int i = 1; i < indices.size(); i++) { 112 | type = ((ArrayType) type).getEleType(); 113 | } 114 | return type; 115 | } 116 | return null; 117 | } 118 | 119 | 120 | // 第一个 operand 是 pointer ,之后的 operand 是 indice 121 | public static class GetElementPtr extends Inst { 122 | private final Type elementType_; 123 | 124 | public GetElementPtr(Value pointer, ArrayList idx) { 125 | super(new PointerType(getElementType(pointer, idx)), TAG.GEP, idx.size() + 1); 126 | setOperand(pointer, 0); 127 | for (int i = 0; i < idx.size(); i++) { 128 | setOperand(idx.get(i), i + 1); 129 | } 130 | elementType_ = getElementType(pointer, idx); 131 | } 132 | 133 | @Override 134 | public String toString() { 135 | StringBuilder b = new StringBuilder(); 136 | b 137 | .append(this.name) 138 | .append("= getelementptr ") 139 | .append(((PointerType) getOP(0).type).getContained()) 140 | .append(",") 141 | .append(getOP(0).type) 142 | .append(" ") 143 | .append(getOP(0).name) 144 | .append(" "); 145 | for (int i = 1; i < getNumOP(); i++) { 146 | b 147 | .append(", ") 148 | .append(getOP(i).type) 149 | .append(" ") 150 | .append(getOP(i).name); 151 | } 152 | return b.toString(); 153 | } 154 | } 155 | 156 | public static class Phi extends Inst { 157 | public Phi(Type type, TAG tag, int numOP) { 158 | super(type, tag, numOP); 159 | } 160 | //todo 161 | } 162 | 163 | 164 | } 165 | -------------------------------------------------------------------------------- /src/ir/values/instructions/TerminatorInst.java: -------------------------------------------------------------------------------- 1 | package ir.values.instructions; 2 | 3 | import ir.Value; 4 | import ir.type.FunctionType; 5 | import ir.type.Type; 6 | import ir.values.BasicBlock; 7 | import ir.values.Function; 8 | 9 | import java.util.ArrayList; 10 | 11 | public class TerminatorInst { 12 | //函数调用指令,第一个 operand 是函数,后面的是传入的实参 13 | public static class Call extends Inst { 14 | public Call(Function function, ArrayList args) { 15 | super(((FunctionType) function.type).getRetTType(), TAG.Call, args.size() + 1); 16 | if (this.type.isVoidTy()) { 17 | needName = false; 18 | retVoid = true; 19 | } else { 20 | retVoid = false; 21 | } 22 | setOperand(function, 0); 23 | for (int i = 0; i < args.size(); i++) { 24 | setOperand(args.get(i), i + 1); 25 | } 26 | } 27 | 28 | public Function getFunc() {return (Function) this.getOP(0);} 29 | 30 | public final boolean retVoid; 31 | 32 | @Override 33 | public String toString() { 34 | StringBuilder sb = new StringBuilder(); 35 | if (retVoid) { 36 | sb.append("call ").append(this.type).append(" @").append(this.getOP(0).name); 37 | } else { 38 | sb.append(this.name).append(" = call ").append(this.type).append(" @") 39 | .append(this.getOP(0).name); 40 | } 41 | sb.append("("); 42 | boolean a = false; 43 | for (int i = 1; i < this.getNumOP(); i++) { 44 | a = true; 45 | sb.append(this.getOP(i).type) 46 | .append(" "). 47 | append(this.getOP(i).name) 48 | .append(","); 49 | } 50 | if (a) { 51 | sb.deleteCharAt(sb.length() - 1); 52 | } 53 | sb.append(")"); 54 | return sb.toString(); 55 | } 56 | } 57 | //分支跳转指令,有条件跳转中的第一个 operand 是条件变量,是一个 i1 的值,这个值为 1 会跳往 trueblock,为 0 会跳往 falseblock 58 | public static class Br extends Inst { 59 | public Br(Value cond, BasicBlock trueBlock, BasicBlock falseBlock) {//有条件跳转 60 | super(Type.LabelType.getType(), TAG.Br, 3); 61 | setOperand(cond, 0); 62 | setOperand(trueBlock, 1); 63 | setOperand(falseBlock, 2); 64 | needName = false; 65 | } 66 | 67 | public Br(BasicBlock trueBlock) {//无条件跳转 68 | super(Type.LabelType.getType(), TAG.Br, 1); 69 | setOperand(trueBlock, 0); 70 | needName = false; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | StringBuilder sb = new StringBuilder(); 76 | sb.append("br "); 77 | if (this.getNumOP() == 1) { 78 | sb.append(getOP(0).type).append(" ").append("%" + getOP(0).name); 79 | } 80 | if (this.getNumOP() == 3) { 81 | sb.append(getOP(0).type).append(" ").append(getOP(0).name) 82 | .append(","); 83 | sb.append(getOP(1).type).append(" ").append("%").append(getOP(1).name) 84 | .append(","); 85 | sb.append(getOP(2).type).append(" ").append("%").append(getOP(2).name) 86 | .append(" "); 87 | } 88 | sb.append("\n"); 89 | return sb.toString(); 90 | } 91 | } 92 | 93 | public static class Ret extends Inst { 94 | public Ret() { //ret void 95 | super(Type.VoidType.getType(), TAG.Ret, 0); 96 | needName = false; 97 | } 98 | 99 | public Ret(Value val) {//ret non-void 100 | super(Type.VoidType.getType(), TAG.Ret, 1); 101 | this.setOperand(val, 0); 102 | needName = false; 103 | } 104 | 105 | @Override 106 | public String toString() { 107 | StringBuilder sb = new StringBuilder(); 108 | sb.append("ret "); 109 | if (this.getNumOP() == 1) { 110 | sb.append(getOP(0).type + " " + getOP(0).name); 111 | } else { 112 | sb.append("void "); 113 | } 114 | return sb.toString(); 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/util/IList.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Iterator; 4 | 5 | /*** 6 | * 这是一个侵入式链表的非常规实现 7 | * 侵入式链表和一般链表的区别在于 8 | * 一般的链表是链表结点中存储了元素 9 | * Node{ 10 | * YourEleType yourEle; 11 | * Node prev; 12 | * Node succ; 13 | * } 14 | * 而侵入式链表是元素中存储了链表结点 15 | * YourEleType{ 16 | * Node prev; 17 | * Node succ; 18 | * } 19 | * 这样做的好处是你在拿到一个元素(而不是这个元素的Node)的时候, 20 | * 能够很方便地知道这个元素的前一个元素和后一个元素是什么 21 | * 22 | * 如果你们这学期的OS实验还是 pintos, 23 | * 那实际上这个链表的和 pintos 里面的内核链表是差不多的 24 | * ps: linux 里面的链表也是这个设计,所以这种链表又称作内核链表 25 | * ***/ 26 | // 27 | public class IList implements Iterable> { 28 | private P val; 29 | //持有链表头的元素,比如一个 BasicBlock 持有了一个包含多个 Inst 的链表 30 | // ,那这个val就是这个BasicBlock 31 | private INode head;//邵兵结点,不存储数据 32 | private INode trailer;//邵兵结点 33 | private int numNode = 0;//节点数 34 | 35 | public IList(P val) { 36 | this.val = val; 37 | head = new INode<>(); 38 | head.setParent(this); 39 | 40 | trailer = new INode<>(); 41 | trailer.setParent(this); 42 | head.succ = trailer; 43 | trailer.prev = head; 44 | } 45 | 46 | public int getNumNode() {return numNode;} 47 | 48 | public P getVal() {return val;} 49 | 50 | public INode getEntry() {return head.succ;} 51 | 52 | public INode getLast() {return trailer.prev;} 53 | 54 | @Override 55 | public Iterator> iterator() {return new IIterator(head, trailer);} 56 | 57 | class IIterator implements Iterator> { 58 | INode head; 59 | INode trailer; 60 | INode tmp; 61 | 62 | IIterator(INode head, INode trailer) { 63 | this.head = head; 64 | this.trailer = trailer; 65 | tmp = head; 66 | } 67 | 68 | @Override 69 | public boolean hasNext() { 70 | return tmp.succ != trailer; 71 | } 72 | 73 | @Override 74 | public INode next() { 75 | var t = tmp.succ; 76 | tmp = tmp.succ; 77 | return t; 78 | } 79 | 80 | @Override 81 | public void remove() { 82 | throw new UnsupportedOperationException(); 83 | } 84 | } 85 | 86 | public static class INode { 87 | public final boolean isguard; 88 | private T val; 89 | private INode prev = null;//前驱 90 | private INode succ = null;//后继 91 | private IList parent = null; 92 | 93 | public INode() {this.isguard = true;}//只用来产生哨兵 94 | 95 | public INode(T t) { 96 | this.val = t; 97 | this.isguard = false; 98 | } 99 | 100 | public T getVal() {return val;} 101 | 102 | public void setVal(T newVal) {this.val = newVal;} 103 | 104 | public void setParent(IList parent) {this.parent = parent;} 105 | 106 | public IList getParent() {return parent;} 107 | 108 | public INode getPrev() {return prev;} 109 | 110 | public INode getNext() {return succ;} 111 | 112 | //将自己插入prev后面 113 | public void insertAsPrevOf(INode prev) { 114 | this.parent = prev.parent; 115 | this.parent.numNode++; 116 | this.prev = prev; 117 | this.succ = prev.succ; 118 | prev.succ = this; 119 | if (this.succ != null) this.succ.prev = this; 120 | } 121 | 122 | //将自己插入目标结点前面 123 | public void insertAsSuccOf(INode succ) { 124 | this.parent = succ.parent; 125 | this.parent.numNode++; 126 | this.prev = succ.prev; 127 | this.succ = succ; 128 | succ.prev = this; 129 | if (this.prev != null) this.prev.succ = this; 130 | } 131 | 132 | //将自己插入目标IList的开头 133 | public void insertAtEntry(IList father) { 134 | this.setParent(father); 135 | father.numNode++; 136 | insertAsPrevOf(father.head); 137 | } 138 | 139 | 140 | // 将自己插入目标IList的末尾 141 | public void insertAtEnd(IList father) { 142 | this.setParent(father); 143 | father.numNode++; 144 | insertAsSuccOf(father.trailer); 145 | } 146 | 147 | public boolean removeSelf() { 148 | if (this.parent == null) return false; 149 | this.succ.prev = this.prev; 150 | this.prev.succ = this.succ; 151 | this.parent.numNode--; 152 | this.parent = null; 153 | return true; 154 | } 155 | } 156 | 157 | } 158 | 159 | 160 | --------------------------------------------------------------------------------