mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-14 23:04:57 +00:00
Implmented asm fragment generator
This commit is contained in:
parent
4ca3fe0787
commit
4e4fee9035
83
src/dk/camelot64/kickc/icl/AsmFragmentSignature.java
Normal file
83
src/dk/camelot64/kickc/icl/AsmFragmentSignature.java
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
48
src/dk/camelot64/kickc/icl/AsmSequence.java
Normal file
48
src/dk/camelot64/kickc/icl/AsmSequence.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -23,4 +23,5 @@ public class ConstantInteger implements Constant {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "("+getType().getTypeName()+") "+Integer.toString(number);
|
return "("+getType().getTypeName()+") "+Integer.toString(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ public class Pass2AliasElimination extends Pass2Optimization {
|
|||||||
final Map<Variable, Variable> aliases = findAliases();
|
final Map<Variable, Variable> aliases = findAliases();
|
||||||
removeAssignments(aliases.values());
|
removeAssignments(aliases.values());
|
||||||
replaceVariables(aliases);
|
replaceVariables(aliases);
|
||||||
|
deleteSymbols(aliases.keySet());
|
||||||
for (Variable var : aliases.keySet()) {
|
for (Variable var : aliases.keySet()) {
|
||||||
Variable alias = aliases.get(var);
|
Variable alias = aliases.get(var);
|
||||||
System.out.println("Alias " + var + " " + alias);
|
System.out.println("Alias " + var + " " + alias);
|
||||||
|
@ -23,6 +23,7 @@ public class Pass2ConstantPropagation extends Pass2Optimization {
|
|||||||
System.out.println("Constant " + constantVar + " " + constantValue);
|
System.out.println("Constant " + constantVar + " " + constantValue);
|
||||||
}
|
}
|
||||||
removeAssignments(constants.keySet());
|
removeAssignments(constants.keySet());
|
||||||
|
deleteSymbols(constants.keySet());
|
||||||
replaceVariables(constants);
|
replaceVariables(constants);
|
||||||
return constants.size() > 0;
|
return constants.size() > 0;
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ public abstract class Pass2Optimization {
|
|||||||
* @param aliases Variables that have alias values.
|
* @param aliases Variables that have alias values.
|
||||||
*/
|
*/
|
||||||
public void replaceVariables(final Map<Variable, ? extends RValue> aliases) {
|
public void replaceVariables(final Map<Variable, ? extends RValue> aliases) {
|
||||||
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor() {
|
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Object visitAssignment(StatementAssignment assignment) {
|
public Void visitAssignment(StatementAssignment assignment) {
|
||||||
if(getAlias(aliases, assignment.getLValue()) !=null) {
|
if(getAlias(aliases, assignment.getLValue()) !=null) {
|
||||||
RValue alias = getAlias(aliases, assignment.getLValue());
|
RValue alias = getAlias(aliases, assignment.getLValue());
|
||||||
if(alias instanceof LValue) {
|
if(alias instanceof LValue) {
|
||||||
@ -65,7 +65,7 @@ public abstract class Pass2Optimization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitConditionalJump(StatementConditionalJump conditionalJump) {
|
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||||
if(getAlias(aliases, conditionalJump.getCondition())!=null) {
|
if(getAlias(aliases, conditionalJump.getCondition())!=null) {
|
||||||
conditionalJump.setCondition(getAlias(aliases, conditionalJump.getCondition()));
|
conditionalJump.setCondition(getAlias(aliases, conditionalJump.getCondition()));
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ public abstract class Pass2Optimization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitPhi(StatementPhi phi) {
|
public Void visitPhi(StatementPhi phi) {
|
||||||
if(getAlias(aliases, phi.getLValue())!=null) {
|
if(getAlias(aliases, phi.getLValue())!=null) {
|
||||||
RValue alias = getAlias(aliases, phi.getLValue());
|
RValue alias = getAlias(aliases, phi.getLValue());
|
||||||
if(alias instanceof LValue) {
|
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
|
* @param variables The variables to eliminate
|
||||||
*/
|
*/
|
||||||
public void removeAssignments(Collection<? extends LValue> variables) {
|
public void removeAssignments(Collection<? extends LValue> variables) {
|
||||||
@ -175,17 +175,26 @@ public abstract class Pass2Optimization {
|
|||||||
StatementAssignment assignment = (StatementAssignment) statement;
|
StatementAssignment assignment = (StatementAssignment) statement;
|
||||||
if (variables.contains(assignment.getLValue())) {
|
if (variables.contains(assignment.getLValue())) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
symbolTable.remove((Symbol) assignment.getLValue());
|
|
||||||
}
|
}
|
||||||
} else if(statement instanceof StatementPhi) {
|
} else if(statement instanceof StatementPhi) {
|
||||||
StatementPhi phi = (StatementPhi) statement;
|
StatementPhi phi = (StatementPhi) statement;
|
||||||
if (variables.contains(phi.getLValue())) {
|
if (variables.contains(phi.getLValue())) {
|
||||||
iterator.remove();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ public class Pass2RedundantPhiElimination extends Pass2Optimization{
|
|||||||
public boolean optimize() {
|
public boolean optimize() {
|
||||||
final Map<Variable, RValue> aliases = findRedundantPhis();
|
final Map<Variable, RValue> aliases = findRedundantPhis();
|
||||||
removeAssignments(aliases.keySet());
|
removeAssignments(aliases.keySet());
|
||||||
|
deleteSymbols(aliases.keySet());
|
||||||
replaceVariables(aliases);
|
replaceVariables(aliases);
|
||||||
for (Variable var : aliases.keySet()) {
|
for (Variable var : aliases.keySet()) {
|
||||||
RValue alias = aliases.get(var);
|
RValue alias = aliases.get(var);
|
||||||
|
@ -16,7 +16,11 @@ public class Pass3RegisterAllocation {
|
|||||||
int currentZp = 2;
|
int currentZp = 2;
|
||||||
for (Variable var : symbols.getAllVariables()) {
|
for (Variable var : symbols.getAllVariables()) {
|
||||||
if(var instanceof VariableIntermediate || var instanceof VariableVersion)
|
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);
|
symbols.setAllocation(allocation);
|
||||||
}
|
}
|
||||||
|
187
src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java
Normal file
187
src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -35,14 +35,16 @@ public class RegisterAllocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The register type. */
|
/** 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. */
|
/** 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;
|
private int zp;
|
||||||
|
|
||||||
public RegisterZp(int zp) {
|
public RegisterZpByte(int zp) {
|
||||||
this.zp = zp;
|
this.zp = zp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +54,35 @@ public class RegisterAllocation {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegisterType getType() {
|
public RegisterType getType() {
|
||||||
return RegisterType.ZP;
|
return RegisterType.ZP_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
2
src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm
Normal file
2
src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
lda #{coby1}
|
||||||
|
sta {zpby1}
|
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm
Normal file
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+coby1.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
lda {zpby2}
|
||||||
|
clc
|
||||||
|
adc #{coby1}
|
||||||
|
sta {zpby1}
|
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm
Normal file
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2+zpby3.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
lda {zpby2}
|
||||||
|
clc
|
||||||
|
adc {zpby3}
|
||||||
|
sta {zpby1}
|
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm
Normal file
4
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2-coby1.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
lda {zpby2}
|
||||||
|
sec
|
||||||
|
sbc #{coby1}
|
||||||
|
sta {zpby1}
|
2
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm
Normal file
2
src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
lda {zpby2}
|
||||||
|
sta {zpby1}
|
@ -8,7 +8,6 @@ import org.antlr.v4.runtime.CharStreams;
|
|||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.LineNumberReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -33,12 +32,6 @@ public class Main {
|
|||||||
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(symbolTable);
|
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(symbolTable);
|
||||||
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
|
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 =
|
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
|
||||||
new Pass1GenerateSingleStaticAssignmentForm(symbolTable, controlFlowGraph);
|
new Pass1GenerateSingleStaticAssignmentForm(symbolTable, controlFlowGraph);
|
||||||
pass1GenerateSingleStaticAssignmentForm.generate();
|
pass1GenerateSingleStaticAssignmentForm.generate();
|
||||||
@ -65,10 +58,16 @@ public class Main {
|
|||||||
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, symbolTable);
|
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, symbolTable);
|
||||||
pass3RegisterAllocation.allocate();
|
pass3RegisterAllocation.allocate();
|
||||||
|
|
||||||
|
Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(controlFlowGraph, symbolTable);
|
||||||
|
|
||||||
|
AsmSequence asmSequence = pass4CodeGeneration.generate();
|
||||||
|
|
||||||
System.out.println("SYMBOLS");
|
System.out.println("SYMBOLS");
|
||||||
System.out.println(symbolTable.toString());
|
System.out.println(symbolTable.toString());
|
||||||
System.out.println("CONTROL FLOW GRAPH");
|
System.out.println("CONTROL FLOW GRAPH");
|
||||||
System.out.println(controlFlowGraph.toString());
|
System.out.println(controlFlowGraph.toString());
|
||||||
|
System.out.println("ASSEMBLER");
|
||||||
|
System.out.println(asmSequence.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
byte a = 0;
|
byte a = 0;
|
||||||
word b = 0;
|
byte b = 0;
|
||||||
byte d=a+b+1;
|
byte d=a+b+1;
|
||||||
while(a<10) {
|
while(a<10) {
|
||||||
b=b+a;
|
b=b+a;
|
||||||
|
Loading…
Reference in New Issue
Block a user