mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-23 23:32:55 +00:00
parent
162b29b2d4
commit
42ecee2f94
8
src/main/fragment/pbuc1_le_pbuc2_then_la1.asm
Normal file
8
src/main/fragment/pbuc1_le_pbuc2_then_la1.asm
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
lda #>{c1}
|
||||||
|
cmp #>{c2}
|
||||||
|
bne !+
|
||||||
|
lda #<{c1}
|
||||||
|
cmp #<{c2}
|
||||||
|
beq {la1}
|
||||||
|
!:
|
||||||
|
bcc {la1}
|
4
src/main/fragment/pssz1=pssz2.asm
Normal file
4
src/main/fragment/pssz1=pssz2.asm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
lda {z2}
|
||||||
|
sta {z1}
|
||||||
|
lda {z2}+1
|
||||||
|
sta {z1}+1
|
@ -1,12 +1,11 @@
|
|||||||
package dk.camelot64.kickc.model;
|
package dk.camelot64.kickc.model;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.values.*;
|
|
||||||
import dk.camelot64.kickc.model.statements.Statement;
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
|
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.stream.Collectors;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached information about which variables/constants are defined/referenced/used in which statements / blocks / symbols .
|
* 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. */
|
/** Variables used in each block. */
|
||||||
private Map<LabelRef, Collection<VariableRef>> blockUsedVars;
|
private Map<LabelRef, Collection<VariableRef>> blockUsedVars;
|
||||||
|
|
||||||
/** Variables referenced in each statement. */
|
/** For each block this is the closure of all successor blocks. */
|
||||||
private Map<Integer, Collection<VariableRef>> stmtReferencedVars;
|
private Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure;
|
||||||
|
|
||||||
/** Variables defined in each statement. */
|
/** References to variables/constants by block label. */
|
||||||
private Map<Integer, Collection<VariableRef>> stmtDefinedVars;
|
private Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences;
|
||||||
|
|
||||||
|
/** References to variables/constants by statement index. */
|
||||||
|
private Map<Integer, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> statementVarReferences;
|
||||||
|
|
||||||
/** All references to symbol variables (constants/variables). References can be either statements or symbols in the symbol table */
|
/** All references to symbol variables (constants/variables). References can be either statements or symbols in the symbol table */
|
||||||
private Map<SymbolVariableRef, Collection<ReferenceToSymbolVar>> symbolVarReferences;
|
private Map<SymbolVariableRef, Collection<ReferenceToSymbolVar>> symbolVarReferences;
|
||||||
@ -127,22 +129,30 @@ public class VariableReferenceInfos {
|
|||||||
public VariableReferenceInfos(
|
public VariableReferenceInfos(
|
||||||
Map<LabelRef, Collection<VariableRef>> blockReferencedVars,
|
Map<LabelRef, Collection<VariableRef>> blockReferencedVars,
|
||||||
Map<LabelRef, Collection<VariableRef>> blockUsedVars,
|
Map<LabelRef, Collection<VariableRef>> blockUsedVars,
|
||||||
Map<Integer, Collection<VariableRef>> stmtReferencedVars,
|
Map<LabelRef, Collection<LabelRef>> blockSuccessorClosure,
|
||||||
Map<Integer, Collection<VariableRef>> stmtDefinedVars,
|
Map<SymbolVariableRef, Collection<ReferenceToSymbolVar>> symbolVarReferences,
|
||||||
Map<SymbolVariableRef, Collection<ReferenceToSymbolVar>> symbolVarReferences
|
Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences,
|
||||||
|
Map<Integer, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> statementVarReferences
|
||||||
) {
|
) {
|
||||||
this.blockReferencedVars = blockReferencedVars;
|
this.blockReferencedVars = blockReferencedVars;
|
||||||
this.blockUsedVars = blockUsedVars;
|
this.blockUsedVars = blockUsedVars;
|
||||||
this.stmtDefinedVars = stmtDefinedVars;
|
this.blockSuccessorClosure = blockSuccessorClosure;
|
||||||
this.stmtReferencedVars = stmtReferencedVars;
|
|
||||||
this.symbolVarReferences = symbolVarReferences;
|
this.symbolVarReferences = symbolVarReferences;
|
||||||
|
this.blockVarReferences = blockVarReferences;
|
||||||
|
this.statementVarReferences = statementVarReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSizeInfo() {
|
public String getSizeInfo() {
|
||||||
StringBuilder sizeInfo = new StringBuilder();
|
StringBuilder sizeInfo = new StringBuilder();
|
||||||
if(blockReferencedVars!=null) {
|
if(blockSuccessorClosure != null) {
|
||||||
|
sizeInfo.append("blockSuccessorClosure " + blockSuccessorClosure.size() + " labels ");
|
||||||
|
int sub = 0;
|
||||||
|
for(Collection<LabelRef> labelRefs : blockSuccessorClosure.values()) {
|
||||||
|
sub += labelRefs.size();
|
||||||
|
}
|
||||||
|
sizeInfo.append(" " + sub + " labels" + "\n");
|
||||||
|
}
|
||||||
|
if(blockReferencedVars != null) {
|
||||||
sizeInfo.append("blockReferencedVars " + blockReferencedVars.size() + " labels ");
|
sizeInfo.append("blockReferencedVars " + blockReferencedVars.size() + " labels ");
|
||||||
int sub = 0;
|
int sub = 0;
|
||||||
for(Collection<VariableRef> variableRefs : blockReferencedVars.values()) {
|
for(Collection<VariableRef> variableRefs : blockReferencedVars.values()) {
|
||||||
@ -150,7 +160,7 @@ public class VariableReferenceInfos {
|
|||||||
}
|
}
|
||||||
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
||||||
}
|
}
|
||||||
if(blockUsedVars!=null) {
|
if(blockUsedVars != null) {
|
||||||
sizeInfo.append("blockUsedVars " + blockUsedVars.size() + " labels ");
|
sizeInfo.append("blockUsedVars " + blockUsedVars.size() + " labels ");
|
||||||
int sub = 0;
|
int sub = 0;
|
||||||
for(Collection<VariableRef> variableRefs : blockUsedVars.values()) {
|
for(Collection<VariableRef> variableRefs : blockUsedVars.values()) {
|
||||||
@ -158,22 +168,6 @@ public class VariableReferenceInfos {
|
|||||||
}
|
}
|
||||||
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
||||||
}
|
}
|
||||||
{
|
|
||||||
sizeInfo.append("stmtDefinedVars " + stmtDefinedVars.size() + " ints ");
|
|
||||||
int sub = 0;
|
|
||||||
for(Collection<VariableRef> variableRefs : stmtDefinedVars.values()) {
|
|
||||||
sub += variableRefs.size();
|
|
||||||
}
|
|
||||||
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
sizeInfo.append("stmtReferencedVars " + stmtReferencedVars.size() + " ints ");
|
|
||||||
int sub = 0;
|
|
||||||
for(Collection<VariableRef> variableRefs : stmtReferencedVars.values()) {
|
|
||||||
sub += variableRefs.size();
|
|
||||||
}
|
|
||||||
sizeInfo.append(" " + sub + " varrefs" + "\n");
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
sizeInfo.append("symbolVarReferences " + symbolVarReferences.size() + " SymbolVariableRefs ");
|
sizeInfo.append("symbolVarReferences " + symbolVarReferences.size() + " SymbolVariableRefs ");
|
||||||
int sub = 0;
|
int sub = 0;
|
||||||
@ -182,6 +176,22 @@ public class VariableReferenceInfos {
|
|||||||
}
|
}
|
||||||
sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n");
|
sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
sizeInfo.append("statementVarReferences " + statementVarReferences.size() + " statements ");
|
||||||
|
int sub = 0;
|
||||||
|
for(Collection<ReferenceToSymbolVar> value : statementVarReferences.values()) {
|
||||||
|
sub += value.size();
|
||||||
|
}
|
||||||
|
sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
sizeInfo.append("blockVarReferences " + blockVarReferences.size() + " blocks ");
|
||||||
|
int sub = 0;
|
||||||
|
for(Collection<ReferenceToSymbolVar> value : blockVarReferences.values()) {
|
||||||
|
sub += value.size();
|
||||||
|
}
|
||||||
|
sizeInfo.append(" " + sub + " ReferenceToSymbolVars" + "\n");
|
||||||
|
}
|
||||||
return sizeInfo.toString();
|
return sizeInfo.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,30 +232,52 @@ public class VariableReferenceInfos {
|
|||||||
* @return Variables defined by the statement
|
* @return Variables defined by the statement
|
||||||
*/
|
*/
|
||||||
public Collection<VariableRef> getDefinedVars(Statement stmt) {
|
public Collection<VariableRef> getDefinedVars(Statement stmt) {
|
||||||
return stmtDefinedVars.get(stmt.getIndex());
|
Collection<ReferenceToSymbolVar> referenceToSymbolVars = statementVarReferences.get(stmt.getIndex());
|
||||||
|
List<VariableRef> 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
|
* 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
|
* @return The referenced variables
|
||||||
*/
|
*/
|
||||||
public Collection<VariableRef> getReferencedVars(Statement statement) {
|
public Collection<VariableRef> getReferencedVars(Statement stmt) {
|
||||||
return stmtReferencedVars.get(statement.getIndex());
|
// Test if new structure is compatible
|
||||||
|
Collection<ReferenceToSymbolVar> referenceToSymbolVars = statementVarReferences.get(stmt.getIndex());
|
||||||
|
List<VariableRef> 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
|
* 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)
|
* @return The used variables (not including defined variables)
|
||||||
*/
|
*/
|
||||||
public Collection<VariableRef> getUsedVars(Statement statement) {
|
public Collection<VariableRef> getUsedVars(Statement stmt) {
|
||||||
LinkedHashSet<VariableRef> used = new LinkedHashSet<>();
|
Collection<ReferenceToSymbolVar> referenceToSymbolVars = statementVarReferences.get(stmt.getIndex());
|
||||||
used.addAll(getReferencedVars(statement));
|
List<VariableRef> variableRefs = referenceToSymbolVars
|
||||||
used.removeAll(getDefinedVars(statement));
|
.stream()
|
||||||
return used;
|
.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) {
|
public boolean isUnused(SymbolVariableRef variableRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(variableRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(variableRef);
|
||||||
if(refs==null) return true;
|
if(refs == null) return true;
|
||||||
return !refs.stream()
|
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<Integer> getConstRefStatements(ConstantRef constRef) {
|
public Collection<Integer> getConstRefStatements(ConstantRef constRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
if(refs!=null) {
|
if(refs != null) {
|
||||||
refs.stream()
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
||||||
@ -287,7 +318,7 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<Integer> getVarRefStatements(VariableRef varRef) {
|
public Collection<Integer> getVarRefStatements(VariableRef varRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
if(refs!=null) {
|
if(refs != null) {
|
||||||
refs.stream()
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
|
||||||
@ -304,7 +335,7 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<Integer> getVarUseStatements(VariableRef varRef) {
|
public Collection<Integer> getVarUseStatements(VariableRef varRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
|
||||||
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
|
||||||
if(refs!=null) {
|
if(refs != null) {
|
||||||
refs.stream()
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
|
||||||
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
|
||||||
@ -323,7 +354,7 @@ public class VariableReferenceInfos {
|
|||||||
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
|
||||||
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
|
||||||
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
|
||||||
if(refs!=null) {
|
if(refs != null) {
|
||||||
refs.stream()
|
refs.stream()
|
||||||
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
|
||||||
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
|
||||||
|
@ -5,7 +5,9 @@ import dk.camelot64.kickc.model.Program;
|
|||||||
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
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.symbols.SymbolVariable;
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
@ -27,14 +29,19 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
public VariableReferenceInfos calculate() {
|
public VariableReferenceInfos calculate() {
|
||||||
LinkedHashMap<LabelRef, Collection<VariableRef>> blockReferencedVars = new LinkedHashMap<>();
|
LinkedHashMap<LabelRef, Collection<VariableRef>> blockReferencedVars = new LinkedHashMap<>();
|
||||||
LinkedHashMap<LabelRef, Collection<VariableRef>> blockUsedVars = new LinkedHashMap<>();
|
LinkedHashMap<LabelRef, Collection<VariableRef>> blockUsedVars = new LinkedHashMap<>();
|
||||||
LinkedHashMap<Integer, Collection<VariableRef>> stmtReferenced = new LinkedHashMap<>();
|
LinkedHashMap<LabelRef, Collection<LabelRef>> blockSuccessors = new LinkedHashMap<>();
|
||||||
LinkedHashMap<Integer, Collection<VariableRef>> stmtDefined = new LinkedHashMap<>();
|
|
||||||
Map<SymbolVariableRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> symbolVarReferences = new LinkedHashMap<>();
|
Map<SymbolVariableRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> symbolVarReferences = new LinkedHashMap<>();
|
||||||
|
Map<LabelRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> blockVarReferences = new LinkedHashMap<>();
|
||||||
|
Map<Integer, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> statementVarReferences = new LinkedHashMap<>();
|
||||||
|
|
||||||
blockDirectVarRefsMap = new LinkedHashMap<>();
|
blockDirectVarRefsMap = new LinkedHashMap<>();
|
||||||
blockDirectUsedVarsMap = new LinkedHashMap<>();
|
blockDirectUsedVarsMap = new LinkedHashMap<>();
|
||||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||||
LinkedHashSet<VariableRef> blockDirectVarRefs = new LinkedHashSet<>();
|
LinkedHashSet<VariableRef> blockDirectVarRefs = new LinkedHashSet<>();
|
||||||
LinkedHashSet<VariableRef> blockDirectUsedVars = new LinkedHashSet<>();
|
LinkedHashSet<VariableRef> blockDirectUsedVars = new LinkedHashSet<>();
|
||||||
|
blockVarReferences.putIfAbsent(block.getLabel(), new ArrayList<>());
|
||||||
|
Collection<VariableReferenceInfos.ReferenceToSymbolVar> blockSymbols = blockVarReferences.get(block.getLabel());
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
LinkedHashSet<SymbolVariableRef> stmtSymbolVarRefs = new LinkedHashSet<>();
|
LinkedHashSet<SymbolVariableRef> stmtSymbolVarRefs = new LinkedHashSet<>();
|
||||||
LinkedHashSet<VariableRef> stmtVarRefs = new LinkedHashSet<>();
|
LinkedHashSet<VariableRef> stmtVarRefs = new LinkedHashSet<>();
|
||||||
@ -51,29 +58,29 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
stmtUsedVars.removeAll(stmtDefinedVars);
|
stmtUsedVars.removeAll(stmtDefinedVars);
|
||||||
blockDirectVarRefs.addAll(stmtVarRefs);
|
blockDirectVarRefs.addAll(stmtVarRefs);
|
||||||
blockDirectUsedVars.addAll(stmtUsedVars);
|
blockDirectUsedVars.addAll(stmtUsedVars);
|
||||||
|
|
||||||
// Add variable definitions to the statement
|
// Add variable definitions to the statement
|
||||||
stmtDefined.put(statement.getIndex(), stmtDefinedVars);
|
statementVarReferences.putIfAbsent(statement.getIndex(), new ArrayList<>());
|
||||||
|
Collection<VariableReferenceInfos.ReferenceToSymbolVar> stmtSymbols = statementVarReferences.get(statement.getIndex());
|
||||||
// Identify statement defining variables
|
// Identify statement defining variables
|
||||||
for(VariableRef variableRef : stmtDefinedVars) {
|
for(VariableRef variableRef : stmtDefinedVars) {
|
||||||
symbolVarReferences.putIfAbsent(variableRef, new ArrayList<>());
|
symbolVarReferences.putIfAbsent(variableRef, new ArrayList<>());
|
||||||
Collection<VariableReferenceInfos.ReferenceToSymbolVar> references = symbolVarReferences.get(variableRef);
|
Collection<VariableReferenceInfos.ReferenceToSymbolVar> varReferences = symbolVarReferences.get(variableRef);
|
||||||
references.add(new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.DEFINE, 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
|
// Gather statements referencing variables/constants
|
||||||
for(SymbolVariableRef referencedVarRef : stmtSymbolVarRefs) {
|
for(SymbolVariableRef referencedVarRef : stmtSymbolVarRefs) {
|
||||||
if(!stmtDefinedVars.contains(referencedVarRef)) {
|
if(!stmtDefinedVars.contains(referencedVarRef)) {
|
||||||
symbolVarReferences.putIfAbsent(referencedVarRef, new ArrayList<>());
|
symbolVarReferences.putIfAbsent(referencedVarRef, new ArrayList<>());
|
||||||
Collection<VariableReferenceInfos.ReferenceToSymbolVar> references = symbolVarReferences.get(referencedVarRef);
|
Collection<VariableReferenceInfos.ReferenceToSymbolVar> references = symbolVarReferences.get(referencedVarRef);
|
||||||
references.add(
|
VariableReferenceInfos.ReferenceInStatement referenceInStmt = new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.USE, referencedVarRef);
|
||||||
new VariableReferenceInfos.ReferenceInStatement(
|
references.add(referenceInStmt);
|
||||||
statement.getIndex(),
|
stmtSymbols.add(referenceInStmt);
|
||||||
VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.USE,
|
if(!blockSymbols.contains(referenceInStmt)) blockSymbols.add(referenceInStmt);
|
||||||
referencedVarRef));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add variable reference to the statement
|
|
||||||
stmtReferenced.put(statement.getIndex(), stmtVarRefs);
|
|
||||||
}
|
}
|
||||||
LabelRef blockLabel = block.getLabel();
|
LabelRef blockLabel = block.getLabel();
|
||||||
blockDirectVarRefsMap.put(blockLabel, blockDirectVarRefs);
|
blockDirectVarRefsMap.put(blockLabel, blockDirectVarRefs);
|
||||||
@ -83,9 +90,12 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
LabelRef blockLabel = block.getLabel();
|
LabelRef blockLabel = block.getLabel();
|
||||||
LinkedHashSet<VariableRef> blockRecursiveVarRefs = new LinkedHashSet<>();
|
LinkedHashSet<VariableRef> blockRecursiveVarRefs = new LinkedHashSet<>();
|
||||||
LinkedHashSet<VariableRef> blockRecursiveUsedVars = new LinkedHashSet<>();
|
LinkedHashSet<VariableRef> blockRecursiveUsedVars = new LinkedHashSet<>();
|
||||||
addReferencedVars(block.getLabel(), block, blockRecursiveVarRefs, blockRecursiveUsedVars, new ArrayList<>());
|
findReferencedVars(block.getLabel(), block, blockRecursiveVarRefs, blockRecursiveUsedVars, new ArrayList<>());
|
||||||
blockReferencedVars.put(blockLabel, blockRecursiveVarRefs);
|
blockReferencedVars.put(blockLabel, blockRecursiveVarRefs);
|
||||||
blockUsedVars.put(blockLabel, blockRecursiveUsedVars);
|
blockUsedVars.put(blockLabel, blockRecursiveUsedVars);
|
||||||
|
LinkedHashSet<LabelRef> successorClosure = new LinkedHashSet<>();
|
||||||
|
findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>());
|
||||||
|
blockSuccessors.put(blockLabel, successorClosure);
|
||||||
}
|
}
|
||||||
// Gather symbols in the symbol table referencing other variables/constants
|
// Gather symbols in the symbol table referencing other variables/constants
|
||||||
Collection<SymbolVariable> allSymbolVariables = getProgram().getScope().getAllSymbolVariables(true);
|
Collection<SymbolVariable> allSymbolVariables = getProgram().getScope().getAllSymbolVariables(true);
|
||||||
@ -101,7 +111,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
VariableReferenceInfos variableReferenceInfos = new VariableReferenceInfos(blockReferencedVars, blockUsedVars, stmtReferenced, stmtDefined, symbolVarReferences);
|
VariableReferenceInfos variableReferenceInfos = new VariableReferenceInfos(blockReferencedVars, blockUsedVars, blockSuccessors, symbolVarReferences, blockVarReferences, statementVarReferences);
|
||||||
if(getLog().isVerboseSSAOptimize()) {
|
if(getLog().isVerboseSSAOptimize()) {
|
||||||
getLog().append(variableReferenceInfos.getSizeInfo());
|
getLog().append(variableReferenceInfos.getSizeInfo());
|
||||||
}
|
}
|
||||||
@ -165,7 +175,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
* @param usedVars the set of referenced variables
|
* @param usedVars the set of referenced variables
|
||||||
* @param visited The blocks already visited during the search. Used to stop infinite recursion
|
* @param visited The blocks already visited during the search. Used to stop infinite recursion
|
||||||
*/
|
*/
|
||||||
private void addReferencedVars(LabelRef labelRef, ControlFlowBlock block, LinkedHashSet<VariableRef> referencedVars, LinkedHashSet<VariableRef> usedVars, Collection<LabelRef> visited) {
|
private void findReferencedVars(LabelRef labelRef, ControlFlowBlock block, LinkedHashSet<VariableRef> referencedVars, LinkedHashSet<VariableRef> usedVars, Collection<LabelRef> visited) {
|
||||||
if(labelRef == null || visited.contains(labelRef))
|
if(labelRef == null || visited.contains(labelRef))
|
||||||
return;
|
return;
|
||||||
visited.add(labelRef);
|
visited.add(labelRef);
|
||||||
@ -176,11 +186,32 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase<VariableRefer
|
|||||||
}
|
}
|
||||||
referencedVars.addAll(blockDirectVarRefsMap.get(labelRef));
|
referencedVars.addAll(blockDirectVarRefsMap.get(labelRef));
|
||||||
usedVars.addAll(blockDirectUsedVarsMap.get(labelRef));
|
usedVars.addAll(blockDirectUsedVarsMap.get(labelRef));
|
||||||
addReferencedVars(block.getDefaultSuccessor(), null, referencedVars, usedVars, visited);
|
findReferencedVars(block.getDefaultSuccessor(), null, referencedVars, usedVars, visited);
|
||||||
addReferencedVars(block.getConditionalSuccessor(), null, referencedVars, usedVars, visited);
|
findReferencedVars(block.getConditionalSuccessor(), null, referencedVars, usedVars, visited);
|
||||||
addReferencedVars(block.getCallSuccessor(), null, referencedVars, usedVars, visited);
|
findReferencedVars(block.getCallSuccessor(), null, referencedVars, usedVars, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively get all blocks in the closure of successors & calls for a specific block
|
||||||
|
*
|
||||||
|
* @param labelRef The block to examine
|
||||||
|
* @param successorClosure the set of all blocks that are successors (including called methods).
|
||||||
|
* @param visited The blocks already visited during the search. Used to stop infinite recursion.
|
||||||
|
*/
|
||||||
|
private void findSuccessorClosure(LabelRef labelRef, LinkedHashSet<LabelRef> successorClosure, Collection<LabelRef> 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
|
* Get the variables defined by a statement
|
||||||
*
|
*
|
||||||
|
@ -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
|
/* TODO: Fix array of struct containing array https://gitlab.com/camelot/kickc/issues/274
|
||||||
@Test
|
@Test
|
||||||
public void testStructPtr23() throws IOException, URISyntaxException {
|
public void testStructPtr23() throws IOException, URISyntaxException {
|
||||||
|
23
src/test/kc/struct-ptr-24.kc
Normal file
23
src/test/kc/struct-ptr-24.kc
Normal file
@ -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;
|
||||||
|
}
|
10
src/test/kc/struct-ptr-25.kc
Normal file
10
src/test/kc/struct-ptr-25.kc
Normal file
@ -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;
|
||||||
|
}
|
44
src/test/ref/struct-ptr-24.asm
Normal file
44
src/test/ref/struct-ptr-24.asm
Normal file
@ -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 #<filesEnd
|
||||||
|
bne b2
|
||||||
|
rts
|
||||||
|
b2:
|
||||||
|
jsr PrintName
|
||||||
|
lda #SIZEOF_STRUCT_FILEENTRY
|
||||||
|
clc
|
||||||
|
adc.z file
|
||||||
|
sta.z file
|
||||||
|
bcc !+
|
||||||
|
inc.z file+1
|
||||||
|
!:
|
||||||
|
jmp b1
|
||||||
|
}
|
||||||
|
// PrintName(struct fileentry* zeropage(2) file)
|
||||||
|
PrintName: {
|
||||||
|
.label file = 2
|
||||||
|
lda.z file+1
|
||||||
|
cmp #>dir
|
||||||
|
bne breturn
|
||||||
|
lda.z file
|
||||||
|
cmp #<dir
|
||||||
|
bne breturn
|
||||||
|
lda #1
|
||||||
|
sta $c7
|
||||||
|
breturn:
|
||||||
|
rts
|
||||||
|
}
|
35
src/test/ref/struct-ptr-24.cfg
Normal file
35
src/test/ref/struct-ptr-24.cfg
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
@begin: scope:[] from
|
||||||
|
[0] phi()
|
||||||
|
to:@1
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
[1] phi()
|
||||||
|
[2] call main
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @1
|
||||||
|
[3] phi()
|
||||||
|
main: scope:[main] from @1
|
||||||
|
[4] phi()
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main main::@3
|
||||||
|
[5] (struct fileentry*) main::file#2 ← phi( main/(struct fileentry*) 0 main::@3/(struct fileentry*) main::file#1 )
|
||||||
|
[6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main::@1
|
||||||
|
[7] return
|
||||||
|
to:@return
|
||||||
|
main::@2: scope:[main] from main::@1
|
||||||
|
[8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2
|
||||||
|
[9] call PrintName
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
[10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY
|
||||||
|
to:main::@1
|
||||||
|
PrintName: scope:[PrintName] from main::@2
|
||||||
|
[11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return
|
||||||
|
to:PrintName::@1
|
||||||
|
PrintName::@1: scope:[PrintName] from PrintName
|
||||||
|
[12] *((byte*) 199) ← (byte) 1
|
||||||
|
to:PrintName::@return
|
||||||
|
PrintName::@return: scope:[PrintName] from PrintName PrintName::@1
|
||||||
|
[13] return
|
||||||
|
to:@return
|
561
src/test/ref/struct-ptr-24.log
Normal file
561
src/test/ref/struct-ptr-24.log
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
Fixing pointer increment (struct fileentry*) main::file ← ++ (struct fileentry*) main::file
|
||||||
|
Identified constant variable (struct fileentry*) filesEnd
|
||||||
|
Identified constant variable (struct fileentry*) dir
|
||||||
|
Culled Empty Block (label) main::@4
|
||||||
|
Culled Empty Block (label) main::@3
|
||||||
|
Culled Empty Block (label) main::@5
|
||||||
|
Culled Empty Block (label) main::@6
|
||||||
|
Culled Empty Block (label) @1
|
||||||
|
Culled Empty Block (label) PrintName::@1
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
@begin: scope:[] from
|
||||||
|
(struct fileentry*) filesEnd#0 ← (struct fileentry*) 0
|
||||||
|
(struct fileentry*) dir#0 ← (struct fileentry*) 0
|
||||||
|
to:@2
|
||||||
|
main: scope:[main] from @2
|
||||||
|
(struct fileentry*) main::file#0 ← (struct fileentry*) 0
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main main::@7
|
||||||
|
(struct fileentry*) main::file#2 ← phi( main/(struct fileentry*) main::file#0 main::@7/(struct fileentry*) main::file#1 )
|
||||||
|
(bool~) main::$0 ← (struct fileentry*) main::file#2 != (struct fileentry*) filesEnd#0
|
||||||
|
if((bool~) main::$0) goto main::@2
|
||||||
|
to:main::@return
|
||||||
|
main::@2: scope:[main] from main::@1
|
||||||
|
(struct fileentry*) main::file#3 ← phi( main::@1/(struct fileentry*) main::file#2 )
|
||||||
|
(struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#3
|
||||||
|
call PrintName
|
||||||
|
to:main::@7
|
||||||
|
main::@7: scope:[main] from main::@2
|
||||||
|
(struct fileentry*) main::file#4 ← phi( main::@2/(struct fileentry*) main::file#3 )
|
||||||
|
(struct fileentry*) main::file#1 ← (struct fileentry*) main::file#4 + (const byte) SIZEOF_STRUCT_FILEENTRY
|
||||||
|
to:main::@1
|
||||||
|
main::@return: scope:[main] from main::@1
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
PrintName: scope:[PrintName] from main::@2
|
||||||
|
(struct fileentry*) PrintName::file#1 ← phi( main::@2/(struct fileentry*) PrintName::file#0 )
|
||||||
|
(bool~) PrintName::$0 ← (struct fileentry*) PrintName::file#1 == (struct fileentry*) dir#0
|
||||||
|
(bool~) PrintName::$1 ← ! (bool~) PrintName::$0
|
||||||
|
if((bool~) PrintName::$1) goto PrintName::@return
|
||||||
|
to:PrintName::@2
|
||||||
|
PrintName::@2: scope:[PrintName] from PrintName
|
||||||
|
(byte*~) PrintName::$2 ← ((byte*)) (number) $c7
|
||||||
|
*((byte*~) PrintName::$2) ← (number) 1
|
||||||
|
to:PrintName::@return
|
||||||
|
PrintName::@return: scope:[PrintName] from PrintName PrintName::@2
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
@2: scope:[] from @begin
|
||||||
|
call main
|
||||||
|
to:@3
|
||||||
|
@3: scope:[] from @2
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @3
|
||||||
|
|
||||||
|
SYMBOL TABLE SSA
|
||||||
|
(label) @2
|
||||||
|
(label) @3
|
||||||
|
(label) @begin
|
||||||
|
(label) @end
|
||||||
|
(void()) PrintName((struct fileentry*) PrintName::file)
|
||||||
|
(bool~) PrintName::$0
|
||||||
|
(bool~) PrintName::$1
|
||||||
|
(byte*~) PrintName::$2
|
||||||
|
(label) PrintName::@2
|
||||||
|
(label) PrintName::@return
|
||||||
|
(struct fileentry*) PrintName::file
|
||||||
|
(struct fileentry*) PrintName::file#0
|
||||||
|
(struct fileentry*) PrintName::file#1
|
||||||
|
(const byte) SIZEOF_STRUCT_FILEENTRY = (byte) 2
|
||||||
|
(struct fileentry*) dir
|
||||||
|
(struct fileentry*) dir#0
|
||||||
|
(byte) fileentry::bError
|
||||||
|
(byte) fileentry::bFlag
|
||||||
|
(struct fileentry*) filesEnd
|
||||||
|
(struct fileentry*) filesEnd#0
|
||||||
|
(void()) main()
|
||||||
|
(bool~) main::$0
|
||||||
|
(label) main::@1
|
||||||
|
(label) main::@2
|
||||||
|
(label) main::@7
|
||||||
|
(label) main::@return
|
||||||
|
(struct fileentry*) main::file
|
||||||
|
(struct fileentry*) main::file#0
|
||||||
|
(struct fileentry*) main::file#1
|
||||||
|
(struct fileentry*) main::file#2
|
||||||
|
(struct fileentry*) main::file#3
|
||||||
|
(struct fileentry*) main::file#4
|
||||||
|
|
||||||
|
Adding number conversion cast (unumber) 1 in *((byte*~) PrintName::$2) ← (number) 1
|
||||||
|
Successful SSA optimization PassNAddNumberTypeConversions
|
||||||
|
Inlining cast (byte*~) PrintName::$2 ← (byte*)(number) $c7
|
||||||
|
Inlining cast *((byte*~) PrintName::$2) ← (unumber)(number) 1
|
||||||
|
Successful SSA optimization Pass2InlineCast
|
||||||
|
Simplifying constant pointer cast (byte*) 199
|
||||||
|
Simplifying constant integer cast 1
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Finalized unsigned number type (byte) 1
|
||||||
|
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||||
|
Inversing boolean not [14] (bool~) PrintName::$1 ← (struct fileentry*) PrintName::file#1 != (struct fileentry*) dir#0 from [13] (bool~) PrintName::$0 ← (struct fileentry*) PrintName::file#1 == (struct fileentry*) dir#0
|
||||||
|
Successful SSA optimization Pass2UnaryNotSimplification
|
||||||
|
Alias (struct fileentry*) main::file#2 = (struct fileentry*) main::file#3 (struct fileentry*) main::file#4
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Identical Phi Values (struct fileentry*) PrintName::file#1 (struct fileentry*) PrintName::file#0
|
||||||
|
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||||
|
Simple Condition (bool~) main::$0 [5] if((struct fileentry*) main::file#2!=(struct fileentry*) filesEnd#0) goto main::@2
|
||||||
|
Simple Condition (bool~) PrintName::$1 [15] if((struct fileentry*) PrintName::file#0!=(struct fileentry*) dir#0) goto PrintName::@return
|
||||||
|
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||||
|
Constant (const struct fileentry*) filesEnd#0 = (struct fileentry*) 0
|
||||||
|
Constant (const struct fileentry*) dir#0 = (struct fileentry*) 0
|
||||||
|
Constant (const struct fileentry*) main::file#0 = (struct fileentry*) 0
|
||||||
|
Constant (const byte*) PrintName::$2 = (byte*) 199
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Inlining constant with var siblings (const struct fileentry*) main::file#0
|
||||||
|
Constant inlined PrintName::$2 = (byte*) 199
|
||||||
|
Constant inlined main::file#0 = (struct fileentry*) 0
|
||||||
|
Successful SSA optimization Pass2ConstantInlining
|
||||||
|
Adding NOP phi() at start of @begin
|
||||||
|
Adding NOP phi() at start of @2
|
||||||
|
Adding NOP phi() at start of @3
|
||||||
|
Adding NOP phi() at start of @end
|
||||||
|
Adding NOP phi() at start of main
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [] to main:2
|
||||||
|
Calls in [main] to PrintName:10
|
||||||
|
|
||||||
|
Created 1 initial phi equivalence classes
|
||||||
|
Coalesced [12] main::file#5 ← main::file#1
|
||||||
|
Coalesced down to 1 phi equivalence classes
|
||||||
|
Culled Empty Block (label) @3
|
||||||
|
Renumbering block @2 to @1
|
||||||
|
Renumbering block main::@7 to main::@3
|
||||||
|
Renumbering block PrintName::@2 to PrintName::@1
|
||||||
|
Adding NOP phi() at start of @begin
|
||||||
|
Adding NOP phi() at start of @1
|
||||||
|
Adding NOP phi() at start of @end
|
||||||
|
Adding NOP phi() at start of main
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
@begin: scope:[] from
|
||||||
|
[0] phi()
|
||||||
|
to:@1
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
[1] phi()
|
||||||
|
[2] call main
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @1
|
||||||
|
[3] phi()
|
||||||
|
main: scope:[main] from @1
|
||||||
|
[4] phi()
|
||||||
|
to:main::@1
|
||||||
|
main::@1: scope:[main] from main main::@3
|
||||||
|
[5] (struct fileentry*) main::file#2 ← phi( main/(struct fileentry*) 0 main::@3/(struct fileentry*) main::file#1 )
|
||||||
|
[6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main::@1
|
||||||
|
[7] return
|
||||||
|
to:@return
|
||||||
|
main::@2: scope:[main] from main::@1
|
||||||
|
[8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2
|
||||||
|
[9] call PrintName
|
||||||
|
to:main::@3
|
||||||
|
main::@3: scope:[main] from main::@2
|
||||||
|
[10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY
|
||||||
|
to:main::@1
|
||||||
|
PrintName: scope:[PrintName] from main::@2
|
||||||
|
[11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return
|
||||||
|
to:PrintName::@1
|
||||||
|
PrintName::@1: scope:[PrintName] from PrintName
|
||||||
|
[12] *((byte*) 199) ← (byte) 1
|
||||||
|
to:PrintName::@return
|
||||||
|
PrintName::@return: scope:[PrintName] from PrintName PrintName::@1
|
||||||
|
[13] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
(void()) PrintName((struct fileentry*) PrintName::file)
|
||||||
|
(struct fileentry*) PrintName::file
|
||||||
|
(struct fileentry*) PrintName::file#0 13.0
|
||||||
|
(struct fileentry*) dir
|
||||||
|
(byte) fileentry::bError
|
||||||
|
(byte) fileentry::bFlag
|
||||||
|
(struct fileentry*) filesEnd
|
||||||
|
(void()) main()
|
||||||
|
(struct fileentry*) main::file
|
||||||
|
(struct fileentry*) main::file#1 22.0
|
||||||
|
(struct fileentry*) main::file#2 11.0
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
[ main::file#2 main::file#1 ]
|
||||||
|
Added variable PrintName::file#0 to zero page equivalence class [ PrintName::file#0 ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ main::file#2 main::file#1 ]
|
||||||
|
[ PrintName::file#0 ]
|
||||||
|
Allocated zp ZP_WORD:2 [ main::file#2 main::file#1 ]
|
||||||
|
Allocated zp ZP_WORD:4 [ PrintName::file#0 ]
|
||||||
|
|
||||||
|
INITIAL ASM
|
||||||
|
Target platform is c64basic
|
||||||
|
// File Comments
|
||||||
|
// Upstart
|
||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(bbegin)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
// Global Constants & labels
|
||||||
|
.const SIZEOF_STRUCT_FILEENTRY = 2
|
||||||
|
.label filesEnd = 0
|
||||||
|
.label dir = 0
|
||||||
|
// @begin
|
||||||
|
bbegin:
|
||||||
|
// [1] phi from @begin to @1 [phi:@begin->@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 #<filesEnd
|
||||||
|
bne b2
|
||||||
|
jmp breturn
|
||||||
|
// main::@return
|
||||||
|
breturn:
|
||||||
|
// [7] return
|
||||||
|
rts
|
||||||
|
// main::@2
|
||||||
|
b2:
|
||||||
|
// [8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2 -- pssz1=pssz2
|
||||||
|
lda.z file
|
||||||
|
sta.z PrintName.file
|
||||||
|
lda.z file+1
|
||||||
|
sta.z PrintName.file+1
|
||||||
|
// [9] call PrintName
|
||||||
|
jsr PrintName
|
||||||
|
jmp b3
|
||||||
|
// main::@3
|
||||||
|
b3:
|
||||||
|
// [10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY -- pssz1=pssz1_plus_vbuc1
|
||||||
|
lda #SIZEOF_STRUCT_FILEENTRY
|
||||||
|
clc
|
||||||
|
adc.z file
|
||||||
|
sta.z file
|
||||||
|
bcc !+
|
||||||
|
inc.z file+1
|
||||||
|
!:
|
||||||
|
// [5] phi from main::@3 to main::@1 [phi:main::@3->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 #<dir
|
||||||
|
bne breturn
|
||||||
|
jmp b1
|
||||||
|
// PrintName::@1
|
||||||
|
b1:
|
||||||
|
// [12] *((byte*) 199) ← (byte) 1 -- _deref_pbuc1=vbuc2
|
||||||
|
lda #1
|
||||||
|
sta $c7
|
||||||
|
jmp breturn
|
||||||
|
// PrintName::@return
|
||||||
|
breturn:
|
||||||
|
// [13] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [6] if((struct fileentry*) main::file#2!=(const struct fileentry*) filesEnd#0) goto main::@2 [ main::file#2 ] ( main:2 [ main::file#2 ] ) always clobbers reg byte a
|
||||||
|
Statement [8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2 [ main::file#2 PrintName::file#0 ] ( main:2 [ main::file#2 PrintName::file#0 ] ) always clobbers reg byte a
|
||||||
|
Statement [10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY [ main::file#1 ] ( main:2 [ main::file#1 ] ) always clobbers reg byte a
|
||||||
|
Statement [11] if((struct fileentry*) PrintName::file#0!=(const struct fileentry*) dir#0) goto PrintName::@return [ ] ( main:2::PrintName:9 [ main::file#2 ] ) always clobbers reg byte a
|
||||||
|
Statement [12] *((byte*) 199) ← (byte) 1 [ ] ( main:2::PrintName:9 [ main::file#2 ] ) always clobbers reg byte a
|
||||||
|
Potential registers zp ZP_WORD:2 [ main::file#2 main::file#1 ] : zp ZP_WORD:2 ,
|
||||||
|
Potential registers zp ZP_WORD:4 [ PrintName::file#0 ] : zp ZP_WORD:4 ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [main] 33: zp ZP_WORD:2 [ main::file#2 main::file#1 ]
|
||||||
|
Uplift Scope [PrintName] 13: zp ZP_WORD:4 [ PrintName::file#0 ]
|
||||||
|
Uplift Scope [fileentry]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [main] best 776 combination zp ZP_WORD:2 [ main::file#2 main::file#1 ]
|
||||||
|
Uplifting [PrintName] best 776 combination zp ZP_WORD:4 [ PrintName::file#0 ]
|
||||||
|
Uplifting [fileentry] best 776 combination
|
||||||
|
Uplifting [] best 776 combination
|
||||||
|
Coalescing zero page register [ zp ZP_WORD:2 [ main::file#2 main::file#1 ] ] with [ zp ZP_WORD:4 [ PrintName::file#0 ] ] - score: 1
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Upstart
|
||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(bbegin)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
// Global Constants & labels
|
||||||
|
.const SIZEOF_STRUCT_FILEENTRY = 2
|
||||||
|
.label filesEnd = 0
|
||||||
|
.label dir = 0
|
||||||
|
// @begin
|
||||||
|
bbegin:
|
||||||
|
// [1] phi from @begin to @1 [phi:@begin->@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 #<filesEnd
|
||||||
|
bne b2
|
||||||
|
jmp breturn
|
||||||
|
// main::@return
|
||||||
|
breturn:
|
||||||
|
// [7] return
|
||||||
|
rts
|
||||||
|
// main::@2
|
||||||
|
b2:
|
||||||
|
// [8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2
|
||||||
|
// [9] call PrintName
|
||||||
|
jsr PrintName
|
||||||
|
jmp b3
|
||||||
|
// main::@3
|
||||||
|
b3:
|
||||||
|
// [10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY -- pssz1=pssz1_plus_vbuc1
|
||||||
|
lda #SIZEOF_STRUCT_FILEENTRY
|
||||||
|
clc
|
||||||
|
adc.z file
|
||||||
|
sta.z file
|
||||||
|
bcc !+
|
||||||
|
inc.z file+1
|
||||||
|
!:
|
||||||
|
// [5] phi from main::@3 to main::@1 [phi:main::@3->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 #<dir
|
||||||
|
bne breturn
|
||||||
|
jmp b1
|
||||||
|
// PrintName::@1
|
||||||
|
b1:
|
||||||
|
// [12] *((byte*) 199) ← (byte) 1 -- _deref_pbuc1=vbuc2
|
||||||
|
lda #1
|
||||||
|
sta $c7
|
||||||
|
jmp breturn
|
||||||
|
// PrintName::@return
|
||||||
|
breturn:
|
||||||
|
// [13] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp b1
|
||||||
|
Removing instruction jmp bend
|
||||||
|
Removing instruction jmp b1
|
||||||
|
Removing instruction jmp breturn
|
||||||
|
Removing instruction jmp b3
|
||||||
|
Removing instruction jmp b1
|
||||||
|
Removing instruction jmp breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction lda #>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 #<filesEnd
|
||||||
|
bne b2
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [7] return
|
||||||
|
rts
|
||||||
|
// main::@2
|
||||||
|
b2:
|
||||||
|
// PrintName(file)
|
||||||
|
// [8] (struct fileentry*) PrintName::file#0 ← (struct fileentry*) main::file#2
|
||||||
|
// [9] call PrintName
|
||||||
|
jsr PrintName
|
||||||
|
// main::@3
|
||||||
|
// ++file;
|
||||||
|
// [10] (struct fileentry*) main::file#1 ← (struct fileentry*) main::file#2 + (const byte) SIZEOF_STRUCT_FILEENTRY -- pssz1=pssz1_plus_vbuc1
|
||||||
|
lda #SIZEOF_STRUCT_FILEENTRY
|
||||||
|
clc
|
||||||
|
adc.z file
|
||||||
|
sta.z file
|
||||||
|
bcc !+
|
||||||
|
inc.z file+1
|
||||||
|
!:
|
||||||
|
// [5] phi from main::@3 to main::@1 [phi:main::@3->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 #<dir
|
||||||
|
bne breturn
|
||||||
|
// PrintName::@1
|
||||||
|
// *(BYTE *)0xC7 = 1
|
||||||
|
// [12] *((byte*) 199) ← (byte) 1 -- _deref_pbuc1=vbuc2
|
||||||
|
lda #1
|
||||||
|
sta $c7
|
||||||
|
// PrintName::@return
|
||||||
|
breturn:
|
||||||
|
// }
|
||||||
|
// [13] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
25
src/test/ref/struct-ptr-24.sym
Normal file
25
src/test/ref/struct-ptr-24.sym
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
(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 ]
|
Loading…
Reference in New Issue
Block a user