1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Fixed infinite recursion

This commit is contained in:
jespergravgaard 2017-11-24 23:49:36 +01:00
parent 0efe62585b
commit 96f2610d25
3 changed files with 54 additions and 29 deletions

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.fragment; package dk.camelot64.kickc.fragment;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCLexer;
import dk.camelot64.kickc.parser.KickCParser; import dk.camelot64.kickc.parser.KickCParser;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
@ -19,6 +20,8 @@ import java.util.regex.Pattern;
*/ */
public class AsmFragmentManager { public class AsmFragmentManager {
static boolean verboseFragmentLog = false;
/** /**
* Cache for fragment files. Maps signature to the parsed file. * 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); private static KickCParser.AsmFileContext UNKNOWN = new KickCParser.AsmFileContext(null, 0);
public static AsmFragment getFragment(AsmFragmentSignature signature) { public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature()); KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature(), log);
AsmFragment fragment = new AsmFragment( AsmFragment fragment = new AsmFragment(
signature.getProgram(), signature.getProgram(),
signature.getSignature(), signature.getSignature(),
@ -37,14 +40,20 @@ public class AsmFragmentManager {
return fragment; return fragment;
} }
private static KickCParser.AsmFileContext getFragmentFile(String signature) { private static KickCParser.AsmFileContext getFragmentFile(String signature, CompileLog log) {
KickCParser.AsmFileContext fragment = fragmentFileCache.get(signature); KickCParser.AsmFileContext fragment = fragmentFileCache.get(signature);
if (fragment == UNKNOWN) { if (fragment == UNKNOWN) {
if (verboseFragmentLog) {
log.append("Unknown fragment " + signature);
}
throw new UnknownFragmentException(signature); throw new UnknownFragmentException(signature);
} }
if (fragment == null) { if (fragment == null) {
CharStream fragmentCharStream = loadOrSynthesizeFragment(signature); CharStream fragmentCharStream = loadOrSynthesizeFragment(signature, log);
if (fragmentCharStream == null) { if (fragmentCharStream == null) {
if (verboseFragmentLog) {
log.append("Unknown fragment " + signature);
}
fragmentFileCache.put(signature, UNKNOWN); fragmentFileCache.put(signature, UNKNOWN);
throw new UnknownFragmentException(signature); throw new UnknownFragmentException(signature);
} }
@ -54,10 +63,17 @@ public class AsmFragmentManager {
return fragment; return fragment;
} }
private static CharStream loadOrSynthesizeFragment(String signature) { private static CharStream loadOrSynthesizeFragment(String signature, CompileLog log) {
CharStream fragmentCharStream = loadFragment(signature); CharStream fragmentCharStream = loadFragment(signature);
if (fragmentCharStream == null) { 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; return fragmentCharStream;
} }
@ -68,7 +84,7 @@ public class AsmFragmentManager {
* @param signature The signature of the fragment to synthesize * @param signature The signature of the fragment to synthesize
* @return The synthesized fragment file contents. Null if the fragment could not be synthesized. * @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<String, String> mapZpsby = new LinkedHashMap<>(); Map<String, String> mapZpsby = new LinkedHashMap<>();
mapZpsby.put("zpsby2", "zpsby1"); 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("(.*)=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("(.*)=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_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("(.*)=(.*)_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", "txa\n", "$1=$2_asby", 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", "tya\n", "$1=$2_aby", 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", "tya\n", "$1=$2_asby", 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("(.*)=(.*)_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)); 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("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("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_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_(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_(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)); 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)); synths.add(new FragmentSynthesis("(.*)_eq_(ys?by)_then_(.*)", ".*[axy]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
for (FragmentSynthesis synth : synths) { for (FragmentSynthesis synth : synths) {
CharStream synthesized = synth.synthesize(signature); CharStream synthesized = synth.synthesize(signature, log);
if(synthesized!=null) { if (synthesized != null) {
if (verboseFragmentLog) {
log.append("Succesfully synthesized fragment " + signature + " (from " + synth.getSubSignature() + ")");
}
return synthesized; 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 static class FragmentSynthesis {
private String sigMatch; private String sigMatch;
@ -165,6 +186,7 @@ public class AsmFragmentManager {
private String sigReplace; private String sigReplace;
private String asmPostfix; private String asmPostfix;
private Map<String, String> bindMappings; private Map<String, String> bindMappings;
private String subSignature;
public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map<String, String> bindMappings) { public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map<String, String> bindMappings) {
this.sigMatch = sigMatch; this.sigMatch = sigMatch;
@ -175,23 +197,23 @@ public class AsmFragmentManager {
this.bindMappings = bindMappings; this.bindMappings = bindMappings;
} }
public CharStream synthesize(String signature) { public CharStream synthesize(String signature, CompileLog log) {
if (signature.matches(sigMatch) ) { if (signature.matches(sigMatch)) {
if (sigAvoid == null || !signature.matches(sigAvoid)) { if (sigAvoid == null || !signature.matches(sigAvoid)) {
String subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace); subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
if(bindMappings!=null) { if (bindMappings != null) {
for (String bound : bindMappings.keySet()) { for (String bound : bindMappings.keySet()) {
subSignature = subSignature.replace(bound, bindMappings.get(bound)); subSignature = subSignature.replace(bound, bindMappings.get(bound));
} }
} }
CharStream subCharStream = loadOrSynthesizeFragment(subSignature); CharStream subCharStream = loadOrSynthesizeFragment(subSignature, log);
if (subCharStream != null) { if (subCharStream != null) {
StringBuilder newFragment = new StringBuilder(); StringBuilder newFragment = new StringBuilder();
if(asmPrefix!=null) { if (asmPrefix != null) {
newFragment.append(asmPrefix); newFragment.append(asmPrefix);
} }
String subFragment = subCharStream.toString(); String subFragment = subCharStream.toString();
if(bindMappings!=null) { if (bindMappings != null) {
List<String> reverse = new ArrayList<>(bindMappings.keySet()); List<String> reverse = new ArrayList<>(bindMappings.keySet());
Collections.reverse(reverse); Collections.reverse(reverse);
for (String bound : reverse) { for (String bound : reverse) {
@ -199,7 +221,7 @@ public class AsmFragmentManager {
} }
} }
newFragment.append(subFragment); newFragment.append(subFragment);
if(asmPostfix!=null) { if (asmPostfix != null) {
newFragment.append("\n"); newFragment.append("\n");
newFragment.append(asmPostfix); newFragment.append(asmPostfix);
} }
@ -210,6 +232,9 @@ public class AsmFragmentManager {
return null; return null;
} }
public String getSubSignature() {
return subSignature;
}
} }

View File

@ -205,7 +205,7 @@ public class Pass4CodeGeneration {
} }
StatementAssignment assignment = (StatementAssignment) statement; StatementAssignment assignment = (StatementAssignment) statement;
AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program); AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program);
AsmFragment asmFragment = AsmFragmentManager.getFragment(signature); AsmFragment asmFragment = AsmFragmentManager.getFragment(signature, program.getLog());
asm.getCurrentSegment().setFragment(asmFragment.getName()); asm.getCurrentSegment().setFragment(asmFragment.getName());
asmFragment.generate(asm); asmFragment.generate(asm);
aluState.clear(); aluState.clear();
@ -232,14 +232,14 @@ public class Pass4CodeGeneration {
asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue)); asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
} else { } else {
AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program); AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program);
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature); AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature, program.getLog());
asm.getCurrentSegment().setFragment(asmFragment.getName()); asm.getCurrentSegment().setFragment(asmFragment.getName());
asmFragment.generate(asm); asmFragment.generate(asm);
} }
} }
} else if (statement instanceof StatementConditionalJump) { } else if (statement instanceof StatementConditionalJump) {
AsmFragmentSignature asmSignature = new AsmFragmentSignature((StatementConditionalJump) statement, block, program, getGraph()); 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()); asm.getCurrentSegment().setFragment(asmFragment.getName());
asmFragment.generate(asm); asmFragment.generate(asm);
} else if (statement instanceof StatementCall) { } else if (statement instanceof StatementCall) {
@ -349,7 +349,7 @@ public class Pass4CodeGeneration {
asm.getCurrentSegment().setFragment("register_copy"); asm.getCurrentSegment().setFragment("register_copy");
} else { } else {
AsmFragmentSignature asmSignature = new AsmFragmentSignature(lValue, rValue, program, scope); 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()); asm.getCurrentSegment().setFragment(asmFragment.getName());
asmFragment.generate(asm); asmFragment.generate(asm);
} }

View File

@ -3,7 +3,7 @@ byte* SCREEN2 = $0600;
void main() { void main() {
for( byte b: 0..100) { for( byte b: 0..100) {
byte b2 = 100-b; byte b2 = 100-b; // Subtract byte from byte (not signed)
SCREEN2[b] = b2; SCREEN2[b] = b2;
signed byte sb = - (signed byte)b; signed byte sb = - (signed byte)b;
SCREEN[b] = (byte)sb; SCREEN[b] = (byte)sb;