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.fragment.AsmFragmentTemplateUsages;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||
@ -275,7 +276,8 @@ public class KickC implements Callable<Integer> {
|
||||
try {
|
||||
final AsmFragmentTemplateMasterSynthesizer masterSynthesizer = compiler.getAsmFragmentMasterSynthesizer();
|
||||
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) {
|
||||
AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, "");
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
|
||||
@ -15,7 +16,7 @@ public class AsmFragmentCodeGenerator {
|
||||
*/
|
||||
public static void generateAsm(AsmProgram asm, AsmFragmentInstanceSpec fragmentInstanceSpec, Program program) {
|
||||
AsmEncodingHelper.ensureEncoding(asm, fragmentInstanceSpec);
|
||||
String initialSignature = fragmentInstanceSpec.getSignature();
|
||||
AsmFragmentSignature initialSignature = fragmentInstanceSpec.getSignature();
|
||||
AsmFragmentInstance fragmentInstance = null;
|
||||
StringBuilder fragmentVariationsTried = new StringBuilder();
|
||||
while(fragmentInstance == null) {
|
||||
@ -24,7 +25,7 @@ public class AsmFragmentCodeGenerator {
|
||||
fragmentInstance = cpuSynthesizer.getFragmentInstance(fragmentInstanceSpec, program.getLog());
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
// 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(" ");
|
||||
if(fragmentInstanceSpec.hasNextVariation()) {
|
||||
fragmentInstanceSpec.nextVariation();
|
||||
@ -37,7 +38,7 @@ public class AsmFragmentCodeGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
asm.getCurrentChunk().setFragment(fragmentInstance.getFragmentName());
|
||||
asm.getCurrentChunk().setFragment(fragmentInstance.getFragmentSignature().getName());
|
||||
fragmentInstance.generate(asm);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.CpuOpcode;
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.symbols.Label;
|
||||
@ -25,7 +26,7 @@ public class AsmFragmentInstance {
|
||||
private final Program program;
|
||||
|
||||
/** The name of the fragment used in error messages. */
|
||||
private final String name;
|
||||
private final AsmFragmentSignature signature;
|
||||
|
||||
/** The fragment template for the ASM code. */
|
||||
private final AsmFragmentTemplate fragmentTemplate;
|
||||
@ -38,12 +39,12 @@ public class AsmFragmentInstance {
|
||||
|
||||
public AsmFragmentInstance(
|
||||
Program program,
|
||||
String name,
|
||||
AsmFragmentSignature signature,
|
||||
ScopeRef codeScopeRef,
|
||||
AsmFragmentTemplate fragmentTemplate,
|
||||
Map<String, Value> bindings) {
|
||||
this.program = program;
|
||||
this.name = name;
|
||||
this.signature = signature;
|
||||
this.fragmentTemplate = fragmentTemplate;
|
||||
this.bindings = bindings;
|
||||
this.codeScopeRef = codeScopeRef;
|
||||
@ -75,7 +76,7 @@ public class AsmFragmentInstance {
|
||||
}
|
||||
|
||||
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()) {
|
||||
Variable boundVar = (Variable) boundValue;
|
||||
@ -151,8 +152,8 @@ public class AsmFragmentInstance {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getFragmentName() {
|
||||
return name;
|
||||
public AsmFragmentSignature getFragmentSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +162,7 @@ public class AsmFragmentInstance {
|
||||
* @param asm The assembler sequence to generate into.
|
||||
*/
|
||||
public void generate(AsmProgram asm) {
|
||||
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(name, this, asm);
|
||||
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature.getName(), this, asm);
|
||||
asmSequenceGenerator.generate(fragmentTemplate.getBodyAsm());
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class AsmFragmentInstanceSpec {
|
||||
/**
|
||||
* 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, ...) .
|
||||
@ -46,13 +46,13 @@ public class AsmFragmentInstanceSpec {
|
||||
*/
|
||||
public AsmFragmentInstanceSpec(Program program, AsmFragmentSignature signature, AsmFragmentBindings bindings, ScopeRef codeScopeRef) {
|
||||
this.program = program;
|
||||
this.signature = signature.getName();
|
||||
this.signature = signature;
|
||||
this.bindings = bindings.variables;
|
||||
this.codeScopeRef = codeScopeRef;
|
||||
}
|
||||
|
||||
|
||||
public String getSignature() {
|
||||
public AsmFragmentSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
@ -148,7 +148,6 @@ public class AsmFragmentInstanceSpec {
|
||||
return potentialTypes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the ASM fragment instance specification to the next available variation.
|
||||
* If no more variations exist the ASM fragment instance specification will become unusable.
|
||||
@ -164,11 +163,11 @@ public class AsmFragmentInstanceSpec {
|
||||
bindings.remove(variationCurrentName);
|
||||
bindings.put(variationNextName, constValue);
|
||||
// Update signature
|
||||
this.signature = signature.replace(variationCurrentName, variationNextName);
|
||||
this.signature = AsmFragmentSignature.parse(signature.getName().replace(variationCurrentName, variationNextName));
|
||||
variationCurrentName = variationNextName;
|
||||
variationCurrentValue = nextVariationValue;
|
||||
} else {
|
||||
this.signature = "no-more-variations";
|
||||
this.signature = new AsmFragmentSignature.Singleton("NO_MORE_VARIATIONS");
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||
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.Registers;
|
||||
import dk.camelot64.kickc.model.TargetCpu;
|
||||
@ -27,7 +29,7 @@ import java.util.Objects;
|
||||
public class AsmFragmentTemplate {
|
||||
|
||||
/** The fragment template signature name. */
|
||||
private final String signature;
|
||||
private final AsmFragmentSignature signature;
|
||||
/** The target CPU. */
|
||||
private final TargetCpu targetCpu;
|
||||
/** 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.*/
|
||||
private Double cycles;
|
||||
|
||||
public AsmFragmentTemplate(String signature, String body, TargetCpu targetCpu) {
|
||||
public AsmFragmentTemplate(AsmFragmentSignature signature, String body, TargetCpu targetCpu) {
|
||||
this.signature = signature;
|
||||
this.body = body;
|
||||
this.targetCpu = targetCpu;
|
||||
@ -52,7 +54,7 @@ public class AsmFragmentTemplate {
|
||||
* @param bodyLines Parsed ASM body
|
||||
*/
|
||||
public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines, TargetCpu targetCpu) {
|
||||
this.signature = "--inline--";
|
||||
this.signature = new AsmFragmentSignature.Singleton("INLINE");
|
||||
this.bodyAsm = bodyLines;
|
||||
this.targetCpu = targetCpu;
|
||||
}
|
||||
@ -89,6 +91,8 @@ public class AsmFragmentTemplate {
|
||||
* Initialize the fields that require parsing the ASM (bodyAsm, clobber, cycles).
|
||||
*/
|
||||
private void initAsm() {
|
||||
String signatureName = signature.getName();
|
||||
|
||||
// Parse the body ASM
|
||||
this.bodyAsm = AsmParser.parseAsm(this.body, new StatementSource(signature + ".asm", 1, 1, this.body, -1, -1));
|
||||
// Generate a dummy instance to find clobber & cycles
|
||||
@ -108,12 +112,12 @@ public class AsmFragmentTemplate {
|
||||
v4.setAllocation(new Registers.RegisterZpMem(8, 1));
|
||||
v5.setAllocation(new Registers.RegisterZpMem(9, 1));
|
||||
v6.setAllocation(new Registers.RegisterZpMem(10, 1));
|
||||
if(signature.contains("z1")) bindings.put("z1", v1);
|
||||
if(signature.contains("z2")) bindings.put("z2", v2);
|
||||
if(signature.contains("z3")) bindings.put("z3", v3);
|
||||
if(signature.contains("z4")) bindings.put("z4", v4);
|
||||
if(signature.contains("z5")) bindings.put("z5", v5);
|
||||
if(signature.contains("z6")) bindings.put("z6", v6);
|
||||
if(signatureName.contains("z1")) bindings.put("z1", v1);
|
||||
if(signatureName.contains("z2")) bindings.put("z2", v2);
|
||||
if(signatureName.contains("z3")) bindings.put("z3", v3);
|
||||
if(signatureName.contains("z4")) bindings.put("z4", v4);
|
||||
if(signatureName.contains("z5")) bindings.put("z5", v5);
|
||||
if(signatureName.contains("z6")) bindings.put("z6", v6);
|
||||
}
|
||||
{
|
||||
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));
|
||||
v5.setAllocation(new Registers.RegisterMainMem(v5.getVariableRef(), 1, null, false));
|
||||
v6.setAllocation(new Registers.RegisterMainMem(v6.getVariableRef(), 1, null, false));
|
||||
if(signature.contains("m1")) bindings.put("m1", v1);
|
||||
if(signature.contains("m2")) bindings.put("m2", v2);
|
||||
if(signature.contains("m3")) bindings.put("m3", v3);
|
||||
if(signature.contains("m4")) bindings.put("m4", v4);
|
||||
if(signature.contains("m5")) bindings.put("m5", v5);
|
||||
if(signature.contains("m6")) bindings.put("m6", v6);
|
||||
if(signatureName.contains("m1")) bindings.put("m1", v1);
|
||||
if(signatureName.contains("m2")) bindings.put("m2", v2);
|
||||
if(signatureName.contains("m3")) bindings.put("m3", v3);
|
||||
if(signatureName.contains("m4")) bindings.put("m4", v4);
|
||||
if(signatureName.contains("m5")) bindings.put("m5", v5);
|
||||
if(signatureName.contains("m6")) bindings.put("m6", v6);
|
||||
}
|
||||
if(signature.contains("c1")) bindings.put("c1", new ConstantInteger(310L));
|
||||
if(signature.contains("c2")) bindings.put("c2", new ConstantInteger(320L));
|
||||
if(signature.contains("c3")) bindings.put("c3", new ConstantInteger(330L));
|
||||
if(signature.contains("c4")) bindings.put("c4", new ConstantInteger(340L));
|
||||
if(signature.contains("c5")) bindings.put("c5", new ConstantInteger(350L));
|
||||
if(signature.contains("c6")) bindings.put("c6", new ConstantInteger(360L));
|
||||
if(signature.contains("la1")) bindings.put("la1", new Label("@1", scope, true));
|
||||
if(signature.startsWith("call_")) bindings.put("la1", new Label("@1", scope, true));
|
||||
if(signatureName.contains("c1")) bindings.put("c1", new ConstantInteger(310L));
|
||||
if(signatureName.contains("c2")) bindings.put("c2", new ConstantInteger(320L));
|
||||
if(signatureName.contains("c3")) bindings.put("c3", new ConstantInteger(330L));
|
||||
if(signatureName.contains("c4")) bindings.put("c4", new ConstantInteger(340L));
|
||||
if(signatureName.contains("c5")) bindings.put("c5", new ConstantInteger(350L));
|
||||
if(signatureName.contains("c6")) bindings.put("c6", new ConstantInteger(360L));
|
||||
if(signatureName.contains("la1")) bindings.put("la1", new Label("@1", scope, true));
|
||||
if(signatureName.startsWith("call_")) bindings.put("la1", new Label("@1", scope, true));
|
||||
AsmFragmentInstance fragmentInstance =
|
||||
new AsmFragmentInstance(new Program(), signature, ScopeRef.ROOT, this, bindings);
|
||||
AsmProgram asm = new AsmProgram(targetCpu);
|
||||
asm.startChunk(ScopeRef.ROOT, null, signature);
|
||||
asm.startChunk(ScopeRef.ROOT, null, signature.getName());
|
||||
fragmentInstance.generate(asm);
|
||||
CpuClobber cpuClobber = asm.getClobber();
|
||||
this.clobber = new AsmFragmentClobber(cpuClobber);
|
||||
@ -154,7 +158,7 @@ public class AsmFragmentTemplate {
|
||||
this.cycles = asm.getCycles();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
public AsmFragmentSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.TargetCpu;
|
||||
@ -29,7 +30,7 @@ public class AsmFragmentTemplateCache {
|
||||
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. */
|
||||
private Map<String, AsmFragmentTemplate> cache;
|
||||
private Map<AsmFragmentSignature, AsmFragmentTemplate> cache;
|
||||
|
||||
/** Detects any modification of the cache. */
|
||||
private boolean modified;
|
||||
@ -39,7 +40,7 @@ public class AsmFragmentTemplateCache {
|
||||
*
|
||||
* @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.cpu = cpu;
|
||||
this.fragmentSystemHash = fragmentSystemHash;
|
||||
@ -48,7 +49,8 @@ public class AsmFragmentTemplateCache {
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
|
||||
@ -62,7 +64,7 @@ public class AsmFragmentTemplateCache {
|
||||
* @param signature The signature
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -72,7 +74,7 @@ public class AsmFragmentTemplateCache {
|
||||
* @param signature The signature
|
||||
* @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.modified = true;
|
||||
}
|
||||
@ -101,7 +103,7 @@ public class AsmFragmentTemplateCache {
|
||||
* @param cpu The CPU to make a cache for
|
||||
* @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);
|
||||
}
|
||||
|
||||
@ -118,7 +120,7 @@ public class AsmFragmentTemplateCache {
|
||||
final Date before = new Date();
|
||||
if(!cacheFolder.toFile().exists()) {
|
||||
if(log.isVerboseFragmentLog())
|
||||
log.append("Creating fragment cache folder " + cacheFolder.toAbsolutePath().toString());
|
||||
log.append("Creating fragment cache folder " + cacheFolder.toAbsolutePath());
|
||||
cacheFolder.toFile().mkdir();
|
||||
return diskCache(cacheFolder, cpu, fragmentSystemHash, new LinkedHashMap<>());
|
||||
}
|
||||
@ -133,7 +135,7 @@ public class AsmFragmentTemplateCache {
|
||||
cacheFile.delete();
|
||||
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));
|
||||
String hashLine = fragmentCacheReader.readLine();
|
||||
final String hashPayload = hashLine.substring(HASH_HEADER.length());
|
||||
@ -152,16 +154,16 @@ public class AsmFragmentTemplateCache {
|
||||
// Read the first "real" line
|
||||
String cacheLine = fragmentCacheReader.readLine();
|
||||
StringBuilder body = null;
|
||||
String signature = null;
|
||||
String signatureText = null;
|
||||
while(cacheLine != null) {
|
||||
// Determine if the line is a new fragment or the continuation of the current fragment body
|
||||
if(cacheLine.startsWith(FRAGMENT_HEADER)) {
|
||||
// New fragment - first put the current one into the cache
|
||||
if(signature != null)
|
||||
addFragment(cache, signature, body, cpu);
|
||||
if(signatureText != null)
|
||||
addFragment(cache, signatureText, body, cpu);
|
||||
// Clear body and initialize signature
|
||||
body = new StringBuilder();
|
||||
signature = cacheLine.substring(FRAGMENT_HEADER.length());
|
||||
signatureText = cacheLine.substring(FRAGMENT_HEADER.length());
|
||||
} else {
|
||||
// Continuation of body
|
||||
body.append(cacheLine).append("\n");
|
||||
@ -169,8 +171,8 @@ public class AsmFragmentTemplateCache {
|
||||
cacheLine = fragmentCacheReader.readLine();
|
||||
}
|
||||
// Put the last fragment into the cache
|
||||
if(signature != null)
|
||||
addFragment(cache, signature, body, cpu);
|
||||
if(signatureText != null)
|
||||
addFragment(cache, signatureText, body, cpu);
|
||||
final Date after = new Date();
|
||||
final long millis = after.getTime() - before.getTime();
|
||||
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();
|
||||
if(bodyString.startsWith(NO_SYNTHESIS.getBody())) {
|
||||
cache.put(signature, NO_SYNTHESIS);
|
||||
@ -213,7 +216,7 @@ public class AsmFragmentTemplateCache {
|
||||
if(newFragmentSystemHash.getHashStringLF() == null || newFragmentSystemHash.getHashStringCRLF() == null)
|
||||
throw new InternalError("Error saving ASM fragment cache file. Not calculated for all systems!");
|
||||
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);
|
||||
fragmentFilePrint.println(FRAGMENT_HEADER + signature);
|
||||
if(fragmentTemplate == NO_SYNTHESIS) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.fragment.synthesis.*;
|
||||
|
||||
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) {
|
||||
|
||||
Map<String, AsmFragmentSynthesis> synthesisGraph =
|
||||
Map<AsmFragmentSignature, AsmFragmentSynthesis> synthesisGraph =
|
||||
synthesizer.getSynthesisGraph();
|
||||
ArrayList<String> signatures = new ArrayList<>(synthesisGraph.keySet());
|
||||
ArrayList<AsmFragmentSignature> signatures = new ArrayList<>(synthesisGraph.keySet());
|
||||
Collections.sort(signatures);
|
||||
File[] files = synthesizer.allFragmentFiles();
|
||||
|
||||
if(logRedundantFiles) {
|
||||
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) {
|
||||
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
|
||||
Collection<AsmFragmentSynthesisResult> templates = synthesizer.getBestTemplates(signature, log);
|
||||
boolean isFile = false;
|
||||
@ -110,7 +112,7 @@ public class AsmFragmentTemplateUsages {
|
||||
log.append("\nUNUSED ASM FRAGMENT SYNTHESIS RULE ANALYSIS (if found consider removing them)");
|
||||
final Collection<AsmFragmentTemplateSynthesisRule> allRules = AsmFragmentTemplateSynthesisRuleManager.getAllSynthesisRules();
|
||||
|
||||
for(String signature : signatures) {
|
||||
for(AsmFragmentSignature signature : signatures) {
|
||||
LinkedList<AsmFragmentSynthesisResult> templates = new LinkedList<>(synthesizer.getBestTemplates(signature, log));
|
||||
while(!templates.isEmpty()) {
|
||||
final AsmFragmentSynthesisResult template = templates.pop();
|
||||
@ -128,7 +130,7 @@ public class AsmFragmentTemplateUsages {
|
||||
log.append("\nDETAILED ASM FILE USAGES");
|
||||
// Find all file templates
|
||||
List<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
||||
for(String signature : signatures) {
|
||||
for(AsmFragmentSignature signature : signatures) {
|
||||
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||
for(AsmFragmentSynthesisResult template : templates) {
|
||||
if(template.isFile()) {
|
||||
@ -143,7 +145,7 @@ public class AsmFragmentTemplateUsages {
|
||||
if(logAllDetails) {
|
||||
log.append("\nDETAILED ASM FRAGMENT USAGES");
|
||||
List<AsmFragmentSynthesisResult> allTemplates = new ArrayList<>();
|
||||
for(String signature : signatures) {
|
||||
for(AsmFragmentSignature signature : signatures) {
|
||||
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||
allTemplates.addAll(templates);
|
||||
}
|
||||
@ -155,14 +157,13 @@ public class AsmFragmentTemplateUsages {
|
||||
|
||||
private static void logTemplatesByUsage(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, List<AsmFragmentSynthesisResult> templates, boolean logBody) {
|
||||
// Sort by usage
|
||||
Collections.sort(templates, (o1, o2) -> {
|
||||
Integer u1 = fragmentTemplateUsage.get(o1);
|
||||
Integer u2 = fragmentTemplateUsage.get(o2);
|
||||
if(u1 == null) u1 = 0;
|
||||
if(u2 == null) u2 = 0;
|
||||
return u2 - u1;
|
||||
}
|
||||
);
|
||||
templates.sort((o1, o2) -> {
|
||||
Integer u1 = fragmentTemplateUsage.get(o1);
|
||||
Integer u2 = fragmentTemplateUsage.get(o2);
|
||||
if (u1 == null) u1 = 0;
|
||||
if (u2 == null) u2 = 0;
|
||||
return u2 - u1;
|
||||
});
|
||||
// Output
|
||||
for(AsmFragmentSynthesisResult template : templates) {
|
||||
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.CommonTokenStream;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A signature of an ASM fragment.
|
||||
* 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>
|
||||
@ -22,6 +24,7 @@ public interface AsmFragmentSignature {
|
||||
|
||||
/**
|
||||
* Parses a signature name to a typed signature.
|
||||
*
|
||||
* @param sigName The signature name (created by signature.getName())
|
||||
* @return The signature
|
||||
*/
|
||||
@ -34,10 +37,36 @@ public interface AsmFragmentSignature {
|
||||
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>.
|
||||
*/
|
||||
class Assignment implements AsmFragmentSignature {
|
||||
class Assignment extends AsmFragmentSignatureBase {
|
||||
|
||||
final private AsmFragmentSignatureExpr lValue;
|
||||
final private AsmFragmentSignatureExpr rValue;
|
||||
@ -56,7 +85,7 @@ public interface AsmFragmentSignature {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@ -73,7 +102,7 @@ public interface AsmFragmentSignature {
|
||||
/**
|
||||
* 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 label;
|
||||
@ -92,7 +121,7 @@ public interface AsmFragmentSignature {
|
||||
/**
|
||||
* ASM fragment signature for a stand-alone expression with a side-effect.
|
||||
*/
|
||||
class ExprSideEffect implements AsmFragmentSignature {
|
||||
class ExprSideEffect extends AsmFragmentSignatureBase {
|
||||
|
||||
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -14,7 +15,7 @@ public class AsmFragmentSynthesis {
|
||||
/**
|
||||
* 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
|
||||
@ -41,7 +42,7 @@ public class AsmFragmentSynthesis {
|
||||
*
|
||||
* @param signature The signature of the fragment template to load/synthesize
|
||||
*/
|
||||
AsmFragmentSynthesis(String signature) {
|
||||
AsmFragmentSynthesis(AsmFragmentSignature signature) {
|
||||
this.signature = signature;
|
||||
this.bestTemplates = new LinkedHashMap<>();
|
||||
this.synthesisOptions = new LinkedHashSet<>();
|
||||
@ -163,7 +164,7 @@ public class AsmFragmentSynthesis {
|
||||
return bestTemplates.values();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
public AsmFragmentSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.fragment.synthesis;
|
||||
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
|
||||
import java.util.List;
|
||||
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.
|
||||
*/
|
||||
private final String signature;
|
||||
private final AsmFragmentSignature signature;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -29,17 +31,17 @@ public class AsmFragmentSynthesisOption {
|
||||
* @param signature the signature of the fragment template being synthesized.
|
||||
* @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.rule = rule;
|
||||
this.subSignatures = rule.getSubSignatures(signature);
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
public AsmFragmentSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
List<String> getSubSignatures() {
|
||||
List<AsmFragmentSignature> getSubSignatures() {
|
||||
return subSignatures;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.fragment.synthesis;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -18,20 +19,20 @@ public class AsmFragmentSynthesisResult {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private boolean cache;
|
||||
private final boolean cache;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private List<AsmFragmentSynthesisResult> subFragments;
|
||||
private final List<AsmFragmentSynthesisResult> subFragments;
|
||||
|
||||
public AsmFragmentSynthesisResult(AsmFragmentTemplate fragment, boolean file, boolean cache, AsmFragmentTemplateSynthesisRule synthesis, List<AsmFragmentSynthesisResult> subFragments) {
|
||||
this.fragment = fragment;
|
||||
@ -92,7 +93,7 @@ public class AsmFragmentSynthesisResult {
|
||||
return fragment.getBody();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
public AsmFragmentSignature getSignature() {
|
||||
return fragment.getSignature();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.fragment.synthesis;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -15,7 +16,7 @@ public interface AsmFragmentTemplateSynthesisRule {
|
||||
* @param signature The fragment template 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
|
||||
@ -23,7 +24,7 @@ public interface AsmFragmentTemplateSynthesisRule {
|
||||
* @param signature The signature of the fragment to synthesize
|
||||
* @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.
|
||||
@ -33,5 +34,5 @@ public interface AsmFragmentTemplateSynthesisRule {
|
||||
* @return The synthesized ASM fragment template.
|
||||
* 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;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
@ -71,39 +72,42 @@ class AsmFragmentTemplateSynthesisRuleRegex implements AsmFragmentTemplateSynthe
|
||||
* @param signature The fragment template 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)
|
||||
sigMatchPattern = Pattern.compile(sigMatch);
|
||||
Matcher m = sigMatchPattern.matcher(signature);
|
||||
Matcher m = sigMatchPattern.matcher(signatureText);
|
||||
if(m.matches()) {
|
||||
if(sigAvoid == null)
|
||||
return true;
|
||||
else {
|
||||
if(sigAvoidPattern == null)
|
||||
sigAvoidPattern = Pattern.compile(sigAvoid);
|
||||
Matcher ma = sigAvoidPattern.matcher(signature);
|
||||
Matcher ma = sigAvoidPattern.matcher(signatureText);
|
||||
return !ma.matches();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String> getSubSignatures(String signature) {
|
||||
public List<AsmFragmentSignature> getSubSignatures(AsmFragmentSignature 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) {
|
||||
// When mapping the signature we do the map replacement in the signature
|
||||
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 {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AsmFragmentTemplate synthesize(String signature, List<AsmFragmentTemplate> subTemplates) {
|
||||
public AsmFragmentTemplate synthesize(AsmFragmentSignature signature, List<AsmFragmentTemplate> subTemplates) {
|
||||
|
||||
final AsmFragmentTemplate subTemplate = subTemplates.get(0);
|
||||
// if(!matches(signature)) {
|
||||
// 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.fragment.*;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.model.TargetCpu;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
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
|
||||
* 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. */
|
||||
void finalize(CompileLog log) {
|
||||
@ -73,7 +74,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
}
|
||||
|
||||
public AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
|
||||
String signature = instanceSpec.getSignature();
|
||||
AsmFragmentSignature signature = instanceSpec.getSignature();
|
||||
AsmFragmentTemplate fragmentTemplate = getFragmentTemplate(signature, log);
|
||||
// Return the resulting fragment instance
|
||||
return new AsmFragmentInstance(
|
||||
@ -91,14 +92,14 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param log The log
|
||||
* @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
|
||||
AsmFragmentTemplate bestTemplate = fragmentCache.get(signature);
|
||||
if (bestTemplate == AsmFragmentTemplateCache.NO_SYNTHESIS) {
|
||||
if (log.isVerboseFragmentLog()) {
|
||||
log.append("Unknown fragment " + signature);
|
||||
}
|
||||
throw new UnknownFragmentException(signature);
|
||||
throw new UnknownFragmentException(signature.getName());
|
||||
}
|
||||
if (bestTemplate != null) {
|
||||
AsmFragmentTemplateUsages.incUsage(new AsmFragmentSynthesisResult(bestTemplate, false, true, null, new ArrayList<>()));
|
||||
@ -144,7 +145,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param log The compile log
|
||||
* @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);
|
||||
updateBestTemplates(log);
|
||||
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
||||
@ -159,7 +160,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
*
|
||||
* @return The entire synthesis graph
|
||||
*/
|
||||
public Map<String, AsmFragmentSynthesis> getSynthesisGraph() {
|
||||
public Map<AsmFragmentSignature, AsmFragmentSynthesis> getSynthesisGraph() {
|
||||
return synthesisGraph;
|
||||
}
|
||||
|
||||
@ -171,7 +172,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @return The synthesis used to synthesize the fragment template.
|
||||
* null if the synthesis graph does not contain the synthesis.
|
||||
*/
|
||||
private AsmFragmentSynthesis getSynthesis(String signature) {
|
||||
private AsmFragmentSynthesis getSynthesis(AsmFragmentSignature signature) {
|
||||
return synthesisGraph.get(signature);
|
||||
}
|
||||
|
||||
@ -184,7 +185,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param log The compile log
|
||||
* @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);
|
||||
if (synthesis != null) {
|
||||
return synthesis;
|
||||
@ -210,13 +211,13 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
AsmFragmentSynthesisOption synthesisOption = new AsmFragmentSynthesisOption(signature, rule);
|
||||
synthesis.addSynthesisOption(synthesisOption);
|
||||
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
|
||||
for (AsmFragmentSynthesisOption synthesisOption : synthesis.getSynthesisOptions()) {
|
||||
for (String subSignature : synthesisOption.getSubSignatures()) {
|
||||
for (AsmFragmentSignature subSignature : synthesisOption.getSubSignatures()) {
|
||||
AsmFragmentSynthesis subSynthesis = getOrCreateSynthesis(subSignature, log);
|
||||
subSynthesis.addParentOption(synthesisOption);
|
||||
}
|
||||
@ -256,7 +257,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
for (AsmFragmentSynthesisOption synthesisOption : synthesisOptions) {
|
||||
// for each sub-signature find the best templates
|
||||
List<Collection<AsmFragmentSynthesisResult>> subSignatureTemplates = new ArrayList<>();
|
||||
for (String subSignature : synthesisOption.getSubSignatures()) {
|
||||
for (AsmFragmentSignature subSignature : synthesisOption.getSubSignatures()) {
|
||||
AsmFragmentSynthesis subSynthesis = getSynthesis(subSignature);
|
||||
if (subSynthesis == null) {
|
||||
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);
|
||||
if (synthesize != null) {
|
||||
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);
|
||||
modified |= synthesis.bestTemplateCandidate(synthesisResult);
|
||||
} else {
|
||||
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) {
|
||||
// The synthesis was modified - update all parents later
|
||||
for (AsmFragmentSynthesisOption parentOption : synthesis.getParentOptions()) {
|
||||
String parentSignature = parentOption.getSignature();
|
||||
AsmFragmentSignature parentSignature = parentOption.getSignature();
|
||||
AsmFragmentSynthesis parentSynthesis = getSynthesis(parentSignature);
|
||||
if (parentSynthesis == null) {
|
||||
throw new RuntimeException("Synthesis Graph Error! Parent synthesis not found in graph " + parentSignature);
|
||||
@ -341,7 +342,7 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param signature The signature
|
||||
* @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<>();
|
||||
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
|
||||
for (TargetCpu.Feature cpuFeature : cpuFeatures) {
|
||||
@ -359,9 +360,11 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
* @param fragmentFolder The folder to look in
|
||||
* @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 {
|
||||
File fragmentFile = fragmentFolder.resolve(signature + ".asm").toFile();
|
||||
File fragmentFile = fragmentFolder.resolve(signatureText + ".asm").toFile();
|
||||
if (!fragmentFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
@ -407,6 +410,10 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
|
||||
private final String signature;
|
||||
|
||||
public UnknownFragmentException(AsmFragmentSignature signature) {
|
||||
this(signature.getName());
|
||||
}
|
||||
|
||||
public UnknownFragmentException(String signature) {
|
||||
super("Fragment not found " + signature);
|
||||
this.signature = signature;
|
||||
|
@ -4,6 +4,7 @@ import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.fragment.*;
|
||||
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
|
||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
@ -893,7 +894,13 @@ public class Pass4CodeGeneration {
|
||||
} else if (statement instanceof StatementAsm) {
|
||||
StatementAsm statementAsm = (StatementAsm) statement;
|
||||
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);
|
||||
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 procedure The interrupt procedure
|
||||
@ -933,10 +940,10 @@ public class Pass4CodeGeneration {
|
||||
String entryName;
|
||||
if (interruptType.contains("clobber")) {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType.replace("clobber", "all"), program);
|
||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
||||
entryName = entryFragment.getSignature().getName().replace("all", "clobber");
|
||||
} else {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptEntry(interruptType, program);
|
||||
entryName = entryFragment.getSignature();
|
||||
entryName = entryFragment.getSignature().getName();
|
||||
}
|
||||
try {
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||
@ -958,10 +965,10 @@ public class Pass4CodeGeneration {
|
||||
String entryName;
|
||||
if (interruptType.contains("clobber")) {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType.replace("clobber", "all"), program);
|
||||
entryName = entryFragment.getSignature().replace("all", "clobber");
|
||||
entryName = entryFragment.getSignature().getName().replace("all", "clobber");
|
||||
} else {
|
||||
entryFragment = AsmFragmentInstanceSpecBuilder.interruptExit(interruptType, program);
|
||||
entryName = entryFragment.getSignature();
|
||||
entryName = entryFragment.getSignature().getName();
|
||||
}
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||
try {
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
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.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.model.TargetCpu;
|
||||
@ -35,7 +36,7 @@ public class TestFragments {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSynthesis() throws IOException {
|
||||
public void testSynthesis() {
|
||||
testFragmentExists("pbuz1=pbuz2_plus_pwuc1_derefidx_vbuxx");
|
||||
}
|
||||
|
||||
@ -189,9 +190,10 @@ public class TestFragments {
|
||||
/**
|
||||
* 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();
|
||||
asmFragmentTemplateSynthesizer = new AsmFragmentTemplateSynthesizer(TargetCpu.MOS6502X, new File("src/main/fragment/").toPath(), false, new CompileLog());
|
||||
log.setSysOut(true);
|
||||
@ -225,17 +227,18 @@ public class TestFragments {
|
||||
if((testStep % 100) == 0)
|
||||
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 =
|
||||
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
||||
Collections.sort(templates, Comparator.comparing(AsmFragmentSynthesisResult::getClobber));
|
||||
templates.sort(Comparator.comparing(AsmFragmentSynthesisResult::getClobber));
|
||||
if(templates.size() == 0) {
|
||||
log.append("CANNOT SYNTHESIZE " + signature);
|
||||
}
|
||||
|
||||
for(AsmFragmentSynthesisResult template : templates) {
|
||||
String prefix = "";
|
||||
String prefix;
|
||||
if(template.isCache()) {
|
||||
prefix = "cached ";
|
||||
} else if(template.isFile()) {
|
||||
@ -328,8 +331,7 @@ public class TestFragments {
|
||||
|
||||
|
||||
private Collection<Value> lValuesBu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesVbu(usedValues));
|
||||
ArrayList<Value> values = new ArrayList<>(lValuesVbu(usedValues));
|
||||
Collection<Value> pbus = rValuesPbu(usedValues);
|
||||
for(Value pbu : pbus) {
|
||||
values.add(new Value("_deref_" + pbu.getSignature(), pbu));
|
||||
@ -347,8 +349,7 @@ public class TestFragments {
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesBu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesBu(usedValues));
|
||||
ArrayList<Value> values = new ArrayList<>(lValuesBu(usedValues));
|
||||
values.add(new Value("vbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
values.add(new Value("vbuc2"));
|
||||
@ -393,8 +394,7 @@ public class TestFragments {
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesVbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesVbu(usedValues));
|
||||
ArrayList<Value> values = new ArrayList<>(lValuesVbu(usedValues));
|
||||
values.add(new Value("vbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
values.add(new Value("vbuc2"));
|
||||
@ -437,8 +437,7 @@ public class TestFragments {
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesPbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesPbu(usedValues));
|
||||
ArrayList<Value> values = new ArrayList<>(lValuesPbu(usedValues));
|
||||
values.add(new Value("pbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
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 */
|
||||
public static class Value {
|
||||
|
||||
private String signature;
|
||||
private final String signature;
|
||||
|
||||
private Collection<Value> subValues;
|
||||
private final Collection<Value> subValues;
|
||||
|
||||
public Value(String signature) {
|
||||
this(signature, new ArrayList<Value>());
|
||||
this(signature, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Value(String signature, Collection<Value> subValues) {
|
||||
@ -484,7 +483,7 @@ public class TestFragments {
|
||||
}
|
||||
|
||||
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