mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-12 11:31:11 +00:00
#742 Working on typed ASM fragment signature in synthesis.
This commit is contained in:
parent
9652931592
commit
7c77be79bd
@ -2,6 +2,7 @@ package dk.camelot64.kickc;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
@ -275,7 +276,8 @@ public class KickC implements Callable<Integer> {
|
|||||||
try {
|
try {
|
||||||
final AsmFragmentTemplateMasterSynthesizer masterSynthesizer = compiler.getAsmFragmentMasterSynthesizer();
|
final AsmFragmentTemplateMasterSynthesizer masterSynthesizer = compiler.getAsmFragmentMasterSynthesizer();
|
||||||
final AsmFragmentTemplateSynthesizer cpuSynthesizer = masterSynthesizer.getSynthesizer(program.getTargetCpu());
|
final AsmFragmentTemplateSynthesizer cpuSynthesizer = masterSynthesizer.getSynthesizer(program.getTargetCpu());
|
||||||
Collection<AsmFragmentSynthesisResult> fragmentTemplates = cpuSynthesizer.getBestTemplates(fragment, compiler.getLog());
|
final AsmFragmentSignature signature = AsmFragmentSignature.parse(fragment);
|
||||||
|
Collection<AsmFragmentSynthesisResult> fragmentTemplates = cpuSynthesizer.getBestTemplates(signature, compiler.getLog());
|
||||||
for(AsmFragmentSynthesisResult fragmentTemplate : fragmentTemplates) {
|
for(AsmFragmentSynthesisResult fragmentTemplate : fragmentTemplates) {
|
||||||
AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, "");
|
AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, "");
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ public class AsmFragmentCodeGenerator {
|
|||||||
*/
|
*/
|
||||||
public static void generateAsm(AsmProgram asm, AsmFragmentInstanceSpec fragmentInstanceSpec, Program program) {
|
public static void generateAsm(AsmProgram asm, AsmFragmentInstanceSpec fragmentInstanceSpec, Program program) {
|
||||||
AsmEncodingHelper.ensureEncoding(asm, fragmentInstanceSpec);
|
AsmEncodingHelper.ensureEncoding(asm, fragmentInstanceSpec);
|
||||||
String initialSignature = fragmentInstanceSpec.getSignature();
|
AsmFragmentSignature initialSignature = fragmentInstanceSpec.getSignature();
|
||||||
AsmFragmentInstance fragmentInstance = null;
|
AsmFragmentInstance fragmentInstance = null;
|
||||||
StringBuilder fragmentVariationsTried = new StringBuilder();
|
StringBuilder fragmentVariationsTried = new StringBuilder();
|
||||||
while(fragmentInstance == null) {
|
while(fragmentInstance == null) {
|
||||||
@ -24,7 +25,7 @@ public class AsmFragmentCodeGenerator {
|
|||||||
fragmentInstance = cpuSynthesizer.getFragmentInstance(fragmentInstanceSpec, program.getLog());
|
fragmentInstance = cpuSynthesizer.getFragmentInstance(fragmentInstanceSpec, program.getLog());
|
||||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||||
// Unknown fragment - keep looking through alternative ASM fragment instance specs until we have tried them all
|
// Unknown fragment - keep looking through alternative ASM fragment instance specs until we have tried them all
|
||||||
String signature = fragmentInstanceSpec.getSignature();
|
AsmFragmentSignature signature = fragmentInstanceSpec.getSignature();
|
||||||
fragmentVariationsTried.append(signature).append(" ");
|
fragmentVariationsTried.append(signature).append(" ");
|
||||||
if(fragmentInstanceSpec.hasNextVariation()) {
|
if(fragmentInstanceSpec.hasNextVariation()) {
|
||||||
fragmentInstanceSpec.nextVariation();
|
fragmentInstanceSpec.nextVariation();
|
||||||
@ -37,7 +38,7 @@ public class AsmFragmentCodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asm.getCurrentChunk().setFragment(fragmentInstance.getFragmentName());
|
asm.getCurrentChunk().setFragment(fragmentInstance.getFragmentSignature().getName());
|
||||||
fragmentInstance.generate(asm);
|
fragmentInstance.generate(asm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
|||||||
import dk.camelot64.cpufamily6502.CpuOpcode;
|
import dk.camelot64.cpufamily6502.CpuOpcode;
|
||||||
import dk.camelot64.kickc.NumberParser;
|
import dk.camelot64.kickc.NumberParser;
|
||||||
import dk.camelot64.kickc.asm.*;
|
import dk.camelot64.kickc.asm.*;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.model.*;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.InternalError;
|
import dk.camelot64.kickc.model.InternalError;
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.symbols.Label;
|
||||||
@ -25,7 +26,7 @@ public class AsmFragmentInstance {
|
|||||||
private final Program program;
|
private final Program program;
|
||||||
|
|
||||||
/** The name of the fragment used in error messages. */
|
/** The name of the fragment used in error messages. */
|
||||||
private final String name;
|
private final AsmFragmentSignature signature;
|
||||||
|
|
||||||
/** The fragment template for the ASM code. */
|
/** The fragment template for the ASM code. */
|
||||||
private final AsmFragmentTemplate fragmentTemplate;
|
private final AsmFragmentTemplate fragmentTemplate;
|
||||||
@ -38,12 +39,12 @@ public class AsmFragmentInstance {
|
|||||||
|
|
||||||
public AsmFragmentInstance(
|
public AsmFragmentInstance(
|
||||||
Program program,
|
Program program,
|
||||||
String name,
|
AsmFragmentSignature signature,
|
||||||
ScopeRef codeScopeRef,
|
ScopeRef codeScopeRef,
|
||||||
AsmFragmentTemplate fragmentTemplate,
|
AsmFragmentTemplate fragmentTemplate,
|
||||||
Map<String, Value> bindings) {
|
Map<String, Value> bindings) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.name = name;
|
this.signature = signature;
|
||||||
this.fragmentTemplate = fragmentTemplate;
|
this.fragmentTemplate = fragmentTemplate;
|
||||||
this.bindings = bindings;
|
this.bindings = bindings;
|
||||||
this.codeScopeRef = codeScopeRef;
|
this.codeScopeRef = codeScopeRef;
|
||||||
@ -75,7 +76,7 @@ public class AsmFragmentInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(boundValue == null) {
|
if(boundValue == null) {
|
||||||
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name);
|
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.signature);
|
||||||
}
|
}
|
||||||
if(boundValue instanceof Variable && ((Variable) boundValue).isVariable()) {
|
if(boundValue instanceof Variable && ((Variable) boundValue).isVariable()) {
|
||||||
Variable boundVar = (Variable) boundValue;
|
Variable boundVar = (Variable) boundValue;
|
||||||
@ -151,8 +152,8 @@ public class AsmFragmentInstance {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFragmentName() {
|
public AsmFragmentSignature getFragmentSignature() {
|
||||||
return name;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,7 +162,7 @@ public class AsmFragmentInstance {
|
|||||||
* @param asm The assembler sequence to generate into.
|
* @param asm The assembler sequence to generate into.
|
||||||
*/
|
*/
|
||||||
public void generate(AsmProgram asm) {
|
public void generate(AsmProgram asm) {
|
||||||
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(name, this, asm);
|
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature.getName(), this, asm);
|
||||||
asmSequenceGenerator.generate(fragmentTemplate.getBodyAsm());
|
asmSequenceGenerator.generate(fragmentTemplate.getBodyAsm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class AsmFragmentInstanceSpec {
|
|||||||
/**
|
/**
|
||||||
* The string signature/name of the fragment template.
|
* The string signature/name of the fragment template.
|
||||||
*/
|
*/
|
||||||
private String signature;
|
private AsmFragmentSignature signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binding of named values in the fragment to values (constants, variables, ...) .
|
* Binding of named values in the fragment to values (constants, variables, ...) .
|
||||||
@ -46,13 +46,13 @@ public class AsmFragmentInstanceSpec {
|
|||||||
*/
|
*/
|
||||||
public AsmFragmentInstanceSpec(Program program, AsmFragmentSignature signature, AsmFragmentBindings bindings, ScopeRef codeScopeRef) {
|
public AsmFragmentInstanceSpec(Program program, AsmFragmentSignature signature, AsmFragmentBindings bindings, ScopeRef codeScopeRef) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.signature = signature.getName();
|
this.signature = signature;
|
||||||
this.bindings = bindings.variables;
|
this.bindings = bindings.variables;
|
||||||
this.codeScopeRef = codeScopeRef;
|
this.codeScopeRef = codeScopeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getSignature() {
|
public AsmFragmentSignature getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +148,6 @@ public class AsmFragmentInstanceSpec {
|
|||||||
return potentialTypes;
|
return potentialTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the ASM fragment instance specification to the next available variation.
|
* Updates the ASM fragment instance specification to the next available variation.
|
||||||
* If no more variations exist the ASM fragment instance specification will become unusable.
|
* If no more variations exist the ASM fragment instance specification will become unusable.
|
||||||
@ -164,11 +163,11 @@ public class AsmFragmentInstanceSpec {
|
|||||||
bindings.remove(variationCurrentName);
|
bindings.remove(variationCurrentName);
|
||||||
bindings.put(variationNextName, constValue);
|
bindings.put(variationNextName, constValue);
|
||||||
// Update signature
|
// Update signature
|
||||||
this.signature = signature.replace(variationCurrentName, variationNextName);
|
this.signature = AsmFragmentSignature.parse(signature.getName().replace(variationCurrentName, variationNextName));
|
||||||
variationCurrentName = variationNextName;
|
variationCurrentName = variationNextName;
|
||||||
variationCurrentValue = nextVariationValue;
|
variationCurrentValue = nextVariationValue;
|
||||||
} else {
|
} else {
|
||||||
this.signature = "no-more-variations";
|
this.signature = new AsmFragmentSignature.Singleton("NO_MORE_VARIATIONS");
|
||||||
this.bindings = new LinkedHashMap<>();
|
this.bindings = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package dk.camelot64.kickc.fragment;
|
|||||||
|
|
||||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignatureExpr;
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.Registers;
|
import dk.camelot64.kickc.model.Registers;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
@ -27,7 +29,7 @@ import java.util.Objects;
|
|||||||
public class AsmFragmentTemplate {
|
public class AsmFragmentTemplate {
|
||||||
|
|
||||||
/** The fragment template signature name. */
|
/** The fragment template signature name. */
|
||||||
private final String signature;
|
private final AsmFragmentSignature signature;
|
||||||
/** The target CPU. */
|
/** The target CPU. */
|
||||||
private final TargetCpu targetCpu;
|
private final TargetCpu targetCpu;
|
||||||
/** The fragment template body */
|
/** The fragment template body */
|
||||||
@ -40,7 +42,7 @@ public class AsmFragmentTemplate {
|
|||||||
/** The cycles consumed by the ASM of the fragment. Initially null. Non-null after the template is used to generate ASM code.*/
|
/** The cycles consumed by the ASM of the fragment. Initially null. Non-null after the template is used to generate ASM code.*/
|
||||||
private Double cycles;
|
private Double cycles;
|
||||||
|
|
||||||
public AsmFragmentTemplate(String signature, String body, TargetCpu targetCpu) {
|
public AsmFragmentTemplate(AsmFragmentSignature signature, String body, TargetCpu targetCpu) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.targetCpu = targetCpu;
|
this.targetCpu = targetCpu;
|
||||||
@ -52,7 +54,7 @@ public class AsmFragmentTemplate {
|
|||||||
* @param bodyLines Parsed ASM body
|
* @param bodyLines Parsed ASM body
|
||||||
*/
|
*/
|
||||||
public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines, TargetCpu targetCpu) {
|
public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines, TargetCpu targetCpu) {
|
||||||
this.signature = "--inline--";
|
this.signature = new AsmFragmentSignature.Singleton("INLINE");
|
||||||
this.bodyAsm = bodyLines;
|
this.bodyAsm = bodyLines;
|
||||||
this.targetCpu = targetCpu;
|
this.targetCpu = targetCpu;
|
||||||
}
|
}
|
||||||
@ -89,6 +91,8 @@ public class AsmFragmentTemplate {
|
|||||||
* Initialize the fields that require parsing the ASM (bodyAsm, clobber, cycles).
|
* Initialize the fields that require parsing the ASM (bodyAsm, clobber, cycles).
|
||||||
*/
|
*/
|
||||||
private void initAsm() {
|
private void initAsm() {
|
||||||
|
String signatureName = signature.getName();
|
||||||
|
|
||||||
// Parse the body ASM
|
// Parse the body ASM
|
||||||
this.bodyAsm = AsmParser.parseAsm(this.body, new StatementSource(signature + ".asm", 1, 1, this.body, -1, -1));
|
this.bodyAsm = AsmParser.parseAsm(this.body, new StatementSource(signature + ".asm", 1, 1, this.body, -1, -1));
|
||||||
// Generate a dummy instance to find clobber & cycles
|
// Generate a dummy instance to find clobber & cycles
|
||||||
@ -108,12 +112,12 @@ public class AsmFragmentTemplate {
|
|||||||
v4.setAllocation(new Registers.RegisterZpMem(8, 1));
|
v4.setAllocation(new Registers.RegisterZpMem(8, 1));
|
||||||
v5.setAllocation(new Registers.RegisterZpMem(9, 1));
|
v5.setAllocation(new Registers.RegisterZpMem(9, 1));
|
||||||
v6.setAllocation(new Registers.RegisterZpMem(10, 1));
|
v6.setAllocation(new Registers.RegisterZpMem(10, 1));
|
||||||
if(signature.contains("z1")) bindings.put("z1", v1);
|
if(signatureName.contains("z1")) bindings.put("z1", v1);
|
||||||
if(signature.contains("z2")) bindings.put("z2", v2);
|
if(signatureName.contains("z2")) bindings.put("z2", v2);
|
||||||
if(signature.contains("z3")) bindings.put("z3", v3);
|
if(signatureName.contains("z3")) bindings.put("z3", v3);
|
||||||
if(signature.contains("z4")) bindings.put("z4", v4);
|
if(signatureName.contains("z4")) bindings.put("z4", v4);
|
||||||
if(signature.contains("z5")) bindings.put("z5", v5);
|
if(signatureName.contains("z5")) bindings.put("z5", v5);
|
||||||
if(signature.contains("z6")) bindings.put("z6", v6);
|
if(signatureName.contains("z6")) bindings.put("z6", v6);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Variable v1 = createLoadStore("m1", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
|
Variable v1 = createLoadStore("m1", SymbolType.BYTE, scope, Variable.MemoryArea.MAIN_MEMORY, null);
|
||||||
@ -128,25 +132,25 @@ public class AsmFragmentTemplate {
|
|||||||
v4.setAllocation(new Registers.RegisterMainMem(v4.getVariableRef(), 1, null, false));
|
v4.setAllocation(new Registers.RegisterMainMem(v4.getVariableRef(), 1, null, false));
|
||||||
v5.setAllocation(new Registers.RegisterMainMem(v5.getVariableRef(), 1, null, false));
|
v5.setAllocation(new Registers.RegisterMainMem(v5.getVariableRef(), 1, null, false));
|
||||||
v6.setAllocation(new Registers.RegisterMainMem(v6.getVariableRef(), 1, null, false));
|
v6.setAllocation(new Registers.RegisterMainMem(v6.getVariableRef(), 1, null, false));
|
||||||
if(signature.contains("m1")) bindings.put("m1", v1);
|
if(signatureName.contains("m1")) bindings.put("m1", v1);
|
||||||
if(signature.contains("m2")) bindings.put("m2", v2);
|
if(signatureName.contains("m2")) bindings.put("m2", v2);
|
||||||
if(signature.contains("m3")) bindings.put("m3", v3);
|
if(signatureName.contains("m3")) bindings.put("m3", v3);
|
||||||
if(signature.contains("m4")) bindings.put("m4", v4);
|
if(signatureName.contains("m4")) bindings.put("m4", v4);
|
||||||
if(signature.contains("m5")) bindings.put("m5", v5);
|
if(signatureName.contains("m5")) bindings.put("m5", v5);
|
||||||
if(signature.contains("m6")) bindings.put("m6", v6);
|
if(signatureName.contains("m6")) bindings.put("m6", v6);
|
||||||
}
|
}
|
||||||
if(signature.contains("c1")) bindings.put("c1", new ConstantInteger(310L));
|
if(signatureName.contains("c1")) bindings.put("c1", new ConstantInteger(310L));
|
||||||
if(signature.contains("c2")) bindings.put("c2", new ConstantInteger(320L));
|
if(signatureName.contains("c2")) bindings.put("c2", new ConstantInteger(320L));
|
||||||
if(signature.contains("c3")) bindings.put("c3", new ConstantInteger(330L));
|
if(signatureName.contains("c3")) bindings.put("c3", new ConstantInteger(330L));
|
||||||
if(signature.contains("c4")) bindings.put("c4", new ConstantInteger(340L));
|
if(signatureName.contains("c4")) bindings.put("c4", new ConstantInteger(340L));
|
||||||
if(signature.contains("c5")) bindings.put("c5", new ConstantInteger(350L));
|
if(signatureName.contains("c5")) bindings.put("c5", new ConstantInteger(350L));
|
||||||
if(signature.contains("c6")) bindings.put("c6", new ConstantInteger(360L));
|
if(signatureName.contains("c6")) bindings.put("c6", new ConstantInteger(360L));
|
||||||
if(signature.contains("la1")) bindings.put("la1", new Label("@1", scope, true));
|
if(signatureName.contains("la1")) bindings.put("la1", new Label("@1", scope, true));
|
||||||
if(signature.startsWith("call_")) bindings.put("la1", new Label("@1", scope, true));
|
if(signatureName.startsWith("call_")) bindings.put("la1", new Label("@1", scope, true));
|
||||||
AsmFragmentInstance fragmentInstance =
|
AsmFragmentInstance fragmentInstance =
|
||||||
new AsmFragmentInstance(new Program(), signature, ScopeRef.ROOT, this, bindings);
|
new AsmFragmentInstance(new Program(), signature, ScopeRef.ROOT, this, bindings);
|
||||||
AsmProgram asm = new AsmProgram(targetCpu);
|
AsmProgram asm = new AsmProgram(targetCpu);
|
||||||
asm.startChunk(ScopeRef.ROOT, null, signature);
|
asm.startChunk(ScopeRef.ROOT, null, signature.getName());
|
||||||
fragmentInstance.generate(asm);
|
fragmentInstance.generate(asm);
|
||||||
CpuClobber cpuClobber = asm.getClobber();
|
CpuClobber cpuClobber = asm.getClobber();
|
||||||
this.clobber = new AsmFragmentClobber(cpuClobber);
|
this.clobber = new AsmFragmentClobber(cpuClobber);
|
||||||
@ -154,7 +158,7 @@ public class AsmFragmentTemplate {
|
|||||||
this.cycles = asm.getCycles();
|
this.cycles = asm.getCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignature() {
|
public AsmFragmentSignature getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.model.InternalError;
|
import dk.camelot64.kickc.model.InternalError;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
@ -29,7 +30,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
private TargetCpu cpu;
|
private TargetCpu cpu;
|
||||||
|
|
||||||
/** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. Maps to NO_SYNTHESIS if synthesis was unsuccessful. */
|
/** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. Maps to NO_SYNTHESIS if synthesis was unsuccessful. */
|
||||||
private Map<String, AsmFragmentTemplate> cache;
|
private Map<AsmFragmentSignature, AsmFragmentTemplate> cache;
|
||||||
|
|
||||||
/** Detects any modification of the cache. */
|
/** Detects any modification of the cache. */
|
||||||
private boolean modified;
|
private boolean modified;
|
||||||
@ -39,7 +40,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
*
|
*
|
||||||
* @param cpu The target CPU
|
* @param cpu The target CPU
|
||||||
*/
|
*/
|
||||||
private AsmFragmentTemplateCache(Path cacheFolder, TargetCpu cpu, AsmFragmentSystemHash fragmentSystemHash, Map<String, AsmFragmentTemplate> cache) {
|
private AsmFragmentTemplateCache(Path cacheFolder, TargetCpu cpu, AsmFragmentSystemHash fragmentSystemHash, Map<AsmFragmentSignature, AsmFragmentTemplate> cache) {
|
||||||
this.cacheFolder = cacheFolder;
|
this.cacheFolder = cacheFolder;
|
||||||
this.cpu = cpu;
|
this.cpu = cpu;
|
||||||
this.fragmentSystemHash = fragmentSystemHash;
|
this.fragmentSystemHash = fragmentSystemHash;
|
||||||
@ -48,7 +49,8 @@ public class AsmFragmentTemplateCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
||||||
public static AsmFragmentTemplate NO_SYNTHESIS = new AsmFragmentTemplate("NO_SYNTHESIS", "NO_SYNTHESIS", null);
|
public static AsmFragmentTemplate NO_SYNTHESIS =
|
||||||
|
new AsmFragmentTemplate(new AsmFragmentSignature.Singleton("NO_SYNTHESIS"), "NO_SYNTHESIS", null);
|
||||||
|
|
||||||
/** Prefix for the fragment hash file header. */
|
/** Prefix for the fragment hash file header. */
|
||||||
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
|
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
|
||||||
@ -62,7 +64,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
* @param signature The signature
|
* @param signature The signature
|
||||||
* @return The cached ASM fragment template. null if not in the cache. NO_SYNTHESIS if synthesis was unsuccessful.
|
* @return The cached ASM fragment template. null if not in the cache. NO_SYNTHESIS if synthesis was unsuccessful.
|
||||||
*/
|
*/
|
||||||
public AsmFragmentTemplate get(String signature) {
|
public AsmFragmentTemplate get(AsmFragmentSignature signature) {
|
||||||
return cache.get(signature);
|
return cache.get(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
* @param signature The signature
|
* @param signature The signature
|
||||||
* @param asmFragmentTemplate The ASM fragment template. NO_SYNTHESIS if synthesis was unsuccessful.
|
* @param asmFragmentTemplate The ASM fragment template. NO_SYNTHESIS if synthesis was unsuccessful.
|
||||||
*/
|
*/
|
||||||
public void put(String signature, AsmFragmentTemplate asmFragmentTemplate) {
|
public void put(AsmFragmentSignature signature, AsmFragmentTemplate asmFragmentTemplate) {
|
||||||
this.cache.put(signature, asmFragmentTemplate);
|
this.cache.put(signature, asmFragmentTemplate);
|
||||||
this.modified = true;
|
this.modified = true;
|
||||||
}
|
}
|
||||||
@ -101,7 +103,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
* @param cpu The CPU to make a cache for
|
* @param cpu The CPU to make a cache for
|
||||||
* @return The new empty cache
|
* @return The new empty cache
|
||||||
*/
|
*/
|
||||||
public static AsmFragmentTemplateCache diskCache(Path cacheFolder, TargetCpu cpu, AsmFragmentSystemHash fragmentSystemHash, Map<String, AsmFragmentTemplate> cache) {
|
public static AsmFragmentTemplateCache diskCache(Path cacheFolder, TargetCpu cpu, AsmFragmentSystemHash fragmentSystemHash, Map<AsmFragmentSignature, AsmFragmentTemplate> cache) {
|
||||||
return new AsmFragmentTemplateCache(cacheFolder, cpu, fragmentSystemHash, cache);
|
return new AsmFragmentTemplateCache(cacheFolder, cpu, fragmentSystemHash, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +120,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
final Date before = new Date();
|
final Date before = new Date();
|
||||||
if(!cacheFolder.toFile().exists()) {
|
if(!cacheFolder.toFile().exists()) {
|
||||||
if(log.isVerboseFragmentLog())
|
if(log.isVerboseFragmentLog())
|
||||||
log.append("Creating fragment cache folder " + cacheFolder.toAbsolutePath().toString());
|
log.append("Creating fragment cache folder " + cacheFolder.toAbsolutePath());
|
||||||
cacheFolder.toFile().mkdir();
|
cacheFolder.toFile().mkdir();
|
||||||
return diskCache(cacheFolder, cpu, fragmentSystemHash, new LinkedHashMap<>());
|
return diskCache(cacheFolder, cpu, fragmentSystemHash, new LinkedHashMap<>());
|
||||||
}
|
}
|
||||||
@ -133,7 +135,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
cacheFile.delete();
|
cacheFile.delete();
|
||||||
return diskCache(cacheFolder, cpu, fragmentSystemHash, new LinkedHashMap<>());
|
return diskCache(cacheFolder, cpu, fragmentSystemHash, new LinkedHashMap<>());
|
||||||
}
|
}
|
||||||
LinkedHashMap<String, AsmFragmentTemplate> cache = new LinkedHashMap<>();
|
LinkedHashMap<AsmFragmentSignature, AsmFragmentTemplate> cache = new LinkedHashMap<>();
|
||||||
BufferedReader fragmentCacheReader = new BufferedReader(new FileReader(cacheFile));
|
BufferedReader fragmentCacheReader = new BufferedReader(new FileReader(cacheFile));
|
||||||
String hashLine = fragmentCacheReader.readLine();
|
String hashLine = fragmentCacheReader.readLine();
|
||||||
final String hashPayload = hashLine.substring(HASH_HEADER.length());
|
final String hashPayload = hashLine.substring(HASH_HEADER.length());
|
||||||
@ -152,16 +154,16 @@ public class AsmFragmentTemplateCache {
|
|||||||
// Read the first "real" line
|
// Read the first "real" line
|
||||||
String cacheLine = fragmentCacheReader.readLine();
|
String cacheLine = fragmentCacheReader.readLine();
|
||||||
StringBuilder body = null;
|
StringBuilder body = null;
|
||||||
String signature = null;
|
String signatureText = null;
|
||||||
while(cacheLine != null) {
|
while(cacheLine != null) {
|
||||||
// Determine if the line is a new fragment or the continuation of the current fragment body
|
// Determine if the line is a new fragment or the continuation of the current fragment body
|
||||||
if(cacheLine.startsWith(FRAGMENT_HEADER)) {
|
if(cacheLine.startsWith(FRAGMENT_HEADER)) {
|
||||||
// New fragment - first put the current one into the cache
|
// New fragment - first put the current one into the cache
|
||||||
if(signature != null)
|
if(signatureText != null)
|
||||||
addFragment(cache, signature, body, cpu);
|
addFragment(cache, signatureText, body, cpu);
|
||||||
// Clear body and initialize signature
|
// Clear body and initialize signature
|
||||||
body = new StringBuilder();
|
body = new StringBuilder();
|
||||||
signature = cacheLine.substring(FRAGMENT_HEADER.length());
|
signatureText = cacheLine.substring(FRAGMENT_HEADER.length());
|
||||||
} else {
|
} else {
|
||||||
// Continuation of body
|
// Continuation of body
|
||||||
body.append(cacheLine).append("\n");
|
body.append(cacheLine).append("\n");
|
||||||
@ -169,8 +171,8 @@ public class AsmFragmentTemplateCache {
|
|||||||
cacheLine = fragmentCacheReader.readLine();
|
cacheLine = fragmentCacheReader.readLine();
|
||||||
}
|
}
|
||||||
// Put the last fragment into the cache
|
// Put the last fragment into the cache
|
||||||
if(signature != null)
|
if(signatureText != null)
|
||||||
addFragment(cache, signature, body, cpu);
|
addFragment(cache, signatureText, body, cpu);
|
||||||
final Date after = new Date();
|
final Date after = new Date();
|
||||||
final long millis = after.getTime() - before.getTime();
|
final long millis = after.getTime() - before.getTime();
|
||||||
if(log.isVerboseFragmentLog())
|
if(log.isVerboseFragmentLog())
|
||||||
@ -183,7 +185,8 @@ public class AsmFragmentTemplateCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addFragment(LinkedHashMap<String, AsmFragmentTemplate> cache, String signature, StringBuilder body, TargetCpu targetCpu) {
|
private static void addFragment(LinkedHashMap<AsmFragmentSignature, AsmFragmentTemplate> cache, String signatureText, StringBuilder body, TargetCpu targetCpu) {
|
||||||
|
AsmFragmentSignature signature = AsmFragmentSignature.parse(signatureText);
|
||||||
final String bodyString = body.toString();
|
final String bodyString = body.toString();
|
||||||
if(bodyString.startsWith(NO_SYNTHESIS.getBody())) {
|
if(bodyString.startsWith(NO_SYNTHESIS.getBody())) {
|
||||||
cache.put(signature, NO_SYNTHESIS);
|
cache.put(signature, NO_SYNTHESIS);
|
||||||
@ -213,7 +216,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
if(newFragmentSystemHash.getHashStringLF() == null || newFragmentSystemHash.getHashStringCRLF() == null)
|
if(newFragmentSystemHash.getHashStringLF() == null || newFragmentSystemHash.getHashStringCRLF() == null)
|
||||||
throw new InternalError("Error saving ASM fragment cache file. Not calculated for all systems!");
|
throw new InternalError("Error saving ASM fragment cache file. Not calculated for all systems!");
|
||||||
fragmentFilePrint.println(HASH_HEADER + newFragmentSystemHash.getHashStringLF() + " " + newFragmentSystemHash.getHashStringCRLF());
|
fragmentFilePrint.println(HASH_HEADER + newFragmentSystemHash.getHashStringLF() + " " + newFragmentSystemHash.getHashStringCRLF());
|
||||||
for(String signature : this.cache.keySet()) {
|
for(AsmFragmentSignature signature : this.cache.keySet()) {
|
||||||
AsmFragmentTemplate fragmentTemplate = this.cache.get(signature);
|
AsmFragmentTemplate fragmentTemplate = this.cache.get(signature);
|
||||||
fragmentFilePrint.println(FRAGMENT_HEADER + signature);
|
fragmentFilePrint.println(FRAGMENT_HEADER + signature);
|
||||||
if(fragmentTemplate == NO_SYNTHESIS) {
|
if(fragmentTemplate == NO_SYNTHESIS) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.*;
|
import dk.camelot64.kickc.fragment.synthesis.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -37,18 +38,19 @@ public class AsmFragmentTemplateUsages {
|
|||||||
*/
|
*/
|
||||||
public static void logUsages(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logUnusedRules, boolean logFileDetails, boolean logAllDetails, boolean logDetailsBody) {
|
public static void logUsages(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logUnusedRules, boolean logFileDetails, boolean logAllDetails, boolean logDetailsBody) {
|
||||||
|
|
||||||
Map<String, AsmFragmentSynthesis> synthesisGraph =
|
Map<AsmFragmentSignature, AsmFragmentSynthesis> synthesisGraph =
|
||||||
synthesizer.getSynthesisGraph();
|
synthesizer.getSynthesisGraph();
|
||||||
ArrayList<String> signatures = new ArrayList<>(synthesisGraph.keySet());
|
ArrayList<AsmFragmentSignature> signatures = new ArrayList<>(synthesisGraph.keySet());
|
||||||
Collections.sort(signatures);
|
Collections.sort(signatures);
|
||||||
File[] files = synthesizer.allFragmentFiles();
|
File[] files = synthesizer.allFragmentFiles();
|
||||||
|
|
||||||
if(logRedundantFiles) {
|
if(logRedundantFiles) {
|
||||||
log.append("\nREDUNDANT ASM FRAGMENT FILES ANALYSIS (if found consider removing them from disk)");
|
log.append("\nREDUNDANT ASM FRAGMENT FILES ANALYSIS (if found consider removing them from disk)");
|
||||||
Set<String> redundantSignatures = new LinkedHashSet<>();
|
Set<AsmFragmentSignature> redundantSignatures = new LinkedHashSet<>();
|
||||||
for(File file : files) {
|
for(File file : files) {
|
||||||
String fileName = file.getName();
|
String fileName = file.getName();
|
||||||
String signature = fileName.substring(0, fileName.length() - 4);
|
String signatureText = fileName.substring(0, fileName.length() - 4);
|
||||||
|
AsmFragmentSignature signature = AsmFragmentSignature.parse(signatureText);
|
||||||
// Synthesize the fragment - and check if the synthesis is as good as the file body
|
// Synthesize the fragment - and check if the synthesis is as good as the file body
|
||||||
Collection<AsmFragmentSynthesisResult> templates = synthesizer.getBestTemplates(signature, log);
|
Collection<AsmFragmentSynthesisResult> templates = synthesizer.getBestTemplates(signature, log);
|
||||||
boolean isFile = false;
|
boolean isFile = false;
|
||||||
@ -110,7 +112,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
log.append("\nUNUSED ASM FRAGMENT SYNTHESIS RULE ANALYSIS (if found consider removing them)");
|
log.append("\nUNUSED ASM FRAGMENT SYNTHESIS RULE ANALYSIS (if found consider removing them)");
|
||||||
final Collection<AsmFragmentTemplateSynthesisRule> allRules = AsmFragmentTemplateSynthesisRuleManager.getAllSynthesisRules();
|
final Collection<AsmFragmentTemplateSynthesisRule> allRules = AsmFragmentTemplateSynthesisRuleManager.getAllSynthesisRules();
|
||||||
|
|
||||||
for(String signature : signatures) {
|
for(AsmFragmentSignature signature : signatures) {
|
||||||
LinkedList<AsmFragmentSynthesisResult> templates = new LinkedList<>(synthesizer.getBestTemplates(signature, log));
|
LinkedList<AsmFragmentSynthesisResult> templates = new LinkedList<>(synthesizer.getBestTemplates(signature, log));
|
||||||
while(!templates.isEmpty()) {
|
while(!templates.isEmpty()) {
|
||||||
final AsmFragmentSynthesisResult template = templates.pop();
|
final AsmFragmentSynthesisResult template = templates.pop();
|
||||||
@ -128,7 +130,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
log.append("\nDETAILED ASM FILE USAGES");
|
log.append("\nDETAILED ASM FILE USAGES");
|
||||||
// Find all file templates
|
// Find all file templates
|
||||||
List<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
List<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
||||||
for(String signature : signatures) {
|
for(AsmFragmentSignature signature : signatures) {
|
||||||
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||||
for(AsmFragmentSynthesisResult template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
if(template.isFile()) {
|
if(template.isFile()) {
|
||||||
@ -143,7 +145,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
if(logAllDetails) {
|
if(logAllDetails) {
|
||||||
log.append("\nDETAILED ASM FRAGMENT USAGES");
|
log.append("\nDETAILED ASM FRAGMENT USAGES");
|
||||||
List<AsmFragmentSynthesisResult> allTemplates = new ArrayList<>();
|
List<AsmFragmentSynthesisResult> allTemplates = new ArrayList<>();
|
||||||
for(String signature : signatures) {
|
for(AsmFragmentSignature signature : signatures) {
|
||||||
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||||
allTemplates.addAll(templates);
|
allTemplates.addAll(templates);
|
||||||
}
|
}
|
||||||
@ -155,14 +157,13 @@ public class AsmFragmentTemplateUsages {
|
|||||||
|
|
||||||
private static void logTemplatesByUsage(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, List<AsmFragmentSynthesisResult> templates, boolean logBody) {
|
private static void logTemplatesByUsage(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, List<AsmFragmentSynthesisResult> templates, boolean logBody) {
|
||||||
// Sort by usage
|
// Sort by usage
|
||||||
Collections.sort(templates, (o1, o2) -> {
|
templates.sort((o1, o2) -> {
|
||||||
Integer u1 = fragmentTemplateUsage.get(o1);
|
Integer u1 = fragmentTemplateUsage.get(o1);
|
||||||
Integer u2 = fragmentTemplateUsage.get(o2);
|
Integer u2 = fragmentTemplateUsage.get(o2);
|
||||||
if(u1 == null) u1 = 0;
|
if (u1 == null) u1 = 0;
|
||||||
if(u2 == null) u2 = 0;
|
if (u2 == null) u2 = 0;
|
||||||
return u2 - u1;
|
return u2 - u1;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
// Output
|
// Output
|
||||||
for(AsmFragmentSynthesisResult template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
Integer usage = fragmentTemplateUsage.get(template);
|
Integer usage = fragmentTemplateUsage.get(template);
|
||||||
|
@ -6,11 +6,13 @@ import org.antlr.v4.runtime.CharStream;
|
|||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A signature of an ASM fragment.
|
* A signature of an ASM fragment.
|
||||||
* The signature captures the operation performed by the fragment and the types of the parameters.
|
* The signature captures the operation performed by the fragment and the types of the parameters.
|
||||||
*/
|
*/
|
||||||
public interface AsmFragmentSignature {
|
public interface AsmFragmentSignature extends Comparable<AsmFragmentSignature> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the signature name. Eg. <code>vbum1=pbum2_derefidx_vbuyy</code>
|
* Get the signature name. Eg. <code>vbum1=pbum2_derefidx_vbuyy</code>
|
||||||
@ -22,6 +24,7 @@ public interface AsmFragmentSignature {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a signature name to a typed signature.
|
* Parses a signature name to a typed signature.
|
||||||
|
*
|
||||||
* @param sigName The signature name (created by signature.getName())
|
* @param sigName The signature name (created by signature.getName())
|
||||||
* @return The signature
|
* @return The signature
|
||||||
*/
|
*/
|
||||||
@ -34,10 +37,36 @@ public interface AsmFragmentSignature {
|
|||||||
return instantiator.visitSignature(sigCtx);
|
return instantiator.visitSignature(sigCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class AsmFragmentSignatureBase implements AsmFragmentSignature {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
AsmFragmentSignatureBase other = (AsmFragmentSignatureBase) o;
|
||||||
|
return Objects.equals(getName(), other.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(AsmFragmentSignature other) {
|
||||||
|
return getName().compareTo(other.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASM fragment signature for an assignment <code>A=B</code>.
|
* ASM fragment signature for an assignment <code>A=B</code>.
|
||||||
*/
|
*/
|
||||||
class Assignment implements AsmFragmentSignature {
|
class Assignment extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
final private AsmFragmentSignatureExpr lValue;
|
final private AsmFragmentSignatureExpr lValue;
|
||||||
final private AsmFragmentSignatureExpr rValue;
|
final private AsmFragmentSignatureExpr rValue;
|
||||||
@ -56,7 +85,7 @@ public interface AsmFragmentSignature {
|
|||||||
/**
|
/**
|
||||||
* ASM fragment signature for a conditional jump <code>if(A) goto B</code>.
|
* ASM fragment signature for a conditional jump <code>if(A) goto B</code>.
|
||||||
*/
|
*/
|
||||||
class Call implements AsmFragmentSignature {
|
class Call extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
final private AsmFragmentSignatureExpr procedure;
|
final private AsmFragmentSignatureExpr procedure;
|
||||||
|
|
||||||
@ -73,7 +102,7 @@ public interface AsmFragmentSignature {
|
|||||||
/**
|
/**
|
||||||
* ASM fragment signature for a conditional jump <code>if(A) goto B</code>.
|
* ASM fragment signature for a conditional jump <code>if(A) goto B</code>.
|
||||||
*/
|
*/
|
||||||
class ConditionalJump implements AsmFragmentSignature {
|
class ConditionalJump extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
final private AsmFragmentSignatureExpr condition;
|
final private AsmFragmentSignatureExpr condition;
|
||||||
final private AsmFragmentSignatureExpr label;
|
final private AsmFragmentSignatureExpr label;
|
||||||
@ -92,7 +121,7 @@ public interface AsmFragmentSignature {
|
|||||||
/**
|
/**
|
||||||
* ASM fragment signature for a stand-alone expression with a side-effect.
|
* ASM fragment signature for a stand-alone expression with a side-effect.
|
||||||
*/
|
*/
|
||||||
class ExprSideEffect implements AsmFragmentSignature {
|
class ExprSideEffect extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
final private AsmFragmentSignatureExpr expr;
|
final private AsmFragmentSignatureExpr expr;
|
||||||
|
|
||||||
@ -106,8 +135,10 @@ public interface AsmFragmentSignature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Interrupt Service Routine Code. */
|
/**
|
||||||
class Isr implements AsmFragmentSignature {
|
* Interrupt Service Routine Code.
|
||||||
|
*/
|
||||||
|
class Isr extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
final private String interruptType;
|
final private String interruptType;
|
||||||
|
|
||||||
@ -129,4 +160,22 @@ public interface AsmFragmentSignature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Signature used for singletons. */
|
||||||
|
class Singleton extends AsmFragmentSignatureBase {
|
||||||
|
|
||||||
|
/** The singleton name. */
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public Singleton(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment.synthesis;
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ public class AsmFragmentSynthesis {
|
|||||||
/**
|
/**
|
||||||
* The signature of the fragment template being synthesized.
|
* The signature of the fragment template being synthesized.
|
||||||
*/
|
*/
|
||||||
private final String signature;
|
private final AsmFragmentSignature signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The best template loaded/synthesized so far for each clobber profile
|
* The best template loaded/synthesized so far for each clobber profile
|
||||||
@ -41,7 +42,7 @@ public class AsmFragmentSynthesis {
|
|||||||
*
|
*
|
||||||
* @param signature The signature of the fragment template to load/synthesize
|
* @param signature The signature of the fragment template to load/synthesize
|
||||||
*/
|
*/
|
||||||
AsmFragmentSynthesis(String signature) {
|
AsmFragmentSynthesis(AsmFragmentSignature signature) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.bestTemplates = new LinkedHashMap<>();
|
this.bestTemplates = new LinkedHashMap<>();
|
||||||
this.synthesisOptions = new LinkedHashSet<>();
|
this.synthesisOptions = new LinkedHashSet<>();
|
||||||
@ -163,7 +164,7 @@ public class AsmFragmentSynthesis {
|
|||||||
return bestTemplates.values();
|
return bestTemplates.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignature() {
|
public AsmFragmentSignature getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment.synthesis;
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -11,12 +13,12 @@ public class AsmFragmentSynthesisOption {
|
|||||||
/**
|
/**
|
||||||
* The signature of the fragment template being synthesized. The from-node in the graph.
|
* The signature of the fragment template being synthesized. The from-node in the graph.
|
||||||
*/
|
*/
|
||||||
private final String signature;
|
private final AsmFragmentSignature signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The signatures of the sub-fragment templates to synthesize from. The to-nodes in the graph.
|
* The signatures of the sub-fragment templates to synthesize from. The to-nodes in the graph.
|
||||||
*/
|
*/
|
||||||
private final List<String> subSignatures;
|
private final List<AsmFragmentSignature> subSignatures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The synthesis rule capable of synthesizing this template from the sub-fragments.
|
* The synthesis rule capable of synthesizing this template from the sub-fragments.
|
||||||
@ -29,17 +31,17 @@ public class AsmFragmentSynthesisOption {
|
|||||||
* @param signature the signature of the fragment template being synthesized.
|
* @param signature the signature of the fragment template being synthesized.
|
||||||
* @param rule The synthesis rule capable of synthesizing this template from the sub-fragment.
|
* @param rule The synthesis rule capable of synthesizing this template from the sub-fragment.
|
||||||
*/
|
*/
|
||||||
AsmFragmentSynthesisOption(String signature, AsmFragmentTemplateSynthesisRule rule) {
|
AsmFragmentSynthesisOption(AsmFragmentSignature signature, AsmFragmentTemplateSynthesisRule rule) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.rule = rule;
|
this.rule = rule;
|
||||||
this.subSignatures = rule.getSubSignatures(signature);
|
this.subSignatures = rule.getSubSignatures(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignature() {
|
public AsmFragmentSignature getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getSubSignatures() {
|
List<AsmFragmentSignature> getSubSignatures() {
|
||||||
return subSignatures;
|
return subSignatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.fragment.synthesis;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -18,20 +19,20 @@ public class AsmFragmentSynthesisResult {
|
|||||||
/**
|
/**
|
||||||
* true if the fragment was loaded from disk.
|
* true if the fragment was loaded from disk.
|
||||||
*/
|
*/
|
||||||
private boolean file;
|
private final boolean file;
|
||||||
/**
|
/**
|
||||||
* true if the fragment was loaded from the disk cache.
|
* true if the fragment was loaded from the disk cache.
|
||||||
*/
|
*/
|
||||||
private boolean cache;
|
private final boolean cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The synthesis that created the fragment. null if the fragment template was loaded.
|
* The synthesis that created the fragment. null if the fragment template was loaded.
|
||||||
*/
|
*/
|
||||||
private AsmFragmentTemplateSynthesisRule synthesis;
|
private final AsmFragmentTemplateSynthesisRule synthesis;
|
||||||
/**
|
/**
|
||||||
* The sub fragment template that the synthesis used to create this.
|
* The sub fragment template that the synthesis used to create this.
|
||||||
*/
|
*/
|
||||||
private List<AsmFragmentSynthesisResult> subFragments;
|
private final List<AsmFragmentSynthesisResult> subFragments;
|
||||||
|
|
||||||
public AsmFragmentSynthesisResult(AsmFragmentTemplate fragment, boolean file, boolean cache, AsmFragmentTemplateSynthesisRule synthesis, List<AsmFragmentSynthesisResult> subFragments) {
|
public AsmFragmentSynthesisResult(AsmFragmentTemplate fragment, boolean file, boolean cache, AsmFragmentTemplateSynthesisRule synthesis, List<AsmFragmentSynthesisResult> subFragments) {
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
@ -92,7 +93,7 @@ public class AsmFragmentSynthesisResult {
|
|||||||
return fragment.getBody();
|
return fragment.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignature() {
|
public AsmFragmentSignature getSignature() {
|
||||||
return fragment.getSignature();
|
return fragment.getSignature();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment.synthesis;
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ public interface AsmFragmentTemplateSynthesisRule {
|
|||||||
* @param signature The fragment template signature
|
* @param signature The fragment template signature
|
||||||
* @return true if the rule matches the signature
|
* @return true if the rule matches the signature
|
||||||
*/
|
*/
|
||||||
boolean matches(String signature);
|
boolean matches(AsmFragmentSignature signature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The signatures of the sub-templates that are needed to generate an ASM fragment template
|
* The signatures of the sub-templates that are needed to generate an ASM fragment template
|
||||||
@ -23,7 +24,7 @@ public interface AsmFragmentTemplateSynthesisRule {
|
|||||||
* @param signature The signature of the fragment to synthesize
|
* @param signature The signature of the fragment to synthesize
|
||||||
* @return Signatures of the sub-templates that are needed to synthesize the fragment template.
|
* @return Signatures of the sub-templates that are needed to synthesize the fragment template.
|
||||||
*/
|
*/
|
||||||
List<String> getSubSignatures(String signature);
|
List<AsmFragmentSignature> getSubSignatures(AsmFragmentSignature signature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synthesize a fragment template from a sub fragment template.
|
* Synthesize a fragment template from a sub fragment template.
|
||||||
@ -33,5 +34,5 @@ public interface AsmFragmentTemplateSynthesisRule {
|
|||||||
* @return The synthesized ASM fragment template.
|
* @return The synthesized ASM fragment template.
|
||||||
* Null if the fragment cannot be synthesized (for instance due to clobber constraints).
|
* Null if the fragment cannot be synthesized (for instance due to clobber constraints).
|
||||||
*/
|
*/
|
||||||
AsmFragmentTemplate synthesize(String signature, List<AsmFragmentTemplate> subTemplates);
|
AsmFragmentTemplate synthesize(AsmFragmentSignature signature, List<AsmFragmentTemplate> subTemplates);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment.synthesis;
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -71,39 +72,42 @@ class AsmFragmentTemplateSynthesisRuleRegex implements AsmFragmentTemplateSynthe
|
|||||||
* @param signature The fragment template signature
|
* @param signature The fragment template signature
|
||||||
* @return true if the rule matches the signature
|
* @return true if the rule matches the signature
|
||||||
*/
|
*/
|
||||||
public boolean matches(String signature) {
|
public boolean matches(AsmFragmentSignature signature) {
|
||||||
|
final String signatureText = signature.getName();
|
||||||
if(sigMatchPattern == null)
|
if(sigMatchPattern == null)
|
||||||
sigMatchPattern = Pattern.compile(sigMatch);
|
sigMatchPattern = Pattern.compile(sigMatch);
|
||||||
Matcher m = sigMatchPattern.matcher(signature);
|
Matcher m = sigMatchPattern.matcher(signatureText);
|
||||||
if(m.matches()) {
|
if(m.matches()) {
|
||||||
if(sigAvoid == null)
|
if(sigAvoid == null)
|
||||||
return true;
|
return true;
|
||||||
else {
|
else {
|
||||||
if(sigAvoidPattern == null)
|
if(sigAvoidPattern == null)
|
||||||
sigAvoidPattern = Pattern.compile(sigAvoid);
|
sigAvoidPattern = Pattern.compile(sigAvoid);
|
||||||
Matcher ma = sigAvoidPattern.matcher(signature);
|
Matcher ma = sigAvoidPattern.matcher(signatureText);
|
||||||
return !ma.matches();
|
return !ma.matches();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getSubSignatures(String signature) {
|
public List<AsmFragmentSignature> getSubSignatures(AsmFragmentSignature signature) {
|
||||||
if(matches(signature)) {
|
if(matches(signature)) {
|
||||||
String subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
|
final String signatureText = signature.getName();
|
||||||
|
String subSignatureText = regexpRewriteSignature(signatureText, sigMatch, sigReplace);
|
||||||
if(mapSignature && bindMappings != null) {
|
if(mapSignature && bindMappings != null) {
|
||||||
// When mapping the signature we do the map replacement in the signature
|
// When mapping the signature we do the map replacement in the signature
|
||||||
for(String bound : bindMappings.keySet()) {
|
for(String bound : bindMappings.keySet()) {
|
||||||
subSignature = subSignature.replace(bound, bindMappings.get(bound));
|
subSignatureText = subSignatureText.replace(bound, bindMappings.get(bound));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collections.singletonList(subSignature);
|
return Collections.singletonList(AsmFragmentSignature.parse(subSignatureText));
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmFragmentTemplate synthesize(String signature, List<AsmFragmentTemplate> subTemplates) {
|
public AsmFragmentTemplate synthesize(AsmFragmentSignature signature, List<AsmFragmentTemplate> subTemplates) {
|
||||||
|
|
||||||
final AsmFragmentTemplate subTemplate = subTemplates.get(0);
|
final AsmFragmentTemplate subTemplate = subTemplates.get(0);
|
||||||
// if(!matches(signature)) {
|
// if(!matches(signature)) {
|
||||||
// throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching signature signature:"+signature+" match:"+sigMatch+" avoid:"+sigAvoid);
|
// throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching signature signature:"+signature+" match:"+sigMatch+" avoid:"+sigAvoid);
|
||||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.fragment.synthesis;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.fragment.*;
|
import dk.camelot64.kickc.fragment.*;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
@ -55,7 +56,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* This map is effectively a full-graph where the nodes are synthesis for signatures and edges are the
|
* This map is effectively a full-graph where the nodes are synthesis for signatures and edges are the
|
||||||
* synthesis rules capable of synthesizing one fragment temple from another.
|
* synthesis rules capable of synthesizing one fragment temple from another.
|
||||||
*/
|
*/
|
||||||
private final Map<String, AsmFragmentSynthesis> synthesisGraph;
|
private final Map<AsmFragmentSignature, AsmFragmentSynthesis> synthesisGraph;
|
||||||
|
|
||||||
/** Finalize the fragment template synthesizer. */
|
/** Finalize the fragment template synthesizer. */
|
||||||
void finalize(CompileLog log) {
|
void finalize(CompileLog log) {
|
||||||
@ -73,7 +74,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
|
public AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
|
||||||
String signature = instanceSpec.getSignature();
|
AsmFragmentSignature signature = instanceSpec.getSignature();
|
||||||
AsmFragmentTemplate fragmentTemplate = getFragmentTemplate(signature, log);
|
AsmFragmentTemplate fragmentTemplate = getFragmentTemplate(signature, log);
|
||||||
// Return the resulting fragment instance
|
// Return the resulting fragment instance
|
||||||
return new AsmFragmentInstance(
|
return new AsmFragmentInstance(
|
||||||
@ -91,14 +92,14 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param log The log
|
* @param log The log
|
||||||
* @return The best templates (with different clobber profiles) for the signature
|
* @return The best templates (with different clobber profiles) for the signature
|
||||||
*/
|
*/
|
||||||
private AsmFragmentTemplate getFragmentTemplate(String signature, CompileLog log) {
|
private AsmFragmentTemplate getFragmentTemplate(AsmFragmentSignature signature, CompileLog log) {
|
||||||
// Attempt to find in memory/disk cache
|
// Attempt to find in memory/disk cache
|
||||||
AsmFragmentTemplate bestTemplate = fragmentCache.get(signature);
|
AsmFragmentTemplate bestTemplate = fragmentCache.get(signature);
|
||||||
if (bestTemplate == AsmFragmentTemplateCache.NO_SYNTHESIS) {
|
if (bestTemplate == AsmFragmentTemplateCache.NO_SYNTHESIS) {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Unknown fragment " + signature);
|
log.append("Unknown fragment " + signature);
|
||||||
}
|
}
|
||||||
throw new UnknownFragmentException(signature);
|
throw new UnknownFragmentException(signature.getName());
|
||||||
}
|
}
|
||||||
if (bestTemplate != null) {
|
if (bestTemplate != null) {
|
||||||
AsmFragmentTemplateUsages.incUsage(new AsmFragmentSynthesisResult(bestTemplate, false, true, null, new ArrayList<>()));
|
AsmFragmentTemplateUsages.incUsage(new AsmFragmentSynthesisResult(bestTemplate, false, true, null, new ArrayList<>()));
|
||||||
@ -144,7 +145,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param log The compile log
|
* @param log The compile log
|
||||||
* @return The best templates for the passed signature
|
* @return The best templates for the passed signature
|
||||||
*/
|
*/
|
||||||
public Collection<AsmFragmentSynthesisResult> getBestTemplates(String signature, CompileLog log) {
|
public Collection<AsmFragmentSynthesisResult> getBestTemplates(AsmFragmentSignature signature, CompileLog log) {
|
||||||
getOrCreateSynthesis(signature, log);
|
getOrCreateSynthesis(signature, log);
|
||||||
updateBestTemplates(log);
|
updateBestTemplates(log);
|
||||||
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
||||||
@ -159,7 +160,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
*
|
*
|
||||||
* @return The entire synthesis graph
|
* @return The entire synthesis graph
|
||||||
*/
|
*/
|
||||||
public Map<String, AsmFragmentSynthesis> getSynthesisGraph() {
|
public Map<AsmFragmentSignature, AsmFragmentSynthesis> getSynthesisGraph() {
|
||||||
return synthesisGraph;
|
return synthesisGraph;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +172,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @return The synthesis used to synthesize the fragment template.
|
* @return The synthesis used to synthesize the fragment template.
|
||||||
* null if the synthesis graph does not contain the synthesis.
|
* null if the synthesis graph does not contain the synthesis.
|
||||||
*/
|
*/
|
||||||
private AsmFragmentSynthesis getSynthesis(String signature) {
|
private AsmFragmentSynthesis getSynthesis(AsmFragmentSignature signature) {
|
||||||
return synthesisGraph.get(signature);
|
return synthesisGraph.get(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +185,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param log The compile log
|
* @param log The compile log
|
||||||
* @return The synthesis that is used to load/synthesize the best template
|
* @return The synthesis that is used to load/synthesize the best template
|
||||||
*/
|
*/
|
||||||
public AsmFragmentSynthesis getOrCreateSynthesis(String signature, CompileLog log) {
|
public AsmFragmentSynthesis getOrCreateSynthesis(AsmFragmentSignature signature, CompileLog log) {
|
||||||
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
||||||
if (synthesis != null) {
|
if (synthesis != null) {
|
||||||
return synthesis;
|
return synthesis;
|
||||||
@ -210,13 +211,13 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
AsmFragmentSynthesisOption synthesisOption = new AsmFragmentSynthesisOption(signature, rule);
|
AsmFragmentSynthesisOption synthesisOption = new AsmFragmentSynthesisOption(signature, rule);
|
||||||
synthesis.addSynthesisOption(synthesisOption);
|
synthesis.addSynthesisOption(synthesisOption);
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("New fragment synthesis " + signature + " - sub-option " + String.join(",", synthesisOption.getSubSignatures()));
|
log.append("New fragment synthesis " + signature + " - sub-option " + synthesisOption.getSubSignatures().stream().map(AsmFragmentSignature::getName).collect(Collectors.joining(",")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ensure that all sub-synthesis exist (recursively) - and set their parent options
|
// Ensure that all sub-synthesis exist (recursively) - and set their parent options
|
||||||
for (AsmFragmentSynthesisOption synthesisOption : synthesis.getSynthesisOptions()) {
|
for (AsmFragmentSynthesisOption synthesisOption : synthesis.getSynthesisOptions()) {
|
||||||
for (String subSignature : synthesisOption.getSubSignatures()) {
|
for (AsmFragmentSignature subSignature : synthesisOption.getSubSignatures()) {
|
||||||
AsmFragmentSynthesis subSynthesis = getOrCreateSynthesis(subSignature, log);
|
AsmFragmentSynthesis subSynthesis = getOrCreateSynthesis(subSignature, log);
|
||||||
subSynthesis.addParentOption(synthesisOption);
|
subSynthesis.addParentOption(synthesisOption);
|
||||||
}
|
}
|
||||||
@ -256,7 +257,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
for (AsmFragmentSynthesisOption synthesisOption : synthesisOptions) {
|
for (AsmFragmentSynthesisOption synthesisOption : synthesisOptions) {
|
||||||
// for each sub-signature find the best templates
|
// for each sub-signature find the best templates
|
||||||
List<Collection<AsmFragmentSynthesisResult>> subSignatureTemplates = new ArrayList<>();
|
List<Collection<AsmFragmentSynthesisResult>> subSignatureTemplates = new ArrayList<>();
|
||||||
for (String subSignature : synthesisOption.getSubSignatures()) {
|
for (AsmFragmentSignature subSignature : synthesisOption.getSubSignatures()) {
|
||||||
AsmFragmentSynthesis subSynthesis = getSynthesis(subSignature);
|
AsmFragmentSynthesis subSynthesis = getSynthesis(subSignature);
|
||||||
if (subSynthesis == null) {
|
if (subSynthesis == null) {
|
||||||
throw new RuntimeException("Synthesis Graph Error! Sub-synthesis not found in graph " + subSignature);
|
throw new RuntimeException("Synthesis Graph Error! Sub-synthesis not found in graph " + subSignature);
|
||||||
@ -272,13 +273,13 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
final AsmFragmentTemplate synthesize = rule.synthesize(synthesis.getSignature(), subFragments);
|
final AsmFragmentTemplate synthesize = rule.synthesize(synthesis.getSignature(), subFragments);
|
||||||
if (synthesize != null) {
|
if (synthesize != null) {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Fragment synthesis " + synthesis.getSignature() + " - Successfully synthesized from " + String.join(",", synthesisOption.getSubSignatures()));
|
log.append("Fragment synthesis " + synthesis.getSignature() + " - Successfully synthesized from " + synthesisOption.getSubSignatures().stream().map(AsmFragmentSignature::getName).collect(Collectors.joining(",")));
|
||||||
}
|
}
|
||||||
AsmFragmentSynthesisResult synthesisResult = new AsmFragmentSynthesisResult(synthesize, false, false, rule, subFragmentCombination);
|
AsmFragmentSynthesisResult synthesisResult = new AsmFragmentSynthesisResult(synthesize, false, false, rule, subFragmentCombination);
|
||||||
modified |= synthesis.bestTemplateCandidate(synthesisResult);
|
modified |= synthesis.bestTemplateCandidate(synthesisResult);
|
||||||
} else {
|
} else {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Fragment synthesis " + synthesis.getSignature() + " - Sub clobber prevents synthesis from " + String.join(",", synthesisOption.getSubSignatures()));
|
log.append("Fragment synthesis " + synthesis.getSignature() + " - Sub clobber prevents synthesis from " + synthesisOption.getSubSignatures().stream().map(AsmFragmentSignature::getName).collect(Collectors.joining(",")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,7 +288,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
if (modified) {
|
if (modified) {
|
||||||
// The synthesis was modified - update all parents later
|
// The synthesis was modified - update all parents later
|
||||||
for (AsmFragmentSynthesisOption parentOption : synthesis.getParentOptions()) {
|
for (AsmFragmentSynthesisOption parentOption : synthesis.getParentOptions()) {
|
||||||
String parentSignature = parentOption.getSignature();
|
AsmFragmentSignature parentSignature = parentOption.getSignature();
|
||||||
AsmFragmentSynthesis parentSynthesis = getSynthesis(parentSignature);
|
AsmFragmentSynthesis parentSynthesis = getSynthesis(parentSignature);
|
||||||
if (parentSynthesis == null) {
|
if (parentSynthesis == null) {
|
||||||
throw new RuntimeException("Synthesis Graph Error! Parent synthesis not found in graph " + parentSignature);
|
throw new RuntimeException("Synthesis Graph Error! Parent synthesis not found in graph " + parentSignature);
|
||||||
@ -341,7 +342,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param signature The signature
|
* @param signature The signature
|
||||||
* @return The fragment template from a file. null if the template is not found as a file.
|
* @return The fragment template from a file. null if the template is not found as a file.
|
||||||
*/
|
*/
|
||||||
private List<AsmFragmentSynthesisResult> loadFragmentTemplates(String signature) {
|
private List<AsmFragmentSynthesisResult> loadFragmentTemplates(AsmFragmentSignature signature) {
|
||||||
ArrayList<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
ArrayList<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
||||||
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
|
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
|
||||||
for (TargetCpu.Feature cpuFeature : cpuFeatures) {
|
for (TargetCpu.Feature cpuFeature : cpuFeatures) {
|
||||||
@ -359,9 +360,11 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param fragmentFolder The folder to look in
|
* @param fragmentFolder The folder to look in
|
||||||
* @return any fragment with the given signature found in the folder. null if not found.
|
* @return any fragment with the given signature found in the folder. null if not found.
|
||||||
*/
|
*/
|
||||||
private AsmFragmentSynthesisResult loadFragmentTemplate(String signature, Path fragmentFolder) {
|
private AsmFragmentSynthesisResult loadFragmentTemplate(AsmFragmentSignature signature, Path fragmentFolder) {
|
||||||
|
final String signatureText = signature.getName();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File fragmentFile = fragmentFolder.resolve(signature + ".asm").toFile();
|
File fragmentFile = fragmentFolder.resolve(signatureText + ".asm").toFile();
|
||||||
if (!fragmentFile.exists()) {
|
if (!fragmentFile.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -407,6 +410,10 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
|
|
||||||
private final String signature;
|
private final String signature;
|
||||||
|
|
||||||
|
public UnknownFragmentException(AsmFragmentSignature signature) {
|
||||||
|
this(signature.getName());
|
||||||
|
}
|
||||||
|
|
||||||
public UnknownFragmentException(String signature) {
|
public UnknownFragmentException(String signature) {
|
||||||
super("Fragment not found " + signature);
|
super("Fragment not found " + signature);
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
|
@ -4,6 +4,7 @@ import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
|||||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||||
import dk.camelot64.kickc.asm.*;
|
import dk.camelot64.kickc.asm.*;
|
||||||
import dk.camelot64.kickc.fragment.*;
|
import dk.camelot64.kickc.fragment.*;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.model.InternalError;
|
import dk.camelot64.kickc.model.InternalError;
|
||||||
import dk.camelot64.kickc.model.*;
|
import dk.camelot64.kickc.model.*;
|
||||||
@ -893,7 +894,13 @@ public class Pass4CodeGeneration {
|
|||||||
} else if (statement instanceof StatementAsm) {
|
} else if (statement instanceof StatementAsm) {
|
||||||
StatementAsm statementAsm = (StatementAsm) statement;
|
StatementAsm statementAsm = (StatementAsm) statement;
|
||||||
HashMap<String, Value> bindings = new HashMap<>();
|
HashMap<String, Value> bindings = new HashMap<>();
|
||||||
AsmFragmentInstance asmFragmentInstance = new AsmFragmentInstance(program, "inline", block.getScope(), new AsmFragmentTemplate(statementAsm.getAsmLines(), program.getTargetCpu()), bindings);
|
AsmFragmentInstance asmFragmentInstance =
|
||||||
|
new AsmFragmentInstance(
|
||||||
|
program,
|
||||||
|
new AsmFragmentSignature.Singleton("INLINE"),
|
||||||
|
block.getScope(),
|
||||||
|
new AsmFragmentTemplate(statementAsm.getAsmLines(), program.getTargetCpu()),
|
||||||
|
bindings);
|
||||||
asmFragmentInstance.generate(asm);
|
asmFragmentInstance.generate(asm);
|
||||||
AsmChunk currentChunk = asm.getCurrentChunk();
|
AsmChunk currentChunk = asm.getCurrentChunk();
|
||||||
|
|
||||||
@ -922,7 +929,7 @@ public class Pass4CodeGeneration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate exit-code for entering an interrupt procedure based on the interrupt type
|
* Generate entry-code for entering an interrupt procedure based on the interrupt type
|
||||||
*
|
*
|
||||||
* @param asm The assembler to generate code into
|
* @param asm The assembler to generate code into
|
||||||
* @param procedure The interrupt procedure
|
* @param procedure The interrupt procedure
|
||||||
@ -933,10 +940,10 @@ public class Pass4CodeGeneration {
|
|||||||
String entryName;
|
String entryName;
|
||||||
if (interruptType.contains("clobber")) {
|
if (interruptType.contains("clobber")) {
|
||||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType.replace("clobber", "all"), program);
|
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType.replace("clobber", "all"), program);
|
||||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
entryName = entryFragment.getSignature().getName().replace("all", "clobber");
|
||||||
} else {
|
} else {
|
||||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType, program);
|
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType, program);
|
||||||
entryName = entryFragment.getSignature();
|
entryName = entryFragment.getSignature().getName();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||||
@ -958,10 +965,10 @@ public class Pass4CodeGeneration {
|
|||||||
String entryName;
|
String entryName;
|
||||||
if (interruptType.contains("clobber")) {
|
if (interruptType.contains("clobber")) {
|
||||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType.replace("clobber", "all"), program);
|
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType.replace("clobber", "all"), program);
|
||||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
entryName = entryFragment.getSignature().getName().replace("all", "clobber");
|
||||||
} else {
|
} else {
|
||||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType, program);
|
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType, program);
|
||||||
entryName = entryFragment.getSignature();
|
entryName = entryFragment.getSignature().getName();
|
||||||
}
|
}
|
||||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||||
try {
|
try {
|
||||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.test;
|
|||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||||
|
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
@ -35,7 +36,7 @@ public class TestFragments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSynthesis() throws IOException {
|
public void testSynthesis() {
|
||||||
testFragmentExists("pbuz1=pbuz2_plus_pwuc1_derefidx_vbuxx");
|
testFragmentExists("pbuz1=pbuz2_plus_pwuc1_derefidx_vbuxx");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,9 +190,10 @@ public class TestFragments {
|
|||||||
/**
|
/**
|
||||||
* Test that a specific fragment can be succesfully loaded/synthesized
|
* Test that a specific fragment can be succesfully loaded/synthesized
|
||||||
*
|
*
|
||||||
* @param signature The fragment signature
|
* @param signatureText The fragment signature
|
||||||
*/
|
*/
|
||||||
private void testFragmentExists(String signature) {
|
private void testFragmentExists(String signatureText) {
|
||||||
|
AsmFragmentSignature signature = AsmFragmentSignature.parse(signatureText);
|
||||||
CompileLog log = new CompileLog();
|
CompileLog log = new CompileLog();
|
||||||
asmFragmentTemplateSynthesizer = new AsmFragmentTemplateSynthesizer(TargetCpu.MOS6502X, new File("src/main/fragment/").toPath(), false, new CompileLog());
|
asmFragmentTemplateSynthesizer = new AsmFragmentTemplateSynthesizer(TargetCpu.MOS6502X, new File("src/main/fragment/").toPath(), false, new CompileLog());
|
||||||
log.setSysOut(true);
|
log.setSysOut(true);
|
||||||
@ -225,17 +227,18 @@ public class TestFragments {
|
|||||||
if((testStep % 100) == 0)
|
if((testStep % 100) == 0)
|
||||||
System.out.println("Testing " + testIdx + "/" + sigs.size());
|
System.out.println("Testing " + testIdx + "/" + sigs.size());
|
||||||
|
|
||||||
String signature = sigs.get(testIdx);
|
String signatureText = sigs.get(testIdx);
|
||||||
|
AsmFragmentSignature signature = AsmFragmentSignature.parse(signatureText);
|
||||||
|
|
||||||
List<AsmFragmentSynthesisResult> templates =
|
List<AsmFragmentSynthesisResult> templates =
|
||||||
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
||||||
Collections.sort(templates, Comparator.comparing(AsmFragmentSynthesisResult::getClobber));
|
templates.sort(Comparator.comparing(AsmFragmentSynthesisResult::getClobber));
|
||||||
if(templates.size() == 0) {
|
if(templates.size() == 0) {
|
||||||
log.append("CANNOT SYNTHESIZE " + signature);
|
log.append("CANNOT SYNTHESIZE " + signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(AsmFragmentSynthesisResult template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
String prefix = "";
|
String prefix;
|
||||||
if(template.isCache()) {
|
if(template.isCache()) {
|
||||||
prefix = "cached ";
|
prefix = "cached ";
|
||||||
} else if(template.isFile()) {
|
} else if(template.isFile()) {
|
||||||
@ -328,8 +331,7 @@ public class TestFragments {
|
|||||||
|
|
||||||
|
|
||||||
private Collection<Value> lValuesBu(Collection<Value> usedValues) {
|
private Collection<Value> lValuesBu(Collection<Value> usedValues) {
|
||||||
ArrayList<Value> values = new ArrayList<>();
|
ArrayList<Value> values = new ArrayList<>(lValuesVbu(usedValues));
|
||||||
values.addAll(lValuesVbu(usedValues));
|
|
||||||
Collection<Value> pbus = rValuesPbu(usedValues);
|
Collection<Value> pbus = rValuesPbu(usedValues);
|
||||||
for(Value pbu : pbus) {
|
for(Value pbu : pbus) {
|
||||||
values.add(new Value("_deref_" + pbu.getSignature(), pbu));
|
values.add(new Value("_deref_" + pbu.getSignature(), pbu));
|
||||||
@ -347,8 +349,7 @@ public class TestFragments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Value> rValuesBu(Collection<Value> usedValues) {
|
private Collection<Value> rValuesBu(Collection<Value> usedValues) {
|
||||||
ArrayList<Value> values = new ArrayList<>();
|
ArrayList<Value> values = new ArrayList<>(lValuesBu(usedValues));
|
||||||
values.addAll(lValuesBu(usedValues));
|
|
||||||
values.add(new Value("vbuc1"));
|
values.add(new Value("vbuc1"));
|
||||||
if(contains(usedValues, "c1")) {
|
if(contains(usedValues, "c1")) {
|
||||||
values.add(new Value("vbuc2"));
|
values.add(new Value("vbuc2"));
|
||||||
@ -393,8 +394,7 @@ public class TestFragments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Value> rValuesVbu(Collection<Value> usedValues) {
|
private Collection<Value> rValuesVbu(Collection<Value> usedValues) {
|
||||||
ArrayList<Value> values = new ArrayList<>();
|
ArrayList<Value> values = new ArrayList<>(lValuesVbu(usedValues));
|
||||||
values.addAll(lValuesVbu(usedValues));
|
|
||||||
values.add(new Value("vbuc1"));
|
values.add(new Value("vbuc1"));
|
||||||
if(contains(usedValues, "c1")) {
|
if(contains(usedValues, "c1")) {
|
||||||
values.add(new Value("vbuc2"));
|
values.add(new Value("vbuc2"));
|
||||||
@ -437,8 +437,7 @@ public class TestFragments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Value> rValuesPbu(Collection<Value> usedValues) {
|
private Collection<Value> rValuesPbu(Collection<Value> usedValues) {
|
||||||
ArrayList<Value> values = new ArrayList<>();
|
ArrayList<Value> values = new ArrayList<>(lValuesPbu(usedValues));
|
||||||
values.addAll(lValuesPbu(usedValues));
|
|
||||||
values.add(new Value("pbuc1"));
|
values.add(new Value("pbuc1"));
|
||||||
if(contains(usedValues, "c1")) {
|
if(contains(usedValues, "c1")) {
|
||||||
values.add(new Value("pbuc2"));
|
values.add(new Value("pbuc2"));
|
||||||
@ -470,12 +469,12 @@ public class TestFragments {
|
|||||||
/** A signature that is part of a fragment signature. The signature may have sub-values (eg. if. it is a _derefidx_ signature */
|
/** A signature that is part of a fragment signature. The signature may have sub-values (eg. if. it is a _derefidx_ signature */
|
||||||
public static class Value {
|
public static class Value {
|
||||||
|
|
||||||
private String signature;
|
private final String signature;
|
||||||
|
|
||||||
private Collection<Value> subValues;
|
private final Collection<Value> subValues;
|
||||||
|
|
||||||
public Value(String signature) {
|
public Value(String signature) {
|
||||||
this(signature, new ArrayList<Value>());
|
this(signature, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value(String signature, Collection<Value> subValues) {
|
public Value(String signature, Collection<Value> subValues) {
|
||||||
@ -484,7 +483,7 @@ public class TestFragments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Value(String signature, Value subVal) {
|
public Value(String signature, Value subVal) {
|
||||||
this(signature, Arrays.asList(subVal));
|
this(signature, Collections.singletonList(subVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user