Skip to content

Commit

Permalink
Add basic block CFG visualization
Browse files Browse the repository at this point in the history
- Generate CFG from linear IR blocks
- Insert block labels for visualization
- Override BasicBlock's compareTo for deterministic order
- Render sample CFG in README
  • Loading branch information
whtoo committed Nov 19, 2023
1 parent ad54724 commit 56a31f6
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 20 deletions.
9 changes: 8 additions & 1 deletion ep20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ graph LR
### 线性化IR
我们的IR本质上是tree模式的,这样一来我们的线性化实际上延迟到了指令生成时。
但是,这样一来我们就无法进行活性分析和很多与TAC表示相关的分析(或者是我没找到
直接对栈代码做分析的例子)。因此,我要对ep20的输出code过程进行线性改造。
直接对栈代码做分析的例子)。因此,我要对ep20的输出code过程进行线性改造。

### CFG

```mermaid
graph TD;
L0["iconst 0;istore 0;;iconst 7;igt"]
```
8 changes: 5 additions & 3 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.teachfx.antlr4.ep20.parser.CymbolLexer;
import org.teachfx.antlr4.ep20.parser.CymbolParser;
import org.teachfx.antlr4.ep20.pass.ast.CymbolASTBuilder;
//import org.teachfx.antlr4.ep20.pass.ir.CymbolIRBuilder;

import org.teachfx.antlr4.ep20.pass.codegen.CymbolAssembler;
import org.teachfx.antlr4.ep20.pass.ir.CymbolIRBuilder;
import org.teachfx.antlr4.ep20.pass.symtab.LocalDefine;
Expand Down Expand Up @@ -49,11 +49,13 @@ public static void main(String[] args) throws IOException {
var irBuilder = new CymbolIRBuilder();

astRoot.accept(irBuilder);
// printIRTree(irBuilder.prog.linearInstrs());

var cfg = irBuilder.getCFG();
logger.info("CFG:\n" + cfg);

var assembler = new CymbolAssembler();
irBuilder.prog.accept(assembler);
saveToEp18Res(assembler.getAsmInfo());
// saveToEp18Res(assembler.getAsmInfo());
logger.info("\n%s".formatted(assembler.getAsmInfo()));
}

Expand Down
3 changes: 0 additions & 3 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/ir/Prog.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ public void addBlock(LinearIRBlock linearIRBlock) {
private void linearInstrsImpl(@NotNull LinearIRBlock linearIRBlock) {
// Add all instr from non-empty block
if (!linearIRBlock.getStmts().isEmpty()) {
if (!linearIRBlock.getJmpRefMap().isEmpty()){
instrs.add(linearIRBlock.getLabel());
}
instrs.addAll(linearIRBlock.getStmts());
} else {
// Drop empty block
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@
import java.util.Optional;
import java.util.Set;

public class BasicBlock<I extends IRNode> implements Iterable<Loc<I>> {
public class BasicBlock<I extends IRNode> implements Comparable<BasicBlock<I>>, Iterable<Loc<I>> {

@Override
public int compareTo(@NotNull BasicBlock<I> o) {
return this.id - o.id;
}


// Generate codes
public List<Loc<I>> codes;
Expand Down
11 changes: 10 additions & 1 deletion ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/CFG.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.teachfx.antlr4.ep20.ir.IRNode;

import java.util.*;
import java.util.LinkedList;

public class CFG<I extends IRNode> implements Iterable<BasicBlock<I>> {
public final List<BasicBlock<I>> nodes;
Expand All @@ -15,7 +16,7 @@ public class CFG<I extends IRNode> implements Iterable<BasicBlock<I>> {

public CFG(List<BasicBlock<I>> nodes, List<Pair<Integer, Integer>> edges) {
// Generate init
this.nodes = nodes;
this.nodes = new LinkedList<>(nodes); ///.stream().sorted(Comparator.comparingInt(BasicBlock::getId)).toList();
this.edges = edges;

links = new ArrayList<>();
Expand Down Expand Up @@ -57,4 +58,12 @@ public int getOutDegree(int id) {
public Iterator<BasicBlock<I>> iterator() {
return nodes.iterator();
}


@Override
public String toString() {
var graphRenderBuffer = new StringBuffer();

return graphRenderBuffer.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
package org.teachfx.antlr4.ep20.pass.cfg;

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.Map;

public class CFGBuilder<I extends IRNode> {
public CFGBuilder(BasicBlock<IRNode> startNode){
public class CFGBuilder {
private CFG<IRNode> cfg;
private List<BasicBlock<IRNode>> basicBlocks;
private List<Pair<Integer,Integer>> edges;
public CFGBuilder(List<LinearIRBlock> blockList){
basicBlocks =new ArrayList<>();
edges = new ArrayList<>();
for (var funcLabelBlock : blockList) {
build(funcLabelBlock);
}
cfg = new CFG<>(basicBlocks, edges);
}

private void build(LinearIRBlock block){
basicBlocks.add(BasicBlock.buildFromLinearBlock(block));
for(var successor : block.getSuccessors()){
edges.add(Pair.of(block.getOrd(), successor.getOrd()));
build(successor);
}
}

public CFG<IRNode> getCFG() {
return cfg;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
public class LinearIRBlock {

// Fields
private static int LABEL_SEQ = 1;
private static int LABEL_SEQ = 0;
private Kind kind = Kind.CONTINUOUS;
private int ord = 1;
private int ord = 0;
private ArrayList<IRNode> stmts;
private List<LinearIRBlock> successors;
private List<LinearIRBlock> predecessors;
Expand Down Expand Up @@ -120,10 +120,11 @@ public void refJMP(IRNode node) {
// Utility Methods
@Override
public String toString() {
var firstInstr = stmts.get(0);

if (firstInstr instanceof FuncEntryLabel) {
return firstInstr.toString();
if (stmts.isEmpty()) {
return "L" + ord;
}
if (stmts.get(0) instanceof FuncEntryLabel funcEntryLabel) {
return funcEntryLabel.toSource();
}
return "L" + ord;
}
Expand All @@ -139,12 +140,18 @@ public String toSource(){
}

public Label getLabel() {
var firstInstr = stmts.get(0);
if (stmts.isEmpty()) {
return new Label(toString(),scope);
}


var firstInstr = stmts.get(0);
if (firstInstr instanceof FuncEntryLabel funcEntryLabel) {
return funcEntryLabel;
}

return new Label(toString(),scope);
}


}
7 changes: 7 additions & 0 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/Loc.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ public Loc(I instr) {
public Set<Operand> liveIn;

public Set<Operand> liveOut;

@Override
public String toString() {
return "Loc{" +
"instr=" + instr +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public Void visit(CallFunc callFunc) {

@Override
public Void visit(Label label) {
// label不存在嵌套可能,下面这种情况必定是空块导致的label悬空。
if (indents > 0) { indents--; }

if (label instanceof FuncEntryLabel){
emit("%s".formatted(label.toSource()));
} else {
Expand All @@ -88,7 +91,7 @@ public Void visit(JMP jmp) {

@Override
public Void visit(CJMP cjmp) {
emit("brf %s".formatted(cjmp.getElseBlock().toString()));
emit("brf %s".formatted(cjmp.getElseBlock().getLabel().toString()));
indents--;
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.teachfx.antlr4.ep20.ast.stmt.*;
import org.teachfx.antlr4.ep20.ast.type.TypeNode;
import org.teachfx.antlr4.ep20.ir.expr.Operand;
import org.teachfx.antlr4.ep20.pass.cfg.CFG;
import org.teachfx.antlr4.ep20.pass.cfg.CFGBuilder;
import org.teachfx.antlr4.ep20.pass.cfg.LinearIRBlock;
import org.teachfx.antlr4.ep20.ir.IRNode;
import org.teachfx.antlr4.ep20.ir.Prog;
Expand All @@ -25,6 +27,7 @@
import org.teachfx.antlr4.ep20.symtab.symbol.MethodSymbol;
import org.teachfx.antlr4.ep20.symtab.symbol.VariableSymbol;

import java.util.Objects;
import java.util.Optional;
import java.util.Stack;

Expand Down Expand Up @@ -418,4 +421,23 @@ protected VarSlot popEvalOperand() {
protected VarSlot peekEvalOperand() {
return evalExprStack.peek();
}

public CFG<IRNode> getCFG() {
for (var func : prog.blockList){
insertBlockLabel(func);
}

var cfgBuilder = new CFGBuilder(prog.blockList);
return cfgBuilder.getCFG();
}

public void insertBlockLabel(LinearIRBlock startBlock) {
var firstInstr = startBlock.getLabel();
if (!(firstInstr instanceof FuncEntryLabel)) {
startBlock.getStmts().add(0,firstInstr);
}
for (var successor : startBlock.getSuccessors()) {
insertBlockLabel(successor);
}
}
}
21 changes: 20 additions & 1 deletion ep21/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,23 @@ 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
```

0 comments on commit 56a31f6

Please sign in to comment.