mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-21 14:30:21 +00:00
improved code using ASM fragment instance spec builder.
This commit is contained in:
parent
b3885abe9c
commit
0152ecd0eb
@ -42,28 +42,13 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
private int nextMemIdx = 1;
|
||||
private int nextConstIdx = 1;
|
||||
private int nextLabelIdx = 1;
|
||||
|
||||
/**
|
||||
* Create a fragment instance spec factory for an interrupt routine (entry or exit)
|
||||
*
|
||||
* @param interruptTypeComplete The interrupt routine handler name - including "isr_" and "_entry"/_exit"
|
||||
* @param program The program
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder interrupt(String interruptTypeComplete, Program program) {
|
||||
Map<String, Value> bindings = new HashMap<>();
|
||||
String signature = interruptTypeComplete;
|
||||
ScopeRef codeScope = program.getScope().getRef();
|
||||
final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a fragment instance spec factory for an indirect call
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder call(StatementCallExecute call, int indirectCallId, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(call, indirectCallId, program);
|
||||
public static AsmFragmentInstanceSpec call(StatementCallExecute call, int indirectCallId, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(call, indirectCallId, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(StatementCallExecute call, int indirectCallId, Program program) {
|
||||
@ -85,12 +70,12 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
* @param program The program
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder interruptEntry(String interruptType, Program program) {
|
||||
public static AsmFragmentInstanceSpec interruptEntry(String interruptType, Program program) {
|
||||
Map<String, Value> bindings = new HashMap<>();
|
||||
String signature = "isr_" + interruptType + "_entry";
|
||||
ScopeRef codeScope = program.getScope().getRef();
|
||||
final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec);
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,12 +85,12 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
* @param program The program
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder interruptExit(String interruptType, Program program) {
|
||||
public static AsmFragmentInstanceSpec interruptExit(String interruptType, Program program) {
|
||||
Map<String, Value> bindings = new HashMap<>();
|
||||
String signature = "isr_" + interruptType + "_exit";
|
||||
ScopeRef codeScope = program.getScope().getRef();
|
||||
final AsmFragmentInstanceSpec fragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec);
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(Program program, Map<String, Value> bindings, AsmFragmentInstanceSpec asmFragmentInstanceSpec) {
|
||||
@ -115,8 +100,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
}
|
||||
|
||||
|
||||
public static AsmFragmentInstanceSpecBuilder conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(conditionalJump, block, program);
|
||||
public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(conditionalJump, block, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(
|
||||
@ -130,8 +115,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
}
|
||||
|
||||
public static AsmFragmentInstanceSpecBuilder exprSideEffect(StatementExprSideEffect exprSideEffect, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(exprSideEffect, program);
|
||||
public static AsmFragmentInstanceSpec exprSideEffect(StatementExprSideEffect exprSideEffect, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(exprSideEffect, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(StatementExprSideEffect exprSideEffect, Program program) {
|
||||
@ -142,8 +127,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
}
|
||||
|
||||
public static AsmFragmentInstanceSpecBuilder assignment(StatementAssignment assignment, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(assignment, program);
|
||||
public static AsmFragmentInstanceSpec assignment(StatementAssignment assignment, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(assignment, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,8 +138,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
* @param program The program
|
||||
* @return The ASM fragment instance
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder makelong4(StatementCall call, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(call, program);
|
||||
public static AsmFragmentInstanceSpec makelong4(StatementCall call, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(call, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(StatementCall make4long, Program program) {
|
||||
@ -190,8 +175,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||
}
|
||||
|
||||
public static AsmFragmentInstanceSpecBuilder assignment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
||||
return new AsmFragmentInstanceSpecBuilder(lValue, rValue, program, codeScopeRef);
|
||||
public static AsmFragmentInstanceSpec assignment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
||||
return new AsmFragmentInstanceSpecBuilder(lValue, rValue, program, codeScopeRef).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
|
||||
@ -201,8 +186,8 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature, bindings, codeScopeRef);
|
||||
}
|
||||
|
||||
public static AsmFragmentInstanceSpecBuilder assignmentAlu(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(assignment, assignmentAlu, program);
|
||||
public static AsmFragmentInstanceSpec assignmentAlu(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(assignment, assignmentAlu, program).getAsmFragmentInstanceSpec();
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
||||
|
@ -848,9 +848,7 @@ public class Pass4CodeGeneration {
|
||||
throw new AsmFragmentInstance.AluNotApplicableException();
|
||||
}
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.assignmentAlu(assignment, assignmentAlu, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.assignmentAlu(assignment, assignmentAlu, program));
|
||||
aluState.clear();
|
||||
return;
|
||||
}
|
||||
@ -873,23 +871,17 @@ public class Pass4CodeGeneration {
|
||||
if(assignment.getOperator() == null && assignment.getrValue1() == null && isRegisterCopy(lValue, assignment.getrValue2())) {
|
||||
//asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
|
||||
} else {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.assignment(assignment, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.assignment(assignment, program));
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.conditionalJump((StatementConditionalJump) statement, block, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.conditionalJump((StatementConditionalJump) statement, block, program));
|
||||
} else if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
Procedure procedure = getScope().getProcedure(call.getProcedure());
|
||||
if(procedure.isDeclaredIntrinsic()) {
|
||||
if(Pass1ByteXIntrinsicRewrite.INTRINSIC_MAKELONG4.equals(procedure.getFullName())) {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.makelong4(call, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.makelong4(call, program));
|
||||
} else {
|
||||
throw new CompileError("Intrinsic procedure not supported " + procedure.toString(program));
|
||||
}
|
||||
@ -913,16 +905,12 @@ public class Pass4CodeGeneration {
|
||||
StatementCallExecute call = (StatementCallExecute) statement;
|
||||
RValue procedureRVal = call.getProcedureRVal();
|
||||
// Generate ASM for a call
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program));
|
||||
if(!(procedureRVal instanceof ProcedureRef)) {
|
||||
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
||||
}
|
||||
} else if(statement instanceof StatementExprSideEffect) {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.exprSideEffect((StatementExprSideEffect) statement, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.exprSideEffect((StatementExprSideEffect) statement, program));
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
Procedure procedure = null;
|
||||
ScopeRef scope = block.getScope();
|
||||
@ -972,6 +960,7 @@ public class Pass4CodeGeneration {
|
||||
* @param fragmentInstanceSpec The ASM fragment instance specification
|
||||
*/
|
||||
private void generateAsm(AsmProgram asm, AsmFragmentInstanceSpec fragmentInstanceSpec) {
|
||||
ensureEncoding(asm, fragmentInstanceSpec);
|
||||
String initialSignature = fragmentInstanceSpec.getSignature();
|
||||
AsmFragmentInstance fragmentInstance = null;
|
||||
StringBuilder fragmentVariationsTried = new StringBuilder();
|
||||
@ -1006,20 +995,20 @@ public class Pass4CodeGeneration {
|
||||
*/
|
||||
private void generateInterruptEntry(AsmProgram asm, Procedure procedure) {
|
||||
final String interruptType = procedure.getInterruptType().toLowerCase();
|
||||
AsmFragmentInstanceSpecBuilder entryFragment;
|
||||
AsmFragmentInstanceSpec entryFragment;
|
||||
String entryName;
|
||||
if(interruptType.contains("clobber")) {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType.replace("clobber", "all"), program);
|
||||
entryName = entryFragment.getAsmFragmentInstanceSpec().getSignature().replace("all", "clobber");
|
||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
||||
} else {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType, program);
|
||||
entryName = entryFragment.getAsmFragmentInstanceSpec().getSignature();
|
||||
entryName = entryFragment.getSignature();
|
||||
}
|
||||
try {
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||
generateAsm(asm, entryFragment.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, entryFragment);
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
throw new CompileError("Interrupt type not supported " + procedure.getInterruptType() + " int " + procedure.toString() + "\n" + e.getMessage());
|
||||
throw new CompileError("Interrupt type not supported " + procedure.getInterruptType() + " int " + procedure + "\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,20 +1020,20 @@ public class Pass4CodeGeneration {
|
||||
*/
|
||||
private void generateInterruptExit(AsmProgram asm, Procedure procedure) {
|
||||
final String interruptType = procedure.getInterruptType().toLowerCase();
|
||||
AsmFragmentInstanceSpecBuilder entryFragment;
|
||||
AsmFragmentInstanceSpec entryFragment;
|
||||
String entryName;
|
||||
if(interruptType.contains("clobber")) {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType.replace("clobber", "all"), program);
|
||||
entryName = entryFragment.getAsmFragmentInstanceSpec().getSignature().replace("all", "clobber");
|
||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
||||
} else {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType, program);
|
||||
entryName = entryFragment.getAsmFragmentInstanceSpec().getSignature();
|
||||
entryName = entryFragment.getSignature();
|
||||
}
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||
try {
|
||||
generateAsm(asm, entryFragment.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, entryFragment);
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
throw new CompileError("Interrupt type not supported " + procedure.getInterruptType() + " int " + procedure.toString() + "\n" + e.getMessage());
|
||||
throw new CompileError("Interrupt type not supported " + procedure.getInterruptType() + " int " + procedure + "\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1121,9 +1110,7 @@ public class Pass4CodeGeneration {
|
||||
if(isRegisterCopy(lValue, rValue)) {
|
||||
asm.getCurrentChunk().setFragment("register_copy");
|
||||
} else {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.assignment(lValue, rValue, program, scope);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
generateAsm(asm, AsmFragmentInstanceSpecBuilder.assignment(lValue, rValue, program, scope));
|
||||
}
|
||||
}
|
||||
transitionSetGenerated(transition);
|
||||
@ -1132,14 +1119,13 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensure that the current encoding in the ASM matches any encoding in the data to be emitted
|
||||
*
|
||||
* @param asm The ASM program (where any .encoding directive will be emitted)
|
||||
* @param asmFragmentInstance The ASM fragment to be emitted
|
||||
*/
|
||||
private static void ensureEncoding(AsmProgram asm, AsmFragmentInstanceSpecBuilder asmFragmentInstance) {
|
||||
private static void ensureEncoding(AsmProgram asm, AsmFragmentInstanceSpec asmFragmentInstance) {
|
||||
asm.ensureEncoding(getEncoding(asmFragmentInstance));
|
||||
}
|
||||
|
||||
@ -1175,7 +1161,7 @@ public class Pass4CodeGeneration {
|
||||
* @param asmFragmentInstance The asm fragment instance to examine
|
||||
* @return Any encoding found inside the constant
|
||||
*/
|
||||
private static Set<StringEncoding> getEncoding(AsmFragmentInstanceSpecBuilder asmFragmentInstance) {
|
||||
private static Set<StringEncoding> getEncoding(AsmFragmentInstanceSpec asmFragmentInstance) {
|
||||
LinkedHashSet<StringEncoding> encodings = new LinkedHashSet<>();
|
||||
Map<String, Value> bindings = asmFragmentInstance.getBindings();
|
||||
for(Value boundValue : bindings.values()) {
|
||||
@ -1184,7 +1170,6 @@ public class Pass4CodeGeneration {
|
||||
return encodings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get phi transitions for a specific to-block.
|
||||
*
|
||||
|
@ -1,10 +1,9 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentInstance;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpecBuilder;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.asm.AsmChunk;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.CallGraph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
@ -119,7 +118,7 @@ public class Pass4InterruptClobberFix extends Pass2Base {
|
||||
* Prune the interrupt entry/exit fragment removing code handling non-clobbered registers
|
||||
*
|
||||
* @param interruptAsmChunk The AsmFragment representing an interrupt entry/exit
|
||||
* @param nonClobberedRegisters The non-clobbered registers
|
||||
* @param clobberedRegisters The clobbered registers
|
||||
*/
|
||||
private void pruneFragmentClobber(AsmChunk interruptAsmChunk, String clobberedRegisters) {
|
||||
final ListIterator<AsmLine> asmLineListIterator = interruptAsmChunk.getLines().listIterator();
|
||||
|
Loading…
Reference in New Issue
Block a user