diff --git a/.gitignore b/.gitignore index db30932fda5748c0db3fa329c334e61c562cf9b4..278f4e458d09b5b2b03fb6922f0926769a5577b4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ *.tar.gz target *.log -test/lib/sylib.ll \ No newline at end of file +test/lib/sylib.ll +.VSCodeCounter +*.pri.* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index b789f52daca5d2b189ed15cfa00760b812fef0b4..d91d524d00f0104eb7bd28c47a311c1942c333cb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,4 +5,5 @@ "java.project.sourcePaths": [ "src/main/java" ], + "java.format.comments.enabled": false } \ No newline at end of file diff --git a/docs/bugs.md b/docs/bugs.md index c1f9ec7a664ca6afd7807fd157e601ca8d2204aa..db0fb84a2204f9ea3b8f0a0edbefc9c824bde338 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -3,7 +3,7 @@ src\main\java\dst\AstDeclVisitor.java 在访问visitConstDef时使用的ä¾ç„¶æ˜¯DeclType.VAR,改为了DeclType.CONST。然åŽå‡ºçŽ°äº†ä¸‹é¢çš„bug。 -exp 展开æˆå˜é‡æ—¶ï¼Œèµ°çš„æ˜¯`PrimaryExp → '(' Exp ')' | LVal | Numbe`ï¼Œå› æ¤å³ä½¿ä¸æ˜¯èµ‹å€¼è¯å¥ä¹Ÿä¼šå±•开为LVal。如果在è¯ä¹‰æ£€æŸ¥ä¸è®¤ä¸ºLValä¸èƒ½å¼•用constå˜é‡åˆ™ä¼šå‡ºçŽ°é—®é¢˜ã€‚ +exp 展开æˆå˜é‡æ—¶ï¼Œèµ°çš„æ˜¯`PrimaryExp → '(' Exp ')' | LVal | Number`ï¼Œå› æ¤å³ä½¿ä¸æ˜¯èµ‹å€¼è¯å¥ä¹Ÿä¼šå±•开为LVal。如果在è¯ä¹‰æ£€æŸ¥ä¸è®¤ä¸ºLValä¸èƒ½å¼•用constå˜é‡åˆ™ä¼šå‡ºçŽ°é—®é¢˜ã€‚ ### å‘点 diff --git a/script/build.sh b/script/build.sh index d994cd4bd8fe2364aa973d51d99ae67782187548..fce6d7d71cc552dd5baa67fcbeb3354f428aa95f 100755 --- a/script/build.sh +++ b/script/build.sh @@ -1,3 +1,9 @@ +# +# æ¤è„šæœ¬ç”¨äºŽæž„å»ºå’Œæ‰“åŒ… compiler.jar +# +# 用法: +# ./script/build.sh +# BASEDIR=$(realpath $(dirname "$0")/..) echo "BASEDIR: $BASEDIR" ANTLR_LIB=$BASEDIR/lib/antlr4-4.8-1-complete.jar diff --git a/script/functional_test.sh b/script/functional_test.sh index d10e8b50dd64d11a0f7df19bec5f955b0c018b09..bd3594634504eb4f48c31cab487c2e5181e2bc02 100644 --- a/script/functional_test.sh +++ b/script/functional_test.sh @@ -1,3 +1,11 @@ +# +# æ¤è„šæœ¬æ‰§è¡Œæ‰€æœ‰æµ‹è¯• +# +# 用法: +# ./script/functional_test.sh +# + + BASEDIR=$(realpath $(dirname "$0")/..) RED='\033[0;34m' NC='\033[0m' # No Color diff --git a/script/functional_test_one.sh b/script/functional_test_one.sh index 0fc5630fea6bbddb48cae46c0404abbb9bc3b188..2252f7b3144b36c9dbc57a1c24115a43c63d5ef1 100644 --- a/script/functional_test_one.sh +++ b/script/functional_test_one.sh @@ -1,8 +1,15 @@ +# +# æ¤è„šæœ¬æ‰§è¡Œä¸€ä¸ªæµ‹è¯• +# +# 用法: +# ./script/functional_test_one.sh SOUCE_FILE OUTPUT_FILE +# + BASEDIR=$(realpath $(dirname "$0")/..) RED='\033[0;34m' NC='\033[0m' # No Color -function runone { +function run_one { java -DlogLevel=trace \ -jar $BASEDIR/target/compiler.jar \ -S -o $2 \ @@ -19,7 +26,7 @@ set -e; # error exit file=$BASEDIR/test/functional/${1} name=$(basename $file) printf "${RED}--- Compile IR ${file} ---${NC}\n" -runone $file $BASEDIR/target/test/functional/${name}.ll +run_one $file $BASEDIR/target/test/functional/${name}.ll clang $BASEDIR/test/lib/sylib.ll $BASEDIR/target/test/functional/${name}.ll -o $BASEDIR/target/test/functional/${name}.elf printf "${RED}--- Testing IR ${file} ---${NC}\n" if [ ! -f $BASEDIR/test/functional/${name%.*}.in ]; then @@ -28,7 +35,7 @@ else python3 $BASEDIR/script/functional_checker.py ir $BASEDIR/target/test/functional/${name}.elf $BASEDIR/test/functional/${name%.*}.out $BASEDIR/test/functional/${name%.*}.in fi printf "${RED}--- Compile ASM ${file} ---${NC}\n" -runone $file $BASEDIR/target/test/functional/${name}.S +run_one $file $BASEDIR/target/test/functional/${name}.S arm-linux-gnueabihf-gcc-10 -march=armv7-a -static $BASEDIR/target/test/functional/${name}.S $BASEDIR/test/lib/libsysy.a -o $BASEDIR/target/test/functional/${name}.arm.elf printf "${RED}--- Testing ASM ${file} ---${NC}\n" if [ ! -f $BASEDIR/test/functional/${name%.*}.in ]; then diff --git a/script/gen.sh b/script/gen.sh index 6568900733c56d651be8cd21ba692924e1ed99e3..413146c68daa3d925197003fecf15feffeca8f49 100755 --- a/script/gen.sh +++ b/script/gen.sh @@ -1,3 +1,10 @@ +# +# æ¤è„šæœ¬ä»Ž g4 文件利用 antlr ç”Ÿæˆ lexer å’Œ parser +# +# 用法: +# ./script/gen.sh +# + BASEDIR=$(realpath $(dirname "$0")/..) echo "BASEDIR: $BASEDIR" RED='\033[0;34m' diff --git a/script/qemu_debug.sh b/script/qemu_debug.sh index 8b23b5ca44b7162bb386a947b0ccbe5c28d6a86a..8be2fde896cb2b649430c446ec30d678b0d0efdb 100644 --- a/script/qemu_debug.sh +++ b/script/qemu_debug.sh @@ -1,2 +1,10 @@ +# +# æ¤è„šæœ¬è¿è¡Œ arm 虚拟机 +# +# 用法: +# ./script/functional_test_one.sh FILE +# +# -g 傿•°æŒ‡å®šè°ƒè¯•ç«¯å£ + #!/bin/bash qemu-arm -L /usr/arm-linux-gnueabihf/ -g 12345 $1 \ No newline at end of file diff --git a/src/main/java/dst/ds/Decl.java b/src/main/java/dst/ds/Decl.java index 7a978eac09bc51491450b58bd7b38d4f0de61439..e5bd11245998cfd0a6b2964b8bdb5228b04d00ad 100644 --- a/src/main/java/dst/ds/Decl.java +++ b/src/main/java/dst/ds/Decl.java @@ -21,7 +21,13 @@ public class Decl extends BlockStatement { public List<Expr> dims; // è¯ä¹‰åˆ†æžåŽè½¬ä¸ºList<Integer>å˜æ”¾åˆ°Type.dimsä¸ // public List<Integer> evaledDims; - // å‡½æ•°å‚æ•°ä¸ºæ•°ç»„çœç•¥ç¾åï¼Œå› ä¸ºè¯ä¹‰åˆ†æžçš„æ—¶å€™æ‰å¡«å…¥Type,所以这里也需è¦ä¸€ä¸ªæˆå‘˜ + /** + * isDimensionOmitted è¯´æ˜Žæ¤ Decl,作为一个函数的**傿•°**,是一个数组,但是没有给出维度信æ¯ã€‚ + * æ¯”å¦‚è¿™æ ·çš„å‚æ•°ï¼š`int arr[]`。那么æ¤å¤„就会 true + * + * 默认情况下这里是 false, 也å³ç»™äº†ç»´åº¦è¡¨è¾¾å¼ï¼Œé‚£ä¹ˆä¸€å®šä¸æ˜¯ä¸€ä¸ªå‡½æ•°å‚æ•° + * å‡½æ•°å‚æ•°ä¸ºæ•°ç»„çœç•¥ç¾åï¼Œå› ä¸ºè¯ä¹‰åˆ†æžçš„æ—¶å€™æ‰å¡«å…¥Type,所以这里也需è¦ä¸€ä¸ªæˆå‘˜ + */ public boolean isDimensionOmitted = false; // Right hand side diff --git a/src/main/java/dst/ds/LValExpr.java b/src/main/java/dst/ds/LValExpr.java index 01f2d51c8726c9ccf8c34eea9983b1cba1f6ad5b..1cc9fb2e273165a85177146ee7dc169d467f3a3b 100644 --- a/src/main/java/dst/ds/LValExpr.java +++ b/src/main/java/dst/ds/LValExpr.java @@ -9,7 +9,10 @@ import ir.ds.Scope; public class LValExpr extends Expr { public String id; - public boolean isArray; // æ˜¯å¦æœ‰æ–¹æ‹¬å·è¡¨è¾¾å¼ + /** + * æ˜¯å¦æœ‰æ–¹æ‹¬å·è¡¨è¾¾å¼ï¼ˆå³æ˜¯å¦æ˜¯è®¿é—®æ•°ç»„) + */ + public boolean isArray; public List<Expr> indices; public DeclSymbol declSymbol; diff --git a/src/main/java/ssa/FakeSSAGenerator.java b/src/main/java/ssa/FakeSSAGenerator.java index 78e4a0bfd7fa2c3d6a0deb8049ec62f166d94070..4f7d2f54ab59e304ea203bf5edeb1e493e3d1583 100644 --- a/src/main/java/ssa/FakeSSAGenerator.java +++ b/src/main/java/ssa/FakeSSAGenerator.java @@ -72,8 +72,13 @@ public class FakeSSAGenerator { } private void visitBuiltinDstFunc(FakeSSAGeneratorContext ctx, dst.ds.Func dstFunc) { + // params var pvs = new ArrayList<ParamValue>(); - dstFunc.params.forEach(decl -> {pvs.add(new ParamValue(decl.id, convertDstType(decl.type)));}); + dstFunc.params.forEach(decl -> { + pvs.add(new ParamValue(decl.id, convertDstType(decl.type))); + }); + + // create ssa func Func func = new Func(dstFunc.id, dstFunc.retType, pvs); if (dstFunc.isVariadic != null) { func.setIsVariadic(dstFunc.isVariadic); @@ -83,6 +88,12 @@ public class FakeSSAGenerator { ctx.funcMap.put(dstFunc, val); } + /** + * 用于将 dst Type 转æ¢ä¸º SSA Type + * + * @param type + * @return + */ private Type convertDstType(dst.ds.Type type) { if (type.basicType == BasicType.STRING_LITERAL) { // string literal应该ä¸å¯èƒ½æ˜¯array @@ -138,7 +149,7 @@ public class FakeSSAGenerator { int currentSize = type.dims.get(0); // è¯ä¹‰æ£€æŸ¥åŽåº”该initVal的层次结构和typeçš„dimsåŒ¹é… assert initVal.values.size() == currentSize; - for (int i=0;i<currentSize;i++) { + for (int i = 0; i < currentSize; i++) { var v = convertArrayEvaledValue(type.subArrType(), initVal.values.get(i)); result.add(v); } @@ -146,10 +157,13 @@ public class FakeSSAGenerator { } } + /** + * Dst EvaluatedValue 转化为 SSA 常数(组) + */ private static ConstantValue convertEvaledValue(EvaluatedValue evaledVal) { if (evaledVal.basicType == BasicType.STRING_LITERAL) { // String转i8数组 List<ConstantValue> chars = new ArrayList<>(); - for (byte c: evaledVal.stringValue.getBytes()) { + for (byte c : evaledVal.stringValue.getBytes()) { chars.add(ConstantValue.ofChar(c)); } chars.add(ConstantValue.ofChar(0)); @@ -161,13 +175,18 @@ public class FakeSSAGenerator { case INT: return ConstantValue.ofInt(evaledVal.intValue); default: - throw new RuntimeException("Unknown basicType "+evaledVal.basicType.toString()); + throw new RuntimeException("Unknown basicType " + evaledVal.basicType.toString()); } } private void visitDstFunc(FakeSSAGeneratorContext ctx, dst.ds.Func dstFunc) { + // params var pvs = new ArrayList<ParamValue>(); - dstFunc.params.forEach(decl -> {pvs.add(new ParamValue(decl.id, convertDstType(decl.type)));}); + dstFunc.params.forEach(decl -> { + pvs.add(new ParamValue(decl.id, convertDstType(decl.type))); + }); + + // create func object Func func = new Func(dstFunc.id, dstFunc.retType, pvs); if (dstFunc.isVariadic != null) { func.setIsVariadic(dstFunc.isVariadic); @@ -177,18 +196,16 @@ public class FakeSSAGenerator { ctx.funcMap.put(dstFunc, val); ctx.currentFunc = func; - // å…¥å£åŸºæœ¬å— + // entry basic block for func func.bbs = new LinkedList<>(); BasicBlock ent = new BasicBlock("entry"); func.bbs.add(ent); ctx.current = ent; - // å‡½æ•°å‚æ•° - // dstFunc.params.forEach(param -> visitFuncParamDecl(ctx, )); - // dstFunc.params.forEach(param -> { - for (int i=0;i<dstFunc.params.size();i++) { + // create insts for params and add to current bb + for (int i = 0; i < dstFunc.params.size(); i++) { var param = dstFunc.params.get(i); - var ref = pvs.get(i); + ParamValue ref = pvs.get(i); ref.name = param.id; if (param.isArray()) { // array傿•°ä¸éœ€è¦åˆ›å»ºalloca指令 @@ -196,22 +213,25 @@ public class FakeSSAGenerator { } else { var alloc = new AllocaInst.Builder(ent).addType(convertDstType(param.type)).build(); alloc.name = ctx.nameLocal(param.id); - ctx.addToCurrent(alloc); + ctx.addToCurrentBB(alloc); ctx.varMap.put(param, alloc); var inst = new StoreInst.Builder(ent).addOperand(ref, alloc).build(); - ctx.addToCurrent(inst); + ctx.addToCurrentBB(inst); } } - // }); - - dstFunc.body.statements.forEach(bs -> {visitDstStmt(ctx, func, bs);}); + // 生æˆå‡½æ•°ä½“çš„ insts + dstFunc.body.statements.forEach(bs -> { + visitDstStmt(ctx, func, bs); + }); // æŒ‡ä»¤ç”Ÿæˆæ˜¯çº¿æ€§æ¨¡åž‹ï¼Œæ¯”如int f(){if(){..} else {...}}我也需è¦åœ¨æœ«å°¾åŠ ä¸Šä¸€ä¸ªåŸºæœ¬å—,ä¿è¯æ˜¯å’Œif elseåŒçº§çš„, // 如果最åŽä¸€ä¸ªåŸºæœ¬å—最åŽä¸æ˜¯è¿”å›žæŒ‡ä»¤ï¼ŒåŠ ä¸Šè¿”å›žæŒ‡ä»¤ã€‚ var current = ctx.current; - // å¦‚æžœåŸºæœ¬å—æ²¡æœ‰ç”¨TerminatorInstç»“å°¾ï¼ŒåŠ å…¥RetInst - if (current.insts.size() == 0 || !(current.insts.get(current.insts.size()-1) instanceof TerminatorInst)) { - var b = new RetInst.Builder(current); + + // å¦‚æžœåŸºæœ¬å—æ²¡æœ‰ç”¨ TerminatorInst ç»“å°¾ï¼ŒåŠ å…¥ RetInst + if (current.insts.size() == 0 || !(current.insts.get(current.insts.size() - 1) instanceof TerminatorInst)) { + var b = new RetInst.Builder(current); + // 自动生æˆè¿”回值 if (func.retType == FuncType.VOID) { b.addType(Type.Void); } else if (func.retType == FuncType.INT) { @@ -226,18 +246,19 @@ public class FakeSSAGenerator { current.insts.add(b.build()); } // 如果基本å—以éžRetInst结尾,报错。 - if (!(current.insts.get(current.insts.size()-1) instanceof RetInst)) { + if (!(current.insts.get(current.insts.size() - 1) instanceof RetInst)) { throw new RuntimeException("Function " + dstFunc.id + ": generated code not end with return."); } } + // 生æˆè¡¨è¾¾å¼çš„ SSA IR private void visitDstStmt(FakeSSAGeneratorContext ctx, Func curFunc, BlockStatement stmt_) { if (stmt_ instanceof AssignStatement) { var stmt = (AssignStatement) stmt_; - // 在assign左边的LVal一般直接是值 + // 在assign左边的LVal一般直接是值 var left = visitLValExpr(ctx, curFunc, stmt.left, true); // 获å–ä»£è¡¨çš„åœ°å€ var right = visitDstExpr(ctx, curFunc, stmt.expr); - ctx.addToCurrent(new StoreInst.Builder(ctx.current).addOperand(right, left).build()); + ctx.addToCurrentBB(new StoreInst.Builder(ctx.current).addOperand(right, left).build()); return; } @@ -249,14 +270,14 @@ public class FakeSSAGenerator { if (stmt_ instanceof BreakStatement) { var stmt = (BreakStatement) stmt_; - var inst = ctx.addToCurrent(new JumpInst(ctx.current, ctx.breakMap.get(stmt.loop))); + var inst = ctx.addToCurrentBB(new JumpInst(ctx.current, ctx.breakMap.get(stmt.loop))); inst.comments = "break"; return; } if (stmt_ instanceof ContinueStatement) { var stmt = (ContinueStatement) stmt_; - var inst = ctx.addToCurrent(new JumpInst(ctx.current, ctx.continueMap.get(stmt.loop))); + var inst = ctx.addToCurrentBB(new JumpInst(ctx.current, ctx.continueMap.get(stmt.loop))); inst.comments = "continue"; return; } @@ -275,27 +296,28 @@ public class FakeSSAGenerator { if (stmt_ instanceof IfElseStatement) { var stmt = (IfElseStatement) stmt_; - int ind = ctx.getBBInd(); - var trueBlock = new BasicBlock("if_true_"+ind); - var exitBlock = new BasicBlock("if_end_"+ind); + int ind = ctx.nextBBIdx(); + var trueBlock = new BasicBlock("if_true_" + ind); + var exitBlock = new BasicBlock("if_end_" + ind); var falseBlock = exitBlock; if (stmt.elseBlock != null) { - falseBlock = new BasicBlock("if_false_"+ind); + falseBlock = new BasicBlock("if_false_" + ind); } // var cond = this.visitDstExpr(ctx, curFunc, stmt.condition); - // ctx.addToCurrent(new BranchInst(ctx.current, cond, trueBlock.getValue(), falseBlock.getValue())); + // ctx.addToCurrent(new BranchInst(ctx.current, cond, trueBlock.getValue(), + // falseBlock.getValue())); visitCondExprs(ctx, curFunc, stmt.condition.expr, trueBlock.getValue(), falseBlock.getValue()); // 在true blockç”ŸæˆæŒ‡ä»¤ ctx.current = trueBlock; curFunc.bbs.add(trueBlock); this.visitDstStmt(ctx, curFunc, stmt.thenBlock); - ctx.addToCurrent(new JumpInst(ctx.current, exitBlock.getValue())); + ctx.addToCurrentBB(new JumpInst(ctx.current, exitBlock.getValue())); if (stmt.elseBlock != null) { ctx.current = falseBlock; curFunc.bbs.add(falseBlock); this.visitDstStmt(ctx, curFunc, stmt.elseBlock); - ctx.addToCurrent(new JumpInst(ctx.current, exitBlock.getValue())); + ctx.addToCurrentBB(new JumpInst(ctx.current, exitBlock.getValue())); } ctx.current = exitBlock; curFunc.bbs.add(exitBlock); @@ -303,27 +325,43 @@ public class FakeSSAGenerator { } if (stmt_ instanceof LoopStatement) { - var stmt = (LoopStatement) stmt_; + /* + * <while_entry> <--\ + * while (cond) { | + * <while_body> | + * block---------/ + * } + * <while_end>: + */ + var loopStmt = (LoopStatement) stmt_; // 由于è¦è·³è½¬åˆ°expr计算的å‰é¢ï¼Œè¿™é‡Œè¦åˆ†å‰²ä¸€ä¸ªåŸºæœ¬å— - int ind = ctx.getBBInd(); - var entBlock = new BasicBlock("while_entry_"+ind); - ctx.addToCurrent(new JumpInst(ctx.current, entBlock.getValue())); - ctx.current = entBlock; - curFunc.bbs.add(entBlock); - var bodyBlock = new BasicBlock("while_body_"+ind); - var exitBlock = new BasicBlock("while_end_"+ind); + int bbid = ctx.nextBBIdx(); + var entBlock = new BasicBlock("while_entry_" + bbid); + { + ctx.addToCurrentBB(new JumpInst(ctx.current, entBlock.getValue())); + ctx.current = entBlock; + curFunc.bbs.add(entBlock); + } + var bodyBlock = new BasicBlock("while_body_" + bbid); + var exitBlock = new BasicBlock("while_end_" + bbid); // var cond = this.visitDstExpr(ctx, curFunc, stmt.condition); - // ctx.addToCurrent(new BranchInst(ctx.current, cond, bodyBlock.getValue(), exitBlock.getValue())); - visitCondExprs(ctx, curFunc, stmt.condition.expr, bodyBlock.getValue(), exitBlock.getValue()); + // cx.addToCurrent(new BranchInst(ctx.current, cond, bodyBlock.getValue(), + // exitBlock.getValue())); - // set continue and brek map; - ctx.breakMap.put(stmt, exitBlock.getValue()); - ctx.continueMap.put(stmt, entBlock.getValue()); + // 生æˆå¾ªçޝæ¡ä»¶æŒ‡ä»¤å¹¶å…³è”æ¡ä»¶è·³è½¬ç›®æ ‡ + visitCondExprs(ctx, curFunc, loopStmt.condition.expr, bodyBlock.getValue(), exitBlock.getValue()); + + // 设置本循环è¯å¥çš„ continue å’Œ break è¯å¥çš„è·³è½¬ç›®æ ‡ + ctx.breakMap.put(loopStmt, exitBlock.getValue()); + ctx.continueMap.put(loopStmt, entBlock.getValue()); ctx.current = bodyBlock; curFunc.bbs.add(bodyBlock); - this.visitDstStmt(ctx, curFunc, stmt.bodyBlock); - ctx.addToCurrent(new JumpInst(ctx.current, entBlock.getValue())); + + // 生æˆå¾ªçŽ¯ä½“çš„æŒ‡ä»¤ + this.visitDstStmt(ctx, curFunc, loopStmt.bodyBlock); + // 循环体末尾跳转到 <while_entry> + ctx.addToCurrentBB(new JumpInst(ctx.current, entBlock.getValue())); ctx.current = exitBlock; curFunc.bbs.add(exitBlock); @@ -335,14 +373,23 @@ public class FakeSSAGenerator { var val = visitDstExpr(ctx, curFunc, stmt.retval); var b = new RetInst.Builder(ctx.current); b.addType(curFunc.getRetType()); + // 若有返回值 if (curFunc.retType != FuncType.VOID) { b.addOperand(val); } - ctx.addToCurrent(b.build()); + ctx.addToCurrentBB(b.build()); return; } } + /** + * 处ç†å„ç§å„æ ·ç±»åž‹çš„è¡¨è¾¾å¼ SSA ç”Ÿæˆ + * + * @param ctx + * @param curFunc + * @param expr_ + * @return + */ private Value visitDstExpr(FakeSSAGeneratorContext ctx, Func curFunc, Expr expr_) { if (expr_ instanceof CastExpr) { var expr = (CastExpr) expr_; @@ -355,7 +402,7 @@ public class FakeSSAGenerator { } var cast = new CastInst.Builder(ctx.current, val).addOp(op).build(); cast.comments = expr.reason; - ctx.addToCurrent(cast); + ctx.addToCurrentBB(cast); return cast; } @@ -367,13 +414,17 @@ public class FakeSSAGenerator { if (expr.op.isBoolean()) { if (!l.type.equals(r.type)) { // 检查两边类型,一边i1一边éži1时,需è¦cast到i1。 if (l.type.equals(Type.Boolean)) { - r = ctx.addToCurrent(new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(r.type), r)); + r = ctx.addToCurrentBB( + new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(r.type), r)); } else if (r.type.equals(Type.Boolean)) { - l = ctx.addToCurrent(new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(l.type), l)); - } else {throw new RuntimeException("Wrong type for BinaryExpr "+expr.op.toString());} + l = ctx.addToCurrentBB( + new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(l.type), l)); + } else { + throw new RuntimeException("Wrong type for BinaryExpr " + expr.op.toString()); + } } } - var ret = ctx.addToCurrent(new BinopInst(ctx.current, expr.op, l, r)); + var ret = ctx.addToCurrentBB(new BinopInst(ctx.current, expr.op, l, r)); return ret; } @@ -382,18 +433,18 @@ public class FakeSSAGenerator { var fv = (FuncValue) ctx.funcMap.get(expr.funcSymbol.func); var cb = new CallInst.Builder(ctx.current, fv); if (expr.args != null) { - for(int i=0;i<expr.args.length;i++) { + for (int i = 0; i < expr.args.length; i++) { // è€ƒè™‘æ•°ç»„ä¼ ä¸€éƒ¨åˆ†çš„æƒ…å†µï¼Ÿ var val = visitDstExpr(ctx, curFunc, expr.args[i]); // Floatéœ€è¦æå‡åˆ°Doubleå†ä¼ å…¥vararg? if ((i >= expr.funcSymbol.func.params.size()) && val.type.equals(Type.Float)) { assert expr.funcSymbol.func.isVariadic; - val = ctx.addToCurrent(new CastInst.Builder(ctx.current, val).f2d().build()); + val = ctx.addToCurrentBB(new CastInst.Builder(ctx.current, val).f2d().build()); } cb.addArg(val); } } - return ctx.addToCurrent(cb.build()); + return ctx.addToCurrentBB(cb.build()); } if (expr_ instanceof LiteralExpr) { @@ -401,11 +452,11 @@ public class FakeSSAGenerator { var constant = convertEvaledValue(expr.value); if (expr.value.basicType == BasicType.STRING_LITERAL) { // å—符串放到全局å˜é‡é‡Œï¼Œç„¶åŽè¿”回i8* - var gv = new GlobalVariable(".str."+ctx.getStrInd(), constant.type.clone()); + var gv = new GlobalVariable(".str." + ctx.nextStrIdx(), constant.type.clone()); gv.init = constant; ctx.module.globs.add(gv); // LLVM 是用 get element ptr 获å–èµ·å§‹i8* 地å€ï¼Œæˆ‘这里直接bitcast应该也行 - return ctx.addToCurrent(new CastInst.Builder(ctx.current, gv).strBitCast(gv.type).build()); + return ctx.addToCurrentBB(new CastInst.Builder(ctx.current, gv).strBitCast(gv.type).build()); } return constant; } @@ -422,15 +473,17 @@ public class FakeSSAGenerator { return visitDstExpr(ctx, curFunc, expr.expr); } else if (expr.op == UnaryOp.NEG) { var val = visitDstExpr(ctx, curFunc, expr.expr); - return ctx.addToCurrent(new BinopInst(ctx.current, BinaryOp.SUB, ConstantValue.getDefault(val.type), val)); + return ctx.addToCurrentBB( + new BinopInst(ctx.current, BinaryOp.SUB, ConstantValue.getDefault(val.type), val)); } else if (expr.op == UnaryOp.NOT) { var val = visitDstExpr(ctx, curFunc, expr.expr); - return ctx.addToCurrent(new BinopInst(ctx.current, BinaryOp.LOG_EQ, ConstantValue.getDefault(val.type), val)); - } else { + return ctx.addToCurrentBB( + new BinopInst(ctx.current, BinaryOp.LOG_EQ, ConstantValue.getDefault(val.type), val)); + } else { throw new RuntimeException("Unknown UnaryOp type."); } } - + if (expr_ instanceof NonShortLogicExpr) { // 说明è¦cast到i1类型了 var expr = (NonShortLogicExpr) expr_; var val = visitDstExpr(ctx, curFunc, expr.expr); @@ -438,7 +491,8 @@ public class FakeSSAGenerator { return val; // æ˜¯é€»è¾‘è¡¨è¾¾å¼ } // cast val to i1; (x) -> (x ne 0) - return ctx.addToCurrent(new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(val.type), val)); + return ctx.addToCurrentBB( + new BinopInst(ctx.current, BinaryOp.LOG_NEQ, ConstantValue.getDefault(val.type), val)); } if (expr_ instanceof LogicExpr) { @@ -454,6 +508,15 @@ public class FakeSSAGenerator { /** * 处ç†LValä¸å–æ•°ç»„ä¸‹æ ‡çš„æƒ…å†µ + * + * 由于å˜åœ¨è¯ä¹‰è§„则 + * primaryExpr + * : '(' expr ')' #primaryExprQuote + * | lVal #primaryExprLVal + * | number #primaryExprNumber + * ; + * 会导致 LVal ä¸ä¸€å®šçœŸçš„æ˜¯å·¦å€¼ï¼Œæœ‰å¯èƒ½åªæ˜¯ä¸€ä¸ªèƒ½ä½œä¸ºå·¦å€¼ä½†ä¸æ˜¯å·¦å€¼çš„表达å¼ã€‚å› æ¤ toAssign 傿•°è¡¨æ˜Žæ˜¯å¦çœŸçš„æ˜¯å·¦å€¼ï¼ˆçœŸçš„被赋值) + * * @param ctx * @param curFunc * @param expr @@ -461,40 +524,44 @@ public class FakeSSAGenerator { * @return */ private Value visitLValExpr(FakeSSAGeneratorContext ctx, Func curFunc, LValExpr expr, boolean toAssign) { + // å–出 expr å¯¹åº”çš„ç¬¦å· Value val; if (expr.declSymbol.decl.isGlobal) { val = ctx.globVarMap.get(expr.declSymbol.decl); - } else { + } else { val = ctx.varMap.get(expr.declSymbol.decl); } - if (!expr.isArray) { // ä¸éœ€è¦å¤„ç†æ•°ç»„访问 + // 如果没有数组访问表达å¼ï¼ˆæ–¹æ‹¬å·ï¼Œä¸‹æ ‡è®¿é—®ï¼‰ + if (!expr.isArray) { + // 进一æ¥åˆ¤æ–æ˜¯å¦æ•°ç»„类型 if (expr.declSymbol.decl.isArray()) { // 没有å–ä¸‹æ ‡ï¼Œä½†æ˜¯æ˜¯æ•°ç»„ // 数组è¦ä¹ˆæ˜¯alloca,è¦ä¹ˆæ˜¯å…¨å±€å˜é‡ï¼Œè¦ä¹ˆæ˜¯å‡½æ•°å‚æ•°ï¼Œè¿™ä¸¤ç§æƒ…å†µéƒ½ç›´æŽ¥æ˜¯åœ°å€ - assert toAssign == false; - // 忘记数组第一维 + assert toAssign == false;// 也就是说,数组åç§°ä¸å¯èƒ½ç›´æŽ¥è¢«èµ‹å€¼ + // 如果给了维度信æ¯ï¼Œå¿˜è®°æ•°ç»„第一维 if (!(expr.declSymbol.decl.isDimensionOmitted)) { assert !(val instanceof ParamValue); var gep = new GetElementPtr(ctx.current, val); gep.comments = "forget first dim"; - ctx.addToCurrent(gep); + ctx.addToCurrentBB(gep); gep.addIndex(ConstantValue.ofInt(0)); return gep; } assert val instanceof ParamValue; return val; } else { // ä¸éœ€è¦å¤„ç†æ•°ç»„è®¿é—®ä¹Ÿä¸æ˜¯æ•°ç»„ + if (expr.declSymbol.decl.isConst()) { // æœ€ç®€å•æƒ…况,直接找到ConstantValue返回 assert toAssign == false; return val; - } else { - if (toAssign) { - return val; - } else { - // 生æˆloadè¯å¥ - return ctx.addToCurrent(new LoadInst(ctx.current, val)); - } } + // 赋值è¯å¥ï¼Œç›´æŽ¥è¿”回 decl + if (toAssign) { + return val; + } + // éž toAssign,则是访问å³å€¼ï¼Œå› æ¤ç”Ÿæˆ load è¯å¥ + return ctx.addToCurrentBB(new LoadInst(ctx.current, val)); + } } else { // æ˜¯æ•°ç»„ï¼ŒåŒæ—¶ä¹Ÿæœ‰å–ä¸‹æ ‡è¿ç®— // æ‹…å¿ƒå¸¸é‡æ•°ç»„å¯èƒ½ä¼ å‡½æ•°å‚æ•°ï¼Œæ‰€ä»¥å°±å½“普通数组处ç†äº†ã€‚ @@ -504,13 +571,13 @@ public class FakeSSAGenerator { var val_ = visitDstExpr(ctx, curFunc, exp); gep.addIndex(val_); }); - ctx.addToCurrent(gep); + ctx.addToCurrentBB(gep); if (gep.type.isArray()) { // index没有å–到底 assert toAssign == false; // ä¸€èˆ¬æ˜¯å‡½æ•°è°ƒç”¨å‡ºçŽ°ï¼Œå› æ¤è¦å†çœç•¥ä¸€ç»´ä¸‹æ ‡ var gep2 = new GetElementPtr(ctx.current, gep); gep2.comments = "forget one dim"; - ctx.addToCurrent(gep2); + ctx.addToCurrentBB(gep2); // éžParamValueè‡ªåŠ¨åŠ ä¸€ä¸ª0 gep2.addIndex(ConstantValue.ofInt(0)); return gep2; @@ -519,9 +586,9 @@ public class FakeSSAGenerator { if (toAssign) { return gep; } else { - return ctx.addToCurrent(new LoadInst(ctx.current, gep)); + return ctx.addToCurrentBB(new LoadInst(ctx.current, gep)); } - } + } } } @@ -534,91 +601,103 @@ public class FakeSSAGenerator { return; } // 生æˆallocaè¯å¥ï¼Œå³ä½¿æ˜¯array也能一个指令解决 - var alloc = new AllocaInst.Builder(ctx.current).addType(convertDstType(decl.type)).build(); - ctx.addToCurrent(alloc); - alloc.name = ctx.nameLocal(decl.id); - ctx.varMap.put(decl, alloc); + var alloca = new AllocaInst.Builder(ctx.current).addType(convertDstType(decl.type)).build(); + ctx.addToCurrentBB(alloca); + alloca.name = ctx.nameLocal(decl.id); + ctx.varMap.put(decl, alloca); + // 处ç†éžConst普通å˜é‡çš„åˆå§‹å€¼ï¼Œå¯èƒ½æ˜¯å¤æ‚表达å¼ã€‚ // è¯ä¹‰åˆ†æžæ²¡æœ‰è®¡ç®—evaledVal - if(decl.initVal != null) { + if (decl.initVal != null) { if (!decl.type.isArray) { - var cv = visitDstExpr(ctx, curFunc, decl.initVal.value); - var inst = new StoreInst.Builder(ctx.current).addOperand(cv, alloc).build(); - ctx.addToCurrent(inst); + var val = visitDstExpr(ctx, curFunc, decl.initVal.value); + var inst = new StoreInst.Builder(ctx.current).addOperand(val, alloca).build(); + ctx.addToCurrentBB(inst); } else { // TODO array memset to 0 and getelementptr and set content. - setArrayInitialVal(ctx, curFunc, alloc, decl.initVal, decl.type.dims); + setArrayInitialVal(ctx, curFunc, alloca, decl.initVal, decl.type.dims); } } } /** + * å¤„ç†æ¡ä»¶è·³è½¬è¡¨è¾¾å¼ã€‚ * 递归处ç†andå’Œorçš„çŸè·¯æ±‚值 + * * @param ctx * @param curFunc * @param inLogic expr in LogicExpr (normally `stmt.condition.expr`) - * @param t - * @param f + * @param trueBlock æ¡ä»¶ä¸ºçœŸæ—¶è·³è½¬åˆ°çš„ bb + * @param falseBlock */ - private void visitCondExprs(FakeSSAGeneratorContext ctx, ssa.ds.Func curFunc, Expr inLogic, BasicBlockValue t, BasicBlockValue f) { - if (inLogic instanceof BinaryExpr && ((BinaryExpr)inLogic).op.isShortCircuit()) { // logic and/or + private void visitCondExprs(FakeSSAGeneratorContext ctx, ssa.ds.Func curFunc, Expr inLogic, BasicBlockValue trueBlock, + BasicBlockValue falseBlock) { + // 如果是å¯ä»¥çŸè·¯æ±‚å€¼çš„äºŒå…ƒè¡¨è¾¾å¼ + if (inLogic instanceof BinaryExpr && ((BinaryExpr) inLogic).op.isShortCircuit()) { // logic and/or BinaryExpr expr = (BinaryExpr) inLogic; // 如果是and,true跳转到å³è¾¹ï¼Œfalse跳转到f。 // 如果是or,true跳转到t,false跳转到å³è¾¹ã€‚ // ç»§ç»åœ¨å³è¾¹é€’归生æˆã€‚ - int ind = ctx.getBBInd(); + int bbid = ctx.nextBBIdx(); BasicBlock next; if (expr.op == BinaryOp.LOG_AND) { - next = new BasicBlock("and_right_"+ind); - visitCondExprs(ctx, curFunc, expr.left, next.getValue(), f); + next = new BasicBlock("and_right_" + bbid); + visitCondExprs(ctx, curFunc, expr.left, next.getValue(), falseBlock); } else { assert expr.op == BinaryOp.LOG_OR; - next = new BasicBlock("or_right_"+ind); - visitCondExprs(ctx, curFunc, expr.left, t, next.getValue()); + next = new BasicBlock("or_right_" + bbid); + visitCondExprs(ctx, curFunc, expr.left, trueBlock, next.getValue()); } ctx.current = next; curFunc.bbs.add(next); - visitCondExprs(ctx, curFunc, expr.right, t, f); - } else { // æ£å¸¸ç”Ÿæˆï¼Œé€šè¿‡NonShortLogicExprå·²ç»ç¡®ä¿æ˜¯i1类型 + visitCondExprs(ctx, curFunc, expr.right, trueBlock, falseBlock); + } else { // æ£å¸¸ç”Ÿæˆï¼Œé€šè¿‡ NonShortLogicExpr å·²ç»ç¡®ä¿æ˜¯ i1 类型 var cond = this.visitDstExpr(ctx, curFunc, inLogic); - ctx.addToCurrent(new BranchInst(ctx.current, cond, t, f)); + ctx.addToCurrentBB(new BranchInst(ctx.current, cond, trueBlock, falseBlock)); } } - void setArrayInitialVal(FakeSSAGeneratorContext ctx, ssa.ds.Func curFunc, Value ptr, InitValue initValue, List<Integer> dims) { + void setArrayInitialVal(FakeSSAGeneratorContext ctx, ssa.ds.Func curFunc, Value ptr, InitValue initValue, + List<Integer> dims) { if (initValue.isAllZero) { // 为了第一次调用时检查。 return; } assert initValue.isArray; + // 处ç†å¤šç»´åº¦ if (dims.size() > 1) { int currentSize = dims.get(0); dims = dims.subList(1, dims.size()); - for (int i=0;i<currentSize;i++) { + for (int i = 0; i < currentSize; i++) { var iv = initValue.values.get(i); if (!iv.isAllZero) { // 生æˆGep var ptr_ = new GetElementPtr(ctx.current, ptr); ptr_.addIndex(ConstantValue.ofInt(i)); - ctx.addToCurrent(ptr_); + ctx.addToCurrentBB(ptr_); // 递归调用 setArrayInitialVal(ctx, curFunc, ptr_, iv, dims); } } } else { - int currentSize = dims.get(0); - for (int i=0;i<currentSize;i++) { - var iv = initValue.values.get(i); - assert !iv.isArray; - // 如果iv䏿˜¯é»˜è®¤å€¼åˆ™ç”Ÿæˆgepå’Œstore? TODO - if (iv.value instanceof LiteralExpr && ((LiteralExpr)(iv.value)).value.isDefault()) { + int dim = dims.get(0); + // é€ä¸ªç»´åº¦è¿›è¡Œåˆå§‹åŒ– + for (int i = 0; i < dim; i++) { + var initval = initValue.values.get(i); + assert !initval.isArray; + // 如果iv䏿˜¯é»˜è®¤å€¼åˆ™ç”Ÿæˆgepå’Œstore? + if (initval.value instanceof LiteralExpr && ((LiteralExpr) (initval.value)).value.isDefault()) { + // TODO } else { + // è®¡ç®—åœ°å€ var ptr_ = new GetElementPtr(ctx.current, ptr); ptr_.addIndex(ConstantValue.ofInt(i)); - ctx.addToCurrent(ptr_); - var val = visitDstExpr(ctx, curFunc, iv.value); + ctx.addToCurrentBB(ptr_); + // æ ¹æ®åˆå§‹åŒ–值表达å¼ç”Ÿæˆåˆå§‹åŒ–指令 + var val = visitDstExpr(ctx, curFunc, initval.value); + // ç„¶åŽæŠŠåˆå§‹åŒ–的结果写入到 gep 指令算出的地å€é‚£é‡Œ var inst = new StoreInst.Builder(ctx.current).addOperand(val, ptr_).build(); - ctx.addToCurrent(inst); + ctx.addToCurrentBB(inst); } } } diff --git a/src/main/java/ssa/FakeSSAGeneratorContext.java b/src/main/java/ssa/FakeSSAGeneratorContext.java index 443bae39ae2fc45492f91216d00a7aa43f78fa23..a194486d4da807dac68354bd37b7f5f013f12ffd 100644 --- a/src/main/java/ssa/FakeSSAGeneratorContext.java +++ b/src/main/java/ssa/FakeSSAGeneratorContext.java @@ -14,14 +14,18 @@ import ssa.ds.Value; public class FakeSSAGeneratorContext { public Module module; + // 由于引用关系已ç»è¢«è¯ä¹‰åˆ†æžå¡«å¥½äº†ï¼Œæ‰€ä»¥ä¸éœ€è¦åŒºåˆ†ä½œç”¨åŸŸã€‚ä¸åŒå‡½æ•°è‚¯å®šæ˜¯ä¸åŒçš„Decl // ç‰æ•ˆäºŽFuncå’ŒDeclä¸å¤šäº†ä¸€ä¸ªValueæˆå‘˜ã€‚ // map from dst to created ssa value (key compared by instance) + + // 从 dst decl 到 alloca æŒ‡ä»¤çš„æ˜ å°„ï¼Œæˆ–è€…å¸¸é‡åˆ° ConstantValue çš„æ˜ å°„ç‰ç‰ public Map<dst.ds.Decl, Value> varMap; - public Map<dst.ds.Func, Value> funcMap; + public Map<dst.ds.Func, Value> funcMap; // including builtin funcs // 全局å˜é‡ç”±äºŽç›´æŽ¥å–的是地å€ï¼Œæ‰€ä»¥å•独分开 public Map<dst.ds.Decl, Value> globVarMap; - // ç‰æ•ˆäºŽLoopStatement多了一个Valueæˆå‘˜ï¼Œä¿å˜breakå’ŒContinue需è¦çš„BasicBlockValue + // ç‰æ•ˆäºŽ LoopStatement 多了一个 Value æˆå‘˜ï¼Œä¿å˜ break å’Œ Continue 需è¦çš„ BasicBlockValue + // 通过æ¤è¡¨æŸ¥è¯¢æŸä¸ª LoopStatement break 或 continue åŽè·³åˆ°å“ªå„¿ public Map<LoopStatement, BasicBlockValue> breakMap; public Map<LoopStatement, BasicBlockValue> continueMap; @@ -37,11 +41,13 @@ public class FakeSSAGeneratorContext { breakMap = new HashMap<>(); continueMap = new HashMap<>(); } - - public Instruction addToCurrent(Instruction i) { + /** + * å°†æŒ‡ä»¤è¿½åŠ åˆ°å½“å‰ä¸Šä¸‹æ–‡çš„åŸºæœ¬å— + */ + public Instruction addToCurrentBB(Instruction i) { if (i instanceof TerminatorInst && current.hasTerminator()) { // åªèƒ½ç”Ÿæˆåˆ°ä¸€ä¸ªæ–°çš„空基本å—了 - var newBB = new BasicBlock("tmp_"+getBBInd()); + var newBB = new BasicBlock("tmp_"+nextBBIdx()); currentFunc.bbs.add(newBB); newBB.insts.add(i); current = newBB; @@ -51,26 +57,31 @@ public class FakeSSAGeneratorContext { } } + /** + * ä»¥ä¸‹å‡½æ•°ç”Ÿæˆæ–°çš„æ•°å—ç¼–å· + */ + int strInd = 0; - public int getStrInd() { + public int nextStrIdx() { return strInd++; } int BBInd = 0; - public int getBBInd() { + public int nextBBIdx() { return BBInd++; } int varInd = 0; - public int getVarInd() { + public int nextVarIdx() { return varInd++; } + // æ ¹æ®æ ‡è¯†ç¬¦ id 生æˆä¸€ä¸ªåå—,以一个ä¸å†²çªçš„æ•°å—为åŽç¼€ public String nameLocal(String id) { if (id.length() > 10) { id = id.substring(0,10); } - return id+"_"+getVarInd(); + return id+"_"+nextVarIdx(); } } diff --git a/src/main/java/ssa/NumValueNamer.java b/src/main/java/ssa/NumValueNamer.java index 6e45b5142f9adf2498951e974c17f3a39cb47957..6874857766b2e5f85abe7767bcb6b60b0e24df8f 100644 --- a/src/main/java/ssa/NumValueNamer.java +++ b/src/main/java/ssa/NumValueNamer.java @@ -8,8 +8,12 @@ import ssa.ds.Module; import ssa.ds.Type; import ssa.ds.Value; -// basicBlockçš„label还是生æˆçš„æ—¶å€™å޻命å,在ctx里放个index防æ¢é‡å -// 全局å˜é‡å’Œå‡½æ•°å‚æ•°ä¹Ÿåº”å½“åœ¨ç”Ÿæˆæ—¶å‘½åã€‚è¯æ³•里好åƒå‡½æ•°å‚æ•°çš„åå—ä¸èƒ½çœç•¥ã€‚ +/** + * NumValueNamer 包å«ä¸€ä¸ªè®¡æ•°å™¨çжæ€å˜é‡ï¼Œç”¨äºŽç»™æ‰€æœ‰çš„ Value æä¾›ä¸€ä¸ªå”¯ä¸€çš„临时åç§° + * + * basicBlockçš„label还是生æˆçš„æ—¶å€™å޻命å,在ctx里放个index防æ¢é‡å + * 全局å˜é‡å’Œå‡½æ•°å‚æ•°ä¹Ÿåº”å½“åœ¨ç”Ÿæˆæ—¶å‘½åã€‚è¯æ³•里好åƒå‡½æ•°å‚æ•°çš„åå—ä¸èƒ½çœç•¥ã€‚ + */ public class NumValueNamer { long count = 0; diff --git a/src/main/java/ssa/ds/AllocaInst.java b/src/main/java/ssa/ds/AllocaInst.java index 5db34c44b0804a6da1e06ba4ad97f80de71359ec..0ffeaa8c84f2bafdec85f898d769138042cdcab6 100644 --- a/src/main/java/ssa/ds/AllocaInst.java +++ b/src/main/java/ssa/ds/AllocaInst.java @@ -1,5 +1,7 @@ package ssa.ds; - +/** + * Alloca æŒ‡ä»¤ç”¨äºŽåœ¨æ ˆä¸åˆ†é…å†…å˜ + */ public class AllocaInst extends Instruction { public Type ty; public long numElement = 1; diff --git a/src/main/java/ssa/ds/BasicBlock.java b/src/main/java/ssa/ds/BasicBlock.java index 5e863d5cab7c9615fb4a47c942028f72649c715d..805e7c4cc38606f908a9c148b1732b3e38c00322 100644 --- a/src/main/java/ssa/ds/BasicBlock.java +++ b/src/main/java/ssa/ds/BasicBlock.java @@ -19,6 +19,10 @@ public class BasicBlock { return val; } + /** + * 判æ–åŸºæœ¬å—æ˜¯å¦åº”该终æ¢ã€‚例如最åŽä¸€ä¸ªæŒ‡ä»¤æ˜¯ TerminatorInst + * @return 如果应该终æ¢ï¼Œè¿”回 true,å¦åˆ™è¿”回 false + */ public boolean hasTerminator() { if (insts.size() == 0 || !(insts.get(insts.size()-1) instanceof TerminatorInst)) { return false; @@ -26,6 +30,11 @@ public class BasicBlock { return true; } + /** + * 将一个指令æ’å…¥åˆ°åŸºæœ¬å—æœ«å°¾çš„终结指令**å‰**。 + * @param i + * @return + */ public Instruction addBeforeTerminator(Instruction i) { if (insts.size() == 0 || !(insts.get(insts.size()-1) instanceof TerminatorInst)) { insts.add(i); @@ -35,6 +44,11 @@ public class BasicBlock { return i; } + /** + * 将一个指令æ’å…¥åˆ°åŸºæœ¬å—æœ«å°¾çš„跳转指令å‰ï¼ˆå³ä¸åŒ…括 ret) + * @param i + * @return + */ public Instruction addBeforeJump(Instruction i) { if (insts.size() == 0 || !(insts.get(insts.size()-1) instanceof TerminatorInst)) { insts.add(i); @@ -46,7 +60,9 @@ public class BasicBlock { return i; } - // æ ¹æ®BasicBlockValue被使用的情况获å–。 + /** + * æ ¹æ® BasicBlockValue è¢«ä½¿ç”¨çš„æƒ…å†µï¼ŒèŽ·å–æ‰€æœ‰å‰é©±åŸºæœ¬å—,以列表形å¼è¿”回。 + */ public List<BasicBlock> pred() { var val = getValue(); ArrayList<BasicBlock> ret = new ArrayList<>(); @@ -60,7 +76,10 @@ public class BasicBlock { return ret; } - // èŽ·å–æœ€åŽè·³è½¬æŒ‡ä»¤çš„ç›®æ ‡ + /** + * æ ¹æ®æœ¬å—末尾的跳转指令,查询能够跳转到的åŽç»§èŠ‚ç‚¹ + * @return + */ public List<BasicBlock> succ() { assert insts.size() != 0 && insts.get(insts.size()-1) instanceof TerminatorInst; TerminatorInst t = (TerminatorInst)insts.get(insts.size()-1); diff --git a/src/main/java/ssa/ds/Func.java b/src/main/java/ssa/ds/Func.java index 5940b883391d918ee883ef1f30d64e029a6d83d0..e2bf1be63246b53ed41dbaf61d5be25019c6058b 100644 --- a/src/main/java/ssa/ds/Func.java +++ b/src/main/java/ssa/ds/Func.java @@ -10,7 +10,7 @@ public class Func { public String name; public List<BasicBlock> bbs; public FuncValue val; // used by CallInst - public boolean isVariadic = false; + public boolean isVariadic = false; // æ˜¯å¦æœ‰å¯å˜å‚æ•° public FuncType retType; public List<ParamValue> argType; diff --git a/src/main/java/ssa/ds/GetElementPtr.java b/src/main/java/ssa/ds/GetElementPtr.java index 48050b18c12953b5e97b2080214c2e37c1f246c9..69f575a48edf97373dfedd7a5547b5e16fcf4b35 100644 --- a/src/main/java/ssa/ds/GetElementPtr.java +++ b/src/main/java/ssa/ds/GetElementPtr.java @@ -1,13 +1,35 @@ package ssa.ds; -// https://llvm.org/docs/LangRef.html#getelementptr-instruction -// https://llvm.org/docs/GetElementPtr.html +/* + * åŸºæœ¬è¯æ³•: + * <result> = getelementptr <ty>, <ty>* <ptrval>, {<ty> <index>}*, + * + * å…¶ä¸ç¬¬ä¸€ä¸ª <ty> 表示第一个索引所指å‘的类型 + * 第二个 <ty> 表示åŽé¢çš„æŒ‡é’ˆåŸºå€ <ptrval> 的类型, + * <ty> <index> 表示一组索引的类型和值。 + * è¦æ³¨æ„索引的类型和 索引指å‘的基本类型 是ä¸ä¸€æ ·çš„,索引的类型一般为 i32 或 i64 + * **而 索引指å‘的基本类型 ç¡®å®šçš„æ˜¯å¢žåŠ ç´¢å¼•å€¼æ—¶æŒ‡é’ˆçš„åç§»é‡ã€‚** + * + * 例å: + * %1 = getelementptr [5 x [4 x i32]], [5 x [4 x i32]]* @a, i32 0, i32 2 + * %1 类型为 [4 x i32]*,å¯ä»¥ç†è§£ä¸º C è¯è¨€ä¸æŒ‡å‘长度为 4 的一维数组基å€çš„æŒ‡é’ˆ + * + * https://llvm.org/docs/LangRef.html#getelementptr-instruction + * https://llvm.org/docs/GetElementPtr.html + * https://buaa-se-compiling.github.io/miniSysY-tutorial/lab7/help.html + */ +/** + * GEP 指令:用于计算地å€ï¼ˆæ— 副作用,ä¸ä¼šè¯»å†™æ•°æ®ï¼‰ã€‚计算结果的接收者是 %name + * ç¬¬ä¸€ä¸ªå‚æ•°ï¼šç”¨äºŽè®¡ç®—基准类型 + * ç¬¬äºŒä¸ªå‚æ•°æ˜¯ä¸€ä¸ªæˆ–一å‘é‡çš„æŒ‡é’ˆï¼Œä½œä¸ºåŸºåœ°å€ + * å…¶ä½™çš„å‚æ•°æ˜¯ç´¢å¼• + */ public class GetElementPtr extends Instruction { public Type base; - public GetElementPtr(BasicBlock p, Value ptr) { + public GetElementPtr(BasicBlock parent_bb, Value ptr) { assert ptr.type.isPointer; - parent = p; + parent = parent_bb; oprands.add(new Use(this, ptr)); // éžå‚数时第一维是0 (æ˜¯å‚æ•°æ—¶å¿…ç„¶çœç•¥ç¬¬ä¸€ç»´) if (!(ptr instanceof ParamValue)) { @@ -29,12 +51,15 @@ public class GetElementPtr extends Instruction { } static String format = "%s = getelementptr %s, %s* %s"; + // getelementptr <ty>, <ty>* <ptrval>{, <ty> <idx>}* @Override public String toString() { - var s = String.format(format, toValueString(), base.toString(), base.toString(), oprands.get(0).value.toValueString()); + var s = String.format(format, toValueString(), base.toString(), base.toString(), + oprands.get(0).value.toValueString()); var b = new StringBuilder(s); - oprands.subList(1, oprands.size()).forEach(use -> b.append(", ").append(use.value.type.toString()).append(" ").append(use.value.toValueString())); + oprands.subList(1, oprands.size()).forEach( + use -> b.append(", ").append(use.value.type.toString()).append(" ").append(use.value.toValueString())); if (comments != null) { b.append(" ; ").append(comments); } diff --git a/src/main/java/ssa/ds/ParamValue.java b/src/main/java/ssa/ds/ParamValue.java index 2d99fb3ff2727dc7d9e710347b4951b1e2342b21..3e081673187d35d12c5f970eb9faf4106d5c1353 100644 --- a/src/main/java/ssa/ds/ParamValue.java +++ b/src/main/java/ssa/ds/ParamValue.java @@ -1,5 +1,8 @@ package ssa.ds; +/** + * å‡½æ•°å‚æ•° + */ public class ParamValue extends Value { public ParamValue(String name, Type t) { diff --git a/src/main/java/ssa/ds/RetInst.java b/src/main/java/ssa/ds/RetInst.java index 2c73bd1992a6d4357d5be1ef8fbb18558b63fec8..2e26f3eff3811cf5b16fbe090cb3cdd7f66eb1f2 100644 --- a/src/main/java/ssa/ds/RetInst.java +++ b/src/main/java/ssa/ds/RetInst.java @@ -26,6 +26,7 @@ public class RetInst extends TerminatorInst { return this; } + // 设置返回值 public Builder addOperand(Value v) { inst.oprands.add(new Use(inst, v)); return this; diff --git a/src/main/java/ssa/ds/StoreInst.java b/src/main/java/ssa/ds/StoreInst.java index a8fddab349d60af30c9191cd057ddfdebb7a4fd9..140896e04414bacc7ed564abe59bc47664c31446 100644 --- a/src/main/java/ssa/ds/StoreInst.java +++ b/src/main/java/ssa/ds/StoreInst.java @@ -2,6 +2,16 @@ package ssa.ds; import ds.Global; +/** + * Store æŒ‡ä»¤å‘ alloca ç”³è¯·åˆ°çš„æ ˆå†…å˜ä¸å†™å…¥æ•°æ® + * + * %i = alloca i32 + * store i32 0, i32* %i + * + * store æŒ‡ä»¤ä¸¤ä¸ªå‚æ•°ï¼š + * 1. è¦ store 的值 + * 2. è¦ store åˆ°çš„åœ°å€ + */ public class StoreInst extends Instruction { public StoreInst() { @@ -15,7 +25,12 @@ public class StoreInst extends Instruction { inst = new StoreInst(); inst.parent = parent; } - + /** + * 设置 Store æŒ‡ä»¤çš„å‚æ•° + * @param val è¦ store 什么值 + * @param ptr è¦ store 到哪儿 + * @return + */ public Builder addOperand(Value val, Value ptr) { inst.oprands.add(new Use(inst, val)); inst.oprands.add(new Use(inst, ptr)); @@ -31,11 +46,13 @@ public class StoreInst extends Instruction { } public static boolean checkType(Type val, Type ptr) { + // å¿…é¡» store åˆ°åœ°å€ if (!ptr.isPointer){ return false; } Type ty = ptr.clone(); ty.isPointer = false; + // 地å€è§£å¼•用åŽå¿…须是 val çš„åŒç±»åž‹ return ty.equals(val); } diff --git a/src/main/java/ssa/ds/TerminatorInst.java b/src/main/java/ssa/ds/TerminatorInst.java index 5be2e3e4ddc1d231be2c6bf56fb85165e17d2f34..187a4356c93ed6fc5b48cd6d09f46b4f9b74dcd6 100644 --- a/src/main/java/ssa/ds/TerminatorInst.java +++ b/src/main/java/ssa/ds/TerminatorInst.java @@ -3,7 +3,7 @@ package ssa.ds; import java.util.List; import java.util.stream.Collectors; -// 终æ¢åŸºæœ¬å—的指令,包括Branchã€Jumpã€Return +// 终æ¢åŸºæœ¬å—的指令,包括 Branchã€Jumpã€Return public abstract class TerminatorInst extends Instruction { List<BasicBlock> getSuccessors() { return oprands.stream().map(u -> {return ((BasicBlockValue) u.value).b;}).collect(Collectors.toList()); diff --git a/src/main/java/ssa/ds/Type.java b/src/main/java/ssa/ds/Type.java index ef5a58d6e1c9fa03e0e7ebe752fbbecdb8c8d216..194fc35413a3d6b6e45683019b9388fb8861f2b7 100644 --- a/src/main/java/ssa/ds/Type.java +++ b/src/main/java/ssa/ds/Type.java @@ -5,9 +5,9 @@ import java.util.List; // æ ¹æ®dimsåŒºåˆ†æ˜¯å¦æ˜¯array类型。 public class Type implements Cloneable { - public PrimitiveTypeTag baseType; - public List<Integer> dims; - public boolean isPointer; + public PrimitiveTypeTag baseType; // 最基础类型 + public List<Integer> dims; // 数组维度 + public boolean isPointer; // if true, first dim is omited // 常用类型 public static Type Void = new Type(PrimitiveTypeTag.VOID, null, false);