diff --git a/prev23/src/prev23/phase/imcgen/CodeGenerator.java b/prev23/src/prev23/phase/imcgen/CodeGenerator.java index 4d9519f..96b27b7 100644 --- a/prev23/src/prev23/phase/imcgen/CodeGenerator.java +++ b/prev23/src/prev23/phase/imcgen/CodeGenerator.java @@ -283,11 +283,14 @@ public ImcInstr visit(AstExprStmt exprStmt, Boolean is_return) { @Override public ImcInstr visit(AstIfStmt ifStmt, Boolean is_return) { + var start_label = new MemLabel(); var positive_label = new MemLabel(); + var negative_label = new MemLabel(); var end_label = new MemLabel(); - var negative_label = (ifStmt.elseStmt != null) ? new MemLabel() : end_label; var stmts = new Vector<>(List.of( + new ImcJUMP(start_label), + new ImcLABEL(start_label), new ImcCJUMP(accept_expr(ifStmt.cond), positive_label, negative_label), new ImcLABEL(positive_label), accept_stmt(ifStmt.thenStmt, false), @@ -295,10 +298,13 @@ public ImcInstr visit(AstIfStmt ifStmt, Boolean is_return) { new ImcLABEL(negative_label) )); - if (ifStmt.elseStmt != null) stmts.addAll(List.of( - accept_stmt(ifStmt.elseStmt, false), - new ImcJUMP(end_label), - new ImcLABEL(end_label) + if (ifStmt.elseStmt != null) stmts.add( + accept_stmt(ifStmt.elseStmt, false) + ); + + stmts.addAll(List.of( + new ImcJUMP(end_label), + new ImcLABEL(end_label) )); return declare_stmt(ifStmt, new ImcSTMTS(stmts), is_return); @@ -316,10 +322,15 @@ public ImcInstr visit(AstStmts stmts, Boolean is_return) { @Override public ImcInstr visit(AstWhileStmt whileStmt, Boolean is_return) { + var start_label = new MemLabel(); var condition_label = new MemLabel(); var body_label = new MemLabel(); var end_label = new MemLabel(); + return declare_stmt(whileStmt, new ImcSTMTS(new Vector<>(List.of( + new ImcJUMP(start_label), + new ImcLABEL(start_label), + new ImcJUMP(condition_label), new ImcLABEL(condition_label), new ImcCJUMP(accept_expr(whileStmt.cond), body_label, end_label), new ImcLABEL(body_label), diff --git a/prev23/src/prev23/phase/imclin/ChunkGenerator.java b/prev23/src/prev23/phase/imclin/ChunkGenerator.java index 0468a9e..fd2f3d0 100644 --- a/prev23/src/prev23/phase/imclin/ChunkGenerator.java +++ b/prev23/src/prev23/phase/imclin/ChunkGenerator.java @@ -2,6 +2,7 @@ import java.util.*; +import prev23.common.report.Report; import prev23.data.ast.tree.decl.*; import prev23.data.ast.tree.expr.*; import prev23.data.ast.visitor.*; @@ -26,7 +27,9 @@ public Object visit(AstFunDecl funDecl, Object o) { body.add(0, new ImcLABEL(entry_label)); body.add(new ImcJUMP(exit_label)); - ImcLin.addCodeChunk(new LinCodeChunk(frame, body, entry_label, exit_label)); + var fixed = fix_basic_blocks(body, entry_label, exit_label); + + ImcLin.addCodeChunk(new LinCodeChunk(frame, fixed, entry_label, exit_label)); funDecl.stmt.accept(this, o); @@ -53,4 +56,92 @@ public Object visit(AstAtomExpr atomExpr, Object o) { } return null; } + + private Vector fix_basic_blocks(Vector stmts, MemLabel entry_label, MemLabel exit_label) { + HashMap> basic_blocks = new HashMap<>(); + + Vector block = null; + + for (var stmt : stmts) { + if (stmt instanceof ImcLABEL label) { + if (block != null) { + throw new Report.InternalError(); + } + block = new Vector<>(); + basic_blocks.put(label.label, block); + } + + // Skip dead code + if (block == null) continue; + + block.add(stmt); + + if (stmt instanceof ImcJUMP || stmt instanceof ImcCJUMP) { + block = null; + } + } + + if (block != null) { + throw new Report.InternalError(); + } + + var fixed = new Vector(); + + // Insert basic blocks starting with entry_label + var next_blocks = new LinkedList(); + next_blocks.addFirst(entry_label); + while(!next_blocks.isEmpty()) { + var next_block_label = next_blocks.removeFirst(); + + // Skip exit block + if (next_block_label.name.equals(exit_label.name)) continue; + + var next_block = basic_blocks.get(next_block_label); + + if (next_block == null) { + continue; + } + + fixed.addAll(next_block); + basic_blocks.remove(next_block_label); + + var next_jump = next_block.lastElement(); + + if (next_jump instanceof ImcJUMP jump) { + next_blocks.addFirst(jump.label); + } else if (next_jump instanceof ImcCJUMP cjump) { + next_blocks.addFirst(cjump.posLabel); + next_blocks.addFirst(cjump.negLabel); + } + } + + var targeted_labels = new HashSet(); + targeted_labels.add(entry_label); + // Remove sequential JUMP L -> LABEL L + for (int i = 0; i < fixed.size(); i++) { + if (fixed.get(i) instanceof ImcCJUMP cjump) { + targeted_labels.add(cjump.posLabel); + targeted_labels.add(cjump.negLabel); + } else if (fixed.get(i) instanceof ImcJUMP jump) { + if (i + 1 < fixed.size() && fixed.get(i + 1) instanceof ImcLABEL label && jump.label == label.label) { + fixed.remove(i--); + } else { + targeted_labels.add(jump.label); + } + } + } + + var removed = 0; + // Remove unused labels + for (int i = 0; i < fixed.size(); i++) { + if (fixed.get(i) instanceof ImcLABEL label) { + if (!targeted_labels.contains(label.label)) { + fixed.remove(i--); + removed++; + } + } + } + + return fixed; + } } diff --git a/prev23/src/prev23/phase/memory/MemEvaluator.java b/prev23/src/prev23/phase/memory/MemEvaluator.java index 3d29f4f..25b830a 100644 --- a/prev23/src/prev23/phase/memory/MemEvaluator.java +++ b/prev23/src/prev23/phase/memory/MemEvaluator.java @@ -161,7 +161,7 @@ public Object visit(AstAtomExpr atomExpr, MemScope scope) { return null; var value = atomExpr.value.replace("\\\"", "\""); - var const_size = (value.length() + 1) * (new SemChar().size()); + var const_size = (value.length() - 1) * (new SemChar().size()); Memory.strings.put(atomExpr, new MemAbsAccess(const_size, new MemLabel(), value)); return null;