1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-26 12:49:21 +00:00

Added support for sizeof without parenthesis. Closes #695

This commit is contained in:
jespergravgaard 2021-08-07 17:21:47 +02:00
parent 1deb381c57
commit f60e1240e2
11 changed files with 990 additions and 884 deletions

View File

@ -222,8 +222,8 @@ expr
| expr DOT NAME #exprDot
| expr '->' NAME #exprArrow
| expr PAR_BEGIN parameterList? PAR_END #exprCall
| SIZEOF PAR_BEGIN ( expr | typeName ) PAR_END #exprSizeOf
| TYPEID PAR_BEGIN ( expr | typeName ) PAR_END #exprTypeId
| SIZEOF ( expr | PAR_BEGIN typeName PAR_END ) #exprSizeOf
| TYPEID ( expr | PAR_BEGIN typeName PAR_END ) #exprTypeId
| DEFINED PAR_BEGIN? NAME PAR_END? #exprDefined
| expr BRACKET_BEGIN commaExpr BRACKET_END #exprArray
| PAR_BEGIN typeName PAR_END expr #exprCast

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -199,6 +199,11 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("procedure-declare-0.c");
}
@Test
public void testSizeNoParen() throws IOException {
compileAndCompare("sizeof-noparen.c");
}
@Test
public void testSizeOfProblem() throws IOException {
compileAndCompare("sizeof-problem.c");

View File

@ -0,0 +1,18 @@
// Tests the sizeof operator without parenthesis
char* const SCREEN = (char*)0x400;
void main() {
char idx = 0;
// Simple types
char b = 0;
int w = 0;
SCREEN[idx++] = '0'+sizeof 0;
SCREEN[idx++] = '0'+sizeof b;
SCREEN[idx++] = '0'+sizeof w;
SCREEN[idx++] = '0'+sizeof (char);
SCREEN[idx++] = '0'+sizeof (int);
}

View File

@ -1,5 +1,5 @@
// Test labels/goto
// goto a nested label
// goto a label nested in a loop
// Commodore 64 PRG executable file
.file [name="labelgoto-5.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]

View File

@ -1,291 +1,3 @@
PARSING /Users/jespergravgaard/c64/kickc/src/test/kc/labelgoto-5.c
// Test labels/goto
// goto a nested label
void main() {
char * const SCREEN = (char*)0x0400;
char i = 0;
goto first;
for(;i<10;i++) {
SCREEN[i] = '*';
first:
SCREEN[40]++;
}
}
Adding pre/post-modifier main::SCREEN[$28] = ++ main::SCREEN[$28]
Adding pre/post-modifier main::i = ++ main::i
FIRST CONTROL FLOW GRAPH
void main()
main: scope:[main] from
main::i = 0
to:main::first
main::first: scope:[main] from main main:::1::@2
main:::1::$1 = main::SCREEN[$28]
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main:::1::@1
main::@1: scope:[main] from
to:main:::1::@1
main:::1::@1: scope:[main] from main::@1 main::first
main:::1::$0 = main::i < $a
if(main:::1::$0) goto main:::1::@2
to:main:::1::@4
main:::1::@2: scope:[main] from main:::1::@1 main:::1::@5
main::SCREEN[main::i] = '*'
to:main::first
main:::1::@4: scope:[main] from main:::1::@1
to:main:::1::@3
main:::1::@3: scope:[main] from main:::1::@4 main::@2
to:main::@return
main:::1::@5: scope:[main] from
to:main:::1::@2
main::@2: scope:[main] from
to:main:::1::@3
main::@return: scope:[main] from main:::1::@3
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@return
__start::@return: scope:[__start] from __start
return
to:@return
SYMBOLS
void __start()
void main()
bool~ main::$0
byte~ main::$1
constant byte* const main::SCREEN = (byte*)$400
byte main::i
CONTROL FLOW GRAPH BEFORE SIZEOF FIX
void main()
main: scope:[main] from
main::i = 0
to:main::first
main::first: scope:[main] from main main::@4
main::$1 = main::SCREEN[$28]
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main::@3
main::@1: scope:[main] from
to:main::@3
main::@3: scope:[main] from main::@1 main::first
main::$0 = main::i < $a
if(main::$0) goto main::@4
to:main::@6
main::@4: scope:[main] from main::@3 main::@7
main::SCREEN[main::i] = '*'
to:main::first
main::@6: scope:[main] from main::@3
to:main::@5
main::@5: scope:[main] from main::@2 main::@6
to:main::@return
main::@7: scope:[main] from
to:main::@4
main::@2: scope:[main] from
to:main::@5
main::@return: scope:[main] from main::@5
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@return
__start::@return: scope:[__start] from __start
return
to:@return
CONTROL FLOW GRAPH AFTER UNWIND
void main()
main: scope:[main] from
main::i = 0
to:main::first
main::first: scope:[main] from main main::@4
main::$1 = main::SCREEN[$28]
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main::@3
main::@1: scope:[main] from
to:main::@3
main::@3: scope:[main] from main::@1 main::first
main::$0 = main::i < $a
if(main::$0) goto main::@4
to:main::@6
main::@4: scope:[main] from main::@3 main::@7
main::SCREEN[main::i] = '*'
to:main::first
main::@6: scope:[main] from main::@3
to:main::@5
main::@5: scope:[main] from main::@2 main::@6
to:main::@return
main::@7: scope:[main] from
to:main::@4
main::@2: scope:[main] from
to:main::@5
main::@return: scope:[main] from main::@5
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@return
__start::@return: scope:[__start] from __start
return
to:@return
CONTROL FLOW GRAPH BEFORE INLINING
void main()
main: scope:[main] from
main::i = 0
to:main::first
main::first: scope:[main] from main main::@4
main::$1 = main::SCREEN[$28]
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main::@3
main::@1: scope:[main] from
to:main::@3
main::@3: scope:[main] from main::@1 main::first
main::$0 = main::i < $a
if(main::$0) goto main::@4
to:main::@6
main::@4: scope:[main] from main::@3 main::@7
main::SCREEN[main::i] = '*'
to:main::first
main::@6: scope:[main] from main::@3
to:main::@5
main::@5: scope:[main] from main::@2 main::@6
to:main::@return
main::@7: scope:[main] from
to:main::@4
main::@2: scope:[main] from
to:main::@5
main::@return: scope:[main] from main::@5
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@return
__start::@return: scope:[__start] from __start
return
to:@return
INITIAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] main::i = 0
to:main::first
main::first: scope:[main] from main main::@4
[1] main::$1 = main::SCREEN[$28]
[2] main::SCREEN[$28] = ++ main::SCREEN[$28]
[3] main::i = ++ main::i
to:main::@3
main::@1: scope:[main] from
to:main::@3
main::@3: scope:[main] from main::@1 main::first
[4] main::$0 = main::i < $a
[5] if(main::$0) goto main::@4
to:main::@6
main::@4: scope:[main] from main::@3 main::@7
[6] main::SCREEN[main::i] = '*'
to:main::first
main::@6: scope:[main] from main::@3
to:main::@5
main::@5: scope:[main] from main::@2 main::@6
to:main::@return
main::@7: scope:[main] from
to:main::@4
main::@2: scope:[main] from
to:main::@5
main::@return: scope:[main] from main::@5
[7] return
to:@return
void __start()
__start: scope:[__start] from
[8] call main
to:__start::@return
__start::@return: scope:[__start] from __start
[9] return
to:@return
Eliminating unused variable main::$1 and assignment [1] main::$1 = main::SCREEN[$28]
PROCEDURE MODIFY VARIABLE ANALYSIS
PROCEDURE CALLS
void main()
main: scope:[main] from
main::i = 0
to:main::first
main::first: scope:[main] from main main::@2
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main::@1
main::@1: scope:[main] from main::first
main::$0 = main::i < $a
if(main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
main::SCREEN[main::i] = '*'
to:main::first
main::@return: scope:[main] from main::@1
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@return
__start::@return: scope:[__start] from __start
return
to:@return
PROCEDURE PARAMETERS
void main()
main: scope:[main] from __start
main::i = 0
to:main::first
main::first: scope:[main] from main main::@2
main::SCREEN[$28] = ++ main::SCREEN[$28]
main::i = ++ main::i
to:main::@1
main::@1: scope:[main] from main::first
main::$0 = main::i < $a
if(main::$0) goto main::@2
to:main::@return
main::@2: scope:[main] from main::@1
main::SCREEN[main::i] = '*'
to:main::first
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
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@ -420,7 +132,7 @@ Uplifting [] best 341 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test labels/goto
// goto a nested label
// goto a label nested in a loop
// Upstart
// Commodore 64 PRG executable file
.file [name="labelgoto-5.prg", type="prg", segments="Program"]
@ -495,7 +207,7 @@ Score: 251
// File Comments
// Test labels/goto
// goto a nested label
// goto a label nested in a loop
// Upstart
// Commodore 64 PRG executable file
.file [name="labelgoto-5.prg", type="prg", segments="Program"]

View File

@ -0,0 +1,33 @@
// Tests the sizeof operator without parenthesis
// Commodore 64 PRG executable file
.file [name="sizeof-noparen.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_BYTE = 1
.const SIZEOF_SIGNED_WORD = 2
.const SIZEOF_NUMBER = -1
.label SCREEN = $400
.segment Code
main: {
// SCREEN[idx++] = '0'+sizeof 0
lda #'0'+SIZEOF_NUMBER
sta SCREEN
// SCREEN[idx++] = '0'+sizeof b
lda #'0'+SIZEOF_BYTE
sta SCREEN+1
// SCREEN[idx++] = '0'+sizeof w
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+2
// SCREEN[idx++] = '0'+sizeof (char)
lda #'0'+SIZEOF_BYTE
sta SCREEN+3
// SCREEN[idx++] = '0'+sizeof (int)
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+4
// }
rts
}

View File

@ -0,0 +1,12 @@
void main()
main: scope:[main] from
[0] *SCREEN = '0'+SIZEOF_NUMBER
[1] *(SCREEN+1) = '0'+SIZEOF_BYTE
[2] *(SCREEN+2) = '0'+SIZEOF_SIGNED_WORD
[3] *(SCREEN+3) = '0'+SIZEOF_BYTE
[4] *(SCREEN+4) = '0'+SIZEOF_SIGNED_WORD
to:main::@return
main::@return: scope:[main] from main
[5] return
to:@return

View File

@ -0,0 +1,280 @@
Resolving sizeof() main::$2 = sizeof main::b
Resolving sizeof() main::$4 = sizeof main::w
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
main::idx#0 = 0
main::$0 = sizeof 0
main::$1 = '0' + main::$0
SCREEN[main::idx#0] = main::$1
main::idx#1 = ++ main::idx#0
main::$2 = SIZEOF_BYTE
main::$3 = '0' + main::$2
SCREEN[main::idx#1] = main::$3
main::idx#2 = ++ main::idx#1
main::$4 = SIZEOF_SIGNED_WORD
main::$5 = '0' + main::$4
SCREEN[main::idx#2] = main::$5
main::idx#3 = ++ main::idx#2
SCREEN[main::idx#3] = '0'+SIZEOF_BYTE
main::idx#4 = ++ main::idx#3
SCREEN[main::idx#4] = '0'+SIZEOF_SIGNED_WORD
main::idx#5 = ++ main::idx#4
to:main::@return
main::@return: scope:[main] from main
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 byte* const SCREEN = (byte*)$400
constant byte SIZEOF_BYTE = 1
constant byte SIZEOF_SIGNED_WORD = 2
void __start()
void main()
word~ main::$0
word~ main::$1
word~ main::$2
word~ main::$3
word~ main::$4
word~ main::$5
byte main::idx
byte main::idx#0
byte main::idx#1
byte main::idx#2
byte main::idx#3
byte main::idx#4
byte main::idx#5
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Constant right-side identified [1] main::$0 = sizeof 0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::idx#0 = 0
Constant main::$0 = sizeof 0
Constant main::$2 = SIZEOF_BYTE
Constant main::$4 = SIZEOF_SIGNED_WORD
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero SCREEN in [3] SCREEN[main::idx#0] = main::$1
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable main::idx#5 and assignment [12] main::idx#5 = ++ main::idx#4
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
Resolving sizeof() sizeof 0
Successful SSA optimization PassNSizeOfSimplification
Constant right-side identified [0] main::$1 = '0' + main::$0
Constant right-side identified [2] main::idx#1 = ++ main::idx#0
Constant right-side identified [3] main::$3 = '0' + main::$2
Constant right-side identified [6] main::$5 = '0' + main::$4
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::$1 = '0'+main::$0
Constant main::idx#1 = ++main::idx#0
Constant main::$3 = '0'+main::$2
Constant main::$5 = '0'+main::$4
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [2] main::idx#2 = ++ main::idx#1
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::idx#2 = ++main::idx#1
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [3] main::idx#3 = ++ main::idx#2
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::idx#3 = ++main::idx#2
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [4] main::idx#4 = ++ main::idx#3
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::idx#4 = ++main::idx#3
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with different constant siblings main::idx#0
Inlining constant with different constant siblings main::idx#1
Inlining constant with different constant siblings main::idx#2
Inlining constant with different constant siblings main::idx#3
Inlining constant with different constant siblings main::idx#4
Constant inlined main::idx#0 = 0
Constant inlined main::idx#1 = ++0
Constant inlined main::idx#2 = ++++0
Constant inlined main::$1 = '0'+SIZEOF_NUMBER
Constant inlined main::idx#3 = ++++++0
Constant inlined main::$2 = SIZEOF_BYTE
Constant inlined main::idx#4 = ++++++++0
Constant inlined main::$0 = SIZEOF_NUMBER
Constant inlined main::$5 = '0'+SIZEOF_SIGNED_WORD
Constant inlined main::$3 = '0'+SIZEOF_BYTE
Constant inlined main::$4 = SIZEOF_SIGNED_WORD
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(SCREEN+++0)
Consolidated array index constant in *(SCREEN+++++0)
Consolidated array index constant in *(SCREEN+++++++0)
Consolidated array index constant in *(SCREEN+++++++++0)
Successful SSA optimization Pass2ConstantAdditionElimination
Simplifying constant integer increment ++0
Simplifying constant integer increment ++0
Simplifying constant integer increment ++1
Simplifying constant integer increment ++2
Successful SSA optimization Pass2ConstantSimplification
Simplifying constant integer increment ++1
Simplifying constant integer increment ++2
Simplifying constant integer increment ++3
Successful SSA optimization Pass2ConstantSimplification
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] *SCREEN = '0'+SIZEOF_NUMBER
[1] *(SCREEN+1) = '0'+SIZEOF_BYTE
[2] *(SCREEN+2) = '0'+SIZEOF_SIGNED_WORD
[3] *(SCREEN+3) = '0'+SIZEOF_BYTE
[4] *(SCREEN+4) = '0'+SIZEOF_SIGNED_WORD
to:main::@return
main::@return: scope:[main] from main
[5] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
byte main::idx
Initial phi equivalence classes
Complete equivalence classes
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = '0'+SIZEOF_NUMBER [ ] ( [ ] { } ) always clobbers reg byte a
Statement [1] *(SCREEN+1) = '0'+SIZEOF_BYTE [ ] ( [ ] { } ) always clobbers reg byte a
Statement [2] *(SCREEN+2) = '0'+SIZEOF_SIGNED_WORD [ ] ( [ ] { } ) always clobbers reg byte a
Statement [3] *(SCREEN+3) = '0'+SIZEOF_BYTE [ ] ( [ ] { } ) always clobbers reg byte a
Statement [4] *(SCREEN+4) = '0'+SIZEOF_SIGNED_WORD [ ] ( [ ] { } ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 39 combination
Uplifting [] best 39 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the sizeof operator without parenthesis
// Upstart
// Commodore 64 PRG executable file
.file [name="sizeof-noparen.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_BYTE = 1
.const SIZEOF_SIGNED_WORD = 2
.const SIZEOF_NUMBER = -1
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = '0'+SIZEOF_NUMBER -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_NUMBER
sta SCREEN
// [1] *(SCREEN+1) = '0'+SIZEOF_BYTE -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_BYTE
sta SCREEN+1
// [2] *(SCREEN+2) = '0'+SIZEOF_SIGNED_WORD -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+2
// [3] *(SCREEN+3) = '0'+SIZEOF_BYTE -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_BYTE
sta SCREEN+3
// [4] *(SCREEN+4) = '0'+SIZEOF_SIGNED_WORD -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+4
jmp __breturn
// main::@return
__breturn:
// [5] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
constant byte* const SCREEN = (byte*) 1024
constant byte SIZEOF_BYTE = 1
constant byte SIZEOF_NUMBER = -1
constant byte SIZEOF_SIGNED_WORD = 2
void main()
byte main::idx
FINAL ASSEMBLER
Score: 36
// File Comments
// Tests the sizeof operator without parenthesis
// Upstart
// Commodore 64 PRG executable file
.file [name="sizeof-noparen.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_BYTE = 1
.const SIZEOF_SIGNED_WORD = 2
.const SIZEOF_NUMBER = -1
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[idx++] = '0'+sizeof 0
// [0] *SCREEN = '0'+SIZEOF_NUMBER -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_NUMBER
sta SCREEN
// SCREEN[idx++] = '0'+sizeof b
// [1] *(SCREEN+1) = '0'+SIZEOF_BYTE -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_BYTE
sta SCREEN+1
// SCREEN[idx++] = '0'+sizeof w
// [2] *(SCREEN+2) = '0'+SIZEOF_SIGNED_WORD -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+2
// SCREEN[idx++] = '0'+sizeof (char)
// [3] *(SCREEN+3) = '0'+SIZEOF_BYTE -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_BYTE
sta SCREEN+3
// SCREEN[idx++] = '0'+sizeof (int)
// [4] *(SCREEN+4) = '0'+SIZEOF_SIGNED_WORD -- _deref_pbuc1=vbuc2
lda #'0'+SIZEOF_SIGNED_WORD
sta SCREEN+4
// main::@return
// }
// [5] return
rts
}
// File Data

View File

@ -0,0 +1,7 @@
constant byte* const SCREEN = (byte*) 1024
constant byte SIZEOF_BYTE = 1
constant byte SIZEOF_NUMBER = -1
constant byte SIZEOF_SIGNED_WORD = 2
void main()
byte main::idx