From 27aa6d04abdbcee509f4e02de39728178b07aaa4 Mon Sep 17 00:00:00 2001 From: willson walter Date: Wed, 29 Nov 2023 22:17:39 +0800 Subject: [PATCH] - Refactor CFG generation to use BasicBlocks - Build CFG from BasicBlocks instead of LinearIRBlocks - Make Label and LinearIRBlock comparable - Add JMP interface for jump instructions - Refactor CJMP and JMP to implement JMP interface - Update control flow analysis visitors to use generics --- ep18/src/main/resources/t.vm | 3 +- ep20/README.md | 121 ++++++++++-------- .../org/teachfx/antlr4/ep20/Compiler.java | 9 +- .../org/teachfx/antlr4/ep20/ir/IRVisitor.java | 2 +- .../org/teachfx/antlr4/ep20/ir/JMPInstr.java | 7 + .../org/teachfx/antlr4/ep20/ir/stmt/CJMP.java | 8 +- .../org/teachfx/antlr4/ep20/ir/stmt/JMP.java | 8 +- .../teachfx/antlr4/ep20/ir/stmt/Label.java | 21 ++- .../antlr4/ep20/pass/cfg/BasicBlock.java | 67 +++++----- .../org/teachfx/antlr4/ep20/pass/cfg/CFG.java | 30 +++-- .../antlr4/ep20/pass/cfg/CFGBuilder.java | 35 ++--- .../ep20/pass/cfg/ControlFlowAnalysis.java | 2 +- .../antlr4/ep20/pass/cfg/LinearIRBlock.java | 81 +++++++----- .../ep20/pass/cfg/LivenessAnalysis.java | 2 +- .../org/teachfx/antlr4/ep20/pass/cfg/Loc.java | 9 +- .../ep20/pass/codegen/CymbolAssembler.java | 7 +- .../antlr4/ep20/pass/ir/CymbolIRBuilder.java | 14 +- 17 files changed, 244 insertions(+), 182 deletions(-) create mode 100644 ep20/src/main/java/org/teachfx/antlr4/ep20/ir/JMPInstr.java diff --git a/ep18/src/main/resources/t.vm b/ep18/src/main/resources/t.vm index 6d17873..d51d757 100644 --- a/ep18/src/main/resources/t.vm +++ b/ep18/src/main/resources/t.vm @@ -25,11 +25,10 @@ L7: load 0 iconst 7 ieq - brf L10 + brf L8 L9: iconst 7 br L3 -L10: L8: sconst "break" print diff --git a/ep20/README.md b/ep20/README.md index 722cdc4..9e5fa75 100644 --- a/ep20/README.md +++ b/ep20/README.md @@ -35,61 +35,70 @@ graph LR ### CFG ```mermaid -graph LR; - .def dec1: args=1 ,locals=1[t0 = @0; -t1 = 1 ; -t0 SUB t1; -jmp L1; -] -L1[ret; -] -.def main: args=0 ,locals=1[t0 = 10 ; -@0 = t0; -jmp L4; -] -L4[t0 = @0; -t1 = 0 ; -t0 GT t1; -jmpIf t0,L5,L6; -] -L5[t0 = @0; -t1 = 5 ; -t0 GT t1; -jmpIf t0,L7,L8; -] -L7[t0 = @0; -call print(args:1); -t0 = @0; -t1 = 7 ; -t0 EQ t1; -jmpIf t0,L9,L10; -] -L9[t0 = 7 ; -jmp L3; -] -L10[] -L8[t0 = "break" ; -call print(args:1); -t0 = @0; -call dec1(args:1); -@0 = t0; -jmp L4; -] -L6[t0 = 0 ; -jmp L3; -] -L3[halt; -] -L0 --> L1 -L2 --> L4 -L4 --> L5 -L5 --> L7 -L7 --> L9 -L9 --> L10 -L10 --> L8 -L8 --> L6 -L6 --> L3 - - +graph TD + subgraph L0 + Q112 + end + subgraph L2 + Q0["t0 = 10 ;"] + Q1["@0 = t0;"] + Q2["jmp L4;"] + end + subgraph L3 + Q3["t0 = @0;"] + Q4["t1 = 0 ;"] + Q5["t0 GT t1;"] + Q6["jmpIf t0,L5,L6;"] + end + subgraph L4 + Q7["t0 = @0;"] + Q8["t1 = 5 ;"] + Q9["t0 GT t1;"] + Q10["jmpIf t0,L7,L8;"] + end + subgraph L5 + Q11["t0 = @0;"] + Q12["call print(args:1);"] + Q13["t0 = @0;"] + Q14["t1 = 7 ;"] + Q15["t0 EQ t1;"] + Q16["jmpIf t0,L9,L10;"] + end + subgraph L6 + Q17["t0 = 7 ;"] + Q18["jmp L3;"] + end + subgraph L7 + Q000 + end + subgraph L8 + Q19["t0 = 'break' ;"] + Q20["call print(args:1);"] + Q21["t0 = @0;"] + Q22["call dec1(args:1);"] + Q23["@0 = t0;"] + Q24["jmp L4;"] + end + subgraph L9 + Q25["t0 = 0 ;"] + Q26["jmp L3;"] + end + subgraph L10 + Q27["halt;"] + end + + L0 --> L4 + L4 --> L5 + L4 --> L6 + L5 --> L7 + L5 --> L8 + L7 --> L0 + L7 --> L9 + L9 --> L3 + L9 --> L10 + L10 --> L8 + L8 --> L4 + L8 --> L6 + L6 --> L3 ``` diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java index 0caba73..41cc9a5 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java @@ -48,12 +48,13 @@ public static void main(String[] args) throws IOException { var irBuilder = new CymbolIRBuilder(); astRoot.accept(irBuilder); - - var cfg = irBuilder.getCFG(irBuilder.prog.blockList); - logger.info("CFG:\n" + cfg.toString()); + for(var block : irBuilder.prog.blockList) { + var cfg = irBuilder.getCFG(List.of(block)); + logger.info("CFG:\n" + cfg.toString()); + } var assembler = new CymbolAssembler(); - irBuilder.prog.accept(assembler); + assembler.visit(irBuilder.prog.linearInstrs()); saveToEp18Res(assembler.getAsmInfo()); logger.info("\n%s".formatted(assembler.getAsmInfo())); } diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/IRVisitor.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/IRVisitor.java index 2cb389e..f6d80a3 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/IRVisitor.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/IRVisitor.java @@ -26,7 +26,7 @@ public interface IRVisitor { S visit(ReturnVal returnVal); default S visit(ExprStmt exprStmt) { return exprStmt.accept(this); } - S visit(Prog prog); + default S visit(Prog prog) { return null; } E visit(OperandSlot operandSlot); diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/JMPInstr.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/JMPInstr.java new file mode 100644 index 0000000..e800b6f --- /dev/null +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/JMPInstr.java @@ -0,0 +1,7 @@ +package org.teachfx.antlr4.ep20.ir; + +import org.teachfx.antlr4.ep20.ir.stmt.Label; + +public interface JMPInstr { + public Label getTarget(); +} diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/CJMP.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/CJMP.java index ec27d1c..4941e28 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/CJMP.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/CJMP.java @@ -1,10 +1,11 @@ package org.teachfx.antlr4.ep20.ir.stmt; import org.teachfx.antlr4.ep20.ir.IRVisitor; +import org.teachfx.antlr4.ep20.ir.JMPInstr; import org.teachfx.antlr4.ep20.ir.expr.VarSlot; import org.teachfx.antlr4.ep20.pass.cfg.LinearIRBlock; -public class CJMP extends Stmt { +public class CJMP extends Stmt implements JMPInstr { public VarSlot cond; private LinearIRBlock thenBlock; private LinearIRBlock elseBlock; @@ -18,6 +19,11 @@ public CJMP(VarSlot cond, LinearIRBlock thenLabel, LinearIRBlock elseLabel) { elseBlock.refJMP(this); } + @Override + public Label getTarget() { + return elseBlock.getLabel(); + } + @Override public S accept(IRVisitor visitor) { return visitor.visit(this); diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/JMP.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/JMP.java index 77b8853..9f4698f 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/JMP.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/JMP.java @@ -1,9 +1,10 @@ package org.teachfx.antlr4.ep20.ir.stmt; import org.teachfx.antlr4.ep20.ir.IRVisitor; +import org.teachfx.antlr4.ep20.ir.JMPInstr; import org.teachfx.antlr4.ep20.pass.cfg.LinearIRBlock; -public class JMP extends Stmt +public class JMP extends Stmt implements JMPInstr { @Override public S accept(IRVisitor visitor) { @@ -17,6 +18,11 @@ public JMP(LinearIRBlock block) } public LinearIRBlock next; + @Override + public Label getTarget() { + return next.getLabel(); + } + @Override public StmtType getStmtType() { return StmtType.JMP; diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/Label.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/Label.java index 07dd151..423a513 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/Label.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/Label.java @@ -1,11 +1,12 @@ package org.teachfx.antlr4.ep20.ir.stmt; +import org.jetbrains.annotations.NotNull; import org.teachfx.antlr4.ep20.ir.IRVisitor; import org.teachfx.antlr4.ep20.symtab.scope.Scope; import java.util.Objects; -public class Label extends Stmt { +public class Label extends Stmt implements Comparable