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
@ -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 {
|
||||||
|
@ -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
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
|
.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"
|
||||||
|
@ -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'
|
||||||
|
@ -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 ]
|
||||||
|
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