diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java index 9ecdcf26a..d78c46e87 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java @@ -1,5 +1,6 @@ package dk.camelot64.kickc.fragment; +import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCParser; import org.antlr.v4.runtime.*; @@ -19,6 +20,8 @@ import java.util.regex.Pattern; */ public class AsmFragmentManager { + static boolean verboseFragmentLog = false; + /** * Cache for fragment files. Maps signature to the parsed file. */ @@ -26,8 +29,8 @@ public class AsmFragmentManager { private static KickCParser.AsmFileContext UNKNOWN = new KickCParser.AsmFileContext(null, 0); - public static AsmFragment getFragment(AsmFragmentSignature signature) { - KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature()); + public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) { + KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature(), log); AsmFragment fragment = new AsmFragment( signature.getProgram(), signature.getSignature(), @@ -37,14 +40,20 @@ public class AsmFragmentManager { return fragment; } - private static KickCParser.AsmFileContext getFragmentFile(String signature) { + private static KickCParser.AsmFileContext getFragmentFile(String signature, CompileLog log) { KickCParser.AsmFileContext fragment = fragmentFileCache.get(signature); if (fragment == UNKNOWN) { + if (verboseFragmentLog) { + log.append("Unknown fragment " + signature); + } throw new UnknownFragmentException(signature); } if (fragment == null) { - CharStream fragmentCharStream = loadOrSynthesizeFragment(signature); + CharStream fragmentCharStream = loadOrSynthesizeFragment(signature, log); if (fragmentCharStream == null) { + if (verboseFragmentLog) { + log.append("Unknown fragment " + signature); + } fragmentFileCache.put(signature, UNKNOWN); throw new UnknownFragmentException(signature); } @@ -54,10 +63,17 @@ public class AsmFragmentManager { return fragment; } - private static CharStream loadOrSynthesizeFragment(String signature) { + private static CharStream loadOrSynthesizeFragment(String signature, CompileLog log) { CharStream fragmentCharStream = loadFragment(signature); if (fragmentCharStream == null) { - fragmentCharStream = synthesizeFragment(signature); + if (verboseFragmentLog) { + log.append("Attempting fragment synthesis " + signature); + } + fragmentCharStream = synthesizeFragment(signature, log); + } else { + if (verboseFragmentLog) { + log.append("Succesfully loaded fragment " + signature); + } } return fragmentCharStream; } @@ -68,7 +84,7 @@ public class AsmFragmentManager { * @param signature The signature of the fragment to synthesize * @return The synthesized fragment file contents. Null if the fragment could not be synthesized. */ - private static CharStream synthesizeFragment(String signature) { + private static CharStream synthesizeFragment(String signature, CompileLog log) { Map mapZpsby = new LinkedHashMap<>(); mapZpsby.put("zpsby2", "zpsby1"); @@ -105,12 +121,12 @@ public class AsmFragmentManager { synths.add(new FragmentSynthesis("(.*)=zpby1(.*)", ".*=.*as?by.*|zpby1=.*", "lda {zpby1}\n", "$1=aby$2", null, mapZpby)); synths.add(new FragmentSynthesis("(.*)=zpsby1(.*)", ".*=.*as?by.*|zpsby1=.*", "lda {zpsby1}\n", "$1=aby$2", null, mapZpsby)); synths.add(new FragmentSynthesis("(.*)=_deref_cowo1(.*)", ".*=.*as?by.*", "lda {cowo1}\n", "$1=aby$2", null, mapConst)); - synths.add(new FragmentSynthesis("(.*)=_deref_zpptrby1(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n"+"lda ({zpptrby1}),y\n", "$1=aby$2", null, mapZpptrby)); + synths.add(new FragmentSynthesis("(.*)=_deref_zpptrby1(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n" + "lda ({zpptrby1}),y\n", "$1=aby$2", null, mapZpptrby)); - synths.add(new FragmentSynthesis("(.*)=(.*)_xby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_aby", null, null)); - synths.add(new FragmentSynthesis("(.*)=(.*)_xsby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_asby", null, null)); - synths.add(new FragmentSynthesis("(.*)=(.*)_yby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_aby", null, null)); - synths.add(new FragmentSynthesis("(.*)=(.*)_ysby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_asby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_xby", ".*=[ax]s?by.*xs?by|.*derefidx_xs?by", "txa\n", "$1=$2_aby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_xsby", ".*=[ax]s?by.*xs?by|.*derefidx_xs?by", "txa\n", "$1=$2_asby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_yby", ".*=[ay]s?by.*ys?by|.*derefidx_ys?by", "tya\n", "$1=$2_aby", null, null)); + synths.add(new FragmentSynthesis("(.*)=(.*)_ysby", ".*=[ay]s?by.*ys?by|.*derefidx_ys?by", "tya\n", "$1=$2_asby", null, null)); synths.add(new FragmentSynthesis("(.*)=(.*)_zpby1", ".*=.*as?by.*", "lda {zpby1}\n", "$1=$2_aby", null, mapZpby)); synths.add(new FragmentSynthesis("(.*)=(.*)_zpsby1", ".*=.*as?by.*", "lda {zpsby1}\n", "$1=$2_asby", null, mapZpsby)); @@ -125,7 +141,7 @@ public class AsmFragmentManager { synths.add(new FragmentSynthesis("zpby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpby1}\n", "aby_$1_$2", null, mapZpby)); synths.add(new FragmentSynthesis("zpsby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpsby1}\n", "asby_$1_$2", null, mapZpsby)); synths.add(new FragmentSynthesis("_deref_cowo1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {cowo1}\n", "aby_$1_$2", null, mapConst)); - synths.add(new FragmentSynthesis("_deref_zpptrby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n"+"lda ({zpptrby1}),y\n", "aby_$1_$2", null, mapZpptrby)); + synths.add(new FragmentSynthesis("_deref_zpptrby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n" + "lda ({zpptrby1}),y\n", "aby_$1_$2", null, mapZpptrby)); synths.add(new FragmentSynthesis("(.*)_ge_(as?by)_then_(.*)", ".*[a]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null)); synths.add(new FragmentSynthesis("(.*)_ge_(xs?by)_then_(.*)", ".*[ax]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null)); synths.add(new FragmentSynthesis("(.*)_ge_(ys?by)_then_(.*)", ".*[axy]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null)); @@ -146,8 +162,11 @@ public class AsmFragmentManager { synths.add(new FragmentSynthesis("(.*)_eq_(ys?by)_then_(.*)", ".*[axy]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null)); for (FragmentSynthesis synth : synths) { - CharStream synthesized = synth.synthesize(signature); - if(synthesized!=null) { + CharStream synthesized = synth.synthesize(signature, log); + if (synthesized != null) { + if (verboseFragmentLog) { + log.append("Succesfully synthesized fragment " + signature + " (from " + synth.getSubSignature() + ")"); + } return synthesized; } } @@ -156,7 +175,9 @@ public class AsmFragmentManager { } - /** AsmFragment synthesis based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings*/ + /** + * AsmFragment synthesis based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings + */ private static class FragmentSynthesis { private String sigMatch; @@ -165,6 +186,7 @@ public class AsmFragmentManager { private String sigReplace; private String asmPostfix; private Map bindMappings; + private String subSignature; public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings) { this.sigMatch = sigMatch; @@ -175,23 +197,23 @@ public class AsmFragmentManager { this.bindMappings = bindMappings; } - public CharStream synthesize(String signature) { - if (signature.matches(sigMatch) ) { + public CharStream synthesize(String signature, CompileLog log) { + if (signature.matches(sigMatch)) { if (sigAvoid == null || !signature.matches(sigAvoid)) { - String subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace); - if(bindMappings!=null) { + subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace); + if (bindMappings != null) { for (String bound : bindMappings.keySet()) { subSignature = subSignature.replace(bound, bindMappings.get(bound)); } } - CharStream subCharStream = loadOrSynthesizeFragment(subSignature); + CharStream subCharStream = loadOrSynthesizeFragment(subSignature, log); if (subCharStream != null) { StringBuilder newFragment = new StringBuilder(); - if(asmPrefix!=null) { + if (asmPrefix != null) { newFragment.append(asmPrefix); } String subFragment = subCharStream.toString(); - if(bindMappings!=null) { + if (bindMappings != null) { List reverse = new ArrayList<>(bindMappings.keySet()); Collections.reverse(reverse); for (String bound : reverse) { @@ -199,7 +221,7 @@ public class AsmFragmentManager { } } newFragment.append(subFragment); - if(asmPostfix!=null) { + if (asmPostfix != null) { newFragment.append("\n"); newFragment.append(asmPostfix); } @@ -210,6 +232,9 @@ public class AsmFragmentManager { return null; } + public String getSubSignature() { + return subSignature; + } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 456d2cf38..603b03ceb 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -205,7 +205,7 @@ public class Pass4CodeGeneration { } StatementAssignment assignment = (StatementAssignment) statement; AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program); - AsmFragment asmFragment = AsmFragmentManager.getFragment(signature); + AsmFragment asmFragment = AsmFragmentManager.getFragment(signature, program.getLog()); asm.getCurrentSegment().setFragment(asmFragment.getName()); asmFragment.generate(asm); aluState.clear(); @@ -232,14 +232,14 @@ public class Pass4CodeGeneration { asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue)); } else { AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program); - AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature); + AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature, program.getLog()); asm.getCurrentSegment().setFragment(asmFragment.getName()); asmFragment.generate(asm); } } } else if (statement instanceof StatementConditionalJump) { AsmFragmentSignature asmSignature = new AsmFragmentSignature((StatementConditionalJump) statement, block, program, getGraph()); - AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature); + AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog()); asm.getCurrentSegment().setFragment(asmFragment.getName()); asmFragment.generate(asm); } else if (statement instanceof StatementCall) { @@ -349,7 +349,7 @@ public class Pass4CodeGeneration { asm.getCurrentSegment().setFragment("register_copy"); } else { AsmFragmentSignature asmSignature = new AsmFragmentSignature(lValue, rValue, program, scope); - AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature); + AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog()); asm.getCurrentSegment().setFragment(asmFragment.getName()); asmFragment.generate(asm); } diff --git a/src/main/java/dk/camelot64/kickc/test/casting.kc b/src/main/java/dk/camelot64/kickc/test/casting.kc index c6e6e7c33..007e3336e 100644 --- a/src/main/java/dk/camelot64/kickc/test/casting.kc +++ b/src/main/java/dk/camelot64/kickc/test/casting.kc @@ -3,7 +3,7 @@ byte* SCREEN2 = $0600; void main() { for( byte b: 0..100) { - byte b2 = 100-b; + byte b2 = 100-b; // Subtract byte from byte (not signed) SCREEN2[b] = b2; signed byte sb = - (signed byte)b; SCREEN[b] = (byte)sb;