1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-11 20:30:08 +00:00

#pragma struct_model(classic) fixes problem with variable instances of structs with array members. Closes #587

This commit is contained in:
jespergravgaard 2021-08-02 23:00:15 +02:00
parent 6c4d0488b9
commit 4f2ae64cac
10 changed files with 455 additions and 60 deletions

View File

@ -2322,6 +2322,10 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("union-0.c"); compileAndCompare("union-0.c");
} }
@Test
public void testStruct46() throws IOException {
compileAndCompare("struct-46.c");
}
@Test @Test
public void testStruct45() throws IOException { public void testStruct45() throws IOException {

View File

@ -1,7 +1,7 @@
// https://gitlab.com/camelot/kickc/-/issues/590 // https://gitlab.com/camelot/kickc/-/issues/590
#pragma var_model(mem)
#pragma struct_model(classic) #pragma struct_model(classic)
#pragma var_model(struct_mem)
struct deviceslot { struct deviceslot {
unsigned char hostSlot; unsigned char hostSlot;

26
src/test/kc/struct-46.c Normal file
View File

@ -0,0 +1,26 @@
// https://gitlab.com/camelot/kickc/-/issues/587
// Creating variable instances of structs with array members fails to compile
#pragma struct_model(classic)
#pragma var_model(struct_mem)
typedef struct netconfig {
char ssid[32];
char password[64];
} NetConfig;
typedef struct other {
char a;
char b;
} Other;
char const * OUT = (char*)0x8000;
void main() {
Other x;
NetConfig a = {"123", "abc"};
*(OUT + 0) = a.ssid[0];
NetConfig b;
}

View File

@ -14,6 +14,7 @@
.segment Code .segment Code
main: { main: {
.label slotsA = ssA .label slotsA = ssA
.label i = 2
// deviceslot_t s1 = {'A', 'R', "f1"} // deviceslot_t s1 = {'A', 'R', "f1"}
ldy #SIZEOF_STRUCT_DEVICESLOT ldy #SIZEOF_STRUCT_DEVICESLOT
!: !:
@ -50,17 +51,17 @@ main: {
dey dey
bne !- bne !-
lda #0 lda #0
sta i sta.z i
__b1: __b1:
// deviceslot_t ds = slotsA->slot[i] // deviceslot_t ds = slotsA->slot[i]
lda i lda.z i
asl asl
asl asl
asl asl
asl asl
asl asl
clc clc
adc i adc.z i
asl asl
tax tax
ldy #0 ldy #0
@ -73,12 +74,12 @@ main: {
bne !- bne !-
// *(OUT + i) = ds.mode // *(OUT + i) = ds.mode
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy i ldy.z i
sta OUT,y sta OUT,y
// for(char i: 0..1) // for(char i: 0..1)
inc i inc.z i
lda #2 lda #2
cmp i cmp.z i
bne __b1 bne __b1
// } // }
rts rts
@ -87,7 +88,6 @@ main: {
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0 s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0 ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0 ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
i: .byte 0
} }
__0: .byte 'A', 'R' __0: .byte 'A', 'R'
.text "f1" .text "f1"

View File

@ -1,4 +1,3 @@
Updating intermediate variable memory area to MAIN_MEMORY main::$1
Fixing struct type size struct deviceslot to 66 Fixing struct type size struct deviceslot to 66
Fixing struct type size struct deviceslotsA to 132 Fixing struct type size struct deviceslotsA to 132
Fixing struct type size struct deviceslot to 66 Fixing struct type size struct deviceslot to 66
@ -231,10 +230,10 @@ Complete equivalence classes
[ main::s2 ] [ main::s2 ]
[ main::ssA ] [ main::ssA ]
[ main::ds ] [ main::ds ]
Allocated mem[1] [ main::i#2 main::i#1 ] Allocated zp[1]:2 [ main::i#2 main::i#1 ]
Allocated mem[1] [ main::$11 ] Allocated zp[1]:3 [ main::$11 ]
Allocated mem[1] [ main::$12 ] Allocated zp[1]:4 [ main::$12 ]
Allocated mem[1] [ main::$4 ] Allocated zp[1]:5 [ main::$4 ]
Allocated mem[66] [ main::s1 ] Allocated mem[66] [ main::s1 ]
Allocated mem[66] [ main::s2 ] Allocated mem[66] [ main::s2 ]
Allocated mem[132] [ main::ssA ] Allocated mem[132] [ main::ssA ]
@ -246,12 +245,12 @@ Statement [2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESL
Statement [3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::s2 main::ds ] ( [ main::s2 main::ds ] { } ) always clobbers reg byte a reg byte y Statement [3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::s2 main::ds ] ( [ main::s2 main::ds ] { } ) always clobbers reg byte a reg byte y
Statement [4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::ds ] ( [ main::ds ] { } ) always clobbers reg byte a reg byte y Statement [4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::ds ] ( [ main::ds ] { } ) always clobbers reg byte a reg byte y
Statement [6] main::$11 = main::i#2 << 5 [ main::i#2 main::$11 main::ds ] ( [ main::i#2 main::$11 main::ds ] { } ) always clobbers reg byte a Statement [6] main::$11 = main::i#2 << 5 [ main::i#2 main::$11 main::ds ] ( [ main::i#2 main::$11 main::ds ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for mem[1] [ main::i#2 main::i#1 ] Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [7] main::$12 = main::$11 + main::i#2 [ main::i#2 main::$12 main::ds ] ( [ main::i#2 main::$12 main::ds ] { } ) always clobbers reg byte a Statement [7] main::$12 = main::$11 + main::i#2 [ main::i#2 main::$12 main::ds ] ( [ main::i#2 main::$12 main::ds ] { } ) always clobbers reg byte a
Statement [8] main::$4 = main::$12 << 1 [ main::i#2 main::$4 main::ds ] ( [ main::i#2 main::$4 main::ds ] { } ) always clobbers reg byte a Statement [8] main::$4 = main::$12 << 1 [ main::i#2 main::$4 main::ds ] ( [ main::i#2 main::$4 main::ds ] { } ) always clobbers reg byte a
Statement [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte x reg byte y Statement [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte x reg byte y
Removing always clobbered register reg byte x as potential for mem[1] [ main::i#2 main::i#1 ] Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for mem[1] [ main::i#2 main::i#1 ] Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte y Statement [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte y
Statement [12] if(main::i#1!=2) goto main::@1 [ main::i#1 main::ds ] ( [ main::i#1 main::ds ] { } ) always clobbers reg byte a Statement [12] if(main::i#1!=2) goto main::@1 [ main::i#1 main::ds ] ( [ main::i#1 main::ds ] { } ) always clobbers reg byte a
Statement [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::s2 main::ssA main::s1 main::ds ] ( [ main::s2 main::ssA main::s1 main::ds ] { } ) always clobbers reg byte a reg byte y Statement [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::s2 main::ssA main::s1 main::ds ] ( [ main::s2 main::ssA main::s1 main::ds ] { } ) always clobbers reg byte a reg byte y
@ -265,27 +264,27 @@ Statement [8] main::$4 = main::$12 << 1 [ main::i#2 main::$4 main::ds ] ( [ mai
Statement [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte x reg byte y Statement [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte x reg byte y
Statement [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte y Statement [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) [ main::i#2 main::ds ] ( [ main::i#2 main::ds ] { } ) always clobbers reg byte a reg byte y
Statement [12] if(main::i#1!=2) goto main::@1 [ main::i#1 main::ds ] ( [ main::i#1 main::ds ] { } ) always clobbers reg byte a Statement [12] if(main::i#1!=2) goto main::@1 [ main::i#1 main::ds ] ( [ main::i#1 main::ds ] { } ) always clobbers reg byte a
Potential registers mem[1] [ main::i#2 main::i#1 ] : mem[1] , Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 ,
Potential registers mem[1] [ main::$11 ] : mem[1] , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:3 [ main::$11 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
Potential registers mem[1] [ main::$12 ] : mem[1] , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:4 [ main::$12 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
Potential registers mem[1] [ main::$4 ] : mem[1] , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:5 [ main::$4 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
Potential registers mem[66] [ main::s1 ] : mem[66] , Potential registers mem[66] [ main::s1 ] : mem[66] ,
Potential registers mem[66] [ main::s2 ] : mem[66] , Potential registers mem[66] [ main::s2 ] : mem[66] ,
Potential registers mem[132] [ main::ssA ] : mem[132] , Potential registers mem[132] [ main::ssA ] : mem[132] ,
Potential registers mem[66] [ main::ds ] : mem[66] , Potential registers mem[66] [ main::ds ] : mem[66] ,
REGISTER UPLIFT SCOPES REGISTER UPLIFT SCOPES
Uplift Scope [main] 25.67: mem[1] [ main::i#2 main::i#1 ] 22: mem[1] [ main::$11 ] 22: mem[1] [ main::$12 ] 11: mem[1] [ main::$4 ] 0: mem[66] [ main::s1 ] 0: mem[66] [ main::s2 ] 0: mem[132] [ main::ssA ] 0: mem[66] [ main::ds ] Uplift Scope [main] 25.67: zp[1]:2 [ main::i#2 main::i#1 ] 22: zp[1]:3 [ main::$11 ] 22: zp[1]:4 [ main::$12 ] 11: zp[1]:5 [ main::$4 ] 0: mem[66] [ main::s1 ] 0: mem[66] [ main::s2 ] 0: mem[132] [ main::ssA ] 0: mem[66] [ main::ds ]
Uplift Scope [deviceslot] Uplift Scope [deviceslot]
Uplift Scope [deviceslotsA] Uplift Scope [deviceslotsA]
Uplift Scope [] Uplift Scope []
Uplifting [main] best 948 combination mem[1] [ main::i#2 main::i#1 ] reg byte a [ main::$11 ] reg byte a [ main::$12 ] reg byte a [ main::$4 ] mem[66] [ main::s1 ] mem[66] [ main::s2 ] mem[132] [ main::ssA ] mem[66] [ main::ds ] Uplifting [main] best 888 combination zp[1]:2 [ main::i#2 main::i#1 ] reg byte a [ main::$11 ] reg byte a [ main::$12 ] reg byte a [ main::$4 ] mem[66] [ main::s1 ] mem[66] [ main::s2 ] mem[132] [ main::ssA ] mem[66] [ main::ds ]
Uplifting [deviceslot] best 948 combination Uplifting [deviceslot] best 888 combination
Uplifting [deviceslotsA] best 948 combination Uplifting [deviceslotsA] best 888 combination
Uplifting [] best 948 combination Uplifting [] best 888 combination
Attempting to uplift remaining variables inmem[1] [ main::i#2 main::i#1 ] Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ]
Uplifting [main] best 948 combination mem[1] [ main::i#2 main::i#1 ] Uplifting [main] best 888 combination zp[1]:2 [ main::i#2 main::i#1 ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
@ -308,6 +307,7 @@ ASSEMBLER BEFORE OPTIMIZATION
// main // main
main: { main: {
.label slotsA = ssA .label slotsA = ssA
.label i = 2
// [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 // [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT ldy #SIZEOF_STRUCT_DEVICESLOT
!: !:
@ -345,9 +345,9 @@ main: {
bne !- bne !-
// [5] phi from main to main::@1 [phi:main->main::@1] // [5] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main: __b1_from_main:
// [5] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbum1=vbuc1 // [5] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0 lda #0
sta i sta.z i
jmp __b1 jmp __b1
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
__b1_from___b1: __b1_from___b1:
@ -355,16 +355,16 @@ main: {
jmp __b1 jmp __b1
// main::@1 // main::@1
__b1: __b1:
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbum1_rol_5 // [6] main::$11 = main::i#2 << 5 -- vbuaa=vbuz1_rol_5
lda i lda.z i
asl asl
asl asl
asl asl
asl asl
asl asl
// [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbum1 // [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbuz1
clc clc
adc i adc.z i
// [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1 // [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1
asl asl
// [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3 // [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3
@ -377,15 +377,15 @@ main: {
iny iny
cpy #SIZEOF_STRUCT_DEVICESLOT cpy #SIZEOF_STRUCT_DEVICESLOT
bne !- bne !-
// [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- pbuc1_derefidx_vbum1=_deref_pbuc2 // [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- pbuc1_derefidx_vbuz1=_deref_pbuc2
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy i ldy.z i
sta OUT,y sta OUT,y
// [11] main::i#1 = ++ main::i#2 -- vbum1=_inc_vbum1 // [11] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
inc i inc.z i
// [12] if(main::i#1!=2) goto main::@1 -- vbum1_neq_vbuc1_then_la1 // [12] if(main::i#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2 lda #2
cmp i cmp.z i
bne __b1_from___b1 bne __b1_from___b1
jmp __breturn jmp __breturn
// main::@return // main::@return
@ -397,7 +397,6 @@ main: {
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0 s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0 ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0 ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
i: .byte 0
} }
// File Data // File Data
__0: .byte 'A', 'R' __0: .byte 'A', 'R'
@ -435,14 +434,14 @@ byte~ main::$12 reg byte a 22.0
byte~ main::$4 reg byte a 11.0 byte~ main::$4 reg byte a 11.0
struct deviceslot main::ds loadstore mem[66] struct deviceslot main::ds loadstore mem[66]
byte main::i byte main::i
byte main::i#1 i mem[1] 16.5 byte main::i#1 i zp[1]:2 16.5
byte main::i#2 i mem[1] 9.166666666666666 byte main::i#2 i zp[1]:2 9.166666666666666
struct deviceslot main::s1 loadstore mem[66] struct deviceslot main::s1 loadstore mem[66]
struct deviceslot main::s2 loadstore mem[66] struct deviceslot main::s2 loadstore mem[66]
constant struct deviceslotsA* main::slotsA = &main::ssA constant struct deviceslotsA* main::slotsA = &main::ssA
volatile struct deviceslotsA main::ssA loadstore mem[132] volatile struct deviceslotsA main::ssA loadstore mem[132]
mem[1] [ main::i#2 main::i#1 ] zp[1]:2 [ main::i#2 main::i#1 ]
reg byte a [ main::$11 ] reg byte a [ main::$11 ]
reg byte a [ main::$12 ] reg byte a [ main::$12 ]
reg byte a [ main::$4 ] reg byte a [ main::$4 ]
@ -453,7 +452,7 @@ mem[66] [ main::ds ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 858 Score: 798
// File Comments // File Comments
// https://gitlab.com/camelot/kickc/-/issues/590 // https://gitlab.com/camelot/kickc/-/issues/590
@ -475,6 +474,7 @@ Score: 858
// main // main
main: { main: {
.label slotsA = ssA .label slotsA = ssA
.label i = 2
// deviceslot_t s1 = {'A', 'R', "f1"} // deviceslot_t s1 = {'A', 'R', "f1"}
// [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 // [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT ldy #SIZEOF_STRUCT_DEVICESLOT
@ -516,24 +516,24 @@ main: {
dey dey
bne !- bne !-
// [5] phi from main to main::@1 [phi:main->main::@1] // [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbum1=vbuc1 // [5] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0 lda #0
sta i sta.z i
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
// [5] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy // [5] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy
// main::@1 // main::@1
__b1: __b1:
// deviceslot_t ds = slotsA->slot[i] // deviceslot_t ds = slotsA->slot[i]
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbum1_rol_5 // [6] main::$11 = main::i#2 << 5 -- vbuaa=vbuz1_rol_5
lda i lda.z i
asl asl
asl asl
asl asl
asl asl
asl asl
// [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbum1 // [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbuz1
clc clc
adc i adc.z i
// [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1 // [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1
asl asl
// [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3 // [9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=pssc2_derefidx_vbuaa_memcpy_vbuc3
@ -547,16 +547,16 @@ main: {
cpy #SIZEOF_STRUCT_DEVICESLOT cpy #SIZEOF_STRUCT_DEVICESLOT
bne !- bne !-
// *(OUT + i) = ds.mode // *(OUT + i) = ds.mode
// [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- pbuc1_derefidx_vbum1=_deref_pbuc2 // [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- pbuc1_derefidx_vbuz1=_deref_pbuc2
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy i ldy.z i
sta OUT,y sta OUT,y
// for(char i: 0..1) // for(char i: 0..1)
// [11] main::i#1 = ++ main::i#2 -- vbum1=_inc_vbum1 // [11] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
inc i inc.z i
// [12] if(main::i#1!=2) goto main::@1 -- vbum1_neq_vbuc1_then_la1 // [12] if(main::i#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #2 lda #2
cmp i cmp.z i
bne __b1 bne __b1
// main::@return // main::@return
// } // }
@ -567,7 +567,6 @@ main: {
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0 s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0 ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0 ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
i: .byte 0
} }
// File Data // File Data
__0: .byte 'A', 'R' __0: .byte 'A', 'R'

View File

@ -10,14 +10,14 @@ byte~ main::$12 reg byte a 22.0
byte~ main::$4 reg byte a 11.0 byte~ main::$4 reg byte a 11.0
struct deviceslot main::ds loadstore mem[66] struct deviceslot main::ds loadstore mem[66]
byte main::i byte main::i
byte main::i#1 i mem[1] 16.5 byte main::i#1 i zp[1]:2 16.5
byte main::i#2 i mem[1] 9.166666666666666 byte main::i#2 i zp[1]:2 9.166666666666666
struct deviceslot main::s1 loadstore mem[66] struct deviceslot main::s1 loadstore mem[66]
struct deviceslot main::s2 loadstore mem[66] struct deviceslot main::s2 loadstore mem[66]
constant struct deviceslotsA* main::slotsA = &main::ssA constant struct deviceslotsA* main::slotsA = &main::ssA
volatile struct deviceslotsA main::ssA loadstore mem[132] volatile struct deviceslotsA main::ssA loadstore mem[132]
mem[1] [ main::i#2 main::i#1 ] zp[1]:2 [ main::i#2 main::i#1 ]
reg byte a [ main::$11 ] reg byte a [ main::$11 ]
reg byte a [ main::$12 ] reg byte a [ main::$12 ]
reg byte a [ main::$4 ] reg byte a [ main::$4 ]

View File

@ -0,0 +1,52 @@
// https://gitlab.com/camelot/kickc/-/issues/587
// Creating variable instances of structs with array members fails to compile
// Commodore 64 PRG executable file
.file [name="struct-46.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.const SIZEOF_STRUCT_OTHER = 2
.const SIZEOF_STRUCT_NETCONFIG = $60
.label OUT = $8000
.segment Code
main: {
// Other x
ldy #SIZEOF_STRUCT_OTHER
lda #0
!:
dey
sta x,y
bne !-
// NetConfig a = {"123", "abc"}
ldy #SIZEOF_STRUCT_NETCONFIG
!:
lda __0-1,y
sta a-1,y
dey
bne !-
// *(OUT + 0) = a.ssid[0]
lda a
sta OUT
// NetConfig b
ldy #SIZEOF_STRUCT_NETCONFIG
lda #0
!:
dey
sta b,y
bne !-
// }
rts
.segment Data
x: .fill SIZEOF_STRUCT_OTHER, 0
a: .fill SIZEOF_STRUCT_NETCONFIG, 0
b: .fill SIZEOF_STRUCT_NETCONFIG, 0
}
__0: .text "123"
.byte 0
.fill $1c, 0
.text "abc"
.byte 0
.fill $3c, 0

View File

@ -0,0 +1,11 @@
void main()
main: scope:[main] from
[0] *(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER)
[1] *(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG)
[2] *OUT = *((byte*)&main::a)
[3] *(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG)
to:main::@return
main::@return: scope:[main] from main
[4] return
to:@return

291
src/test/ref/struct-46.log Normal file
View File

@ -0,0 +1,291 @@
Fixing struct type size struct netconfig to 96
Fixing struct type size struct netconfig to 96
Fixing struct type size struct netconfig to 96
Fixing struct type SIZE_OF struct netconfig to 96
Fixing struct type SIZE_OF struct netconfig to 96
Inlined call call __init
Removing C-classic struct-unwound assignment main::x = struct-unwound {*(&main::x)}
Removing C-classic struct-unwound assignment main::a = struct-unwound {*(&main::a)}
Removing C-classic struct-unwound assignment main::b = struct-unwound {*(&main::b)}
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start::@1
*(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER)
*(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG)
main::$0 = OUT + 0
*main::$0 = ((byte*)&main::a+OFFSET_STRUCT_NETCONFIG_SSID)[0]
*(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
to:__start::__init1
__start::__init1: scope:[__start] from __start
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
call main
to:__start::@2
__start::@2: scope:[__start] from __start::@1
to:__start::@return
__start::@return: scope:[__start] from __start::@2
return
to:@return
SYMBOL TABLE SSA
constant struct netconfig $0 = { ssid: "123", password: "abc" }
constant byte OFFSET_STRUCT_NETCONFIG_SSID = 0
constant const byte* OUT = (byte*)$8000
constant byte SIZEOF_STRUCT_NETCONFIG = $60
constant byte SIZEOF_STRUCT_OTHER = 2
void __start()
void main()
const byte*~ main::$0
struct netconfig main::a loadstore
struct netconfig main::b loadstore
struct other main::x loadstore
Adding number conversion cast (unumber) 0 in main::$0 = OUT + 0
Adding number conversion cast (unumber) 0 in *main::$0 = ((byte*)&main::a+OFFSET_STRUCT_NETCONFIG_SSID)[0]
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 32768
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) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant right-side identified [2] main::$0 = OUT + 0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::$0 = OUT+0
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero OUT in
Simplifying expression containing zero (byte*)&main::a+OFFSET_STRUCT_NETCONFIG_SSID in [3] *main::$0 = ((byte*)&main::a+OFFSET_STRUCT_NETCONFIG_SSID)[0]
Simplifying expression containing zero (byte*)&main::a in [3] *main::$0 = *((byte*)&main::a+OFFSET_STRUCT_NETCONFIG_SSID)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_STRUCT_NETCONFIG_SSID
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Constant inlined main::$0 = OUT
Successful SSA optimization Pass2ConstantInlining
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $40
Finalized unsigned number type (byte) $40
Successful SSA optimization PassNFinalizeNumberTypeConversions
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER)
[1] *(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG)
[2] *OUT = *((byte*)&main::a)
[3] *(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG)
to:main::@return
main::@return: scope:[main] from main
[4] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
struct netconfig main::a loadstore
struct netconfig main::b loadstore
struct other main::x loadstore
Initial phi equivalence classes
Added variable main::x to live range equivalence class [ main::x ]
Added variable main::a to live range equivalence class [ main::a ]
Added variable main::b to live range equivalence class [ main::b ]
Complete equivalence classes
[ main::x ]
[ main::a ]
[ main::b ]
Allocated mem[2] [ main::x ]
Allocated mem[96] [ main::a ]
Allocated mem[96] [ main::b ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER) [ main::a main::b ] ( [ main::a main::b ] { } ) always clobbers reg byte a reg byte y
Statement [1] *(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG) [ main::a main::b ] ( [ main::a main::b ] { } ) always clobbers reg byte a reg byte y
Statement [2] *OUT = *((byte*)&main::a) [ main::b ] ( [ main::b ] { } ) always clobbers reg byte a
Statement [3] *(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
Potential registers mem[2] [ main::x ] : mem[2] ,
Potential registers mem[96] [ main::a ] : mem[96] ,
Potential registers mem[96] [ main::b ] : mem[96] ,
REGISTER UPLIFT SCOPES
Uplift Scope [netconfig]
Uplift Scope [other]
Uplift Scope [main] 0: mem[2] [ main::x ] 0: mem[96] [ main::a ] 0: mem[96] [ main::b ]
Uplift Scope []
Uplifting [netconfig] best 59 combination
Uplifting [other] best 59 combination
Uplifting [main] best 59 combination mem[2] [ main::x ] mem[96] [ main::a ] mem[96] [ main::b ]
Uplifting [] best 59 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// https://gitlab.com/camelot/kickc/-/issues/587
// Creating variable instances of structs with array members fails to compile
// Upstart
// Commodore 64 PRG executable file
.file [name="struct-46.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const SIZEOF_STRUCT_OTHER = 2
.const SIZEOF_STRUCT_NETCONFIG = $60
.label OUT = $8000
.segment Code
// main
main: {
// [0] *(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_OTHER
lda #0
!:
dey
sta x,y
bne !-
// [1] *(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_NETCONFIG
!:
lda __0-1,y
sta a-1,y
dey
bne !-
// [2] *OUT = *((byte*)&main::a) -- _deref_pbuc1=_deref_pbuc2
lda a
sta OUT
// [3] *(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_NETCONFIG
lda #0
!:
dey
sta b,y
bne !-
jmp __breturn
// main::@return
__breturn:
// [4] return
rts
.segment Data
x: .fill SIZEOF_STRUCT_OTHER, 0
a: .fill SIZEOF_STRUCT_NETCONFIG, 0
b: .fill SIZEOF_STRUCT_NETCONFIG, 0
}
// File Data
__0: .text "123"
.byte 0
.fill $1c, 0
.text "abc"
.byte 0
.fill $3c, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
constant struct netconfig $0 = { ssid: "123", password: "abc" }
constant const byte* OUT = (byte*) 32768
constant byte SIZEOF_STRUCT_NETCONFIG = $60
constant byte SIZEOF_STRUCT_OTHER = 2
void main()
struct netconfig main::a loadstore mem[96]
struct netconfig main::b loadstore mem[96]
struct other main::x loadstore mem[2]
mem[2] [ main::x ]
mem[96] [ main::a ]
mem[96] [ main::b ]
FINAL ASSEMBLER
Score: 56
// File Comments
// https://gitlab.com/camelot/kickc/-/issues/587
// Creating variable instances of structs with array members fails to compile
// Upstart
// Commodore 64 PRG executable file
.file [name="struct-46.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.const SIZEOF_STRUCT_OTHER = 2
.const SIZEOF_STRUCT_NETCONFIG = $60
.label OUT = $8000
.segment Code
// main
main: {
// Other x
// [0] *(&main::x) = memset(struct other, SIZEOF_STRUCT_OTHER) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_OTHER
lda #0
!:
dey
sta x,y
bne !-
// NetConfig a = {"123", "abc"}
// [1] *(&main::a) = memcpy(*(&$0), struct netconfig, SIZEOF_STRUCT_NETCONFIG) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_NETCONFIG
!:
lda __0-1,y
sta a-1,y
dey
bne !-
// *(OUT + 0) = a.ssid[0]
// [2] *OUT = *((byte*)&main::a) -- _deref_pbuc1=_deref_pbuc2
lda a
sta OUT
// NetConfig b
// [3] *(&main::b) = memset(struct netconfig, SIZEOF_STRUCT_NETCONFIG) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_NETCONFIG
lda #0
!:
dey
sta b,y
bne !-
// main::@return
// }
// [4] return
rts
.segment Data
x: .fill SIZEOF_STRUCT_OTHER, 0
a: .fill SIZEOF_STRUCT_NETCONFIG, 0
b: .fill SIZEOF_STRUCT_NETCONFIG, 0
}
// File Data
__0: .text "123"
.byte 0
.fill $1c, 0
.text "abc"
.byte 0
.fill $3c, 0

View File

@ -0,0 +1,12 @@
constant struct netconfig $0 = { ssid: "123", password: "abc" }
constant const byte* OUT = (byte*) 32768
constant byte SIZEOF_STRUCT_NETCONFIG = $60
constant byte SIZEOF_STRUCT_OTHER = 2
void main()
struct netconfig main::a loadstore mem[96]
struct netconfig main::b loadstore mem[96]
struct other main::x loadstore mem[2]
mem[2] [ main::x ]
mem[96] [ main::a ]
mem[96] [ main::b ]