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;
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<String, String> 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<String, String> bindMappings;
private String subSignature;
public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map<String, String> 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<String> 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;
}
}

View File

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

View File

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