diff --git a/ep18/src/main/resources/t.vm b/ep18/src/main/resources/t.vm index 05eefb6..6d17873 100644 --- a/ep18/src/main/resources/t.vm +++ b/ep18/src/main/resources/t.vm @@ -2,42 +2,43 @@ load 0 iconst 1 isub - br L2 -L2: + br L1 +L1: ret .def main: args=0 ,locals=1 iconst 10 store 0 - br L5 -L5: + br L4 +L4: load 0 iconst 0 igt - brf L7 -L6: + brf L6 +L5: load 0 iconst 5 igt - brf L9 -L8: + brf L8 +L7: load 0 print load 0 iconst 7 ieq - brf L9 -L10: - iconst 7 - br L4 + brf L10 L9: + iconst 7 + br L3 +L10: +L8: sconst "break" print load 0 call dec1() store 0 - br L5 -L7: - iconst 0 br L4 -L4: +L6: + iconst 0 + br L3 +L3: halt 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 d590d27..0caba73 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java @@ -49,12 +49,12 @@ public static void main(String[] args) throws IOException { astRoot.accept(irBuilder); - var cfg = irBuilder.getCFG(); + var cfg = irBuilder.getCFG(irBuilder.prog.blockList); logger.info("CFG:\n" + cfg.toString()); var assembler = new CymbolAssembler(); irBuilder.prog.accept(assembler); -// saveToEp18Res(assembler.getAsmInfo()); + saveToEp18Res(assembler.getAsmInfo()); logger.info("\n%s".formatted(assembler.getAsmInfo())); } diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/CFGBuilder.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/CFGBuilder.java index 8fdc151..8ca3a6e 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/CFGBuilder.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/CFGBuilder.java @@ -3,8 +3,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.teachfx.antlr4.ep20.ir.IRNode; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class CFGBuilder { private CFG cfg; @@ -19,10 +18,26 @@ public CFGBuilder(List blockList){ cfg = new CFG<>(basicBlocks, edges); } + private static final Set cachedEdgeLinks = new HashSet<>(); + private void build(LinearIRBlock block){ + basicBlocks.add(BasicBlock.buildFromLinearBlock(block)); + block.getJumpEntries().ifPresent(entries -> { + for(var dest : entries){ + var key = "%d-%d".formatted(block.getOrd(), dest); + if (!cachedEdgeLinks.contains(key)) { + edges.add(Pair.of(block.getOrd(), dest)); + cachedEdgeLinks.add("%d-%d".formatted(block.getOrd(), dest)); + } + } + }); for(var successor : block.getSuccessors()){ - edges.add(Pair.of(block.getOrd(), successor.getOrd())); + var key = "%d-%d".formatted(block.getOrd(), successor.getOrd()); + if (!cachedEdgeLinks.contains(key)) { + cachedEdgeLinks.add(key); + edges.add(Pair.of(block.getOrd(), successor.getOrd())); + } build(successor); } } diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/LinearIRBlock.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/LinearIRBlock.java index e9766a9..07b198f 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/LinearIRBlock.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/LinearIRBlock.java @@ -5,8 +5,7 @@ import org.teachfx.antlr4.ep20.symtab.scope.Scope; import org.teachfx.antlr4.ep20.utils.Kind; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class LinearIRBlock { @@ -153,5 +152,27 @@ public Label getLabel() { return new Label(toString(),scope); } + public Optional> getJumpEntries() { + var entries = new TreeSet(); + switch (kind) { + case END_BY_CJMP -> { + CJMP cjmp = (CJMP) getStmts().getLast(); + var tid = cjmp.getThenBlock().getOrd(); + var eid = cjmp.getElseBlock().getOrd(); + entries.add(tid); + entries.add(eid); + return Optional.of(entries); + } + case END_BY_JMP -> { + JMP cjmp = (JMP) getStmts().getLast(); + var tid = cjmp.next.getOrd(); + entries.add(tid); + return Optional.of(entries); + } + default -> { + return Optional.empty(); + } + } + } } \ No newline at end of file diff --git a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/ir/CymbolIRBuilder.java b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/ir/CymbolIRBuilder.java index 808df74..052f576 100644 --- a/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/ir/CymbolIRBuilder.java +++ b/ep20/src/main/java/org/teachfx/antlr4/ep20/pass/ir/CymbolIRBuilder.java @@ -27,6 +27,7 @@ import org.teachfx.antlr4.ep20.symtab.symbol.MethodSymbol; import org.teachfx.antlr4.ep20.symtab.symbol.VariableSymbol; +import java.util.List; import java.util.Optional; import java.util.Stack; @@ -421,12 +422,12 @@ protected VarSlot peekEvalOperand() { return evalExprStack.peek(); } - public CFG getCFG() { - for (var func : prog.blockList){ + public CFG getCFG(List blocks) { + for (var func : blocks){ insertBlockLabel(func); } - var cfgBuilder = new CFGBuilder(prog.blockList); + var cfgBuilder = new CFGBuilder(blocks); return cfgBuilder.getCFG(); } diff --git a/ep21/README.md b/ep21/README.md index 693485f..26cd529 100644 --- a/ep21/README.md +++ b/ep21/README.md @@ -21,22 +21,75 @@ graph LR ## DONE ```mermaid -graph TD; - A[基本块1] --> B[基本块2] - B --> C[基本块3] - C -->|条件跳转| D[基本块6] - C -->|否则| E[基本块4] - E -->|条件跳转| F[基本块7] - F --> B - E -->|否则| G[基本块5] - G -->|条件跳转| F - G -->|否则| H[基本块8] - H --> I[基本块9] - D --> I - subgraph dec1 - A - end - subgraph main - B --> C --> D --> E --> F --> G --> H --> I - end +graph TD +subgraph L0 +Q0["t0 = @0;"] +Q1["t1 = 1 ;"] +Q2["t0 SUB t1;"] +Q3["jmp L1;"] +end +subgraph L1 +Q4["ret;"] +end +subgraph L2 +Q5["t0 = 10 ;"] +Q6["@0 = t0;"] +Q7["jmp L4;"] +end +subgraph L4 +Q8["t0 = @0;"] +Q9["t1 = 0 ;"] +Q10["t0 GT t1;"] +Q11["jmpIf t0,L5,L6;"] +end +subgraph L5 +Q12["t0 = @0;"] +Q13["t1 = 5 ;"] +Q14["t0 GT t1;"] +Q15["jmpIf t0,L7,L8;"] +end +subgraph L7 +Q16["t0 = @0;"] +Q17["call print(args:1);"] +Q18["t0 = @0;"] +Q19["t1 = 7 ;"] +Q20["t0 EQ t1;"] +Q21["jmpIf t0,L9,L10;"] +end +subgraph L9 +Q22["t0 = 7 ;"] +Q23["jmp L3;"] +end +subgraph L10 +end +subgraph L8 +Q24["t0 = 'break' ;"] +Q25["call print(args:1);"] +Q26["t0 = @0;"] +Q27["call dec1(args:1);"] +Q28["@0 = t0;"] +Q29["jmp L4;"] +end +subgraph L6 +Q30["t0 = 0 ;"] +Q31["jmp L3;"] +end +subgraph L3 +Q32["halt;"] +end + +L0 --> L1 +L2 --> L4 +L4 --> L5 +L4 --> L6 +L5 --> L7 +L5 --> L8 +L7 --> L9 +L7 --> L10 +L9 --> L3 +L9 --> L10 +L10 --> L8 +L8 --> L4 +L8 --> L6 +L6 --> L3 ```