From 4e4fee9035d5ee8b12d0381db8501c0c0d85d255 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 15 May 2017 17:01:11 +0200
Subject: [PATCH] Implmented asm fragment generator

---
 .../kickc/icl/AsmFragmentSignature.java       |  83 ++++++++
 .../icl/AsmFragmentSignatureAssignment.java   |  31 +++
 src/dk/camelot64/kickc/icl/AsmSequence.java   |  48 +++++
 .../camelot64/kickc/icl/ConstantInteger.java  |   1 +
 .../kickc/icl/Pass2AliasElimination.java      |   1 +
 .../kickc/icl/Pass2ConstantPropagation.java   |   1 +
 .../kickc/icl/Pass2Optimization.java          |  23 ++-
 .../icl/Pass2RedundantPhiElimination.java     |   1 +
 .../kickc/icl/Pass3RegisterAllocation.java    |   6 +-
 .../kickc/icl/Pass4CodeGeneration.java        | 187 ++++++++++++++++++
 .../kickc/icl/RegisterAllocation.java         |  36 +++-
 .../camelot64/kickc/icl/asm/zpby1=coby1.asm   |   2 +
 .../kickc/icl/asm/zpby1=zpby2+coby1.asm       |   4 +
 .../kickc/icl/asm/zpby1=zpby2+zpby3.asm       |   4 +
 .../kickc/icl/asm/zpby1=zpby2-coby1.asm       |   4 +
 .../camelot64/kickc/icl/asm/zpby1=zpby2.asm   |   2 +
 src/dk/camelot64/kickc/test/Main.java         |  13 +-
 src/dk/camelot64/kickc/test/test.kc           |   2 +-
 18 files changed, 428 insertions(+), 21 deletions(-)
 create mode 100644 src/dk/camelot64/kickc/icl/AsmFragmentSignature.java
 create mode 100644 src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java
 create mode 100644 src/dk/camelot64/kickc/icl/AsmSequence.java
 create mode 100644 src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java
 create mode 100644 src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm
 create mode 100644 src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm
 create mode 100644 src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm
 create mode 100644 src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm
 create mode 100644 src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm

diff --git a/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java b/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java
new file mode 100644
index 000000000..1ed10e690
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java
@@ -0,0 +1,83 @@
+package dk.camelot64.kickc.icl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**  Signature and Binding for a Code Generation Fragment */
+public abstract class AsmFragmentSignature {
+
+   /** The symbol table. */
+   private SymbolTable symbols;
+
+   /** Binding of named values in the fragment to values (constants, variables, ...) .*/
+   private Map<String, RValue> bindings;
+
+   /** The string signature/name of the asm fragment. */
+   private String signature;
+
+   public AsmFragmentSignature(SymbolTable symbols) {
+      this.symbols = symbols;
+      this.bindings = new HashMap<>();
+   }
+
+   public RValue getBinding(String name) {
+      return bindings.get(name);
+   }
+
+   public String getSignature() {
+      return signature;
+   }
+
+   public void setSignature(String signature) {
+      this.signature = signature;
+   }
+
+   /** Zero page byte register name indexing. */
+   private int nextZpByteIdx = 1;
+
+   /** Zero page bool register name indexing. */
+   private int nextZpBoolIdx = 1;
+
+   /** Constant byte indexing. */
+   private int nextConstByteIdx = 1;
+
+   /**
+    * Add bindings of a value.
+    * @param value The value to bind.
+    * @return The bound name of the value. If the value has already been bound the existing bound name is returned.
+    */
+   public String bind(RValue value) {
+      // Find value if it is already bound
+      for (String name : bindings.keySet()) {
+         if (value.equals(bindings.get(name))) {
+            return name;
+         }
+      }
+      if (value instanceof Variable) {
+         RegisterAllocation.Register register = symbols.getRegister((Variable) value);
+         if (RegisterAllocation.RegisterType.ZP_BYTE.equals(register.getType())) {
+            String name = "zpby" + nextZpByteIdx++;
+            bindings.put(name, value);
+            return name;
+         } else if (RegisterAllocation.RegisterType.ZP_BOOL.equals(register.getType())) {
+            String name = "zpbo" + nextZpBoolIdx++;
+            bindings.put(name, value);
+            return name;
+         } else {
+            throw new RuntimeException("Binding of register type not supported " + register.getType());
+         }
+      } else if (value instanceof ConstantInteger) {
+         ConstantInteger intValue = (ConstantInteger) value;
+         if(intValue.getType().equals(SymbolType.BYTE)) {
+            String name = "coby"+ nextConstByteIdx++;
+            bindings.put(name, value);
+            return name;
+         } else {
+            throw new RuntimeException("Binding of word integers not supported " + intValue);
+         }
+      } else {
+         throw new RuntimeException("Binding of value type not supported " + value);
+      }
+   }
+
+}
diff --git a/src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java b/src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java
new file mode 100644
index 000000000..a748c6bb6
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java
@@ -0,0 +1,31 @@
+package dk.camelot64.kickc.icl;
+
+/** Assembler Fragemnt Signature for an assignment  */
+public class AsmFragmentSignatureAssignment extends AsmFragmentSignature {
+
+   public AsmFragmentSignatureAssignment(StatementAssignment assignment, SymbolTable symbols) {
+      super(symbols);
+      setSignature(assignment.getLValue(), assignment.getRValue1(), assignment.getOperator(), assignment.getRValue2());
+   }
+
+   public AsmFragmentSignatureAssignment(LValue lValue, RValue rValue, SymbolTable symbols) {
+      super(symbols);
+      setSignature(lValue, null, null, rValue);
+   }
+
+   private void setSignature(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) {
+      StringBuilder signature = new StringBuilder();
+      signature.append(bind(lValue));
+      signature.append("=");
+      if (rValue1 != null) {
+         signature.append(bind(rValue1));
+      }
+      if (operator != null) {
+         signature.append(operator.getOperator());
+      }
+      signature.append(bind(rValue2));
+      setSignature(signature.toString());
+   }
+
+
+}
diff --git a/src/dk/camelot64/kickc/icl/AsmSequence.java b/src/dk/camelot64/kickc/icl/AsmSequence.java
new file mode 100644
index 000000000..9ba99df04
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/AsmSequence.java
@@ -0,0 +1,48 @@
+package dk.camelot64.kickc.icl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** A sequence of assembler code. */
+public class AsmSequence {
+
+   private List<AsmStatement> sequence;
+
+   public AsmSequence() {
+      this.sequence = new ArrayList<>();
+   }
+
+   public List<AsmStatement> getSequence() {
+      return sequence;
+   }
+
+   public void addAsm(String asm) {
+      sequence.add(new AsmStatement(asm));
+   }
+
+   public class AsmStatement {
+      private String asm;
+
+      public AsmStatement(String asm) {
+         this.asm = asm;
+      }
+
+      public String getAsm() {
+         return asm;
+      }
+
+      @Override
+      public String toString() {
+         return asm ;
+      }
+   }
+
+   @Override
+   public String toString() {
+      StringBuffer out = new StringBuffer();
+      for (AsmStatement asmStatement : sequence) {
+         out.append(asmStatement+"\n");
+      }
+      return out.toString();
+   }
+}
diff --git a/src/dk/camelot64/kickc/icl/ConstantInteger.java b/src/dk/camelot64/kickc/icl/ConstantInteger.java
index 38aff41a4..faf3cf0cb 100644
--- a/src/dk/camelot64/kickc/icl/ConstantInteger.java
+++ b/src/dk/camelot64/kickc/icl/ConstantInteger.java
@@ -23,4 +23,5 @@ public class ConstantInteger implements Constant {
    public String toString() {
       return "("+getType().getTypeName()+") "+Integer.toString(number);
    }
+
 }
diff --git a/src/dk/camelot64/kickc/icl/Pass2AliasElimination.java b/src/dk/camelot64/kickc/icl/Pass2AliasElimination.java
index 24f802797..56da42a31 100644
--- a/src/dk/camelot64/kickc/icl/Pass2AliasElimination.java
+++ b/src/dk/camelot64/kickc/icl/Pass2AliasElimination.java
@@ -18,6 +18,7 @@ public class Pass2AliasElimination extends Pass2Optimization {
       final Map<Variable, Variable> aliases = findAliases();
       removeAssignments(aliases.values());
       replaceVariables(aliases);
+      deleteSymbols(aliases.keySet());
       for (Variable var : aliases.keySet()) {
          Variable alias = aliases.get(var);
          System.out.println("Alias " + var + " " + alias);
diff --git a/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java b/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java
index 6cba75b7d..0df412f9d 100644
--- a/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java
+++ b/src/dk/camelot64/kickc/icl/Pass2ConstantPropagation.java
@@ -23,6 +23,7 @@ public class Pass2ConstantPropagation extends Pass2Optimization {
          System.out.println("Constant " + constantVar + " " + constantValue);
       }
       removeAssignments(constants.keySet());
+      deleteSymbols(constants.keySet());
       replaceVariables(constants);
       return constants.size() > 0;
    }
diff --git a/src/dk/camelot64/kickc/icl/Pass2Optimization.java b/src/dk/camelot64/kickc/icl/Pass2Optimization.java
index f7e302705..bd4a623b9 100644
--- a/src/dk/camelot64/kickc/icl/Pass2Optimization.java
+++ b/src/dk/camelot64/kickc/icl/Pass2Optimization.java
@@ -46,9 +46,9 @@ public abstract  class Pass2Optimization {
     * @param aliases Variables that have alias values.
     */
    public void replaceVariables(final Map<Variable, ? extends RValue> aliases) {
-      ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor() {
+      ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
          @Override
-         public Object visitAssignment(StatementAssignment assignment) {
+         public Void visitAssignment(StatementAssignment assignment) {
             if(getAlias(aliases, assignment.getLValue()) !=null) {
                RValue alias = getAlias(aliases, assignment.getLValue());
                if(alias instanceof LValue) {
@@ -65,7 +65,7 @@ public abstract  class Pass2Optimization {
          }
 
          @Override
-         public Object visitConditionalJump(StatementConditionalJump conditionalJump) {
+         public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
             if(getAlias(aliases, conditionalJump.getCondition())!=null) {
                conditionalJump.setCondition(getAlias(aliases, conditionalJump.getCondition()));
             }
@@ -73,7 +73,7 @@ public abstract  class Pass2Optimization {
          }
 
          @Override
-         public Object visitPhi(StatementPhi phi) {
+         public Void visitPhi(StatementPhi phi) {
             if(getAlias(aliases, phi.getLValue())!=null) {
                RValue alias = getAlias(aliases, phi.getLValue());
                if(alias instanceof LValue) {
@@ -164,7 +164,7 @@ public abstract  class Pass2Optimization {
 
 
    /**
-    * Remove all assignments to specific LValues from the control frlo graph (as they are no longer needed).
+    * Remove all assignments to specific LValues from the control flow graph (as they are no longer needed).
     * @param variables The variables to eliminate
     */
    public void removeAssignments(Collection<? extends LValue> variables) {
@@ -175,17 +175,26 @@ public abstract  class Pass2Optimization {
                StatementAssignment assignment = (StatementAssignment) statement;
                if (variables.contains(assignment.getLValue())) {
                   iterator.remove();
-                  symbolTable.remove((Symbol) assignment.getLValue());
                }
             } else if(statement instanceof StatementPhi) {
                StatementPhi phi = (StatementPhi) statement;
                if (variables.contains(phi.getLValue())) {
                   iterator.remove();
-                  symbolTable.remove(phi.getLValue());
                }
             }
          }
       }
    }
 
+   /**
+    * Remove variables from the symbol table
+    * @param variables The variables to remove
+    */
+   public void deleteSymbols(Collection<? extends LValue> variables) {
+      for (LValue variable : variables) {
+         symbolTable.remove((Symbol) variable);
+      }
+   }
+
+
 }
diff --git a/src/dk/camelot64/kickc/icl/Pass2RedundantPhiElimination.java b/src/dk/camelot64/kickc/icl/Pass2RedundantPhiElimination.java
index 65c5adc0a..847ea83dc 100644
--- a/src/dk/camelot64/kickc/icl/Pass2RedundantPhiElimination.java
+++ b/src/dk/camelot64/kickc/icl/Pass2RedundantPhiElimination.java
@@ -17,6 +17,7 @@ public class Pass2RedundantPhiElimination extends Pass2Optimization{
    public boolean optimize() {
       final Map<Variable, RValue> aliases = findRedundantPhis();
       removeAssignments(aliases.keySet());
+      deleteSymbols(aliases.keySet());
       replaceVariables(aliases);
       for (Variable var : aliases.keySet()) {
          RValue alias = aliases.get(var);
diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java
index d025adc7f..7bb5de57a 100644
--- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java
+++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java
@@ -16,7 +16,11 @@ public class Pass3RegisterAllocation {
       int currentZp = 2;
       for (Variable var : symbols.getAllVariables()) {
          if(var instanceof VariableIntermediate || var instanceof VariableVersion)
-         allocation.allocate(var, new RegisterAllocation.RegisterZp(currentZp++));
+            if(var.getType().equals(SymbolType.BYTE)) {
+               allocation.allocate(var, new RegisterAllocation.RegisterZpByte(currentZp++));
+            } else if(var.getType().equals(SymbolType.BOOLEAN))  {
+               allocation.allocate(var, new RegisterAllocation.RegisterZpBool(currentZp++));
+            }
       }
       symbols.setAllocation(allocation);
    }
diff --git a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java
new file mode 100644
index 000000000..c974ee79f
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java
@@ -0,0 +1,187 @@
+package dk.camelot64.kickc.icl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Code Generation of 6502 Assembler from ICL/SSA Control Flow Graph
+ */
+public class Pass4CodeGeneration {
+
+   private ControlFlowGraph graph;
+   private SymbolTable symbols;
+
+   public Pass4CodeGeneration(ControlFlowGraph graph, SymbolTable symbols) {
+      this.graph = graph;
+      this.symbols = symbols;
+   }
+
+   public AsmSequence generate() {
+      AsmSequence asm = new AsmSequence();
+      for (ControlFlowBlock block : graph.getAllBlocks()) {
+         // Generate entry points (if needed)
+         genBlockEntryPoints(asm, block);
+         // Generate label
+         genAsmLabel(asm, block.getLabel());
+         // Generate statements
+         genStatements(asm, block);
+         // Generate exit
+         ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor();
+         if (defaultSuccessor != null) {
+            if(defaultSuccessor.getPredecessors().size()>1) {
+               String label = defaultSuccessor.getLabel().getName() + "_from_" + block.getLabel().getName();
+               genAsmJump(asm, label);
+            } else {
+               genAsmJump(asm, defaultSuccessor.getLabel().getName());
+            }
+         }
+      }
+      return asm;
+   }
+
+   private void genStatements(AsmSequence asm, ControlFlowBlock block) {
+      for (Statement statement : block.getStatements()) {
+         if (!(statement instanceof StatementPhi)) {
+            genStatement(asm, statement);
+         }
+      }
+   }
+
+   private void genStatement(AsmSequence asm, Statement statement) {
+      if (statement instanceof StatementAssignment) {
+         AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignatureAssignment((StatementAssignment) statement, symbols);
+         asm.addAsm("  // " + statement + "  //  "+asmFragmentSignature.getSignature());
+         genAsmFragment(asm, asmFragmentSignature);
+      } else {
+         asm.addAsm("  // TODO: " + statement);
+      }
+   }
+
+   private void genBlockEntryPoints(AsmSequence asm, ControlFlowBlock block) {
+      List<Statement> statements = block.getStatements();
+      if (statements.size() > 0 && (statements.get(0) instanceof StatementPhi)) {
+         for (ControlFlowBlock predecessor : block.getPredecessors()) {
+            genBlockEntryPoint(asm, block, predecessor);
+         }
+      }
+   }
+
+   private void genBlockEntryPoint(AsmSequence asm, ControlFlowBlock block, ControlFlowBlock predecessor) {
+      genAsmLabel(asm, block.getLabel().getName() + "_from_" + predecessor.getLabel().getName());
+      for (Statement statement : block.getStatements()) {
+         if (!(statement instanceof StatementPhi)) {
+            // No more phi statements to handle
+            break;
+         }
+         StatementPhi phi = (StatementPhi) statement;
+         for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
+            if (previousSymbol.getBlock().equals(predecessor)) {
+               genAsmMove(asm, previousSymbol.getRValue(), phi.getLValue());
+               break;
+            }
+         }
+      }
+      genAsmJump(asm, block.getLabel().getName());
+   }
+
+   /**
+    * Generate an assembler move from an Rvalue to an LValue
+    *
+    * @param asm    The assembler sequence
+    * @param rValue The rValue
+    * @param lValue The lValue
+    */
+   private void genAsmMove(AsmSequence asm, RValue rValue, LValue lValue) {
+      AsmFragmentSignatureAssignment signature = new AsmFragmentSignatureAssignment(lValue, rValue, symbols);
+      asm.addAsm("  // " + rValue + " = " + lValue + "  // "+signature.getSignature());
+      genAsmFragment(asm, signature);
+   }
+
+   private void genAsmLabel(AsmSequence asm, Label label) {
+      genAsmLabel(asm, label.getName());
+   }
+
+   private void genAsmLabel(AsmSequence asm, String label) {
+      asm.addAsm(label.replace('@', 'B') + ":");
+   }
+
+   private void genAsmJump(AsmSequence asm, String label) {
+      asm.addAsm("  jmp " + label.replace('B', '_'));
+   }
+
+   /**
+    * Generate assembler code for an assembler fragment.
+    *
+    * @param asm               The assembler sequence to generate into.
+    * @param fragmentSignature Signature of the code fragment to generate
+    */
+   private void genAsmFragment(AsmSequence asm, AsmFragmentSignature fragmentSignature) {
+      String signature = fragmentSignature.getSignature();
+      ClassLoader classLoader = this.getClass().getClassLoader();
+      URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/icl/asm/" + signature + ".asm");
+      if (fragmentResource == null) {
+         System.out.println("Fragment not found " + fragmentResource);
+         asm.addAsm("  // Fragment not found: " + signature);
+         return;
+      }
+      Pattern bindPattern = Pattern.compile(".*\\{([^}]*)}.*");
+      try {
+         InputStream fragmentStream = fragmentResource.openStream();
+         BufferedReader fragmentReader = new BufferedReader(new InputStreamReader(fragmentStream));
+         String line;
+         while ((line = fragmentReader.readLine()) != null) {
+            Matcher matcher = bindPattern.matcher(line);
+            if(matcher.matches()) {
+               String name = matcher.group(1);
+               String bound = getFragmentBoundValue(name, fragmentSignature);
+               line = line.replaceFirst("\\{[^}]*}", bound);
+            }
+            asm.addAsm("  " + line);
+         }
+         fragmentReader.close();
+         fragmentStream.close();
+      } catch (IOException e) {
+         throw new RuntimeException("Error reading code fragment " + fragmentResource);
+      }
+
+   }
+
+   /**
+    * Get the value to replace a bound name with from the fragment signature
+    * @param boundName The name of the bound value in the fragment
+    * @param fragmentSignature The fragment signature containing the bindings
+    * @return The bound value to use in the generated ASM code
+    */
+   private String getFragmentBoundValue(String boundName, AsmFragmentSignature fragmentSignature) {
+      RValue boundValue = fragmentSignature.getBinding(boundName);
+      String bound;
+      if(boundValue instanceof Variable) {
+         RegisterAllocation.Register register = symbols.getRegister((Variable) boundValue);
+         if(register instanceof RegisterAllocation.RegisterZpByte) {
+            bound = Integer.toString(((RegisterAllocation.RegisterZpByte) register).getZp());
+         }  else if(register instanceof RegisterAllocation.RegisterZpBool) {
+            bound = Integer.toString(((RegisterAllocation.RegisterZpBool) register).getZp());
+         } else {
+            throw new RuntimeException("Register Type not implemented "+register);
+         }
+      } else if(boundValue instanceof ConstantInteger) {
+         ConstantInteger boundInt = (ConstantInteger) boundValue;
+         if(boundInt.getType().equals(SymbolType.BYTE)) {
+            bound = Integer.toString(boundInt.getNumber());
+         } else {
+            throw new RuntimeException("Bound Value Type not implemented " + boundValue);
+         }
+      } else {
+         throw new RuntimeException("Bound Value Type not implemented " + boundValue);
+      }
+      return bound;
+   }
+
+
+}
diff --git a/src/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/dk/camelot64/kickc/icl/RegisterAllocation.java
index 06f52bad0..6b75100ae 100644
--- a/src/dk/camelot64/kickc/icl/RegisterAllocation.java
+++ b/src/dk/camelot64/kickc/icl/RegisterAllocation.java
@@ -35,14 +35,16 @@ public class RegisterAllocation {
    }
 
    /** The register type. */
-   public enum RegisterType { ZP };
+   public enum RegisterType {
+      ZP_BYTE, ZP_BOOL
+   };
 
    /** A zero page address used as a register for a single byte variable. */
-   public static class RegisterZp implements Register {
+   public static class RegisterZpByte implements Register {
 
       private int zp;
 
-      public RegisterZp(int zp) {
+      public RegisterZpByte(int zp) {
          this.zp = zp;
       }
 
@@ -52,12 +54,35 @@ public class RegisterAllocation {
 
       @Override
       public RegisterType getType() {
-         return  RegisterType.ZP;
+         return  RegisterType.ZP_BYTE;
       }
 
       @Override
       public String toString() {
-         return "zp:"+zp;
+         return "zp byte:"+zp;
+      }
+   }
+
+   /** A zero page address used as a register for a boolean variable. */
+   public static class RegisterZpBool implements Register {
+      private int zp;
+
+      public RegisterZpBool(int zp) {
+         this.zp = zp;
+      }
+
+      public int getZp() {
+         return zp;
+      }
+
+      @Override
+      public RegisterType getType() {
+         return  RegisterType.ZP_BOOL;
+      }
+
+      @Override
+      public String toString() {
+         return "zp bool:"+zp;
       }
    }
 
@@ -70,4 +95,5 @@ public class RegisterAllocation {
       }
       return out.toString();
    }
+
 }
diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm b/src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm
new file mode 100644
index 000000000..74a2a50a8
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm
@@ -0,0 +1,2 @@
+lda #{coby1}
+sta {zpby1}
\ No newline at end of file
diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm
new file mode 100644
index 000000000..5bd825bba
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm
@@ -0,0 +1,4 @@
+lda {zpby2}
+clc
+adc #{coby1}
+sta {zpby1}
\ No newline at end of file
diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm
new file mode 100644
index 000000000..3a5edaaa0
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm
@@ -0,0 +1,4 @@
+lda {zpby2}
+clc
+adc {zpby3}
+sta {zpby1}
\ No newline at end of file
diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm
new file mode 100644
index 000000000..a1cc2cef9
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm
@@ -0,0 +1,4 @@
+lda {zpby2}
+sec
+sbc #{coby1}
+sta {zpby1}
\ No newline at end of file
diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm
new file mode 100644
index 000000000..f52963699
--- /dev/null
+++ b/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm
@@ -0,0 +1,2 @@
+lda {zpby2}
+sta {zpby1}
\ No newline at end of file
diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java
index 4619fb11c..a35fc29d7 100644
--- a/src/dk/camelot64/kickc/test/Main.java
+++ b/src/dk/camelot64/kickc/test/Main.java
@@ -8,7 +8,6 @@ import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
 
 import java.io.IOException;
-import java.io.LineNumberReader;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -33,12 +32,6 @@ public class Main {
       Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(symbolTable);
       ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
 
-      System.out.println("SYMBOLS");
-      System.out.println(symbolTable.toString());
-      System.out.println("CONTROL FLOW GRAPH");
-      System.out.println(controlFlowGraph.toString());
-
-
       Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
             new Pass1GenerateSingleStaticAssignmentForm(symbolTable, controlFlowGraph);
       pass1GenerateSingleStaticAssignmentForm.generate();
@@ -65,10 +58,16 @@ public class Main {
       Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, symbolTable);
       pass3RegisterAllocation.allocate();
 
+      Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(controlFlowGraph, symbolTable);
+
+      AsmSequence asmSequence = pass4CodeGeneration.generate();
+
       System.out.println("SYMBOLS");
       System.out.println(symbolTable.toString());
       System.out.println("CONTROL FLOW GRAPH");
       System.out.println(controlFlowGraph.toString());
+      System.out.println("ASSEMBLER");
+      System.out.println(asmSequence.toString());
    }
 
 }
diff --git a/src/dk/camelot64/kickc/test/test.kc b/src/dk/camelot64/kickc/test/test.kc
index 8fa686ee9..543ed766f 100644
--- a/src/dk/camelot64/kickc/test/test.kc
+++ b/src/dk/camelot64/kickc/test/test.kc
@@ -1,5 +1,5 @@
 byte a = 0;
-word b = 0;
+byte b = 0;
 byte d=a+b+1;
 while(a<10) {
   b=b+a;