From 62533afc6a0717e385968fc98f68cd8ff9561662 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 15 May 2017 18:30:43 +0200 Subject: [PATCH] Refactored fragment handling --- src/dk/camelot64/kickc/icl/AsmFragment.java | 199 ++++++++++++++++++ .../kickc/icl/AsmFragmentSignature.java | 90 -------- .../icl/AsmFragmentSignatureAssignment.java | 31 --- .../AsmFragmentSignatureConditionalJump.java | 13 -- .../kickc/icl/Pass4CodeGeneration.java | 96 +-------- 5 files changed, 208 insertions(+), 221 deletions(-) create mode 100644 src/dk/camelot64/kickc/icl/AsmFragment.java delete mode 100644 src/dk/camelot64/kickc/icl/AsmFragmentSignature.java delete mode 100644 src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java delete mode 100644 src/dk/camelot64/kickc/icl/AsmFragmentSignatureConditionalJump.java diff --git a/src/dk/camelot64/kickc/icl/AsmFragment.java b/src/dk/camelot64/kickc/icl/AsmFragment.java new file mode 100644 index 000000000..b317712c7 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/AsmFragment.java @@ -0,0 +1,199 @@ +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.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Code Generation Fragment that can handle loading of fragment file and binding of values / registers */ +public class AsmFragment { + + /** The symbol table. */ + private SymbolTable symbols; + + /** Binding of named values in the fragment to values (constants, variables, ...) .*/ + private Map bindings; + + /** The string signature/name of the asm fragment. */ + private String signature; + + public AsmFragment(StatementConditionalJump conditionalJump, SymbolTable symbols) { + this.bindings = new HashMap<>(); + this.symbols = symbols; + StringBuilder signature = new StringBuilder(); + signature.append(bind(conditionalJump.getCondition())); + signature.append("?"); + signature.append(bind(conditionalJump.getDestination())); + setSignature(signature.toString()); + } + + public AsmFragment(StatementAssignment assignment, SymbolTable symbols) { + this.bindings = new HashMap<>(); + this.symbols = symbols; + setSignature(assignmentSignature(assignment.getLValue(), assignment.getRValue1(), assignment.getOperator(), assignment.getRValue2())); + } + + public AsmFragment(LValue lValue, RValue rValue, SymbolTable symbols) { + this.bindings = new HashMap<>(); + this.symbols = symbols; + setSignature(assignmentSignature(lValue, null, null, rValue)); + } + + private String assignmentSignature(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)); + return signature.toString(); + } + + public Value 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; + + /** Label indexing. */ + private int nextLabelIdx = 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(Value 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 if (value instanceof Label) { + String name = "la"+ nextLabelIdx++; + bindings.put(name, value); + return name; + } else { + throw new RuntimeException("Binding of value type not supported " + value); + } + } + + /** + * Get the value to replace a bound name with from the fragment signature + * + * @param name The name of the bound value in the fragment + * @return The bound value to use in the generated ASM code + */ + public String getValue(String name) { + Value boundValue = getBinding(name); + 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 if (boundValue instanceof Label) { + bound = ((Label) boundValue).getName().replace('@', 'B'); + } else { + throw new RuntimeException("Bound Value Type not implemented " + boundValue); + } + return bound; + } + + /** + * Generate assembler code for the assembler fragment. + * + * @param asm The assembler sequence to generate into. + */ + public void generateAsm(AsmSequence asm) { + String signature = this.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 = this.getValue(name); + line = line.replaceFirst("\\{[^}]*}", bound); + } + asm.addAsm(" " + line); + } + fragmentReader.close(); + fragmentStream.close(); + } catch (IOException e) { + throw new RuntimeException("Error reading code fragment " + fragmentResource); + } + + } + + + +} diff --git a/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java b/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java deleted file mode 100644 index 437ee7aeb..000000000 --- a/src/dk/camelot64/kickc/icl/AsmFragmentSignature.java +++ /dev/null @@ -1,90 +0,0 @@ -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 bindings; - - /** The string signature/name of the asm fragment. */ - private String signature; - - public AsmFragmentSignature(SymbolTable symbols) { - this.symbols = symbols; - this.bindings = new HashMap<>(); - } - - public Value 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; - - /** Label indexing. */ - private int nextLabelIdx = 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(Value 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 if (value instanceof Label) { - String name = "la"+ nextLabelIdx++; - bindings.put(name, value); - return name; - } 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 deleted file mode 100644 index a748c6bb6..000000000 --- a/src/dk/camelot64/kickc/icl/AsmFragmentSignatureAssignment.java +++ /dev/null @@ -1,31 +0,0 @@ -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/AsmFragmentSignatureConditionalJump.java b/src/dk/camelot64/kickc/icl/AsmFragmentSignatureConditionalJump.java deleted file mode 100644 index 755712e31..000000000 --- a/src/dk/camelot64/kickc/icl/AsmFragmentSignatureConditionalJump.java +++ /dev/null @@ -1,13 +0,0 @@ -package dk.camelot64.kickc.icl; - -/** Assembler Fragment Signature for a conditional jump */ -public class AsmFragmentSignatureConditionalJump extends AsmFragmentSignature { - public AsmFragmentSignatureConditionalJump(StatementConditionalJump conditionalJump, SymbolTable symbols) { - super(symbols); - StringBuilder signature = new StringBuilder(); - signature.append(bind(conditionalJump.getCondition())); - signature.append("?"); - signature.append(bind(conditionalJump.getDestination())); - setSignature(signature.toString()); - } -} diff --git a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java index 87cd486c5..f7c7af24d 100644 --- a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java +++ b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java @@ -1,13 +1,6 @@ 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 @@ -55,13 +48,13 @@ public class Pass4CodeGeneration { 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); + AsmFragment asmFragment = new AsmFragment((StatementAssignment) statement, symbols); + asm.addAsm(" // " + statement + " // " + asmFragment.getSignature()); + asmFragment.generateAsm(asm); } else if (statement instanceof StatementConditionalJump) { - AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignatureConditionalJump((StatementConditionalJump) statement, symbols); - asm.addAsm(" // " + statement + " // " + asmFragmentSignature.getSignature()); - genAsmFragment(asm, asmFragmentSignature); + AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, symbols); + asm.addAsm(" // " + statement + " // " + asmFragment.getSignature()); + asmFragment.generateAsm(asm); } else { asm.addAsm(" // TODO: " + statement); } @@ -102,9 +95,9 @@ public class Pass4CodeGeneration { * @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); + AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); + asm.addAsm(" // " + rValue + " = " + lValue + " // " + asmFragment.getSignature()); + asmFragment.generateAsm(asm); } private void genAsmLabel(AsmSequence asm, Label label) { @@ -119,76 +112,5 @@ public class Pass4CodeGeneration { 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) { - Value 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 if (boundValue instanceof Label) { - bound = ((Label) boundValue).getName().replace('@', 'B'); - } else { - throw new RuntimeException("Bound Value Type not implemented " + boundValue); - } - return bound; - } - }