Skip to content

Commit

Permalink
- Refactor CFG generation to use BasicBlocks
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
whtoo committed Nov 29, 2023
1 parent 8d0ff96 commit 27aa6d0
Show file tree
Hide file tree
Showing 17 changed files with 244 additions and 182 deletions.
3 changes: 1 addition & 2 deletions ep18/src/main/resources/t.vm
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ L7:
load 0
iconst 7
ieq
brf L10
brf L8
L9:
iconst 7
br L3
L10:
L8:
sconst "break"
print
Expand Down
121 changes: 65 additions & 56 deletions ep20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

9 changes: 5 additions & 4 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface IRVisitor<S,E> {
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);

Expand Down
7 changes: 7 additions & 0 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/ir/JMPInstr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.teachfx.antlr4.ep20.ir;

import org.teachfx.antlr4.ep20.ir.stmt.Label;

public interface JMPInstr {
public Label getTarget();
}
8 changes: 7 additions & 1 deletion ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/CJMP.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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, E> S accept(IRVisitor<S, E> visitor) {
return visitor.visit(this);
Expand Down
8 changes: 7 additions & 1 deletion ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/JMP.java
Original file line number Diff line number Diff line change
@@ -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, E> S accept(IRVisitor<S, E> visitor) {
Expand All @@ -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;
Expand Down
21 changes: 20 additions & 1 deletion ep20/src/main/java/org/teachfx/antlr4/ep20/ir/stmt/Label.java
Original file line number Diff line number Diff line change
@@ -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<Label> {

private Stmt nextEntry = null;

Expand All @@ -23,6 +24,12 @@ public Label(String rawLabel, Scope scope) {
}
}

public Label(Scope scope,Integer ord) {
this.seq = ord;
this.rawLabel = "L%d".formatted(seq);
this.scope = scope;
}

public Label(Scope scope) {
this.scope = scope;
this.seq = scope.getLabelSeq();
Expand Down Expand Up @@ -93,4 +100,16 @@ public Scope getScope() {
public int getSeq() {
return seq;
}

@Override
public int hashCode() {
return getSeq();
}

@Override
public int compareTo(@NotNull Label o) {
var e = Integer.valueOf(getSeq());
var t = Integer.valueOf(o.getSeq());
return e.compareTo(t);
}
}
67 changes: 35 additions & 32 deletions ep20/src/main/java/org/teachfx/antlr4/ep20/pass/cfg/BasicBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,45 @@

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;
}


public final int id;
// Generate codes
public List<Loc<I>> codes;
public Kind kind;
// For data flow analysis
public Set<Operand> def;
public Set<Operand> liveUse;
public Set<Operand> liveIn;
public Set<Operand> liveOut;
protected Label label;

public final int id;
public BasicBlock(Kind kind, List<Loc<I>> codes, Label label) {
this.codes = codes;
this.label = label;
this.id = label.getSeq();
this.kind = kind;
}

protected Optional<Label> label;
@NotNull
@Contract("_ -> new")
public static BasicBlock<IRNode> buildFromLinearBlock(@NotNull LinearIRBlock block) {
return new BasicBlock<IRNode>(block.getKind(), block.getStmts().stream().map(Loc::new).toList(), block.getLabel());
}

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

@NotNull
@Override
public Iterator<Loc<I>> iterator() {
return codes.iterator();
}

public Iterator<Loc<I>> backwardIterator() {
return new Iterator<Loc<I>>() {
private int index = codes.size() - 1;

@Override
public boolean hasNext() {
return index != -1;
Expand All @@ -51,24 +67,11 @@ public Loc<I> next() {
};
}

@NotNull
@Contract("_ -> new")
public static BasicBlock<IRNode> buildFromLinearBlock(@NotNull LinearIRBlock block) {
return new BasicBlock<IRNode>(block.getKind(), block.getOrd(), block.getStmts().stream().map(Loc::new).toList(), Optional.of(block.getLabel()));
}

public BasicBlock(Kind kind, int id, List<Loc<I>> codes, Optional<Label> label) {
this.codes = codes;
this.label = label;
this.id = id;
this.kind = kind;
}

public int getId() {
return id;
}

public Optional<Label> getLabel() {
public Label getLabel() {
return label;
}

Expand All @@ -80,28 +83,28 @@ public String getOrdLabel() {
public boolean isEmpty() {
return codes.isEmpty();
}

public List<Loc<I>> allSeq() {
if (kind.equals(Kind.CONTINUOUS)){
if (kind.equals(Kind.CONTINUOUS)) {
return codes;
}
return codes.subList(0, codes.size() - 1);
}

public List<Loc<I>> dropLabelSeq() {
if (codes.size() <= 1) return codes;
return codes.subList(1, codes.size());
}

public I getLastInstr() {
return codes.get(codes.size() - 1).instr;
}

// For data flow analysis
public Set<Operand> def;

public Set<Operand> liveUse;

public Set<Operand> liveIn;

public Set<Operand> liveOut;
public void mergeNearBlock(BasicBlock<I> nextBlock) {
/// remove last jump instr
codes.remove(codes.size() - 1);
/// merge instr
codes.addAll(nextBlock.codes);
}

}
Loading

0 comments on commit 27aa6d0

Please sign in to comment.