mirror of
https://gitlab.com/camelot/kickc.git
synced 2026-10-25 10:02:28 +00:00
Work in progress creating typed AsmParameters (to enable jmp/jsr etc. to be references and to support intelligent scope resolving during ASM generation). Currently not compiling.
This commit is contained in:
1 parent
0ff32887d6
commit
ca8d817b5d
19 files changed
+226
-119
No files matched your search
@@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
|
||||
/** 6502 Assembler Instruction Addressing Modes. */
|
||||
public enum AsmAddressingMode {
|
||||
NON("", "%i", 1),
|
||||
@@ -36,10 +38,10 @@ public enum AsmAddressingMode {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAsm(String mnemnonic, String parameter) {
|
||||
public String getAsm(String mnemnonic, AsmParameter parameter) {
|
||||
String replaced = template.replace("%i", mnemnonic);
|
||||
if(parameter != null) {
|
||||
replaced = replaced.replace("%p", parameter);
|
||||
replaced = replaced.replace("%p", parameter.getAsm());
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
@@ -5,22 +5,22 @@ public class AsmInstruction implements AsmLine {
|
||||
|
||||
private AsmInstructionType type;
|
||||
|
||||
private String parameter;
|
||||
private AsmParameter parameter;
|
||||
|
||||
private int index;
|
||||
|
||||
private boolean dontOptimize;
|
||||
|
||||
public AsmInstruction(AsmInstructionType type, String parameter) {
|
||||
public AsmInstruction(AsmInstructionType type, AsmParameter parameter) {
|
||||
this.type = type;
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
public AsmParameter getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public void setParameter(String parameter) {
|
||||
public void setParameter(AsmParameter parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@ public class AsmInstructionType {
|
||||
return addressingMode.getBytes();
|
||||
}
|
||||
|
||||
public int getOpcode() {
|
||||
int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
public String getAsm(String parameter) {
|
||||
public String getAsm(AsmParameter parameter) {
|
||||
return addressingMode.getAsm(mnemnonic, parameter);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
/** A parameter for an assembler instruction. */
|
||||
public interface AsmParameter {
|
||||
|
||||
String getAsm();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFormat;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
|
||||
public class AsmParameterConstant implements AsmParameter {
|
||||
|
||||
ConstantValue constantExpr;
|
||||
ScopeRef codeScope;
|
||||
Program program;
|
||||
|
||||
|
||||
public AsmParameterConstant(ConstantValue constantExpr, ScopeRef codeScope, Program program) {
|
||||
this.constantExpr = constantExpr;
|
||||
this.codeScope = codeScope;
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return AsmFormat.getAsmConstant(program, constantExpr, 99, codeScope);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
|
||||
public class AsmParameterLabel implements AsmParameter {
|
||||
|
||||
private LabelRef label;
|
||||
|
||||
public AsmParameterLabel(LabelRef label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return label.getLocalName().replace('@', 'b').replace(':', '_');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
|
||||
public class AsmParameterLabelTransition implements AsmParameter {
|
||||
|
||||
private LabelRef fromLabel;
|
||||
private LabelRef toLabel;
|
||||
|
||||
public AsmParameterLabelTransition(LabelRef fromLabel, LabelRef toLabel) {
|
||||
this.fromLabel = fromLabel;
|
||||
this.toLabel = toLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return (toLabel.getLocalName() + "_from_" + fromLabel.getLocalName()).replace('@', 'b').replace(':', '_');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
|
||||
public class AsmParameterProcedure implements AsmParameter {
|
||||
|
||||
private ProcedureRef procedure;
|
||||
|
||||
public AsmParameterProcedure(ProcedureRef procedure) {
|
||||
this.procedure= procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return procedure.getFullName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,7 +70,7 @@ public class AsmProgram {
|
||||
addLine(new AsmScopeEnd());
|
||||
}
|
||||
|
||||
public AsmInstruction addInstruction(String mnemonic, AsmAddressingMode addressingMode, String parameter, boolean zp) {
|
||||
public AsmInstruction addInstruction(String mnemonic, AsmAddressingMode addressingMode, AsmParameter parameter, boolean zp) {
|
||||
AsmInstructionType instructionType = AsmInstructionSet.getInstructionType(mnemonic, addressingMode, zp);
|
||||
AsmInstruction instruction = new AsmInstruction(instructionType, parameter);
|
||||
addLine(instruction);
|
||||
@@ -237,31 +237,31 @@ public class AsmProgram {
|
||||
boolean lineIdx;
|
||||
String indent;
|
||||
|
||||
public AsmPrintState(boolean comments, boolean lineIdx) {
|
||||
AsmPrintState(boolean comments, boolean lineIdx) {
|
||||
this.comments = comments;
|
||||
this.lineIdx = lineIdx;
|
||||
this.indent = "";
|
||||
}
|
||||
|
||||
public boolean isComments() {
|
||||
boolean isComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void incIndent() {
|
||||
void incIndent() {
|
||||
this.indent = this.indent + " ";
|
||||
}
|
||||
|
||||
public void decIndent() {
|
||||
void decIndent() {
|
||||
if(this.indent.length() >= 2) {
|
||||
this.indent = this.indent.substring(0, this.indent.length() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
public String getIndent() {
|
||||
String getIndent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
public boolean getLineIdx() {
|
||||
boolean getLineIdx() {
|
||||
return lineIdx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class AsmFragmentInstance {
|
||||
* @param name The name of the bound value in the fragment
|
||||
* @return The bound value to use in the generated ASM code
|
||||
*/
|
||||
public AsmParameter getBoundValue(String name) {
|
||||
public AsmFragmentParameter getBoundValue(String name) {
|
||||
Value boundValue = null;
|
||||
if(name.length() == 2) {
|
||||
// Short name!
|
||||
@@ -80,7 +80,7 @@ public class AsmFragmentInstance {
|
||||
Variable boundVar = (Variable) boundValue;
|
||||
Registers.Register register = boundVar.getAllocation();
|
||||
if(register != null && register instanceof Registers.RegisterZp) {
|
||||
return new AsmParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), true);
|
||||
return new AsmFragmentParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), true);
|
||||
} else {
|
||||
throw new RuntimeException("Register Type not implemented " + register);
|
||||
}
|
||||
@@ -88,15 +88,15 @@ public class AsmFragmentInstance {
|
||||
ConstantVar constantVar = (ConstantVar) boundValue;
|
||||
String constantValueAsm = AsmFormat.getAsmConstant(program, constantVar.getRef(), 99, codeScopeRef);
|
||||
boolean constantValueZp = SymbolType.BYTE.equals(constantVar.getType());
|
||||
return new AsmParameter(constantValueAsm, constantValueZp);
|
||||
return new AsmFragmentParameter(constantValueAsm, constantValueZp);
|
||||
} else if(boundValue instanceof ConstantValue) {
|
||||
ConstantValue boundConst = (ConstantValue) boundValue;
|
||||
String constantValueAsm = AsmFormat.getAsmConstant(program, boundConst, 99, codeScopeRef);
|
||||
boolean constantValueZp = SymbolType.BYTE.equals(boundConst.getType(program.getScope()));
|
||||
return new AsmParameter(constantValueAsm, constantValueZp);
|
||||
return new AsmFragmentParameter(constantValueAsm, constantValueZp);
|
||||
} else if(boundValue instanceof Label) {
|
||||
String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
|
||||
return new AsmParameter(param, false);
|
||||
return new AsmFragmentParameter(param, false);
|
||||
} else {
|
||||
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
|
||||
}
|
||||
@@ -119,12 +119,12 @@ public class AsmFragmentInstance {
|
||||
/**
|
||||
* A parameter of an ASM instruction from a bound value.
|
||||
*/
|
||||
public static class AsmParameter {
|
||||
public static class AsmFragmentParameter {
|
||||
|
||||
private String param;
|
||||
private boolean zp;
|
||||
|
||||
public AsmParameter(String param, boolean zp) {
|
||||
public AsmFragmentParameter(String param, boolean zp) {
|
||||
this.param = param;
|
||||
this.zp = zp;
|
||||
}
|
||||
@@ -258,7 +258,7 @@ public class AsmFragmentInstance {
|
||||
AsmAddressingMode addressingMode) {
|
||||
KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
|
||||
String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText();
|
||||
AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
|
||||
AsmFragmentParameter parameter = (AsmFragmentParameter) this.visit(exprCtx);
|
||||
AsmInstructionType type = AsmInstructionSet.getInstructionType(
|
||||
mnemonic,
|
||||
addressingMode,
|
||||
@@ -270,61 +270,61 @@ public class AsmFragmentInstance {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsmParameter visitAsmExprBinary(KickCParser.AsmExprBinaryContext ctx) {
|
||||
AsmParameter left = (AsmParameter) this.visit(ctx.asmExpr(0));
|
||||
AsmParameter right = (AsmParameter) this.visit(ctx.asmExpr(1));
|
||||
public AsmFragmentParameter visitAsmExprBinary(KickCParser.AsmExprBinaryContext ctx) {
|
||||
AsmFragmentParameter left = (AsmFragmentParameter) this.visit(ctx.asmExpr(0));
|
||||
AsmFragmentParameter right = (AsmFragmentParameter) this.visit(ctx.asmExpr(1));
|
||||
String param = "" + left.getParam() + ctx.getChild(1).getText() + right.getParam();
|
||||
boolean zp = left.isZp() && right.isZp();
|
||||
return new AsmParameter(param, zp);
|
||||
return new AsmFragmentParameter(param, zp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsmParameter visitAsmExprUnary(KickCParser.AsmExprUnaryContext ctx) {
|
||||
AsmParameter sub = (AsmParameter) this.visit(ctx.asmExpr());
|
||||
public AsmFragmentParameter visitAsmExprUnary(KickCParser.AsmExprUnaryContext ctx) {
|
||||
AsmFragmentParameter sub = (AsmFragmentParameter) this.visit(ctx.asmExpr());
|
||||
String operator = ctx.getChild(0).getText();
|
||||
String param = operator + sub.getParam();
|
||||
boolean isZp = sub.isZp();
|
||||
if(operator.equals("<") || operator.equals(">")) {
|
||||
isZp = true;
|
||||
}
|
||||
return new AsmParameter(param, isZp);
|
||||
return new AsmFragmentParameter(param, isZp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmExprPar(KickCParser.AsmExprParContext ctx) {
|
||||
AsmParameter sub = (AsmParameter) this.visit(ctx.asmExpr());
|
||||
AsmFragmentParameter sub = (AsmFragmentParameter) this.visit(ctx.asmExpr());
|
||||
String param = "[" + sub.getParam() + "]";
|
||||
return new AsmParameter(param, sub.isZp());
|
||||
return new AsmFragmentParameter(param, sub.isZp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
|
||||
public AsmFragmentParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
|
||||
Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
|
||||
ConstantInteger intVal = new ConstantInteger(number.longValue());
|
||||
boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType());
|
||||
String param = AsmFormat.getAsmNumber(number);
|
||||
return new AsmParameter(param, isZp);
|
||||
return new AsmFragmentParameter(param, isZp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmExprChar(KickCParser.AsmExprCharContext ctx) {
|
||||
return new AsmParameter(ctx.getText(), true);
|
||||
return new AsmFragmentParameter(ctx.getText(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsmParameter visitAsmExprLabel(KickCParser.AsmExprLabelContext ctx) {
|
||||
public AsmFragmentParameter visitAsmExprLabel(KickCParser.AsmExprLabelContext ctx) {
|
||||
String param = ctx.NAME().getSymbol().getText();
|
||||
return new AsmParameter(param, false);
|
||||
return new AsmFragmentParameter(param, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmExprLabelRel(KickCParser.AsmExprLabelRelContext ctx) {
|
||||
String param = ctx.ASMREL().getSymbol().getText();
|
||||
return new AsmParameter(param, false);
|
||||
return new AsmFragmentParameter(param, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsmParameter visitAsmExprReplace(KickCParser.AsmExprReplaceContext ctx) {
|
||||
public AsmFragmentParameter visitAsmExprReplace(KickCParser.AsmExprReplaceContext ctx) {
|
||||
String replaceName = ctx.NAME().getSymbol().getText();
|
||||
return bindings.getBoundValue(replaceName);
|
||||
}
|
||||
|
||||
@@ -29,4 +29,24 @@ public class BlockScope extends Scope {
|
||||
public String toString(Program program) {
|
||||
return "scope "+getFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VariableIntermediate addVariableIntermediate() {
|
||||
return getScope().addVariableIntermediate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Label addLabelIntermediate() {
|
||||
return getScope().addLabelIntermediate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String allocateIntermediateLabelName() {
|
||||
return getScope().allocateIntermediateLabelName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String allocateIntermediateVariableName() {
|
||||
return getScope().allocateIntermediateVariableName();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,42 @@
|
||||
package dk.camelot64.kickc.model.symbols;
|
||||
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
|
||||
/**
|
||||
* A Scope that is a part of the call-graph.
|
||||
* This is the {@link ProgramScope} and {@link Procedure}
|
||||
*/
|
||||
public abstract class CallingScope extends Scope {
|
||||
|
||||
private int intermediateVarCount = 0;
|
||||
private int intermediateLabelCount = 1;
|
||||
|
||||
CallingScope(String name, Scope parentScope) {
|
||||
super(name, parentScope);
|
||||
}
|
||||
|
||||
public String allocateIntermediateVariableName() {
|
||||
return "$" + intermediateVarCount++;
|
||||
}
|
||||
|
||||
public String allocateIntermediateLabelName() {
|
||||
return "@" + intermediateLabelCount++;
|
||||
}
|
||||
|
||||
public VariableIntermediate addVariableIntermediate() {
|
||||
String name = allocateIntermediateVariableName();
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
public Label addLabelIntermediate() {
|
||||
String name = allocateIntermediateLabelName();
|
||||
Label symbol = new Label(name, this, true);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -15,8 +15,6 @@ public abstract class Scope implements Symbol {
|
||||
|
||||
private String name;
|
||||
private HashMap<String, Symbol> symbols;
|
||||
private int intermediateVarCount = 0;
|
||||
private int intermediateLabelCount = 1;
|
||||
private Scope parentScope;
|
||||
|
||||
public Scope(String name, Scope parentScope) {
|
||||
@@ -97,13 +95,6 @@ public abstract class Scope implements Symbol {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableIntermediate addVariableIntermediate() {
|
||||
String name = allocateIntermediateVariableName();
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all versions of an unversioned variable
|
||||
*
|
||||
@@ -124,10 +115,6 @@ public abstract class Scope implements Symbol {
|
||||
return versions;
|
||||
}
|
||||
|
||||
public String allocateIntermediateVariableName() {
|
||||
return "$" + intermediateVarCount++;
|
||||
}
|
||||
|
||||
public Symbol getSymbol(SymbolRef symbolRef) {
|
||||
return getSymbol(symbolRef.getFullName());
|
||||
}
|
||||
@@ -155,6 +142,21 @@ public abstract class Scope implements Symbol {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract VariableIntermediate addVariableIntermediate();
|
||||
|
||||
public abstract Label addLabelIntermediate();
|
||||
|
||||
public abstract String allocateIntermediateLabelName();
|
||||
|
||||
public abstract String allocateIntermediateVariableName();
|
||||
|
||||
public BlockScope addBlockScope() {
|
||||
String name = allocateIntermediateLabelName();
|
||||
BlockScope scope = new BlockScope(name, this);
|
||||
add(scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public Variable getVariable(String name) {
|
||||
return (Variable) getSymbol(name);
|
||||
}
|
||||
@@ -239,19 +241,6 @@ public abstract class Scope implements Symbol {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label addLabelIntermediate() {
|
||||
String name = "@" + intermediateLabelCount++;
|
||||
Label symbol = new Label(name, this, true);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public BlockScope addBlockScope() {
|
||||
String name = "@" + intermediateLabelCount++;
|
||||
BlockScope scope = new BlockScope(name, this);
|
||||
add(scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
public Label getLabel(String name) {
|
||||
return (Label) getSymbol(name);
|
||||
@@ -356,36 +345,15 @@ public abstract class Scope implements Symbol {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(this == o) {
|
||||
return true;
|
||||
}
|
||||
if(o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this == o) return true;
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
Scope scope = (Scope) o;
|
||||
|
||||
if(intermediateVarCount != scope.intermediateVarCount) {
|
||||
return false;
|
||||
}
|
||||
if(intermediateLabelCount != scope.intermediateLabelCount) {
|
||||
return false;
|
||||
}
|
||||
if(!name.equals(scope.name)) {
|
||||
return false;
|
||||
}
|
||||
if(!symbols.equals(scope.symbols)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return Objects.equals(name, scope.name) &&
|
||||
Objects.equals(parentScope, scope.parentScope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + intermediateVarCount;
|
||||
result = 31 * result + intermediateLabelCount;
|
||||
return result;
|
||||
return Objects.hash(name, parentScope);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public abstract class SymbolVariable implements Symbol {
|
||||
/** Specifies that the variable must always live in memory to be available for any multi-threaded accees (eg. in interrupts). */
|
||||
private boolean declaredVolatile;
|
||||
|
||||
public SymbolVariable(String name, Scope scope, SymbolType type) {
|
||||
SymbolVariable(String name, Scope scope, SymbolType type) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.type = type;
|
||||
|
||||
@@ -66,10 +66,11 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
|
||||
// Start scopes until the new scope is the current scope
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
while(!currentScope.equals(newScope)) {
|
||||
currentScope = newScope.getParentScope(currentScope.getScopeDepth()+1);
|
||||
asm.startSegment(currentScope, null, block.getLabel().getFullName());
|
||||
asm.addScopeBegin(block.getLabel().getFullName().replace('@', 'b').replace(':', '_'));
|
||||
asm.startSegment(currentScope, null, blockLabel.getFullName());
|
||||
asm.addScopeBegin(currentScope.getLocalName().replace('@', 'b').replace(':', '_'));
|
||||
// Add all ZP labels for the scope
|
||||
addConstants(asm, currentScope);
|
||||
addZpLabels(asm, currentScope);
|
||||
@@ -86,27 +87,25 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
} else {
|
||||
// Generate label for block inside procedure
|
||||
asm.startSegment(currentScope, null, block.getLabel().getFullName());
|
||||
asm.addLabel(block.getLabel().getLocalName().replace('@', 'b').replace(':', '_'));
|
||||
asm.startSegment(currentScope, null, blockLabel.getFullName());
|
||||
asm.addLabel(blockLabel.getLocalName().replace('@', 'b').replace(':', '_'));
|
||||
}
|
||||
// Generate statements
|
||||
genStatements(asm, block);
|
||||
// Generate block exit
|
||||
ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
|
||||
if(defaultSuccessor != null) {
|
||||
LabelRef defaultSuccessorLabel = defaultSuccessor.getLabel();
|
||||
if(defaultSuccessor.hasPhiBlock()) {
|
||||
PhiTransitions.PhiTransition transition = getTransitions(defaultSuccessor).getTransition(block);
|
||||
if(!transition.isGenerated()) {
|
||||
genBlockPhiTransition(asm, block, defaultSuccessor, defaultSuccessor.getScope());
|
||||
String label = defaultSuccessor.getLabel().getLocalName().replace('@', 'b').replace(':', '_');
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, new AsmParameterLabel(defaultSuccessorLabel), false);
|
||||
} else {
|
||||
String label = (defaultSuccessor.getLabel().getLocalName() + "_from_" + block.getLabel().getLocalName()).replace('@', 'b').replace(':', '_');
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, new AsmParameterLabelTransition(blockLabel, defaultSuccessorLabel), false);
|
||||
}
|
||||
} else {
|
||||
String label = defaultSuccessor.getLabel().getLocalName().replace('@', 'b').replace(':', '_');
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, new AsmParameterLabel(defaultSuccessorLabel), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,7 +444,7 @@ public class Pass4CodeGeneration {
|
||||
genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
|
||||
}
|
||||
}
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, new AsmParameterProcedure(call.getProcedure()), false);
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
Procedure.InterruptType interruptType = null;
|
||||
ScopeRef scope = block.getScope();
|
||||
@@ -566,7 +565,7 @@ public class Pass4CodeGeneration {
|
||||
PhiTransitions.PhiTransition transition = transitions.getTransition(fromBlock);
|
||||
if(!transition.isGenerated() && toBlock.getLabel().equals(fromBlock.getConditionalSuccessor())) {
|
||||
genBlockPhiTransition(asm, fromBlock, toBlock, toBlock.getScope());
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, toBlock.getLabel().getLocalName().replace('@', 'b').replace(':', '_'), false);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, new AsmParameterLabel(toBlock.getLabel()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
// Find all labels immediately followed by a a jump
|
||||
String currentScope = "";
|
||||
String currentLabel = null;
|
||||
Map<String, String> immediateJumps = new LinkedHashMap<>();
|
||||
Map<String, AsmParameter> immediateJumps = new LinkedHashMap<>();
|
||||
for(AsmSegment segment : getAsmProgram().getSegments()) {
|
||||
for(AsmLine line : segment.getLines()) {
|
||||
if(line instanceof AsmScopeBegin) {
|
||||
@@ -61,7 +61,7 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
if(asmInstruction.getType().isJump()) {
|
||||
String immediateJmpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getParameter());
|
||||
AsmParameter immediateJmpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getParameter());
|
||||
if(immediateJmpTarget != null && !immediateJmpTarget.equals(asmInstruction.getParameter())) {
|
||||
getLog().append("Skipping double jump to " + immediateJmpTarget + " in " + asmInstruction.toString());
|
||||
asmInstruction.setParameter(immediateJmpTarget);
|
||||
|
||||
@@ -32,7 +32,7 @@ public class Pass5RedundantLabelElimination extends Pass5AsmOptimization {
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().isJump()) {
|
||||
String labelStr = instruction.getParameter();
|
||||
String labelStr = instruction.getParameter().getAsm();
|
||||
if(!labelStr.contains("!")) {
|
||||
// If redundant - Replace with the shortest
|
||||
for(RedundantLabels redundantLabels : redundantLabelSet) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
|
||||
|
||||
// Find relabels for all long labels
|
||||
// Scope->(Label->NewLabel)
|
||||
Map<String, Map<String, String>> relabels = new LinkedHashMap<>();
|
||||
Map<String, Map<String, AsmParameter>> relabels = new LinkedHashMap<>();
|
||||
for(AsmSegment asmSegment : getAsmProgram().getSegments()) {
|
||||
for(AsmLine asmLine : asmSegment.getLines()) {
|
||||
if(asmLine instanceof AsmScopeBegin) {
|
||||
@@ -58,7 +58,7 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
|
||||
if(asmLabel.getLabel().contains("_from_")) {
|
||||
// Found a long label
|
||||
Set<String> scopeLabels = allLabels.get(currentScope);
|
||||
Map<String, String> scopeRelabels = relabels.get(currentScope);
|
||||
Map<String, AsmParameter> scopeRelabels = relabels.get(currentScope);
|
||||
if(scopeRelabels == null) {
|
||||
scopeRelabels = new LinkedHashMap<>();
|
||||
relabels.put(currentScope, scopeRelabels);
|
||||
@@ -86,9 +86,9 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
|
||||
currentScope = "";
|
||||
} else if(asmLine instanceof AsmLabel) {
|
||||
AsmLabel asmLabel = (AsmLabel) asmLine;
|
||||
Map<String, String> scopeRelabels = relabels.get(currentScope);
|
||||
Map<String, AsmParameter> scopeRelabels = relabels.get(currentScope);
|
||||
if(scopeRelabels != null) {
|
||||
String newLabel = scopeRelabels.get(asmLabel.getLabel());
|
||||
AsmParameter newLabel = scopeRelabels.get(asmLabel.getLabel());
|
||||
if(newLabel != null) {
|
||||
asmLabel.setLabel(newLabel);
|
||||
}
|
||||
@@ -96,10 +96,10 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
|
||||
} else if(asmLine instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
|
||||
if(asmInstruction.getType().isJump()) {
|
||||
String parameter = asmInstruction.getParameter();
|
||||
Map<String, String> scopeRelabels = relabels.get(currentScope);
|
||||
AsmParameter parameter = asmInstruction.getParameter();
|
||||
Map<String, AsmParameter> scopeRelabels = relabels.get(currentScope);
|
||||
if(scopeRelabels != null) {
|
||||
String newLabel = scopeRelabels.get(parameter);
|
||||
AsmParameter newLabel = scopeRelabels.get(parameter);
|
||||
if(newLabel != null) {
|
||||
asmInstruction.setParameter(newLabel);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,11 @@ public class TestPrograms {
|
||||
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalScope() throws IOException, URISyntaxException {
|
||||
compileAndCompare("local-scope");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitwiseNot() throws IOException, URISyntaxException {
|
||||
compileAndCompare("bitwise-not");
|
||||
@@ -54,11 +59,6 @@ public class TestPrograms {
|
||||
// compileAndCompare("unroll-call");
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testLocalScope() throws IOException, URISyntaxException {
|
||||
compileAndCompare("local-scope");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnrollInfinite() throws IOException, URISyntaxException {
|
||||
assertError("unroll-infinite", "Loop cannot be unrolled.");
|
||||
|
||||
Reference in new issue
Block a user