diff --git a/src/main/fragment/pbuc1_le_pbuc2_then_la1.asm b/src/main/fragment/pbuc1_le_pbuc2_then_la1.asm new file mode 100644 index 000000000..5e5539006 --- /dev/null +++ b/src/main/fragment/pbuc1_le_pbuc2_then_la1.asm @@ -0,0 +1,8 @@ +lda #>{c1} +cmp #>{c2} +bne !+ +lda #<{c1} +cmp #<{c2} +beq {la1} +!: +bcc {la1} diff --git a/src/main/fragment/pssz1=pssz2.asm b/src/main/fragment/pssz1=pssz2.asm new file mode 100644 index 000000000..5b8ff5c26 --- /dev/null +++ b/src/main/fragment/pssz1=pssz2.asm @@ -0,0 +1,4 @@ +lda {z2} +sta {z1} +lda {z2}+1 +sta {z1}+1 diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index 59a8516ab..7ece14c02 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -1,12 +1,11 @@ package dk.camelot64.kickc.model; -import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * Cached information about which variables/constants are defined/referenced/used in which statements / blocks / symbols . @@ -24,11 +23,14 @@ public class VariableReferenceInfos { /** Variables used in each block. */ private Map> blockUsedVars; - /** Variables referenced in each statement. */ - private Map> stmtReferencedVars; + /** For each block this is the closure of all successor blocks. */ + private Map> blockSuccessorClosure; - /** Variables defined in each statement. */ - private Map> stmtDefinedVars; + /** References to variables/constants by block label. */ + private Map> blockVarReferences; + + /** References to variables/constants by statement index. */ + private Map> statementVarReferences; /** All references to symbol variables (constants/variables). References can be either statements or symbols in the symbol table */ private Map> symbolVarReferences; @@ -127,22 +129,30 @@ public class VariableReferenceInfos { public VariableReferenceInfos( Map> blockReferencedVars, Map> blockUsedVars, - Map> stmtReferencedVars, - Map> stmtDefinedVars, - Map> symbolVarReferences - + Map> blockSuccessorClosure, + Map> symbolVarReferences, + Map> blockVarReferences, + Map> statementVarReferences ) { this.blockReferencedVars = blockReferencedVars; this.blockUsedVars = blockUsedVars; - this.stmtDefinedVars = stmtDefinedVars; - this.stmtReferencedVars = stmtReferencedVars; + this.blockSuccessorClosure = blockSuccessorClosure; this.symbolVarReferences = symbolVarReferences; - + this.blockVarReferences = blockVarReferences; + this.statementVarReferences = statementVarReferences; } public String getSizeInfo() { StringBuilder sizeInfo = new StringBuilder(); - if(blockReferencedVars!=null) { + if(blockSuccessorClosure != null) { + sizeInfo.append("blockSuccessorClosure " + blockSuccessorClosure.size() + " labels "); + int sub = 0; + for(Collection labelRefs : blockSuccessorClosure.values()) { + sub += labelRefs.size(); + } + sizeInfo.append(" " + sub + " labels" + "\n"); + } + if(blockReferencedVars != null) { sizeInfo.append("blockReferencedVars " + blockReferencedVars.size() + " labels "); int sub = 0; for(Collection variableRefs : blockReferencedVars.values()) { @@ -150,7 +160,7 @@ public class VariableReferenceInfos { } sizeInfo.append(" " + sub + " varrefs" + "\n"); } - if(blockUsedVars!=null) { + if(blockUsedVars != null) { sizeInfo.append("blockUsedVars " + blockUsedVars.size() + " labels "); int sub = 0; for(Collection variableRefs : blockUsedVars.values()) { @@ -158,22 +168,6 @@ public class VariableReferenceInfos { } sizeInfo.append(" " + sub + " varrefs" + "\n"); } - { - sizeInfo.append("stmtDefinedVars " + stmtDefinedVars.size() + " ints "); - int sub = 0; - for(Collection variableRefs : stmtDefinedVars.values()) { - sub += variableRefs.size(); - } - sizeInfo.append(" " + sub + " varrefs" + "\n"); - } - { - sizeInfo.append("stmtReferencedVars " + stmtReferencedVars.size() + " ints "); - int sub = 0; - for(Collection variableRefs : stmtReferencedVars.values()) { - sub += variableRefs.size(); - } - sizeInfo.append(" " + sub + " varrefs" + "\n"); - } { sizeInfo.append("symbolVarReferences " + symbolVarReferences.size() + " SymbolVariableRefs "); int sub = 0; @@ -182,6 +176,22 @@ public class VariableReferenceInfos { } sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n"); } + { + sizeInfo.append("statementVarReferences " + statementVarReferences.size() + " statements "); + int sub = 0; + for(Collection value : statementVarReferences.values()) { + sub += value.size(); + } + sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n"); + } + { + sizeInfo.append("blockVarReferences " + blockVarReferences.size() + " blocks "); + int sub = 0; + for(Collection value : blockVarReferences.values()) { + sub += value.size(); + } + sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n"); + } return sizeInfo.toString(); } @@ -222,30 +232,52 @@ public class VariableReferenceInfos { * @return Variables defined by the statement */ public Collection getDefinedVars(Statement stmt) { - return stmtDefinedVars.get(stmt.getIndex()); + Collection referenceToSymbolVars = statementVarReferences.get(stmt.getIndex()); + List variableRefs = referenceToSymbolVars + .stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef) + .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.DEFINE.equals(referenceToSymbolVar.getReferenceType())) + .map(ReferenceToSymbolVar::getReferenced) + .map(symbolVariableRef -> (VariableRef) symbolVariableRef) + .collect(Collectors.toList()); + return variableRefs; } /** * Get the variables referenced (used or defined) in a statement * - * @param statement The statement to examine + * @param stmt The statement to examine * @return The referenced variables */ - public Collection getReferencedVars(Statement statement) { - return stmtReferencedVars.get(statement.getIndex()); + public Collection getReferencedVars(Statement stmt) { + // Test if new structure is compatible + Collection referenceToSymbolVars = statementVarReferences.get(stmt.getIndex()); + List variableRefs = + referenceToSymbolVars + .stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef) + .map(ReferenceToSymbolVar::getReferenced) + .map(symbolVariableRef -> (VariableRef)symbolVariableRef) + .collect(Collectors.toList()); + return variableRefs; } /** * Get the variables used, but not defined, in a statement * - * @param statement The statement to examine + * @param stmt The statement to examine * @return The used variables (not including defined variables) */ - public Collection getUsedVars(Statement statement) { - LinkedHashSet used = new LinkedHashSet<>(); - used.addAll(getReferencedVars(statement)); - used.removeAll(getDefinedVars(statement)); - return used; + public Collection getUsedVars(Statement stmt) { + Collection referenceToSymbolVars = statementVarReferences.get(stmt.getIndex()); + List variableRefs = referenceToSymbolVars + .stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef) + .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())) + .map(ReferenceToSymbolVar::getReferenced) + .map(symbolVariableRef -> (VariableRef) symbolVariableRef) + .collect(Collectors.toList()); + return variableRefs; } /** @@ -255,10 +287,9 @@ public class VariableReferenceInfos { */ public boolean isUnused(SymbolVariableRef variableRef) { Collection refs = symbolVarReferences.get(variableRef); - if(refs==null) return true; + if(refs == null) return true; return !refs.stream() - .anyMatch(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()) - ); + .anyMatch(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())); } /** @@ -270,7 +301,7 @@ public class VariableReferenceInfos { public Collection getConstRefStatements(ConstantRef constRef) { Collection refs = symbolVarReferences.get(constRef); LinkedHashSet stmts = new LinkedHashSet<>(); - if(refs!=null) { + if(refs != null) { refs.stream() .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); @@ -287,7 +318,7 @@ public class VariableReferenceInfos { public Collection getVarRefStatements(VariableRef varRef) { Collection refs = symbolVarReferences.get(varRef); LinkedHashSet stmts = new LinkedHashSet<>(); - if(refs!=null) { + if(refs != null) { refs.stream() .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx())); @@ -304,7 +335,7 @@ public class VariableReferenceInfos { public Collection getVarUseStatements(VariableRef varRef) { Collection refs = symbolVarReferences.get(varRef); LinkedHashSet stmts = new LinkedHashSet<>(); - if(refs!=null) { + if(refs != null) { refs.stream() .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType()) @@ -323,7 +354,7 @@ public class VariableReferenceInfos { public Collection getSymbolRefConsts(ConstantRef constRef) { Collection refs = symbolVarReferences.get(constRef); LinkedHashSet constRefs = new LinkedHashSet<>(); - if(refs!=null) { + if(refs != null) { refs.stream() .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType())) .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol) diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java index dd7e24aab..d0b2a4dd8 100644 --- a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java @@ -5,7 +5,9 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.VariableReferenceInfos; import dk.camelot64.kickc.model.iterator.ProgramValue; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; -import dk.camelot64.kickc.model.statements.*; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementLValue; +import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.symbols.SymbolVariable; import dk.camelot64.kickc.model.values.*; @@ -27,14 +29,19 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase> blockReferencedVars = new LinkedHashMap<>(); LinkedHashMap> blockUsedVars = new LinkedHashMap<>(); - LinkedHashMap> stmtReferenced = new LinkedHashMap<>(); - LinkedHashMap> stmtDefined = new LinkedHashMap<>(); + LinkedHashMap> blockSuccessors = new LinkedHashMap<>(); + Map> symbolVarReferences = new LinkedHashMap<>(); + Map> blockVarReferences = new LinkedHashMap<>(); + Map> statementVarReferences = new LinkedHashMap<>(); + blockDirectVarRefsMap = new LinkedHashMap<>(); blockDirectUsedVarsMap = new LinkedHashMap<>(); for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { LinkedHashSet blockDirectVarRefs = new LinkedHashSet<>(); LinkedHashSet blockDirectUsedVars = new LinkedHashSet<>(); + blockVarReferences.putIfAbsent(block.getLabel(), new ArrayList<>()); + Collection blockSymbols = blockVarReferences.get(block.getLabel()); for(Statement statement : block.getStatements()) { LinkedHashSet stmtSymbolVarRefs = new LinkedHashSet<>(); LinkedHashSet stmtVarRefs = new LinkedHashSet<>(); @@ -51,29 +58,29 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase()); + Collection stmtSymbols = statementVarReferences.get(statement.getIndex()); // Identify statement defining variables for(VariableRef variableRef : stmtDefinedVars) { symbolVarReferences.putIfAbsent(variableRef, new ArrayList<>()); - Collection references = symbolVarReferences.get(variableRef); - references.add(new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.DEFINE, variableRef)); + Collection varReferences = symbolVarReferences.get(variableRef); + VariableReferenceInfos.ReferenceInStatement referenceInStmt = new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.DEFINE, variableRef); + varReferences.add(referenceInStmt); + stmtSymbols.add(referenceInStmt); + if(!blockSymbols.contains(referenceInStmt)) blockSymbols.add(referenceInStmt); } // Gather statements referencing variables/constants for(SymbolVariableRef referencedVarRef : stmtSymbolVarRefs) { if(!stmtDefinedVars.contains(referencedVarRef)) { symbolVarReferences.putIfAbsent(referencedVarRef, new ArrayList<>()); Collection references = symbolVarReferences.get(referencedVarRef); - references.add( - new VariableReferenceInfos.ReferenceInStatement( - statement.getIndex(), - VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.USE, - referencedVarRef)); + VariableReferenceInfos.ReferenceInStatement referenceInStmt = new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.USE, referencedVarRef); + references.add(referenceInStmt); + stmtSymbols.add(referenceInStmt); + if(!blockSymbols.contains(referenceInStmt)) blockSymbols.add(referenceInStmt); } } - // Add variable reference to the statement - stmtReferenced.put(statement.getIndex(), stmtVarRefs); } LabelRef blockLabel = block.getLabel(); blockDirectVarRefsMap.put(blockLabel, blockDirectVarRefs); @@ -83,9 +90,12 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase blockRecursiveVarRefs = new LinkedHashSet<>(); LinkedHashSet blockRecursiveUsedVars = new LinkedHashSet<>(); - addReferencedVars(block.getLabel(), block, blockRecursiveVarRefs, blockRecursiveUsedVars, new ArrayList<>()); + findReferencedVars(block.getLabel(), block, blockRecursiveVarRefs, blockRecursiveUsedVars, new ArrayList<>()); blockReferencedVars.put(blockLabel, blockRecursiveVarRefs); blockUsedVars.put(blockLabel, blockRecursiveUsedVars); + LinkedHashSet successorClosure = new LinkedHashSet<>(); + findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>()); + blockSuccessors.put(blockLabel, successorClosure); } // Gather symbols in the symbol table referencing other variables/constants Collection allSymbolVariables = getProgram().getScope().getAllSymbolVariables(true); @@ -101,7 +111,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase referencedVars, LinkedHashSet usedVars, Collection visited) { + private void findReferencedVars(LabelRef labelRef, ControlFlowBlock block, LinkedHashSet referencedVars, LinkedHashSet usedVars, Collection visited) { if(labelRef == null || visited.contains(labelRef)) return; visited.add(labelRef); @@ -176,11 +186,32 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase successorClosure, Collection visited) { + if(labelRef == null || visited.contains(labelRef)) + return; + visited.add(labelRef); + ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef); + if(block == null) + return; + successorClosure.add(labelRef); + findSuccessorClosure(block.getDefaultSuccessor(), successorClosure, visited); + findSuccessorClosure(block.getConditionalSuccessor(), successorClosure, visited); + findSuccessorClosure(block.getCallSuccessor(), successorClosure, visited); + } + + /** * Get the variables defined by a statement * diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index c81fc15d8..66bc634fb 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -638,6 +638,16 @@ public class TestPrograms { } */ + @Test + public void testStructPtr25() throws IOException, URISyntaxException { + compileAndCompare("struct-ptr-25"); + } + + @Test + public void testStructPtr24() throws IOException, URISyntaxException { + compileAndCompare("struct-ptr-24"); + } + /* TODO: Fix array of struct containing array https://gitlab.com/camelot/kickc/issues/274 @Test public void testStructPtr23() throws IOException, URISyntaxException { diff --git a/src/test/kc/struct-ptr-24.kc b/src/test/kc/struct-ptr-24.kc new file mode 100644 index 000000000..41f5cda9d --- /dev/null +++ b/src/test/kc/struct-ptr-24.kc @@ -0,0 +1,23 @@ +typedef unsigned char BYTE; + +struct fileentry { + BYTE bFlag; + BYTE bError; +}; + +typedef struct fileentry ENTRY; + +ENTRY *filesEnd; +ENTRY *dir; + +void main(){ + ENTRY *file; + while(file != filesEnd){ + PrintName(file); + ++file; + } +} + +void PrintName(ENTRY *file) { + if (file == dir) *(BYTE *)0xC7 = 1; +} \ No newline at end of file diff --git a/src/test/kc/struct-ptr-25.kc b/src/test/kc/struct-ptr-25.kc new file mode 100644 index 000000000..8608e7177 --- /dev/null +++ b/src/test/kc/struct-ptr-25.kc @@ -0,0 +1,10 @@ +char *fileCur; +char *fileTop; +char *filesEnd; +char *file; + +void main(void) { + if (fileTop == filesEnd) --fileTop; + if (file <= fileCur) --fileCur; + if (fileCur < fileTop) fileCur = fileTop; +} diff --git a/src/test/ref/struct-ptr-24.asm b/src/test/ref/struct-ptr-24.asm new file mode 100644 index 000000000..3e8cd2911 --- /dev/null +++ b/src/test/ref/struct-ptr-24.asm @@ -0,0 +1,44 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SIZEOF_STRUCT_FILEENTRY = 2 + .label filesEnd = 0 + .label dir = 0 +main: { + .label file = 2 + lda #<0 + sta.z file + sta.z file+1 + b1: + lda.z file+1 + cmp #>filesEnd + bne b2 + lda.z file + cmp #dir + bne breturn + lda.z file + cmp #@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + .label file = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) 0 [phi:main->main::@1#0] -- pssz1=pssc1 + lda #<0 + sta.z file + lda #>0 + sta.z file+1 + jmp b1 + // main::@1 + b1: + // [6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2 -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>filesEnd + bne b2 + lda.z file + cmp #main::@1] + b1_from_b3: + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) main::file#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 +} + // PrintName +// PrintName(struct fileentry* zeropage(4) file) +PrintName: { + .label file = 4 + // [11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>dir + bne breturn + lda.z file + cmp #@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + .label file = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) 0 [phi:main->main::@1#0] -- pssz1=pssc1 + lda #<0 + sta.z file + lda #>0 + sta.z file+1 + jmp b1 + // main::@1 + b1: + // [6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2 -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>filesEnd + bne b2 + lda.z file + cmp #main::@1] + b1_from_b3: + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) main::file#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 +} + // PrintName +// PrintName(struct fileentry* zeropage(2) file) +PrintName: { + .label file = 2 + // [11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>dir + bne breturn + lda.z file + cmp #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction breturn: +Removing instruction b3: +Removing instruction b1_from_b3: +Removing instruction b1: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) PrintName((struct fileentry*) PrintName::file) +(label) PrintName::@1 +(label) PrintName::@return +(struct fileentry*) PrintName::file +(struct fileentry*) PrintName::file#0 file zp ZP_WORD:2 13.0 +(const byte) SIZEOF_STRUCT_FILEENTRY SIZEOF_STRUCT_FILEENTRY = (byte) 2 +(struct fileentry*) dir +(const struct fileentry*) dir#0 dir = (struct fileentry*) 0 +(byte) fileentry::bError +(byte) fileentry::bFlag +(struct fileentry*) filesEnd +(const struct fileentry*) filesEnd#0 filesEnd = (struct fileentry*) 0 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(struct fileentry*) main::file +(struct fileentry*) main::file#1 file zp ZP_WORD:2 22.0 +(struct fileentry*) main::file#2 file zp ZP_WORD:2 11.0 + +zp ZP_WORD:2 [ main::file#2 main::file#1 PrintName::file#0 ] + + +FINAL ASSEMBLER +Score: 528 + + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const SIZEOF_STRUCT_FILEENTRY = 2 + .label filesEnd = 0 + .label dir = 0 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [4] phi from @1 to main [phi:@1->main] + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .label file = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) 0 [phi:main->main::@1#0] -- pssz1=pssc1 + lda #<0 + sta.z file + sta.z file+1 + // main::@1 + b1: + // while(file != filesEnd) + // [6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2 -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>filesEnd + bne b2 + lda.z file + cmp #main::@1] + // [5] phi (struct fileentry*) main::file#2 = (struct fileentry*) main::file#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 +} + // PrintName +// PrintName(struct fileentry* zeropage(2) file) +PrintName: { + .label file = 2 + // if (file == dir) + // [11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return -- pssz1_neq_pssc1_then_la1 + lda.z file+1 + cmp #>dir + bne breturn + lda.z file + cmp #