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:
parent
a9e0c7805f
commit
0c33353bf8
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 ]
|
|
||||||
|
Loading…
Reference in New Issue
Block a user