1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-30 09:57:11 +00:00

Struct Array problems fixed with #pragma struct_model(classic). Closes #590

This commit is contained in:
jespergravgaard 2021-08-02 12:43:47 +02:00
parent 689246780e
commit 8b69a1f583
6 changed files with 767 additions and 0 deletions

View File

@ -2318,6 +2318,11 @@ public class TestProgramsFast extends TestPrograms {
}
@Test
public void testStruct45() throws IOException {
compileAndCompare("struct-45.c");
}
@Test
public void testStruct44() throws IOException {
compileAndCompare("struct-44.c");

33
src/test/kc/struct-45.c Normal file
View File

@ -0,0 +1,33 @@
// https://gitlab.com/camelot/kickc/-/issues/590
#pragma var_model(mem)
#pragma struct_model(classic)
struct deviceslot {
unsigned char hostSlot;
unsigned char mode;
unsigned char file[64];
};
typedef struct deviceslot deviceslot_t;
typedef struct deviceslotsA {
deviceslot_t slot[2];
} DeviceSlotsA;
char * const OUT = (char *)0x8000;
void main() {
deviceslot_t s1 = {'A', 'R', "f1"};
deviceslot_t s2 = {'B', 'W', "f2"};
DeviceSlotsA ssA;
DeviceSlotsA *slotsA = &ssA;
slotsA->slot[0] = s1;
slotsA->slot[1] = s2;
for(char i: 0..1) {
deviceslot_t ds = slotsA->slot[i];
*(OUT + i) = ds.mode;
}
}

View File

@ -0,0 +1,99 @@
// https://gitlab.com/camelot/kickc/-/issues/590
// Commodore 64 PRG executable file
.file [name="struct-45.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_DEVICESLOT = $42
.const SIZEOF_STRUCT_DEVICESLOTSA = $84
.const OFFSET_STRUCT_DEVICESLOT_MODE = 1
.label OUT = $8000
.segment Code
main: {
.label slotsA = ssA
// deviceslot_t s1 = {'A', 'R', "f1"}
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda __0-1,y
sta s1-1,y
dey
bne !-
// deviceslot_t s2 = {'B', 'W', "f2"}
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda __1-1,y
sta s2-1,y
dey
bne !-
// DeviceSlotsA ssA
ldy #SIZEOF_STRUCT_DEVICESLOTSA
lda #0
!:
dey
sta ssA,y
bne !-
// slotsA->slot[0] = s1
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s1-1,y
sta slotsA-1,y
dey
bne !-
// slotsA->slot[1] = s2
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s2-1,y
sta slotsA+1*SIZEOF_STRUCT_DEVICESLOT-1,y
dey
bne !-
lda #0
sta i
__b1:
// deviceslot_t ds = slotsA->slot[i]
lda i
asl
asl
asl
asl
asl
clc
adc i
asl
tax
ldy #0
!:
lda slotsA,x
sta ds,y
inx
iny
cpy #SIZEOF_STRUCT_DEVICESLOT
bne !-
// *(OUT + i) = ds.mode
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy i
sta OUT,y
// for(char i: 0..1)
inc i
lda #2
cmp i
bne __b1
// }
rts
.segment Data
s1: .fill SIZEOF_STRUCT_DEVICESLOT, 0
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"
.byte 0
.fill $3d, 0
__1: .byte 'B', 'W'
.text "f2"
.byte 0
.fill $3d, 0

View File

@ -0,0 +1,22 @@
void main()
main: scope:[main] from
[0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[1] *(&main::s2) = memcpy(*(&$1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA)
[3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
to:main::@1
main::@1: scope:[main] from main main::@1
[5] main::i#2 = phi( main/0, main::@1/main::i#1 )
[6] main::$11 = main::i#2 << 5
[7] main::$12 = main::$11 + main::i#2
[8] main::$4 = main::$12 << 1
[9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE)
[11] main::i#1 = ++ main::i#2
[12] if(main::i#1!=2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[13] return
to:@return

581
src/test/ref/struct-45.log Normal file
View File

@ -0,0 +1,581 @@
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
Fixing struct type size struct deviceslot to 66
Fixing struct type size struct deviceslotsA to 132
Fixing struct type SIZE_OF struct deviceslot to 66
Fixing struct type SIZE_OF struct deviceslotsA to 132
Fixing struct type SIZE_OF struct deviceslot to 66
Fixing struct type SIZE_OF struct deviceslotsA to 132
Setting struct to load/store in variable affected by address-of main::slotsA = &main::ssA
Removing C-classic struct-unwound assignment main::s1 = struct-unwound {*(&main::s1)}
Removing C-classic struct-unwound assignment main::s2 = struct-unwound {*(&main::s2)}
Removing C-classic struct-unwound assignment main::ssA = struct-unwound {*(&main::ssA)}
Removing C-classic struct-unwound assignment main::ds = struct-unwound {*(&main::ds)}
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
*(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
*(&main::s2) = memcpy(*(&$1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
*(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA)
main::$2 = 0 * SIZEOF_STRUCT_DEVICESLOT
main::$8 = (struct deviceslot*)main::slotsA
main::$5 = main::$8 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
main::$5[main::$2] = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
main::$3 = 1 * SIZEOF_STRUCT_DEVICESLOT
main::$9 = (struct deviceslot*)main::slotsA
main::$6 = main::$9 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
main::$6[main::$3] = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
main::i#0 = 0
to:main::@1
main::@1: scope:[main] from main main::@1
main::i#2 = phi( main/main::i#0, main::@1/main::i#1 )
main::$4 = main::i#2 * SIZEOF_STRUCT_DEVICESLOT
main::$10 = (struct deviceslot*)main::slotsA
main::$7 = main::$10 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
*(&main::ds) = memcpy(main::$7[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
main::$0 = OUT + main::i#2
*main::$0 = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE)
main::i#1 = main::i#2 + rangenext(0,1)
main::$1 = main::i#1 != rangelast(0,1)
if(main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
constant struct deviceslot $0 = { hostSlot: 'A', mode: 'R', file: "f1" }
constant struct deviceslot $1 = { hostSlot: 'B', mode: 'W', file: "f2" }
constant byte OFFSET_STRUCT_DEVICESLOTSA_SLOT = 0
constant byte OFFSET_STRUCT_DEVICESLOT_MODE = 1
constant byte* const OUT = (byte*)$8000
constant byte SIZEOF_STRUCT_DEVICESLOT = $42
constant byte SIZEOF_STRUCT_DEVICESLOTSA = $84
void __start()
void main()
byte*~ main::$0
bool~ main::$1
struct deviceslot*~ main::$10
number~ main::$2
number~ main::$3
byte~ main::$4
struct deviceslot*~ main::$5
struct deviceslot*~ main::$6
struct deviceslot*~ main::$7
struct deviceslot*~ main::$8
struct deviceslot*~ main::$9
struct deviceslot main::ds loadstore
byte main::i
byte main::i#0
byte main::i#1
byte main::i#2
struct deviceslot main::s1 loadstore
struct deviceslot main::s2 loadstore
constant struct deviceslotsA* main::slotsA = &main::ssA
volatile struct deviceslotsA main::ssA loadstore
Adding number conversion cast (unumber) 0 in main::$2 = 0 * SIZEOF_STRUCT_DEVICESLOT
Adding number conversion cast (unumber) main::$2 in main::$2 = (unumber)0 * SIZEOF_STRUCT_DEVICESLOT
Adding number conversion cast (unumber) 1 in main::$3 = 1 * SIZEOF_STRUCT_DEVICESLOT
Adding number conversion cast (unumber) main::$3 in main::$3 = (unumber)1 * SIZEOF_STRUCT_DEVICESLOT
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (byte*) 32768
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in main::$2 = 0 * SIZEOF_STRUCT_DEVICESLOT
Inferred type updated to byte in main::$3 = 1 * SIZEOF_STRUCT_DEVICESLOT
Simple Condition main::$1 [21] if(main::i#1!=rangelast(0,1)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [3] main::$2 = 0 * SIZEOF_STRUCT_DEVICESLOT
Constant right-side identified [4] main::$8 = (struct deviceslot*)main::slotsA
Constant right-side identified [7] main::$3 = 1 * SIZEOF_STRUCT_DEVICESLOT
Constant right-side identified [8] main::$9 = (struct deviceslot*)main::slotsA
Constant right-side identified [14] main::$10 = (struct deviceslot*)main::slotsA
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::$2 = 0*SIZEOF_STRUCT_DEVICESLOT
Constant main::$8 = (struct deviceslot*)main::slotsA
Constant main::$3 = 1*SIZEOF_STRUCT_DEVICESLOT
Constant main::$9 = (struct deviceslot*)main::slotsA
Constant main::i#0 = 0
Constant main::$10 = (struct deviceslot*)main::slotsA
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [19] main::i#1 = ++ main::i#2 to ++
Resolved ranged comparison value [21] if(main::i#1!=rangelast(0,1)) goto main::@1 to 2
Converting *(pointer+n) to pointer[n] [18] *main::$0 = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- OUT[main::i#2]
Successful SSA optimization Pass2InlineDerefIdx
Simplifying constant evaluating to zero 0*SIZEOF_STRUCT_DEVICESLOT in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero main::$8 in [5] main::$5 = main::$8 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
Simplifying expression containing zero main::$5 in [6] main::$5[main::$2] = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
Simplifying expression containing zero main::$9 in [9] main::$6 = main::$9 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
Simplifying expression containing zero main::$10 in [15] main::$7 = main::$10 + OFFSET_STRUCT_DEVICESLOTSA_SLOT
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable main::$0 and assignment [11] main::$0 = OUT + main::i#2
Eliminating unused constant main::$2
Eliminating unused constant OFFSET_STRUCT_DEVICESLOTSA_SLOT
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Adding number conversion cast (unumber) 2 in [13] if(main::i#1!=2) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 2
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant main::$5 = main::$8
Constant main::$6 = main::$9
Constant main::$7 = main::$10
Successful SSA optimization Pass2ConstantIdentification
Rewriting multiplication to use shift and addition[6] main::$4 = main::i#2 * SIZEOF_STRUCT_DEVICESLOT
Inlining constant with var siblings main::i#0
Constant inlined main::$5 = (struct deviceslot*)main::slotsA
Constant inlined main::i#0 = 0
Constant inlined main::$6 = (struct deviceslot*)main::slotsA
Constant inlined main::$3 = 1*SIZEOF_STRUCT_DEVICESLOT
Constant inlined main::$9 = (struct deviceslot*)main::slotsA
Constant inlined main::$10 = (struct deviceslot*)main::slotsA
Constant inlined main::$7 = (struct deviceslot*)main::slotsA
Constant inlined main::$8 = (struct deviceslot*)main::slotsA
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT)
Successful SSA optimization Pass2ConstantAdditionElimination
Alias main::$4 = main::$13
Successful SSA optimization Pass2AliasElimination
Finalized unsigned number type (byte) $40
Finalized unsigned number type (byte) $40
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Added new block during phi lifting main::@2(between main::@1 and main::@1)
CALL GRAPH
Created 1 initial phi equivalence classes
Coalesced [14] main::i#3 = main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block label main::@2
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[1] *(&main::s2) = memcpy(*(&$1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA)
[3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
to:main::@1
main::@1: scope:[main] from main main::@1
[5] main::i#2 = phi( main/0, main::@1/main::i#1 )
[6] main::$11 = main::i#2 << 5
[7] main::$12 = main::$11 + main::i#2
[8] main::$4 = main::$12 << 1
[9] *(&main::ds) = memcpy(((struct deviceslot*)main::slotsA)[main::$4], struct deviceslot, SIZEOF_STRUCT_DEVICESLOT)
[10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE)
[11] main::i#1 = ++ main::i#2
[12] if(main::i#1!=2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
byte~ main::$11 22.0
byte~ main::$12 22.0
byte~ main::$4 11.0
struct deviceslot main::ds loadstore
byte main::i
byte main::i#1 16.5
byte main::i#2 9.166666666666666
struct deviceslot main::s1 loadstore
struct deviceslot main::s2 loadstore
volatile struct deviceslotsA main::ssA loadstore
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Added variable main::$11 to live range equivalence class [ main::$11 ]
Added variable main::$12 to live range equivalence class [ main::$12 ]
Added variable main::$4 to live range equivalence class [ main::$4 ]
Added variable main::s1 to live range equivalence class [ main::s1 ]
Added variable main::s2 to live range equivalence class [ main::s2 ]
Added variable main::ssA to live range equivalence class [ main::ssA ]
Added variable main::ds to live range equivalence class [ main::ds ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::$11 ]
[ main::$12 ]
[ main::$4 ]
[ main::s1 ]
[ 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 mem[66] [ main::s1 ]
Allocated mem[66] [ main::s2 ]
Allocated mem[132] [ main::ssA ]
Allocated mem[66] [ main::ds ]
REGISTER UPLIFT POTENTIAL REGISTERS
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 [1] *(&main::s2) = memcpy(*(&$1), 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 [2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA) [ main::s2 main::s1 main::ds ] ( [ main::s2 main::s1 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 [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 ]
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 ]
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
Statement [1] *(&main::s2) = memcpy(*(&$1), 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 [2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA) [ main::s2 main::s1 main::ds ] ( [ main::s2 main::s1 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 [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 [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
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 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 [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 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// https://gitlab.com/camelot/kickc/-/issues/590
// Upstart
// Commodore 64 PRG executable file
.file [name="struct-45.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_DEVICESLOT = $42
.const SIZEOF_STRUCT_DEVICESLOTSA = $84
.const OFFSET_STRUCT_DEVICESLOT_MODE = 1
.label OUT = $8000
.segment Code
// main
main: {
.label slotsA = ssA
// [0] *(&main::s1) = memcpy(*(&$0), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda __0-1,y
sta s1-1,y
dey
bne !-
// [1] *(&main::s2) = memcpy(*(&$1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda __1-1,y
sta s2-1,y
dey
bne !-
// [2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_DEVICESLOTSA
lda #0
!:
dey
sta ssA,y
bne !-
// [3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s1-1,y
sta slotsA-1,y
dey
bne !-
// [4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s2-1,y
sta slotsA+1*SIZEOF_STRUCT_DEVICESLOT-1,y
dey
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
lda #0
sta i
jmp __b1
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
__b1_from___b1:
// [5] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp __b1
// main::@1
__b1:
// [6] main::$11 = main::i#2 << 5 -- vbuaa=vbum1_rol_5
lda i
asl
asl
asl
asl
asl
// [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbum1
clc
adc 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
tax
ldy #0
!:
lda slotsA,x
sta ds,y
inx
iny
cpy #SIZEOF_STRUCT_DEVICESLOT
bne !-
// [10] OUT[main::i#2] = *((byte*)&main::ds+OFFSET_STRUCT_DEVICESLOT_MODE) -- pbuc1_derefidx_vbum1=_deref_pbuc2
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy 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
lda #2
cmp i
bne __b1_from___b1
jmp __breturn
// main::@return
__breturn:
// [13] return
rts
.segment Data
s1: .fill SIZEOF_STRUCT_DEVICESLOT, 0
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'
.text "f1"
.byte 0
.fill $3d, 0
__1: .byte 'B', 'W'
.text "f2"
.byte 0
.fill $3d, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __b1_from___b1 with __b1
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1_from_main:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
constant struct deviceslot $0 = { hostSlot: 'A', mode: 'R', file: "f1" }
constant struct deviceslot $1 = { hostSlot: 'B', mode: 'W', file: "f2" }
constant byte OFFSET_STRUCT_DEVICESLOT_MODE = 1
constant byte* const OUT = (byte*) 32768
constant byte SIZEOF_STRUCT_DEVICESLOT = $42
constant byte SIZEOF_STRUCT_DEVICESLOTSA = $84
void main()
byte~ main::$11 reg byte a 22.0
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
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 ]
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 ]
FINAL ASSEMBLER
Score: 858
// File Comments
// https://gitlab.com/camelot/kickc/-/issues/590
// Upstart
// Commodore 64 PRG executable file
.file [name="struct-45.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_DEVICESLOT = $42
.const SIZEOF_STRUCT_DEVICESLOTSA = $84
.const OFFSET_STRUCT_DEVICESLOT_MODE = 1
.label OUT = $8000
.segment Code
// main
main: {
.label slotsA = ssA
// 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
!:
lda __0-1,y
sta s1-1,y
dey
bne !-
// deviceslot_t s2 = {'B', 'W', "f2"}
// [1] *(&main::s2) = memcpy(*(&$1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda __1-1,y
sta s2-1,y
dey
bne !-
// DeviceSlotsA ssA
// [2] *(&main::ssA) = memset(struct deviceslotsA, SIZEOF_STRUCT_DEVICESLOTSA) -- _deref_pssc1=_memset_vbuc2
ldy #SIZEOF_STRUCT_DEVICESLOTSA
lda #0
!:
dey
sta ssA,y
bne !-
// slotsA->slot[0] = s1
// [3] *((struct deviceslot*)main::slotsA) = memcpy(*(&main::s1), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s1-1,y
sta slotsA-1,y
dey
bne !-
// slotsA->slot[1] = s2
// [4] *((struct deviceslot*)main::slotsA+1*SIZEOF_STRUCT_DEVICESLOT) = memcpy(*(&main::s2), struct deviceslot, SIZEOF_STRUCT_DEVICESLOT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_DEVICESLOT
!:
lda s2-1,y
sta slotsA+1*SIZEOF_STRUCT_DEVICESLOT-1,y
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
lda #0
sta 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
asl
asl
asl
asl
asl
// [7] main::$12 = main::$11 + main::i#2 -- vbuaa=vbuaa_plus_vbum1
clc
adc 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
tax
ldy #0
!:
lda slotsA,x
sta ds,y
inx
iny
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
lda ds+OFFSET_STRUCT_DEVICESLOT_MODE
ldy 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
lda #2
cmp i
bne __b1
// main::@return
// }
// [13] return
rts
.segment Data
s1: .fill SIZEOF_STRUCT_DEVICESLOT, 0
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'
.text "f1"
.byte 0
.fill $3d, 0
__1: .byte 'B', 'W'
.text "f2"
.byte 0
.fill $3d, 0

View File

@ -0,0 +1,27 @@
constant struct deviceslot $0 = { hostSlot: 'A', mode: 'R', file: "f1" }
constant struct deviceslot $1 = { hostSlot: 'B', mode: 'W', file: "f2" }
constant byte OFFSET_STRUCT_DEVICESLOT_MODE = 1
constant byte* const OUT = (byte*) 32768
constant byte SIZEOF_STRUCT_DEVICESLOT = $42
constant byte SIZEOF_STRUCT_DEVICESLOTSA = $84
void main()
byte~ main::$11 reg byte a 22.0
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
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 ]
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 ]