From 8d0ff963411c287f00678d5202505542ccce49b8 Mon Sep 17 00:00:00 2001 From: willson walter Date: Thu, 23 Nov 2023 13:50:00 +0800 Subject: [PATCH] 1. Caching edge links during CFG construction to avoid duplicate edges between the same blocks. 2. Constructing the CFG from the LinearIRBuilder blocks instead of the full program. This allows finer grained CFG construction. 3. Adding a helper method to LinearIRBlock to return jump entry blocks for conditional and unconditional jumps. 4. Updating the CFG visualization to reflect the code logic of control flow. --- ep18/src/main/resources/t.vm | 33 +++---- .../org/teachfx/antlr4/ep20/Compiler.java | 4 +- .../antlr4/ep20/pass/cfg/CFGBuilder.java | 21 ++++- .../antlr4/ep20/pass/cfg/LinearIRBlock.java | 25 +++++- .../antlr4/ep20/pass/ir/CymbolIRBuilder.java | 7 +- ep21/README.md | 89 +++++++++++++++---- 6 files changed, 135 insertions(+), 44 deletions(-) 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 ```