diff --git a/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuxx_memcpy_vbuc3.asm b/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuxx_memcpy_vbuc3.asm new file mode 100644 index 000000000..4c71287d4 --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuxx_memcpy_vbuc3.asm @@ -0,0 +1,8 @@ +ldy #0 +!: +lda {c2},x +sta {c1},y +inx +iny +cpy #{c3} +bne !- diff --git a/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuyy_memcpy_vbuc3.asm b/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuyy_memcpy_vbuc3.asm new file mode 100644 index 000000000..e8abe5e7c --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pssc1=pssc2_derefidx_vbuyy_memcpy_vbuc3.asm @@ -0,0 +1,8 @@ +ldx #0 +!: +lda {c2},y +sta {c1},x +iny +inx +cpx #{c3} +bne !- diff --git a/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuxx.asm b/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuxx.asm new file mode 100644 index 000000000..1a01e7be1 --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuxx.asm @@ -0,0 +1,4 @@ +lda {c2},x +sta {c1} +lda {c2}+1,x +sta {c1}+1 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuyy.asm b/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuyy.asm new file mode 100644 index 000000000..f6f087525 --- /dev/null +++ b/src/main/fragment/mos6502-common/_deref_pwsc1=pwsc2_derefidx_vbuyy.asm @@ -0,0 +1,4 @@ +lda {c2},y +sta {c1} +lda {c2}+1,y +sta {c1}+1 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuxx=_deref_pwsc2.asm b/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuxx=_deref_pwsc2.asm new file mode 100644 index 000000000..8f994e41e --- /dev/null +++ b/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuxx=_deref_pwsc2.asm @@ -0,0 +1,4 @@ +lda {c2} +sta {c1},x +lda {c2}+1 +sta {c1}+1,x \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuyy=_deref_pwsc2.asm b/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuyy=_deref_pwsc2.asm new file mode 100644 index 000000000..3ed0e2a53 --- /dev/null +++ b/src/main/fragment/mos6502-common/pwsc1_derefidx_vbuyy=_deref_pwsc2.asm @@ -0,0 +1,4 @@ +lda {c2} +sta {c1},y +lda {c2}+1 +sta {c1}+1,y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java index 14e7c1b9d..1a8ef4271 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java @@ -4,10 +4,7 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantLiteral; -import dk.camelot64.kickc.model.values.ConstantPointer; -import dk.camelot64.kickc.model.values.ConstantString; +import dk.camelot64.kickc.model.values.*; /** Unary Cast to double word operator ( (dword) x ) */ public class OperatorCastDWord extends OperatorCast { @@ -20,6 +17,8 @@ public class OperatorCastDWord extends OperatorCast { public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.DWORD); + } else if(value instanceof ConstantChar) { + return new ConstantInteger(((ConstantChar) value).getInteger(), SymbolType.DWORD); } else if(value instanceof ConstantPointer) { return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.DWORD); } else if(value instanceof ConstantString) { diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java index 7d020c032..c1c0f35e8 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantChar; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -17,6 +18,8 @@ public class OperatorCastSByte extends OperatorCast { public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.SBYTE); + } else if(value instanceof ConstantChar) { + return new ConstantInteger(((ConstantChar) value).getInteger(), SymbolType.SBYTE); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java index bea05b604..5a23932fa 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantChar; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -17,6 +18,8 @@ public class OperatorCastSDWord extends OperatorCast { public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.SDWORD); + } else if(value instanceof ConstantChar) { + return new ConstantInteger(((ConstantChar) value).getInteger(), SymbolType.SDWORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java index 7954d4243..1d4f5567e 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java @@ -3,6 +3,7 @@ package dk.camelot64.kickc.model.operators; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.values.ConstantChar; import dk.camelot64.kickc.model.values.ConstantInteger; import dk.camelot64.kickc.model.values.ConstantLiteral; @@ -17,6 +18,8 @@ public class OperatorCastSWord extends OperatorCast { public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.SWORD); + } else if(value instanceof ConstantChar) { + return new ConstantInteger(((ConstantChar) value).getInteger(), SymbolType.SWORD); } throw new CompileError("Calculation not implemented " + getOperator() + " " + value ); } diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java index c5b349696..027391233 100644 --- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java +++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java @@ -4,10 +4,7 @@ import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.ConstantInteger; -import dk.camelot64.kickc.model.values.ConstantLiteral; -import dk.camelot64.kickc.model.values.ConstantPointer; -import dk.camelot64.kickc.model.values.ConstantString; +import dk.camelot64.kickc.model.values.*; /** Unary Cast to word operator ( (word) x ) */ public class OperatorCastWord extends OperatorCast { @@ -20,6 +17,8 @@ public class OperatorCastWord extends OperatorCast { public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) { if(value instanceof ConstantInteger) { return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.WORD); + } else if(value instanceof ConstantChar) { + return new ConstantInteger(((ConstantChar) value).getInteger(), SymbolType.WORD); } else if(value instanceof ConstantPointer) { return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.WORD); } else if(value instanceof ConstantString) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java index b07f1b2a7..cfcc4b46d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java @@ -4,10 +4,7 @@ import dk.camelot64.kickc.model.InternalError; import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.statements.*; -import dk.camelot64.kickc.model.symbols.Procedure; -import dk.camelot64.kickc.model.symbols.ProgramScope; -import dk.camelot64.kickc.model.symbols.StructDefinition; -import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeStruct; @@ -314,6 +311,9 @@ public class Pass1UnwindStructValues extends Pass1Base { if(value instanceof ConstantStructValue) // A constant struct value return true; + if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof PointerDereference) + // A member of a struct in memory + return true; if(value instanceof PointerDereference) { final SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), value); if(symbolType instanceof SymbolTypeStruct) @@ -341,15 +341,28 @@ public class Pass1UnwindStructValues extends Pass1Base { return new RValueUnwindingStructVariable(variable); } } - if(value instanceof StructZero) { + if(value instanceof StructZero) return new RValueUnwindingZero(valueType, null); - } - if(value instanceof ConstantStructValue) { + if(value instanceof ConstantStructValue) return new RValueUnwindingConstant(valueType, null, (ConstantStructValue) value); - } - if(value instanceof PointerDereference) { + if(value instanceof PointerDereference) return new RValueUnwindingStructPointerDeref((PointerDereference) value, (SymbolTypeStruct) valueType); + if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof PointerDereferenceIndexed) { + final StructMemberRef structMemberRef = (StructMemberRef) value; + final PointerDereferenceIndexed structPointerDerefIdx = (PointerDereferenceIndexed) structMemberRef.getStruct(); + final SymbolType structPointerType = SymbolTypeInference.inferType(getScope(), structPointerDerefIdx); + if(!(structPointerType instanceof SymbolTypeStruct)) + throw new CompileError("Value is not a struct"+structPointerDerefIdx.toString(getProgram()), currentStmt); + + final StructDefinition structDefinition = ((SymbolTypeStruct) structPointerType).getStructDefinition(getScope()); + final String memberName = structMemberRef.getMemberName(); + final Variable member = structDefinition.getMember(memberName); + final SymbolType memberType = member.getType(); + final ArraySpec memberArraySpec = member.getArraySpec(); + final ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(getScope(), structDefinition, memberName); + return new RValueUnwindingStructPointerDereferenceIndexedMember(structPointerDerefIdx, memberType, memberArraySpec, memberOffsetConstant, currentBlock, stmtIt, currentStmt); } + } } return null; @@ -396,6 +409,9 @@ public class Pass1UnwindStructValues extends Pass1Base { return new StructUnwindingPointerDerefSimple((PointerDereferenceSimple) value, structDefinition, stmtIt, currentBlock, currentStmt); } else if(value instanceof PointerDereferenceIndexed) { return new StructUnwindingPointerDerefIndexed((PointerDereferenceIndexed) value, structDefinition, stmtIt, currentBlock, currentStmt); + } else if(value instanceof StructMemberRef && ((StructMemberRef) value).getStruct() instanceof PointerDereferenceIndexed) { + final StructMemberRef structMemberRef = (StructMemberRef) value; + return new StructUnwindingMemberOfPointerDerefIndexed((PointerDereferenceIndexed) structMemberRef.getStruct(),structMemberRef.getMemberName(), structDefinition, stmtIt, currentBlock, currentStmt); } else if(value instanceof ConstantStructValue) { return new StructUnwindingConstant((ConstantStructValue) value, structDefinition); } else if(value instanceof StructZero) { diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimple.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimpleMember.java similarity index 86% rename from src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimple.java rename to src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimpleMember.java index 33e933e0f..c3ab4f7ee 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimple.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDerefSimpleMember.java @@ -11,7 +11,7 @@ import dk.camelot64.kickc.model.values.*; import java.util.ListIterator; -public class RValueUnwindingStructPointerDerefSimple implements RValueUnwinding { +public class RValueUnwindingStructPointerDerefSimpleMember implements RValueUnwinding { private final PointerDereferenceSimple structPointerDeref; private final ArraySpec memberArraySpec; private final SymbolType memberType; @@ -21,7 +21,7 @@ public class RValueUnwindingStructPointerDerefSimple implements RValueUnwinding private final ListIterator stmtIt; private final Statement currentStmt; - public RValueUnwindingStructPointerDerefSimple(PointerDereferenceSimple structPointerDeref, ArraySpec memberArraySpec, SymbolType memberType, ConstantRef memberOffsetConstant, ControlFlowBlock currentBlock, ListIterator stmtIt, Statement currentStmt) { + public RValueUnwindingStructPointerDerefSimpleMember(PointerDereferenceSimple structPointerDeref, ArraySpec memberArraySpec, SymbolType memberType, ConstantRef memberOffsetConstant, ControlFlowBlock currentBlock, ListIterator stmtIt, Statement currentStmt) { this.structPointerDeref = structPointerDeref; this.memberArraySpec = memberArraySpec; this.memberType = memberType; diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDereferenceIndexedMember.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDereferenceIndexedMember.java index bb24de6ed..9ae0934bf 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDereferenceIndexedMember.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwindingStructPointerDereferenceIndexedMember.java @@ -7,11 +7,12 @@ import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.symbols.*; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; import dk.camelot64.kickc.model.values.*; import java.util.ListIterator; -class RValueUnwindingStructPointerDereferenceIndexedMember implements RValueUnwinding { +public class RValueUnwindingStructPointerDereferenceIndexedMember implements RValueUnwinding { private final PointerDereferenceIndexed structPointerDeref; private final SymbolType memberType; private final ArraySpec memberArraySpec; @@ -54,7 +55,7 @@ class RValueUnwindingStructPointerDereferenceIndexedMember implements RValueUnwi @Override public boolean isBulkCopyable() { - return getArraySpec() != null; + return getArraySpec() != null || memberType instanceof SymbolTypeStruct; } @Override @@ -64,6 +65,6 @@ class RValueUnwindingStructPointerDereferenceIndexedMember implements RValueUnwi @Override public RValue getBulkRValue(ProgramScope scope) { - throw new RuntimeException("TODO: Implement!"); + return getUnwinding(scope); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingMemberOfPointerDerefIndexed.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingMemberOfPointerDerefIndexed.java new file mode 100644 index 000000000..6b9361fbf --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingMemberOfPointerDerefIndexed.java @@ -0,0 +1,87 @@ +package dk.camelot64.kickc.passes.unwinding; + +import dk.camelot64.kickc.model.CompileError; +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.operators.Operators; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementAssignment; +import dk.camelot64.kickc.model.symbols.*; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypePointer; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; +import dk.camelot64.kickc.model.values.CastValue; +import dk.camelot64.kickc.model.values.ConstantRef; +import dk.camelot64.kickc.model.values.LValue; +import dk.camelot64.kickc.model.values.PointerDereferenceIndexed; +import dk.camelot64.kickc.passes.PassNStructPointerRewriting; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +public class StructUnwindingMemberOfPointerDerefIndexed implements StructUnwinding { + + // The struct member reference a[i].b + private final PointerDereferenceIndexed structRef; + private final String memberRef; + + // The referenced struct (type of b) + private final StructDefinition structDefinition; + + // For adding any needed statements + private final ListIterator stmtIt; + private final ControlFlowBlock currentBlock; + private final Statement currentStmt; + + public StructUnwindingMemberOfPointerDerefIndexed(PointerDereferenceIndexed structRef, String memberRef, StructDefinition structDefinition, ListIterator stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) { + this.structRef = structRef; + this.memberRef = memberRef; + this.structDefinition = structDefinition; + this.stmtIt = stmtIt; + this.currentBlock = currentBlock; + this.currentStmt = currentStmt; + } + + @Override + public List getMemberNames() { + Collection structMemberVars = structDefinition.getAllVariables(false); + ArrayList memberNames = new ArrayList<>(); + for(Variable structMemberVar : structMemberVars) { + memberNames.add(structMemberVar.getLocalName()); + } + return memberNames; + } + + @Override + public RValueUnwinding getMemberUnwinding(String memberName, ProgramScope programScope) { + // a[i].b.c -> ((memberType*)a+OFFSET_B+OFFSET_C)[i] + + + // Type of b + SymbolType outerStructType = SymbolTypeInference.inferType(programScope, structRef); + if(!(outerStructType instanceof SymbolTypeStruct)) + throw new CompileError("Error! Member is not a struct " + memberRef, currentStmt); + StructDefinition outerStructDefinition = ((SymbolTypeStruct) outerStructType).getStructDefinition(programScope); + ConstantRef outerMemberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, outerStructDefinition, memberRef); + + Variable member = this.structDefinition.getMember(memberName); + SymbolType memberType = member.getType(); + + Scope scope = programScope.getScope(currentBlock.getScope()); + Variable outerMemberAddress = scope.addVariableIntermediate(); + outerMemberAddress.setType(new SymbolTypePointer(memberType)); + CastValue structTypedPointer = new CastValue(new SymbolTypePointer(memberType), structRef.getPointer()); + // Add statement $1 = (elmType*)ptr_struct + OFFSET_B + stmtIt.add(new StatementAssignment((LValue) outerMemberAddress.getRef(), structTypedPointer, Operators.PLUS, outerMemberOffsetConstant, true, currentStmt.getSource(), currentStmt.getComments())); + // Unwind to ((elmType*)ptr_struct+OFFSET_B)[idx] + PointerDereferenceIndexed outerMemberIndexing = new PointerDereferenceIndexed(outerMemberAddress.getRef(), structRef.getIndex()); + + ConstantRef memberOffsetConstant = PassNStructPointerRewriting.getMemberOffsetConstant(programScope, this.structDefinition, memberName); + ArraySpec memberArraySpec = member.getArraySpec(); + + return new RValueUnwindingStructPointerDereferenceIndexedMember(outerMemberIndexing, memberType, memberArraySpec, memberOffsetConstant, currentBlock, stmtIt, currentStmt); + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingPointerDerefSimple.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingPointerDerefSimple.java index 9cdc6eda8..743d1ecb6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingPointerDerefSimple.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/StructUnwindingPointerDerefSimple.java @@ -45,7 +45,7 @@ public class StructUnwindingPointerDerefSimple implements StructUnwinding { Variable member = structDefinition.getMember(memberName); SymbolType memberType = member.getType(); ArraySpec memberArraySpec = member.getArraySpec(); - return new RValueUnwindingStructPointerDerefSimple(pointerDeref, memberArraySpec, memberType, memberOffsetConstant, currentBlock, stmtIt, currentStmt); + return new RValueUnwindingStructPointerDerefSimpleMember(pointerDeref, memberArraySpec, memberType, memberOffsetConstant, currentBlock, stmtIt, currentStmt); } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index fa20d95a3..f24b14bd6 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1153,6 +1153,21 @@ public class TestPrograms { assertError("struct-err-0", "Unknown struct type"); } + @Test + public void testStruct39() throws IOException, URISyntaxException { + compileAndCompare("struct-39"); + } + + @Test + public void testStruct38() throws IOException, URISyntaxException { + compileAndCompare("struct-38"); + } + + @Test + public void testStruct37() throws IOException, URISyntaxException { + compileAndCompare("struct-37"); + } + @Test public void testStruct36() throws IOException, URISyntaxException { compileAndCompare("struct-36"); diff --git a/src/test/kc/complex/splines/truetype-splines.kc b/src/test/kc/complex/splines/truetype-splines.kc index 744d913a6..583e52c57 100644 --- a/src/test/kc/complex/splines/truetype-splines.kc +++ b/src/test/kc/complex/splines/truetype-splines.kc @@ -69,11 +69,11 @@ void main() { void show_letter(char angle) { struct SplineVector16 current = {0,0}; for( byte i: 0..21) { - struct SplineVector16 to = { letter_c[i].to.x, letter_c[i].to.y }; + struct SplineVector16 to = letter_c[i].to; to = { to.x - 50, to.y - 150}; to = rotate(to, angle); to = { to.x + 100, to.y + 100}; - struct SplineVector16 via = { letter_c[i].via.x, letter_c[i].via.y }; + struct SplineVector16 via = letter_c[i].via; via = { via.x - 50, via.y - 150}; via = rotate(via, angle); via = { via.x + 100, via.y + 100}; diff --git a/src/test/kc/struct-37.kc b/src/test/kc/struct-37.kc new file mode 100644 index 000000000..bbfca8ecd --- /dev/null +++ b/src/test/kc/struct-37.kc @@ -0,0 +1,32 @@ +// Complex C-struct - copying a sub-struct from C-standard layout to Unwound layout + +// Vector with 16-coordinates that is part of a spline +struct SplineVector16 { + char x; + char y; +}; + +// A segment of a spline +struct Segment { + enum SegmentType { MOVE_TO, SPLINE_TO, LINE_TO} type; + struct SplineVector16 to; + struct SplineVector16 via; +}; + +// True type letter c +struct Segment[] letter_c = { + { MOVE_TO, {'a','b'}, {0,0} }, + { SPLINE_TO, {'c','d'}, {103,169} }, + { SPLINE_TO, {'e','f'}, {75,195} } +}; + +const char* SCREEN = 0x0400; + +void main() { + char j=0; + for( byte i: 0..2) { + struct SplineVector16 to = letter_c[i].to; + SCREEN[j++] = to.x; + SCREEN[j++] = to.y; + } +} \ No newline at end of file diff --git a/src/test/kc/struct-38.kc b/src/test/kc/struct-38.kc new file mode 100644 index 000000000..e8eea2cd5 --- /dev/null +++ b/src/test/kc/struct-38.kc @@ -0,0 +1,32 @@ +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to Unwound layout + +// Vector with 16-coordinates that is part of a spline +struct SplineVector16 { + signed int x; + signed int y; +}; + +// A segment of a spline +struct Segment { + enum SegmentType { MOVE_TO, SPLINE_TO, LINE_TO} type; + struct SplineVector16 to; + struct SplineVector16 via; +}; + +// True type letter c +struct Segment[] letter_c = { + { MOVE_TO, {'a','b'}, {0,0} }, + { SPLINE_TO, {'c','d'}, {103,169} }, + { SPLINE_TO, {'e','f'}, {75,195} } +}; + +const signed int* SCREEN = 0x0400; + +void main() { + char j=0; + for( byte i: 0..2) { + struct SplineVector16 to = letter_c[i].to; + SCREEN[j++] = to.x; + SCREEN[j++] = to.y; + } +} \ No newline at end of file diff --git a/src/test/kc/struct-39.kc b/src/test/kc/struct-39.kc new file mode 100644 index 000000000..8e4f66c77 --- /dev/null +++ b/src/test/kc/struct-39.kc @@ -0,0 +1,32 @@ +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to C-standard layout (expecting a memcpy) + +// Vector with 16-coordinates that is part of a spline +struct Vector { + signed int x; + signed int y; +}; + +// A segment of a spline +struct Segment { + enum SegmentType { MOVE_TO, SPLINE_TO, LINE_TO} type; + struct Vector to; + struct Vector via; +}; + +// True type letter c +struct Segment[] letter_c = { + { MOVE_TO, {'a','b'}, {0,0} }, + { SPLINE_TO, {'c','d'}, {103,169} }, + { SPLINE_TO, {'e','f'}, {75,195} } +}; + +const signed int* SCREEN = 0x0400; + +void main() { + char j=0; + for( byte i: 0..2) { + __ma struct Vector to = letter_c[i].to; + SCREEN[j++] = to.x; + SCREEN[j++] = to.y; + } +} \ No newline at end of file diff --git a/src/test/ref/complex/splines/truetype-splines.cfg b/src/test/ref/complex/splines/truetype-splines.cfg index 21f5adfbb..eec98ee67 100644 --- a/src/test/ref/complex/splines/truetype-splines.cfg +++ b/src/test/ref/complex/splines/truetype-splines.cfg @@ -73,8 +73,8 @@ show_letter::@1: scope:[show_letter] from show_letter show_letter::@9 [28] (byte) show_letter::i#10 ← phi( show_letter/(byte) 0 show_letter::@9/(byte) show_letter::i#1 ) [29] (byte~) show_letter::$32 ← (byte) show_letter::i#10 << (byte) 3 [30] (byte~) show_letter::$20 ← (byte~) show_letter::$32 + (byte) show_letter::i#10 - [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) - [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) + [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) + [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [33] (signed word) show_letter::to_x#1 ← (signed word) show_letter::to_x#0 - (signed byte) $32 [34] (signed word) show_letter::to_y#1 ← (signed word) show_letter::to_y#0 - (signed word) $96 [35] (signed word) rotate::vector_x#0 ← (signed word) show_letter::to_x#1 @@ -91,8 +91,8 @@ show_letter::@6: scope:[show_letter] from show_letter::@1 [44] (signed word) show_letter::current_y#10 ← (signed word) show_letter::to_y#2 + (signed byte) $64 [45] (byte~) show_letter::$34 ← (byte) show_letter::i#10 << (byte) 3 [46] (byte~) show_letter::$21 ← (byte~) show_letter::$34 + (byte) show_letter::i#10 - [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) - [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) + [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) + [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [49] (signed word) show_letter::via_x#1 ← (signed word) show_letter::via_x#0 - (signed byte) $32 [50] (signed word) show_letter::via_y#1 ← (signed word) show_letter::via_y#0 - (signed word) $96 [51] (signed word) rotate::vector_x#1 ← (signed word) show_letter::via_x#1 diff --git a/src/test/ref/complex/splines/truetype-splines.log b/src/test/ref/complex/splines/truetype-splines.log index f8ea60a2a..083d5b1e6 100644 --- a/src/test/ref/complex/splines/truetype-splines.log +++ b/src/test/ref/complex/splines/truetype-splines.log @@ -12,8 +12,6 @@ Fixing pointer array-indexing *((dword*) ultoa::digit_values + (byte) ultoa::dig Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) show_letter::i) Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) show_letter::i) Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) show_letter::i) -Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) show_letter::i) -Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) show_letter::i) Fixing pointer array-indexing *((const struct SplineVector16*) SPLINE_8SEG + (number) 0) Fixing pointer array-indexing *((const struct SplineVector16*) SPLINE_8SEG + (byte) bitmap_plot_spline_8seg::n) Fixing pointer array-indexing *((const struct SplineVector16*) SPLINE_8SEG + (byte) bitmap_plot_spline_8seg::n) @@ -203,8 +201,8 @@ Adding struct value member variable copy *((signed word*~) spline_8segB::$35 + ( Adding struct value member variable copy *((signed word*~) spline_8segB::$36 + (number~) spline_8segB::$32) ← (signed word)(number~) spline_8segB::$21 Adding struct value member variable copy (signed word) show_letter::current_x ← (signed word) 0 Adding struct value member variable copy (signed word) show_letter::current_y ← (signed word) 0 -Adding struct value member variable copy (signed word) show_letter::to_x ← *((const struct Segment*) letter_c + (byte~) show_letter::$20).to.x -Adding struct value member variable copy (signed word) show_letter::to_y ← *((const struct Segment*) letter_c + (byte~) show_letter::$20).to.y +Adding struct value member variable copy (signed word) show_letter::to_x ← *((signed word*~) show_letter::$24 + (byte~) show_letter::$20) +Adding struct value member variable copy (signed word) show_letter::to_y ← *((signed word*~) show_letter::$26 + (byte~) show_letter::$20) Adding struct value member variable copy (signed word) show_letter::to_x ← (signed word)(number~) show_letter::$0 Adding struct value member variable copy (signed word) show_letter::to_y ← (signed word)(number~) show_letter::$1 Converted procedure call LValue to member unwinding { (signed word~) show_letter::$2_x, (signed word~) show_letter::$2_y } ← call rotate (struct SplineVector16) show_letter::to (byte) show_letter::angle @@ -213,8 +211,8 @@ Adding struct value member variable copy (signed word) show_letter::to_x ← (si Adding struct value member variable copy (signed word) show_letter::to_y ← (signed word~) show_letter::$2_y Adding struct value member variable copy (signed word) show_letter::to_x ← (signed word)(number~) show_letter::$3 Adding struct value member variable copy (signed word) show_letter::to_y ← (signed word)(number~) show_letter::$4 -Adding struct value member variable copy (signed word) show_letter::via_x ← *((const struct Segment*) letter_c + (byte~) show_letter::$21).via.x -Adding struct value member variable copy (signed word) show_letter::via_y ← *((const struct Segment*) letter_c + (byte~) show_letter::$21).via.y +Adding struct value member variable copy (signed word) show_letter::via_x ← *((signed word*~) show_letter::$28 + (byte~) show_letter::$21) +Adding struct value member variable copy (signed word) show_letter::via_y ← *((signed word*~) show_letter::$30 + (byte~) show_letter::$21) Adding struct value member variable copy (signed word) show_letter::via_x ← (signed word)(number~) show_letter::$5 Adding struct value member variable copy (signed word) show_letter::via_y ← (signed word)(number~) show_letter::$6 Converted procedure call LValue to member unwinding { (signed word~) show_letter::$7_x, (signed word~) show_letter::$7_y } ← call rotate (struct SplineVector16) show_letter::via (byte) show_letter::angle @@ -366,17 +364,9 @@ Adding struct value member variable copy (signed word) show_letter::current_x Adding struct value member variable copy (signed word) show_letter::current_y ← (signed word) show_letter::segment_to_y Replacing struct member reference (struct SplineVector16) show_letter::segment_to.x with member unwinding reference (signed word) show_letter::segment_to_x Replacing struct member reference (struct SplineVector16) show_letter::segment_to.y with member unwinding reference (signed word) show_letter::segment_to_y -Rewriting struct pointer member access *((const struct Segment*) letter_c + (byte~) show_letter::$20).to -Rewriting struct pointer member access *((const struct Segment*) letter_c + (byte~) show_letter::$20).to -Rewriting struct pointer member access *((const struct Segment*) letter_c + (byte~) show_letter::$21).via -Rewriting struct pointer member access *((const struct Segment*) letter_c + (byte~) show_letter::$21).via Rewriting struct pointer member access *((const struct Segment*) letter_c + (byte~) show_letter::$22).type Rewriting struct pointer member access *((const struct SplineVector16*) SPLINE_8SEG + (byte~) bitmap_plot_spline_8seg::$7).x Rewriting struct pointer member access *((const struct SplineVector16*) SPLINE_8SEG + (byte~) bitmap_plot_spline_8seg::$8).y -Rewriting struct pointer member access *((struct SplineVector16*~) show_letter::$23 + (byte~) show_letter::$20).x -Rewriting struct pointer member access *((struct SplineVector16*~) show_letter::$24 + (byte~) show_letter::$20).y -Rewriting struct pointer member access *((struct SplineVector16*~) show_letter::$25 + (byte~) show_letter::$21).x -Rewriting struct pointer member access *((struct SplineVector16*~) show_letter::$26 + (byte~) show_letter::$21).y Warning! Adding boolean cast to non-boolean condition *((byte*) strcpy::src) Warning! Adding boolean cast to non-boolean condition *((byte*) strlen::str) Warning! Adding boolean cast to non-boolean condition (number~) abs_u16::$1 @@ -1414,12 +1404,12 @@ show_letter::@1: scope:[show_letter] from show_letter show_letter::@5 (byte) show_letter::angle#1 ← phi( show_letter/(byte) show_letter::angle#3 show_letter::@5/(byte) show_letter::angle#4 ) (byte) show_letter::i#2 ← phi( show_letter/(byte) show_letter::i#0 show_letter::@5/(byte) show_letter::i#1 ) (byte~) show_letter::$20 ← (byte) show_letter::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT - (struct SplineVector16*~) show_letter::$23 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO - (signed word*~) show_letter::$28 ← (signed word*)(struct SplineVector16*~) show_letter::$23 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X - (signed word) show_letter::to_x#0 ← *((signed word*~) show_letter::$28 + (byte~) show_letter::$20) - (struct SplineVector16*~) show_letter::$24 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO - (signed word*~) show_letter::$29 ← (signed word*)(struct SplineVector16*~) show_letter::$24 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y - (signed word) show_letter::to_y#0 ← *((signed word*~) show_letter::$29 + (byte~) show_letter::$20) + (signed word*~) show_letter::$24 ← (signed word*)(signed word*~) show_letter::$23 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X + (signed word) show_letter::to_x#0 ← *((signed word*~) show_letter::$24 + (byte~) show_letter::$20) + (signed word*~) show_letter::$23 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + (signed word*~) show_letter::$26 ← (signed word*)(signed word*~) show_letter::$25 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (signed word) show_letter::to_y#0 ← *((signed word*~) show_letter::$26 + (byte~) show_letter::$20) + (signed word*~) show_letter::$25 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO (number~) show_letter::$0 ← (signed word) show_letter::to_x#0 - (number) $32 (number~) show_letter::$1 ← (signed word) show_letter::to_y#0 - (number) $96 (signed word) show_letter::to_x#1 ← (signed word)(number~) show_letter::$0 @@ -1447,12 +1437,12 @@ show_letter::@11: scope:[show_letter] from show_letter::@1 (signed word) show_letter::to_x#3 ← (signed word)(number~) show_letter::$3 (signed word) show_letter::to_y#3 ← (signed word)(number~) show_letter::$4 (byte~) show_letter::$21 ← (byte) show_letter::i#3 * (const byte) SIZEOF_STRUCT_SEGMENT - (struct SplineVector16*~) show_letter::$25 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA - (signed word*~) show_letter::$30 ← (signed word*)(struct SplineVector16*~) show_letter::$25 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X - (signed word) show_letter::via_x#0 ← *((signed word*~) show_letter::$30 + (byte~) show_letter::$21) - (struct SplineVector16*~) show_letter::$26 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA - (signed word*~) show_letter::$31 ← (signed word*)(struct SplineVector16*~) show_letter::$26 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y - (signed word) show_letter::via_y#0 ← *((signed word*~) show_letter::$31 + (byte~) show_letter::$21) + (signed word*~) show_letter::$28 ← (signed word*)(signed word*~) show_letter::$27 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X + (signed word) show_letter::via_x#0 ← *((signed word*~) show_letter::$28 + (byte~) show_letter::$21) + (signed word*~) show_letter::$27 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA + (signed word*~) show_letter::$30 ← (signed word*)(signed word*~) show_letter::$29 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (signed word) show_letter::via_y#0 ← *((signed word*~) show_letter::$30 + (byte~) show_letter::$21) + (signed word*~) show_letter::$29 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA (number~) show_letter::$5 ← (signed word) show_letter::via_x#0 - (number) $32 (number~) show_letter::$6 ← (signed word) show_letter::via_y#0 - (number) $96 (signed word) show_letter::via_x#1 ← (signed word)(number~) show_letter::$5 @@ -1482,8 +1472,8 @@ show_letter::@12: scope:[show_letter] from show_letter::@11 (signed word) show_letter::via_x#3 ← (signed word)(number~) show_letter::$8 (signed word) show_letter::via_y#3 ← (signed word)(number~) show_letter::$9 (byte~) show_letter::$22 ← (byte) show_letter::i#4 * (const byte) SIZEOF_STRUCT_SEGMENT - (byte*~) show_letter::$27 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TYPE - (byte) show_letter::segment_type#0 ← *((byte*~) show_letter::$27 + (byte~) show_letter::$22) + (byte*~) show_letter::$31 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TYPE + (byte) show_letter::segment_type#0 ← *((byte*~) show_letter::$31 + (byte~) show_letter::$22) (signed word) show_letter::segment_to_x#0 ← (signed word) show_letter::to_x#4 (signed word) show_letter::segment_to_y#0 ← (signed word) show_letter::to_y#4 (signed word) show_letter::segment_via_x#0 ← (signed word) show_letter::via_x#3 @@ -2623,18 +2613,18 @@ SYMBOL TABLE SSA (byte~) show_letter::$20 (byte~) show_letter::$21 (byte~) show_letter::$22 -(struct SplineVector16*~) show_letter::$23 -(struct SplineVector16*~) show_letter::$24 -(struct SplineVector16*~) show_letter::$25 -(struct SplineVector16*~) show_letter::$26 -(byte*~) show_letter::$27 +(signed word*~) show_letter::$23 +(signed word*~) show_letter::$24 +(signed word*~) show_letter::$25 +(signed word*~) show_letter::$26 +(signed word*~) show_letter::$27 (signed word*~) show_letter::$28 (signed word*~) show_letter::$29 (signed word~) show_letter::$2_x (signed word~) show_letter::$2_y (number~) show_letter::$3 (signed word*~) show_letter::$30 -(signed word*~) show_letter::$31 +(byte*~) show_letter::$31 (number~) show_letter::$4 (number~) show_letter::$5 (number~) show_letter::$6 @@ -3119,10 +3109,14 @@ Simplifying constant integer cast $fe Simplifying constant integer cast $ff Simplifying constant integer cast 9 Simplifying constant integer cast $3e7 +Simplifying constant integer cast (signed word*~) show_letter::$23 +Simplifying constant integer cast (signed word*~) show_letter::$25 Simplifying constant integer cast $32 Simplifying constant integer cast $96 Simplifying constant integer cast $64 Simplifying constant integer cast $64 +Simplifying constant integer cast (signed word*~) show_letter::$27 +Simplifying constant integer cast (signed word*~) show_letter::$29 Simplifying constant integer cast $32 Simplifying constant integer cast $96 Simplifying constant integer cast $64 @@ -3583,11 +3577,11 @@ Constant right-side identified [38] (signed word*~) spline_8segB::$34 ← (signe Constant right-side identified [56] (byte~) spline_8segB::$32 ← (byte) 8 * (const byte) SIZEOF_STRUCT_SPLINEVECTOR16 Constant right-side identified [57] (signed word*~) spline_8segB::$35 ← (signed word*)(const struct SplineVector16*) SPLINE_8SEG + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X Constant right-side identified [59] (signed word*~) spline_8segB::$36 ← (signed word*)(const struct SplineVector16*) SPLINE_8SEG + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant right-side identified [442] (struct SplineVector16*~) show_letter::$23 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO -Constant right-side identified [445] (struct SplineVector16*~) show_letter::$24 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO -Constant right-side identified [468] (struct SplineVector16*~) show_letter::$25 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA -Constant right-side identified [471] (struct SplineVector16*~) show_letter::$26 ← (struct SplineVector16*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA -Constant right-side identified [494] (byte*~) show_letter::$27 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TYPE +Constant right-side identified [444] (signed word*~) show_letter::$23 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Constant right-side identified [447] (signed word*~) show_letter::$25 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Constant right-side identified [470] (signed word*~) show_letter::$27 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA +Constant right-side identified [473] (signed word*~) show_letter::$29 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_VIA +Constant right-side identified [494] (byte*~) show_letter::$31 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TYPE Constant right-side identified [539] (byte~) bitmap_plot_spline_8seg::$6 ← (byte) 0 * (const byte) SIZEOF_STRUCT_SPLINEVECTOR16 Constant right-side identified [540] (signed word*~) bitmap_plot_spline_8seg::$10 ← (signed word*)(const struct SplineVector16*) SPLINE_8SEG + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X Constant right-side identified [542] (signed word*~) bitmap_plot_spline_8seg::$11 ← (signed word*)(const struct SplineVector16*) SPLINE_8SEG + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y @@ -3637,11 +3631,11 @@ Constant (const byte) main::w#0 = 0 Constant (const signed word) show_letter::current_x#0 = 0 Constant (const signed word) show_letter::current_y#0 = 0 Constant (const byte) show_letter::i#0 = 0 -Constant (const struct SplineVector16*) show_letter::$23 = (struct SplineVector16*)letter_c+OFFSET_STRUCT_SEGMENT_TO -Constant (const struct SplineVector16*) show_letter::$24 = (struct SplineVector16*)letter_c+OFFSET_STRUCT_SEGMENT_TO -Constant (const struct SplineVector16*) show_letter::$25 = (struct SplineVector16*)letter_c+OFFSET_STRUCT_SEGMENT_VIA -Constant (const struct SplineVector16*) show_letter::$26 = (struct SplineVector16*)letter_c+OFFSET_STRUCT_SEGMENT_VIA -Constant (const byte*) show_letter::$27 = (byte*)letter_c+OFFSET_STRUCT_SEGMENT_TYPE +Constant (const signed word*) show_letter::$23 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Constant (const signed word*) show_letter::$25 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Constant (const signed word*) show_letter::$27 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_VIA +Constant (const signed word*) show_letter::$29 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_VIA +Constant (const byte*) show_letter::$31 = (byte*)letter_c+OFFSET_STRUCT_SEGMENT_TYPE Constant (const byte) bitmap_plot_spline_8seg::$6 = 0*SIZEOF_STRUCT_SPLINEVECTOR16 Constant (const signed word*) bitmap_plot_spline_8seg::$10 = (signed word*)SPLINE_8SEG+OFFSET_STRUCT_SPLINEVECTOR16_X Constant (const signed word*) bitmap_plot_spline_8seg::$11 = (signed word*)SPLINE_8SEG+OFFSET_STRUCT_SPLINEVECTOR16_Y @@ -3660,11 +3654,6 @@ Successful SSA optimization Pass2ConstantIdentification Constant (const void*) memset::str#0 = (void*)bitmap_screen#1 Constant (const void*) memset::str#1 = (void*)bitmap_gfx#1 Successful SSA optimization Pass2ConstantIdentification -Constant value identified (signed word*)show_letter::$23 in [443] (signed word*~) show_letter::$28 ← (signed word*)(const struct SplineVector16*) show_letter::$23 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X -Constant value identified (signed word*)show_letter::$24 in [446] (signed word*~) show_letter::$29 ← (signed word*)(const struct SplineVector16*) show_letter::$24 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant value identified (signed word*)show_letter::$25 in [469] (signed word*~) show_letter::$30 ← (signed word*)(const struct SplineVector16*) show_letter::$25 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X -Constant value identified (signed word*)show_letter::$26 in [472] (signed word*~) show_letter::$31 ← (signed word*)(const struct SplineVector16*) show_letter::$26 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Successful SSA optimization Pass2ConstantValues if() condition always true - replacing block destination [406] if(true) goto main::@2 if() condition always true - replacing block destination [429] if(true) goto main::@14 Successful SSA optimization Pass2ConstantIfs @@ -3688,8 +3677,8 @@ Simplifying expression containing zero (byte*)letter_c in Simplifying expression containing zero (signed word*)SPLINE_8SEG in Simplifying expression containing zero (signed word*)SPLINE_8SEG in Simplifying expression containing zero (signed word*)SPLINE_8SEG in -Simplifying expression containing zero (signed word*)show_letter::$23 in [443] (signed word*~) show_letter::$28 ← (signed word*)(const struct SplineVector16*) show_letter::$23 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X -Simplifying expression containing zero (signed word*)show_letter::$25 in [469] (signed word*~) show_letter::$30 ← (signed word*)(const struct SplineVector16*) show_letter::$25 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Simplifying expression containing zero show_letter::$23 in [442] (signed word*~) show_letter::$24 ← (const signed word*) show_letter::$23 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Simplifying expression containing zero show_letter::$27 in [468] (signed word*~) show_letter::$28 ← (const signed word*) show_letter::$27 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X Simplifying expression containing zero bitmap_plot_spline_8seg::$10 in [541] (signed word) bitmap_plot_spline_8seg::current_x#0 ← *((const signed word*) bitmap_plot_spline_8seg::$10 + (const byte) bitmap_plot_spline_8seg::$6) Simplifying expression containing zero bitmap_plot_spline_8seg::$11 in [543] (signed word) bitmap_plot_spline_8seg::current_y#0 ← *((const signed word*) bitmap_plot_spline_8seg::$11 + (const byte) bitmap_plot_spline_8seg::$6) Successful SSA optimization PassNSimplifyExpressionWithZero @@ -3761,16 +3750,16 @@ Successful SSA optimization Pass2ConditionalJumpSequenceImprovement Constant right-side identified [207] (byte~) main::vicSelectGfxBank1_toDd001_$1 ← > (const word) main::vicSelectGfxBank1_toDd001_$0 Constant right-side identified [211] (word~) main::toD0181_$1 ← (const word) main::toD0181_$0 & (word) $3fff Constant right-side identified [214] (byte~) main::toD0181_$5 ← > (const word) main::toD0181_$4 -Constant right-side identified [234] (signed word*~) show_letter::$29 ← (signed word*)(const struct SplineVector16*) show_letter::$24 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant right-side identified [255] (signed word*~) show_letter::$31 ← (signed word*)(const struct SplineVector16*) show_letter::$26 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant right-side identified [234] (signed word*~) show_letter::$26 ← (const signed word*) show_letter::$25 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant right-side identified [255] (signed word*~) show_letter::$30 ← (const signed word*) show_letter::$29 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::vicSelectGfxBank1_toDd001_$1 = >main::vicSelectGfxBank1_toDd001_$0 Constant (const word) main::toD0181_$1 = main::toD0181_$0&$3fff Constant (const byte) main::toD0181_$5 = >main::toD0181_$4 -Constant (const signed word*) show_letter::$28 = (signed word*)show_letter::$23 -Constant (const signed word*) show_letter::$29 = (signed word*)show_letter::$24+OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant (const signed word*) show_letter::$30 = (signed word*)show_letter::$25 -Constant (const signed word*) show_letter::$31 = (signed word*)show_letter::$26+OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant (const signed word*) show_letter::$24 = show_letter::$23 +Constant (const signed word*) show_letter::$26 = show_letter::$25+OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant (const signed word*) show_letter::$28 = show_letter::$27 +Constant (const signed word*) show_letter::$30 = show_letter::$29+OFFSET_STRUCT_SPLINEVECTOR16_Y Successful SSA optimization Pass2ConstantIdentification Eliminating unused constant (const byte*) PRINT_SCREEN Successful SSA optimization PassNEliminateUnusedVars @@ -3885,13 +3874,13 @@ Constant inlined bitmap_gfx#1 = (const byte*) BITMAP_GRAPHICS Constant inlined main::toD0181_$0 = (word)(const byte*) BITMAP_SCREEN Constant inlined show_letter::current_x#0 = (signed word) 0 Constant inlined main::toD0181_$6 = >(word)(const byte*) BITMAP_GRAPHICS/(byte) 4 -Constant inlined show_letter::$24 = (struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined show_letter::$24 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO Constant inlined main::toD0181_$5 = >(word)(const byte*) BITMAP_GRAPHICS -Constant inlined show_letter::$25 = (struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA +Constant inlined show_letter::$25 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO Constant inlined main::w#0 = (byte) 0 Constant inlined main::toD0181_$4 = (word)(const byte*) BITMAP_GRAPHICS +Constant inlined show_letter::$23 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO Constant inlined main::toD0181_$3 = >(word)(const byte*) BITMAP_SCREEN&(word) $3fff*(byte) 4 -Constant inlined show_letter::$23 = (struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO Constant inlined bitmap_plot_spline_8seg::$12 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG Constant inlined bitmap_plot_spline_8seg::$13 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y Constant inlined bitmap_plot_spline_8seg::$14 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG @@ -3906,19 +3895,19 @@ Constant inlined bitmap_plot_spline_8seg::$11 = (signed word*)(const struct Spli Constant inlined mulf_init::c#0 = (byte) 0 Constant inlined main::toD0181_screen#0 = (const byte*) BITMAP_SCREEN Constant inlined main::toD0181_gfx#0 = (const byte*) BITMAP_GRAPHICS -Constant inlined show_letter::$31 = (signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant inlined show_letter::$30 = (signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA +Constant inlined show_letter::$31 = (byte*)(const struct Segment*) letter_c +Constant inlined show_letter::$30 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y Constant inlined bitmap_init::bits#0 = (byte) $80 Constant inlined spline_8segB::$36 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y Constant inlined bitmap_init::bits#2 = (byte) $80 Constant inlined spline_8segB::$32 = (byte) 8*(const byte) SIZEOF_STRUCT_SPLINEVECTOR16 -Constant inlined show_letter::$28 = (signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined show_letter::$28 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA Constant inlined spline_8segB::$33 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG -Constant inlined show_letter::$29 = (signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant inlined show_letter::$29 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA Constant inlined spline_8segB::$34 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y -Constant inlined show_letter::$26 = (struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA +Constant inlined show_letter::$26 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant inlined show_letter::$27 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA Constant inlined spline_8segB::$35 = (signed word*)(const struct SplineVector16*) SPLINE_8SEG -Constant inlined show_letter::$27 = (byte*)(const struct Segment*) letter_c Constant inlined sgn_u16::return#3 = (byte) 1 Constant inlined sgn_u16::return#2 = (byte) -1 Constant inlined memset::str#1 = (void*)(const byte*) BITMAP_GRAPHICS @@ -4316,8 +4305,8 @@ show_letter::@1: scope:[show_letter] from show_letter show_letter::@9 [28] (byte) show_letter::i#10 ← phi( show_letter/(byte) 0 show_letter::@9/(byte) show_letter::i#1 ) [29] (byte~) show_letter::$32 ← (byte) show_letter::i#10 << (byte) 3 [30] (byte~) show_letter::$20 ← (byte~) show_letter::$32 + (byte) show_letter::i#10 - [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) - [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) + [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) + [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [33] (signed word) show_letter::to_x#1 ← (signed word) show_letter::to_x#0 - (signed byte) $32 [34] (signed word) show_letter::to_y#1 ← (signed word) show_letter::to_y#0 - (signed word) $96 [35] (signed word) rotate::vector_x#0 ← (signed word) show_letter::to_x#1 @@ -4334,8 +4323,8 @@ show_letter::@6: scope:[show_letter] from show_letter::@1 [44] (signed word) show_letter::current_y#10 ← (signed word) show_letter::to_y#2 + (signed byte) $64 [45] (byte~) show_letter::$34 ← (byte) show_letter::i#10 << (byte) 3 [46] (byte~) show_letter::$21 ← (byte~) show_letter::$34 + (byte) show_letter::i#10 - [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) - [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) + [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) + [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [49] (signed word) show_letter::via_x#1 ← (signed word) show_letter::via_x#0 - (signed byte) $32 [50] (signed word) show_letter::via_y#1 ← (signed word) show_letter::via_y#0 - (signed word) $96 [51] (signed word) rotate::vector_x#1 ← (signed word) show_letter::via_x#1 @@ -5984,13 +5973,13 @@ show_letter: { clc adc.z i sta.z __20 - // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuz2 + // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuz2 ldy.z __20 lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y sta.z to_x lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,y sta.z to_x+1 - // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuz2 + // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuz2 ldy.z __20 lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y sta.z to_y @@ -6082,13 +6071,13 @@ show_letter: { clc adc.z i sta.z __21 - // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuz2 + // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuz2 ldy.z __21 lda letter_c+OFFSET_STRUCT_SEGMENT_VIA,y sta.z via_x lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+1,y sta.z via_x+1 - // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuz2 + // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuz2 ldy.z __21 lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+OFFSET_STRUCT_SPLINEVECTOR16_Y,y sta.z via_y @@ -8428,9 +8417,9 @@ Statement [29] (byte~) show_letter::$32 ← (byte) show_letter::i#10 << (byte) 3 Removing always clobbered register reg byte a as potential for zp[1]:83 [ show_letter::angle#0 ] Removing always clobbered register reg byte a as potential for zp[1]:4 [ show_letter::i#10 show_letter::i#1 ] Statement [30] (byte~) show_letter::$20 ← (byte~) show_letter::$32 + (byte) show_letter::i#10 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 ] ) always clobbers reg byte a -Statement [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ) always clobbers reg byte a +Statement [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:85 [ show_letter::$20 ] -Statement [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ) always clobbers reg byte a +Statement [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ) always clobbers reg byte a Statement [33] (signed word) show_letter::to_x#1 ← (signed word) show_letter::to_x#0 - (signed byte) $32 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#0 show_letter::to_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#0 show_letter::to_x#1 ] ) always clobbers reg byte a Statement [34] (signed word) show_letter::to_y#1 ← (signed word) show_letter::to_y#0 - (signed word) $96 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#1 show_letter::to_y#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#1 show_letter::to_y#1 ] ) always clobbers reg byte a Statement [35] (signed word) rotate::vector_x#0 ← (signed word) show_letter::to_x#1 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#1 rotate::vector_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#1 rotate::vector_x#0 ] ) always clobbers reg byte a @@ -8443,9 +8432,9 @@ Statement [43] (signed word) show_letter::current_x#10 ← (signed word) show_le Statement [44] (signed word) show_letter::current_y#10 ← (signed word) show_letter::to_y#2 + (signed byte) $64 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 ] ) always clobbers reg byte a Statement [45] (byte~) show_letter::$34 ← (byte) show_letter::i#10 << (byte) 3 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$34 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$34 ] ) always clobbers reg byte a Statement [46] (byte~) show_letter::$21 ← (byte~) show_letter::$34 + (byte) show_letter::i#10 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 ] ) always clobbers reg byte a -Statement [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ) always clobbers reg byte a +Statement [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:107 [ show_letter::$21 ] -Statement [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ) always clobbers reg byte a +Statement [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ) always clobbers reg byte a Statement [49] (signed word) show_letter::via_x#1 ← (signed word) show_letter::via_x#0 - (signed byte) $32 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#0 show_letter::via_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#0 show_letter::via_x#1 ] ) always clobbers reg byte a Statement [50] (signed word) show_letter::via_y#1 ← (signed word) show_letter::via_y#0 - (signed word) $96 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#1 show_letter::via_y#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#1 show_letter::via_y#1 ] ) always clobbers reg byte a Statement [51] (signed word) rotate::vector_x#1 ← (signed word) show_letter::via_x#1 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#1 rotate::vector_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#1 rotate::vector_x#1 ] ) always clobbers reg byte a @@ -8664,8 +8653,8 @@ Statement [23] if(*((const byte*) RASTER)!=(byte) $ff) goto main::@4 [ main::ang Statement [26] (byte) main::angle#1 ← (byte) main::angle#2 + (byte) 9 [ main::angle#1 ] ( main:2 [ main::angle#1 ] ) always clobbers reg byte a reg byte x Statement [29] (byte~) show_letter::$32 ← (byte) show_letter::i#10 << (byte) 3 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$32 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$32 ] ) always clobbers reg byte a Statement [30] (byte~) show_letter::$20 ← (byte~) show_letter::$32 + (byte) show_letter::i#10 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 ] ) always clobbers reg byte a -Statement [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ) always clobbers reg byte a -Statement [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ) always clobbers reg byte a +Statement [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::$20 show_letter::to_x#0 ] ) always clobbers reg byte a +Statement [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#0 show_letter::to_y#0 ] ) always clobbers reg byte a Statement [33] (signed word) show_letter::to_x#1 ← (signed word) show_letter::to_x#0 - (signed byte) $32 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#0 show_letter::to_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#0 show_letter::to_x#1 ] ) always clobbers reg byte a Statement [34] (signed word) show_letter::to_y#1 ← (signed word) show_letter::to_y#0 - (signed word) $96 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#1 show_letter::to_y#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_x#1 show_letter::to_y#1 ] ) always clobbers reg byte a Statement [35] (signed word) rotate::vector_x#0 ← (signed word) show_letter::to_x#1 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#1 rotate::vector_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::to_y#1 rotate::vector_x#0 ] ) always clobbers reg byte a @@ -8678,8 +8667,8 @@ Statement [43] (signed word) show_letter::current_x#10 ← (signed word) show_le Statement [44] (signed word) show_letter::current_y#10 ← (signed word) show_letter::to_y#2 + (signed byte) $64 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 ] ) always clobbers reg byte a Statement [45] (byte~) show_letter::$34 ← (byte) show_letter::i#10 << (byte) 3 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$34 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$34 ] ) always clobbers reg byte a Statement [46] (byte~) show_letter::$21 ← (byte~) show_letter::$34 + (byte) show_letter::i#10 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 ] ) always clobbers reg byte a -Statement [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ) always clobbers reg byte a -Statement [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ) always clobbers reg byte a +Statement [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::$21 show_letter::via_x#0 ] ) always clobbers reg byte a +Statement [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#0 show_letter::via_y#0 ] ) always clobbers reg byte a Statement [49] (signed word) show_letter::via_x#1 ← (signed word) show_letter::via_x#0 - (signed byte) $32 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#0 show_letter::via_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#0 show_letter::via_x#1 ] ) always clobbers reg byte a Statement [50] (signed word) show_letter::via_y#1 ← (signed word) show_letter::via_y#0 - (signed word) $96 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#1 show_letter::via_y#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_x#1 show_letter::via_y#1 ] ) always clobbers reg byte a Statement [51] (signed word) rotate::vector_x#1 ← (signed word) show_letter::via_x#1 [ show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#1 rotate::vector_x#1 ] ( main:2::show_letter:20 [ main::angle#2 show_letter::angle#0 show_letter::i#10 show_letter::current_x#4 show_letter::current_y#4 show_letter::current_x#10 show_letter::current_y#10 show_letter::via_y#1 rotate::vector_x#1 ] ) always clobbers reg byte a @@ -9449,12 +9438,12 @@ show_letter: { clc adc.z i tax - // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx + // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x sta.z to_x lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,x sta.z to_x+1 - // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx + // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,x sta.z to_y lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,x @@ -9518,12 +9507,12 @@ show_letter: { clc adc.z i tax - // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx + // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_VIA,x sta.z via_x lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+1,x sta.z via_x+1 - // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx + // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+OFFSET_STRUCT_SPLINEVECTOR16_Y,x sta.z via_y lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,x @@ -12524,7 +12513,7 @@ show_letter: { sta.z i // show_letter::@1 __b1: - // to = { letter_c[i].to.x, letter_c[i].to.y } + // to = letter_c[i].to // [29] (byte~) show_letter::$32 ← (byte) show_letter::i#10 << (byte) 3 -- vbuaa=vbuz1_rol_3 lda.z i asl @@ -12534,12 +12523,12 @@ show_letter: { clc adc.z i tax - // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx + // [31] (signed word) show_letter::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x sta.z to_x lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,x sta.z to_x+1 - // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx + // [32] (signed word) show_letter::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$20) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,x sta.z to_y lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,x @@ -12596,7 +12585,7 @@ show_letter: { lda.z to_y_1+1 adc #>$64 sta.z current_y_1+1 - // via = { letter_c[i].via.x, letter_c[i].via.y } + // via = letter_c[i].via // [45] (byte~) show_letter::$34 ← (byte) show_letter::i#10 << (byte) 3 -- vbuaa=vbuz1_rol_3 lda.z i asl @@ -12606,12 +12595,12 @@ show_letter: { clc adc.z i tax - // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx + // [47] (signed word) show_letter::via_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_VIA,x sta.z via_x lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+1,x sta.z via_x+1 - // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(struct SplineVector16*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx + // [48] (signed word) show_letter::via_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_VIA+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) show_letter::$21) -- vwsz1=pwsc1_derefidx_vbuxx lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+OFFSET_STRUCT_SPLINEVECTOR16_Y,x sta.z via_y lda letter_c+OFFSET_STRUCT_SEGMENT_VIA+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,x diff --git a/src/test/ref/struct-37.asm b/src/test/ref/struct-37.asm new file mode 100644 index 000000000..7b7b0479d --- /dev/null +++ b/src/test/ref/struct-37.asm @@ -0,0 +1,43 @@ +// Complex C-struct - copying a sub-struct from C-standard layout to Unwound layout +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 1 +main: { + .label to_x = 3 + .label to_y = 4 + .label j = 2 + lda #0 + sta.z j + tax + __b1: + txa + asl + asl + stx.z $ff + clc + adc.z $ff + tay + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + lda.z to_x + ldy.z j + sta SCREEN,y + iny + lda.z to_y + sta SCREEN,y + iny + sty.z j + inx + cpx #3 + bne __b1 + rts +} + // True type letter c + letter_c: .byte MOVE_TO, 'a', 'b', 0, 0, SPLINE_TO, 'c', 'd', $67, $a9, SPLINE_TO, 'e', 'f', $4b, $c3 diff --git a/src/test/ref/struct-37.cfg b/src/test/ref/struct-37.cfg new file mode 100644 index 000000000..7d12a9694 --- /dev/null +++ b/src/test/ref/struct-37.cfg @@ -0,0 +1,31 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 + [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 + [8] (byte) main::to_x#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) + [9] (byte) main::to_y#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) + [10] *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 + [11] (byte) main::j#1 ← ++ (byte) main::j#3 + [12] *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 + [13] (byte) main::j#2 ← ++ (byte) main::j#1 + [14] (byte) main::i#1 ← ++ (byte) main::i#2 + [15] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [16] return + to:@return diff --git a/src/test/ref/struct-37.log b/src/test/ref/struct-37.log new file mode 100644 index 000000000..bf57f55e2 --- /dev/null +++ b/src/test/ref/struct-37.log @@ -0,0 +1,630 @@ +Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) main::i) +Created struct value member variable (byte) main::to_x +Created struct value member variable (byte) main::to_y +Converted struct value to member variables (struct SplineVector16) main::to +Adding struct value member variable copy (byte) main::to_x ← *((byte*~) main::$3 + (byte~) main::$1) +Adding struct value member variable copy (byte) main::to_y ← *((byte*~) main::$5 + (byte~) main::$1) +Replacing struct member reference (struct SplineVector16) main::to.x with member unwinding reference (byte) main::to_x +Replacing struct member reference (struct SplineVector16) main::to.y with member unwinding reference (byte) main::to_y +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::j#0 ← (byte) 0 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::j#3 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#2 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT + (byte*~) main::$3 ← (byte*)(byte*~) main::$2 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X + (byte) main::to_x#0 ← *((byte*~) main::$3 + (byte~) main::$1) + (byte*~) main::$2 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + (byte*~) main::$5 ← (byte*)(byte*~) main::$4 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte) main::to_y#0 ← *((byte*~) main::$5 + (byte~) main::$1) + (byte*~) main::$4 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 + (byte) main::j#1 ← ++ (byte) main::j#3 + *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 + (byte) main::j#2 ← ++ (byte) main::j#1 + (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,2) + (bool~) main::$0 ← (byte) main::i#1 != rangelast(0,2) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_X = (byte) 0 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 1 +(const byte*) SCREEN = (byte*)(number) $400 +(const byte) SIZEOF_STRUCT_SEGMENT = (byte) 5 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(byte) SplineVector16::x +(byte) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (byte) 'a', y: (byte) 'b' }, via: { x: (byte) 0, y: (byte) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'c', y: (byte) 'd' }, via: { x: (byte) $67, y: (byte) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'e', y: (byte) 'f' }, via: { x: (byte) $4b, y: (byte) $c3 } } } +(void()) main() +(bool~) main::$0 +(byte~) main::$1 +(byte*~) main::$2 +(byte*~) main::$3 +(byte*~) main::$4 +(byte*~) main::$5 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::j +(byte) main::j#0 +(byte) main::j#1 +(byte) main::j#2 +(byte) main::j#3 +(byte) main::to_x +(byte) main::to_x#0 +(byte) main::to_y +(byte) main::to_y#0 + +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast (byte*~) main::$2 +Simplifying constant integer cast (byte*~) main::$4 +Successful SSA optimization PassNCastSimplification +Simple Condition (bool~) main::$0 [16] if((byte) main::i#1!=rangelast(0,2)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [6] (byte*~) main::$2 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Constant right-side identified [9] (byte*~) main::$4 ← (byte*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::j#0 = 0 +Constant (const byte) main::i#0 = 0 +Constant (const byte*) main::$2 = (byte*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Constant (const byte*) main::$4 = (byte*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [14] main::i#1 ← ++ main::i#2 to ++ +Resolved ranged comparison value [16] if(main::i#1!=rangelast(0,2)) goto main::@1 to (number) 3 +Simplifying expression containing zero main::$2 in [4] (byte*~) main::$3 ← (const byte*) main::$2 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Successful SSA optimization PassNEliminateUnusedVars +Adding number conversion cast (unumber) 3 in if((byte) main::i#1!=(number) 3) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 3 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 3 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Constant right-side identified [4] (byte*~) main::$5 ← (const byte*) main::$4 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) main::$3 = main::$2 +Constant (const byte*) main::$5 = main::$4+OFFSET_STRUCT_SPLINEVECTOR16_Y +Successful SSA optimization Pass2ConstantIdentification +Rewriting multiplication to use shift and addition[1] (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT +Inlining constant with var siblings (const byte) main::j#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::$5 = (byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Constant inlined main::i#0 = (byte) 0 +Constant inlined main::$3 = (byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::$4 = (byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::j#0 = (byte) 0 +Constant inlined main::$2 = (byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantInlining +Alias (byte~) main::$1 = (byte~) main::$7 +Successful SSA optimization Pass2AliasElimination +Eliminating unused constant (const byte) SIZEOF_STRUCT_SEGMENT +Successful SSA optimization PassNEliminateUnusedVars +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 + +Created 2 initial phi equivalence classes +Coalesced [18] main::i#3 ← main::i#1 +Coalesced [19] main::j#4 ← main::j#2 +Coalesced down to 2 phi equivalence classes +Culled Empty Block (label) @2 +Culled Empty Block (label) main::@3 +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() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 + [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 + [8] (byte) main::to_x#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) + [9] (byte) main::to_y#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) + [10] *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 + [11] (byte) main::j#1 ← ++ (byte) main::j#3 + [12] *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 + [13] (byte) main::j#2 ← ++ (byte) main::j#1 + [14] (byte) main::i#1 ← ++ (byte) main::i#2 + [15] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [16] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(byte) SplineVector16::x +(byte) SplineVector16::y +(void()) main() +(byte~) main::$1 16.5 +(byte~) main::$6 22.0 +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 4.888888888888889 +(byte) main::j +(byte) main::j#1 16.5 +(byte) main::j#2 7.333333333333333 +(byte) main::j#3 5.5 +(byte) main::to_x +(byte) main::to_x#0 11.0 +(byte) main::to_y +(byte) main::to_y#0 7.333333333333333 + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +Added variable main::$6 to live range equivalence class [ main::$6 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable main::to_x#0 to live range equivalence class [ main::to_x#0 ] +Added variable main::to_y#0 to live range equivalence class [ main::to_y#0 ] +Added variable main::j#1 to live range equivalence class [ main::j#1 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +[ main::$6 ] +[ main::$1 ] +[ main::to_x#0 ] +[ main::to_y#0 ] +[ main::j#1 ] +Allocated zp[1]:2 [ main::i#2 main::i#1 ] +Allocated zp[1]:3 [ main::j#3 main::j#2 ] +Allocated zp[1]:4 [ main::$6 ] +Allocated zp[1]:5 [ main::$1 ] +Allocated zp[1]:6 [ main::to_x#0 ] +Allocated zp[1]:7 [ main::to_y#0 ] +Allocated zp[1]:8 [ main::j#1 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Complex C-struct - copying a sub-struct from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 1 + // @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 __1 = 5 + .label to_x = 6 + .label to_y = 7 + .label j = 8 + .label j_1 = 3 + .label i = 2 + .label __6 = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j_1 + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta.z i + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 -- vbuz1=vbuz2_rol_2 + lda.z i + asl + asl + sta.z __6 + // [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3 + lda.z __6 + clc + adc.z i + sta.z __1 + // [8] (byte) main::to_x#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __1 + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + // [9] (byte) main::to_y#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z __1 + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + // [10] *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z to_x + ldy.z j_1 + sta SCREEN,y + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuz1=_inc_vbuz2 + ldy.z j_1 + iny + sty.z j + // [12] *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z to_y + ldy.z j + sta SCREEN,y + // [13] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuz2 + ldy.z j + iny + sty.z j_1 + // [14] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [15] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #3 + cmp.z i + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [16] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO, 'a', 'b', 0, 0, SPLINE_TO, 'c', 'd', $67, $a9, SPLINE_TO, 'e', 'f', $4b, $c3 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 [ main::i#2 main::j#3 main::$6 ] ( main:2 [ main::i#2 main::j#3 main::$6 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::j#3 main::j#2 ] +Statement [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 ] ( main:2 [ main::i#2 main::j#3 main::$1 ] ) always clobbers reg byte a +Statement [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 [ main::i#2 main::j#3 main::$6 ] ( main:2 [ main::i#2 main::j#3 main::$6 ] ) always clobbers reg byte a +Statement [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 ] ( main:2 [ main::i#2 main::j#3 main::$1 ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::j#3 main::j#2 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ main::$6 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$1 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ main::to_x#0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ main::to_y#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ main::j#1 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 22: zp[1]:4 [ main::$6 ] 21.39: zp[1]:2 [ main::i#2 main::i#1 ] 16.5: zp[1]:5 [ main::$1 ] 16.5: zp[1]:8 [ main::j#1 ] 12.83: zp[1]:3 [ main::j#3 main::j#2 ] 11: zp[1]:6 [ main::to_x#0 ] 7.33: zp[1]:7 [ main::to_y#0 ] +Uplift Scope [SplineVector16] +Uplift Scope [Segment] +Uplift Scope [Segment::SegmentType] +Uplift Scope [] + +Uplifting [main] best 933 combination reg byte a [ main::$6 ] reg byte x [ main::i#2 main::i#1 ] reg byte y [ main::$1 ] zp[1]:8 [ main::j#1 ] zp[1]:3 [ main::j#3 main::j#2 ] zp[1]:6 [ main::to_x#0 ] zp[1]:7 [ main::to_y#0 ] +Limited combination testing to 100 combinations of 9216 possible. +Uplifting [SplineVector16] best 933 combination +Uplifting [Segment] best 933 combination +Uplifting [Segment::SegmentType] best 933 combination +Uplifting [] best 933 combination +Attempting to uplift remaining variables inzp[1]:8 [ main::j#1 ] +Uplifting [main] best 843 combination reg byte y [ main::j#1 ] +Attempting to uplift remaining variables inzp[1]:3 [ main::j#3 main::j#2 ] +Uplifting [main] best 843 combination zp[1]:3 [ main::j#3 main::j#2 ] +Attempting to uplift remaining variables inzp[1]:6 [ main::to_x#0 ] +Uplifting [main] best 843 combination zp[1]:6 [ main::to_x#0 ] +Attempting to uplift remaining variables inzp[1]:7 [ main::to_y#0 ] +Uplifting [main] best 843 combination zp[1]:7 [ main::to_y#0 ] +Allocated (was zp[1]:3) zp[1]:2 [ main::j#3 main::j#2 ] +Allocated (was zp[1]:6) zp[1]:3 [ main::to_x#0 ] +Allocated (was zp[1]:7) zp[1]:4 [ main::to_y#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Complex C-struct - copying a sub-struct from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 1 + // @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 to_x = 3 + .label to_y = 4 + .label j = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 -- vbuaa=vbuxx_rol_2 + txa + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tay + // [8] (byte) main::to_x#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + // [9] (byte) main::to_y#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + // [10] *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z to_x + ldy.z j + sta SCREEN,y + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuyy=_inc_vbuz1 + ldy.z j + iny + // [12] *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 -- pbuc1_derefidx_vbuyy=vbuz1 + lda.z to_y + sta SCREEN,y + // [13] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuyy + iny + sty.z j + // [14] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [15] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #3 + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [16] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO, 'a', 'b', 0, 0, SPLINE_TO, 'c', 'd', $67, $a9, SPLINE_TO, 'e', 'f', $4b, $c3 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldx #0 with TAX +Removing instruction ldy.z j +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label __bbegin with __b1 +Replacing label __b1_from___b1 with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction main_from___b1: +Removing instruction __bend_from___b1: +Removing instruction __b1_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 1 +(const byte*) SCREEN = (byte*) 1024 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(byte) SplineVector16::x +(byte) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (byte) 'a', y: (byte) 'b' }, via: { x: (byte) 0, y: (byte) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'c', y: (byte) 'd' }, via: { x: (byte) $67, y: (byte) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'e', y: (byte) 'f' }, via: { x: (byte) $4b, y: (byte) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte y 16.5 +(byte~) main::$6 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 4.888888888888889 +(byte) main::j +(byte) main::j#1 reg byte y 16.5 +(byte) main::j#2 j zp[1]:2 7.333333333333333 +(byte) main::j#3 j zp[1]:2 5.5 +(byte) main::to_x +(byte) main::to_x#0 to_x zp[1]:3 11.0 +(byte) main::to_y +(byte) main::to_y#0 to_y zp[1]:4 7.333333333333333 + +reg byte x [ main::i#2 main::i#1 ] +zp[1]:2 [ main::j#3 main::j#2 ] +reg byte a [ main::$6 ] +reg byte y [ main::$1 ] +zp[1]:3 [ main::to_x#0 ] +zp[1]:4 [ main::to_y#0 ] +reg byte y [ main::j#1 ] + + +FINAL ASSEMBLER +Score: 711 + + // File Comments +// Complex C-struct - copying a sub-struct from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 1 + // @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 to_x = 3 + .label to_y = 4 + .label j = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + tax + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + // main::@1 + __b1: + // to = letter_c[i].to + // [6] (byte~) main::$6 ← (byte) main::i#2 << (byte) 2 -- vbuaa=vbuxx_rol_2 + txa + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$6 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tay + // [8] (byte) main::to_x#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + // [9] (byte) main::to_y#0 ← *((byte*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vbuz1=pbuc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + // SCREEN[j++] = to.x + // [10] *((const byte*) SCREEN + (byte) main::j#3) ← (byte) main::to_x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z to_x + ldy.z j + sta SCREEN,y + // SCREEN[j++] = to.x; + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuyy=_inc_vbuz1 + iny + // SCREEN[j++] = to.y + // [12] *((const byte*) SCREEN + (byte) main::j#1) ← (byte) main::to_y#0 -- pbuc1_derefidx_vbuyy=vbuz1 + lda.z to_y + sta SCREEN,y + // SCREEN[j++] = to.y; + // [13] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuyy + iny + sty.z j + // for( byte i: 0..2) + // [14] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [15] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #3 + bne __b1 + // main::@return + // } + // [16] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO, 'a', 'b', 0, 0, SPLINE_TO, 'c', 'd', $67, $a9, SPLINE_TO, 'e', 'f', $4b, $c3 + diff --git a/src/test/ref/struct-37.sym b/src/test/ref/struct-37.sym new file mode 100644 index 000000000..d2d1ebbba --- /dev/null +++ b/src/test/ref/struct-37.sym @@ -0,0 +1,41 @@ +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 1 +(const byte*) SCREEN = (byte*) 1024 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(byte) SplineVector16::x +(byte) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (byte) 'a', y: (byte) 'b' }, via: { x: (byte) 0, y: (byte) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'c', y: (byte) 'd' }, via: { x: (byte) $67, y: (byte) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (byte) 'e', y: (byte) 'f' }, via: { x: (byte) $4b, y: (byte) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte y 16.5 +(byte~) main::$6 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 4.888888888888889 +(byte) main::j +(byte) main::j#1 reg byte y 16.5 +(byte) main::j#2 j zp[1]:2 7.333333333333333 +(byte) main::j#3 j zp[1]:2 5.5 +(byte) main::to_x +(byte) main::to_x#0 to_x zp[1]:3 11.0 +(byte) main::to_y +(byte) main::to_y#0 to_y zp[1]:4 7.333333333333333 + +reg byte x [ main::i#2 main::i#1 ] +zp[1]:2 [ main::j#3 main::j#2 ] +reg byte a [ main::$6 ] +reg byte y [ main::$1 ] +zp[1]:3 [ main::to_x#0 ] +zp[1]:4 [ main::to_y#0 ] +reg byte y [ main::j#1 ] diff --git a/src/test/ref/struct-38.asm b/src/test/ref/struct-38.asm new file mode 100644 index 000000000..6aa8e0033 --- /dev/null +++ b/src/test/ref/struct-38.asm @@ -0,0 +1,61 @@ +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to Unwound layout +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 2 +main: { + .label to_x = 3 + .label to_y = 5 + .label j = 2 + lda #0 + sta.z j + tax + __b1: + txa + asl + asl + asl + stx.z $ff + clc + adc.z $ff + tay + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,y + sta.z to_x+1 + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,y + sta.z to_y+1 + lda.z j + asl + tay + lda.z to_x + sta SCREEN,y + lda.z to_x+1 + sta SCREEN+1,y + inc.z j + lda.z j + asl + tay + lda.z to_y + sta SCREEN,y + lda.z to_y+1 + sta SCREEN+1,y + inc.z j + inx + cpx #3 + bne __b1 + rts +} + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 diff --git a/src/test/ref/struct-38.cfg b/src/test/ref/struct-38.cfg new file mode 100644 index 000000000..35e9b3acc --- /dev/null +++ b/src/test/ref/struct-38.cfg @@ -0,0 +1,33 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 + [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 + [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) + [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) + [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 + [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 + [12] (byte) main::j#1 ← ++ (byte) main::j#3 + [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 + [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 + [15] (byte) main::j#2 ← ++ (byte) main::j#1 + [16] (byte) main::i#1 ← ++ (byte) main::i#2 + [17] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [18] return + to:@return diff --git a/src/test/ref/struct-38.log b/src/test/ref/struct-38.log new file mode 100644 index 000000000..f693d8850 --- /dev/null +++ b/src/test/ref/struct-38.log @@ -0,0 +1,730 @@ +Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) main::i) +Fixing pointer array-indexing *((const signed word*) SCREEN + (byte) main::j) +Fixing pointer array-indexing *((const signed word*) SCREEN + (byte) main::j) +Created struct value member variable (signed word) main::to_x +Created struct value member variable (signed word) main::to_y +Converted struct value to member variables (struct SplineVector16) main::to +Adding struct value member variable copy (signed word) main::to_x ← *((signed word*~) main::$5 + (byte~) main::$1) +Adding struct value member variable copy (signed word) main::to_y ← *((signed word*~) main::$7 + (byte~) main::$1) +Replacing struct member reference (struct SplineVector16) main::to.x with member unwinding reference (signed word) main::to_x +Replacing struct member reference (struct SplineVector16) main::to.y with member unwinding reference (signed word) main::to_y +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::j#0 ← (byte) 0 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::j#3 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#2 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT + (signed word*~) main::$5 ← (signed word*)(signed word*~) main::$4 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X + (signed word) main::to_x#0 ← *((signed word*~) main::$5 + (byte~) main::$1) + (signed word*~) main::$4 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + (signed word*~) main::$7 ← (signed word*)(signed word*~) main::$6 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (signed word) main::to_y#0 ← *((signed word*~) main::$7 + (byte~) main::$1) + (signed word*~) main::$6 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$2 ← (byte) main::j#3 * (const byte) SIZEOF_SIGNED_WORD + *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 + (byte) main::j#1 ← ++ (byte) main::j#3 + (byte~) main::$3 ← (byte) main::j#1 * (const byte) SIZEOF_SIGNED_WORD + *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 + (byte) main::j#2 ← ++ (byte) main::j#1 + (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,2) + (bool~) main::$0 ← (byte) main::i#1 != rangelast(0,2) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_X = (byte) 0 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*)(number) $400 +(const byte) SIZEOF_SIGNED_WORD = (byte) 2 +(const byte) SIZEOF_STRUCT_SEGMENT = (byte) 9 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(signed word) SplineVector16::x +(signed word) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(bool~) main::$0 +(byte~) main::$1 +(byte~) main::$2 +(byte~) main::$3 +(signed word*~) main::$4 +(signed word*~) main::$5 +(signed word*~) main::$6 +(signed word*~) main::$7 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::j +(byte) main::j#0 +(byte) main::j#1 +(byte) main::j#2 +(byte) main::j#3 +(signed word) main::to_x +(signed word) main::to_x#0 +(signed word) main::to_y +(signed word) main::to_y#0 + +Simplifying constant pointer cast (signed word*) 1024 +Simplifying constant integer cast (signed word*~) main::$4 +Simplifying constant integer cast (signed word*~) main::$6 +Successful SSA optimization PassNCastSimplification +Simple Condition (bool~) main::$0 [18] if((byte) main::i#1!=rangelast(0,2)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [6] (signed word*~) main::$4 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Constant right-side identified [9] (signed word*~) main::$6 ← (signed word*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::j#0 = 0 +Constant (const byte) main::i#0 = 0 +Constant (const signed word*) main::$4 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Constant (const signed word*) main::$6 = (signed word*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [16] main::i#1 ← ++ main::i#2 to ++ +Resolved ranged comparison value [18] if(main::i#1!=rangelast(0,2)) goto main::@1 to (number) 3 +Simplifying expression containing zero main::$4 in [4] (signed word*~) main::$5 ← (const signed word*) main::$4 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) OFFSET_STRUCT_SPLINEVECTOR16_X +Successful SSA optimization PassNEliminateUnusedVars +Adding number conversion cast (unumber) 3 in if((byte) main::i#1!=(number) 3) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 3 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 3 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Constant right-side identified [4] (signed word*~) main::$7 ← (const signed word*) main::$6 + (const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const signed word*) main::$5 = main::$4 +Constant (const signed word*) main::$7 = main::$6+OFFSET_STRUCT_SPLINEVECTOR16_Y +Successful SSA optimization Pass2ConstantIdentification +Rewriting multiplication to use shift and addition[1] (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT +Rewriting multiplication to use shift [4] (byte~) main::$2 ← (byte) main::j#3 * (const byte) SIZEOF_SIGNED_WORD +Rewriting multiplication to use shift [7] (byte~) main::$3 ← (byte) main::j#1 * (const byte) SIZEOF_SIGNED_WORD +Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings (const byte) main::j#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::$5 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::i#0 = (byte) 0 +Constant inlined main::$6 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::$4 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::j#0 = (byte) 0 +Constant inlined main::$7 = (signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y +Successful SSA optimization Pass2ConstantInlining +Alias (byte~) main::$1 = (byte~) main::$9 +Successful SSA optimization Pass2AliasElimination +Eliminating unused constant (const byte) SIZEOF_STRUCT_SEGMENT +Eliminating unused constant (const byte) SIZEOF_SIGNED_WORD +Successful SSA optimization PassNEliminateUnusedVars +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 + +Created 2 initial phi equivalence classes +Coalesced [20] main::i#3 ← main::i#1 +Coalesced [21] main::j#4 ← main::j#2 +Coalesced down to 2 phi equivalence classes +Culled Empty Block (label) @2 +Culled Empty Block (label) main::@3 +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() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 + [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 + [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) + [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) + [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 + [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 + [12] (byte) main::j#1 ← ++ (byte) main::j#3 + [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 + [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 + [15] (byte) main::j#2 ← ++ (byte) main::j#1 + [16] (byte) main::i#1 ← ++ (byte) main::i#2 + [17] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [18] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(signed word) SplineVector16::x +(signed word) SplineVector16::y +(void()) main() +(byte~) main::$1 16.5 +(byte~) main::$2 22.0 +(byte~) main::$3 22.0 +(byte~) main::$8 22.0 +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 4.0 +(byte) main::j +(byte) main::j#1 11.0 +(byte) main::j#2 7.333333333333333 +(byte) main::j#3 4.714285714285714 +(signed word) main::to_x +(signed word) main::to_x#0 7.333333333333333 +(signed word) main::to_y +(signed word) main::to_y#0 4.4 + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +Added variable main::$8 to live range equivalence class [ main::$8 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable main::to_x#0 to live range equivalence class [ main::to_x#0 ] +Added variable main::to_y#0 to live range equivalence class [ main::to_y#0 ] +Added variable main::$2 to live range equivalence class [ main::$2 ] +Added variable main::j#1 to live range equivalence class [ main::j#1 ] +Added variable main::$3 to live range equivalence class [ main::$3 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +[ main::$8 ] +[ main::$1 ] +[ main::to_x#0 ] +[ main::to_y#0 ] +[ main::$2 ] +[ main::j#1 ] +[ main::$3 ] +Allocated zp[1]:2 [ main::i#2 main::i#1 ] +Allocated zp[1]:3 [ main::j#3 main::j#2 ] +Allocated zp[1]:4 [ main::$8 ] +Allocated zp[1]:5 [ main::$1 ] +Allocated zp[2]:6 [ main::to_x#0 ] +Allocated zp[2]:8 [ main::to_y#0 ] +Allocated zp[1]:10 [ main::$2 ] +Allocated zp[1]:11 [ main::j#1 ] +Allocated zp[1]:12 [ main::$3 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 2 + // @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 __1 = 5 + .label __2 = $a + .label __3 = $c + .label to_x = 6 + .label to_y = 8 + .label j = $b + .label j_1 = 3 + .label i = 2 + .label __8 = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j_1 + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta.z i + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 -- vbuz1=vbuz2_rol_3 + lda.z i + asl + asl + asl + sta.z __8 + // [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3 + lda.z __8 + clc + adc.z i + sta.z __1 + // [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuz2 + ldy.z __1 + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,y + sta.z to_x+1 + // [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuz2 + ldy.z __1 + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,y + sta.z to_y+1 + // [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda.z j_1 + asl + sta.z __2 + // [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 -- pwsc1_derefidx_vbuz1=vwsz2 + ldy.z __2 + lda.z to_x + sta SCREEN,y + lda.z to_x+1 + sta SCREEN+1,y + // [12] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuz1=_inc_vbuz2 + ldy.z j_1 + iny + sty.z j + // [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda.z j + asl + sta.z __3 + // [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 -- pwsc1_derefidx_vbuz1=vwsz2 + ldy.z __3 + lda.z to_y + sta SCREEN,y + lda.z to_y+1 + sta SCREEN+1,y + // [15] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuz2 + ldy.z j + iny + sty.z j_1 + // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [17] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #3 + cmp.z i + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [18] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 [ main::i#2 main::j#3 main::$8 ] ( main:2 [ main::i#2 main::j#3 main::$8 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::j#3 main::j#2 ] +Statement [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 ] ( main:2 [ main::i#2 main::j#3 main::$1 ] ) always clobbers reg byte a +Statement [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) [ main::i#2 main::j#3 main::$1 main::to_x#0 ] ( main:2 [ main::i#2 main::j#3 main::$1 main::to_x#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:5 [ main::$1 ] +Statement [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 ] ( main:2 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 ] ) always clobbers reg byte a +Statement [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 main::$2 ] ( main:2 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 main::$2 ] ) always clobbers reg byte a +Statement [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 [ main::i#2 main::j#3 main::to_y#0 ] ( main:2 [ main::i#2 main::j#3 main::to_y#0 ] ) always clobbers reg byte a +Statement [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 [ main::i#2 main::to_y#0 main::j#1 main::$3 ] ( main:2 [ main::i#2 main::to_y#0 main::j#1 main::$3 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:11 [ main::j#1 ] +Statement [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 [ main::i#2 main::j#1 ] ( main:2 [ main::i#2 main::j#1 ] ) always clobbers reg byte a +Statement [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 [ main::i#2 main::j#3 main::$8 ] ( main:2 [ main::i#2 main::j#3 main::$8 ] ) always clobbers reg byte a +Statement [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 ] ( main:2 [ main::i#2 main::j#3 main::$1 ] ) always clobbers reg byte a +Statement [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) [ main::i#2 main::j#3 main::$1 main::to_x#0 ] ( main:2 [ main::i#2 main::j#3 main::$1 main::to_x#0 ] ) always clobbers reg byte a +Statement [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 ] ( main:2 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 ] ) always clobbers reg byte a +Statement [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 main::$2 ] ( main:2 [ main::i#2 main::j#3 main::to_x#0 main::to_y#0 main::$2 ] ) always clobbers reg byte a +Statement [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 [ main::i#2 main::j#3 main::to_y#0 ] ( main:2 [ main::i#2 main::j#3 main::to_y#0 ] ) always clobbers reg byte a +Statement [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 [ main::i#2 main::to_y#0 main::j#1 main::$3 ] ( main:2 [ main::i#2 main::to_y#0 main::j#1 main::$3 ] ) always clobbers reg byte a +Statement [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 [ main::i#2 main::j#1 ] ( main:2 [ main::i#2 main::j#1 ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::j#3 main::j#2 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ main::$8 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$1 ] : zp[1]:5 , reg byte x , reg byte y , +Potential registers zp[2]:6 [ main::to_x#0 ] : zp[2]:6 , +Potential registers zp[2]:8 [ main::to_y#0 ] : zp[2]:8 , +Potential registers zp[1]:10 [ main::$2 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::j#1 ] : zp[1]:11 , reg byte x , reg byte y , +Potential registers zp[1]:12 [ main::$3 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 22: zp[1]:4 [ main::$8 ] 22: zp[1]:10 [ main::$2 ] 22: zp[1]:12 [ main::$3 ] 20.5: zp[1]:2 [ main::i#2 main::i#1 ] 16.5: zp[1]:5 [ main::$1 ] 12.05: zp[1]:3 [ main::j#3 main::j#2 ] 11: zp[1]:11 [ main::j#1 ] 7.33: zp[2]:6 [ main::to_x#0 ] 4.4: zp[2]:8 [ main::to_y#0 ] +Uplift Scope [SplineVector16] +Uplift Scope [Segment] +Uplift Scope [Segment::SegmentType] +Uplift Scope [] + +Uplifting [main] best 1413 combination reg byte a [ main::$8 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] reg byte x [ main::i#2 main::i#1 ] zp[1]:5 [ main::$1 ] zp[1]:3 [ main::j#3 main::j#2 ] zp[1]:11 [ main::j#1 ] zp[2]:6 [ main::to_x#0 ] zp[2]:8 [ main::to_y#0 ] +Limited combination testing to 100 combinations of 5184 possible. +Uplifting [SplineVector16] best 1413 combination +Uplifting [Segment] best 1413 combination +Uplifting [Segment::SegmentType] best 1413 combination +Uplifting [] best 1413 combination +Attempting to uplift remaining variables inzp[1]:5 [ main::$1 ] +Uplifting [main] best 1343 combination reg byte y [ main::$1 ] +Attempting to uplift remaining variables inzp[1]:3 [ main::j#3 main::j#2 ] +Uplifting [main] best 1343 combination zp[1]:3 [ main::j#3 main::j#2 ] +Attempting to uplift remaining variables inzp[1]:11 [ main::j#1 ] +Uplifting [main] best 1343 combination zp[1]:11 [ main::j#1 ] +Coalescing zero page register [ zp[1]:3 [ main::j#3 main::j#2 ] ] with [ zp[1]:11 [ main::j#1 ] ] - score: 2 +Allocated (was zp[1]:3) zp[1]:2 [ main::j#3 main::j#2 main::j#1 ] +Allocated (was zp[2]:6) zp[2]:3 [ main::to_x#0 ] +Allocated (was zp[2]:8) zp[2]:5 [ main::to_y#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 2 + // @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 to_x = 3 + .label to_y = 5 + .label j = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 -- vbuaa=vbuxx_rol_3 + txa + asl + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tay + // [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,y + sta.z to_x+1 + // [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,y + sta.z to_y+1 + // [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 -- pwsc1_derefidx_vbuaa=vwsz1 + tay + lda.z to_x + sta SCREEN,y + lda.z to_x+1 + sta SCREEN+1,y + // [12] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuz1=_inc_vbuz1 + inc.z j + // [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 -- pwsc1_derefidx_vbuaa=vwsz1 + tay + lda.z to_y + sta SCREEN,y + lda.z to_y+1 + sta SCREEN+1,y + // [15] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuz1 + inc.z j + // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [17] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #3 + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [18] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldx #0 with TAX +Replacing label __bbegin with __b1 +Replacing label __b1_from___b1 with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction main_from___b1: +Removing instruction __bend_from___b1: +Removing instruction __b1_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*) 1024 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(signed word) SplineVector16::x +(signed word) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte y 16.5 +(byte~) main::$2 reg byte a 22.0 +(byte~) main::$3 reg byte a 22.0 +(byte~) main::$8 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 4.0 +(byte) main::j +(byte) main::j#1 j zp[1]:2 11.0 +(byte) main::j#2 j zp[1]:2 7.333333333333333 +(byte) main::j#3 j zp[1]:2 4.714285714285714 +(signed word) main::to_x +(signed word) main::to_x#0 to_x zp[2]:3 7.333333333333333 +(signed word) main::to_y +(signed word) main::to_y#0 to_y zp[2]:5 4.4 + +reg byte x [ main::i#2 main::i#1 ] +zp[1]:2 [ main::j#3 main::j#2 main::j#1 ] +reg byte a [ main::$8 ] +reg byte y [ main::$1 ] +zp[2]:3 [ main::to_x#0 ] +zp[2]:5 [ main::to_y#0 ] +reg byte a [ main::$2 ] +reg byte a [ main::$3 ] + + +FINAL ASSEMBLER +Score: 1181 + + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to Unwound layout + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_SPLINEVECTOR16_Y = 2 + // @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 to_x = 3 + .label to_y = 5 + .label j = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + tax + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + // main::@1 + __b1: + // to = letter_c[i].to + // [6] (byte~) main::$8 ← (byte) main::i#2 << (byte) 3 -- vbuaa=vbuxx_rol_3 + txa + asl + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$8 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tay + // [8] (signed word) main::to_x#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,y + sta.z to_x + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+1,y + sta.z to_x+1 + // [9] (signed word) main::to_y#0 ← *((signed word*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO+(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y + (byte~) main::$1) -- vwsz1=pwsc1_derefidx_vbuyy + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y,y + sta.z to_y + lda letter_c+OFFSET_STRUCT_SEGMENT_TO+OFFSET_STRUCT_SPLINEVECTOR16_Y+1,y + sta.z to_y+1 + // SCREEN[j++] = to.x + // [10] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [11] *((const signed word*) SCREEN + (byte~) main::$2) ← (signed word) main::to_x#0 -- pwsc1_derefidx_vbuaa=vwsz1 + tay + lda.z to_x + sta SCREEN,y + lda.z to_x+1 + sta SCREEN+1,y + // SCREEN[j++] = to.x; + // [12] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuz1=_inc_vbuz1 + inc.z j + // SCREEN[j++] = to.y + // [13] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [14] *((const signed word*) SCREEN + (byte~) main::$3) ← (signed word) main::to_y#0 -- pwsc1_derefidx_vbuaa=vwsz1 + tay + lda.z to_y + sta SCREEN,y + lda.z to_y+1 + sta SCREEN+1,y + // SCREEN[j++] = to.y; + // [15] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuz1 + inc.z j + // for( byte i: 0..2) + // [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [17] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #3 + bne __b1 + // main::@return + // } + // [18] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + diff --git a/src/test/ref/struct-38.sym b/src/test/ref/struct-38.sym new file mode 100644 index 000000000..1e9f43c5f --- /dev/null +++ b/src/test/ref/struct-38.sym @@ -0,0 +1,44 @@ +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_SPLINEVECTOR16_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*) 1024 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct SplineVector16) Segment::to +(byte) Segment::type +(struct SplineVector16) Segment::via +(signed word) SplineVector16::x +(signed word) SplineVector16::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte y 16.5 +(byte~) main::$2 reg byte a 22.0 +(byte~) main::$3 reg byte a 22.0 +(byte~) main::$8 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 4.0 +(byte) main::j +(byte) main::j#1 j zp[1]:2 11.0 +(byte) main::j#2 j zp[1]:2 7.333333333333333 +(byte) main::j#3 j zp[1]:2 4.714285714285714 +(signed word) main::to_x +(signed word) main::to_x#0 to_x zp[2]:3 7.333333333333333 +(signed word) main::to_y +(signed word) main::to_y#0 to_y zp[2]:5 4.4 + +reg byte x [ main::i#2 main::i#1 ] +zp[1]:2 [ main::j#3 main::j#2 main::j#1 ] +reg byte a [ main::$8 ] +reg byte y [ main::$1 ] +zp[2]:3 [ main::to_x#0 ] +zp[2]:5 [ main::to_y#0 ] +reg byte a [ main::$2 ] +reg byte a [ main::$3 ] diff --git a/src/test/ref/struct-39.asm b/src/test/ref/struct-39.asm new file mode 100644 index 000000000..dbcfbce8d --- /dev/null +++ b/src/test/ref/struct-39.asm @@ -0,0 +1,64 @@ +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to C-standard layout (expecting a memcpy) +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_VECTOR_Y = 2 + .const SIZEOF_STRUCT_VECTOR = 4 +main: { + .label to = 4 + .label j = 3 + .label i = 2 + lda #0 + sta.z j + sta.z i + __b1: + lda.z i + asl + asl + asl + clc + adc.z i + tax + ldy #0 + !: + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x + sta to,y + inx + iny + cpy #SIZEOF_STRUCT_VECTOR + bne !- + lda.z j + asl + tay + lda.z to + sta SCREEN,y + lda.z to+1 + sta SCREEN+1,y + ldx.z j + inx + txa + asl + tay + lda to+OFFSET_STRUCT_VECTOR_Y + sta SCREEN,y + lda to+OFFSET_STRUCT_VECTOR_Y+1 + sta SCREEN+1,y + inx + stx.z j + inc.z i + lda #3 + cmp.z i + bne __b1 + rts +} + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 diff --git a/src/test/ref/struct-39.cfg b/src/test/ref/struct-39.cfg new file mode 100644 index 000000000..64b3a5a09 --- /dev/null +++ b/src/test/ref/struct-39.cfg @@ -0,0 +1,32 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 + [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 + [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 + [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) + [11] (byte) main::j#1 ← ++ (byte) main::j#3 + [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 + [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) + [14] (byte) main::j#2 ← ++ (byte) main::j#1 + [15] (byte) main::i#1 ← ++ (byte) main::i#2 + [16] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [17] return + to:@return diff --git a/src/test/ref/struct-39.log b/src/test/ref/struct-39.log new file mode 100644 index 000000000..33a7f6795 --- /dev/null +++ b/src/test/ref/struct-39.log @@ -0,0 +1,700 @@ +Fixing pointer array-indexing *((const struct Segment*) letter_c + (byte) main::i) +Fixing pointer array-indexing *((const signed word*) SCREEN + (byte) main::j) +Fixing pointer array-indexing *((const signed word*) SCREEN + (byte) main::j) +Adding struct value member variable copy *(&(struct Vector) main::to) ← *((struct Vector*~) main::$4 + (byte~) main::$1) +Replacing struct member reference (struct Vector) main::to.x with member unwinding reference *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_X) +Replacing struct member reference (struct Vector) main::to.y with member unwinding reference *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) +Adding struct value member variable copy *(&(struct Vector) main::to) ← memcpy(*((struct Vector*~) main::$4 + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::j#0 ← (byte) 0 + (byte) main::i#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::j#3 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#2 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT + (struct Vector*~) main::$4 ← (struct Vector*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO + *(&(struct Vector) main::to) ← memcpy(*((struct Vector*~) main::$4 + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + (byte~) main::$2 ← (byte) main::j#3 * (const byte) SIZEOF_SIGNED_WORD + *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_X) + (byte) main::j#1 ← ++ (byte) main::j#3 + (byte~) main::$3 ← (byte) main::j#1 * (const byte) SIZEOF_SIGNED_WORD + *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) + (byte) main::j#2 ← ++ (byte) main::j#1 + (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,2) + (bool~) main::$0 ← (byte) main::i#1 != rangelast(0,2) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_X = (byte) 0 +(const byte) OFFSET_STRUCT_VECTOR_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*)(number) $400 +(const byte) SIZEOF_SIGNED_WORD = (byte) 2 +(const byte) SIZEOF_STRUCT_SEGMENT = (byte) 9 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct Vector) Segment::to +(byte) Segment::type +(struct Vector) Segment::via +(signed word) Vector::x +(signed word) Vector::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(bool~) main::$0 +(byte~) main::$1 +(byte~) main::$2 +(byte~) main::$3 +(struct Vector*~) main::$4 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::j +(byte) main::j#0 +(byte) main::j#1 +(byte) main::j#2 +(byte) main::j#3 +(struct Vector) main::to loadstore + +Simplifying constant pointer cast (signed word*) 1024 +Successful SSA optimization PassNCastSimplification +Simple Condition (bool~) main::$0 [14] if((byte) main::i#1!=rangelast(0,2)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant right-side identified [4] (struct Vector*~) main::$4 ← (struct Vector*)(const struct Segment*) letter_c + (const byte) OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::j#0 = 0 +Constant (const byte) main::i#0 = 0 +Constant (const struct Vector*) main::$4 = (struct Vector*)letter_c+OFFSET_STRUCT_SEGMENT_TO +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [12] main::i#1 ← ++ main::i#2 to ++ +Resolved ranged comparison value [14] if(main::i#1!=rangelast(0,2)) goto main::@1 to (number) 3 +Simplifying expression containing zero (signed word*)&main::to in [7] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_X) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_X +Successful SSA optimization PassNEliminateUnusedVars +Adding number conversion cast (unumber) 3 in if((byte) main::i#1!=(number) 3) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 3 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 3 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Rewriting multiplication to use shift and addition[1] (byte~) main::$1 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_SEGMENT +Rewriting multiplication to use shift [3] (byte~) main::$2 ← (byte) main::j#3 * (const byte) SIZEOF_SIGNED_WORD +Rewriting multiplication to use shift [6] (byte~) main::$3 ← (byte) main::j#1 * (const byte) SIZEOF_SIGNED_WORD +Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings (const byte) main::j#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::i#0 = (byte) 0 +Constant inlined main::$4 = (struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO +Constant inlined main::j#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining +Alias (byte~) main::$1 = (byte~) main::$6 +Successful SSA optimization Pass2AliasElimination +Eliminating unused constant (const byte) SIZEOF_STRUCT_SEGMENT +Eliminating unused constant (const byte) SIZEOF_SIGNED_WORD +Successful SSA optimization PassNEliminateUnusedVars +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 + +Created 2 initial phi equivalence classes +Coalesced [19] main::i#3 ← main::i#1 +Coalesced [20] main::j#4 ← main::j#2 +Coalesced down to 2 phi equivalence classes +Culled Empty Block (label) @2 +Culled Empty Block (label) main::@3 +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() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::j#3 ← phi( main/(byte) 0 main::@1/(byte) main::j#2 ) + [5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) + [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 + [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 + [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 + [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) + [11] (byte) main::j#1 ← ++ (byte) main::j#3 + [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 + [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) + [14] (byte) main::j#2 ← ++ (byte) main::j#1 + [15] (byte) main::i#1 ← ++ (byte) main::i#2 + [16] if((byte) main::i#1!=(byte) 3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [17] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(struct Vector) Segment::to +(byte) Segment::type +(struct Vector) Segment::via +(signed word) Vector::x +(signed word) Vector::y +(void()) main() +(byte~) main::$1 11.0 +(byte~) main::$2 22.0 +(byte~) main::$3 22.0 +(byte~) main::$5 22.0 +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 4.4 +(byte) main::j +(byte) main::j#1 11.0 +(byte) main::j#2 7.333333333333333 +(byte) main::j#3 5.5 +(struct Vector) main::to loadstore + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +Added variable main::$5 to live range equivalence class [ main::$5 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable main::$2 to live range equivalence class [ main::$2 ] +Added variable main::j#1 to live range equivalence class [ main::j#1 ] +Added variable main::$3 to live range equivalence class [ main::$3 ] +Added variable main::to to live range equivalence class [ main::to ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::j#3 main::j#2 ] +[ main::$5 ] +[ main::$1 ] +[ main::$2 ] +[ main::j#1 ] +[ main::$3 ] +[ main::to ] +Allocated zp[1]:2 [ main::i#2 main::i#1 ] +Allocated zp[1]:3 [ main::j#3 main::j#2 ] +Allocated zp[1]:4 [ main::$5 ] +Allocated zp[1]:5 [ main::$1 ] +Allocated zp[1]:6 [ main::$2 ] +Allocated zp[1]:7 [ main::j#1 ] +Allocated zp[1]:8 [ main::$3 ] +Allocated zp[4]:9 [ main::to ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to C-standard layout (expecting a memcpy) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_VECTOR_Y = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + // @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 to = 9 + .label __1 = 5 + .label __2 = 6 + .label __3 = 8 + .label j = 7 + .label j_1 = 3 + .label i = 2 + .label __5 = 4 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j_1 + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta.z i + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 -- vbuz1=vbuz2_rol_3 + lda.z i + asl + asl + asl + sta.z __5 + // [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3 + lda.z __5 + clc + adc.z i + sta.z __1 + // [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=pssc2_derefidx_vbuz1_memcpy_vbuc3 + ldx.z __1 + ldy #0 + !: + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x + sta to,y + inx + iny + cpy #SIZEOF_STRUCT_VECTOR + bne !- + // [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda.z j_1 + asl + sta.z __2 + // [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) -- pwsc1_derefidx_vbuz1=_deref_pwsc2 + ldy.z __2 + lda.z to + sta SCREEN,y + lda.z to+1 + sta SCREEN+1,y + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuz1=_inc_vbuz2 + ldy.z j_1 + iny + sty.z j + // [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda.z j + asl + sta.z __3 + // [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) -- pwsc1_derefidx_vbuz1=_deref_pwsc2 + ldy.z __3 + lda to+OFFSET_STRUCT_VECTOR_Y + sta SCREEN,y + lda to+OFFSET_STRUCT_VECTOR_Y+1 + sta SCREEN+1,y + // [14] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuz2 + ldy.z j + iny + sty.z j_1 + // [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [16] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #3 + cmp.z i + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [17] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 [ main::i#2 main::j#3 main::$5 main::to ] ( main:2 [ main::i#2 main::j#3 main::$5 main::to ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::j#3 main::j#2 ] +Statement [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 main::to ] ( main:2 [ main::i#2 main::j#3 main::$1 main::to ] ) always clobbers reg byte a +Statement [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) [ main::i#2 main::j#3 main::to ] ( main:2 [ main::i#2 main::j#3 main::to ] ) always clobbers reg byte a reg byte x reg byte y +Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte x as potential for zp[1]:3 [ main::j#3 main::j#2 ] +Removing always clobbered register reg byte y as potential for zp[1]:3 [ main::j#3 main::j#2 ] +Statement [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 [ main::i#2 main::j#3 main::to main::$2 ] ( main:2 [ main::i#2 main::j#3 main::to main::$2 ] ) always clobbers reg byte a +Statement [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) [ main::i#2 main::j#3 main::to ] ( main:2 [ main::i#2 main::j#3 main::to ] ) always clobbers reg byte a +Statement [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 [ main::i#2 main::to main::j#1 main::$3 ] ( main:2 [ main::i#2 main::to main::j#1 main::$3 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:7 [ main::j#1 ] +Statement [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) [ main::i#2 main::to main::j#1 ] ( main:2 [ main::i#2 main::to main::j#1 ] ) always clobbers reg byte a +Statement [16] if((byte) main::i#1!=(byte) 3) goto main::@1 [ main::i#1 main::j#2 main::to ] ( main:2 [ main::i#1 main::j#2 main::to ] ) always clobbers reg byte a +Statement [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 [ main::i#2 main::j#3 main::$5 main::to ] ( main:2 [ main::i#2 main::j#3 main::$5 main::to ] ) always clobbers reg byte a +Statement [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 [ main::i#2 main::j#3 main::$1 main::to ] ( main:2 [ main::i#2 main::j#3 main::$1 main::to ] ) always clobbers reg byte a +Statement [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) [ main::i#2 main::j#3 main::to ] ( main:2 [ main::i#2 main::j#3 main::to ] ) always clobbers reg byte a reg byte x reg byte y +Statement [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 [ main::i#2 main::j#3 main::to main::$2 ] ( main:2 [ main::i#2 main::j#3 main::to main::$2 ] ) always clobbers reg byte a +Statement [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) [ main::i#2 main::j#3 main::to ] ( main:2 [ main::i#2 main::j#3 main::to ] ) always clobbers reg byte a +Statement [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 [ main::i#2 main::to main::j#1 main::$3 ] ( main:2 [ main::i#2 main::to main::j#1 main::$3 ] ) always clobbers reg byte a +Statement [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) [ main::i#2 main::to main::j#1 ] ( main:2 [ main::i#2 main::to main::j#1 ] ) always clobbers reg byte a +Statement [16] if((byte) main::i#1!=(byte) 3) goto main::@1 [ main::i#1 main::j#2 main::to ] ( main:2 [ main::i#1 main::j#2 main::to ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , +Potential registers zp[1]:3 [ main::j#3 main::j#2 ] : zp[1]:3 , +Potential registers zp[1]:4 [ main::$5 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$1 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ main::$2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ main::j#1 ] : zp[1]:7 , reg byte x , reg byte y , +Potential registers zp[1]:8 [ main::$3 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[4]:9 [ main::to ] : zp[4]:9 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 22: zp[1]:4 [ main::$5 ] 22: zp[1]:6 [ main::$2 ] 22: zp[1]:8 [ main::$3 ] 20.9: zp[1]:2 [ main::i#2 main::i#1 ] 12.83: zp[1]:3 [ main::j#3 main::j#2 ] 11: zp[1]:5 [ main::$1 ] 11: zp[1]:7 [ main::j#1 ] 0: zp[4]:9 [ main::to ] +Uplift Scope [Vector] +Uplift Scope [Segment] +Uplift Scope [Segment::SegmentType] +Uplift Scope [] + +Uplifting [main] best 1333 combination reg byte a [ main::$5 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] zp[1]:2 [ main::i#2 main::i#1 ] zp[1]:3 [ main::j#3 main::j#2 ] reg byte a [ main::$1 ] zp[1]:7 [ main::j#1 ] zp[4]:9 [ main::to ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [Vector] best 1333 combination +Uplifting [Segment] best 1333 combination +Uplifting [Segment::SegmentType] best 1333 combination +Uplifting [] best 1333 combination +Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ] +Uplifting [main] best 1333 combination zp[1]:2 [ main::i#2 main::i#1 ] +Attempting to uplift remaining variables inzp[1]:3 [ main::j#3 main::j#2 ] +Uplifting [main] best 1333 combination zp[1]:3 [ main::j#3 main::j#2 ] +Attempting to uplift remaining variables inzp[1]:7 [ main::j#1 ] +Uplifting [main] best 1263 combination reg byte x [ main::j#1 ] +Allocated (was zp[4]:9) zp[4]:4 [ main::to ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to C-standard layout (expecting a memcpy) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_VECTOR_Y = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + // @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 to = 4 + .label j = 3 + .label i = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta.z i + jmp __b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 -- vbuaa=vbuz1_rol_3 + lda.z i + asl + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuz1 + clc + adc.z i + // [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3 + tax + ldy #0 + !: + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x + sta to,y + inx + iny + cpy #SIZEOF_STRUCT_VECTOR + bne !- + // [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) -- pwsc1_derefidx_vbuaa=_deref_pwsc2 + tay + lda.z to + sta SCREEN,y + lda.z to+1 + sta SCREEN+1,y + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuxx=_inc_vbuz1 + ldx.z j + inx + // [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuaa=vbuxx_rol_1 + txa + asl + // [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) -- pwsc1_derefidx_vbuaa=_deref_pwsc2 + tay + lda to+OFFSET_STRUCT_VECTOR_Y + sta SCREEN,y + lda to+OFFSET_STRUCT_VECTOR_Y+1 + sta SCREEN+1,y + // [14] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuxx + inx + stx.z j + // [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [16] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #3 + cmp.z i + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [17] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label __bbegin with __b1 +Replacing label __b1_from___b1 with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction main_from___b1: +Removing instruction __bend_from___b1: +Removing instruction __b1_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*) 1024 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct Vector) Segment::to +(byte) Segment::type +(struct Vector) Segment::via +(signed word) Vector::x +(signed word) Vector::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte a 11.0 +(byte~) main::$2 reg byte a 22.0 +(byte~) main::$3 reg byte a 22.0 +(byte~) main::$5 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 i zp[1]:2 16.5 +(byte) main::i#2 i zp[1]:2 4.4 +(byte) main::j +(byte) main::j#1 reg byte x 11.0 +(byte) main::j#2 j zp[1]:3 7.333333333333333 +(byte) main::j#3 j zp[1]:3 5.5 +(struct Vector) main::to loadstore zp[4]:4 + +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ main::j#3 main::j#2 ] +reg byte a [ main::$5 ] +reg byte a [ main::$1 ] +reg byte a [ main::$2 ] +reg byte x [ main::j#1 ] +reg byte a [ main::$3 ] +zp[4]:4 [ main::to ] + + +FINAL ASSEMBLER +Score: 1141 + + // File Comments +// Complex C-struct - copying a sub-struct with 2-byte members from C-standard layout to C-standard layout (expecting a memcpy) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .const MOVE_TO = 0 + .const SPLINE_TO = 1 + .label SCREEN = $400 + .const OFFSET_STRUCT_SEGMENT_TO = 1 + .const OFFSET_STRUCT_VECTOR_Y = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + // @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 to = 4 + .label j = 3 + .label i = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::j#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z j + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + sta.z i + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [5] phi (byte) main::j#3 = (byte) main::j#2 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + // main::@1 + __b1: + // to = letter_c[i].to + // [6] (byte~) main::$5 ← (byte) main::i#2 << (byte) 3 -- vbuaa=vbuz1_rol_3 + lda.z i + asl + asl + asl + // [7] (byte~) main::$1 ← (byte~) main::$5 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuz1 + clc + adc.z i + // [8] *(&(struct Vector) main::to) ← memcpy(*((struct Vector*)(const struct Segment*) letter_c+(const byte) OFFSET_STRUCT_SEGMENT_TO + (byte~) main::$1), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3 + tax + ldy #0 + !: + lda letter_c+OFFSET_STRUCT_SEGMENT_TO,x + sta to,y + inx + iny + cpy #SIZEOF_STRUCT_VECTOR + bne !- + // SCREEN[j++] = to.x + // [9] (byte~) main::$2 ← (byte) main::j#3 << (byte) 1 -- vbuaa=vbuz1_rol_1 + lda.z j + asl + // [10] *((const signed word*) SCREEN + (byte~) main::$2) ← *((signed word*)&(struct Vector) main::to) -- pwsc1_derefidx_vbuaa=_deref_pwsc2 + tay + lda.z to + sta SCREEN,y + lda.z to+1 + sta SCREEN+1,y + // SCREEN[j++] = to.x; + // [11] (byte) main::j#1 ← ++ (byte) main::j#3 -- vbuxx=_inc_vbuz1 + ldx.z j + inx + // SCREEN[j++] = to.y + // [12] (byte~) main::$3 ← (byte) main::j#1 << (byte) 1 -- vbuaa=vbuxx_rol_1 + txa + asl + // [13] *((const signed word*) SCREEN + (byte~) main::$3) ← *((signed word*)&(struct Vector) main::to+(const byte) OFFSET_STRUCT_VECTOR_Y) -- pwsc1_derefidx_vbuaa=_deref_pwsc2 + tay + lda to+OFFSET_STRUCT_VECTOR_Y + sta SCREEN,y + lda to+OFFSET_STRUCT_VECTOR_Y+1 + sta SCREEN+1,y + // SCREEN[j++] = to.y; + // [14] (byte) main::j#2 ← ++ (byte) main::j#1 -- vbuz1=_inc_vbuxx + inx + stx.z j + // for( byte i: 0..2) + // [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [16] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #3 + cmp.z i + bne __b1 + // main::@return + // } + // [17] return + rts +} + // File Data + // True type letter c + letter_c: .byte MOVE_TO + .word 'a', 'b', 0, 0 + .byte SPLINE_TO + .word 'c', 'd', $67, $a9 + .byte SPLINE_TO + .word 'e', 'f', $4b, $c3 + diff --git a/src/test/ref/struct-39.sym b/src/test/ref/struct-39.sym new file mode 100644 index 000000000..522bdb6f1 --- /dev/null +++ b/src/test/ref/struct-39.sym @@ -0,0 +1,42 @@ +(label) @1 +(label) @begin +(label) @end +(const byte) MOVE_TO = (byte) 0 +(const byte) OFFSET_STRUCT_SEGMENT_TO = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_Y = (byte) 2 +(const signed word*) SCREEN = (signed word*) 1024 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(const byte) SPLINE_TO = (byte) 1 +(const byte) Segment::SegmentType::LINE_TO = (byte) 2 +(const byte) Segment::SegmentType::MOVE_TO = (byte) 0 +(const byte) Segment::SegmentType::SPLINE_TO = (byte) 1 +(struct Vector) Segment::to +(byte) Segment::type +(struct Vector) Segment::via +(signed word) Vector::x +(signed word) Vector::y +(const struct Segment*) letter_c[] = { { type: (const byte) MOVE_TO, to: { x: (signed word)(byte) 'a', y: (signed word)(byte) 'b' }, via: { x: (signed word) 0, y: (signed word) 0 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'c', y: (signed word)(byte) 'd' }, via: { x: (signed word) $67, y: (signed word) $a9 } }, { type: (const byte) SPLINE_TO, to: { x: (signed word)(byte) 'e', y: (signed word)(byte) 'f' }, via: { x: (signed word) $4b, y: (signed word) $c3 } } } +(void()) main() +(byte~) main::$1 reg byte a 11.0 +(byte~) main::$2 reg byte a 22.0 +(byte~) main::$3 reg byte a 22.0 +(byte~) main::$5 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 i zp[1]:2 16.5 +(byte) main::i#2 i zp[1]:2 4.4 +(byte) main::j +(byte) main::j#1 reg byte x 11.0 +(byte) main::j#2 j zp[1]:3 7.333333333333333 +(byte) main::j#3 j zp[1]:3 5.5 +(struct Vector) main::to loadstore zp[4]:4 + +zp[1]:2 [ main::i#2 main::i#1 ] +zp[1]:3 [ main::j#3 main::j#2 ] +reg byte a [ main::$5 ] +reg byte a [ main::$1 ] +reg byte a [ main::$2 ] +reg byte x [ main::j#1 ] +reg byte a [ main::$3 ] +zp[4]:4 [ main::to ]