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:
parent
6c4d0488b9
commit
4f2ae64cac
src/test
@ -2322,6 +2322,10 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("union-0.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct46() throws IOException {
|
||||
compileAndCompare("struct-46.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStruct45() throws IOException {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// https://gitlab.com/camelot/kickc/-/issues/590
|
||||
|
||||
#pragma var_model(mem)
|
||||
#pragma struct_model(classic)
|
||||
#pragma var_model(struct_mem)
|
||||
|
||||
struct deviceslot {
|
||||
unsigned char hostSlot;
|
||||
|
26
src/test/kc/struct-46.c
Normal file
26
src/test/kc/struct-46.c
Normal 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;
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
.segment Code
|
||||
main: {
|
||||
.label slotsA = ssA
|
||||
.label i = 2
|
||||
// deviceslot_t s1 = {'A', 'R', "f1"}
|
||||
ldy #SIZEOF_STRUCT_DEVICESLOT
|
||||
!:
|
||||
@ -50,17 +51,17 @@ main: {
|
||||
dey
|
||||
bne !-
|
||||
lda #0
|
||||
sta i
|
||||
sta.z i
|
||||
__b1:
|
||||
// deviceslot_t ds = slotsA->slot[i]
|
||||
lda i
|
||||
lda.z i
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
clc
|
||||
adc i
|
||||
adc.z i
|
||||
asl
|
||||
tax
|
||||
ldy #0
|
||||
@ -73,12 +74,12 @@ main: {
|
||||
bne !-
|
||||
// *(OUT + i) = ds.mode
|
||||
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
|
||||
ldy i
|
||||
ldy.z i
|
||||
sta OUT,y
|
||||
// for(char i: 0..1)
|
||||
inc i
|
||||
inc.z i
|
||||
lda #2
|
||||
cmp i
|
||||
cmp.z i
|
||||
bne __b1
|
||||
// }
|
||||
rts
|
||||
@ -87,7 +88,6 @@ main: {
|
||||
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
|
||||
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
i: .byte 0
|
||||
}
|
||||
__0: .byte 'A', 'R'
|
||||
.text "f1"
|
||||
|
@ -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 deviceslotsA to 132
|
||||
Fixing struct type size struct deviceslot to 66
|
||||
@ -231,10 +230,10 @@ Complete equivalence classes
|
||||
[ main::s2 ]
|
||||
[ main::ssA ]
|
||||
[ main::ds ]
|
||||
Allocated mem[1] [ main::i#2 main::i#1 ]
|
||||
Allocated mem[1] [ main::$11 ]
|
||||
Allocated mem[1] [ main::$12 ]
|
||||
Allocated mem[1] [ main::$4 ]
|
||||
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp[1]:3 [ main::$11 ]
|
||||
Allocated zp[1]:4 [ main::$12 ]
|
||||
Allocated zp[1]:5 [ main::$4 ]
|
||||
Allocated mem[66] [ main::s1 ]
|
||||
Allocated mem[66] [ main::s2 ]
|
||||
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 [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
|
||||
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 [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
|
||||
Removing always clobbered register reg byte x as potential for mem[1] [ 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 x as potential for zp[1]:2 [ 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 [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
|
||||
@ -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 [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
|
||||
Potential registers mem[1] [ main::i#2 main::i#1 ] : mem[1] ,
|
||||
Potential registers mem[1] [ main::$11 ] : mem[1] , 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 mem[1] [ main::$4 ] : mem[1] , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 ,
|
||||
Potential registers zp[1]:3 [ main::$11 ] : zp[1]:3 , 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 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::s2 ] : mem[66] ,
|
||||
Potential registers mem[132] [ main::ssA ] : mem[132] ,
|
||||
Potential registers mem[66] [ main::ds ] : mem[66] ,
|
||||
|
||||
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 [deviceslotsA]
|
||||
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 [deviceslot] best 948 combination
|
||||
Uplifting [deviceslotsA] best 948 combination
|
||||
Uplifting [] best 948 combination
|
||||
Attempting to uplift remaining variables inmem[1] [ 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 ] 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 888 combination
|
||||
Uplifting [deviceslotsA] best 888 combination
|
||||
Uplifting [] best 888 combination
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 888 combination zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -308,6 +307,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
// main
|
||||
main: {
|
||||
.label slotsA = ssA
|
||||
.label i = 2
|
||||
// [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_DEVICESLOT
|
||||
!:
|
||||
@ -345,9 +345,9 @@ main: {
|
||||
bne !-
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
__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
|
||||
sta i
|
||||
sta.z i
|
||||
jmp __b1
|
||||
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
|
||||
__b1_from___b1:
|
||||
@ -355,16 +355,16 @@ main: {
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbum1_rol_5
|
||||
lda i
|
||||
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbuz1_rol_5
|
||||
lda.z i
|
||||
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
|
||||
adc i
|
||||
adc.z i
|
||||
// [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
// [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
|
||||
cpy #SIZEOF_STRUCT_DEVICESLOT
|
||||
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
|
||||
ldy i
|
||||
ldy.z i
|
||||
sta OUT,y
|
||||
// [11] main::i#1 = ++ main::i#2 -- vbum1=_inc_vbum1
|
||||
inc i
|
||||
// [12] if(main::i#1!=2) goto main::@1 -- vbum1_neq_vbuc1_then_la1
|
||||
// [11] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [12] if(main::i#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #2
|
||||
cmp i
|
||||
cmp.z i
|
||||
bne __b1_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
@ -397,7 +397,6 @@ main: {
|
||||
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
|
||||
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
i: .byte 0
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 'A', 'R'
|
||||
@ -435,14 +434,14 @@ byte~ main::$12 reg byte a 22.0
|
||||
byte~ main::$4 reg byte a 11.0
|
||||
struct deviceslot main::ds loadstore mem[66]
|
||||
byte main::i
|
||||
byte main::i#1 i mem[1] 16.5
|
||||
byte main::i#2 i mem[1] 9.166666666666666
|
||||
byte main::i#1 i zp[1]:2 16.5
|
||||
byte main::i#2 i zp[1]:2 9.166666666666666
|
||||
struct deviceslot main::s1 loadstore mem[66]
|
||||
struct deviceslot main::s2 loadstore mem[66]
|
||||
constant struct deviceslotsA* main::slotsA = &main::ssA
|
||||
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::$12 ]
|
||||
reg byte a [ main::$4 ]
|
||||
@ -453,7 +452,7 @@ mem[66] [ main::ds ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 858
|
||||
Score: 798
|
||||
|
||||
// File Comments
|
||||
// https://gitlab.com/camelot/kickc/-/issues/590
|
||||
@ -475,6 +474,7 @@ Score: 858
|
||||
// main
|
||||
main: {
|
||||
.label slotsA = ssA
|
||||
.label i = 2
|
||||
// deviceslot_t s1 = {'A', 'R', "f1"}
|
||||
// [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_DEVICESLOT
|
||||
@ -516,24 +516,24 @@ main: {
|
||||
dey
|
||||
bne !-
|
||||
// [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
|
||||
sta i
|
||||
sta.z i
|
||||
// [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
|
||||
// main::@1
|
||||
__b1:
|
||||
// deviceslot_t ds = slotsA->slot[i]
|
||||
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbum1_rol_5
|
||||
lda i
|
||||
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbuz1_rol_5
|
||||
lda.z i
|
||||
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
|
||||
adc i
|
||||
adc.z i
|
||||
// [8] main::$4 = main::$12 << 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
// [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
|
||||
bne !-
|
||||
// *(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
|
||||
ldy i
|
||||
ldy.z i
|
||||
sta OUT,y
|
||||
// for(char i: 0..1)
|
||||
// [11] main::i#1 = ++ main::i#2 -- vbum1=_inc_vbum1
|
||||
inc i
|
||||
// [12] if(main::i#1!=2) goto main::@1 -- vbum1_neq_vbuc1_then_la1
|
||||
// [11] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [12] if(main::i#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #2
|
||||
cmp i
|
||||
cmp.z i
|
||||
bne __b1
|
||||
// main::@return
|
||||
// }
|
||||
@ -567,7 +567,6 @@ main: {
|
||||
s2: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
ssA: .fill SIZEOF_STRUCT_DEVICESLOTSA, 0
|
||||
ds: .fill SIZEOF_STRUCT_DEVICESLOT, 0
|
||||
i: .byte 0
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 'A', 'R'
|
||||
|
@ -10,14 +10,14 @@ byte~ main::$12 reg byte a 22.0
|
||||
byte~ main::$4 reg byte a 11.0
|
||||
struct deviceslot main::ds loadstore mem[66]
|
||||
byte main::i
|
||||
byte main::i#1 i mem[1] 16.5
|
||||
byte main::i#2 i mem[1] 9.166666666666666
|
||||
byte main::i#1 i zp[1]:2 16.5
|
||||
byte main::i#2 i zp[1]:2 9.166666666666666
|
||||
struct deviceslot main::s1 loadstore mem[66]
|
||||
struct deviceslot main::s2 loadstore mem[66]
|
||||
constant struct deviceslotsA* main::slotsA = &main::ssA
|
||||
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::$12 ]
|
||||
reg byte a [ main::$4 ]
|
||||
|
52
src/test/ref/struct-46.asm
Normal file
52
src/test/ref/struct-46.asm
Normal 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
|
11
src/test/ref/struct-46.cfg
Normal file
11
src/test/ref/struct-46.cfg
Normal 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
291
src/test/ref/struct-46.log
Normal 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
|
||||
|
12
src/test/ref/struct-46.sym
Normal file
12
src/test/ref/struct-46.sym
Normal 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 ]
|
Loading…
x
Reference in New Issue
Block a user