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

Implemented fragment tests - first for assignment to unsigned bytes.

This commit is contained in:
jespergravgaard 2018-01-07 11:42:46 +01:00
parent a047fedebf
commit a6e75ffcb0
11 changed files with 192060 additions and 7 deletions

View File

@ -35,7 +35,7 @@ public class CompileLog {
/**
* Should the log be output to System.out while being built
*/
private boolean sysOut = true;
private boolean sysOut = false;
public CompileLog() {
this.log = new StringBuilder();

View File

@ -66,7 +66,7 @@ public class AsmFragmentInstance {
}
if(boundValue == null) {
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name + ".asm");
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name );
}
if(boundValue instanceof Variable) {
Variable boundVar = (Variable) boundValue;

View File

@ -379,7 +379,7 @@ class AsmFragmentTemplateSynthesisRule {
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x", mapC, "xx"));
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y", mapZ2));
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}", "$1=vb$2aa$3", null, mapC));
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1}", "$1=vb$2aa$3", null, mapC));
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*yy.*", "ldy #0\n" + "lda ({z1}),y", "$1=vb$2aa$3", null, mapZ));
// Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )

View File

@ -43,7 +43,12 @@ public class AsmFragmentTemplateSynthesizer {
/** Special singleton representing that the fragment can not be synthesized or loaded. */
private AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
public static AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
public static void clearCaches() {
SYNTHESIZER = new AsmFragmentTemplateSynthesizer();
}
public static AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
String signature = instanceSpec.getSignature();
AsmFragmentTemplate fragmentTemplate = SYNTHESIZER.getFragmentTemplate(signature, log);
// Return the resulting fragment instance

View File

@ -10,7 +10,7 @@ public class Operator {
public static final Operator POS = new Operator("+", "_pos_", Type.UNARY, 2);
public static final Operator NEG = new Operator("-", "_neg_", Type.UNARY, 2);
public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2);
public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2);
public static final Operator LOGIC_NOT = new Operator("!", "_not_", Type.UNARY, 2);
public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2);
public static final Operator WORD = new Operator("w=", "_word_", Type.BINARY, 2);
public static final Operator DEREF_IDX = new Operator("*idx", "_derefidx_", Type.BINARY, 2);
@ -109,7 +109,7 @@ public class Operator {
case "--":
return DECREMENT;
case "!":
return NOT;
return LOGIC_NOT;
case "~":
return BOOL_NOT;
case "*":

View File

@ -227,7 +227,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
PrePostModifierHandler.addPreModifiers(this, ctx.expr());
RValue rValue = (RValue) this.visit(ctx.expr());
VariableRef notExprVar = getCurrentSymbols().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(notExprVar, null, Operator.NOT, rValue));
sequence.addStatement(new StatementAssignment(notExprVar, null, Operator.LOGIC_NOT, rValue));
PrePostModifierHandler.addPostModifiers(this, ctx.expr());
Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate();

View File

@ -0,0 +1,313 @@
package dk.camelot64.kickc.test;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
import dk.camelot64.kickc.model.Operator;
import org.junit.AfterClass;
import org.junit.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static junit.framework.TestCase.fail;
/** Test the ASM fragment sub-system by loading/synthesizing a lot of different fragments and comparing with reference fragments. */
public class TestFragments {
@AfterClass
public static void tearDown() throws Exception {
CompileLog log = new CompileLog();
log.setSysOut(true);
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
}
@Test
public void testAssignmentsBu() throws IOException, URISyntaxException {
testFragments("fragments-assignment-copy", assignmentsBu());
}
@Test
public void testAssignmentsUnaryBu() throws IOException, URISyntaxException {
testFragments("fragments-assignment-unary", assignmentsUnaryBu());
}
@Test
public void testAssignmentsBinaryBu() throws IOException, URISyntaxException {
testFragments("fragments-assignment-binary", assignmentsBinaryBu());
}
private void testFragments(String fileName, Collection<String> signatures) throws IOException, URISyntaxException {
CompileLog log = new CompileLog();
int cnt = 0;
for(String signature : signatures) {
if(++cnt % 1000 == 0) System.out.println(""+cnt+"/"+signatures.size());
Collection<AsmFragmentTemplate> templates =
AsmFragmentTemplateSynthesizer.getFragmentTemplates(signature, log);
if(templates.size() == 0) {
log.append("CANNOT SYNTHESIZE " + signature);
}
for(AsmFragmentTemplate template : templates) {
log.append((template.isFile() ? "*" : "") + template.getName() + " - clobber:" + template.getClobber().toString() + " cycles:" + template.getCycles());
log.append(" " + template.getBody().replace("\n", "\n "));
}
}
ReferenceHelper helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/");
boolean success = helper.testOutput(fileName, ".log", log.toString());
if(!success) {
fail("Output does not match reference!");
}
}
private Collection<String> assignmentsBu() {
ArrayList<String> signatures = new ArrayList<>();
Collection<Value> lVals = lValuesBu(new ArrayList<>());
for(Value lValue : lVals) {
Collection<Value> rVals = rValuesBu(lValue.getAllValues());
for(Value rValue : rVals) {
signatures.add(lValue.getSignature() + "=" + rValue.getSignature());
}
}
return signatures;
}
private Collection<String> assignmentsUnaryBu() {
ArrayList<String> signatures = new ArrayList<>();
Collection<Value> lVals = lValuesBu(new ArrayList<>());
for(Value lValue : lVals) {
Collection<Value> rVals = rValuesBu(lValue.getAllValues());
for(Value rValue : rVals) {
for(String unary : unaryBu()) {
signatures.add(lValue.getSignature() + "=" + unary + rValue.getSignature());
}
}
}
return signatures;
}
private Collection<String> assignmentsBinaryBu() {
ArrayList<String> signatures = new ArrayList<>();
Collection<Value> lVals = lValuesBu(new ArrayList<>());
for(Value lValue : lVals) {
Collection<Value> rVal1s = rValuesBu(lValue.getAllValues());
for(Value rVal1 : rVal1s) {
ArrayList<Value> used = new ArrayList<>();
used.addAll(lValue.getAllValues());
used.addAll(rVal1.getAllValues());
Collection<Value> rVal2s = rValuesBu(used);
for(Value rVal2 : rVal2s) {
for(String binary : binaryBu()) {
signatures.add(lValue.getSignature() + "=" + rVal1.getSignature() + binary + rVal2.getSignature());
}
}
}
}
return signatures;
}
private Collection<String> unaryBu() {
ArrayList<String> unaries = new ArrayList<>();
unaries.add(Operator.BOOL_NOT.getAsmOperator());
unaries.add(Operator.DECREMENT.getAsmOperator());
unaries.add(Operator.INCREMENT.getAsmOperator());
unaries.add(Operator.NEG.getAsmOperator());
unaries.add(Operator.POS.getAsmOperator());
return unaries;
}
private Collection<String> binaryBu() {
ArrayList<String> unaries = new ArrayList<>();
unaries.add(Operator.BOOL_AND.getAsmOperator());
unaries.add(Operator.BOOL_OR.getAsmOperator());
unaries.add(Operator.BOOL_XOR.getAsmOperator());
unaries.add(Operator.MINUS.getAsmOperator());
unaries.add(Operator.PLUS.getAsmOperator());
return unaries;
}
private Collection<Value> lValuesBu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.addAll(lValuesVbu(usedValues));
Collection<Value> pbus = rValuesPbu(usedValues);
for(Value pbu : pbus) {
values.add(new Value("_deref_" + pbu.getSignature(), pbu));
}
for(Value pbu : pbus) {
Collection<Value> used = new ArrayList<>();
used.addAll(usedValues);
used.addAll(pbu.getAllValues());
Collection<Value> idxs = rValuesVbu(used);
for(Value idx : idxs) {
values.add(new Value(pbu.getSignature() + "_derefidx_" + idx.getSignature(), Arrays.asList(pbu, idx)));
}
}
return values;
}
private Collection<Value> rValuesBu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.addAll(lValuesBu(usedValues));
values.add(new Value("vbuc1"));
if(contains(usedValues, "c1")) {
values.add(new Value("vbuc2"));
}
if(contains(usedValues, "c2")) {
values.add(new Value("vbuc3"));
}
if(contains(usedValues, "c3")) {
values.add(new Value("vbuc4"));
}
if(contains(usedValues, "c4")) {
values.add(new Value("vbuc5"));
}
if(contains(usedValues, "c5")) {
values.add(new Value("vbuc6"));
}
return values;
}
private Collection<Value> lValuesVbu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.add(new Value("vbuaa"));
values.add(new Value("vbuxx"));
values.add(new Value("vbuyy"));
values.add(new Value("vbuz1"));
if(contains(usedValues, "z1")) {
values.add(new Value("vbuz2"));
}
if(contains(usedValues, "z2")) {
values.add(new Value("vbuz3"));
}
if(contains(usedValues, "z3")) {
values.add(new Value("vbuz4"));
}
if(contains(usedValues, "z4")) {
values.add(new Value("vbuz5"));
}
if(contains(usedValues, "z5")) {
values.add(new Value("vbuz6"));
}
return values;
}
private Collection<Value> rValuesVbu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.addAll(lValuesVbu(usedValues));
values.add(new Value("vbuc1"));
if(contains(usedValues, "c1")) {
values.add(new Value("vbuc2"));
}
if(contains(usedValues, "c2")) {
values.add(new Value("vbuc3"));
}
if(contains(usedValues, "c3")) {
values.add(new Value("vbuc4"));
}
if(contains(usedValues, "c4")) {
values.add(new Value("vbuc5"));
}
if(contains(usedValues, "c5")) {
values.add(new Value("vbuc6"));
}
return values;
}
private Collection<Value> lValuesPbu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.add(new Value("pbuz1"));
if(contains(usedValues, "z1")) {
values.add(new Value("pbuz2"));
}
if(contains(usedValues, "z2")) {
values.add(new Value("pbuz3"));
}
if(contains(usedValues, "z3")) {
values.add(new Value("pbuz4"));
}
if(contains(usedValues, "z4")) {
values.add(new Value("pbuz5"));
}
if(contains(usedValues, "z5")) {
values.add(new Value("pbuz6"));
}
return values;
}
private Collection<Value> rValuesPbu(Collection<Value> usedValues) {
ArrayList<Value> values = new ArrayList<>();
values.addAll(lValuesPbu(usedValues));
values.add(new Value("pbuc1"));
if(contains(usedValues, "c1")) {
values.add(new Value("pbuc2"));
}
if(contains(usedValues, "c2")) {
values.add(new Value("pbuc3"));
}
if(contains(usedValues, "c3")) {
values.add(new Value("pbuc4"));
}
if(contains(usedValues, "c4")) {
values.add(new Value("pbuc5"));
}
if(contains(usedValues, "c5")) {
values.add(new Value("pbuc6"));
}
return values;
}
private boolean contains(Collection<Value> usedValues, String subString) {
for(Value usedValue : usedValues) {
if(usedValue.getSignature().contains(subString)) {
return true;
}
}
return false;
}
/** 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 Collection<Value> subValues;
public Value(String signature) {
this(signature, new ArrayList<Value>());
}
public Value(String signature, Collection<Value> subValues) {
this.signature = signature;
this.subValues = subValues;
}
public Value(String signature, Value subVal) {
this(signature, Arrays.asList(subVal));
}
public String getSignature() {
return signature;
}
public Collection<Value> getAllValues() {
ArrayList<Value> values = new ArrayList<>();
values.add(this);
if(subValues != null) {
values.addAll(subValues);
}
return values;
}
}
}

View File

@ -2,10 +2,12 @@ package dk.camelot64.kickc.test;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.Compiler;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
@ -28,6 +30,11 @@ public class TestPrograms {
helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/");
}
@BeforeClass
public static void setUp() {
AsmFragmentTemplateSynthesizer.clearCaches();
}
@AfterClass
public static void tearDown() throws Exception {
CompileLog log = new CompileLog();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff