1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-27 04:49:27 +00:00

Fixed problems with sizeof()-handling struct members. Closes #230

This commit is contained in:
jespergravgaard 2019-07-25 23:06:09 +02:00
parent a9e0c7805f
commit 0c33353bf8
6 changed files with 159 additions and 426 deletions

View File

@ -9,12 +9,14 @@ import dk.camelot64.kickc.model.operators.OperatorSizeOf;
import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.VariableIntermediate; import dk.camelot64.kickc.model.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.model.values.*;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -38,25 +40,22 @@ public class Pass1PointerSizeofFix extends Pass1Base {
Statement statement = stmtIt.next(); Statement statement = stmtIt.next();
if(statement instanceof StatementAssignment) { if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement; StatementAssignment assignment = (StatementAssignment) statement;
if((assignment.getrValue1() == null) && (assignment.getOperator() != null) && (assignment.getrValue2() instanceof VariableRef)) { if((assignment.getrValue1() == null) && (assignment.getOperator() != null) && (assignment.getrValue2() != null)) {
fixPointerUnary(assignment); fixPointerUnary(assignment);
} else if((assignment.getrValue1() instanceof VariableRef) && (assignment.getOperator() != null) && (assignment.getrValue2() != null)) { } else if((assignment.getrValue1() != null) && (assignment.getOperator() != null) && (assignment.getrValue2() != null)) {
fixPointerBinary(block, stmtIt, assignment); fixPointerBinary(block, stmtIt, assignment);
} }
} }
} }
} }
// For each statement maps RValues used as index to the new *2 variable created // For each statement maps RValues used as index to the new *sizeof() variable created
Map<Statement, Map<RValue, VariableRef>> handled = new LinkedHashMap<>(); Map<Statement, Map<RValue, VariableRef>> handled = new LinkedHashMap<>();
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof PointerDereferenceIndexed) { if(programValue.get() instanceof PointerDereferenceIndexed) {
PointerDereferenceIndexed deref = (PointerDereferenceIndexed) programValue.get(); PointerDereferenceIndexed deref = (PointerDereferenceIndexed) programValue.get();
if(deref.getPointer() instanceof VariableRef) { SymbolTypePointer pointerType = getPointerType(deref.getPointer());
VariableRef varRef = (VariableRef) deref.getPointer(); if(pointerType != null) {
Variable variable = getScope().getVariable(varRef);
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(pointerType.getElementType().getSizeBytes() > 1) { if(pointerType.getElementType().getSizeBytes() > 1) {
// Array-indexing into a non-byte pointer - multiply by sizeof() // Array-indexing into a non-byte pointer - multiply by sizeof()
getLog().append("Fixing pointer array-indexing " + deref.toString(getProgram())); getLog().append("Fixing pointer array-indexing " + deref.toString(getProgram()));
@ -78,7 +77,6 @@ public class Pass1PointerSizeofFix extends Pass1Base {
} }
} }
}); });
return false; return false;
} }
@ -89,10 +87,8 @@ public class Pass1PointerSizeofFix extends Pass1Base {
*/ */
public void fixPointerBinary(ControlFlowBlock block, ListIterator<Statement> stmtIt, StatementAssignment assignment) { public void fixPointerBinary(ControlFlowBlock block, ListIterator<Statement> stmtIt, StatementAssignment assignment) {
VariableRef varRef = (VariableRef) assignment.getrValue1(); SymbolTypePointer pointerType = getPointerType(assignment.getrValue1());
Variable variable = getScope().getVariable(varRef); if(pointerType != null) {
if(variable.getType() instanceof SymbolTypePointer) {
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(SymbolType.VOID.equals(pointerType.getElementType())) { if(SymbolType.VOID.equals(pointerType.getElementType())) {
if(Operators.PLUS.equals(assignment.getOperator()) || Operators.MINUS.equals(assignment.getOperator())) { if(Operators.PLUS.equals(assignment.getOperator()) || Operators.MINUS.equals(assignment.getOperator())) {
throw new CompileError("Void pointer math not allowed. ", assignment); throw new CompileError("Void pointer math not allowed. ", assignment);
@ -139,11 +135,9 @@ public class Pass1PointerSizeofFix extends Pass1Base {
* @param assignment The assignment statement * @param assignment The assignment statement
*/ */
public void fixPointerUnary(StatementAssignment assignment) { public void fixPointerUnary(StatementAssignment assignment) {
// Found assignment of unary operator // Found assignment with unary operator
VariableRef varRef = (VariableRef) assignment.getrValue2(); SymbolTypePointer pointerType = getPointerType(assignment.getrValue2());
Variable variable = getScope().getVariable(varRef); if(pointerType != null) {
if(variable.getType() instanceof SymbolTypePointer) {
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(SymbolType.VOID.equals(pointerType.getElementType())) { if(SymbolType.VOID.equals(pointerType.getElementType())) {
if(Operators.INCREMENT.equals(assignment.getOperator()) || Operators.DECREMENT.equals(assignment.getOperator())) { if(Operators.INCREMENT.equals(assignment.getOperator()) || Operators.DECREMENT.equals(assignment.getOperator())) {
throw new CompileError("Void pointer math not allowed. ", assignment); throw new CompileError("Void pointer math not allowed. ", assignment);
@ -168,5 +162,34 @@ public class Pass1PointerSizeofFix extends Pass1Base {
} }
} }
/**
* Examine the passed value to determine if it is a pointer.
* If it is a pointer return the type of the pointer
* @param pointer The potential pointer to examine
* @return The type of the pointer - if the value was a pointer. null if the value is not a pointer.
*/
private SymbolTypePointer getPointerType(RValue pointer) {
if(pointer instanceof VariableRef) {
VariableRef varRef = (VariableRef) pointer;
Variable variable = getScope().getVariable(varRef);
SymbolType type = variable.getType();
if(type instanceof SymbolTypePointer) {
return (SymbolTypePointer) type;
}
} else if(pointer instanceof StructMemberRef) {
StructMemberRef structMemberRef = (StructMemberRef) pointer;
RValue struct = structMemberRef.getStruct();
SymbolType structType = SymbolTypeInference.inferType(getScope(), struct);
if(structType instanceof SymbolTypeStruct) {
StructDefinition structDefinition = ((SymbolTypeStruct) structType).getStructDefinition(getScope());
Variable memberVariable = structDefinition.getMember(structMemberRef.getMemberName());
SymbolType memberType = memberVariable.getType();
if(memberType instanceof SymbolTypePointer) {
return (SymbolTypePointer) memberType;
}
}
}
return null;
}
} }

View File

@ -8,11 +8,7 @@ struct RadixInfo {
void main() { void main() {
const unsigned int* SCREEN = 0x400; const unsigned int* SCREEN = 0x400;
for( byte radix: 0..1) {
struct RadixInfo info = { RADIX_DECIMAL_VALUES }; struct RadixInfo info = { RADIX_DECIMAL_VALUES };
for( char digit: 0..4 ) { SCREEN[0] = info.values[1];
unsigned int digit_value = info.values[digit]; SCREEN[1] = RADIX_DECIMAL_VALUES[1];
SCREEN[digit] = digit_value;
}
}
} }

View File

@ -2,33 +2,17 @@
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
.const SIZEOF_WORD = 2
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label digit_value = 3 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
.label radix = 2 sta SCREEN
lda #0 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
sta radix sta SCREEN+1
b1: lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
ldx #0 sta SCREEN+1*SIZEOF_WORD
b2: lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
lda RADIX_DECIMAL_VALUES,x sta SCREEN+1*SIZEOF_WORD+1
sta digit_value
lda RADIX_DECIMAL_VALUES+1,x
sta digit_value+1
txa
asl
tay
lda digit_value
sta SCREEN,y
lda digit_value+1
sta SCREEN+1,y
inx
cpx #5
bne b2
inc radix
lda #2
cmp radix
bne b1
rts rts
} }
RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a

View File

@ -8,23 +8,9 @@
@end: scope:[] from @1 @end: scope:[] from @1
[3] phi() [3] phi()
main: scope:[main] from @1 main: scope:[main] from @1
[4] phi() [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD)
to:main::@1 [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD)
main::@1: scope:[main] from main main::@3
[5] (byte) main::radix#4 ← phi( main/(byte) 0 main::@3/(byte) main::radix#1 )
to:main::@2
main::@2: scope:[main] from main::@1 main::@2
[6] (byte) main::digit#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::digit#1 )
[7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2)
[8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1
[9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0
[10] (byte) main::digit#1 ← ++ (byte) main::digit#2
[11] if((byte) main::digit#1!=(byte) 5) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@2
[12] (byte) main::radix#1 ← ++ (byte) main::radix#4
[13] if((byte) main::radix#1!=(byte) 2) goto main::@1
to:main::@return to:main::@return
main::@return: scope:[main] from main::@3 main::@return: scope:[main] from main
[14] return [6] return
to:@return to:@return

View File

@ -1,9 +1,11 @@
Fixing pointer array-indexing *((word*) main::SCREEN + (byte) main::digit) Fixing pointer array-indexing *((struct RadixInfo) main::info.values + (number) 1)
Fixing pointer array-indexing *((word*) main::SCREEN + (number) 0)
Fixing pointer array-indexing *((word[]) RADIX_DECIMAL_VALUES + (number) 1)
Fixing pointer array-indexing *((word*) main::SCREEN + (number) 1)
Created struct value member variable (word*) main::info_values Created struct value member variable (word*) main::info_values
Converted struct value to member variables (struct RadixInfo) main::info Converted struct value to member variables (struct RadixInfo) main::info
Adding struct value list initializer (word*) main::info_values ← (word[]) RADIX_DECIMAL_VALUES Adding struct value list initializer (word*) main::info_values ← (word[]) RADIX_DECIMAL_VALUES
Replacing struct member reference (struct RadixInfo) main::info.values with member variable reference (word*) main::info_values Replacing struct member reference (struct RadixInfo) main::info.values with member variable reference (word*) main::info_values
Culled Empty Block (label) main::@4
CONTROL FLOW GRAPH SSA CONTROL FLOW GRAPH SSA
@begin: scope:[] from @begin: scope:[] from
@ -11,31 +13,14 @@ CONTROL FLOW GRAPH SSA
to:@1 to:@1
main: scope:[main] from @1 main: scope:[main] from @1
(word*) main::SCREEN#0 ← ((word*)) (number) $400 (word*) main::SCREEN#0 ← ((word*)) (number) $400
(byte) main::radix#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(byte) main::radix#4 ← phi( main/(byte) main::radix#0 main::@3/(byte) main::radix#1 )
(word*) main::info_values#0 ← (word[]) RADIX_DECIMAL_VALUES#0 (word*) main::info_values#0 ← (word[]) RADIX_DECIMAL_VALUES#0
(byte) main::digit#0 ← (byte) 0 (number~) main::$0 ← (number) 1 * (const byte) SIZEOF_WORD
to:main::@2 (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD
main::@2: scope:[main] from main::@1 main::@2 *((word*) main::SCREEN#0 + (number~) main::$1) ← *((word*) main::info_values#0 + (number~) main::$0)
(byte) main::radix#3 ← phi( main::@1/(byte) main::radix#4 main::@2/(byte) main::radix#3 ) (number~) main::$2 ← (number) 1 * (const byte) SIZEOF_WORD
(byte) main::digit#2 ← phi( main::@1/(byte) main::digit#0 main::@2/(byte) main::digit#1 ) *((word*) main::SCREEN#0 + (number~) main::$2) ← *((word[]) RADIX_DECIMAL_VALUES#0 + (number~) main::$2)
(word*) main::info_values#1 ← phi( main::@1/(word*) main::info_values#0 main::@2/(word*) main::info_values#1 )
(word) main::digit_value#0 ← *((word*) main::info_values#1 + (byte) main::digit#2)
(byte~) main::$2 ← (byte) main::digit#2 * (const byte) SIZEOF_WORD
*((word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0
(byte) main::digit#1 ← (byte) main::digit#2 + rangenext(0,4)
(bool~) main::$0 ← (byte) main::digit#1 != rangelast(0,4)
if((bool~) main::$0) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@2
(byte) main::radix#2 ← phi( main::@2/(byte) main::radix#3 )
(byte) main::radix#1 ← (byte) main::radix#2 + rangenext(0,1)
(bool~) main::$1 ← (byte) main::radix#1 != rangelast(0,1)
if((bool~) main::$1) goto main::@1
to:main::@return to:main::@return
main::@return: scope:[main] from main::@3 main::@return: scope:[main] from main
return return
to:@return to:@return
@1: scope:[] from @begin @1: scope:[] from @begin
@ -55,31 +40,22 @@ SYMBOL TABLE SSA
(word*) RadixInfo::values (word*) RadixInfo::values
(const byte) SIZEOF_WORD = (byte) 2 (const byte) SIZEOF_WORD = (byte) 2
(void()) main() (void()) main()
(bool~) main::$0 (number~) main::$0
(bool~) main::$1 (number~) main::$1
(byte~) main::$2 (number~) main::$2
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(word*) main::SCREEN (word*) main::SCREEN
(word*) main::SCREEN#0 (word*) main::SCREEN#0
(byte) main::digit
(byte) main::digit#0
(byte) main::digit#1
(byte) main::digit#2
(word) main::digit_value
(word) main::digit_value#0
(word*) main::info_values (word*) main::info_values
(word*) main::info_values#0 (word*) main::info_values#0
(word*) main::info_values#1
(byte) main::radix
(byte) main::radix#0
(byte) main::radix#1
(byte) main::radix#2
(byte) main::radix#3
(byte) main::radix#4
Adding number conversion cast (unumber) 1 in (number~) main::$0 ← (number) 1 * (const byte) SIZEOF_WORD
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (unumber)(number) 1 * (const byte) SIZEOF_WORD
Adding number conversion cast (unumber) 0 in (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD
Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 0 * (const byte) SIZEOF_WORD
Adding number conversion cast (unumber) 1 in (number~) main::$2 ← (number) 1 * (const byte) SIZEOF_WORD
Adding number conversion cast (unumber) main::$2 in (number~) main::$2 ← (unumber)(number) 1 * (const byte) SIZEOF_WORD
Successful SSA optimization PassNAddNumberTypeConversions
Adding number conversion cast (word) to elements in (word[]) RADIX_DECIMAL_VALUES#0 ← { (word)(number) $2710, (word)(number) $3e8, (word)(number) $64, (word)(number) $a } Adding number conversion cast (word) to elements in (word[]) RADIX_DECIMAL_VALUES#0 ← { (word)(number) $2710, (word)(number) $3e8, (word)(number) $64, (word)(number) $a }
Successful SSA optimization PassNAddArrayNumberTypeConversions Successful SSA optimization PassNAddArrayNumberTypeConversions
Inlining cast (word*) main::SCREEN#0 ← (word*)(number) $400 Inlining cast (word*) main::SCREEN#0 ← (word*)(number) $400
@ -89,68 +65,57 @@ Simplifying constant integer cast $3e8
Simplifying constant integer cast $64 Simplifying constant integer cast $64
Simplifying constant integer cast $a Simplifying constant integer cast $a
Simplifying constant pointer cast (word*) 1024 Simplifying constant pointer cast (word*) 1024
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Alias (byte) main::radix#2 = (byte) main::radix#3 Finalized unsigned number type (byte) 1
Successful SSA optimization Pass2AliasElimination Finalized unsigned number type (byte) 0
Identical Phi Values (word*) main::info_values#1 (word*) main::info_values#0 Finalized unsigned number type (byte) 1
Identical Phi Values (byte) main::radix#2 (byte) main::radix#4 Successful SSA optimization PassNFinalizeNumberTypeConversions
Successful SSA optimization Pass2IdenticalPhiElimination Inferred type updated to byte in (unumber~) main::$0 ← (byte) 1 * (const byte) SIZEOF_WORD
Simple Condition (bool~) main::$0 [12] if((byte) main::digit#1!=rangelast(0,4)) goto main::@2 Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Simple Condition (bool~) main::$1 [16] if((byte) main::radix#1!=rangelast(0,1)) goto main::@1 Inferred type updated to byte in (unumber~) main::$2 ← (byte) 1 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [0] (word[]) RADIX_DECIMAL_VALUES#0 ← { (word) $2710, (word) $3e8, (word) $64, (word) $a } Constant right-side identified [0] (word[]) RADIX_DECIMAL_VALUES#0 ← { (word) $2710, (word) $3e8, (word) $64, (word) $a }
Constant right-side identified [3] (byte~) main::$0 ← (byte) 1 * (const byte) SIZEOF_WORD
Constant right-side identified [4] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD
Constant right-side identified [6] (byte~) main::$2 ← (byte) 1 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const word[]) RADIX_DECIMAL_VALUES#0 = { $2710, $3e8, $64, $a } Constant (const word[]) RADIX_DECIMAL_VALUES#0 = { $2710, $3e8, $64, $a }
Constant (const word*) main::SCREEN#0 = (word*) 1024 Constant (const word*) main::SCREEN#0 = (word*) 1024
Constant (const byte) main::radix#0 = 0 Constant (const byte) main::$0 = 1*SIZEOF_WORD
Constant (const byte) main::digit#0 = 0 Constant (const byte) main::$1 = 0*SIZEOF_WORD
Constant (const byte) main::$2 = 1*SIZEOF_WORD
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Constant (const word*) main::info_values#0 = RADIX_DECIMAL_VALUES#0 Constant (const word*) main::info_values#0 = RADIX_DECIMAL_VALUES#0
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [10] main::digit#1 ← ++ main::digit#2 to ++ Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_WORD in
Resolved ranged comparison value [12] if(main::digit#1!=rangelast(0,4)) goto main::@2 to (number) 5 Successful SSA optimization PassNSimplifyConstantZero
Resolved ranged next value [14] main::radix#1 ← ++ main::radix#4 to ++ Simplifying expression containing zero main::SCREEN#0 in [5] *((const word*) main::SCREEN#0 + (const byte) main::$1) ← *((const word*) main::info_values#0 + (const byte) main::$0)
Resolved ranged comparison value [16] if(main::radix#1!=rangelast(0,1)) goto main::@1 to (number) 2 Successful SSA optimization PassNSimplifyExpressionWithZero
Adding number conversion cast (unumber) 5 in if((byte) main::digit#1!=(number) 5) goto main::@2 Eliminating unused constant (const byte) main::$1
Adding number conversion cast (unumber) 2 in if((byte) main::radix#1!=(number) 2) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 5
Simplifying constant integer cast 2
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 5
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Rewriting multiplication to use shift [3] (byte~) main::$2 ← (byte) main::digit#2 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings (const byte) main::radix#0
Inlining constant with var siblings (const byte) main::digit#0
Constant inlined main::info_values#0 = (const word[]) RADIX_DECIMAL_VALUES#0
Constant inlined main::radix#0 = (byte) 0
Constant inlined main::digit#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Eliminating unused constant (const byte) SIZEOF_WORD
Successful SSA optimization PassNEliminateUnusedVars Successful SSA optimization PassNEliminateUnusedVars
Added new block during phi lifting main::@5(between main::@3 and main::@1) Constant inlined main::info_values#0 = (const word[]) RADIX_DECIMAL_VALUES#0
Added new block during phi lifting main::@6(between main::@2 and main::@2) Constant inlined main::$2 = (byte) 1*(const byte) SIZEOF_WORD
Constant inlined main::$0 = (byte) 1*(const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(RADIX_DECIMAL_VALUES#0+1*SIZEOF_WORD)
Consolidated array index constant in *(RADIX_DECIMAL_VALUES#0+1*SIZEOF_WORD)
Consolidated array index constant in *(main::SCREEN#0+1*SIZEOF_WORD)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1 Adding NOP phi() at start of @1
Adding NOP phi() at start of @2 Adding NOP phi() at start of @2
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH CALL GRAPH
Calls in [] to main:2 Calls in [] to main:2
Created 2 initial phi equivalence classes Created 0 initial phi equivalence classes
Coalesced [16] main::radix#5 ← main::radix#1 Coalesced down to 0 phi equivalence classes
Coalesced [17] main::digit#3 ← main::digit#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @2 Culled Empty Block (label) @2
Culled Empty Block (label) main::@5
Culled Empty Block (label) main::@6
Adding NOP phi() at start of @begin Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1 Adding NOP phi() at start of @1
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH FINAL CONTROL FLOW GRAPH
@begin: scope:[] from @begin: scope:[] from
@ -163,25 +128,11 @@ FINAL CONTROL FLOW GRAPH
@end: scope:[] from @1 @end: scope:[] from @1
[3] phi() [3] phi()
main: scope:[main] from @1 main: scope:[main] from @1
[4] phi() [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD)
to:main::@1 [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD)
main::@1: scope:[main] from main main::@3
[5] (byte) main::radix#4 ← phi( main/(byte) 0 main::@3/(byte) main::radix#1 )
to:main::@2
main::@2: scope:[main] from main::@1 main::@2
[6] (byte) main::digit#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::digit#1 )
[7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2)
[8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1
[9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0
[10] (byte) main::digit#1 ← ++ (byte) main::digit#2
[11] if((byte) main::digit#1!=(byte) 5) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@2
[12] (byte) main::radix#1 ← ++ (byte) main::radix#4
[13] if((byte) main::radix#1!=(byte) 2) goto main::@1
to:main::@return to:main::@return
main::@return: scope:[main] from main::@3 main::@return: scope:[main] from main
[14] return [6] return
to:@return to:@return
@ -189,32 +140,11 @@ VARIABLE REGISTER WEIGHTS
(word[]) RADIX_DECIMAL_VALUES (word[]) RADIX_DECIMAL_VALUES
(word*) RadixInfo::values (word*) RadixInfo::values
(void()) main() (void()) main()
(byte~) main::$2 202.0
(word*) main::SCREEN (word*) main::SCREEN
(byte) main::digit
(byte) main::digit#1 151.5
(byte) main::digit#2 101.0
(word) main::digit_value
(word) main::digit_value#0 101.0
(word*) main::info_values (word*) main::info_values
(byte) main::radix
(byte) main::radix#1 16.5
(byte) main::radix#4 3.142857142857143
Initial phi equivalence classes Initial phi equivalence classes
[ main::radix#4 main::radix#1 ]
[ main::digit#2 main::digit#1 ]
Added variable main::digit_value#0 to zero page equivalence class [ main::digit_value#0 ]
Added variable main::$2 to zero page equivalence class [ main::$2 ]
Complete equivalence classes Complete equivalence classes
[ main::radix#4 main::radix#1 ]
[ main::digit#2 main::digit#1 ]
[ main::digit_value#0 ]
[ main::$2 ]
Allocated zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
Allocated zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ]
Allocated zp ZP_WORD:4 [ main::digit_value#0 ]
Allocated zp ZP_BYTE:6 [ main::$2 ]
INITIAL ASM INITIAL ASM
Target platform is c64basic Target platform is c64basic
@ -225,6 +155,7 @@ Target platform is c64basic
:BasicUpstart(bbegin) :BasicUpstart(bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_WORD = 2
// @begin // @begin
bbegin: bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
@ -233,8 +164,6 @@ b1_from_bbegin:
// @1 // @1
b1: b1:
// [2] call main // [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main jsr main
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1: bend_from_b1:
@ -244,99 +173,37 @@ bend:
// main // main
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label _2 = 6 // [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
.label digit_value = 4 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
.label digit = 3 sta SCREEN
.label radix = 2 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
// [5] phi from main to main::@1 [phi:main->main::@1] sta SCREEN+1
b1_from_main: // [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
// [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
lda #0 sta SCREEN+1*SIZEOF_WORD
sta radix lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
jmp b1 sta SCREEN+1*SIZEOF_WORD+1
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
// [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
b2_from_b1:
// [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1
lda #0
sta digit
jmp b2
// [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
b2_from_b2:
// [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy
jmp b2
// main::@2
b2:
// [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuz2
ldy digit
lda RADIX_DECIMAL_VALUES,y
sta digit_value
lda RADIX_DECIMAL_VALUES+1,y
sta digit_value+1
// [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuz1=vbuz2_rol_1
lda digit
asl
sta _2
// [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuz1=vwuz2
ldy _2
lda digit_value
sta SCREEN,y
lda digit_value+1
sta SCREEN+1,y
// [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuz1=_inc_vbuz1
inc digit
// [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuz1_neq_vbuc1_then_la1
lda #5
cmp digit
bne b2_from_b2
jmp b3
// main::@3
b3:
// [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1
inc radix
// [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2
cmp radix
bne b1_from_b3
jmp breturn jmp breturn
// main::@return // main::@return
breturn: breturn:
// [14] return // [6] return
rts rts
} }
// File Data // File Data
RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a
REGISTER UPLIFT POTENTIAL REGISTERS REGISTER UPLIFT POTENTIAL REGISTERS
Statement [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) [ main::radix#4 main::digit#2 main::digit_value#0 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 ] ) always clobbers reg byte a Statement [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) [ ] ( main:2 [ ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] Statement [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) [ ] ( main:2 [ ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ]
Statement [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ) always clobbers reg byte a
Statement [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 [ main::radix#4 main::digit#2 ] ( main:2 [ main::radix#4 main::digit#2 ] ) always clobbers reg byte a
Statement [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) [ main::radix#4 main::digit#2 main::digit_value#0 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 ] ) always clobbers reg byte a
Statement [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ) always clobbers reg byte a
Statement [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 [ main::radix#4 main::digit#2 ] ( main:2 [ main::radix#4 main::digit#2 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
Potential registers zp ZP_WORD:4 [ main::digit_value#0 ] : zp ZP_WORD:4 ,
Potential registers zp ZP_BYTE:6 [ main::$2 ] : zp ZP_BYTE:6 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES REGISTER UPLIFT SCOPES
Uplift Scope [main] 252.5: zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ] 202: zp ZP_BYTE:6 [ main::$2 ] 101: zp ZP_WORD:4 [ main::digit_value#0 ] 19.64: zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
Uplift Scope [RadixInfo] Uplift Scope [RadixInfo]
Uplift Scope [main]
Uplift Scope [] Uplift Scope []
Uplifting [main] best 5733 combination reg byte x [ main::digit#2 main::digit#1 ] reg byte a [ main::$2 ] zp ZP_WORD:4 [ main::digit_value#0 ] zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] Uplifting [RadixInfo] best 53 combination
Uplifting [RadixInfo] best 5733 combination Uplifting [main] best 53 combination
Uplifting [] best 5733 combination Uplifting [] best 53 combination
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
Uplifting [main] best 5733 combination zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
Allocated (was zp ZP_WORD:4) zp ZP_WORD:3 [ main::digit_value#0 ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
@ -346,6 +213,7 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(bbegin) :BasicUpstart(bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_WORD = 2
// @begin // @begin
bbegin: bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
@ -354,8 +222,6 @@ b1_from_bbegin:
// @1 // @1
b1: b1:
// [2] call main // [2] call main
// [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main jsr main
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1: bend_from_b1:
@ -365,63 +231,20 @@ bend:
// main // main
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label digit_value = 3 // [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
.label radix = 2 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
// [5] phi from main to main::@1 [phi:main->main::@1] sta SCREEN
b1_from_main: lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
// [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 sta SCREEN+1
lda #0 // [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
sta radix lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
jmp b1 sta SCREEN+1*SIZEOF_WORD
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
b1_from_b3: sta SCREEN+1*SIZEOF_WORD+1
// [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
b2_from_b1:
// [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
ldx #0
jmp b2
// [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
b2_from_b2:
// [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy
jmp b2
// main::@2
b2:
// [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuxx
lda RADIX_DECIMAL_VALUES,x
sta digit_value
lda RADIX_DECIMAL_VALUES+1,x
sta digit_value+1
// [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
txa
asl
// [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuaa=vwuz1
tay
lda digit_value
sta SCREEN,y
lda digit_value+1
sta SCREEN+1,y
// [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuxx=_inc_vbuxx
inx
// [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
cpx #5
bne b2_from_b2
jmp b3
// main::@3
b3:
// [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1
inc radix
// [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2
cmp radix
bne b1_from_b3
jmp breturn jmp breturn
// main::@return // main::@return
breturn: breturn:
// [14] return // [6] return
rts rts
} }
// File Data // File Data
@ -430,32 +253,18 @@ main: {
ASSEMBLER OPTIMIZATIONS ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1 Removing instruction jmp b1
Removing instruction jmp bend Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp b3
Removing instruction jmp breturn Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Replacing label b2_from_b2 with b2
Replacing label b1_from_b3 with b1
Removing instruction b1_from_bbegin: Removing instruction b1_from_bbegin:
Removing instruction b1: Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1: Removing instruction bend_from_b1:
Removing instruction b1_from_b3:
Removing instruction b2_from_b1:
Removing instruction b2_from_b2:
Succesful ASM optimization Pass5RedundantLabelElimination Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend: Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction b3:
Removing instruction breturn: Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly Updating BasicUpstart to call main directly
Removing instruction jsr main Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp b1
Removing instruction jmp b2
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin: Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
@ -466,32 +275,17 @@ FINAL SYMBOL TABLE
(word[]) RADIX_DECIMAL_VALUES (word[]) RADIX_DECIMAL_VALUES
(const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a } (const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a }
(word*) RadixInfo::values (word*) RadixInfo::values
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2
(void()) main() (void()) main()
(byte~) main::$2 reg byte a 202.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(word*) main::SCREEN (word*) main::SCREEN
(const word*) main::SCREEN#0 SCREEN = (word*) 1024 (const word*) main::SCREEN#0 SCREEN = (word*) 1024
(byte) main::digit
(byte) main::digit#1 reg byte x 151.5
(byte) main::digit#2 reg byte x 101.0
(word) main::digit_value
(word) main::digit_value#0 digit_value zp ZP_WORD:3 101.0
(word*) main::info_values (word*) main::info_values
(byte) main::radix
(byte) main::radix#1 radix zp ZP_BYTE:2 16.5
(byte) main::radix#4 radix zp ZP_BYTE:2 3.142857142857143
zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
reg byte x [ main::digit#2 main::digit#1 ]
zp ZP_WORD:3 [ main::digit_value#0 ]
reg byte a [ main::$2 ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 4731 Score: 38
// File Comments // File Comments
// Illustrates a problem with pointer sizeof()-rewriting for pointers inside structs // Illustrates a problem with pointer sizeof()-rewriting for pointers inside structs
@ -500,66 +294,31 @@ Score: 4731
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_WORD = 2
// @begin // @begin
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
// @1 // @1
// [2] call main // [2] call main
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
// @end // @end
// main // main
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label digit_value = 3 // SCREEN[0] = info.values[1]
.label radix = 2 // [4] *((const word*) main::SCREEN#0) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
// [5] phi from main to main::@1 [phi:main->main::@1] lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
// [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 sta SCREEN
lda #0 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
sta radix sta SCREEN+1
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] // SCREEN[1] = RADIX_DECIMAL_VALUES[1]
// [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy // [5] *((const word*) main::SCREEN#0+(byte) 1*(const byte) SIZEOF_WORD) ← *((const word[]) RADIX_DECIMAL_VALUES#0+(byte) 1*(const byte) SIZEOF_WORD) -- _deref_pwuc1=_deref_pwuc2
// main::@1 lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD
b1: sta SCREEN+1*SIZEOF_WORD
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2] lda RADIX_DECIMAL_VALUES+1*SIZEOF_WORD+1
// [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1 sta SCREEN+1*SIZEOF_WORD+1
ldx #0
// [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
// [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy
// main::@2
b2:
// digit_value = info.values[digit]
// [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuxx
lda RADIX_DECIMAL_VALUES,x
sta digit_value
lda RADIX_DECIMAL_VALUES+1,x
sta digit_value+1
// SCREEN[digit] = digit_value
// [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
txa
asl
// [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuaa=vwuz1
tay
lda digit_value
sta SCREEN,y
lda digit_value+1
sta SCREEN+1,y
// for( char digit: 0..4 )
// [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuxx=_inc_vbuxx
inx
// [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
cpx #5
bne b2
// main::@3
// for( byte radix: 0..1)
// [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1
inc radix
// [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2
cmp radix
bne b1
// main::@return // main::@return
// } // }
// [14] return // [6] return
rts rts
} }
// File Data // File Data

View File

@ -4,25 +4,10 @@
(word[]) RADIX_DECIMAL_VALUES (word[]) RADIX_DECIMAL_VALUES
(const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a } (const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a }
(word*) RadixInfo::values (word*) RadixInfo::values
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2
(void()) main() (void()) main()
(byte~) main::$2 reg byte a 202.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(word*) main::SCREEN (word*) main::SCREEN
(const word*) main::SCREEN#0 SCREEN = (word*) 1024 (const word*) main::SCREEN#0 SCREEN = (word*) 1024
(byte) main::digit
(byte) main::digit#1 reg byte x 151.5
(byte) main::digit#2 reg byte x 101.0
(word) main::digit_value
(word) main::digit_value#0 digit_value zp ZP_WORD:3 101.0
(word*) main::info_values (word*) main::info_values
(byte) main::radix
(byte) main::radix#1 radix zp ZP_BYTE:2 16.5
(byte) main::radix#4 radix zp ZP_BYTE:2 3.142857142857143
zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ]
reg byte x [ main::digit#2 main::digit#1 ]
zp ZP_WORD:3 [ main::digit_value#0 ]
reg byte a [ main::$2 ]