mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-24 04:31:02 +00:00
Struct Array problems fixed with #pragma struct_model(classic). Closes #590
This commit is contained in:
parent
689246780e
commit
8b69a1f583
@ -2318,6 +2318,11 @@ public class TestProgramsFast extends TestPrograms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStruct45() throws IOException {
|
||||||
|
compileAndCompare("struct-45.c");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStruct44() throws IOException {
|
public void testStruct44() throws IOException {
|
||||||
compileAndCompare("struct-44.c");
|
compileAndCompare("struct-44.c");
|
||||||
|
33
src/test/kc/struct-45.c
Normal file
33
src/test/kc/struct-45.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
99
src/test/ref/struct-45.asm
Normal file
99
src/test/ref/struct-45.asm
Normal 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
|
22
src/test/ref/struct-45.cfg
Normal file
22
src/test/ref/struct-45.cfg
Normal 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
581
src/test/ref/struct-45.log
Normal 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
|
||||||
|
|
27
src/test/ref/struct-45.sym
Normal file
27
src/test/ref/struct-45.sym
Normal 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 ]
|
Loading…
Reference in New Issue
Block a user