mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-07 20:31:32 +00:00
Added missing struct-ptr fragments. Added padding to initialization of fixed size arrays with to few elements in the initializer. Closes #311
This commit is contained in:
parent
d6ad2c3b9b
commit
5fe5c9f84b
@ -0,0 +1,8 @@
|
||||
stx $fd
|
||||
lda ({z1}),y
|
||||
sta $fe
|
||||
iny
|
||||
lda ({z1}),y
|
||||
sta $ff
|
||||
ldy $fd
|
||||
lda ($fe),y
|
@ -0,0 +1,7 @@
|
||||
lda ({z1}),y
|
||||
sta $fe
|
||||
iny
|
||||
lda ({z1}),y
|
||||
sta $ff
|
||||
ldy {z2}
|
||||
lda ($fe),y
|
@ -0,0 +1,10 @@
|
||||
stx $fd
|
||||
lda ({z1}),y
|
||||
sta $fe
|
||||
iny
|
||||
lda ({z1}),y
|
||||
sta $ff
|
||||
ldy $fd
|
||||
lda ($fe),y
|
||||
cmp #{c1}
|
||||
bne {la1}
|
@ -0,0 +1,9 @@
|
||||
lda ({z1}),y
|
||||
sta $fe
|
||||
iny
|
||||
lda ({z1}),y
|
||||
sta $ff
|
||||
ldy {z2}
|
||||
lda ($fe),y
|
||||
cmp #{c1}
|
||||
bne {la1}
|
@ -36,7 +36,9 @@ public class AsmDataFill implements AsmLine {
|
||||
@Override
|
||||
public String getAsm() {
|
||||
StringBuilder asm = new StringBuilder();
|
||||
asm.append(label + ": ");
|
||||
if(label!=null) {
|
||||
asm.append(label + ": ");
|
||||
}
|
||||
asm.append(".fill ");
|
||||
asm.append(sizeAsm);
|
||||
asm.append(", ");
|
||||
|
@ -0,0 +1,37 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* Factory usable for creating the default "zero" values for all types.
|
||||
*/
|
||||
public class ZeroConstantValues {
|
||||
|
||||
public static ConstantValue zeroValue(SymbolType type, ProgramScope programScope) {
|
||||
if(type instanceof SymbolTypeStruct) {
|
||||
SymbolTypeStruct typeStruct = (SymbolTypeStruct) type;
|
||||
LinkedHashMap<VariableRef, ConstantValue> zeroValues = new LinkedHashMap<>();
|
||||
StructDefinition structDefinition = typeStruct.getStructDefinition(programScope);
|
||||
for(Variable memberVar : structDefinition.getAllVariables(false)) {
|
||||
zeroValues.put(memberVar.getRef(), zeroValue(memberVar.getType(), programScope));
|
||||
}
|
||||
return new ConstantStructValue(typeStruct, zeroValues);
|
||||
} else if(type instanceof SymbolTypeIntegerFixed) {
|
||||
return new ConstantInteger(0L, type);
|
||||
} else if(type instanceof SymbolTypePointer) {
|
||||
return new ConstantPointer(0L, ((SymbolTypePointer) type).getElementType());
|
||||
} else {
|
||||
throw new InternalError("Unhandled type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -50,7 +50,7 @@ public class Pass3AssertArrayLengths extends Pass2SsaAssertion {
|
||||
}
|
||||
} else if(constantValue instanceof ConstantArrayList) {
|
||||
Integer assignedSizeVal = ((ConstantArrayList) constantValue).getElements().size();
|
||||
if(!assignedSizeVal.equals(declaredSizeInt)) {
|
||||
if(assignedSizeVal > declaredSizeInt) {
|
||||
throw new CompileError("Error! Array length mismatch " + constantVar.toString(getProgram()));
|
||||
}
|
||||
} else if(constantValue instanceof ConstantArrayKickAsm) {
|
||||
@ -59,7 +59,7 @@ public class Pass3AssertArrayLengths extends Pass2SsaAssertion {
|
||||
ConstantLiteral constantLiteral = constantValue.calculateLiteral(getScope());
|
||||
if(constantLiteral instanceof ConstantString) {
|
||||
Integer assignedSizeVal = ((ConstantString) constantLiteral).getString().length();
|
||||
if(!assignedSizeVal.equals(declaredSizeInt)) {
|
||||
if(assignedSizeVal > declaredSizeInt) {
|
||||
throw new CompileError("Error! Array length mismatch " + constantVar.toString(getProgram()));
|
||||
}
|
||||
} else if(constantLiteral instanceof ConstantPointer) {
|
||||
|
@ -467,6 +467,18 @@ public class Pass4CodeGeneration {
|
||||
addChunkData(asmDataChunk, element, scopeRef);
|
||||
asm.addDataNumeric(null, asmDataChunk);
|
||||
}
|
||||
// Pad output to match declared size (if larger than the data list)
|
||||
int dataSize = constantArrayList.getElements().size();
|
||||
Integer declaredSize = getArrayDeclaredSize(constantVar);
|
||||
if(declaredSize!=null && declaredSize>dataSize) {
|
||||
int padding = declaredSize - dataSize;
|
||||
ConstantStructValue zeroStructValue = (ConstantStructValue) ZeroConstantValues.zeroValue(elementType, program.getScope());
|
||||
for(int i=0; i<padding; i++) {
|
||||
AsmProgram.AsmDataNumericChunk asmDataChunk = new AsmProgram.AsmDataNumericChunk();
|
||||
addChunkData(asmDataChunk, zeroStructValue, scopeRef);
|
||||
asm.addDataNumeric(null, asmDataChunk);
|
||||
}
|
||||
}
|
||||
} else if(elementType instanceof SymbolTypeArray) {
|
||||
// Constant array of sub-arrays
|
||||
throw new InternalError("Array of array not supported");
|
||||
@ -478,6 +490,31 @@ public class Pass4CodeGeneration {
|
||||
addChunkData(asmDataChunk, element, scopeRef);
|
||||
}
|
||||
asm.addDataNumeric(asmName, asmDataChunk);
|
||||
// Pad output to match declared size (if larger than the data list)
|
||||
int dataSize = constantArrayList.getElements().size();
|
||||
Integer declaredSize = getArrayDeclaredSize(constantVar);
|
||||
if(declaredSize!=null && declaredSize>dataSize) {
|
||||
int padding = declaredSize-dataSize;
|
||||
AsmDataNumeric.Type dataType;
|
||||
if(SymbolType.BYTE.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.BYTE;
|
||||
} else if(SymbolType.SBYTE.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.BYTE;
|
||||
} else if(SymbolType.WORD.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.WORD;
|
||||
} else if(SymbolType.SWORD.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.WORD;
|
||||
} else if(SymbolType.DWORD.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.DWORD;
|
||||
} else if(SymbolType.SDWORD.equals(elementType)) {
|
||||
dataType = AsmDataNumeric.Type.DWORD;
|
||||
} else if(elementType instanceof SymbolTypePointer) {
|
||||
dataType = AsmDataNumeric.Type.WORD;
|
||||
} else {
|
||||
throw new InternalError("Unhandled constant array element type " + constantArrayList.toString(program));
|
||||
}
|
||||
asm.addDataFilled(null, dataType, Integer.toString(padding), padding, "0");
|
||||
}
|
||||
}
|
||||
} else if(constantValue instanceof ConstantArrayFilled) {
|
||||
ConstantArrayFilled constantArrayFilled = (ConstantArrayFilled) constantValue;
|
||||
@ -549,8 +586,16 @@ public class Pass4CodeGeneration {
|
||||
ensureEncoding(asm, constantValue);
|
||||
String asmConstant = AsmFormat.getAsmConstant(program, constantValue, 99, scopeRef);
|
||||
asm.addDataString(AsmFormat.asmFix(asmName), asmConstant);
|
||||
int dataSize = ((ConstantString) literal).getString().length();
|
||||
if(((ConstantString) literal).isZeroTerminated()) {
|
||||
asm.addDataNumeric(null, AsmDataNumeric.Type.BYTE, Collections.singletonList(AsmFormat.getAsmNumber(0L)));
|
||||
dataSize++;
|
||||
}
|
||||
// Pad output to match declared size (if larger than the data list)
|
||||
Integer declaredSize = getArrayDeclaredSize(constantVar);
|
||||
if(declaredSize!=null && declaredSize>dataSize) {
|
||||
int padding = declaredSize-dataSize;
|
||||
asm.addDataFilled(null, AsmDataNumeric.Type.BYTE, Integer.toString(padding), padding, "0");
|
||||
}
|
||||
added.add(asmName);
|
||||
}
|
||||
@ -562,6 +607,29 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the declared size of an array variable.
|
||||
* @param constantVar The array variable
|
||||
* @return The declared size. Null if the type is not array or no size is declared.
|
||||
*/
|
||||
private Integer getArrayDeclaredSize(ConstantVar constantVar) {
|
||||
SymbolType constantType = constantVar.getType();
|
||||
if(constantType instanceof SymbolTypeArray) {
|
||||
RValue declaredSize = ((SymbolTypeArray) constantType).getSize();
|
||||
if(declaredSize != null) {
|
||||
if(!(declaredSize instanceof ConstantValue)) {
|
||||
throw new CompileError("Error! Array declared size is not constant " + constantType.toString());
|
||||
}
|
||||
ConstantLiteral declaredSizeVal = ((ConstantValue) declaredSize).calculateLiteral(getScope());
|
||||
if(!(declaredSizeVal instanceof ConstantInteger)) {
|
||||
throw new CompileError("Error! Array declared size is not integer " + constantType.toString());
|
||||
}
|
||||
return ((ConstantInteger) declaredSizeVal).getInteger().intValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fill the data of a constant value into a data chunk
|
||||
|
@ -35,10 +35,10 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOs51() throws IOException, URISyntaxException {
|
||||
compileAndCompare("complex/unit5/os5.1", log().verboseSSAOptimize());
|
||||
}
|
||||
//@Test
|
||||
//public void testOs51() throws IOException, URISyntaxException {
|
||||
// compileAndCompare("complex/unit5/os5.1", log().verboseSSAOptimize());
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testCpu6502() throws IOException, URISyntaxException {
|
||||
@ -649,6 +649,26 @@ public class TestPrograms {
|
||||
}
|
||||
*/
|
||||
|
||||
//@Test
|
||||
//public void testStructPtr31() throws IOException, URISyntaxException {
|
||||
// compileAndCompare("struct-ptr-31");
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testStructPtr30() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-30");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPtr29() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-29");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPtr28() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-28");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPtr26() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-26");
|
||||
@ -821,6 +841,11 @@ public class TestPrograms {
|
||||
assertError("struct-err-0", "Unknown struct type");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct12() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-12");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct11() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-11");
|
||||
@ -2578,6 +2603,11 @@ public class TestPrograms {
|
||||
compileAndCompare("test-multiply-16bit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArraysInitShort() throws IOException, URISyntaxException {
|
||||
compileAndCompare("arrays-init-short");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArraysInit() throws IOException, URISyntaxException {
|
||||
compileAndCompare("arrays-init");
|
||||
@ -3187,6 +3217,7 @@ public class TestPrograms {
|
||||
private void testFile(String fileName, Integer upliftCombinations, CompileLog compileLog) throws IOException, URISyntaxException {
|
||||
System.out.println("Testing output for " + fileName);
|
||||
Compiler compiler = new Compiler();
|
||||
//compiler.setWarnFragmentMissing(true);
|
||||
compiler.setAsmFragmentBaseFolder(new File("src/main/fragment/").toPath());
|
||||
compiler.setAsmFragmentCacheFolder(null);
|
||||
if(compileLog != null) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
byte[3] b = { 1, 2 };
|
||||
byte[3] b = { 1, 2, 3, 4, 5 };
|
||||
|
||||
void main() {
|
||||
byte* SCREEN = $400;
|
||||
|
13
src/test/kc/arrays-init-short.kc
Normal file
13
src/test/kc/arrays-init-short.kc
Normal file
@ -0,0 +1,13 @@
|
||||
// Test a short array initializer - the rest should be zero-filled
|
||||
|
||||
char[16] msg1 ="camelot";
|
||||
char[16] msg2 = { 'c', 'm', 'l' };
|
||||
|
||||
const char* SCREEN = 0x400;
|
||||
|
||||
void main() {
|
||||
for(char i=0;msg1[i];i++)
|
||||
SCREEN[i] = msg1[i];
|
||||
for(char i=0;msg2[i];i++)
|
||||
(SCREEN+40)[i] = msg2[i];
|
||||
}
|
34
src/test/kc/struct-12.kc
Normal file
34
src/test/kc/struct-12.kc
Normal file
@ -0,0 +1,34 @@
|
||||
// Example of a struct containing an array
|
||||
// Works because the struct is only handled as a value
|
||||
|
||||
struct Person {
|
||||
char id;
|
||||
char[64] name;
|
||||
};
|
||||
|
||||
void main() {
|
||||
struct Person jesper;
|
||||
jesper.id = 4;
|
||||
jesper.name = "jesper";
|
||||
print_person(jesper);
|
||||
|
||||
struct Person henriette;
|
||||
henriette.id = 7;
|
||||
henriette.name = "repsej";
|
||||
print_person(henriette);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
char[] DIGIT = "0123456789";
|
||||
|
||||
void print_person(struct Person person) {
|
||||
SCREEN[idx++] = DIGIT[person.id];
|
||||
SCREEN[idx++] = ' ';
|
||||
for(byte i=0; person.name[i]; i++)
|
||||
SCREEN[idx++] = person.name[i];
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
|
||||
|
||||
|
31
src/test/kc/struct-ptr-28.kc
Normal file
31
src/test/kc/struct-ptr-28.kc
Normal file
@ -0,0 +1,31 @@
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
|
||||
struct Person {
|
||||
char id;
|
||||
char[16] name;
|
||||
};
|
||||
|
||||
void main() {
|
||||
struct Person jesper = { 4, "jesper" };
|
||||
print_person(&jesper);
|
||||
|
||||
struct Person henriette = { 7, "henriette" };
|
||||
print_person(&henriette);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
char[] DIGIT = "0123456789";
|
||||
|
||||
void print_person(struct Person *person) {
|
||||
SCREEN[idx++] = DIGIT[person->id];
|
||||
SCREEN[idx++] = ' ';
|
||||
for(byte i=0; person->name[i]; i++)
|
||||
SCREEN[idx++] = person->name[i];
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
|
||||
|
||||
|
34
src/test/kc/struct-ptr-29.kc
Normal file
34
src/test/kc/struct-ptr-29.kc
Normal file
@ -0,0 +1,34 @@
|
||||
// Example of a struct containing a pointer
|
||||
|
||||
struct Person {
|
||||
char id;
|
||||
char* name;
|
||||
};
|
||||
|
||||
char* name1 = "jesper";
|
||||
char* name2 = "repsej";
|
||||
|
||||
struct Person[2] persons = {
|
||||
{ 4, name1 },
|
||||
{ 7, name2 }
|
||||
};
|
||||
|
||||
void main() {
|
||||
print_person(&persons[0]);
|
||||
print_person(&persons[1]);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
char[] DIGIT = "0123456789";
|
||||
|
||||
void print_person(struct Person *person) {
|
||||
SCREEN[idx++] = DIGIT[person->id];
|
||||
SCREEN[idx++] = ' ';
|
||||
for(byte i=0; person->name[i]; i++)
|
||||
SCREEN[idx++] = person->name[i];
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
|
||||
|
||||
|
24
src/test/kc/struct-ptr-30.kc
Normal file
24
src/test/kc/struct-ptr-30.kc
Normal file
@ -0,0 +1,24 @@
|
||||
// Test a struct array initialized with to few members (zero-filled for the rest)
|
||||
|
||||
struct Point {
|
||||
char x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct Point[4] points = { { 1, 2111 }, { 3, 4222 } };
|
||||
|
||||
void main() {
|
||||
for ( char i: 0..3) {
|
||||
print(points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
|
||||
void print(struct Point p) {
|
||||
SCREEN[idx++] = p.x;
|
||||
SCREEN[idx++] = <p.y;
|
||||
SCREEN[idx++] = >p.y;
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
34
src/test/kc/struct-ptr-31.kc
Normal file
34
src/test/kc/struct-ptr-31.kc
Normal file
@ -0,0 +1,34 @@
|
||||
// Example of a struct containing an array
|
||||
// Fails with an exception because the initializers do not work properly - and the memory layout is wrong
|
||||
// https://gitlab.com/camelot/kickc/issues/274
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
|
||||
struct Person {
|
||||
char id;
|
||||
char[16] name;
|
||||
};
|
||||
|
||||
struct Person[] persons = {
|
||||
{ 4, "jesper" },
|
||||
{ 7, "henriette" }
|
||||
};
|
||||
|
||||
void main() {
|
||||
print_person(persons);
|
||||
print_person(persons+1);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
char[] DIGIT = "0123456789";
|
||||
|
||||
void print_person(struct Person *person) {
|
||||
SCREEN[idx++] = DIGIT[person->id];
|
||||
SCREEN[idx++] = ' ';
|
||||
for(byte i=0; person->name[i]; i++)
|
||||
SCREEN[idx++] = person->name[i];
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
|
||||
|
||||
|
@ -1042,9 +1042,8 @@ processChars: {
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
stx $ffff
|
||||
// Enable the sprite
|
||||
lda SPRITES_ENABLE
|
||||
ora.z bitmask
|
||||
|
@ -7120,9 +7120,8 @@ processChars: {
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
stx $ffff
|
||||
// [266] *((const byte*) SPRITES_ENABLE#0) ← *((const byte*) SPRITES_ENABLE#0) | (byte) processChars::bitmask#0 -- _deref_pbuc1=_deref_pbuc1_bor_vbuz1
|
||||
// Enable the sprite
|
||||
lda SPRITES_ENABLE
|
||||
@ -8057,142 +8056,142 @@ Uplift Scope [setupRasterIrq]
|
||||
Uplift Scope [irqTop]
|
||||
Uplift Scope [irqBottom]
|
||||
|
||||
Uplifting [atan2_16] best 1280029 combination reg byte y [ atan2_16::shift#2 atan2_16::shift#5 atan2_16::shift#1 ] zp ZP_WORD:44 [ atan2_16::yd#5 atan2_16::yd#3 atan2_16::yd#10 atan2_16::yd#1 atan2_16::yd#2 ] zp ZP_WORD:46 [ atan2_16::xd#5 atan2_16::xd#3 atan2_16::xd#10 atan2_16::xd#1 atan2_16::xd#2 ] zp ZP_WORD:39 [ atan2_16::angle#6 atan2_16::angle#12 atan2_16::angle#13 atan2_16::angle#2 atan2_16::angle#3 ] zp ZP_WORD:34 [ atan2_16::yi#3 atan2_16::yi#8 atan2_16::yi#0 atan2_16::yi#16 atan2_16::$2 atan2_16::yi#1 atan2_16::yi#2 ] zp ZP_WORD:36 [ atan2_16::xi#3 atan2_16::xi#8 atan2_16::xi#0 atan2_16::xi#13 atan2_16::$7 atan2_16::xi#1 atan2_16::xi#2 ] reg byte a [ atan2_16::$24 ] reg byte a [ atan2_16::$23 ] reg byte x [ atan2_16::i#2 atan2_16::i#1 ] zp ZP_WORD:146 [ atan2_16::return#2 ] zp ZP_WORD:41 [ atan2_16::return#0 atan2_16::angle#5 atan2_16::angle#11 atan2_16::angle#1 atan2_16::angle#4 ] zp ZP_WORD:142 [ atan2_16::x#0 ] zp ZP_WORD:144 [ atan2_16::y#0 ]
|
||||
Uplifting [atan2_16] best 1280009 combination reg byte y [ atan2_16::shift#2 atan2_16::shift#5 atan2_16::shift#1 ] zp ZP_WORD:44 [ atan2_16::yd#5 atan2_16::yd#3 atan2_16::yd#10 atan2_16::yd#1 atan2_16::yd#2 ] zp ZP_WORD:46 [ atan2_16::xd#5 atan2_16::xd#3 atan2_16::xd#10 atan2_16::xd#1 atan2_16::xd#2 ] zp ZP_WORD:39 [ atan2_16::angle#6 atan2_16::angle#12 atan2_16::angle#13 atan2_16::angle#2 atan2_16::angle#3 ] zp ZP_WORD:34 [ atan2_16::yi#3 atan2_16::yi#8 atan2_16::yi#0 atan2_16::yi#16 atan2_16::$2 atan2_16::yi#1 atan2_16::yi#2 ] zp ZP_WORD:36 [ atan2_16::xi#3 atan2_16::xi#8 atan2_16::xi#0 atan2_16::xi#13 atan2_16::$7 atan2_16::xi#1 atan2_16::xi#2 ] reg byte a [ atan2_16::$24 ] reg byte a [ atan2_16::$23 ] reg byte x [ atan2_16::i#2 atan2_16::i#1 ] zp ZP_WORD:146 [ atan2_16::return#2 ] zp ZP_WORD:41 [ atan2_16::return#0 atan2_16::angle#5 atan2_16::angle#11 atan2_16::angle#1 atan2_16::angle#4 ] zp ZP_WORD:142 [ atan2_16::x#0 ] zp ZP_WORD:144 [ atan2_16::y#0 ]
|
||||
Limited combination testing to 100 combinations of 144 possible.
|
||||
Uplifting [getCharToProcess] best 1266696 combination reg byte x [ getCharToProcess::return_dist#1 getCharToProcess::return_dist#5 getCharToProcess::return_dist#6 getCharToProcess::dist#0 ] zp ZP_BYTE:20 [ getCharToProcess::closest_dist#2 getCharToProcess::closest_dist#8 getCharToProcess::closest_dist#10 getCharToProcess::closest_dist#12 ] zp ZP_BYTE:22 [ getCharToProcess::closest_y#7 getCharToProcess::closest_y#9 getCharToProcess::return_y#1 getCharToProcess::return_y#7 ] zp ZP_BYTE:21 [ getCharToProcess::closest_x#7 getCharToProcess::closest_x#9 getCharToProcess::return_x#1 getCharToProcess::return_x#7 ] zp ZP_BYTE:19 [ getCharToProcess::x#2 getCharToProcess::x#1 ] zp ZP_BYTE:18 [ getCharToProcess::y#7 getCharToProcess::y#1 ] zp ZP_WORD:16 [ getCharToProcess::dist_line#6 getCharToProcess::dist_line#0 getCharToProcess::dist_line#1 ] zp ZP_WORD:14 [ getCharToProcess::screen_line#4 getCharToProcess::screen_line#0 getCharToProcess::screen_line#1 ] zp ZP_BYTE:63 [ getCharToProcess::return_x#0 ] zp ZP_BYTE:64 [ getCharToProcess::return_y#0 ] zp ZP_BYTE:65 [ getCharToProcess::return_dist#0 ] zp ZP_WORD:127 [ getCharToProcess::$12 ] zp ZP_WORD:129 [ getCharToProcess::$13 ] zp ZP_WORD:131 [ getCharToProcess::$9 ] zp ZP_WORD:133 [ getCharToProcess::$10 ] zp ZP_WORD:125 [ getCharToProcess::$8 ]
|
||||
Uplifting [getCharToProcess] best 1266676 combination reg byte x [ getCharToProcess::return_dist#1 getCharToProcess::return_dist#5 getCharToProcess::return_dist#6 getCharToProcess::dist#0 ] zp ZP_BYTE:20 [ getCharToProcess::closest_dist#2 getCharToProcess::closest_dist#8 getCharToProcess::closest_dist#10 getCharToProcess::closest_dist#12 ] zp ZP_BYTE:22 [ getCharToProcess::closest_y#7 getCharToProcess::closest_y#9 getCharToProcess::return_y#1 getCharToProcess::return_y#7 ] zp ZP_BYTE:21 [ getCharToProcess::closest_x#7 getCharToProcess::closest_x#9 getCharToProcess::return_x#1 getCharToProcess::return_x#7 ] zp ZP_BYTE:19 [ getCharToProcess::x#2 getCharToProcess::x#1 ] zp ZP_BYTE:18 [ getCharToProcess::y#7 getCharToProcess::y#1 ] zp ZP_WORD:16 [ getCharToProcess::dist_line#6 getCharToProcess::dist_line#0 getCharToProcess::dist_line#1 ] zp ZP_WORD:14 [ getCharToProcess::screen_line#4 getCharToProcess::screen_line#0 getCharToProcess::screen_line#1 ] zp ZP_BYTE:63 [ getCharToProcess::return_x#0 ] zp ZP_BYTE:64 [ getCharToProcess::return_y#0 ] zp ZP_BYTE:65 [ getCharToProcess::return_dist#0 ] zp ZP_WORD:127 [ getCharToProcess::$12 ] zp ZP_WORD:129 [ getCharToProcess::$13 ] zp ZP_WORD:131 [ getCharToProcess::$9 ] zp ZP_WORD:133 [ getCharToProcess::$10 ] zp ZP_WORD:125 [ getCharToProcess::$8 ]
|
||||
Limited combination testing to 100 combinations of 46656 possible.
|
||||
Uplifting [init_angle_screen] best 1265096 combination zp ZP_BYTE:33 [ init_angle_screen::xb#2 init_angle_screen::xb#1 ] reg byte a [ init_angle_screen::$3 ] reg byte a [ init_angle_screen::$4 ] reg byte a [ init_angle_screen::$7 ] zp ZP_WORD:148 [ init_angle_screen::angle_w#0 ] zp ZP_WORD:150 [ init_angle_screen::$11 ] zp ZP_BYTE:153 [ init_angle_screen::$13 ] zp ZP_BYTE:154 [ init_angle_screen::$14 ] zp ZP_BYTE:155 [ init_angle_screen::$15 ] zp ZP_BYTE:32 [ init_angle_screen::x#2 init_angle_screen::x#1 ] zp ZP_BYTE:152 [ init_angle_screen::ang_w#0 ] zp ZP_WORD:140 [ init_angle_screen::yw#0 ] zp ZP_WORD:137 [ init_angle_screen::xw#0 ] zp ZP_BYTE:27 [ init_angle_screen::y#5 init_angle_screen::y#1 ] zp ZP_WORD:30 [ init_angle_screen::screen_bottomline#6 init_angle_screen::screen_bottomline#0 init_angle_screen::screen_bottomline#1 ] zp ZP_WORD:28 [ init_angle_screen::screen_topline#6 init_angle_screen::screen_topline#0 init_angle_screen::screen_topline#1 ] zp ZP_WORD:56 [ init_angle_screen::screen#0 ]
|
||||
Uplifting [init_angle_screen] best 1265076 combination zp ZP_BYTE:33 [ init_angle_screen::xb#2 init_angle_screen::xb#1 ] reg byte a [ init_angle_screen::$3 ] reg byte a [ init_angle_screen::$4 ] reg byte a [ init_angle_screen::$7 ] zp ZP_WORD:148 [ init_angle_screen::angle_w#0 ] zp ZP_WORD:150 [ init_angle_screen::$11 ] zp ZP_BYTE:153 [ init_angle_screen::$13 ] zp ZP_BYTE:154 [ init_angle_screen::$14 ] zp ZP_BYTE:155 [ init_angle_screen::$15 ] zp ZP_BYTE:32 [ init_angle_screen::x#2 init_angle_screen::x#1 ] zp ZP_BYTE:152 [ init_angle_screen::ang_w#0 ] zp ZP_WORD:140 [ init_angle_screen::yw#0 ] zp ZP_WORD:137 [ init_angle_screen::xw#0 ] zp ZP_BYTE:27 [ init_angle_screen::y#5 init_angle_screen::y#1 ] zp ZP_WORD:30 [ init_angle_screen::screen_bottomline#6 init_angle_screen::screen_bottomline#0 init_angle_screen::screen_bottomline#1 ] zp ZP_WORD:28 [ init_angle_screen::screen_topline#6 init_angle_screen::screen_topline#0 init_angle_screen::screen_topline#1 ] zp ZP_WORD:56 [ init_angle_screen::screen#0 ]
|
||||
Limited combination testing to 100 combinations of 65536 possible.
|
||||
Uplifting [main] best 1264856 combination zp ZP_WORD:4 [ main::dst#2 main::dst#0 main::dst#1 ] zp ZP_WORD:2 [ main::src#2 main::src#1 ] reg byte a [ main::$27 ] reg byte a [ main::$28 ] reg byte a [ main::$29 ] reg byte a [ main::$30 ] zp ZP_BYTE:68 [ main::center_dist#0 ] zp ZP_BYTE:6 [ main::i#2 main::i#1 ] zp ZP_BYTE:62 [ main::$17 ] zp ZP_BYTE:66 [ main::center_x#0 ] zp ZP_BYTE:67 [ main::center_y#0 ]
|
||||
Uplifting [main] best 1264836 combination zp ZP_WORD:4 [ main::dst#2 main::dst#0 main::dst#1 ] zp ZP_WORD:2 [ main::src#2 main::src#1 ] reg byte a [ main::$27 ] reg byte a [ main::$28 ] reg byte a [ main::$29 ] reg byte a [ main::$30 ] zp ZP_BYTE:68 [ main::center_dist#0 ] zp ZP_BYTE:6 [ main::i#2 main::i#1 ] zp ZP_BYTE:62 [ main::$17 ] zp ZP_BYTE:66 [ main::center_x#0 ] zp ZP_BYTE:67 [ main::center_y#0 ]
|
||||
Limited combination testing to 100 combinations of 147456 possible.
|
||||
Uplifting [initSprites] best 1264736 combination zp ZP_WORD:24 [ initSprites::sp#2 initSprites::sp#1 ] reg byte x [ initSprites::i#2 initSprites::i#1 ]
|
||||
Uplifting [] best 1264736 combination zp ZP_WORD:48 [ heap_head#5 heap_head#1 ] zp ZP_WORD:54 [ SCREEN_DIST#0 ] zp ZP_WORD:52 [ SCREEN_COPY#0 ]
|
||||
Uplifting [malloc] best 1264736 combination zp ZP_WORD:158 [ malloc::mem#0 ]
|
||||
Uplifting [RADIX] best 1264736 combination
|
||||
Uplifting [ProcessingChar] best 1264736 combination
|
||||
Uplifting [ProcessingSprite] best 1264736 combination
|
||||
Uplifting [ProcessingSprite::$0] best 1264736 combination
|
||||
Uplifting [setupRasterIrq] best 1264736 combination
|
||||
Uplifting [irqTop] best 1264736 combination
|
||||
Uplifting [irqBottom] best 1264736 combination
|
||||
Uplifting [initSprites] best 1264716 combination zp ZP_WORD:24 [ initSprites::sp#2 initSprites::sp#1 ] reg byte x [ initSprites::i#2 initSprites::i#1 ]
|
||||
Uplifting [] best 1264716 combination zp ZP_WORD:48 [ heap_head#5 heap_head#1 ] zp ZP_WORD:54 [ SCREEN_DIST#0 ] zp ZP_WORD:52 [ SCREEN_COPY#0 ]
|
||||
Uplifting [malloc] best 1264716 combination zp ZP_WORD:158 [ malloc::mem#0 ]
|
||||
Uplifting [RADIX] best 1264716 combination
|
||||
Uplifting [ProcessingChar] best 1264716 combination
|
||||
Uplifting [ProcessingSprite] best 1264716 combination
|
||||
Uplifting [ProcessingSprite::$0] best 1264716 combination
|
||||
Uplifting [setupRasterIrq] best 1264716 combination
|
||||
Uplifting [irqTop] best 1264716 combination
|
||||
Uplifting [irqBottom] best 1264716 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:20 [ getCharToProcess::closest_dist#2 getCharToProcess::closest_dist#8 getCharToProcess::closest_dist#10 getCharToProcess::closest_dist#12 ]
|
||||
Uplifting [getCharToProcess] best 1264736 combination zp ZP_BYTE:20 [ getCharToProcess::closest_dist#2 getCharToProcess::closest_dist#8 getCharToProcess::closest_dist#10 getCharToProcess::closest_dist#12 ]
|
||||
Uplifting [getCharToProcess] best 1264716 combination zp ZP_BYTE:20 [ getCharToProcess::closest_dist#2 getCharToProcess::closest_dist#8 getCharToProcess::closest_dist#10 getCharToProcess::closest_dist#12 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:22 [ getCharToProcess::closest_y#7 getCharToProcess::closest_y#9 getCharToProcess::return_y#1 getCharToProcess::return_y#7 ]
|
||||
Uplifting [getCharToProcess] best 1264736 combination zp ZP_BYTE:22 [ getCharToProcess::closest_y#7 getCharToProcess::closest_y#9 getCharToProcess::return_y#1 getCharToProcess::return_y#7 ]
|
||||
Uplifting [getCharToProcess] best 1264716 combination zp ZP_BYTE:22 [ getCharToProcess::closest_y#7 getCharToProcess::closest_y#9 getCharToProcess::return_y#1 getCharToProcess::return_y#7 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:8 [ startProcessing::freeIdx#2 startProcessing::freeIdx#8 startProcessing::i#2 startProcessing::i#1 ]
|
||||
Uplifting [startProcessing] best 1264736 combination zp ZP_BYTE:8 [ startProcessing::freeIdx#2 startProcessing::freeIdx#8 startProcessing::i#2 startProcessing::i#1 ]
|
||||
Uplifting [startProcessing] best 1264716 combination zp ZP_BYTE:8 [ startProcessing::freeIdx#2 startProcessing::freeIdx#8 startProcessing::i#2 startProcessing::i#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:71 [ startProcessing::$42 ]
|
||||
Uplifting [startProcessing] best 1258736 combination reg byte a [ startProcessing::$42 ]
|
||||
Uplifting [startProcessing] best 1258716 combination reg byte a [ startProcessing::$42 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:72 [ startProcessing::$43 ]
|
||||
Uplifting [startProcessing] best 1252736 combination reg byte a [ startProcessing::$43 ]
|
||||
Uplifting [startProcessing] best 1252716 combination reg byte a [ startProcessing::$43 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:73 [ startProcessing::$44 ]
|
||||
Uplifting [startProcessing] best 1246736 combination reg byte a [ startProcessing::$44 ]
|
||||
Uplifting [startProcessing] best 1246716 combination reg byte a [ startProcessing::$44 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:74 [ startProcessing::$45 ]
|
||||
Uplifting [startProcessing] best 1240736 combination reg byte a [ startProcessing::$45 ]
|
||||
Uplifting [startProcessing] best 1240716 combination reg byte a [ startProcessing::$45 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:75 [ startProcessing::$30 ]
|
||||
Uplifting [startProcessing] best 1236736 combination reg byte a [ startProcessing::$30 ]
|
||||
Uplifting [startProcessing] best 1236716 combination reg byte a [ startProcessing::$30 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:21 [ getCharToProcess::closest_x#7 getCharToProcess::closest_x#9 getCharToProcess::return_x#1 getCharToProcess::return_x#7 ]
|
||||
Uplifting [getCharToProcess] best 1236736 combination zp ZP_BYTE:21 [ getCharToProcess::closest_x#7 getCharToProcess::closest_x#9 getCharToProcess::return_x#1 getCharToProcess::return_x#7 ]
|
||||
Uplifting [getCharToProcess] best 1236716 combination zp ZP_BYTE:21 [ getCharToProcess::closest_x#7 getCharToProcess::closest_x#9 getCharToProcess::return_x#1 getCharToProcess::return_x#7 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:19 [ getCharToProcess::x#2 getCharToProcess::x#1 ]
|
||||
Uplifting [getCharToProcess] best 1218736 combination reg byte y [ getCharToProcess::x#2 getCharToProcess::x#1 ]
|
||||
Uplifting [getCharToProcess] best 1218716 combination reg byte y [ getCharToProcess::x#2 getCharToProcess::x#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:7 [ startProcessing::freeIdx#6 startProcessing::freeIdx#7 ]
|
||||
Uplifting [startProcessing] best 1217836 combination reg byte x [ startProcessing::freeIdx#6 startProcessing::freeIdx#7 ]
|
||||
Uplifting [startProcessing] best 1217816 combination reg byte x [ startProcessing::freeIdx#6 startProcessing::freeIdx#7 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:33 [ init_angle_screen::xb#2 init_angle_screen::xb#1 ]
|
||||
Uplifting [init_angle_screen] best 1217836 combination zp ZP_BYTE:33 [ init_angle_screen::xb#2 init_angle_screen::xb#1 ]
|
||||
Uplifting [init_angle_screen] best 1217816 combination zp ZP_BYTE:33 [ init_angle_screen::xb#2 init_angle_screen::xb#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:13 [ startProcessing::i1#2 startProcessing::i1#1 ]
|
||||
Uplifting [startProcessing] best 1216936 combination reg byte x [ startProcessing::i1#2 startProcessing::i1#1 ]
|
||||
Uplifting [startProcessing] best 1216916 combination reg byte x [ startProcessing::i1#2 startProcessing::i1#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:153 [ init_angle_screen::$13 ]
|
||||
Uplifting [init_angle_screen] best 1216336 combination reg byte a [ init_angle_screen::$13 ]
|
||||
Uplifting [init_angle_screen] best 1216316 combination reg byte a [ init_angle_screen::$13 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:154 [ init_angle_screen::$14 ]
|
||||
Uplifting [init_angle_screen] best 1215936 combination reg byte a [ init_angle_screen::$14 ]
|
||||
Uplifting [init_angle_screen] best 1215916 combination reg byte a [ init_angle_screen::$14 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:155 [ init_angle_screen::$15 ]
|
||||
Uplifting [init_angle_screen] best 1215336 combination reg byte a [ init_angle_screen::$15 ]
|
||||
Uplifting [init_angle_screen] best 1215316 combination reg byte a [ init_angle_screen::$15 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:18 [ getCharToProcess::y#7 getCharToProcess::y#1 ]
|
||||
Uplifting [getCharToProcess] best 1215336 combination zp ZP_BYTE:18 [ getCharToProcess::y#7 getCharToProcess::y#1 ]
|
||||
Uplifting [getCharToProcess] best 1215316 combination zp ZP_BYTE:18 [ getCharToProcess::y#7 getCharToProcess::y#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:32 [ init_angle_screen::x#2 init_angle_screen::x#1 ]
|
||||
Uplifting [init_angle_screen] best 1215336 combination zp ZP_BYTE:32 [ init_angle_screen::x#2 init_angle_screen::x#1 ]
|
||||
Uplifting [init_angle_screen] best 1215316 combination zp ZP_BYTE:32 [ init_angle_screen::x#2 init_angle_screen::x#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:152 [ init_angle_screen::ang_w#0 ]
|
||||
Uplifting [init_angle_screen] best 1215336 combination zp ZP_BYTE:152 [ init_angle_screen::ang_w#0 ]
|
||||
Uplifting [init_angle_screen] best 1215316 combination zp ZP_BYTE:152 [ init_angle_screen::ang_w#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:51 [ processChars::numActive#10 processChars::numActive#3 processChars::numActive#1 ]
|
||||
Uplifting [processChars] best 1215336 combination zp ZP_BYTE:51 [ processChars::numActive#10 processChars::numActive#3 processChars::numActive#1 ]
|
||||
Uplifting [processChars] best 1215316 combination zp ZP_BYTE:51 [ processChars::numActive#10 processChars::numActive#3 processChars::numActive#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:68 [ main::center_dist#0 ]
|
||||
Uplifting [main] best 1215276 combination reg byte a [ main::center_dist#0 ]
|
||||
Uplifting [main] best 1215256 combination reg byte a [ main::center_dist#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:160 [ processChars::$67 ]
|
||||
Uplifting [processChars] best 1215216 combination reg byte a [ processChars::$67 ]
|
||||
Uplifting [processChars] best 1215196 combination reg byte a [ processChars::$67 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:161 [ processChars::$68 ]
|
||||
Uplifting [processChars] best 1215156 combination reg byte a [ processChars::$68 ]
|
||||
Uplifting [processChars] best 1215136 combination reg byte a [ processChars::$68 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:162 [ processChars::$69 ]
|
||||
Uplifting [processChars] best 1215096 combination reg byte a [ processChars::$69 ]
|
||||
Uplifting [processChars] best 1215076 combination reg byte a [ processChars::$69 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:163 [ processChars::$70 ]
|
||||
Uplifting [processChars] best 1215036 combination reg byte a [ processChars::$70 ]
|
||||
Uplifting [processChars] best 1215016 combination reg byte a [ processChars::$70 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:164 [ processChars::$37 ]
|
||||
Uplifting [processChars] best 1214976 combination reg byte a [ processChars::$37 ]
|
||||
Uplifting [processChars] best 1214956 combination reg byte a [ processChars::$37 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:170 [ processChars::$11 ]
|
||||
Uplifting [processChars] best 1214916 combination reg byte a [ processChars::$11 ]
|
||||
Uplifting [processChars] best 1214896 combination reg byte a [ processChars::$11 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:171 [ processChars::$12 ]
|
||||
Uplifting [processChars] best 1214856 combination reg byte a [ processChars::$12 ]
|
||||
Uplifting [processChars] best 1214836 combination reg byte a [ processChars::$12 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:173 [ processChars::$14 ]
|
||||
Uplifting [processChars] best 1214796 combination reg byte a [ processChars::$14 ]
|
||||
Uplifting [processChars] best 1214776 combination reg byte a [ processChars::$14 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:179 [ processChars::$26 ]
|
||||
Uplifting [processChars] best 1214756 combination reg byte a [ processChars::$26 ]
|
||||
Uplifting [processChars] best 1214736 combination reg byte a [ processChars::$26 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:180 [ processChars::xchar#0 ]
|
||||
Uplifting [processChars] best 1214696 combination reg byte a [ processChars::xchar#0 ]
|
||||
Uplifting [processChars] best 1214676 combination reg byte a [ processChars::xchar#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:181 [ processChars::$38 ]
|
||||
Uplifting [processChars] best 1214656 combination reg byte a [ processChars::$38 ]
|
||||
Uplifting [processChars] best 1214636 combination reg byte a [ processChars::$38 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:182 [ processChars::$30 ]
|
||||
Uplifting [processChars] best 1214616 combination reg byte a [ processChars::$30 ]
|
||||
Uplifting [processChars] best 1214596 combination reg byte a [ processChars::$30 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:183 [ processChars::ychar#0 ]
|
||||
Uplifting [processChars] best 1214556 combination reg byte a [ processChars::ychar#0 ]
|
||||
Uplifting [processChars] best 1214536 combination reg byte a [ processChars::ychar#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:184 [ processChars::$39 ]
|
||||
Uplifting [processChars] best 1214516 combination reg byte a [ processChars::$39 ]
|
||||
Uplifting [processChars] best 1214496 combination reg byte a [ processChars::$39 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:185 [ processChars::$33 ]
|
||||
Uplifting [processChars] best 1214456 combination reg byte a [ processChars::$33 ]
|
||||
Uplifting [processChars] best 1214436 combination reg byte a [ processChars::$33 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:27 [ init_angle_screen::y#5 init_angle_screen::y#1 ]
|
||||
Uplifting [init_angle_screen] best 1214456 combination zp ZP_BYTE:27 [ init_angle_screen::y#5 init_angle_screen::y#1 ]
|
||||
Uplifting [init_angle_screen] best 1214436 combination zp ZP_BYTE:27 [ init_angle_screen::y#5 init_angle_screen::y#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:6 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 1214456 combination zp ZP_BYTE:6 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 1214436 combination zp ZP_BYTE:6 [ main::i#2 main::i#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:50 [ processChars::i#10 processChars::i#1 ]
|
||||
Uplifting [processChars] best 1214456 combination zp ZP_BYTE:50 [ processChars::i#10 processChars::i#1 ]
|
||||
Uplifting [processChars] best 1214436 combination zp ZP_BYTE:50 [ processChars::i#10 processChars::i#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:62 [ main::$17 ]
|
||||
Uplifting [main] best 1214296 combination reg byte x [ main::$17 ]
|
||||
Uplifting [main] best 1214276 combination reg byte x [ main::$17 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:63 [ getCharToProcess::return_x#0 ]
|
||||
Uplifting [getCharToProcess] best 1214236 combination reg byte y [ getCharToProcess::return_x#0 ]
|
||||
Uplifting [getCharToProcess] best 1214216 combination reg byte y [ getCharToProcess::return_x#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:64 [ getCharToProcess::return_y#0 ]
|
||||
Uplifting [getCharToProcess] best 1214176 combination reg byte a [ getCharToProcess::return_y#0 ]
|
||||
Uplifting [getCharToProcess] best 1214156 combination reg byte a [ getCharToProcess::return_y#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:65 [ getCharToProcess::return_dist#0 ]
|
||||
Uplifting [getCharToProcess] best 1214136 combination reg byte x [ getCharToProcess::return_dist#0 ]
|
||||
Uplifting [getCharToProcess] best 1214116 combination reg byte x [ getCharToProcess::return_dist#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:172 [ processChars::$17 ]
|
||||
Uplifting [processChars] best 1214066 combination reg byte x [ processChars::$17 ]
|
||||
Uplifting [processChars] best 1214046 combination reg byte x [ processChars::$17 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:66 [ main::center_x#0 ]
|
||||
Uplifting [main] best 1214006 combination reg byte y [ main::center_x#0 ]
|
||||
Uplifting [main] best 1213986 combination reg byte y [ main::center_x#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:67 [ main::center_y#0 ]
|
||||
Uplifting [main] best 1214006 combination zp ZP_BYTE:67 [ main::center_y#0 ]
|
||||
Uplifting [main] best 1213986 combination zp ZP_BYTE:67 [ main::center_y#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:120 [ startProcessing::$50 ]
|
||||
Uplifting [startProcessing] best 1214000 combination reg byte a [ startProcessing::$50 ]
|
||||
Uplifting [startProcessing] best 1213980 combination reg byte a [ startProcessing::$50 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:121 [ startProcessing::$51 ]
|
||||
Uplifting [startProcessing] best 1213994 combination reg byte a [ startProcessing::$51 ]
|
||||
Uplifting [startProcessing] best 1213974 combination reg byte a [ startProcessing::$51 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:122 [ startProcessing::$52 ]
|
||||
Uplifting [startProcessing] best 1213988 combination reg byte a [ startProcessing::$52 ]
|
||||
Uplifting [startProcessing] best 1213968 combination reg byte a [ startProcessing::$52 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:123 [ startProcessing::$53 ]
|
||||
Uplifting [startProcessing] best 1213982 combination reg byte a [ startProcessing::$53 ]
|
||||
Uplifting [startProcessing] best 1213962 combination reg byte a [ startProcessing::$53 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:176 [ processChars::ypos#0 ]
|
||||
Uplifting [processChars] best 1213982 combination zp ZP_BYTE:176 [ processChars::ypos#0 ]
|
||||
Uplifting [processChars] best 1213962 combination zp ZP_BYTE:176 [ processChars::ypos#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:124 [ startProcessing::$31 ]
|
||||
Uplifting [startProcessing] best 1213957 combination reg byte x [ startProcessing::$31 ]
|
||||
Uplifting [startProcessing] best 1213937 combination reg byte x [ startProcessing::$31 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:167 [ processChars::bitmask#0 ]
|
||||
Uplifting [processChars] best 1213957 combination zp ZP_BYTE:167 [ processChars::bitmask#0 ]
|
||||
Uplifting [processChars] best 1213937 combination zp ZP_BYTE:167 [ processChars::bitmask#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:95 [ startProcessing::ch#0 ]
|
||||
Uplifting [startProcessing] best 1213951 combination reg byte a [ startProcessing::ch#0 ]
|
||||
Uplifting [startProcessing] best 1213931 combination reg byte a [ startProcessing::ch#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:117 [ startProcessing::$22 ]
|
||||
Uplifting [startProcessing] best 1213945 combination reg byte a [ startProcessing::$22 ]
|
||||
Uplifting [startProcessing] best 1213925 combination reg byte a [ startProcessing::$22 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:69 [ startProcessing::center_x#0 ]
|
||||
Uplifting [startProcessing] best 1213945 combination zp ZP_BYTE:69 [ startProcessing::center_x#0 ]
|
||||
Uplifting [startProcessing] best 1213925 combination zp ZP_BYTE:69 [ startProcessing::center_x#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:116 [ startProcessing::spritePtr#0 ]
|
||||
Uplifting [startProcessing] best 1213945 combination zp ZP_BYTE:116 [ startProcessing::spritePtr#0 ]
|
||||
Uplifting [startProcessing] best 1213925 combination zp ZP_BYTE:116 [ startProcessing::spritePtr#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:70 [ startProcessing::center_y#0 ]
|
||||
Uplifting [startProcessing] best 1213945 combination zp ZP_BYTE:70 [ startProcessing::center_y#0 ]
|
||||
Uplifting [startProcessing] best 1213925 combination zp ZP_BYTE:70 [ startProcessing::center_y#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:88 [ startProcessing::spriteCol#0 ]
|
||||
Uplifting [startProcessing] best 1213945 combination zp ZP_BYTE:88 [ startProcessing::spriteCol#0 ]
|
||||
Uplifting [startProcessing] best 1213925 combination zp ZP_BYTE:88 [ startProcessing::spriteCol#0 ]
|
||||
Coalescing zero page register [ zp ZP_WORD:9 [ startProcessing::chargenData#2 startProcessing::chargenData#0 startProcessing::chargenData#1 ] ] with [ zp ZP_WORD:98 [ startProcessing::$9 ] ] - score: 1
|
||||
Coalescing zero page register [ zp ZP_WORD:11 [ startProcessing::spriteData#2 startProcessing::spriteData#0 startProcessing::spriteData#1 ] ] with [ zp ZP_WORD:93 [ startProcessing::$6 ] ] - score: 1
|
||||
Coalescing zero page register [ zp ZP_WORD:30 [ init_angle_screen::screen_bottomline#6 init_angle_screen::screen_bottomline#0 init_angle_screen::screen_bottomline#1 ] ] with [ zp ZP_WORD:56 [ init_angle_screen::screen#0 ] ] - score: 1
|
||||
@ -9953,9 +9952,8 @@ processChars: {
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
stx $ffff
|
||||
// [266] *((const byte*) SPRITES_ENABLE#0) ← *((const byte*) SPRITES_ENABLE#0) | (byte) processChars::bitmask#0 -- _deref_pbuc1=_deref_pbuc1_bor_vbuz1
|
||||
// Enable the sprite
|
||||
lda SPRITES_ENABLE
|
||||
@ -10542,21 +10540,21 @@ Removing instruction ldy #OFFSET_STRUCT_PROCESSINGSPRITE_STATUS
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Fixing long branch [458] bne b2 to beq
|
||||
Fixing long branch [873] beq b12 to bne
|
||||
Fixing long branch [1217] bne b1 to beq
|
||||
Fixing long branch [1216] bne b1 to beq
|
||||
Fixing long branch [234] bne b3 to beq
|
||||
Fixing long branch [240] beq b8 to bne
|
||||
Fixing long branch [503] beq b11 to bne
|
||||
Fixing long branch [773] bpl b1 to bmi
|
||||
Fixing long branch [785] bpl b4 to bmi
|
||||
Fixing long branch [1030] beq b2 to bne
|
||||
Fixing long branch [1091] bne b4 to beq
|
||||
Fixing long branch [1125] bcc b6 to bcs
|
||||
Fixing long branch [1132] bcc b6 to bcs
|
||||
Fixing long branch [1139] bcc b6 to bcs
|
||||
Fixing long branch [1146] bcc b6 to bcs
|
||||
Fixing long branch [1154] bcc b6 to bcs
|
||||
Fixing long branch [1161] bcc b6 to bcs
|
||||
Fixing long branch [1169] bcc b6 to bcs
|
||||
Fixing long branch [1090] bne b4 to beq
|
||||
Fixing long branch [1124] bcc b6 to bcs
|
||||
Fixing long branch [1131] bcc b6 to bcs
|
||||
Fixing long branch [1138] bcc b6 to bcs
|
||||
Fixing long branch [1145] bcc b6 to bcs
|
||||
Fixing long branch [1153] bcc b6 to bcs
|
||||
Fixing long branch [1160] bcc b6 to bcs
|
||||
Fixing long branch [1168] bcc b6 to bcs
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -11159,7 +11157,7 @@ reg byte a [ processChars::$33 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1113942
|
||||
Score: 1113922
|
||||
|
||||
// File Comments
|
||||
// Clears start screen throwing around the letters (by turning them into sprites)
|
||||
@ -12813,9 +12811,8 @@ processChars: {
|
||||
iny
|
||||
lda (processing),y
|
||||
sta !+ +2
|
||||
txa
|
||||
!:
|
||||
sta $ffff
|
||||
stx $ffff
|
||||
// *SPRITES_ENABLE |= bitmask
|
||||
// [266] *((const byte*) SPRITES_ENABLE#0) ← *((const byte*) SPRITES_ENABLE#0) | (byte) processChars::bitmask#0 -- _deref_pbuc1=_deref_pbuc1_bor_vbuz1
|
||||
// Enable the sprite
|
||||
|
61
src/test/ref/struct-12.asm
Normal file
61
src/test/ref/struct-12.asm
Normal file
@ -0,0 +1,61 @@
|
||||
// Example of a struct containing an array
|
||||
// Works because the struct is only handled as a value
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
ldy #0
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
henriette_name: .text "repsej"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
}
|
||||
// print_person(byte register(X) person_id, byte[$40] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
ldy #0
|
||||
b1:
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
rts
|
||||
b2:
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
iny
|
||||
jmp b1
|
||||
}
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
46
src/test/ref/struct-12.cfg
Normal file
46
src/test/ref/struct-12.cfg
Normal file
@ -0,0 +1,46 @@
|
||||
@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_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte[$40]) print_person::person_name#4 ← phi( main/(const byte[$40]) main::jesper_name#1 main::@1/(const byte[$40]) main::henriette_name#1 )
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (byte) print_person::person_id#2 ← phi( main/(const byte) main::jesper_id#1 main::@1/(const byte) main::henriette_id#1 )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
927
src/test/ref/struct-12.log
Normal file
927
src/test/ref/struct-12.log
Normal file
@ -0,0 +1,927 @@
|
||||
Created struct value member variable (byte) main::jesper_id
|
||||
Created struct value member variable (byte[$40]) main::jesper_name
|
||||
Converted struct value to member variables (struct Person) main::jesper
|
||||
Created struct value member variable (byte) main::henriette_id
|
||||
Created struct value member variable (byte[$40]) main::henriette_name
|
||||
Converted struct value to member variables (struct Person) main::henriette
|
||||
Created struct value member variable (byte) print_person::person_id
|
||||
Created struct value member variable (byte[$40]) print_person::person_name
|
||||
Converted struct value to member variables (struct Person) print_person::person
|
||||
Converted procedure struct value parameter to member unwinding (void()) print_person((byte) print_person::person_id , (byte[$40]) print_person::person_name)
|
||||
Adding struct value member variable default initializer (byte) main::jesper_id ← (byte) 0
|
||||
Adding struct value member variable default initializer (byte[$40]) main::jesper_name ← { fill( $40, 0) }
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print_person (byte) main::jesper_id (byte[$40]) main::jesper_name
|
||||
Adding struct value member variable default initializer (byte) main::henriette_id ← (byte) 0
|
||||
Adding struct value member variable default initializer (byte[$40]) main::henriette_name ← { fill( $40, 0) }
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$1 ← call print_person (byte) main::henriette_id (byte[$40]) main::henriette_name
|
||||
Replacing struct member reference (struct Person) main::jesper.id with member unwinding reference (byte) main::jesper_id
|
||||
Replacing struct member reference (struct Person) main::jesper.name with member unwinding reference (byte[$40]) main::jesper_name
|
||||
Replacing struct member reference (struct Person) main::henriette.id with member unwinding reference (byte) main::henriette_id
|
||||
Replacing struct member reference (struct Person) main::henriette.name with member unwinding reference (byte[$40]) main::henriette_name
|
||||
Replacing struct member reference (struct Person) print_person::person.id with member unwinding reference (byte) print_person::person_id
|
||||
Replacing struct member reference (struct Person) print_person::person.name with member unwinding reference (byte[$40]) print_person::person_name
|
||||
Replacing struct member reference (struct Person) print_person::person.name with member unwinding reference (byte[$40]) print_person::person_name
|
||||
Warning! Adding boolean cast to non-boolean condition *((byte[$40]) print_person::person_name + (byte) print_person::i)
|
||||
Culled Empty Block (label) print_person::@4
|
||||
Culled Empty Block (label) print_person::@5
|
||||
Culled Empty Block (label) print_person::@6
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#18 ← phi( @2/(byte) idx#20 )
|
||||
(byte) main::jesper_id#0 ← (byte) 0
|
||||
(byte[$40]) main::jesper_name#0 ← { fill( $40, 0) }
|
||||
(byte) main::jesper_id#1 ← (number) 4
|
||||
(byte[$40]) main::jesper_name#1 ← (const string) main::$2
|
||||
(byte) print_person::person_id#0 ← (byte) main::jesper_id#1
|
||||
(byte[$40]) print_person::person_name#0 ← (byte[$40]) main::jesper_name#1
|
||||
call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte) idx#10 ← phi( main/(byte) idx#8 )
|
||||
(byte) idx#0 ← (byte) idx#10
|
||||
(byte) main::henriette_id#0 ← (byte) 0
|
||||
(byte[$40]) main::henriette_name#0 ← { fill( $40, 0) }
|
||||
(byte) main::henriette_id#1 ← (number) 7
|
||||
(byte[$40]) main::henriette_name#1 ← (const string) main::$3
|
||||
(byte) print_person::person_id#1 ← (byte) main::henriette_id#1
|
||||
(byte[$40]) print_person::person_name#1 ← (byte[$40]) main::henriette_name#1
|
||||
call print_person
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) idx#11 ← phi( main::@1/(byte) idx#8 )
|
||||
(byte) idx#1 ← (byte) idx#11
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
(byte) idx#12 ← phi( main::@2/(byte) idx#1 )
|
||||
(byte) idx#2 ← (byte) idx#12
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
(byte) idx#3 ← (number) 0
|
||||
(byte[]) DIGIT#0 ← (const string) $0
|
||||
to:@2
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
(byte[$40]) print_person::person_name#4 ← phi( main/(byte[$40]) print_person::person_name#0 main::@1/(byte[$40]) print_person::person_name#1 )
|
||||
(byte) idx#13 ← phi( main/(byte) idx#18 main::@1/(byte) idx#0 )
|
||||
(byte) print_person::person_id#2 ← phi( main/(byte) print_person::person_id#0 main::@1/(byte) print_person::person_id#1 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#13) ← *((byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
(byte) idx#4 ← ++ (byte) idx#13
|
||||
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
(byte) idx#5 ← ++ (byte) idx#4
|
||||
(byte) print_person::i#0 ← (number) 0
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
(byte) idx#19 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
(byte) print_person::i#2 ← phi( print_person/(byte) print_person::i#0 print_person::@2/(byte) print_person::i#1 )
|
||||
(byte[$40]) print_person::person_name#2 ← phi( print_person/(byte[$40]) print_person::person_name#4 print_person::@2/(byte[$40]) print_person::person_name#3 )
|
||||
(bool~) print_person::$0 ← (number) 0 != *((byte[$40]) print_person::person_name#2 + (byte) print_person::i#2)
|
||||
if((bool~) print_person::$0) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
(byte) idx#14 ← phi( print_person::@1/(byte) idx#19 )
|
||||
(byte) print_person::i#3 ← phi( print_person::@1/(byte) print_person::i#2 )
|
||||
(byte[$40]) print_person::person_name#3 ← phi( print_person::@1/(byte[$40]) print_person::person_name#2 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#3 + (byte) print_person::i#3)
|
||||
(byte) idx#6 ← ++ (byte) idx#14
|
||||
(byte) print_person::i#1 ← ++ (byte) print_person::i#3
|
||||
to:print_person::@1
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
(byte) idx#15 ← phi( print_person::@1/(byte) idx#19 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#15) ← (byte) ' '
|
||||
(byte) idx#7 ← ++ (byte) idx#15
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
(byte) idx#16 ← phi( print_person::@3/(byte) idx#7 )
|
||||
(byte) idx#8 ← (byte) idx#16
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#20 ← phi( @1/(byte) idx#3 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#17 ← phi( @2/(byte) idx#2 )
|
||||
(byte) idx#9 ← (byte) idx#17
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "0123456789"
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(byte[]) DIGIT#0
|
||||
(byte) Person::id
|
||||
(byte[$40]) Person::name
|
||||
(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#17
|
||||
(byte) idx#18
|
||||
(byte) idx#19
|
||||
(byte) idx#2
|
||||
(byte) idx#20
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(void()) main()
|
||||
(const string) main::$2 = (string) "jesper"
|
||||
(const string) main::$3 = (string) "repsej"
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::henriette_id
|
||||
(byte) main::henriette_id#0
|
||||
(byte) main::henriette_id#1
|
||||
(byte[$40]) main::henriette_name
|
||||
(byte[$40]) main::henriette_name#0
|
||||
(byte[$40]) main::henriette_name#1
|
||||
(byte) main::jesper_id
|
||||
(byte) main::jesper_id#0
|
||||
(byte) main::jesper_id#1
|
||||
(byte[$40]) main::jesper_name
|
||||
(byte[$40]) main::jesper_name#0
|
||||
(byte[$40]) main::jesper_name#1
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$40]) print_person::person_name)
|
||||
(bool~) print_person::$0
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#0
|
||||
(byte) print_person::i#1
|
||||
(byte) print_person::i#2
|
||||
(byte) print_person::i#3
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#0
|
||||
(byte) print_person::person_id#1
|
||||
(byte) print_person::person_id#2
|
||||
(byte[$40]) print_person::person_name
|
||||
(byte[$40]) print_person::person_name#0
|
||||
(byte[$40]) print_person::person_name#1
|
||||
(byte[$40]) print_person::person_name#2
|
||||
(byte[$40]) print_person::person_name#3
|
||||
(byte[$40]) print_person::person_name#4
|
||||
|
||||
Adding number conversion cast (unumber) 4 in (byte) main::jesper_id#1 ← (number) 4
|
||||
Adding number conversion cast (unumber) 7 in (byte) main::henriette_id#1 ← (number) 7
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#3 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) print_person::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print_person::$0 ← (number) 0 != *((byte[$40]) print_person::person_name#2 + (byte) print_person::i#2)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte) main::jesper_id#1 ← (unumber)(number) 4
|
||||
Inlining cast (byte) main::henriette_id#1 ← (unumber)(number) 7
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#3 ← (unumber)(number) 0
|
||||
Inlining cast (byte) print_person::i#0 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 7
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized unsigned number type (byte) 7
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte) idx#0 = (byte) idx#10
|
||||
Alias (byte) idx#1 = (byte) idx#11 (byte) idx#12 (byte) idx#2
|
||||
Alias (byte[$40]) print_person::person_name#2 = (byte[$40]) print_person::person_name#3
|
||||
Alias (byte) print_person::i#2 = (byte) print_person::i#3
|
||||
Alias (byte) idx#14 = (byte) idx#19 (byte) idx#15
|
||||
Alias (byte) idx#16 = (byte) idx#7 (byte) idx#8
|
||||
Alias (byte) idx#20 = (byte) idx#3
|
||||
Alias (byte) idx#17 = (byte) idx#9
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#18 (byte) idx#20
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#16
|
||||
Identical Phi Values (byte) idx#1 (byte) idx#16
|
||||
Identical Phi Values (byte[$40]) print_person::person_name#2 (byte[$40]) print_person::person_name#4
|
||||
Identical Phi Values (byte) idx#17 (byte) idx#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) print_person::$0 [33] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant right-side identified [2] (byte[$40]) main::jesper_name#0 ← { fill( $40, 0) }
|
||||
Constant right-side identified [11] (byte[$40]) main::henriette_name#0 ← { fill( $40, 0) }
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::jesper_id#0 = 0
|
||||
Constant (const byte[$40]) main::jesper_name#0 = { fill( $40, 0) }
|
||||
Constant (const byte) main::jesper_id#1 = 4
|
||||
Constant (const byte[$40]) main::jesper_name#1 = main::$2
|
||||
Constant (const byte) main::henriette_id#0 = 0
|
||||
Constant (const byte[$40]) main::henriette_name#0 = { fill( $40, 0) }
|
||||
Constant (const byte) main::henriette_id#1 = 7
|
||||
Constant (const byte[$40]) main::henriette_name#1 = main::$3
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Constant (const byte) idx#20 = 0
|
||||
Constant (const byte[]) DIGIT#0 = $0
|
||||
Constant (const byte) print_person::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte) print_person::person_id#0 = main::jesper_id#1
|
||||
Constant (const byte[$40]) print_person::person_name#0 = main::jesper_name#1
|
||||
Constant (const byte) print_person::person_id#1 = main::henriette_id#1
|
||||
Constant (const byte[$40]) print_person::person_name#1 = main::henriette_name#1
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Eliminating unused constant (const byte) main::jesper_id#0
|
||||
Eliminating unused constant (const byte[$40]) main::jesper_name#0
|
||||
Eliminating unused constant (const byte) main::henriette_id#0
|
||||
Eliminating unused constant (const byte[$40]) main::henriette_name#0
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Inlining constant with var siblings (const byte) print_person::i#0
|
||||
Inlining constant with var siblings (const byte) print_person::person_id#0
|
||||
Inlining constant with var siblings (const byte[$40]) print_person::person_name#0
|
||||
Inlining constant with var siblings (const byte) print_person::person_id#1
|
||||
Inlining constant with var siblings (const byte[$40]) print_person::person_name#1
|
||||
Inlining constant with var siblings (const byte) idx#20
|
||||
Constant inlined idx#20 = (byte) 0
|
||||
Constant inlined print_person::person_id#1 = (const byte) main::henriette_id#1
|
||||
Constant inlined print_person::person_id#0 = (const byte) main::jesper_id#1
|
||||
Constant inlined main::$2 = (const byte[$40]) main::jesper_name#1
|
||||
Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined print_person::person_name#1 = (const byte[$40]) main::henriette_name#1
|
||||
Constant inlined main::$3 = (const byte[$40]) main::henriette_name#1
|
||||
Constant inlined $0 = (const byte[]) DIGIT#0
|
||||
Constant inlined print_person::person_name#0 = (const byte[$40]) main::jesper_name#1
|
||||
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
|
||||
Adding NOP phi() at start of main::@2
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print_person:7 print_person:9
|
||||
|
||||
Created 5 initial phi equivalence classes
|
||||
Coalesced [8] idx#21 ← idx#16
|
||||
Coalesced [17] idx#22 ← idx#5
|
||||
Coalesced [26] print_person::i#4 ← print_person::i#1
|
||||
Coalesced [27] idx#23 ← idx#6
|
||||
Coalesced down to 5 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@2
|
||||
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
|
||||
|
||||
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_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte[$40]) print_person::person_name#4 ← phi( main/(const byte[$40]) main::jesper_name#1 main::@1/(const byte[$40]) main::henriette_name#1 )
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (byte) print_person::person_id#2 ← phi( main/(const byte) main::jesper_id#1 main::@1/(const byte) main::henriette_id#1 )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte[]) DIGIT
|
||||
(byte) Person::id
|
||||
(byte[$40]) Person::name
|
||||
(byte*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#13 3.0
|
||||
(byte) idx#14 9.75
|
||||
(byte) idx#16 1.0
|
||||
(byte) idx#4 3.0
|
||||
(byte) idx#5 4.0
|
||||
(byte) idx#6 11.0
|
||||
(void()) main()
|
||||
(byte) main::henriette_id
|
||||
(byte[$40]) main::henriette_name
|
||||
(byte) main::jesper_id
|
||||
(byte[$40]) main::jesper_name
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$40]) print_person::person_name)
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 22.0
|
||||
(byte) print_person::i#2 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 2.0
|
||||
(byte[$40]) print_person::person_name
|
||||
(byte[$40]) print_person::person_name#4 2.2
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print_person::person_id#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::person_name#4 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
Added variable idx#4 to zero page equivalence class [ idx#4 ]
|
||||
Complete equivalence classes
|
||||
[ print_person::person_id#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::person_name#4 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
[ idx#4 ]
|
||||
Allocated zp ZP_BYTE:2 [ print_person::person_id#2 ]
|
||||
Allocated zp ZP_BYTE:3 [ idx#13 idx#16 ]
|
||||
Allocated zp ZP_WORD:4 [ print_person::person_name#4 ]
|
||||
Allocated zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ]
|
||||
Allocated zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ]
|
||||
Allocated zp ZP_BYTE:8 [ idx#4 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// Works because the struct is only handled as a value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 8
|
||||
.label idx_5 = 7
|
||||
.label idx_6 = 7
|
||||
.label idx_13 = 3
|
||||
.label idx_14 = 7
|
||||
.label idx_16 = 3
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::jesper_name#1 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx_13
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#1 [phi:main->print_person#2] -- vbuz1=vbuc1
|
||||
lda #jesper_id
|
||||
sta.z print_person.person_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::henriette_name#1 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#1 [phi:main::@1->print_person#2] -- vbuz1=vbuc1
|
||||
lda #henriette_id
|
||||
sta.z print_person.person_id
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
henriette_name: .text "repsej"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte zeropage(2) person_id, byte[$40] zeropage(4) person_name)
|
||||
print_person: {
|
||||
.label i = 6
|
||||
.label person_id = 2
|
||||
.label person_name = 4
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
|
||||
ldy.z person_id
|
||||
lda DIGIT,y
|
||||
ldy.z idx_13
|
||||
sta SCREEN,y
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_13
|
||||
iny
|
||||
sty.z idx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx
|
||||
iny
|
||||
sty.z idx_5
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuz2_then_la1
|
||||
ldy.z i
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx_14
|
||||
sta SCREEN,y
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_14
|
||||
iny
|
||||
sty.z idx_16
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuz3
|
||||
ldx.z idx_14
|
||||
ldy.z i
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz1
|
||||
inc.z idx_6
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) [ idx#13 print_person::person_name#4 ] ( main:2::print_person:5 [ idx#13 print_person::person_name#4 ] main:2::print_person:7 [ idx#13 print_person::person_name#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ idx#13 idx#16 ]
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person_name#4 idx#4 ] ( main:2::print_person:5 [ print_person::person_name#4 idx#4 ] main:2::print_person:7 [ print_person::person_name#4 idx#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:8 [ idx#4 ]
|
||||
Statement [15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ]
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2) [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) [ idx#13 print_person::person_name#4 ] ( main:2::print_person:5 [ idx#13 print_person::person_name#4 ] main:2::print_person:7 [ idx#13 print_person::person_name#4 ] ) always clobbers reg byte a
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person_name#4 idx#4 ] ( main:2::print_person:5 [ print_person::person_name#4 idx#4 ] main:2::print_person:7 [ print_person::person_name#4 idx#4 ] ) always clobbers reg byte a
|
||||
Statement [15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2) [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ print_person::person_id#2 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ idx#13 idx#16 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:4 [ print_person::person_name#4 ] : zp ZP_WORD:4 ,
|
||||
Potential registers zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ] : zp ZP_BYTE:6 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ] : zp ZP_BYTE:7 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:8 [ idx#4 ] : zp ZP_BYTE:8 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print_person] 33: zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ] 2.2: zp ZP_WORD:4 [ print_person::person_name#4 ] 2: zp ZP_BYTE:2 [ print_person::person_id#2 ]
|
||||
Uplift Scope [] 24.75: zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ] 4: zp ZP_BYTE:3 [ idx#13 idx#16 ] 3: zp ZP_BYTE:8 [ idx#4 ]
|
||||
Uplift Scope [Person]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [print_person] best 545 combination reg byte y [ print_person::i#2 print_person::i#1 ] zp ZP_WORD:4 [ print_person::person_name#4 ] reg byte x [ print_person::person_id#2 ]
|
||||
Uplifting [] best 463 combination reg byte x [ idx#14 idx#5 idx#6 ] reg byte y [ idx#13 idx#16 ] reg byte x [ idx#4 ]
|
||||
Uplifting [Person] best 463 combination
|
||||
Uplifting [main] best 463 combination
|
||||
Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// Works because the struct is only handled as a value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::jesper_name#1 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#1 [phi:main->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::henriette_name#1 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#1 [phi:main::@1->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
henriette_name: .text "repsej"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte register(X) person_id, byte[$40] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuyy
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuyy_then_la1
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuxx
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b3
|
||||
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_person_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print_person_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_print_person:
|
||||
Removing instruction b3:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_b2:
|
||||
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[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(byte) Person::id
|
||||
(byte[$40]) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte y 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte y 1.0
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte) main::henriette_id
|
||||
(const byte) main::henriette_id#1 henriette_id = (byte) 7
|
||||
(byte[$40]) main::henriette_name
|
||||
(const byte[$40]) main::henriette_name#1 henriette_name = (string) "repsej"
|
||||
(byte) main::jesper_id
|
||||
(const byte) main::jesper_id#1 jesper_id = (byte) 4
|
||||
(byte[$40]) main::jesper_name
|
||||
(const byte[$40]) main::jesper_name#1 jesper_name = (string) "jesper"
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$40]) print_person::person_name)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 reg byte y 22.0
|
||||
(byte) print_person::i#2 reg byte y 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 reg byte x 2.0
|
||||
(byte[$40]) print_person::person_name
|
||||
(byte[$40]) print_person::person_name#4 person_name zp ZP_WORD:2 2.2
|
||||
|
||||
reg byte x [ print_person::person_id#2 ]
|
||||
reg byte y [ idx#13 idx#16 ]
|
||||
zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
reg byte y [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 382
|
||||
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// Works because the struct is only handled as a value
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// print_person(jesper)
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::jesper_name#1 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#1 [phi:main->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// main::@1
|
||||
// print_person(henriette)
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
// [9] phi (byte[$40]) print_person::person_name#4 = (const byte[$40]) main::henriette_name#1 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#1 [phi:main::@1->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
henriette_name: .text "repsej"
|
||||
.byte 0
|
||||
.fill 57, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte register(X) person_id, byte[$40] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
// SCREEN[idx++] = DIGIT[person.id]
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = DIGIT[person.id];
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuyy
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
// SCREEN[idx++] = ' '
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// print_person::@1
|
||||
b1:
|
||||
// for(byte i=0; person.name[i]; i++)
|
||||
// [15] if((byte) 0!=*((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuyy_then_la1
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
// print_person::@3
|
||||
// SCREEN[idx++] = ' '
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuxx
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
// print_person::@return
|
||||
// }
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// SCREEN[idx++] = person.name[i]
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$40]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = person.name[i];
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// for(byte i=0; person.name[i]; i++)
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
47
src/test/ref/struct-12.sym
Normal file
47
src/test/ref/struct-12.sym
Normal file
@ -0,0 +1,47 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(byte) Person::id
|
||||
(byte[$40]) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte y 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte y 1.0
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte) main::henriette_id
|
||||
(const byte) main::henriette_id#1 henriette_id = (byte) 7
|
||||
(byte[$40]) main::henriette_name
|
||||
(const byte[$40]) main::henriette_name#1 henriette_name = (string) "repsej"
|
||||
(byte) main::jesper_id
|
||||
(const byte) main::jesper_id#1 jesper_id = (byte) 4
|
||||
(byte[$40]) main::jesper_name
|
||||
(const byte[$40]) main::jesper_name#1 jesper_name = (string) "jesper"
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$40]) print_person::person_name)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 reg byte y 22.0
|
||||
(byte) print_person::i#2 reg byte y 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 reg byte x 2.0
|
||||
(byte[$40]) print_person::person_name
|
||||
(byte[$40]) print_person::person_name#4 person_name zp ZP_WORD:2 2.2
|
||||
|
||||
reg byte x [ print_person::person_id#2 ]
|
||||
reg byte y [ idx#13 idx#16 ]
|
||||
zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
reg byte y [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
88
src/test/ref/struct-ptr-28.asm
Normal file
88
src/test/ref/struct-ptr-28.asm
Normal file
@ -0,0 +1,88 @@
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.label jesper_id = 5
|
||||
.label jesper_name = 6
|
||||
.label henriette_id = 8
|
||||
.label henriette_name = 9
|
||||
lda #4
|
||||
sta.z jesper_id
|
||||
lda #<_4
|
||||
sta.z jesper_name
|
||||
lda #>_4
|
||||
sta.z jesper_name+1
|
||||
ldx #0
|
||||
lda #<jesper_id
|
||||
sta.z print_person.person
|
||||
lda #>jesper_id
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
lda #7
|
||||
sta.z henriette_id
|
||||
lda #<_5
|
||||
sta.z henriette_name
|
||||
lda #>_5
|
||||
sta.z henriette_name+1
|
||||
lda #<henriette_id
|
||||
sta.z print_person.person
|
||||
lda #>henriette_id
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
rts
|
||||
_4: .text "jesper"
|
||||
.byte 0
|
||||
_5: .text "henriette"
|
||||
.byte 0
|
||||
}
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
print_person: {
|
||||
.label i = 4
|
||||
.label person = 2
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
lda #0
|
||||
sta.z i
|
||||
b1:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne b2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
rts
|
||||
b2:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
inc.z i
|
||||
jmp b1
|
||||
}
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
47
src/test/ref/struct-ptr-28.cfg
Normal file
47
src/test/ref/struct-ptr-28.cfg
Normal file
@ -0,0 +1,47 @@
|
||||
@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] (byte) main::jesper_id#0 ← (byte) 4
|
||||
[5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4
|
||||
[6] call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[7] (byte) main::henriette_id#0 ← (byte) 7
|
||||
[8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5
|
||||
[9] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[10] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[11] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[11] (struct Person*) print_person::person#2 ← phi( main/(struct Person*)&(byte) main::jesper_id#0 main::@1/(struct Person*)&(byte) main::henriette_id#0 )
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2))
|
||||
[13] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[15] (byte) idx#5 ← ++ (byte) idx#4
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[16] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[16] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
|
||||
[19] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[20] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)
|
||||
[22] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[23] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
1028
src/test/ref/struct-ptr-28.log
Normal file
1028
src/test/ref/struct-ptr-28.log
Normal file
File diff suppressed because it is too large
Load Diff
52
src/test/ref/struct-ptr-28.sym
Normal file
52
src/test/ref/struct-ptr-28.sym
Normal file
@ -0,0 +1,52 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
|
||||
(byte) Person::id
|
||||
(byte[$10]) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte x 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte x 0.8
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(const string) main::$4 $4 = (string) "jesper"
|
||||
(const string) main::$5 $5 = (string) "henriette"
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(struct Person) main::henriette
|
||||
(byte) main::henriette_id
|
||||
(byte) main::henriette_id#0 henriette_id zp ZP_BYTE:8 20.0
|
||||
(byte[$10]) main::henriette_name
|
||||
(byte[$10]) main::henriette_name#0 henriette_name zp ZP_WORD:9 20.0
|
||||
(struct Person) main::jesper
|
||||
(byte) main::jesper_id
|
||||
(byte) main::jesper_id#0 jesper_id zp ZP_BYTE:5 20.0
|
||||
(byte[$10]) main::jesper_name
|
||||
(byte[$10]) main::jesper_name#0 jesper_name zp ZP_WORD:6 20.0
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 i zp ZP_BYTE:4 22.0
|
||||
(byte) print_person::i#2 i zp ZP_BYTE:4 11.0
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#2 person zp ZP_WORD:2
|
||||
|
||||
zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
reg byte x [ idx#13 idx#16 ]
|
||||
zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
zp ZP_BYTE:5 [ main::jesper_id#0 ]
|
||||
zp ZP_WORD:6 [ main::jesper_name#0 ]
|
||||
zp ZP_BYTE:8 [ main::henriette_id#0 ]
|
||||
zp ZP_WORD:9 [ main::henriette_name#0 ]
|
||||
reg byte x [ idx#4 ]
|
76
src/test/ref/struct-ptr-29.asm
Normal file
76
src/test/ref/struct-ptr-29.asm
Normal file
@ -0,0 +1,76 @@
|
||||
// Example of a struct containing a pointer
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const SIZEOF_STRUCT_PERSON = 3
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
ldx #0
|
||||
lda #<persons
|
||||
sta.z print_person.person
|
||||
lda #>persons
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
lda #<persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person
|
||||
lda #>persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
rts
|
||||
}
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
print_person: {
|
||||
.label i = 4
|
||||
.label person = 2
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
lda #0
|
||||
sta.z i
|
||||
b1:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne b2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
rts
|
||||
b2:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
inc.z i
|
||||
jmp b1
|
||||
}
|
||||
name1: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
persons:
|
||||
.byte 4
|
||||
.word name1
|
||||
.byte 7
|
||||
.word name2
|
45
src/test/ref/struct-ptr-29.cfg
Normal file
45
src/test/ref/struct-ptr-29.cfg
Normal file
@ -0,0 +1,45 @@
|
||||
@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_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (struct Person*) print_person::person#2 ← phi( main/(const struct Person[2]) persons#0 main::@1/(const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2))
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
959
src/test/ref/struct-ptr-29.log
Normal file
959
src/test/ref/struct-ptr-29.log
Normal file
@ -0,0 +1,959 @@
|
||||
Fixing pointer array-indexing *((struct Person[2]) persons + (number) 0)
|
||||
Fixing pointer array-indexing *((struct Person[2]) persons + (number) 1)
|
||||
Rewriting struct pointer member access *((struct Person*) print_person::person).id
|
||||
Rewriting struct pointer member access *((struct Person*) print_person::person).name
|
||||
Rewriting struct pointer member access *((struct Person*) print_person::person).name
|
||||
Warning! Adding boolean cast to non-boolean condition *(*((byte**) print_person::$1) + (byte) print_person::i)
|
||||
Identified constant variable (byte*) name1
|
||||
Identified constant variable (byte*) name2
|
||||
Culled Empty Block (label) print_person::@4
|
||||
Culled Empty Block (label) print_person::@5
|
||||
Culled Empty Block (label) print_person::@6
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) name1#0 ← (const string) $0
|
||||
(byte*) name2#0 ← (const string) $1
|
||||
(struct Person[2]) persons#0 ← { { (number) 4, (byte*) name1#0 }, { (number) 7, (byte*) name2#0 } }
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#18 ← phi( @2/(byte) idx#20 )
|
||||
(number~) main::$4 ← (number) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person*~) main::$0 ← & *((struct Person[2]) persons#0 + (number~) main::$4)
|
||||
(struct Person*) print_person::person#0 ← (struct Person*~) main::$0
|
||||
call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte) idx#10 ← phi( main/(byte) idx#8 )
|
||||
(byte) idx#0 ← (byte) idx#10
|
||||
(number~) main::$5 ← (number) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person*~) main::$2 ← & *((struct Person[2]) persons#0 + (number~) main::$5)
|
||||
(struct Person*) print_person::person#1 ← (struct Person*~) main::$2
|
||||
call print_person
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) idx#11 ← phi( main::@1/(byte) idx#8 )
|
||||
(byte) idx#1 ← (byte) idx#11
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
(byte) idx#12 ← phi( main::@2/(byte) idx#1 )
|
||||
(byte) idx#2 ← (byte) idx#12
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
(byte) idx#3 ← (number) 0
|
||||
(byte[]) DIGIT#0 ← (const string) $2
|
||||
to:@2
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
(byte) idx#13 ← phi( main/(byte) idx#18 main::@1/(byte) idx#0 )
|
||||
(struct Person*) print_person::person#2 ← phi( main/(struct Person*) print_person::person#0 main::@1/(struct Person*) print_person::person#1 )
|
||||
(byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
*((byte*) SCREEN#0 + (byte) idx#13) ← *((byte[]) DIGIT#0 + *((byte*) print_person::$0))
|
||||
(byte) idx#4 ← ++ (byte) idx#13
|
||||
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
(byte) idx#5 ← ++ (byte) idx#4
|
||||
(byte) print_person::i#0 ← (number) 0
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
(byte) idx#19 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
(byte) print_person::i#2 ← phi( print_person/(byte) print_person::i#0 print_person::@2/(byte) print_person::i#1 )
|
||||
(struct Person*) print_person::person#3 ← phi( print_person/(struct Person*) print_person::person#2 print_person::@2/(struct Person*) print_person::person#4 )
|
||||
(byte**) print_person::$1 ← (byte**)(struct Person*) print_person::person#3 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
(bool~) print_person::$3 ← (number) 0 != *(*((byte**) print_person::$1) + (byte) print_person::i#2)
|
||||
if((bool~) print_person::$3) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
(byte) idx#14 ← phi( print_person::@1/(byte) idx#19 )
|
||||
(byte) print_person::i#3 ← phi( print_person::@1/(byte) print_person::i#2 )
|
||||
(struct Person*) print_person::person#4 ← phi( print_person::@1/(struct Person*) print_person::person#3 )
|
||||
(byte**) print_person::$2 ← (byte**)(struct Person*) print_person::person#4 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
*((byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**) print_person::$2) + (byte) print_person::i#3)
|
||||
(byte) idx#6 ← ++ (byte) idx#14
|
||||
(byte) print_person::i#1 ← ++ (byte) print_person::i#3
|
||||
to:print_person::@1
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
(byte) idx#15 ← phi( print_person::@1/(byte) idx#19 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#15) ← (byte) ' '
|
||||
(byte) idx#7 ← ++ (byte) idx#15
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
(byte) idx#16 ← phi( print_person::@3/(byte) idx#7 )
|
||||
(byte) idx#8 ← (byte) idx#16
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#20 ← phi( @1/(byte) idx#3 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#17 ← phi( @2/(byte) idx#2 )
|
||||
(byte) idx#9 ← (byte) idx#17
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "jesper"
|
||||
(const string) $1 = (string) "repsej"
|
||||
(const string) $2 = (string) "0123456789"
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(byte[]) DIGIT#0
|
||||
(const byte) OFFSET_STRUCT_PERSON_ID = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_PERSON_NAME = (byte) 1
|
||||
(byte) Person::id
|
||||
(byte*) Person::name
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(const byte) SIZEOF_STRUCT_PERSON = (byte) 3
|
||||
(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#17
|
||||
(byte) idx#18
|
||||
(byte) idx#19
|
||||
(byte) idx#2
|
||||
(byte) idx#20
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(void()) main()
|
||||
(struct Person*~) main::$0
|
||||
(struct Person*~) main::$2
|
||||
(number~) main::$4
|
||||
(number~) main::$5
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(byte*) name1#0
|
||||
(byte*) name2
|
||||
(byte*) name2#0
|
||||
(struct Person[2]) persons
|
||||
(struct Person[2]) persons#0
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte*) print_person::$0
|
||||
(byte**) print_person::$1
|
||||
(byte**) print_person::$2
|
||||
(bool~) print_person::$3
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#0
|
||||
(byte) print_person::i#1
|
||||
(byte) print_person::i#2
|
||||
(byte) print_person::i#3
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#0
|
||||
(struct Person*) print_person::person#1
|
||||
(struct Person*) print_person::person#2
|
||||
(struct Person*) print_person::person#3
|
||||
(struct Person*) print_person::person#4
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (number~) main::$4 ← (number) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Adding number conversion cast (unumber) main::$4 in (number~) main::$4 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Adding number conversion cast (unumber) 1 in (number~) main::$5 ← (number) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Adding number conversion cast (unumber) main::$5 in (number~) main::$5 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#3 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) print_person::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print_person::$3 ← (number) 0 != *(*((byte**) print_person::$1) + (byte) print_person::i#2)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Added casts to value list in (struct Person[2]) persons#0 ← (struct Person[2]){ (struct Person){ (byte)(number) 4, (byte*) name1#0 }, (struct Person){ (byte)(number) 7, (byte*) name2#0 } }
|
||||
Successful SSA optimization PassNAddInitializerValueListTypeCasts
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#3 ← (unumber)(number) 0
|
||||
Inlining cast (byte) print_person::i#0 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 7
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to byte in (unumber~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Inferred type updated to byte in (unumber~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Alias (struct Person*) print_person::person#0 = (struct Person*~) main::$0
|
||||
Alias (byte) idx#0 = (byte) idx#10
|
||||
Alias (struct Person*) print_person::person#1 = (struct Person*~) main::$2
|
||||
Alias (byte) idx#1 = (byte) idx#11 (byte) idx#12 (byte) idx#2
|
||||
Alias (struct Person*) print_person::person#3 = (struct Person*) print_person::person#4
|
||||
Alias (byte) print_person::i#2 = (byte) print_person::i#3
|
||||
Alias (byte) idx#14 = (byte) idx#19 (byte) idx#15
|
||||
Alias (byte) idx#16 = (byte) idx#7 (byte) idx#8
|
||||
Alias (byte) idx#20 = (byte) idx#3
|
||||
Alias (byte) idx#17 = (byte) idx#9
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#18 (byte) idx#20
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#16
|
||||
Identical Phi Values (byte) idx#1 (byte) idx#16
|
||||
Identical Phi Values (struct Person*) print_person::person#3 (struct Person*) print_person::person#2
|
||||
Identical Phi Values (byte) idx#17 (byte) idx#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) print_person::$3 [32] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Rewriting array member address-of to pointer addition [5] (struct Person*) print_person::person#0 ← (struct Person[2]) persons#0 + (byte~) main::$4
|
||||
Rewriting array member address-of to pointer addition [11] (struct Person*) print_person::person#1 ← (struct Person[2]) persons#0 + (byte~) main::$5
|
||||
Successful SSA optimization PassNArrayElementAddressOfRewriting
|
||||
Constant right-side identified [4] (byte~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant right-side identified [10] (byte~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) name1#0 = $0
|
||||
Constant (const byte*) name2#0 = $1
|
||||
Constant (const byte) main::$4 = 0*SIZEOF_STRUCT_PERSON
|
||||
Constant (const byte) main::$5 = 1*SIZEOF_STRUCT_PERSON
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Constant (const byte) idx#20 = 0
|
||||
Constant (const byte[]) DIGIT#0 = $2
|
||||
Constant (const byte) print_person::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Converting *(pointer+n) to pointer[n] [24] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*) print_person::$0)) -- *((byte*)print_person::person#2 + OFFSET_STRUCT_PERSON_ID)
|
||||
Converting *(pointer+n) to pointer[n] [32] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2 -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Converting *(pointer+n) to pointer[n] [35] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**) print_person::$2) + (byte) print_person::i#2) -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_PERSON in
|
||||
Successful SSA optimization PassNSimplifyConstantZero
|
||||
Simplifying expression containing zero persons#0 in [5] (struct Person*) print_person::person#0 ← (struct Person[2]) persons#0 + (const byte) main::$4
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [23] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [24] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID))
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*) print_person::$0 and assignment [7] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2
|
||||
Eliminating unused variable (byte**) print_person::$1 and assignment [13] (byte**) print_person::$1 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused variable (byte**) print_person::$2 and assignment [15] (byte**) print_person::$2 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused constant (const byte) main::$4
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Identified constant from value list (struct Person) { id: (byte) 4, name: (const byte*) name1#0 }
|
||||
Identified constant from value list (struct Person) { id: (byte) 7, name: (const byte*) name2#0 }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Identified constant from value list (struct Person[2]) { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Constant (const struct Person[2]) persons#0 = { { id: 4, name: name1#0 }, { id: 7, name: name2#0 } }
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const struct Person*) print_person::person#0 = persons#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant right-side identified [1] (struct Person*) print_person::person#1 ← (const struct Person[2]) persons#0 + (const byte) main::$5
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const struct Person*) print_person::person#1 = persons#0+main::$5
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings (const byte) print_person::i#0
|
||||
Inlining constant with var siblings (const struct Person*) print_person::person#0
|
||||
Inlining constant with var siblings (const struct Person*) print_person::person#1
|
||||
Inlining constant with var siblings (const byte) idx#20
|
||||
Constant inlined idx#20 = (byte) 0
|
||||
Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined main::$5 = (byte) 1*(const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant inlined print_person::person#0 = (const struct Person[2]) persons#0
|
||||
Constant inlined $0 = (const byte*) name1#0
|
||||
Constant inlined $1 = (const byte*) name2#0
|
||||
Constant inlined $2 = (const byte[]) DIGIT#0
|
||||
Constant inlined print_person::person#1 = (const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON
|
||||
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
|
||||
Adding NOP phi() at start of main::@2
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print_person:7 print_person:9
|
||||
|
||||
Created 4 initial phi equivalence classes
|
||||
Coalesced [8] idx#21 ← idx#16
|
||||
Coalesced [17] idx#22 ← idx#5
|
||||
Coalesced [26] print_person::i#4 ← print_person::i#1
|
||||
Coalesced [27] idx#23 ← idx#6
|
||||
Coalesced down to 4 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@2
|
||||
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
|
||||
|
||||
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_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (struct Person*) print_person::person#2 ← phi( main/(const struct Person[2]) persons#0 main::@1/(const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2))
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte[]) DIGIT
|
||||
(byte) Person::id
|
||||
(byte*) Person::name
|
||||
(byte*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#13 3.0
|
||||
(byte) idx#14 9.75
|
||||
(byte) idx#16 1.0
|
||||
(byte) idx#4 3.0
|
||||
(byte) idx#5 4.0
|
||||
(byte) idx#6 11.0
|
||||
(void()) main()
|
||||
(byte*) name1
|
||||
(byte*) name2
|
||||
(struct Person[2]) persons
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 22.0
|
||||
(byte) print_person::i#2 11.0
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#2
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print_person::person#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
Added variable idx#4 to zero page equivalence class [ idx#4 ]
|
||||
Complete equivalence classes
|
||||
[ print_person::person#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
[ idx#4 ]
|
||||
Allocated zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
Allocated zp ZP_BYTE:4 [ idx#13 idx#16 ]
|
||||
Allocated zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
|
||||
Allocated zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
|
||||
Allocated zp ZP_BYTE:7 [ idx#4 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Example of a struct containing a pointer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_PERSON = 3
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 7
|
||||
.label idx_5 = 6
|
||||
.label idx_6 = 6
|
||||
.label idx_13 = 4
|
||||
.label idx_14 = 6
|
||||
.label idx_16 = 4
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx_13
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0 [phi:main->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons
|
||||
sta.z print_person.person
|
||||
lda #>persons
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON [phi:main::@1->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person
|
||||
lda #>persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// print_person
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
print_person: {
|
||||
.label i = 5
|
||||
.label person = 2
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_(_deref_pbuz2)
|
||||
ldx.z idx_13
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_13
|
||||
iny
|
||||
sty.z idx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx
|
||||
iny
|
||||
sty.z idx_5
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx_14
|
||||
sta SCREEN,y
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_14
|
||||
iny
|
||||
sty.z idx_16
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuz1=(pptz2_derefidx_vbuc2)_derefidx_vbuz3
|
||||
ldx.z idx_14
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz1
|
||||
inc.z idx_6
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
persons:
|
||||
.byte 4
|
||||
.word name1
|
||||
.byte 7
|
||||
.word name2
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) [ print_person::person#2 idx#13 ] ( main:2::print_person:5 [ print_person::person#2 idx#13 ] main:2::print_person:7 [ print_person::person#2 idx#13 ] ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#13 idx#16 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:4 [ idx#13 idx#16 ]
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person#2 idx#4 ] ( main:2::print_person:5 [ print_person::person#2 idx#4 ] main:2::print_person:7 [ print_person::person#2 idx#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:7 [ idx#4 ]
|
||||
Statement [15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) [ print_person::person#2 idx#13 ] ( main:2::print_person:5 [ print_person::person#2 idx#13 ] main:2::print_person:7 [ print_person::person#2 idx#13 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person#2 idx#4 ] ( main:2::print_person:5 [ print_person::person#2 idx#4 ] main:2::print_person:7 [ print_person::person#2 idx#4 ] ) always clobbers reg byte a
|
||||
Statement [15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp ZP_WORD:2 [ print_person::person#2 ] : zp ZP_WORD:2 ,
|
||||
Potential registers zp ZP_BYTE:4 [ idx#13 idx#16 ] : zp ZP_BYTE:4 , reg byte x ,
|
||||
Potential registers zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] : zp ZP_BYTE:5 , reg byte x ,
|
||||
Potential registers zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ] : zp ZP_BYTE:6 , reg byte x ,
|
||||
Potential registers zp ZP_BYTE:7 [ idx#4 ] : zp ZP_BYTE:7 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print_person] 33: zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] 0: zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
Uplift Scope [] 24.75: zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ] 4: zp ZP_BYTE:4 [ idx#13 idx#16 ] 3: zp ZP_BYTE:7 [ idx#4 ]
|
||||
Uplift Scope [Person]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [print_person] best 1091 combination zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
Uplifting [] best 1001 combination reg byte x [ idx#14 idx#5 idx#6 ] reg byte x [ idx#13 idx#16 ] reg byte x [ idx#4 ]
|
||||
Uplifting [Person] best 1001 combination
|
||||
Uplifting [main] best 1001 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
|
||||
Uplifting [print_person] best 1001 combination zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
|
||||
Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Example of a struct containing a pointer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_PERSON = 3
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0 [phi:main->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons
|
||||
sta.z print_person.person
|
||||
lda #>persons
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON [phi:main::@1->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person
|
||||
lda #>persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// print_person
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
print_person: {
|
||||
.label i = 4
|
||||
.label person = 2
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_(_deref_pbuz1)
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=(pptz1_derefidx_vbuc2)_derefidx_vbuz2
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
persons:
|
||||
.byte 4
|
||||
.word name1
|
||||
.byte 7
|
||||
.word name2
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b3
|
||||
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_person_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print_person_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_print_person:
|
||||
Removing instruction b3:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_b2:
|
||||
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[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
|
||||
(byte) Person::id
|
||||
(byte*) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(const byte) SIZEOF_STRUCT_PERSON SIZEOF_STRUCT_PERSON = (byte) 3
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte x 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte x 1.0
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(const byte*) name1#0 name1 = (string) "jesper"
|
||||
(byte*) name2
|
||||
(const byte*) name2#0 name2 = (string) "repsej"
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 i zp ZP_BYTE:4 22.0
|
||||
(byte) print_person::i#2 i zp ZP_BYTE:4 11.0
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#2 person zp ZP_WORD:2
|
||||
|
||||
zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
reg byte x [ idx#13 idx#16 ]
|
||||
zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 920
|
||||
|
||||
// File Comments
|
||||
// Example of a struct containing a pointer
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_PERSON = 3
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// print_person(&persons[0])
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0 [phi:main->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons
|
||||
sta.z print_person.person
|
||||
lda #>persons
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// main::@1
|
||||
// print_person(&persons[1])
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
|
||||
// [9] phi (struct Person*) print_person::person#2 = (const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON [phi:main::@1->print_person#1] -- pssz1=pssc1
|
||||
lda #<persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person
|
||||
lda #>persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// print_person
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
print_person: {
|
||||
.label i = 4
|
||||
.label person = 2
|
||||
// SCREEN[idx++] = DIGIT[person->id]
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_(_deref_pbuz1)
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = DIGIT[person->id];
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// SCREEN[idx++] = ' '
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
// print_person::@1
|
||||
b1:
|
||||
// for(byte i=0; person->name[i]; i++)
|
||||
// [15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne b2
|
||||
// print_person::@3
|
||||
// SCREEN[idx++] = ' '
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// print_person::@return
|
||||
// }
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// SCREEN[idx++] = person->name[i]
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=(pptz1_derefidx_vbuc2)_derefidx_vbuz2
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = person->name[i];
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// for(byte i=0; person->name[i]; i++)
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
persons:
|
||||
.byte 4
|
||||
.word name1
|
||||
.byte 7
|
||||
.word name2
|
||||
|
43
src/test/ref/struct-ptr-29.sym
Normal file
43
src/test/ref/struct-ptr-29.sym
Normal file
@ -0,0 +1,43 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
|
||||
(byte) Person::id
|
||||
(byte*) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(const byte) SIZEOF_STRUCT_PERSON SIZEOF_STRUCT_PERSON = (byte) 3
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte x 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte x 1.0
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(const byte*) name1#0 name1 = (string) "jesper"
|
||||
(byte*) name2
|
||||
(const byte*) name2#0 name2 = (string) "repsej"
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 i zp ZP_BYTE:4 22.0
|
||||
(byte) print_person::i#2 i zp ZP_BYTE:4 11.0
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#2 person zp ZP_WORD:2
|
||||
|
||||
zp ZP_WORD:2 [ print_person::person#2 ]
|
||||
reg byte x [ idx#13 idx#16 ]
|
||||
zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
59
src/test/ref/struct-ptr-30.asm
Normal file
59
src/test/ref/struct-ptr-30.asm
Normal file
@ -0,0 +1,59 @@
|
||||
// Test a struct array initialized with to few members (zero-filled for the rest)
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 2
|
||||
main: {
|
||||
lda #0
|
||||
sta.z idx
|
||||
tax
|
||||
b1:
|
||||
txa
|
||||
asl
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
tay
|
||||
lda points,y
|
||||
sta.z print.p_x
|
||||
lda points+OFFSET_STRUCT_POINT_Y,y
|
||||
sta.z print.p_y
|
||||
lda points+OFFSET_STRUCT_POINT_Y+1,y
|
||||
sta.z print.p_y+1
|
||||
jsr print
|
||||
inx
|
||||
cpx #4
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
// print(byte zeropage(3) p_x, signed word zeropage(4) p_y)
|
||||
print: {
|
||||
.label p_x = 3
|
||||
.label p_y = 4
|
||||
lda.z p_x
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
iny
|
||||
lda.z p_y
|
||||
sta SCREEN,y
|
||||
iny
|
||||
lda.z p_y+1
|
||||
sta SCREEN,y
|
||||
iny
|
||||
lda #' '
|
||||
sta SCREEN,y
|
||||
iny
|
||||
sty.z idx
|
||||
rts
|
||||
}
|
||||
points:
|
||||
.byte 1
|
||||
.word $83f
|
||||
.byte 3
|
||||
.word $107e
|
||||
.byte 0
|
||||
.word 0
|
||||
.byte 0
|
||||
.word 0
|
43
src/test/ref/struct-ptr-30.cfg
Normal file
43
src/test/ref/struct-ptr-30.cfg
Normal file
@ -0,0 +1,43 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[5] (byte) idx#14 ← phi( main/(byte) 0 main::@2/(byte) idx#12 )
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
|
||||
[6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1
|
||||
[7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2
|
||||
[8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2)
|
||||
[9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2)
|
||||
[10] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[11] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[12] if((byte) main::i#1!=(byte) 4) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[13] return
|
||||
to:@return
|
||||
print: scope:[print] from main::@1
|
||||
[14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0
|
||||
[15] (byte) idx#3 ← ++ (byte) idx#14
|
||||
[16] (byte~) print::$0 ← < (signed word) print::p_y#0
|
||||
[17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0
|
||||
[18] (byte) idx#4 ← ++ (byte) idx#3
|
||||
[19] (byte~) print::$1 ← > (signed word) print::p_y#0
|
||||
[20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1
|
||||
[21] (byte) idx#5 ← ++ (byte) idx#4
|
||||
[22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' '
|
||||
[23] (byte) idx#12 ← ++ (byte) idx#5
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[24] return
|
||||
to:@return
|
865
src/test/ref/struct-ptr-30.log
Normal file
865
src/test/ref/struct-ptr-30.log
Normal file
@ -0,0 +1,865 @@
|
||||
Fixing pointer array-indexing *((struct Point[4]) points + (byte) main::i)
|
||||
Created struct value member variable (byte) print::p_x
|
||||
Created struct value member variable (signed word) print::p_y
|
||||
Converted struct value to member variables (struct Point) print::p
|
||||
Converted procedure struct value parameter to member unwinding (void()) print((byte) print::p_x , (signed word) print::p_y)
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print *((byte*) main::$3 + (byte~) main::$2) *((signed word*) main::$4 + (byte~) main::$2)
|
||||
Replacing struct member reference (struct Point) print::p.x with member unwinding reference (byte) print::p_x
|
||||
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (signed word) print::p_y
|
||||
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (signed word) print::p_y
|
||||
Culled Empty Block (label) main::@2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(struct Point[4]) points#0 ← { { (number) 1, (number) $83f }, { (number) 3, (number) $107e } }
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#16 ← phi( @2/(byte) idx#15 )
|
||||
(byte) main::i#0 ← (byte) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
(byte) idx#14 ← phi( main/(byte) idx#16 main::@3/(byte) idx#0 )
|
||||
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
|
||||
(byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT
|
||||
(byte) print::p_x#0 ← *((byte*) main::$3 + (byte~) main::$2)
|
||||
(signed word) print::p_y#0 ← *((signed word*) main::$4 + (byte~) main::$2)
|
||||
call print
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@1
|
||||
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
|
||||
(byte) idx#9 ← phi( main::@1/(byte) idx#7 )
|
||||
(byte) idx#0 ← (byte) idx#9
|
||||
(byte*) main::$3 ← (byte*)(struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
(signed word*) main::$4 ← (signed word*)(struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
(byte) main::i#1 ← (byte) main::i#3 + rangenext(0,3)
|
||||
(bool~) main::$1 ← (byte) main::i#1 != rangelast(0,3)
|
||||
if((bool~) main::$1) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
(byte) idx#10 ← phi( main::@3/(byte) idx#0 )
|
||||
(byte) idx#1 ← (byte) idx#10
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
(byte) idx#2 ← (number) 0
|
||||
to:@2
|
||||
print: scope:[print] from main::@1
|
||||
(signed word) print::p_y#1 ← phi( main::@1/(signed word) print::p_y#0 )
|
||||
(byte) idx#11 ← phi( main::@1/(byte) idx#14 )
|
||||
(byte) print::p_x#1 ← phi( main::@1/(byte) print::p_x#0 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#11) ← (byte) print::p_x#1
|
||||
(byte) idx#3 ← ++ (byte) idx#11
|
||||
(byte~) print::$0 ← < (signed word) print::p_y#1
|
||||
*((byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0
|
||||
(byte) idx#4 ← ++ (byte) idx#3
|
||||
(byte~) print::$1 ← > (signed word) print::p_y#1
|
||||
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1
|
||||
(byte) idx#5 ← ++ (byte) idx#4
|
||||
*((byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' '
|
||||
(byte) idx#6 ← ++ (byte) idx#5
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
(byte) idx#12 ← phi( print/(byte) idx#6 )
|
||||
(byte) idx#7 ← (byte) idx#12
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#15 ← phi( @1/(byte) idx#2 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#13 ← phi( @2/(byte) idx#1 )
|
||||
(byte) idx#8 ← (byte) idx#13
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(signed word) Point::y
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(const byte) SIZEOF_STRUCT_POINT = (byte) 3
|
||||
(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()
|
||||
(bool~) main::$1
|
||||
(byte~) main::$2
|
||||
(byte*) main::$3
|
||||
(signed word*) main::$4
|
||||
(label) main::@1
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
(byte) main::i#3
|
||||
(struct Point[4]) points
|
||||
(struct Point[4]) points#0
|
||||
(void()) print((byte) print::p_x , (signed word) print::p_y)
|
||||
(byte~) print::$0
|
||||
(byte~) print::$1
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0
|
||||
(byte) print::p_x#1
|
||||
(signed word) print::p_y
|
||||
(signed word) print::p_y#0
|
||||
(signed word) print::p_y#1
|
||||
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#2 ← (number) 0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Added casts to value list in (struct Point[4]) points#0 ← (struct Point[4]){ (struct Point){ (byte)(number) 1, (signed word)(number) $83f }, (struct Point){ (byte)(number) 3, (signed word)(number) $107e } }
|
||||
Successful SSA optimization PassNAddInitializerValueListTypeCasts
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#2 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast $83f
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast $107e
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte) main::i#2 = (byte) main::i#3
|
||||
Alias (byte) idx#0 = (byte) idx#9 (byte) idx#10 (byte) idx#1
|
||||
Alias (byte) idx#12 = (byte) idx#6 (byte) idx#7
|
||||
Alias (byte) idx#15 = (byte) idx#2
|
||||
Alias (byte) idx#13 = (byte) idx#8
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#16 (byte) idx#15
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#12
|
||||
Identical Phi Values (byte) print::p_x#1 (byte) print::p_x#0
|
||||
Identical Phi Values (byte) idx#11 (byte) idx#14
|
||||
Identical Phi Values (signed word) print::p_y#1 (signed word) print::p_y#0
|
||||
Identical Phi Values (byte) idx#13 (byte) idx#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) main::$1 [14] if((byte) main::i#1!=rangelast(0,3)) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Identified constant from value list (struct Point) { x: (byte) 1, y: (signed word) $83f }
|
||||
Identified constant from value list (struct Point) { x: (byte) 3, y: (signed word) $107e }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Identified constant from value list (struct Point[4]) { { x: (byte) 1, y: (signed word) $83f }, { x: (byte) 3, y: (signed word) $107e } }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Constant (const struct Point[4]) points#0 = { { x: 1, y: $83f }, { x: 3, y: $107e } }
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Constant (const byte) idx#15 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)points#0 in [10] (byte*) main::$3 ← (byte*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Constant value identified (signed word*)points#0 in [11] (signed word*) main::$4 ← (signed word*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Resolved ranged next value [12] main::i#1 ← ++ main::i#2 to ++
|
||||
Resolved ranged comparison value [14] if(main::i#1!=rangelast(0,3)) goto main::@1 to (number) 4
|
||||
Simplifying expression containing zero (byte*)points#0 in [10] (byte*) main::$3 ← (byte*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Adding number conversion cast (unumber) 4 in if((byte) main::i#1!=(number) 4) goto main::@1
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant integer cast 4
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 4
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant right-side identified [6] (signed word*) main::$4 ← (signed word*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$3 = (byte*)points#0
|
||||
Constant (const signed word*) main::$4 = (signed word*)points#0+OFFSET_STRUCT_POINT_Y
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Rewriting multiplication to use shift and addition[1] (byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT
|
||||
Inlining constant with var siblings (const byte) main::i#0
|
||||
Inlining constant with var siblings (const byte) idx#15
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::$3 = (byte*)(const struct Point[4]) points#0
|
||||
Constant inlined main::$4 = (signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y
|
||||
Constant inlined idx#15 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Alias (byte~) main::$2 = (byte) main::$6
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Added new block during phi lifting main::@4(between main::@3 and main::@1)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print:12
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [16] main::i#4 ← main::i#1
|
||||
Coalesced [17] idx#17 ← idx#12
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@4
|
||||
Renumbering block @2 to @1
|
||||
Renumbering block main::@3 to main::@2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
[5] (byte) idx#14 ← phi( main/(byte) 0 main::@2/(byte) idx#12 )
|
||||
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
|
||||
[6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1
|
||||
[7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2
|
||||
[8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2)
|
||||
[9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2)
|
||||
[10] call print
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[11] (byte) main::i#1 ← ++ (byte) main::i#2
|
||||
[12] if((byte) main::i#1!=(byte) 4) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[13] return
|
||||
to:@return
|
||||
print: scope:[print] from main::@1
|
||||
[14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0
|
||||
[15] (byte) idx#3 ← ++ (byte) idx#14
|
||||
[16] (byte~) print::$0 ← < (signed word) print::p_y#0
|
||||
[17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0
|
||||
[18] (byte) idx#4 ← ++ (byte) idx#3
|
||||
[19] (byte~) print::$1 ← > (signed word) print::p_y#0
|
||||
[20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1
|
||||
[21] (byte) idx#5 ← ++ (byte) idx#4
|
||||
[22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' '
|
||||
[23] (byte) idx#12 ← ++ (byte) idx#5
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print
|
||||
[24] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) Point::x
|
||||
(signed word) Point::y
|
||||
(byte*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#12 2.6
|
||||
(byte) idx#14 2.5
|
||||
(byte) idx#3 2.0
|
||||
(byte) idx#4 2.0
|
||||
(byte) idx#5 3.0
|
||||
(void()) main()
|
||||
(byte~) main::$2 16.5
|
||||
(byte) main::$5 22.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 16.5
|
||||
(byte) main::i#2 7.333333333333333
|
||||
(struct Point[4]) points
|
||||
(void()) print((byte) print::p_x , (signed word) print::p_y)
|
||||
(byte~) print::$0 4.0
|
||||
(byte~) print::$1 4.0
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 6.5
|
||||
(signed word) print::p_y
|
||||
(signed word) print::p_y#0 2.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ idx#14 idx#12 ]
|
||||
Added variable main::$5 to zero page equivalence class [ main::$5 ]
|
||||
Added variable main::$2 to zero page equivalence class [ main::$2 ]
|
||||
Added variable print::p_x#0 to zero page equivalence class [ print::p_x#0 ]
|
||||
Added variable print::p_y#0 to zero page equivalence class [ print::p_y#0 ]
|
||||
Added variable idx#3 to zero page equivalence class [ idx#3 ]
|
||||
Added variable print::$0 to zero page equivalence class [ print::$0 ]
|
||||
Added variable idx#4 to zero page equivalence class [ idx#4 ]
|
||||
Added variable print::$1 to zero page equivalence class [ print::$1 ]
|
||||
Added variable idx#5 to zero page equivalence class [ idx#5 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ idx#14 idx#12 ]
|
||||
[ main::$5 ]
|
||||
[ main::$2 ]
|
||||
[ print::p_x#0 ]
|
||||
[ print::p_y#0 ]
|
||||
[ idx#3 ]
|
||||
[ print::$0 ]
|
||||
[ idx#4 ]
|
||||
[ print::$1 ]
|
||||
[ idx#5 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ idx#14 idx#12 ]
|
||||
Allocated zp ZP_BYTE:4 [ main::$5 ]
|
||||
Allocated zp ZP_BYTE:5 [ main::$2 ]
|
||||
Allocated zp ZP_BYTE:6 [ print::p_x#0 ]
|
||||
Allocated zp ZP_WORD:7 [ print::p_y#0 ]
|
||||
Allocated zp ZP_BYTE:9 [ idx#3 ]
|
||||
Allocated zp ZP_BYTE:10 [ print::$0 ]
|
||||
Allocated zp ZP_BYTE:11 [ idx#4 ]
|
||||
Allocated zp ZP_BYTE:12 [ print::$1 ]
|
||||
Allocated zp ZP_BYTE:13 [ idx#5 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Test a struct array initialized with to few members (zero-filled for the rest)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 9
|
||||
.label idx_4 = $b
|
||||
.label idx_5 = $d
|
||||
.label idx_12 = 3
|
||||
.label idx_14 = 3
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label _2 = 5
|
||||
.label i = 2
|
||||
.label _5 = 4
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx_14
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
sta.z _5
|
||||
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3
|
||||
lda.z _5
|
||||
clc
|
||||
adc.z i
|
||||
sta.z _2
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuz2
|
||||
ldy.z _2
|
||||
lda points,y
|
||||
sta.z print.p_x
|
||||
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuz2
|
||||
ldy.z _2
|
||||
lda points+OFFSET_STRUCT_POINT_Y,y
|
||||
sta.z print.p_y
|
||||
lda points+OFFSET_STRUCT_POINT_Y+1,y
|
||||
sta.z print.p_y+1
|
||||
// [10] call print
|
||||
jsr print
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #4
|
||||
cmp.z i
|
||||
bne b1_from_b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte zeropage(6) p_x, signed word zeropage(7) p_y)
|
||||
print: {
|
||||
.label _0 = $a
|
||||
.label _1 = $c
|
||||
.label p_x = 6
|
||||
.label p_y = 7
|
||||
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda.z p_x
|
||||
ldy.z idx_14
|
||||
sta SCREEN,y
|
||||
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_14
|
||||
iny
|
||||
sty.z idx
|
||||
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuz1=_lo_vwsz2
|
||||
lda.z p_y
|
||||
sta.z _0
|
||||
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda.z _0
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx
|
||||
iny
|
||||
sty.z idx_4
|
||||
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuz1=_hi_vwsz2
|
||||
lda.z p_y+1
|
||||
sta.z _1
|
||||
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda.z _1
|
||||
ldy.z idx_4
|
||||
sta SCREEN,y
|
||||
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_4
|
||||
iny
|
||||
sty.z idx_5
|
||||
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx_5
|
||||
sta SCREEN,y
|
||||
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_5
|
||||
iny
|
||||
sty.z idx_12
|
||||
jmp breturn
|
||||
// print::@return
|
||||
breturn:
|
||||
// [24] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points:
|
||||
.byte 1
|
||||
.word $83f
|
||||
.byte 3
|
||||
.word $107e
|
||||
.byte 0
|
||||
.word 0
|
||||
.byte 0
|
||||
.word 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 [ main::i#2 idx#14 main::$5 ] ( main:2 [ main::i#2 idx#14 main::$5 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ idx#14 idx#12 ]
|
||||
Statement [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 [ main::i#2 idx#14 main::$2 ] ( main:2 [ main::i#2 idx#14 main::$2 ] ) always clobbers reg byte a
|
||||
Statement [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ( main:2 [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ print::p_x#0 ]
|
||||
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 [ idx#14 print::p_y#0 ] ( main:2::print:10 [ main::i#2 idx#14 print::p_y#0 ] ) always clobbers reg byte a
|
||||
Statement [16] (byte~) print::$0 ← < (signed word) print::p_y#0 [ print::p_y#0 idx#3 print::$0 ] ( main:2::print:10 [ main::i#2 print::p_y#0 idx#3 print::$0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ idx#3 ]
|
||||
Statement [19] (byte~) print::$1 ← > (signed word) print::p_y#0 [ idx#4 print::$1 ] ( main:2::print:10 [ main::i#2 idx#4 print::$1 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:11 [ idx#4 ]
|
||||
Statement [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' [ idx#5 ] ( main:2::print:10 [ main::i#2 idx#5 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:13 [ idx#5 ]
|
||||
Statement [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 [ main::i#2 idx#14 main::$5 ] ( main:2 [ main::i#2 idx#14 main::$5 ] ) always clobbers reg byte a
|
||||
Statement [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 [ main::i#2 idx#14 main::$2 ] ( main:2 [ main::i#2 idx#14 main::$2 ] ) always clobbers reg byte a
|
||||
Statement [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ( main:2 [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 [ idx#14 print::p_y#0 ] ( main:2::print:10 [ main::i#2 idx#14 print::p_y#0 ] ) always clobbers reg byte a
|
||||
Statement [16] (byte~) print::$0 ← < (signed word) print::p_y#0 [ print::p_y#0 idx#3 print::$0 ] ( main:2::print:10 [ main::i#2 print::p_y#0 idx#3 print::$0 ] ) always clobbers reg byte a
|
||||
Statement [19] (byte~) print::$1 ← > (signed word) print::p_y#0 [ idx#4 print::$1 ] ( main:2::print:10 [ main::i#2 idx#4 print::$1 ] ) always clobbers reg byte a
|
||||
Statement [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' [ idx#5 ] ( main:2::print:10 [ main::i#2 idx#5 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ idx#14 idx#12 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ main::$5 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:5 [ main::$2 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:6 [ print::p_x#0 ] : zp ZP_BYTE:6 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:7 [ print::p_y#0 ] : zp ZP_WORD:7 ,
|
||||
Potential registers zp ZP_BYTE:9 [ idx#3 ] : zp ZP_BYTE:9 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:10 [ print::$0 ] : zp ZP_BYTE:10 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:11 [ idx#4 ] : zp ZP_BYTE:11 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:12 [ print::$1 ] : zp ZP_BYTE:12 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:13 [ idx#5 ] : zp ZP_BYTE:13 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 23.83: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:4 [ main::$5 ] 16.5: zp ZP_BYTE:5 [ main::$2 ]
|
||||
Uplift Scope [print] 6.5: zp ZP_BYTE:6 [ print::p_x#0 ] 4: zp ZP_BYTE:10 [ print::$0 ] 4: zp ZP_BYTE:12 [ print::$1 ] 2.5: zp ZP_WORD:7 [ print::p_y#0 ]
|
||||
Uplift Scope [] 5.1: zp ZP_BYTE:3 [ idx#14 idx#12 ] 3: zp ZP_BYTE:13 [ idx#5 ] 2: zp ZP_BYTE:9 [ idx#3 ] 2: zp ZP_BYTE:11 [ idx#4 ]
|
||||
Uplift Scope [Point]
|
||||
|
||||
Uplifting [main] best 794 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$5 ] reg byte y [ main::$2 ]
|
||||
Uplifting [print] best 782 combination zp ZP_BYTE:6 [ print::p_x#0 ] reg byte a [ print::$0 ] reg byte a [ print::$1 ] zp ZP_WORD:7 [ print::p_y#0 ]
|
||||
Uplifting [] best 755 combination zp ZP_BYTE:3 [ idx#14 idx#12 ] reg byte y [ idx#5 ] reg byte y [ idx#3 ] reg byte y [ idx#4 ]
|
||||
Uplifting [Point] best 755 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:6 [ print::p_x#0 ]
|
||||
Uplifting [print] best 755 combination zp ZP_BYTE:6 [ print::p_x#0 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ idx#14 idx#12 ]
|
||||
Uplifting [] best 755 combination zp ZP_BYTE:3 [ idx#14 idx#12 ]
|
||||
Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ idx#14 idx#12 ]
|
||||
Allocated (was zp ZP_BYTE:6) zp ZP_BYTE:3 [ print::p_x#0 ]
|
||||
Allocated (was zp ZP_WORD:7) zp ZP_WORD:4 [ print::p_y#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a struct array initialized with to few members (zero-filled for the rest)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 2
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp b1
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
b1_from_b2:
|
||||
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
|
||||
txa
|
||||
asl
|
||||
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
tay
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuyy
|
||||
lda points,y
|
||||
sta.z print.p_x
|
||||
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuyy
|
||||
lda points+OFFSET_STRUCT_POINT_Y,y
|
||||
sta.z print.p_y
|
||||
lda points+OFFSET_STRUCT_POINT_Y+1,y
|
||||
sta.z print.p_y+1
|
||||
// [10] call print
|
||||
jsr print
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #4
|
||||
bne b1_from_b2
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte zeropage(3) p_x, signed word zeropage(4) p_y)
|
||||
print: {
|
||||
.label p_x = 3
|
||||
.label p_y = 4
|
||||
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda.z p_x
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuz1
|
||||
ldy.z idx
|
||||
iny
|
||||
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuaa=_lo_vwsz1
|
||||
lda.z p_y
|
||||
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuyy=vbuaa
|
||||
sta SCREEN,y
|
||||
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuaa=_hi_vwsz1
|
||||
lda.z p_y+1
|
||||
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuyy=vbuaa
|
||||
sta SCREEN,y
|
||||
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,y
|
||||
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuyy
|
||||
iny
|
||||
sty.z idx
|
||||
jmp breturn
|
||||
// print::@return
|
||||
breturn:
|
||||
// [24] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points:
|
||||
.byte 1
|
||||
.word $83f
|
||||
.byte 3
|
||||
.word $107e
|
||||
.byte 0
|
||||
.word 0
|
||||
.byte 0
|
||||
.word 0
|
||||
|
||||
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
|
||||
Replacing instruction ldx #0 with TAX
|
||||
Removing instruction ldy.z idx
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label b1_from_b2 with b1
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_b2:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
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 jmp b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(signed word) Point::y
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 idx zp ZP_BYTE:2 2.6
|
||||
(byte) idx#14 idx zp ZP_BYTE:2 2.5
|
||||
(byte) idx#3 reg byte y 2.0
|
||||
(byte) idx#4 reg byte y 2.0
|
||||
(byte) idx#5 reg byte y 3.0
|
||||
(void()) main()
|
||||
(byte~) main::$2 reg byte y 16.5
|
||||
(byte) main::$5 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 7.333333333333333
|
||||
(struct Point[4]) points
|
||||
(const struct Point[4]) points#0 points = { { x: (byte) 1, y: (signed word) $83f }, { x: (byte) 3, y: (signed word) $107e } }
|
||||
(void()) print((byte) print::p_x , (signed word) print::p_y)
|
||||
(byte~) print::$0 reg byte a 4.0
|
||||
(byte~) print::$1 reg byte a 4.0
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 p_x zp ZP_BYTE:3 6.5
|
||||
(signed word) print::p_y
|
||||
(signed word) print::p_y#0 p_y zp ZP_WORD:4 2.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ idx#14 idx#12 ]
|
||||
reg byte a [ main::$5 ]
|
||||
reg byte y [ main::$2 ]
|
||||
zp ZP_BYTE:3 [ print::p_x#0 ]
|
||||
zp ZP_WORD:4 [ print::p_y#0 ]
|
||||
reg byte y [ idx#3 ]
|
||||
reg byte a [ print::$0 ]
|
||||
reg byte y [ idx#4 ]
|
||||
reg byte a [ print::$1 ]
|
||||
reg byte y [ idx#5 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 617
|
||||
|
||||
// File Comments
|
||||
// Test a struct array initialized with to few members (zero-filled for the rest)
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 2
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx
|
||||
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
|
||||
tax
|
||||
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
|
||||
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
|
||||
// main::@1
|
||||
b1:
|
||||
// print(points[i])
|
||||
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
|
||||
txa
|
||||
asl
|
||||
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
tay
|
||||
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuyy
|
||||
lda points,y
|
||||
sta.z print.p_x
|
||||
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuyy
|
||||
lda points+OFFSET_STRUCT_POINT_Y,y
|
||||
sta.z print.p_y
|
||||
lda points+OFFSET_STRUCT_POINT_Y+1,y
|
||||
sta.z print.p_y+1
|
||||
// [10] call print
|
||||
jsr print
|
||||
// main::@2
|
||||
// for ( char i: 0..3)
|
||||
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #4
|
||||
bne b1
|
||||
// main::@return
|
||||
// }
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// print
|
||||
// print(byte zeropage(3) p_x, signed word zeropage(4) p_y)
|
||||
print: {
|
||||
.label p_x = 3
|
||||
.label p_y = 4
|
||||
// SCREEN[idx++] = p.x
|
||||
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda.z p_x
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = p.x;
|
||||
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuz1
|
||||
iny
|
||||
// <p.y
|
||||
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuaa=_lo_vwsz1
|
||||
lda.z p_y
|
||||
// SCREEN[idx++] = <p.y
|
||||
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuyy=vbuaa
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = <p.y;
|
||||
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// >p.y
|
||||
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuaa=_hi_vwsz1
|
||||
lda.z p_y+1
|
||||
// SCREEN[idx++] = >p.y
|
||||
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuyy=vbuaa
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = >p.y;
|
||||
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// SCREEN[idx++] = ' '
|
||||
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuyy
|
||||
iny
|
||||
sty.z idx
|
||||
// print::@return
|
||||
// }
|
||||
// [24] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
points:
|
||||
.byte 1
|
||||
.word $83f
|
||||
.byte 3
|
||||
.word $107e
|
||||
.byte 0
|
||||
.word 0
|
||||
.byte 0
|
||||
.word 0
|
||||
|
46
src/test/ref/struct-ptr-30.sym
Normal file
46
src/test/ref/struct-ptr-30.sym
Normal file
@ -0,0 +1,46 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1
|
||||
(byte) Point::x
|
||||
(signed word) Point::y
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#12 idx zp ZP_BYTE:2 2.6
|
||||
(byte) idx#14 idx zp ZP_BYTE:2 2.5
|
||||
(byte) idx#3 reg byte y 2.0
|
||||
(byte) idx#4 reg byte y 2.0
|
||||
(byte) idx#5 reg byte y 3.0
|
||||
(void()) main()
|
||||
(byte~) main::$2 reg byte y 16.5
|
||||
(byte) main::$5 reg byte a 22.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 16.5
|
||||
(byte) main::i#2 reg byte x 7.333333333333333
|
||||
(struct Point[4]) points
|
||||
(const struct Point[4]) points#0 points = { { x: (byte) 1, y: (signed word) $83f }, { x: (byte) 3, y: (signed word) $107e } }
|
||||
(void()) print((byte) print::p_x , (signed word) print::p_y)
|
||||
(byte~) print::$0 reg byte a 4.0
|
||||
(byte~) print::$1 reg byte a 4.0
|
||||
(label) print::@return
|
||||
(struct Point) print::p
|
||||
(byte) print::p_x
|
||||
(byte) print::p_x#0 p_x zp ZP_BYTE:3 6.5
|
||||
(signed word) print::p_y
|
||||
(signed word) print::p_y#0 p_y zp ZP_WORD:4 2.5
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ idx#14 idx#12 ]
|
||||
reg byte a [ main::$5 ]
|
||||
reg byte y [ main::$2 ]
|
||||
zp ZP_BYTE:3 [ print::p_x#0 ]
|
||||
zp ZP_WORD:4 [ print::p_y#0 ]
|
||||
reg byte y [ idx#3 ]
|
||||
reg byte a [ print::$0 ]
|
||||
reg byte y [ idx#4 ]
|
||||
reg byte a [ print::$1 ]
|
||||
reg byte y [ idx#5 ]
|
Loading…
x
Reference in New Issue
Block a user