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

Fixed _deref(_deref_pptc1) fragments to handle {c1}>255. Added simpler test for struct containing array problem. #312

This commit is contained in:
jespergravgaard 2019-09-10 00:18:31 +02:00
parent 4ab1cac029
commit f110b86ee1
20 changed files with 752 additions and 70 deletions

View File

@ -1,2 +1,6 @@
ldy {c1}
sty $fe
ldy {c1}+1
sty $ff
ldy #0
sta ({c1}),y
sta ($fe),y

View File

@ -1,2 +1,6 @@
ldy {c1}
sty $fe
ldy {c1}+1
sty $ff
ldy #0
lda ({c1}),y
lda ($fe),y

View File

@ -649,6 +649,12 @@ public class TestPrograms {
}
*/
@Test
public void testStructPtr32() throws IOException, URISyntaxException {
compileAndCompare("struct-ptr-32", log());
}
//@Test
//public void testStructPtr31() throws IOException, URISyntaxException {
// compileAndCompare("struct-ptr-31");

View File

@ -0,0 +1,23 @@
// Example of a struct containing an array
// Fails (by displaying "BB" ) because the memory layout is wrong - and the name is treated like a pointer (to 0x0000) instead of a value.
// https://gitlab.com/camelot/kickc/issues/312
struct Person {
char id;
char[16] name;
};
struct Person[2] persons;
void main() {
persons[0].name[0] = 'a';
persons[1].name[0] = 'b';
const char* SCREEN = 0x0400;
struct Person* person = persons;
SCREEN[0] = person->name[0];
person++;
SCREEN[1] = person->name[0];
}

View File

@ -91,8 +91,12 @@ utoa16n: {
beq breturn
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
inc.z utoa16w.dst
bne !+
inc.z utoa16w.dst+1

View File

@ -1049,8 +1049,12 @@ utoa16n: {
// [43] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuz1
ldy.z nybble
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// [44] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst
bne !+
@ -1163,17 +1167,17 @@ Uplift Scope [cls] 33: zp ZP_WORD:8 [ cls::sc#2 cls::sc#1 ]
Uplift Scope [main]
Uplift Scope []
Uplifting [utoa16w] best 955 combination zp ZP_WORD:4 [ utoa16w::dst#5 utoa16w::dst#0 utoa16w::dst#1 utoa16w::dst#2 utoa16w::dst#3 utoa16w::dst#4 ] reg byte a [ utoa16w::$0 ] reg byte a [ utoa16w::$4 ] reg byte a [ utoa16w::$8 ] reg byte a [ utoa16w::$12 ] zp ZP_BYTE:12 [ utoa16w::started#1 ] zp ZP_BYTE:15 [ utoa16w::started#2 ] zp ZP_WORD:2 [ utoa16w::value#5 ]
Uplifting [utoa16w] best 967 combination zp ZP_WORD:4 [ utoa16w::dst#5 utoa16w::dst#0 utoa16w::dst#1 utoa16w::dst#2 utoa16w::dst#3 utoa16w::dst#4 ] reg byte a [ utoa16w::$0 ] reg byte a [ utoa16w::$4 ] reg byte a [ utoa16w::$8 ] reg byte a [ utoa16w::$12 ] zp ZP_BYTE:12 [ utoa16w::started#1 ] zp ZP_BYTE:15 [ utoa16w::started#2 ] zp ZP_WORD:2 [ utoa16w::value#5 ]
Limited combination testing to 100 combinations of 2304 possible.
Uplifting [utoa16n] best 903 combination reg byte a [ utoa16n::nybble#4 utoa16n::nybble#0 utoa16n::nybble#1 utoa16n::nybble#2 utoa16n::nybble#3 ] reg byte x [ utoa16n::return#4 utoa16n::started#7 utoa16n::started#1 utoa16n::started#2 ] reg byte x [ utoa16n::return#0 ] reg byte x [ utoa16n::return#1 ]
Uplifting [utoa16n] best 915 combination reg byte a [ utoa16n::nybble#4 utoa16n::nybble#0 utoa16n::nybble#1 utoa16n::nybble#2 utoa16n::nybble#3 ] reg byte x [ utoa16n::return#4 utoa16n::started#7 utoa16n::started#1 utoa16n::started#2 ] reg byte x [ utoa16n::return#0 ] reg byte x [ utoa16n::return#1 ]
Limited combination testing to 100 combinations of 128 possible.
Uplifting [cls] best 903 combination zp ZP_WORD:8 [ cls::sc#2 cls::sc#1 ]
Uplifting [main] best 903 combination
Uplifting [] best 903 combination
Uplifting [cls] best 915 combination zp ZP_WORD:8 [ cls::sc#2 cls::sc#1 ]
Uplifting [main] best 915 combination
Uplifting [] best 915 combination
Attempting to uplift remaining variables inzp ZP_BYTE:12 [ utoa16w::started#1 ]
Uplifting [utoa16w] best 897 combination reg byte x [ utoa16w::started#1 ]
Uplifting [utoa16w] best 909 combination reg byte x [ utoa16w::started#1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:15 [ utoa16w::started#2 ]
Uplifting [utoa16w] best 891 combination reg byte x [ utoa16w::started#2 ]
Uplifting [utoa16w] best 903 combination reg byte x [ utoa16w::started#2 ]
Coalescing zero page register [ zp ZP_WORD:8 [ cls::sc#2 cls::sc#1 ] ] with [ zp ZP_WORD:2 [ utoa16w::value#5 ] ]
Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ utoa16w::dst#5 utoa16w::dst#0 utoa16w::dst#1 utoa16w::dst#2 utoa16w::dst#3 utoa16w::dst#4 ]
Allocated (was zp ZP_WORD:8) zp ZP_WORD:4 [ cls::sc#2 cls::sc#1 utoa16w::value#5 ]
@ -1418,8 +1422,12 @@ utoa16n: {
// [43] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuaa
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// [44] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst
bne !+
@ -1628,7 +1636,7 @@ reg byte a [ utoa16w::$12 ]
FINAL ASSEMBLER
Score: 739
Score: 751
// File Comments
// Testing binary to hex conversion using pointer to pointer
@ -1842,8 +1850,12 @@ utoa16n: {
// [43] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuaa
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// *(*dst)++ = DIGITS[nybble];
// [44] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst

View File

@ -217,8 +217,12 @@ utoa16n: {
beq breturn
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
inc.z utoa16w.dst
bne !+
inc.z utoa16w.dst+1

View File

@ -1992,8 +1992,12 @@ utoa16n: {
// [82] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuz1
ldy.z nybble
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// [83] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst
bne !+
@ -2176,36 +2180,36 @@ Uplift Scope [utoa16n] 14.4: zp ZP_BYTE:14 [ utoa16n::nybble#4 utoa16n::nybble#0
Uplift Scope [cls] 33: zp ZP_WORD:16 [ cls::sc#2 cls::sc#1 ]
Uplift Scope []
Uplifting [utoa10w] best 28959 combination zp ZP_WORD:8 [ utoa10w::dst#7 utoa10w::dst#11 utoa10w::dst#4 utoa10w::dst#1 ] zp ZP_WORD:4 [ utoa10w::value#10 utoa10w::value#0 utoa10w::value#1 ] zp ZP_BYTE:6 [ utoa10w::digit#3 utoa10w::digit#7 utoa10w::digit#1 ] reg byte x [ utoa10w::i#2 utoa10w::i#1 ] reg byte a [ utoa10w::$8 ] reg byte a [ utoa10w::$2 ] zp ZP_BYTE:29 [ utoa10w::$9 ] zp ZP_BYTE:7 [ utoa10w::bStarted#2 ] zp ZP_BYTE:26 [ utoa10w::$0 ] zp ZP_WORD:27 [ utoa10w::dst#2 ]
Uplifting [utoa10w] best 28971 combination zp ZP_WORD:8 [ utoa10w::dst#7 utoa10w::dst#11 utoa10w::dst#4 utoa10w::dst#1 ] zp ZP_WORD:4 [ utoa10w::value#10 utoa10w::value#0 utoa10w::value#1 ] zp ZP_BYTE:6 [ utoa10w::digit#3 utoa10w::digit#7 utoa10w::digit#1 ] reg byte x [ utoa10w::i#2 utoa10w::i#1 ] reg byte a [ utoa10w::$8 ] reg byte a [ utoa10w::$2 ] zp ZP_BYTE:29 [ utoa10w::$9 ] zp ZP_BYTE:7 [ utoa10w::bStarted#2 ] zp ZP_BYTE:26 [ utoa10w::$0 ] zp ZP_WORD:27 [ utoa10w::dst#2 ]
Limited combination testing to 100 combinations of 3072 possible.
Uplifting [main] best 26559 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$2 ] reg byte a [ main::rst#0 ] zp ZP_BYTE:18 [ main::$1 ] zp ZP_BYTE:22 [ main::time_end#0 ] zp ZP_BYTE:23 [ main::time#0 ] zp ZP_BYTE:21 [ main::time_start#0 ]
Uplifting [main] best 26571 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$2 ] reg byte a [ main::rst#0 ] zp ZP_BYTE:18 [ main::$1 ] zp ZP_BYTE:22 [ main::time_end#0 ] zp ZP_BYTE:23 [ main::time#0 ] zp ZP_BYTE:21 [ main::time_start#0 ]
Limited combination testing to 100 combinations of 3456 possible.
Uplifting [utoa16w] best 26535 combination zp ZP_WORD:12 [ utoa16w::dst#5 utoa16w::dst#1 utoa16w::dst#2 utoa16w::dst#3 utoa16w::dst#4 utoa16w::dst#0 ] reg byte a [ utoa16w::$0 ] reg byte a [ utoa16w::$4 ] reg byte a [ utoa16w::$8 ] reg byte a [ utoa16w::$12 ] zp ZP_BYTE:32 [ utoa16w::started#1 ] zp ZP_BYTE:35 [ utoa16w::started#2 ] zp ZP_WORD:10 [ utoa16w::value#5 ]
Uplifting [utoa16w] best 26547 combination zp ZP_WORD:12 [ utoa16w::dst#5 utoa16w::dst#1 utoa16w::dst#2 utoa16w::dst#3 utoa16w::dst#4 utoa16w::dst#0 ] reg byte a [ utoa16w::$0 ] reg byte a [ utoa16w::$4 ] reg byte a [ utoa16w::$8 ] reg byte a [ utoa16w::$12 ] zp ZP_BYTE:32 [ utoa16w::started#1 ] zp ZP_BYTE:35 [ utoa16w::started#2 ] zp ZP_WORD:10 [ utoa16w::value#5 ]
Limited combination testing to 100 combinations of 2304 possible.
Uplifting [utoa16n] best 26483 combination reg byte a [ utoa16n::nybble#4 utoa16n::nybble#0 utoa16n::nybble#1 utoa16n::nybble#2 utoa16n::nybble#3 ] reg byte x [ utoa16n::return#4 utoa16n::started#7 utoa16n::started#1 utoa16n::started#2 ] reg byte x [ utoa16n::return#0 ] reg byte x [ utoa16n::return#1 ]
Uplifting [utoa16n] best 26495 combination reg byte a [ utoa16n::nybble#4 utoa16n::nybble#0 utoa16n::nybble#1 utoa16n::nybble#2 utoa16n::nybble#3 ] reg byte x [ utoa16n::return#4 utoa16n::started#7 utoa16n::started#1 utoa16n::started#2 ] reg byte x [ utoa16n::return#0 ] reg byte x [ utoa16n::return#1 ]
Limited combination testing to 100 combinations of 128 possible.
Uplifting [cls] best 26483 combination zp ZP_WORD:16 [ cls::sc#2 cls::sc#1 ]
Uplifting [] best 26483 combination
Uplifting [cls] best 26495 combination zp ZP_WORD:16 [ cls::sc#2 cls::sc#1 ]
Uplifting [] best 26495 combination
Attempting to uplift remaining variables inzp ZP_BYTE:6 [ utoa10w::digit#3 utoa10w::digit#7 utoa10w::digit#1 ]
Uplifting [utoa10w] best 26483 combination zp ZP_BYTE:6 [ utoa10w::digit#3 utoa10w::digit#7 utoa10w::digit#1 ]
Uplifting [utoa10w] best 26495 combination zp ZP_BYTE:6 [ utoa10w::digit#3 utoa10w::digit#7 utoa10w::digit#1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:29 [ utoa10w::$9 ]
Uplifting [utoa10w] best 26083 combination reg byte a [ utoa10w::$9 ]
Uplifting [utoa10w] best 26095 combination reg byte a [ utoa10w::$9 ]
Attempting to uplift remaining variables inzp ZP_BYTE:18 [ main::$1 ]
Uplifting [main] best 26083 combination zp ZP_BYTE:18 [ main::$1 ]
Uplifting [main] best 26095 combination zp ZP_BYTE:18 [ main::$1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:7 [ utoa10w::bStarted#2 ]
Uplifting [utoa10w] best 26083 combination zp ZP_BYTE:7 [ utoa10w::bStarted#2 ]
Uplifting [utoa10w] best 26095 combination zp ZP_BYTE:7 [ utoa10w::bStarted#2 ]
Attempting to uplift remaining variables inzp ZP_BYTE:22 [ main::time_end#0 ]
Uplifting [main] best 26043 combination reg byte x [ main::time_end#0 ]
Uplifting [main] best 26055 combination reg byte x [ main::time_end#0 ]
Attempting to uplift remaining variables inzp ZP_BYTE:23 [ main::time#0 ]
Uplifting [main] best 25983 combination reg byte a [ main::time#0 ]
Uplifting [main] best 25995 combination reg byte a [ main::time#0 ]
Attempting to uplift remaining variables inzp ZP_BYTE:26 [ utoa10w::$0 ]
Uplifting [utoa10w] best 25979 combination reg byte a [ utoa10w::$0 ]
Uplifting [utoa10w] best 25991 combination reg byte a [ utoa10w::$0 ]
Attempting to uplift remaining variables inzp ZP_BYTE:32 [ utoa16w::started#1 ]
Uplifting [utoa16w] best 25973 combination reg byte x [ utoa16w::started#1 ]
Uplifting [utoa16w] best 25985 combination reg byte x [ utoa16w::started#1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:35 [ utoa16w::started#2 ]
Uplifting [utoa16w] best 25967 combination reg byte x [ utoa16w::started#2 ]
Uplifting [utoa16w] best 25979 combination reg byte x [ utoa16w::started#2 ]
Attempting to uplift remaining variables inzp ZP_BYTE:21 [ main::time_start#0 ]
Uplifting [main] best 25967 combination zp ZP_BYTE:21 [ main::time_start#0 ]
Uplifting [main] best 25979 combination zp ZP_BYTE:21 [ main::time_start#0 ]
Coalescing zero page register [ zp ZP_WORD:8 [ utoa10w::dst#7 utoa10w::dst#11 utoa10w::dst#4 utoa10w::dst#1 ] ] with [ zp ZP_WORD:27 [ utoa10w::dst#2 ] ] - score: 1
Coalescing zero page register [ zp ZP_WORD:10 [ utoa16w::value#5 ] ] with [ zp ZP_WORD:4 [ utoa10w::value#10 utoa10w::value#0 utoa10w::value#1 ] ]
Coalescing zero page register [ zp ZP_WORD:16 [ cls::sc#2 cls::sc#1 ] ] with [ zp ZP_WORD:8 [ utoa10w::dst#7 utoa10w::dst#11 utoa10w::dst#4 utoa10w::dst#1 utoa10w::dst#2 ] ]
@ -2688,8 +2692,12 @@ utoa16n: {
// [82] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuaa
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// [83] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst
bne !+
@ -3008,7 +3016,7 @@ reg byte a [ utoa16w::$12 ]
FINAL ASSEMBLER
Score: 22306
Score: 22318
// File Comments
// Testing hex to decimal conversion
@ -3458,8 +3466,12 @@ utoa16n: {
// [82] *(*(&(byte*) utoa16w::dst#5)) ← *((const byte[]) DIGITS#0 + (byte) utoa16n::nybble#4) -- _deref_(_deref_pptc1)=pbuc2_derefidx_vbuaa
tay
lda DIGITS,y
ldy.z utoa16w.dst
sty.z $fe
ldy.z utoa16w.dst+1
sty.z $ff
ldy #0
sta (utoa16w.dst),y
sta ($fe),y
// *(*dst)++ = DIGITS[nybble];
// [83] *(&(byte*) utoa16w::dst#5) ← ++ *(&(byte*) utoa16w::dst#5) -- _deref_pptc1=_inc__deref_pptc1
inc.z utoa16w.dst

View File

@ -13,8 +13,12 @@ main: {
sta.z pb
lda #>b
sta.z pb+1
ldy.z ppb
sty.z $fe
ldy.z ppb+1
sty.z $ff
ldy #0
lda (ppb),y
lda ($fe),y
sta SCREEN
rts
}

View File

@ -146,8 +146,12 @@ main: {
lda #>b
sta.z pb+1
// [6] *((const byte*) main::SCREEN#0) ← *(*((const byte**) main::ppb#0)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy.z ppb
sty.z $fe
ldy.z ppb+1
sty.z $ff
ldy #0
lda (ppb),y
lda ($fe),y
sta SCREEN
jmp breturn
// main::@return
@ -168,10 +172,10 @@ REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp ZP_WORD:3 [ main::pb#0 ] 2: zp ZP_BYTE:2 [ main::b#0 ]
Uplift Scope []
Uplifting [main] best 47 combination zp ZP_WORD:3 [ main::pb#0 ] zp ZP_BYTE:2 [ main::b#0 ]
Uplifting [] best 47 combination
Uplifting [main] best 59 combination zp ZP_WORD:3 [ main::pb#0 ] zp ZP_BYTE:2 [ main::b#0 ]
Uplifting [] best 59 combination
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::b#0 ]
Uplifting [main] best 47 combination zp ZP_BYTE:2 [ main::b#0 ]
Uplifting [main] best 59 combination zp ZP_BYTE:2 [ main::b#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -210,8 +214,12 @@ main: {
lda #>b
sta.z pb+1
// [6] *((const byte*) main::SCREEN#0) ← *(*((const byte**) main::ppb#0)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy.z ppb
sty.z $fe
ldy.z ppb+1
sty.z $ff
ldy #0
lda (ppb),y
lda ($fe),y
sta SCREEN
jmp breturn
// main::@return
@ -259,7 +267,7 @@ zp ZP_WORD:3 [ main::pb#0 ]
FINAL ASSEMBLER
Score: 32
Score: 44
// File Comments
// Tests a simple pointer to a pointer
@ -292,8 +300,12 @@ main: {
sta.z pb+1
// *SCREEN = **ppb
// [6] *((const byte*) main::SCREEN#0) ← *(*((const byte**) main::ppb#0)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy.z ppb
sty.z $fe
ldy.z ppb+1
sty.z $ff
ldy #0
lda (ppb),y
lda ($fe),y
sta SCREEN
// main::@return
// }

View File

@ -10,14 +10,22 @@ main: {
lda #>$400
sta.z screen+1
lda #'a'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
inc.z pscreen
bne !+
inc.z pscreen+1
!:
lda #'b'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
rts
}

View File

@ -124,8 +124,12 @@ main: {
sta.z screen+1
// [5] *(*((const byte**) main::pscreen#0)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
// [6] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z pscreen
bne !+
@ -133,8 +137,12 @@ main: {
!:
// [7] *(*((const byte**) main::pscreen#0)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
jmp breturn
// main::@return
breturn:
@ -153,8 +161,8 @@ REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp ZP_WORD:2 [ main::screen#0 ]
Uplift Scope []
Uplifting [main] best 63 combination zp ZP_WORD:2 [ main::screen#0 ]
Uplifting [] best 63 combination
Uplifting [main] best 87 combination zp ZP_WORD:2 [ main::screen#0 ]
Uplifting [] best 87 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -189,8 +197,12 @@ main: {
sta.z screen+1
// [5] *(*((const byte**) main::pscreen#0)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
// [6] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z pscreen
bne !+
@ -198,8 +210,12 @@ main: {
!:
// [7] *(*((const byte**) main::pscreen#0)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
jmp breturn
// main::@return
breturn:
@ -241,7 +257,7 @@ zp ZP_WORD:2 [ main::screen#0 ]
FINAL ASSEMBLER
Score: 48
Score: 72
// File Comments
// Tests optimization of constant pointers to pointers
@ -269,8 +285,12 @@ main: {
// **pscreen = 'a'
// [5] *(*((const byte**) main::pscreen#0)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
// (*pscreen)++;
// [6] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z pscreen
@ -280,8 +300,12 @@ main: {
// **pscreen = 'b'
// [7] *(*((const byte**) main::pscreen#0)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy.z pscreen
sty.z $fe
ldy.z pscreen+1
sty.z $ff
ldy #0
sta (pscreen),y
sta ($fe),y
// main::@return
// }
// [8] return

View File

@ -17,8 +17,12 @@ main: {
}
// sub(byte register(A) ch)
sub: {
ldy.z main.pscreen
sty.z $fe
ldy.z main.pscreen+1
sty.z $ff
ldy #0
sta (main.pscreen),y
sta ($fe),y
inc.z main.pscreen
bne !+
inc.z main.pscreen+1

View File

@ -223,8 +223,12 @@ sub: {
.label ch = 2
// [10] *(*((const byte**) main::pscreen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuz1
lda.z ch
ldy.z main.pscreen
sty.z $fe
ldy.z main.pscreen+1
sty.z $ff
ldy #0
sta (main.pscreen),y
sta ($fe),y
// [11] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.pscreen
bne !+
@ -249,9 +253,9 @@ Uplift Scope [main] 20: zp ZP_WORD:3 [ main::screen#0 ]
Uplift Scope [sub] 2: zp ZP_BYTE:2 [ sub::ch#2 ]
Uplift Scope []
Uplifting [main] best 88 combination zp ZP_WORD:3 [ main::screen#0 ]
Uplifting [sub] best 79 combination reg byte a [ sub::ch#2 ]
Uplifting [] best 79 combination
Uplifting [main] best 100 combination zp ZP_WORD:3 [ main::screen#0 ]
Uplifting [sub] best 91 combination reg byte a [ sub::ch#2 ]
Uplifting [] best 91 combination
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::screen#0 ]
ASSEMBLER BEFORE OPTIMIZATION
@ -312,8 +316,12 @@ main: {
// sub(byte register(A) ch)
sub: {
// [10] *(*((const byte**) main::pscreen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuaa
ldy.z main.pscreen
sty.z $fe
ldy.z main.pscreen+1
sty.z $ff
ldy #0
sta (main.pscreen),y
sta ($fe),y
// [11] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.pscreen
bne !+
@ -374,7 +382,7 @@ zp ZP_WORD:2 [ main::screen#0 ]
FINAL ASSEMBLER
Score: 58
Score: 70
// File Comments
// Tests optimization of constant pointers to pointers
@ -423,8 +431,12 @@ main: {
sub: {
// *(*dst)++ = ch
// [10] *(*((const byte**) main::pscreen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuaa
ldy.z main.pscreen
sty.z $fe
ldy.z main.pscreen+1
sty.z $ff
ldy #0
sta (main.pscreen),y
sta ($fe),y
// *(*dst)++ = ch;
// [11] *((const byte**) main::pscreen#0) ← ++ *((const byte**) main::pscreen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.pscreen

View File

@ -17,8 +17,12 @@ main: {
}
// sub(byte register(A) ch)
sub: {
ldy.z main.screen
sty.z $fe
ldy.z main.screen+1
sty.z $ff
ldy #0
sta (main.screen),y
sta ($fe),y
inc.z main.screen
bne !+
inc.z main.screen+1

View File

@ -223,8 +223,12 @@ sub: {
.label ch = 2
// [10] *(*(&(byte*) main::screen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuz1
lda.z ch
ldy.z main.screen
sty.z $fe
ldy.z main.screen+1
sty.z $ff
ldy #0
sta (main.screen),y
sta ($fe),y
// [11] *(&(byte*) main::screen#0) ← ++ *(&(byte*) main::screen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.screen
bne !+
@ -249,9 +253,9 @@ Uplift Scope [sub] 2: zp ZP_BYTE:2 [ sub::ch#2 ]
Uplift Scope [main] 0.29: zp ZP_WORD:3 [ main::screen#0 ]
Uplift Scope []
Uplifting [sub] best 79 combination reg byte a [ sub::ch#2 ]
Uplifting [main] best 79 combination zp ZP_WORD:3 [ main::screen#0 ]
Uplifting [] best 79 combination
Uplifting [sub] best 91 combination reg byte a [ sub::ch#2 ]
Uplifting [main] best 91 combination zp ZP_WORD:3 [ main::screen#0 ]
Uplifting [] best 91 combination
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::screen#0 ]
ASSEMBLER BEFORE OPTIMIZATION
@ -312,8 +316,12 @@ main: {
// sub(byte register(A) ch)
sub: {
// [10] *(*(&(byte*) main::screen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuaa
ldy.z main.screen
sty.z $fe
ldy.z main.screen+1
sty.z $ff
ldy #0
sta (main.screen),y
sta ($fe),y
// [11] *(&(byte*) main::screen#0) ← ++ *(&(byte*) main::screen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.screen
bne !+
@ -372,7 +380,7 @@ zp ZP_WORD:2 [ main::screen#0 ]
FINAL ASSEMBLER
Score: 58
Score: 70
// File Comments
// Tests (non-)optimization of constant pointers to pointers
@ -421,8 +429,12 @@ main: {
sub: {
// *(*dst)++ = ch
// [10] *(*(&(byte*) main::screen#0)) ← (byte) sub::ch#2 -- _deref_(_deref_pptc1)=vbuaa
ldy.z main.screen
sty.z $fe
ldy.z main.screen+1
sty.z $ff
ldy #0
sta (main.screen),y
sta ($fe),y
// *(*dst)++ = ch;
// [11] *(&(byte*) main::screen#0) ← ++ *(&(byte*) main::screen#0) -- _deref_pptc1=_inc__deref_pptc1
inc.z main.screen

View File

@ -0,0 +1,42 @@
// Example of a struct containing an array
// Fails (by displaying "BB" ) because the memory layout is wrong - and the name is treated like a pointer (to 0x0000) instead of a value.
// https://gitlab.com/camelot/kickc/issues/312
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_STRUCT_PERSON = 3
.const OFFSET_STRUCT_PERSON_NAME = 1
main: {
.label SCREEN = $400
.label person = persons+SIZEOF_STRUCT_PERSON
lda #'a'
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
sta ($fe),y
lda #'b'
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON+1
sty.z $ff
ldy #0
sta ($fe),y
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN
ldy person+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy person+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN+1
rts
}
persons: .fill 3*2, 0

View File

@ -0,0 +1,18 @@
@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[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a'
[5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b'
[6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME))
[7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME))
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return

View File

@ -0,0 +1,457 @@
Fixing pointer increment (struct Person*) main::person ← ++ (struct Person*) main::person
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[2]) persons + (number~) main::$0).name
Rewriting struct pointer member access *((struct Person[2]) persons + (number~) main::$1).name
Rewriting struct pointer member access *((struct Person*) main::person).name
Rewriting struct pointer member access *((struct Person*) main::person).name
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Person[2]) persons#0 ← { fill( 2, 0) }
to:@1
main: scope:[main] from @1
(number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_PERSON
(byte[$10]*) main::$2 ← (byte[$10]*)(struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
*(*((byte[$10]*) main::$2 + (number~) main::$0) + (number) 0) ← (byte) 'a'
(number~) main::$1 ← (number) 1 * (const byte) SIZEOF_STRUCT_PERSON
(byte[$10]*) main::$3 ← (byte[$10]*)(struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
*(*((byte[$10]*) main::$3 + (number~) main::$1) + (number) 0) ← (byte) 'b'
(byte*) main::SCREEN#0 ← ((byte*)) (number) $400
(struct Person*) main::person#0 ← (struct Person[2]) persons#0
(byte[$10]*) main::$4 ← (byte[$10]*)(struct Person*) main::person#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
*((byte*) main::SCREEN#0 + (number) 0) ← *(*((byte[$10]*) main::$4) + (number) 0)
(struct Person*) main::person#1 ← (struct Person*) main::person#0 + (const byte) SIZEOF_STRUCT_PERSON
(byte[$10]*) main::$5 ← (byte[$10]*)(struct Person*) main::person#1 + (const byte) OFFSET_STRUCT_PERSON_NAME
*((byte*) main::SCREEN#0 + (number) 1) ← *(*((byte[$10]*) main::$5) + (number) 0)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(byte[$10]) Person::name
(const byte) SIZEOF_STRUCT_PERSON = (byte) 3
(void()) main()
(number~) main::$0
(number~) main::$1
(byte[$10]*) main::$2
(byte[$10]*) main::$3
(byte[$10]*) main::$4
(byte[$10]*) main::$5
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(struct Person*) main::person
(struct Person*) main::person#0
(struct Person*) main::person#1
(struct Person[2]) persons
(struct Person[2]) persons#0
Adding number conversion cast (unumber) 0 in (number~) main::$0 ← (number) 0 * (const byte) SIZEOF_STRUCT_PERSON
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_PERSON
Adding number conversion cast (unumber) 0 in *(*((byte[$10]*) main::$2 + (unumber~) main::$0) + (number) 0) ← (byte) 'a'
Adding number conversion cast (unumber) 1 in (number~) main::$1 ← (number) 1 * (const byte) SIZEOF_STRUCT_PERSON
Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_PERSON
Adding number conversion cast (unumber) 0 in *(*((byte[$10]*) main::$3 + (unumber~) main::$1) + (number) 0) ← (byte) 'b'
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← *(*((byte[$10]*) main::$4) + (number) 0)
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← *(*((byte[$10]*) main::$4) + (unumber)(number) 0)
Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 1) ← *(*((byte[$10]*) main::$5) + (number) 0)
Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← *(*((byte[$10]*) main::$5) + (unumber)(number) 0)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
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
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
Inferred type updated to byte in (unumber~) main::$1 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
Constant right-side identified [0] (struct Person[2]) persons#0 ← { fill( 2, 0) }
Constant right-side identified [1] (byte~) main::$0 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
Constant right-side identified [4] (byte~) main::$1 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const struct Person[2]) persons#0 = { fill( 2, 0) }
Constant (const byte) main::$0 = 0*SIZEOF_STRUCT_PERSON
Constant (const byte) main::$1 = 1*SIZEOF_STRUCT_PERSON
Constant (const byte*) main::SCREEN#0 = (byte*) 1024
Successful SSA optimization Pass2ConstantIdentification
Constant (const struct Person*) main::person#0 = persons#0
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte[$10]*)persons#0 in [2] (byte[$10]*) main::$2 ← (byte[$10]*)(const struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Constant value identified (byte[$10]*)persons#0 in [5] (byte[$10]*) main::$3 ← (byte[$10]*)(const struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Constant value identified (byte[$10]*)main::person#0 in [9] (byte[$10]*) main::$4 ← (byte[$10]*)(const struct Person*) main::person#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Successful SSA optimization Pass2ConstantValues
Converting *(pointer+n) to pointer[n] [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *(*((byte[$10]*) main::$4) + (byte) 0) -- *((byte[$10]*)main::person#0 + OFFSET_STRUCT_PERSON_NAME)
Converting *(pointer+n) to pointer[n] [13] *((const byte*) main::SCREEN#0 + (byte) 1) ← *(*((byte[$10]*) main::$5) + (byte) 0) -- *((byte[$10]*)main::person#1 + 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 *(main::$2 + main::$0) in [3] *(*((byte[$10]*) main::$2 + (const byte) main::$0) + (byte) 0) ← (byte) 'a'
Simplifying expression containing zero main::$2 in [3] *(*((byte[$10]*) main::$2 + (const byte) main::$0)) ← (byte) 'a'
Simplifying expression containing zero *(main::$3 + main::$1) in [6] *(*((byte[$10]*) main::$3 + (const byte) main::$1) + (byte) 0) ← (byte) 'b'
Simplifying expression containing zero *((byte[$10]*)main::person#0 + OFFSET_STRUCT_PERSON_NAME) in [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *(*((byte[$10]*)(const struct Person*) main::person#0 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) 0)
Simplifying expression containing zero main::SCREEN#0 in [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *(*((byte[$10]*)(const struct Person*) main::person#0 + (const byte) OFFSET_STRUCT_PERSON_NAME))
Simplifying expression containing zero *((byte[$10]*)main::person#1 + OFFSET_STRUCT_PERSON_NAME) in [13] *((const byte*) main::SCREEN#0 + (byte) 1) ← *(*((byte[$10]*)(struct Person*) main::person#1 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) 0)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte[$10]*) main::$4 and assignment [4] (byte[$10]*) main::$4 ← (byte[$10]*)(const struct Person*) main::person#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Eliminating unused variable (byte[$10]*) main::$5 and assignment [7] (byte[$10]*) main::$5 ← (byte[$10]*)(struct Person*) main::person#1 + (const byte) OFFSET_STRUCT_PERSON_NAME
Eliminating unused constant (const byte) main::$0
Successful SSA optimization PassNEliminateUnusedVars
Constant right-side identified [0] (byte[$10]*) main::$2 ← (byte[$10]*)(const struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Constant right-side identified [2] (byte[$10]*) main::$3 ← (byte[$10]*)(const struct Person[2]) persons#0 + (const byte) OFFSET_STRUCT_PERSON_NAME
Constant right-side identified [5] (struct Person*) main::person#1 ← (const struct Person*) main::person#0 + (const byte) SIZEOF_STRUCT_PERSON
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte[$10]*) main::$2 = (byte[$10]*)persons#0+OFFSET_STRUCT_PERSON_NAME
Constant (const byte[$10]*) main::$3 = (byte[$10]*)persons#0+OFFSET_STRUCT_PERSON_NAME
Constant (const struct Person*) main::person#1 = main::person#0+SIZEOF_STRUCT_PERSON
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte[$10]*)main::person#1 in [6] *((const byte*) main::SCREEN#0 + (byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1 + (const byte) OFFSET_STRUCT_PERSON_NAME))
Successful SSA optimization Pass2ConstantValues
Inlining constant with different constant siblings (const struct Person*) main::person#0
Constant inlined main::$3 = (byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME
Constant inlined main::$1 = (byte) 1*(const byte) SIZEOF_STRUCT_PERSON
Constant inlined main::$2 = (byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME
Constant inlined main::person#0 = (const struct Person[2]) persons#0
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte[$10]*)persons#0+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON)
Consolidated array index constant in *((byte[$10]*)persons#0+OFFSET_STRUCT_PERSON_NAME)
Consolidated array index constant in *((byte[$10]*)main::person#1+OFFSET_STRUCT_PERSON_NAME)
Consolidated array index constant in *(main::SCREEN#0+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
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] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a'
[5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b'
[6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME))
[7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME))
to:main::@return
main::@return: scope:[main] from main
[8] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Person::id
(byte[$10]) Person::name
(void()) main()
(byte*) main::SCREEN
(struct Person*) main::person
(struct Person[2]) persons
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Example of a struct containing an array
// Fails (by displaying "BB" ) because the memory layout is wrong - and the name is treated like a pointer (to 0x0000) instead of a value.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_PERSON = 3
.const OFFSET_STRUCT_PERSON_NAME = 1
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label SCREEN = $400
.label person = persons+SIZEOF_STRUCT_PERSON
// [4] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
sta ($fe),y
// [5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON+1
sty.z $ff
ldy #0
sta ($fe),y
// [6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN
// [7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy person+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy person+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN+1
jmp breturn
// main::@return
breturn:
// [8] return
rts
}
// File Data
persons: .fill 3*2, 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
Statement [5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b' [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
Statement [6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
Statement [7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME)) [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y
REGISTER UPLIFT SCOPES
Uplift Scope [Person]
Uplift Scope [main]
Uplift Scope []
Uplifting [Person] best 119 combination
Uplifting [main] best 119 combination
Uplifting [] best 119 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Example of a struct containing an array
// Fails (by displaying "BB" ) because the memory layout is wrong - and the name is treated like a pointer (to 0x0000) instead of a value.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_PERSON = 3
.const OFFSET_STRUCT_PERSON_NAME = 1
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label SCREEN = $400
.label person = persons+SIZEOF_STRUCT_PERSON
// [4] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
sta ($fe),y
// [5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON+1
sty.z $ff
ldy #0
sta ($fe),y
// [6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN
// [7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy person+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy person+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN+1
jmp breturn
// main::@return
breturn:
// [8] return
rts
}
// File Data
persons: .fill 3*2, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(byte[$10]) Person::name
(const byte) SIZEOF_STRUCT_PERSON SIZEOF_STRUCT_PERSON = (byte) 3
(void()) main()
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024
(struct Person*) main::person
(const struct Person*) main::person#1 person = (const struct Person[2]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
(struct Person[2]) persons
(const struct Person[2]) persons#0 persons = { fill( 2, 0) }
FINAL ASSEMBLER
Score: 104
// File Comments
// Example of a struct containing an array
// Fails (by displaying "BB" ) because the memory layout is wrong - and the name is treated like a pointer (to 0x0000) instead of a value.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_PERSON = 3
.const OFFSET_STRUCT_PERSON_NAME = 1
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label SCREEN = $400
.label person = persons+SIZEOF_STRUCT_PERSON
// persons[0].name[0] = 'a'
// [4] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) ← (byte) 'a' -- _deref_(_deref_pptc1)=vbuc2
lda #'a'
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
sta ($fe),y
// persons[1].name[0] = 'b'
// [5] *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON)) ← (byte) 'b' -- _deref_(_deref_pptc1)=vbuc2
lda #'b'
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1*SIZEOF_STRUCT_PERSON+1
sty.z $ff
ldy #0
sta ($fe),y
// SCREEN[0] = person->name[0]
// [6] *((const byte*) main::SCREEN#0) ← *(*((byte[$10]*)(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy persons+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy persons+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN
// SCREEN[1] = person->name[0]
// [7] *((const byte*) main::SCREEN#0+(byte) 1) ← *(*((byte[$10]*)(const struct Person*) main::person#1+(const byte) OFFSET_STRUCT_PERSON_NAME)) -- _deref_pbuc1=_deref_(_deref_pptc2)
ldy person+OFFSET_STRUCT_PERSON_NAME
sty.z $fe
ldy person+OFFSET_STRUCT_PERSON_NAME+1
sty.z $ff
ldy #0
lda ($fe),y
sta SCREEN+1
// main::@return
// }
// [8] return
rts
}
// File Data
persons: .fill 3*2, 0

View File

@ -0,0 +1,16 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(byte[$10]) Person::name
(const byte) SIZEOF_STRUCT_PERSON SIZEOF_STRUCT_PERSON = (byte) 3
(void()) main()
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024
(struct Person*) main::person
(const struct Person*) main::person#1 person = (const struct Person[2]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
(struct Person[2]) persons
(const struct Person[2]) persons#0 persons = { fill( 2, 0) }