1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

improved code using ASM fragment instance spec builder.

This commit is contained in:
jespergravgaard 2021-12-24 09:48:11 +01:00
parent b3885abe9c
commit 0152ecd0eb
3 changed files with 43 additions and 74 deletions

View File

@ -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) {

View File

@ -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.
*

View File

@ -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();