mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-07 05:30:43 +00:00
Working on fixing void pointers #186
This commit is contained in:
parent
d3e21133fa
commit
0a4ef77056
4
src/main/fragment/pvoz1=pvoc1.asm
Normal file
4
src/main/fragment/pvoz1=pvoc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c1}
|
||||
sta {z1}
|
||||
lda #>{c1}
|
||||
sta {z1}+1
|
@ -181,12 +181,16 @@ public class Compiler {
|
||||
new Pass1AssertNoLValueIntermediate(program).execute();
|
||||
new Pass1PointerSizeofFix(program).execute(); // After this point in the code all pointer math is byte-based
|
||||
new PassNSizeOfSimplification(program).execute(); // Needed to eliminate sizeof() referencing pointer value variables
|
||||
|
||||
//new PassNAddTypeConversionAssignment(program).execute();
|
||||
//new Pass1AssertProcedureCallParameters(program).execute();
|
||||
|
||||
new Pass1UnwindStructValues(program).execute();
|
||||
new PassNStructPointerRewriting(program).execute();
|
||||
|
||||
new PassNAddBooleanCasts(program).execute();
|
||||
new PassNAddTypeConversionAssignment(program).execute();
|
||||
|
||||
//new Pass1AssertProcedureCallParameters(program).execute();
|
||||
|
||||
new Pass1EarlyConstantIdentification(program).execute();
|
||||
new Pass1ProcedureInline(program).execute();
|
||||
|
@ -358,6 +358,8 @@ public class AsmFragmentInstanceSpecFactory {
|
||||
return "pds";
|
||||
} else if(SymbolType.BOOLEAN.equals(elementType)) {
|
||||
return "pbo";
|
||||
} else if(SymbolType.VOID.equals(elementType)) {
|
||||
return "pvo";
|
||||
} else if(elementType instanceof SymbolTypeProcedure) {
|
||||
return "ppr";
|
||||
} else if(elementType instanceof SymbolTypePointer) {
|
||||
|
@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary {
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType left, SymbolType right) {
|
||||
if(left instanceof SymbolTypePointer) {
|
||||
if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) {
|
||||
if(SymbolType.isInteger(right)) {
|
||||
return left;
|
||||
} else {
|
||||
throw new NoMatchingType("Cannot divide pointer by "+right.toString());
|
||||
|
@ -1,7 +1,10 @@
|
||||
package dk.camelot64.kickc.model.operators;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInteger;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantChar;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
@ -25,7 +28,7 @@ public class OperatorMinus extends OperatorBinary {
|
||||
} else if(left instanceof ConstantChar && right instanceof ConstantInteger) {
|
||||
return new ConstantInteger(((ConstantChar) left).getChar() - ((ConstantInteger) right).getInteger());
|
||||
}
|
||||
throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right);
|
||||
throw new InternalError("Calculation not implemented " + left + " " + getOperator() + " " + right);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -40,7 +43,7 @@ public class OperatorMinus extends OperatorBinary {
|
||||
if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
|
||||
return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
|
||||
}
|
||||
throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
||||
throw new InternalError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.model.operators;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
@ -17,7 +17,7 @@ public class OperatorMultiply extends OperatorBinary {
|
||||
if(left instanceof ConstantInteger && right instanceof ConstantInteger) {
|
||||
return new ConstantInteger(((ConstantInteger) left).getInteger() * ((ConstantInteger) right).getInteger());
|
||||
}
|
||||
throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right);
|
||||
throw new ConstantNotLiteral("Not literal "+left.toString()+"*"+right.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,15 +103,12 @@ public class SymbolTypeConversion {
|
||||
if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
|
||||
|
||||
// Identify which of the two operands is a number and which is a fixed type
|
||||
RValue numberVal;
|
||||
SymbolTypeIntegerFixed fixedType;
|
||||
if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
|
||||
// Left is the number type - right is the fixed type
|
||||
numberVal = left;
|
||||
fixedType = (SymbolTypeIntegerFixed) rightType;
|
||||
} else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) {
|
||||
// Right is the number type - left is the fixed type
|
||||
numberVal = right;
|
||||
fixedType = (SymbolTypeIntegerFixed) leftType;
|
||||
} else {
|
||||
// Binary operator combining number and non-integer
|
||||
@ -187,6 +184,8 @@ public class SymbolTypeConversion {
|
||||
* @return true if the types match up
|
||||
*/
|
||||
public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
|
||||
if(SymbolType.VAR.equals(rValueType))
|
||||
return true;
|
||||
if(lValueType.equals(rValueType))
|
||||
return true;
|
||||
if(SymbolType.WORD.equals(lValueType) && SymbolType.BYTE.equals(rValueType))
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.model.types;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
@ -43,7 +44,7 @@ public class SymbolTypeInference {
|
||||
SymbolType rightType = inferType(symbols, constBin.getRight());
|
||||
return constBin.getOperator().inferType(leftType, rightType);
|
||||
} else if(rValue instanceof ValueList) {
|
||||
type = inferTypeList(symbols, (ValueList) rValue);
|
||||
return SymbolType.VAR;
|
||||
} else if(rValue instanceof PointerDereference) {
|
||||
SymbolType pointerType = inferType(symbols, ((PointerDereference) rValue).getPointer());
|
||||
if(pointerType instanceof SymbolTypePointer) {
|
||||
@ -51,7 +52,7 @@ public class SymbolTypeInference {
|
||||
} else if(pointerType.equals(SymbolType.STRING)) {
|
||||
return SymbolType.BYTE;
|
||||
} else {
|
||||
throw new RuntimeException("Cannot infer pointer element type from pointer type " + pointerType);
|
||||
throw new InternalError("Cannot infer pointer element type from pointer type " + pointerType);
|
||||
}
|
||||
} else if(rValue instanceof ConstantArrayList) {
|
||||
return new SymbolTypeArray(((ConstantArrayList) rValue).getElementType());
|
||||
@ -97,7 +98,7 @@ public class SymbolTypeInference {
|
||||
SymbolType rightType = inferType(symbols, rValue2);
|
||||
rValueType = ((OperatorBinary) assignment.getOperator()).inferType(leftType, rightType);
|
||||
} else {
|
||||
throw new CompileError("Cannot infer type of " + assignment.toString());
|
||||
throw new InternalError("Cannot infer type of " + assignment.toString());
|
||||
}
|
||||
return rValueType;
|
||||
} else if(rValue instanceof StructMemberRef) {
|
||||
@ -119,35 +120,9 @@ public class SymbolTypeInference {
|
||||
return ((StructUnwoundPlaceholder) rValue).getTypeStruct();
|
||||
}
|
||||
if(type == null) {
|
||||
throw new RuntimeException("Cannot infer type for " + rValue.toString());
|
||||
throw new InternalError("Cannot infer type for " + rValue.toString());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static SymbolType inferTypeList(ProgramScope symbols, ValueList list) {
|
||||
SymbolType elmType = null;
|
||||
for(RValue elm : list.getList()) {
|
||||
SymbolType type = inferType(symbols, elm);
|
||||
if(elmType == null) {
|
||||
elmType = type;
|
||||
} else {
|
||||
if(!elmType.equals(type)) {
|
||||
if(SymbolType.NUMBER.equals(elmType) && SymbolType.isInteger(type)) {
|
||||
elmType = SymbolType.NUMBER;
|
||||
} else if(SymbolType.isInteger(elmType) && SymbolType.NUMBER.equals(type)) {
|
||||
elmType = SymbolType.NUMBER;
|
||||
} else {
|
||||
throw new CompileError("Array element has type mismatch "+elm.toString() + " not matching type " + elmType.getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(elmType != null) {
|
||||
long size = list.getList().size();
|
||||
return new SymbolTypeArray(elmType, new ConstantInteger(size, size<256?SymbolType.BYTE:SymbolType.WORD));
|
||||
} else {
|
||||
throw new RuntimeException("Cannot infer list element type " + list.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.model.types;
|
||||
|
||||
/** Integer type marker interface. */
|
||||
public interface SymbolTypeInteger extends SymbolType {
|
||||
public interface SymbolTypeInteger extends SymbolType {
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
@ -98,7 +99,7 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
|
||||
} else {
|
||||
if(!listType.equals(elmType)) {
|
||||
// No overlap between list type and element type
|
||||
throw new RuntimeException("Array type " + listType + " does not match element type " + elmType + ". Array: " + valueList.toString(getProgram()));
|
||||
throw new InternalError("Array type " + listType + " does not match element type " + elmType + ". Array: " + valueList.toString(getProgram()));
|
||||
}
|
||||
}
|
||||
elements.add(constantValue);
|
||||
|
@ -4,9 +4,10 @@ import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.ValueList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -29,8 +30,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
RValue right = binary.getRight();
|
||||
SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
|
||||
SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
|
||||
|
||||
if(!SymbolTypeConversion.assignmentTypeMatch(leftType, rightType)) {
|
||||
if(!SymbolTypeConversion.assignmentTypeMatch(leftType, rightType) || SymbolType.VAR.equals(rightType)) {
|
||||
// Assigning a pointer from an unsigned word
|
||||
if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) {
|
||||
if((leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) {
|
||||
@ -45,19 +45,19 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
getLog().append("Adding pointer type conversion cast to void pointer (" + leftType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
|
||||
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if(SymbolType.WORD.equals(leftType) && isLiteralWordCandidate(rightType)) {
|
||||
} else if(SymbolType.WORD.equals(leftType) && isLiteralWordCandidate(right)) {
|
||||
// Detect word literal constructor
|
||||
SymbolType conversionType = SymbolType.WORD;
|
||||
getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
|
||||
binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if(leftType instanceof SymbolTypePointer && isLiteralWordCandidate(rightType)) {
|
||||
} else if(leftType instanceof SymbolTypePointer && !(leftType instanceof SymbolTypeArray) && isLiteralWordCandidate(right)) {
|
||||
// Detect word literal constructor
|
||||
SymbolType conversionType = SymbolType.WORD;
|
||||
getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
|
||||
binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
|
||||
modified.set(true);
|
||||
} else if(SymbolType.DWORD.equals(leftType) && isLiteralWordCandidate(rightType)) {
|
||||
} else if(SymbolType.DWORD.equals(leftType) && isLiteralWordCandidate(right)) {
|
||||
// Detect dword literal constructor
|
||||
SymbolType conversionType = SymbolType.DWORD;
|
||||
getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
|
||||
@ -72,12 +72,18 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
return modified.get();
|
||||
}
|
||||
|
||||
public static boolean isLiteralWordCandidate(SymbolType rightType) {
|
||||
if(rightType instanceof SymbolTypeArray) {
|
||||
SymbolTypeArray rightArray = (SymbolTypeArray) rightType;
|
||||
if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize()))
|
||||
if(SymbolType.isInteger(rightArray.getElementType()))
|
||||
return true;
|
||||
private boolean isLiteralWordCandidate(RValue rValue) {
|
||||
if(rValue instanceof ValueList) {
|
||||
List<RValue> list = ((ValueList) rValue).getList();
|
||||
if(list.size() == 2) {
|
||||
for(RValue elm : list) {
|
||||
if(!SymbolType.isInteger(SymbolTypeInference.inferType(getProgram().getScope(), elm))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Two integer elements
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -36,7 +36,24 @@ public class TestPrograms {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerVoid() throws IOException, URISyntaxException {
|
||||
public void testCallParameterAutocast() throws IOException, URISyntaxException {
|
||||
compileAndCompare("call-parameter-autocast", log());
|
||||
}
|
||||
|
||||
/** Awaiting type system fix for void pointers
|
||||
@Test
|
||||
public void testPointerVoid2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-void-2", log());
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testPointerVoid1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-void-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerVoid0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-void-0");
|
||||
}
|
||||
|
||||
|
15
src/test/kc/call-parameter-autocast.kc
Normal file
15
src/test/kc/call-parameter-autocast.kc
Normal file
@ -0,0 +1,15 @@
|
||||
// Test auto-casting of call-parameters
|
||||
|
||||
void main() {
|
||||
word w = 0x1234;
|
||||
print(0x1234);
|
||||
print(w);
|
||||
print( {0x12,0x34} );
|
||||
}
|
||||
|
||||
const word* SCREEN = 0x0400;
|
||||
byte idx = 0;
|
||||
|
||||
void print(word w) {
|
||||
SCREEN[idx++] = w;
|
||||
}
|
20
src/test/kc/pointer-void-1.kc
Normal file
20
src/test/kc/pointer-void-1.kc
Normal file
@ -0,0 +1,20 @@
|
||||
// Test simple void pointer - void pointer function
|
||||
|
||||
void main() {
|
||||
dword d = 0x12345678;
|
||||
word w = 0x1234;
|
||||
byte b = 0x12;
|
||||
void* vb = &b;
|
||||
void* vw = &w;
|
||||
void* vd = &d;
|
||||
print(vb);
|
||||
print(vw);
|
||||
print(vd);
|
||||
}
|
||||
|
||||
const byte* SCREEN = 0x0400;
|
||||
byte idx = 0;
|
||||
|
||||
void print(void* ptr) {
|
||||
SCREEN[idx++] = *((byte*)ptr);
|
||||
}
|
17
src/test/kc/pointer-void-2.kc
Normal file
17
src/test/kc/pointer-void-2.kc
Normal file
@ -0,0 +1,17 @@
|
||||
// Test simple void pointer - void pointer function
|
||||
|
||||
void main() {
|
||||
dword d = 0x12345678;
|
||||
word w = 0x1234;
|
||||
byte b = 0x12;
|
||||
print(&b);
|
||||
print(&w);
|
||||
print(&d);
|
||||
}
|
||||
|
||||
const byte* SCREEN = 0x0400;
|
||||
byte idx = 0;
|
||||
|
||||
void print(void* ptr) {
|
||||
SCREEN[idx++] = *((byte*)ptr);
|
||||
}
|
38
src/test/ref/call-parameter-autocast.asm
Normal file
38
src/test/ref/call-parameter-autocast.asm
Normal file
@ -0,0 +1,38 @@
|
||||
// Test auto-casting of call-parameters
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.const w = $1234
|
||||
lda #<$1234
|
||||
sta print.w
|
||||
lda #>$1234
|
||||
sta print.w+1
|
||||
ldx #0
|
||||
jsr print
|
||||
lda #<w
|
||||
sta print.w
|
||||
lda #>w
|
||||
sta print.w+1
|
||||
jsr print
|
||||
lda #<$12*$100+$34
|
||||
sta print.w
|
||||
lda #>$12*$100+$34
|
||||
sta print.w+1
|
||||
jsr print
|
||||
rts
|
||||
}
|
||||
// print(word zeropage(2) w)
|
||||
print: {
|
||||
.label w = 2
|
||||
txa
|
||||
asl
|
||||
tay
|
||||
lda w
|
||||
sta SCREEN,y
|
||||
lda w+1
|
||||
sta SCREEN+1,y
|
||||
inx
|
||||
rts
|
||||
}
|
34
src/test/ref/call-parameter-autocast.cfg
Normal file
34
src/test/ref/call-parameter-autocast.cfg
Normal file
@ -0,0 +1,34 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
[9] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[10] return
|
||||
to:@return
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
[11] (word) print::w#3 ← phi( main/(word) $1234 main::@1/(const word) main::w#0 main::@2/(byte) $12*(word) $100+(byte) $34 )
|
||||
[11] (byte) idx#12 ← phi( main/(byte) 0 main::@1/(byte) idx#13 main::@2/(byte) idx#13 )
|
||||
[12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1
|
||||
[13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3
|
||||
[14] (byte) idx#13 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[15] return
|
||||
to:@return
|
617
src/test/ref/call-parameter-autocast.log
Normal file
617
src/test/ref/call-parameter-autocast.log
Normal file
@ -0,0 +1,617 @@
|
||||
Fixing pointer array-indexing *((word*) SCREEN + (byte) idx)
|
||||
Adding pointer type conversion cast (word*) SCREEN in (word*) SCREEN ← (number) $400
|
||||
Identified constant variable (word) main::w
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#15 ← phi( @2/(byte) idx#16 )
|
||||
(word) main::w#0 ← (number) $1234
|
||||
(word) print::w#0 ← (number) $1234
|
||||
call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte) idx#8 ← phi( main/(byte) idx#6 )
|
||||
(byte) idx#0 ← (byte) idx#8
|
||||
(word) print::w#1 ← (word) main::w#0
|
||||
call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) idx#9 ← phi( main::@1/(byte) idx#6 )
|
||||
(byte) idx#1 ← (byte) idx#9
|
||||
(word) print::w#2 ← { (number) $12, (number) $34 }
|
||||
call print
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
(byte) idx#10 ← phi( main::@2/(byte) idx#6 )
|
||||
(byte) idx#2 ← (byte) idx#10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
(byte) idx#11 ← phi( main::@3/(byte) idx#2 )
|
||||
(byte) idx#3 ← (byte) idx#11
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(word*) SCREEN#0 ← ((word*)) (number) $400
|
||||
(byte) idx#4 ← (number) 0
|
||||
to:@2
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
(word) print::w#3 ← phi( main/(word) print::w#0 main::@1/(word) print::w#1 main::@2/(word) print::w#2 )
|
||||
(byte) idx#12 ← phi( main/(byte) idx#15 main::@1/(byte) idx#0 main::@2/(byte) idx#1 )
|
||||
(byte~) print::$0 ← (byte) idx#12 * (const byte) SIZEOF_WORD
|
||||
*((word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3
|
||||
(byte) idx#5 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
(byte) idx#13 ← phi( print/(byte) idx#5 )
|
||||
(byte) idx#6 ← (byte) idx#13
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#16 ← phi( @1/(byte) idx#4 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#14 ← phi( @2/(byte) idx#3 )
|
||||
(byte) idx#7 ← (byte) idx#14
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(word*) SCREEN
|
||||
(word*) SCREEN#0
|
||||
(const byte) SIZEOF_WORD = (byte) 2
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#10
|
||||
(byte) idx#11
|
||||
(byte) idx#12
|
||||
(byte) idx#13
|
||||
(byte) idx#14
|
||||
(byte) idx#15
|
||||
(byte) idx#16
|
||||
(byte) idx#2
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(word) main::w
|
||||
(word) main::w#0
|
||||
(void()) print((word) print::w)
|
||||
(byte~) print::$0
|
||||
(label) print::@return
|
||||
(word) print::w
|
||||
(word) print::w#0
|
||||
(word) print::w#1
|
||||
(word) print::w#2
|
||||
(word) print::w#3
|
||||
|
||||
Adding number conversion cast (unumber) $1234 in (word) main::w#0 ← (number) $1234
|
||||
Adding number conversion cast (unumber) $1234 in (word) print::w#0 ← (number) $1234
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#4 ← (number) 0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (word) main::w#0 ← (unumber)(number) $1234
|
||||
Inlining cast (word) print::w#0 ← (unumber)(number) $1234
|
||||
Inlining cast (word*) SCREEN#0 ← (word*)(number) $400
|
||||
Inlining cast (byte) idx#4 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast $1234
|
||||
Simplifying constant integer cast $1234
|
||||
Simplifying constant pointer cast (word*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (word) $1234
|
||||
Finalized unsigned number type (word) $1234
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Identified literal word (word) { $12, $34 } in (word) print::w#2 ← { (number) $12, (number) $34 }
|
||||
Successful SSA optimization PassNAddTypeConversionAssignment
|
||||
Alias (byte) idx#0 = (byte) idx#8
|
||||
Alias (byte) idx#1 = (byte) idx#9
|
||||
Alias (byte) idx#10 = (byte) idx#2 (byte) idx#11 (byte) idx#3
|
||||
Alias (byte) idx#13 = (byte) idx#5 (byte) idx#6
|
||||
Alias (byte) idx#16 = (byte) idx#4
|
||||
Alias (byte) idx#14 = (byte) idx#7
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#15 (byte) idx#16
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#1 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#10 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#14 (byte) idx#10
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Constant (const word) main::w#0 = $1234
|
||||
Constant (const word) print::w#0 = $1234
|
||||
Constant (const word*) SCREEN#0 = (word*) 1024
|
||||
Constant (const byte) idx#16 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const word) print::w#1 = main::w#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Fixing inline constructor with main::$3 ← (byte)$12 w= (byte)$34
|
||||
Successful SSA optimization Pass2FixInlineConstructorsNew
|
||||
Simplifying constant integer cast $12
|
||||
Simplifying constant integer cast $34
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Alias (word) print::w#2 = (word~) main::$3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Constant right-side identified [2] (word) print::w#2 ← (byte) $12 w= (byte) $34
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Adding number conversion cast (unumber) $12*$100+$34 in (word) print::w#2 ← (byte) $12*(number) $100+(byte) $34
|
||||
Adding number conversion cast (unumber) $12*$100 in (word) print::w#2 ← ((unumber)) (byte) $12*(number) $100+(byte) $34
|
||||
Adding number conversion cast (unumber) $100 in (word) print::w#2 ← ((unumber)) (unumber)(byte) $12*(number) $100+(byte) $34
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (word) print::w#2 ← (unumber)(unumber)(byte) $12*(unumber)(number) $100+(byte) $34
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast (unumber)(byte) $12*(unumber)(number) $100+(byte) $34
|
||||
Simplifying constant integer cast (byte) $12*(unumber)(number) $100
|
||||
Simplifying constant integer cast $100
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (word) $100
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant (const word) print::w#2 = $12*$100+$34
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Rewriting multiplication to use shift [5] (byte~) print::$0 ← (byte) idx#12 * (const byte) SIZEOF_WORD
|
||||
Successful SSA optimization Pass2MultiplyToShiftRewriting
|
||||
Inlining constant with var siblings (const word) print::w#0
|
||||
Inlining constant with var siblings (const word) print::w#1
|
||||
Inlining constant with var siblings (const word) print::w#2
|
||||
Inlining constant with var siblings (const byte) idx#16
|
||||
Constant inlined print::w#2 = (byte) $12*(word) $100+(byte) $34
|
||||
Constant inlined print::w#1 = (const word) main::w#0
|
||||
Constant inlined print::w#0 = (word) $1234
|
||||
Constant inlined idx#16 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Eliminating unused constant (const byte) SIZEOF_WORD
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@3
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print:7 print:9 print:11
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [8] idx#17 ← idx#13
|
||||
Coalesced (already) [10] idx#18 ← idx#13
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@3
|
||||
Renumbering block @2 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@1
|
||||
Adding NOP phi() at start of main::@2
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
[9] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[10] return
|
||||
to:@return
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
[11] (word) print::w#3 ← phi( main/(word) $1234 main::@1/(const word) main::w#0 main::@2/(byte) $12*(word) $100+(byte) $34 )
|
||||
[11] (byte) idx#12 ← phi( main/(byte) 0 main::@1/(byte) idx#13 main::@2/(byte) idx#13 )
|
||||
[12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1
|
||||
[13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3
|
||||
[14] (byte) idx#13 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[15] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(word*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#12 2.6666666666666665
|
||||
(byte) idx#13 1.0
|
||||
(void()) main()
|
||||
(word) main::w
|
||||
(void()) print((word) print::w)
|
||||
(byte~) print::$0 4.0
|
||||
(word) print::w
|
||||
(word) print::w#3 1.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ idx#12 idx#13 ]
|
||||
[ print::w#3 ]
|
||||
Added variable print::$0 to zero page equivalence class [ print::$0 ]
|
||||
Complete equivalence classes
|
||||
[ idx#12 idx#13 ]
|
||||
[ print::w#3 ]
|
||||
[ print::$0 ]
|
||||
Allocated zp ZP_BYTE:2 [ idx#12 idx#13 ]
|
||||
Allocated zp ZP_WORD:3 [ print::w#3 ]
|
||||
Allocated zp ZP_BYTE:5 [ print::$0 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Test auto-casting of call-parameters
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 2
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG9 @end
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.const w = $1234
|
||||
//SEG11 [5] call print
|
||||
//SEG12 [11] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
//SEG13 [11] phi (word) print::w#3 = (word) $1234 [phi:main->print#0] -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta print.w
|
||||
lda #>$1234
|
||||
sta print.w+1
|
||||
//SEG14 [11] phi (byte) idx#12 = (byte) 0 [phi:main->print#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
jsr print
|
||||
//SEG15 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
//SEG16 main::@1
|
||||
b1:
|
||||
//SEG17 [7] call print
|
||||
//SEG18 [11] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from_b1:
|
||||
//SEG19 [11] phi (word) print::w#3 = (const word) main::w#0 [phi:main::@1->print#0] -- vwuz1=vwuc1
|
||||
lda #<w
|
||||
sta print.w
|
||||
lda #>w
|
||||
sta print.w+1
|
||||
//SEG20 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
//SEG21 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG22 main::@2
|
||||
b2:
|
||||
//SEG23 [9] call print
|
||||
//SEG24 [11] phi from main::@2 to print [phi:main::@2->print]
|
||||
print_from_b2:
|
||||
//SEG25 [11] phi (word) print::w#3 = (byte) $12*(word) $100+(byte) $34 [phi:main::@2->print#0] -- vwuz1=vwuc1
|
||||
lda #<$12*$100+$34
|
||||
sta print.w
|
||||
lda #>$12*$100+$34
|
||||
sta print.w+1
|
||||
//SEG26 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp breturn
|
||||
//SEG27 main::@return
|
||||
breturn:
|
||||
//SEG28 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG29 print
|
||||
// print(word zeropage(3) w)
|
||||
print: {
|
||||
.label _0 = 5
|
||||
.label w = 3
|
||||
//SEG30 [12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda idx
|
||||
asl
|
||||
sta _0
|
||||
//SEG31 [13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3 -- pwuc1_derefidx_vbuz1=vwuz2
|
||||
ldy _0
|
||||
lda w
|
||||
sta SCREEN,y
|
||||
lda w+1
|
||||
sta SCREEN+1,y
|
||||
//SEG32 [14] (byte) idx#13 ← ++ (byte) idx#12 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
jmp breturn
|
||||
//SEG33 print::@return
|
||||
breturn:
|
||||
//SEG34 [15] return
|
||||
rts
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1 [ idx#12 print::w#3 print::$0 ] ( main:2::print:5 [ idx#12 print::w#3 print::$0 ] main:2::print:7 [ idx#12 print::w#3 print::$0 ] main:2::print:9 [ idx#12 print::w#3 print::$0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ idx#12 idx#13 ]
|
||||
Statement [13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3 [ idx#12 ] ( main:2::print:5 [ idx#12 ] main:2::print:7 [ idx#12 ] main:2::print:9 [ idx#12 ] ) always clobbers reg byte a
|
||||
Statement [12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1 [ idx#12 print::w#3 print::$0 ] ( main:2::print:5 [ idx#12 print::w#3 print::$0 ] main:2::print:7 [ idx#12 print::w#3 print::$0 ] main:2::print:9 [ idx#12 print::w#3 print::$0 ] ) always clobbers reg byte a
|
||||
Statement [13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3 [ idx#12 ] ( main:2::print:5 [ idx#12 ] main:2::print:7 [ idx#12 ] main:2::print:9 [ idx#12 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ idx#12 idx#13 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:3 [ print::w#3 ] : zp ZP_WORD:3 ,
|
||||
Potential registers zp ZP_BYTE:5 [ print::$0 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print] 4: zp ZP_BYTE:5 [ print::$0 ] 1: zp ZP_WORD:3 [ print::w#3 ]
|
||||
Uplift Scope [] 3.67: zp ZP_BYTE:2 [ idx#12 idx#13 ]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [print] best 117 combination reg byte a [ print::$0 ] zp ZP_WORD:3 [ print::w#3 ]
|
||||
Uplifting [] best 110 combination reg byte x [ idx#12 idx#13 ]
|
||||
Uplifting [main] best 110 combination
|
||||
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ print::w#3 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Test auto-casting of call-parameters
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG9 @end
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.const w = $1234
|
||||
//SEG11 [5] call print
|
||||
//SEG12 [11] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
//SEG13 [11] phi (word) print::w#3 = (word) $1234 [phi:main->print#0] -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta print.w
|
||||
lda #>$1234
|
||||
sta print.w+1
|
||||
//SEG14 [11] phi (byte) idx#12 = (byte) 0 [phi:main->print#1] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jsr print
|
||||
//SEG15 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
//SEG16 main::@1
|
||||
b1:
|
||||
//SEG17 [7] call print
|
||||
//SEG18 [11] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from_b1:
|
||||
//SEG19 [11] phi (word) print::w#3 = (const word) main::w#0 [phi:main::@1->print#0] -- vwuz1=vwuc1
|
||||
lda #<w
|
||||
sta print.w
|
||||
lda #>w
|
||||
sta print.w+1
|
||||
//SEG20 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
//SEG21 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG22 main::@2
|
||||
b2:
|
||||
//SEG23 [9] call print
|
||||
//SEG24 [11] phi from main::@2 to print [phi:main::@2->print]
|
||||
print_from_b2:
|
||||
//SEG25 [11] phi (word) print::w#3 = (byte) $12*(word) $100+(byte) $34 [phi:main::@2->print#0] -- vwuz1=vwuc1
|
||||
lda #<$12*$100+$34
|
||||
sta print.w
|
||||
lda #>$12*$100+$34
|
||||
sta print.w+1
|
||||
//SEG26 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#1] -- register_copy
|
||||
jsr print
|
||||
jmp breturn
|
||||
//SEG27 main::@return
|
||||
breturn:
|
||||
//SEG28 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG29 print
|
||||
// print(word zeropage(2) w)
|
||||
print: {
|
||||
.label w = 2
|
||||
//SEG30 [12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1 -- vbuaa=vbuxx_rol_1
|
||||
txa
|
||||
asl
|
||||
//SEG31 [13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3 -- pwuc1_derefidx_vbuaa=vwuz1
|
||||
tay
|
||||
lda w
|
||||
sta SCREEN,y
|
||||
lda w+1
|
||||
sta SCREEN+1,y
|
||||
//SEG32 [14] (byte) idx#13 ← ++ (byte) idx#12 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
jmp breturn
|
||||
//SEG33 print::@return
|
||||
breturn:
|
||||
//SEG34 [15] return
|
||||
rts
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction print_from_b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction print_from_b2:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction b2:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(word*) SCREEN
|
||||
(const word*) SCREEN#0 SCREEN = (word*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 reg byte x 2.6666666666666665
|
||||
(byte) idx#13 reg byte x 1.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(word) main::w
|
||||
(const word) main::w#0 w = (word) $1234
|
||||
(void()) print((word) print::w)
|
||||
(byte~) print::$0 reg byte a 4.0
|
||||
(label) print::@return
|
||||
(word) print::w
|
||||
(word) print::w#3 w zp ZP_WORD:2 1.0
|
||||
|
||||
reg byte x [ idx#12 idx#13 ]
|
||||
zp ZP_WORD:2 [ print::w#3 ]
|
||||
reg byte a [ print::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 86
|
||||
|
||||
//SEG0 File Comments
|
||||
// Test auto-casting of call-parameters
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
//SEG5 @1
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [4] phi from @1 to main [phi:@1->main]
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
.const w = $1234
|
||||
//SEG11 [5] call print
|
||||
//SEG12 [11] phi from main to print [phi:main->print]
|
||||
//SEG13 [11] phi (word) print::w#3 = (word) $1234 [phi:main->print#0] -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta print.w
|
||||
lda #>$1234
|
||||
sta print.w+1
|
||||
//SEG14 [11] phi (byte) idx#12 = (byte) 0 [phi:main->print#1] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jsr print
|
||||
//SEG15 [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG16 main::@1
|
||||
//SEG17 [7] call print
|
||||
//SEG18 [11] phi from main::@1 to print [phi:main::@1->print]
|
||||
//SEG19 [11] phi (word) print::w#3 = (const word) main::w#0 [phi:main::@1->print#0] -- vwuz1=vwuc1
|
||||
lda #<w
|
||||
sta print.w
|
||||
lda #>w
|
||||
sta print.w+1
|
||||
//SEG20 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#1] -- register_copy
|
||||
jsr print
|
||||
//SEG21 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
//SEG22 main::@2
|
||||
//SEG23 [9] call print
|
||||
//SEG24 [11] phi from main::@2 to print [phi:main::@2->print]
|
||||
//SEG25 [11] phi (word) print::w#3 = (byte) $12*(word) $100+(byte) $34 [phi:main::@2->print#0] -- vwuz1=vwuc1
|
||||
lda #<$12*$100+$34
|
||||
sta print.w
|
||||
lda #>$12*$100+$34
|
||||
sta print.w+1
|
||||
//SEG26 [11] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#1] -- register_copy
|
||||
jsr print
|
||||
//SEG27 main::@return
|
||||
//SEG28 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG29 print
|
||||
// print(word zeropage(2) w)
|
||||
print: {
|
||||
.label w = 2
|
||||
//SEG30 [12] (byte~) print::$0 ← (byte) idx#12 << (byte) 1 -- vbuaa=vbuxx_rol_1
|
||||
txa
|
||||
asl
|
||||
//SEG31 [13] *((const word*) SCREEN#0 + (byte~) print::$0) ← (word) print::w#3 -- pwuc1_derefidx_vbuaa=vwuz1
|
||||
tay
|
||||
lda w
|
||||
sta SCREEN,y
|
||||
lda w+1
|
||||
sta SCREEN+1,y
|
||||
//SEG32 [14] (byte) idx#13 ← ++ (byte) idx#12 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG33 print::@return
|
||||
//SEG34 [15] return
|
||||
rts
|
||||
}
|
||||
|
23
src/test/ref/call-parameter-autocast.sym
Normal file
23
src/test/ref/call-parameter-autocast.sym
Normal file
@ -0,0 +1,23 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(word*) SCREEN
|
||||
(const word*) SCREEN#0 SCREEN = (word*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 reg byte x 2.6666666666666665
|
||||
(byte) idx#13 reg byte x 1.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(word) main::w
|
||||
(const word) main::w#0 w = (word) $1234
|
||||
(void()) print((word) print::w)
|
||||
(byte~) print::$0 reg byte a 4.0
|
||||
(label) print::@return
|
||||
(word) print::w
|
||||
(word) print::w#3 w zp ZP_WORD:2 1.0
|
||||
|
||||
reg byte x [ idx#12 idx#13 ]
|
||||
zp ZP_WORD:2 [ print::w#3 ]
|
||||
reg byte a [ print::$0 ]
|
53
src/test/ref/pointer-void-1.asm
Normal file
53
src/test/ref/pointer-void-1.asm
Normal file
@ -0,0 +1,53 @@
|
||||
// Test simple void pointer - void pointer function
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.label vb = b
|
||||
.label vw = w
|
||||
.label vd = d
|
||||
.label d = 4
|
||||
.label w = 8
|
||||
.label b = $a
|
||||
lda #<$12345678
|
||||
sta d
|
||||
lda #>$12345678
|
||||
sta d+1
|
||||
lda #<$12345678>>$10
|
||||
sta d+2
|
||||
lda #>$12345678>>$10
|
||||
sta d+3
|
||||
lda #<$1234
|
||||
sta w
|
||||
lda #>$1234
|
||||
sta w+1
|
||||
lda #$12
|
||||
sta b
|
||||
ldx #0
|
||||
lda #<vb
|
||||
sta print.ptr
|
||||
lda #>vb
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
lda #<vw
|
||||
sta print.ptr
|
||||
lda #>vw
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
lda #<vd
|
||||
sta print.ptr
|
||||
lda #>vd
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
rts
|
||||
}
|
||||
// print(void* zeropage(2) ptr)
|
||||
print: {
|
||||
.label ptr = 2
|
||||
ldy #0
|
||||
lda (ptr),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
rts
|
||||
}
|
35
src/test/ref/pointer-void-1.cfg
Normal file
35
src/test/ref/pointer-void-1.cfg
Normal file
@ -0,0 +1,35 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] (dword) main::d#0 ← (dword) $12345678
|
||||
[5] (word) main::w#0 ← (word) $1234
|
||||
[6] (byte) main::b#0 ← (byte) $12
|
||||
[7] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] phi()
|
||||
[9] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[10] phi()
|
||||
[11] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[12] return
|
||||
to:@return
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
[13] (byte) idx#12 ← phi( main/(byte) 0 main::@1/(byte) idx#13 main::@2/(byte) idx#13 )
|
||||
[13] (void*) print::ptr#3 ← phi( main/(const void*) main::vb#0 main::@1/(const void*) main::vw#0 main::@2/(const void*) main::vd#0 )
|
||||
[14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3)
|
||||
[15] (byte) idx#13 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[16] return
|
||||
to:@return
|
723
src/test/ref/pointer-void-1.log
Normal file
723
src/test/ref/pointer-void-1.log
Normal file
@ -0,0 +1,723 @@
|
||||
Setting inferred volatile on symbol affected by address-of (byte*~) main::$0 ← & (byte) main::b
|
||||
Setting inferred volatile on symbol affected by address-of (word*~) main::$1 ← & (word) main::w
|
||||
Setting inferred volatile on symbol affected by address-of (dword*~) main::$2 ← & (dword) main::d
|
||||
Adding void pointer type conversion cast (void*) main::$0 in (void*) main::vb ← (byte*~) main::$0
|
||||
Adding void pointer type conversion cast (void*) main::$1 in (void*) main::vw ← (word*~) main::$1
|
||||
Adding void pointer type conversion cast (void*) main::$2 in (void*) main::vd ← (dword*~) main::$2
|
||||
Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (number) $400
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#15 ← phi( @2/(byte) idx#16 )
|
||||
(dword) main::d#0 ← (number) $12345678
|
||||
(word) main::w#0 ← (number) $1234
|
||||
(byte) main::b#0 ← (number) $12
|
||||
(byte*~) main::$0 ← & (byte) main::b#0
|
||||
(void*) main::vb#0 ← ((void*)) (byte*~) main::$0
|
||||
(word*~) main::$1 ← & (word) main::w#0
|
||||
(void*) main::vw#0 ← ((void*)) (word*~) main::$1
|
||||
(dword*~) main::$2 ← & (dword) main::d#0
|
||||
(void*) main::vd#0 ← ((void*)) (dword*~) main::$2
|
||||
(void*) print::ptr#0 ← (void*) main::vb#0
|
||||
call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(void*) main::vd#2 ← phi( main/(void*) main::vd#0 )
|
||||
(void*) main::vw#1 ← phi( main/(void*) main::vw#0 )
|
||||
(byte) idx#8 ← phi( main/(byte) idx#6 )
|
||||
(byte) idx#0 ← (byte) idx#8
|
||||
(void*) print::ptr#1 ← (void*) main::vw#1
|
||||
call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(void*) main::vd#1 ← phi( main::@1/(void*) main::vd#2 )
|
||||
(byte) idx#9 ← phi( main::@1/(byte) idx#6 )
|
||||
(byte) idx#1 ← (byte) idx#9
|
||||
(void*) print::ptr#2 ← (void*) main::vd#1
|
||||
call print
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
(byte) idx#10 ← phi( main::@2/(byte) idx#6 )
|
||||
(byte) idx#2 ← (byte) idx#10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
(byte) idx#11 ← phi( main::@3/(byte) idx#2 )
|
||||
(byte) idx#3 ← (byte) idx#11
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
(byte) idx#4 ← (number) 0
|
||||
to:@2
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
(byte) idx#12 ← phi( main/(byte) idx#15 main::@1/(byte) idx#0 main::@2/(byte) idx#1 )
|
||||
(void*) print::ptr#3 ← phi( main/(void*) print::ptr#0 main::@1/(void*) print::ptr#1 main::@2/(void*) print::ptr#2 )
|
||||
(byte*~) print::$0 ← ((byte*)) (void*) print::ptr#3
|
||||
*((byte*) SCREEN#0 + (byte) idx#12) ← *((byte*~) print::$0)
|
||||
(byte) idx#5 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
(byte) idx#13 ← phi( print/(byte) idx#5 )
|
||||
(byte) idx#6 ← (byte) idx#13
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#16 ← phi( @1/(byte) idx#4 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#14 ← phi( @2/(byte) idx#3 )
|
||||
(byte) idx#7 ← (byte) idx#14
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#10
|
||||
(byte) idx#11
|
||||
(byte) idx#12
|
||||
(byte) idx#13
|
||||
(byte) idx#14
|
||||
(byte) idx#15
|
||||
(byte) idx#16
|
||||
(byte) idx#2
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(void()) main()
|
||||
(byte*~) main::$0
|
||||
(word*~) main::$1
|
||||
(dword*~) main::$2
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(byte) main::b
|
||||
(byte) main::b#0
|
||||
(dword) main::d
|
||||
(dword) main::d#0
|
||||
(void*) main::vb
|
||||
(void*) main::vb#0
|
||||
(void*) main::vd
|
||||
(void*) main::vd#0
|
||||
(void*) main::vd#1
|
||||
(void*) main::vd#2
|
||||
(void*) main::vw
|
||||
(void*) main::vw#0
|
||||
(void*) main::vw#1
|
||||
(word) main::w
|
||||
(word) main::w#0
|
||||
(void()) print((void*) print::ptr)
|
||||
(byte*~) print::$0
|
||||
(label) print::@return
|
||||
(void*) print::ptr
|
||||
(void*) print::ptr#0
|
||||
(void*) print::ptr#1
|
||||
(void*) print::ptr#2
|
||||
(void*) print::ptr#3
|
||||
|
||||
Adding number conversion cast (unumber) $12345678 in (dword) main::d#0 ← (number) $12345678
|
||||
Adding number conversion cast (unumber) $1234 in (word) main::w#0 ← (number) $1234
|
||||
Adding number conversion cast (unumber) $12 in (byte) main::b#0 ← (number) $12
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#4 ← (number) 0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (dword) main::d#0 ← (unumber)(number) $12345678
|
||||
Inlining cast (word) main::w#0 ← (unumber)(number) $1234
|
||||
Inlining cast (byte) main::b#0 ← (unumber)(number) $12
|
||||
Inlining cast (void*) main::vb#0 ← (void*)(byte*~) main::$0
|
||||
Inlining cast (void*) main::vw#0 ← (void*)(word*~) main::$1
|
||||
Inlining cast (void*) main::vd#0 ← (void*)(dword*~) main::$2
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#4 ← (unumber)(number) 0
|
||||
Inlining cast (byte*~) print::$0 ← (byte*)(void*) print::ptr#3
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast $12345678
|
||||
Simplifying constant integer cast $1234
|
||||
Simplifying constant integer cast $12
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (dword) $12345678
|
||||
Finalized unsigned number type (word) $1234
|
||||
Finalized unsigned number type (byte) $12
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (void*) main::vw#0 = (void*) main::vw#1
|
||||
Alias (void*) main::vd#0 = (void*) main::vd#2 (void*) main::vd#1
|
||||
Alias (byte) idx#0 = (byte) idx#8
|
||||
Alias (byte) idx#1 = (byte) idx#9
|
||||
Alias (byte) idx#10 = (byte) idx#2 (byte) idx#11 (byte) idx#3
|
||||
Alias (byte) idx#13 = (byte) idx#5 (byte) idx#6
|
||||
Alias (byte) idx#16 = (byte) idx#4
|
||||
Alias (byte) idx#14 = (byte) idx#7
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#15 (byte) idx#16
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#1 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#10 (byte) idx#13
|
||||
Identical Phi Values (byte) idx#14 (byte) idx#10
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Constant right-side identified [4] (byte*~) main::$0 ← & (byte) main::b#0
|
||||
Constant right-side identified [6] (word*~) main::$1 ← & (word) main::w#0
|
||||
Constant right-side identified [8] (dword*~) main::$2 ← & (dword) main::d#0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$0 = &main::b#0
|
||||
Constant (const word*) main::$1 = &main::w#0
|
||||
Constant (const dword*) main::$2 = &main::d#0
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Constant (const byte) idx#16 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (void*)main::$0 in [5] (void*) main::vb#0 ← (void*)(const byte*) main::$0
|
||||
Constant value identified (void*)main::$1 in [7] (void*) main::vw#0 ← (void*)(const word*) main::$1
|
||||
Constant value identified (void*)main::$2 in [9] (void*) main::vd#0 ← (void*)(const dword*) main::$2
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Constant (const void*) main::vb#0 = (void*)main::$0
|
||||
Constant (const void*) main::vw#0 = (void*)main::$1
|
||||
Constant (const void*) main::vd#0 = (void*)main::$2
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const void*) print::ptr#0 = main::vb#0
|
||||
Constant (const void*) print::ptr#1 = main::vw#0
|
||||
Constant (const void*) print::ptr#2 = main::vd#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining Noop Cast [8] (byte*~) print::$0 ← (byte*)(void*) print::ptr#3 keeping print::ptr#3
|
||||
Successful SSA optimization Pass2NopCastInlining
|
||||
Inlining constant with var siblings (const void*) print::ptr#0
|
||||
Inlining constant with var siblings (const void*) print::ptr#1
|
||||
Inlining constant with var siblings (const void*) print::ptr#2
|
||||
Inlining constant with var siblings (const byte) idx#16
|
||||
Constant inlined print::ptr#2 = (const void*) main::vd#0
|
||||
Constant inlined main::$1 = &(word) main::w#0
|
||||
Constant inlined main::$2 = &(dword) main::d#0
|
||||
Constant inlined main::$0 = &(byte) main::b#0
|
||||
Constant inlined print::ptr#0 = (const void*) main::vb#0
|
||||
Constant inlined print::ptr#1 = (const void*) main::vw#0
|
||||
Constant inlined idx#16 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main::@3
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print:9 print:11 print:13
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [10] idx#17 ← idx#13
|
||||
Coalesced (already) [12] idx#18 ← idx#13
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@3
|
||||
Renumbering block @2 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main::@1
|
||||
Adding NOP phi() at start of main::@2
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] (dword) main::d#0 ← (dword) $12345678
|
||||
[5] (word) main::w#0 ← (word) $1234
|
||||
[6] (byte) main::b#0 ← (byte) $12
|
||||
[7] call print
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] phi()
|
||||
[9] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[10] phi()
|
||||
[11] call print
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[12] return
|
||||
to:@return
|
||||
print: scope:[print] from main main::@1 main::@2
|
||||
[13] (byte) idx#12 ← phi( main/(byte) 0 main::@1/(byte) idx#13 main::@2/(byte) idx#13 )
|
||||
[13] (void*) print::ptr#3 ← phi( main/(const void*) main::vb#0 main::@1/(const void*) main::vw#0 main::@2/(const void*) main::vd#0 )
|
||||
[14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3)
|
||||
[15] (byte) idx#13 ← ++ (byte) idx#12
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#12 4.0
|
||||
(byte) idx#13 1.0
|
||||
(void()) main()
|
||||
(byte) main::b
|
||||
(byte) main::b#0 20.0
|
||||
(dword) main::d
|
||||
(dword) main::d#0 20.0
|
||||
(void*) main::vb
|
||||
(void*) main::vd
|
||||
(void*) main::vw
|
||||
(word) main::w
|
||||
(word) main::w#0 20.0
|
||||
(void()) print((void*) print::ptr)
|
||||
(void*) print::ptr
|
||||
(void*) print::ptr#3
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print::ptr#3 ]
|
||||
[ idx#12 idx#13 ]
|
||||
Complete equivalence classes
|
||||
[ print::ptr#3 ]
|
||||
[ idx#12 idx#13 ]
|
||||
[ main::d#0 ]
|
||||
[ main::w#0 ]
|
||||
[ main::b#0 ]
|
||||
Allocated zp ZP_WORD:2 [ print::ptr#3 ]
|
||||
Allocated zp ZP_BYTE:4 [ idx#12 idx#13 ]
|
||||
Allocated zp ZP_DWORD:5 [ main::d#0 ]
|
||||
Allocated zp ZP_WORD:9 [ main::w#0 ]
|
||||
Allocated zp ZP_BYTE:11 [ main::b#0 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Test simple void pointer - void pointer function
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 4
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label vb = b
|
||||
.label vw = w
|
||||
.label vd = d
|
||||
.label d = 5
|
||||
.label w = 9
|
||||
.label b = $b
|
||||
//SEG10 [4] (dword) main::d#0 ← (dword) $12345678 -- vduz1=vduc1
|
||||
lda #<$12345678
|
||||
sta d
|
||||
lda #>$12345678
|
||||
sta d+1
|
||||
lda #<$12345678>>$10
|
||||
sta d+2
|
||||
lda #>$12345678>>$10
|
||||
sta d+3
|
||||
//SEG11 [5] (word) main::w#0 ← (word) $1234 -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta w
|
||||
lda #>$1234
|
||||
sta w+1
|
||||
//SEG12 [6] (byte) main::b#0 ← (byte) $12 -- vbuz1=vbuc1
|
||||
lda #$12
|
||||
sta b
|
||||
//SEG13 [7] call print
|
||||
//SEG14 [13] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
//SEG15 [13] phi (byte) idx#12 = (byte) 0 [phi:main->print#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG16 [13] phi (void*) print::ptr#3 = (const void*) main::vb#0 [phi:main->print#1] -- pvoz1=pvoc1
|
||||
lda #<vb
|
||||
sta print.ptr
|
||||
lda #>vb
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG17 [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
//SEG18 main::@1
|
||||
b1:
|
||||
//SEG19 [9] call print
|
||||
//SEG20 [13] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from_b1:
|
||||
//SEG21 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#0] -- register_copy
|
||||
//SEG22 [13] phi (void*) print::ptr#3 = (const void*) main::vw#0 [phi:main::@1->print#1] -- pvoz1=pvoc1
|
||||
lda #<vw
|
||||
sta print.ptr
|
||||
lda #>vw
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG23 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG24 main::@2
|
||||
b2:
|
||||
//SEG25 [11] call print
|
||||
//SEG26 [13] phi from main::@2 to print [phi:main::@2->print]
|
||||
print_from_b2:
|
||||
//SEG27 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#0] -- register_copy
|
||||
//SEG28 [13] phi (void*) print::ptr#3 = (const void*) main::vd#0 [phi:main::@2->print#1] -- pvoz1=pvoc1
|
||||
lda #<vd
|
||||
sta print.ptr
|
||||
lda #>vd
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
jmp breturn
|
||||
//SEG29 main::@return
|
||||
breturn:
|
||||
//SEG30 [12] return
|
||||
rts
|
||||
}
|
||||
//SEG31 print
|
||||
// print(void* zeropage(2) ptr)
|
||||
print: {
|
||||
.label ptr = 2
|
||||
//SEG32 [14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3) -- pbuc1_derefidx_vbuz1=_deref_pbuz2
|
||||
ldx idx
|
||||
ldy #0
|
||||
lda (ptr),y
|
||||
sta SCREEN,x
|
||||
//SEG33 [15] (byte) idx#13 ← ++ (byte) idx#12 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
jmp breturn
|
||||
//SEG34 print::@return
|
||||
breturn:
|
||||
//SEG35 [16] return
|
||||
rts
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] (dword) main::d#0 ← (dword) $12345678 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] (word) main::w#0 ← (word) $1234 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] (byte) main::b#0 ← (byte) $12 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3) [ idx#12 ] ( main:2::print:7 [ idx#12 ] main:2::print:9 [ idx#12 ] main:2::print:11 [ idx#12 ] ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#12 idx#13 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:4 [ idx#12 idx#13 ]
|
||||
Statement [4] (dword) main::d#0 ← (dword) $12345678 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [5] (word) main::w#0 ← (word) $1234 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] (byte) main::b#0 ← (byte) $12 [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3) [ idx#12 ] ( main:2::print:7 [ idx#12 ] main:2::print:9 [ idx#12 ] main:2::print:11 [ idx#12 ] ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp ZP_WORD:2 [ print::ptr#3 ] : zp ZP_WORD:2 ,
|
||||
Potential registers zp ZP_BYTE:4 [ idx#12 idx#13 ] : zp ZP_BYTE:4 , reg byte x ,
|
||||
Potential registers zp ZP_DWORD:5 [ main::d#0 ] : zp ZP_DWORD:5 ,
|
||||
Potential registers zp ZP_WORD:9 [ main::w#0 ] : zp ZP_WORD:9 ,
|
||||
Potential registers zp ZP_BYTE:11 [ main::b#0 ] : zp ZP_BYTE:11 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 20: zp ZP_DWORD:5 [ main::d#0 ] 20: zp ZP_WORD:9 [ main::w#0 ] 20: zp ZP_BYTE:11 [ main::b#0 ]
|
||||
Uplift Scope [] 5: zp ZP_BYTE:4 [ idx#12 idx#13 ]
|
||||
Uplift Scope [print] 0: zp ZP_WORD:2 [ print::ptr#3 ]
|
||||
|
||||
Uplifting [main] best 144 combination zp ZP_DWORD:5 [ main::d#0 ] zp ZP_WORD:9 [ main::w#0 ] zp ZP_BYTE:11 [ main::b#0 ]
|
||||
Uplifting [] best 135 combination reg byte x [ idx#12 idx#13 ]
|
||||
Uplifting [print] best 135 combination zp ZP_WORD:2 [ print::ptr#3 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:11 [ main::b#0 ]
|
||||
Uplifting [main] best 135 combination zp ZP_BYTE:11 [ main::b#0 ]
|
||||
Allocated (was zp ZP_DWORD:5) zp ZP_DWORD:4 [ main::d#0 ]
|
||||
Allocated (was zp ZP_WORD:9) zp ZP_WORD:8 [ main::w#0 ]
|
||||
Allocated (was zp ZP_BYTE:11) zp ZP_BYTE:10 [ main::b#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Test simple void pointer - void pointer function
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
//SEG5 @1
|
||||
b1:
|
||||
//SEG6 [2] call main
|
||||
jsr main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
//SEG8 @end
|
||||
bend:
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label vb = b
|
||||
.label vw = w
|
||||
.label vd = d
|
||||
.label d = 4
|
||||
.label w = 8
|
||||
.label b = $a
|
||||
//SEG10 [4] (dword) main::d#0 ← (dword) $12345678 -- vduz1=vduc1
|
||||
lda #<$12345678
|
||||
sta d
|
||||
lda #>$12345678
|
||||
sta d+1
|
||||
lda #<$12345678>>$10
|
||||
sta d+2
|
||||
lda #>$12345678>>$10
|
||||
sta d+3
|
||||
//SEG11 [5] (word) main::w#0 ← (word) $1234 -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta w
|
||||
lda #>$1234
|
||||
sta w+1
|
||||
//SEG12 [6] (byte) main::b#0 ← (byte) $12 -- vbuz1=vbuc1
|
||||
lda #$12
|
||||
sta b
|
||||
//SEG13 [7] call print
|
||||
//SEG14 [13] phi from main to print [phi:main->print]
|
||||
print_from_main:
|
||||
//SEG15 [13] phi (byte) idx#12 = (byte) 0 [phi:main->print#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG16 [13] phi (void*) print::ptr#3 = (const void*) main::vb#0 [phi:main->print#1] -- pvoz1=pvoc1
|
||||
lda #<vb
|
||||
sta print.ptr
|
||||
lda #>vb
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG17 [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
//SEG18 main::@1
|
||||
b1:
|
||||
//SEG19 [9] call print
|
||||
//SEG20 [13] phi from main::@1 to print [phi:main::@1->print]
|
||||
print_from_b1:
|
||||
//SEG21 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#0] -- register_copy
|
||||
//SEG22 [13] phi (void*) print::ptr#3 = (const void*) main::vw#0 [phi:main::@1->print#1] -- pvoz1=pvoc1
|
||||
lda #<vw
|
||||
sta print.ptr
|
||||
lda #>vw
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG23 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG24 main::@2
|
||||
b2:
|
||||
//SEG25 [11] call print
|
||||
//SEG26 [13] phi from main::@2 to print [phi:main::@2->print]
|
||||
print_from_b2:
|
||||
//SEG27 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#0] -- register_copy
|
||||
//SEG28 [13] phi (void*) print::ptr#3 = (const void*) main::vd#0 [phi:main::@2->print#1] -- pvoz1=pvoc1
|
||||
lda #<vd
|
||||
sta print.ptr
|
||||
lda #>vd
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
jmp breturn
|
||||
//SEG29 main::@return
|
||||
breturn:
|
||||
//SEG30 [12] return
|
||||
rts
|
||||
}
|
||||
//SEG31 print
|
||||
// print(void* zeropage(2) ptr)
|
||||
print: {
|
||||
.label ptr = 2
|
||||
//SEG32 [14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3) -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (ptr),y
|
||||
sta SCREEN,x
|
||||
//SEG33 [15] (byte) idx#13 ← ++ (byte) idx#12 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
jmp breturn
|
||||
//SEG34 print::@return
|
||||
breturn:
|
||||
//SEG35 [16] return
|
||||
rts
|
||||
}
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction print_from_b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction print_from_b2:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction b2:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 reg byte x 4.0
|
||||
(byte) idx#13 reg byte x 1.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::b
|
||||
(byte) main::b#0 b zp ZP_BYTE:10 20.0
|
||||
(dword) main::d
|
||||
(dword) main::d#0 d zp ZP_DWORD:4 20.0
|
||||
(void*) main::vb
|
||||
(const void*) main::vb#0 vb = (void*)&(byte) main::b#0
|
||||
(void*) main::vd
|
||||
(const void*) main::vd#0 vd = (void*)&(dword) main::d#0
|
||||
(void*) main::vw
|
||||
(const void*) main::vw#0 vw = (void*)&(word) main::w#0
|
||||
(word) main::w
|
||||
(word) main::w#0 w zp ZP_WORD:8 20.0
|
||||
(void()) print((void*) print::ptr)
|
||||
(label) print::@return
|
||||
(void*) print::ptr
|
||||
(void*) print::ptr#3 ptr zp ZP_WORD:2
|
||||
|
||||
zp ZP_WORD:2 [ print::ptr#3 ]
|
||||
reg byte x [ idx#12 idx#13 ]
|
||||
zp ZP_DWORD:4 [ main::d#0 ]
|
||||
zp ZP_WORD:8 [ main::w#0 ]
|
||||
zp ZP_BYTE:10 [ main::b#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 111
|
||||
|
||||
//SEG0 File Comments
|
||||
// Test simple void pointer - void pointer function
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
//SEG3 @begin
|
||||
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
//SEG5 @1
|
||||
//SEG6 [2] call main
|
||||
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG8 @end
|
||||
//SEG9 main
|
||||
main: {
|
||||
.label vb = b
|
||||
.label vw = w
|
||||
.label vd = d
|
||||
.label d = 4
|
||||
.label w = 8
|
||||
.label b = $a
|
||||
//SEG10 [4] (dword) main::d#0 ← (dword) $12345678 -- vduz1=vduc1
|
||||
lda #<$12345678
|
||||
sta d
|
||||
lda #>$12345678
|
||||
sta d+1
|
||||
lda #<$12345678>>$10
|
||||
sta d+2
|
||||
lda #>$12345678>>$10
|
||||
sta d+3
|
||||
//SEG11 [5] (word) main::w#0 ← (word) $1234 -- vwuz1=vwuc1
|
||||
lda #<$1234
|
||||
sta w
|
||||
lda #>$1234
|
||||
sta w+1
|
||||
//SEG12 [6] (byte) main::b#0 ← (byte) $12 -- vbuz1=vbuc1
|
||||
lda #$12
|
||||
sta b
|
||||
//SEG13 [7] call print
|
||||
//SEG14 [13] phi from main to print [phi:main->print]
|
||||
//SEG15 [13] phi (byte) idx#12 = (byte) 0 [phi:main->print#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG16 [13] phi (void*) print::ptr#3 = (const void*) main::vb#0 [phi:main->print#1] -- pvoz1=pvoc1
|
||||
lda #<vb
|
||||
sta print.ptr
|
||||
lda #>vb
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG17 [8] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG18 main::@1
|
||||
//SEG19 [9] call print
|
||||
//SEG20 [13] phi from main::@1 to print [phi:main::@1->print]
|
||||
//SEG21 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@1->print#0] -- register_copy
|
||||
//SEG22 [13] phi (void*) print::ptr#3 = (const void*) main::vw#0 [phi:main::@1->print#1] -- pvoz1=pvoc1
|
||||
lda #<vw
|
||||
sta print.ptr
|
||||
lda #>vw
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG23 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
//SEG24 main::@2
|
||||
//SEG25 [11] call print
|
||||
//SEG26 [13] phi from main::@2 to print [phi:main::@2->print]
|
||||
//SEG27 [13] phi (byte) idx#12 = (byte) idx#13 [phi:main::@2->print#0] -- register_copy
|
||||
//SEG28 [13] phi (void*) print::ptr#3 = (const void*) main::vd#0 [phi:main::@2->print#1] -- pvoz1=pvoc1
|
||||
lda #<vd
|
||||
sta print.ptr
|
||||
lda #>vd
|
||||
sta print.ptr+1
|
||||
jsr print
|
||||
//SEG29 main::@return
|
||||
//SEG30 [12] return
|
||||
rts
|
||||
}
|
||||
//SEG31 print
|
||||
// print(void* zeropage(2) ptr)
|
||||
print: {
|
||||
.label ptr = 2
|
||||
//SEG32 [14] *((const byte*) SCREEN#0 + (byte) idx#12) ← *((byte*)(void*) print::ptr#3) -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (ptr),y
|
||||
sta SCREEN,x
|
||||
//SEG33 [15] (byte) idx#13 ← ++ (byte) idx#12 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG34 print::@return
|
||||
//SEG35 [16] return
|
||||
rts
|
||||
}
|
||||
|
34
src/test/ref/pointer-void-1.sym
Normal file
34
src/test/ref/pointer-void-1.sym
Normal file
@ -0,0 +1,34 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 reg byte x 4.0
|
||||
(byte) idx#13 reg byte x 1.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::b
|
||||
(byte) main::b#0 b zp ZP_BYTE:10 20.0
|
||||
(dword) main::d
|
||||
(dword) main::d#0 d zp ZP_DWORD:4 20.0
|
||||
(void*) main::vb
|
||||
(const void*) main::vb#0 vb = (void*)&(byte) main::b#0
|
||||
(void*) main::vd
|
||||
(const void*) main::vd#0 vd = (void*)&(dword) main::d#0
|
||||
(void*) main::vw
|
||||
(const void*) main::vw#0 vw = (void*)&(word) main::w#0
|
||||
(word) main::w
|
||||
(word) main::w#0 w zp ZP_WORD:8 20.0
|
||||
(void()) print((void*) print::ptr)
|
||||
(label) print::@return
|
||||
(void*) print::ptr
|
||||
(void*) print::ptr#3 ptr zp ZP_WORD:2
|
||||
|
||||
zp ZP_WORD:2 [ print::ptr#3 ]
|
||||
reg byte x [ idx#12 idx#13 ]
|
||||
zp ZP_DWORD:4 [ main::d#0 ]
|
||||
zp ZP_WORD:8 [ main::w#0 ]
|
||||
zp ZP_BYTE:10 [ main::b#0 ]
|
Loading…
x
Reference in New Issue
Block a user