mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-03-08 17:30:33 +00:00
Fixed problem where uninitialized variables resultes in compile errors. Closes #131
This commit is contained in:
parent
f6a566e2f8
commit
627df0bda9
@ -212,12 +212,13 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(statement instanceof StatementPhiBlock) {
|
} else if(statement instanceof StatementPhiBlock) {
|
||||||
|
boolean modified = false;
|
||||||
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
||||||
Iterator<StatementPhiBlock.PhiVariable> variableIterator = phiBlock.getPhiVariables().iterator();
|
Iterator<StatementPhiBlock.PhiVariable> variableIterator = phiBlock.getPhiVariables().iterator();
|
||||||
while(variableIterator.hasNext()) {
|
while(variableIterator.hasNext()) {
|
||||||
StatementPhiBlock.PhiVariable phiVariable = variableIterator.next();
|
StatementPhiBlock.PhiVariable phiVariable = variableIterator.next();
|
||||||
AliasSet aliasSet = aliases.findAliasSet(phiVariable.getVariable());
|
AliasSet aliasSet = aliases.findAliasSet(phiVariable.getVariable());
|
||||||
if(aliasSet != null) {
|
if(aliasSet != null && phiVariable.getValues().size()>0) {
|
||||||
boolean remove = true;
|
boolean remove = true;
|
||||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||||
if(!aliasSet.contains(phiRValue.getrValue())) {
|
if(!aliasSet.contains(phiRValue.getrValue())) {
|
||||||
@ -227,10 +228,11 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
if(remove) {
|
if(remove) {
|
||||||
variableIterator.remove();
|
variableIterator.remove();
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(phiBlock.getPhiVariables().size() == 0) {
|
if(modified && phiBlock.getPhiVariables().size() == 0) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,30 +84,30 @@ public class TestPrograms {
|
|||||||
compileAndCompare("examples/tetris/tetris");
|
compileAndCompare("examples/tetris/tetris");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVarInitProblem() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("var-init-problem");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Test
|
@Test
|
||||||
public void testVarInitProblem() throws IOException, URISyntaxException {
|
public void testConstIfProblem() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("var-init-problem");
|
compileAndCompare("const-if-problem");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstIfProblem() throws IOException, URISyntaxException {
|
public void testTetrisNullPointer() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("const-if-problem");
|
compileAndCompare("tetris-npe");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
//@Test
|
||||||
public void testTetrisNullPointer() throws IOException, URISyntaxException {
|
//public void testUnrollCall() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("tetris-npe");
|
// compileAndCompare("unroll-call");
|
||||||
}
|
//}
|
||||||
|
|
||||||
//@Test
|
|
||||||
//public void testUnrollCall() throws IOException, URISyntaxException {
|
|
||||||
// compileAndCompare("unroll-call");
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testFastMultiply8() throws IOException, URISyntaxException {
|
public void testFastMultiply8() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("examples/fastmultiply/fastmultiply8.kc");
|
compileAndCompare("examples/fastmultiply/fastmultiply8.kc");
|
||||||
@ -1182,6 +1182,7 @@ public class TestPrograms {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the path to the passed file is created.
|
* Ensures that the path to the passed file is created.
|
||||||
|
*
|
||||||
* @param file The file to create a path for
|
* @param file The file to create a path for
|
||||||
*/
|
*/
|
||||||
private void mkPath(File file) {
|
private void mkPath(File file) {
|
||||||
@ -1203,5 +1204,4 @@ public class TestPrograms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
9
src/test/ref/var-init-problem.asm
Normal file
9
src/test/ref/var-init-problem.asm
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(main)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
.label screen = $400
|
||||||
|
main: {
|
||||||
|
lda #'a'
|
||||||
|
sta screen
|
||||||
|
rts
|
||||||
|
}
|
15
src/test/ref/var-init-problem.cfg
Normal file
15
src/test/ref/var-init-problem.cfg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@begin: scope:[] from
|
||||||
|
[0] phi()
|
||||||
|
to:@1
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
[1] phi()
|
||||||
|
[2] call main
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @1
|
||||||
|
[3] phi()
|
||||||
|
main: scope:[main] from @1
|
||||||
|
[4] *((const byte*) screen#0) ← (byte) 'a'
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[5] return
|
||||||
|
to:@return
|
218
src/test/ref/var-init-problem.log
Normal file
218
src/test/ref/var-init-problem.log
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
@begin: scope:[] from
|
||||||
|
(byte*) screen#6 ← phi( )
|
||||||
|
to:@1
|
||||||
|
main: scope:[main] from @1
|
||||||
|
(byte*) screen#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
|
||||||
|
*((byte*) screen#0) ← (byte) 'a'
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
(byte*) screen#3 ← phi( main/(byte*) screen#0 )
|
||||||
|
(byte*) screen#1 ← (byte*) screen#3
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
(byte*) screen#5 ← phi( @begin/(byte*) screen#6 )
|
||||||
|
call main
|
||||||
|
to:@2
|
||||||
|
@2: scope:[] from @1
|
||||||
|
(byte*) screen#4 ← phi( @1/(byte*) screen#1 )
|
||||||
|
(byte*) screen#2 ← (byte*) screen#4
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @2
|
||||||
|
|
||||||
|
SYMBOL TABLE SSA
|
||||||
|
(label) @1
|
||||||
|
(label) @2
|
||||||
|
(label) @begin
|
||||||
|
(label) @end
|
||||||
|
(void()) main()
|
||||||
|
(label) main::@return
|
||||||
|
(byte*) screen
|
||||||
|
(byte*) screen#0
|
||||||
|
(byte*) screen#1
|
||||||
|
(byte*) screen#2
|
||||||
|
(byte*) screen#3
|
||||||
|
(byte*) screen#4
|
||||||
|
(byte*) screen#5
|
||||||
|
(byte*) screen#6
|
||||||
|
|
||||||
|
Alias (byte*) screen#0 = (byte*) screen#3 (byte*) screen#1
|
||||||
|
Alias (byte*) screen#5 = (byte*) screen#6
|
||||||
|
Alias (byte*) screen#2 = (byte*) screen#4
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Redundant Phi (byte*) screen#5 VOID
|
||||||
|
Redundant Phi (byte*) screen#2 (byte*) screen#0
|
||||||
|
Successful SSA optimization Pass2RedundantPhiElimination
|
||||||
|
Constant (const byte*) screen#0 = ((byte*))1024
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Culled Empty Block (label) @2
|
||||||
|
Successful SSA optimization Pass2CullEmptyBlocks
|
||||||
|
Adding NOP phi() at start of @begin
|
||||||
|
Adding NOP phi() at start of @1
|
||||||
|
Adding NOP phi() at start of @end
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [] to main:2
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
Adding NOP phi() at start of @begin
|
||||||
|
Adding NOP phi() at start of @1
|
||||||
|
Adding NOP phi() at start of @end
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
@begin: scope:[] from
|
||||||
|
[0] phi()
|
||||||
|
to:@1
|
||||||
|
@1: scope:[] from @begin
|
||||||
|
[1] phi()
|
||||||
|
[2] call main
|
||||||
|
to:@end
|
||||||
|
@end: scope:[] from @1
|
||||||
|
[3] phi()
|
||||||
|
main: scope:[main] from @1
|
||||||
|
[4] *((const byte*) screen#0) ← (byte) 'a'
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[5] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
(void()) main()
|
||||||
|
(byte*) screen
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Complete equivalence classes
|
||||||
|
|
||||||
|
INITIAL ASM
|
||||||
|
//SEG0 Basic Upstart
|
||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(bbegin)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
//SEG1 Global Constants & labels
|
||||||
|
.label screen = $400
|
||||||
|
//SEG2 @begin
|
||||||
|
bbegin:
|
||||||
|
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||||
|
b1_from_bbegin:
|
||||||
|
jmp b1
|
||||||
|
//SEG4 @1
|
||||||
|
b1:
|
||||||
|
//SEG5 [2] call main
|
||||||
|
jsr main
|
||||||
|
//SEG6 [3] phi from @1 to @end [phi:@1->@end]
|
||||||
|
bend_from_b1:
|
||||||
|
jmp bend
|
||||||
|
//SEG7 @end
|
||||||
|
bend:
|
||||||
|
//SEG8 main
|
||||||
|
main: {
|
||||||
|
//SEG9 [4] *((const byte*) screen#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||||
|
lda #'a'
|
||||||
|
sta screen
|
||||||
|
jmp breturn
|
||||||
|
//SEG10 main::@return
|
||||||
|
breturn:
|
||||||
|
//SEG11 [5] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [4] *((const byte*) screen#0) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [main]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [main] best 27 combination
|
||||||
|
Uplifting [] best 27 combination
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
//SEG0 Basic Upstart
|
||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(bbegin)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
//SEG1 Global Constants & labels
|
||||||
|
.label screen = $400
|
||||||
|
//SEG2 @begin
|
||||||
|
bbegin:
|
||||||
|
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||||
|
b1_from_bbegin:
|
||||||
|
jmp b1
|
||||||
|
//SEG4 @1
|
||||||
|
b1:
|
||||||
|
//SEG5 [2] call main
|
||||||
|
jsr main
|
||||||
|
//SEG6 [3] phi from @1 to @end [phi:@1->@end]
|
||||||
|
bend_from_b1:
|
||||||
|
jmp bend
|
||||||
|
//SEG7 @end
|
||||||
|
bend:
|
||||||
|
//SEG8 main
|
||||||
|
main: {
|
||||||
|
//SEG9 [4] *((const byte*) screen#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||||
|
lda #'a'
|
||||||
|
sta screen
|
||||||
|
jmp breturn
|
||||||
|
//SEG10 main::@return
|
||||||
|
breturn:
|
||||||
|
//SEG11 [5] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp b1
|
||||||
|
Removing instruction jmp bend
|
||||||
|
Removing instruction jmp breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction b1_from_bbegin:
|
||||||
|
Removing instruction b1:
|
||||||
|
Removing instruction bend_from_b1:
|
||||||
|
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||||
|
Removing instruction bend:
|
||||||
|
Removing instruction breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
Updating BasicUpstart to call main directly
|
||||||
|
Removing instruction jsr main
|
||||||
|
Succesful ASM optimization Pass5SkipBegin
|
||||||
|
Removing instruction bbegin:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
(label) @1
|
||||||
|
(label) @begin
|
||||||
|
(label) @end
|
||||||
|
(void()) main()
|
||||||
|
(label) main::@return
|
||||||
|
(byte*) screen
|
||||||
|
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 12
|
||||||
|
|
||||||
|
//SEG0 Basic Upstart
|
||||||
|
.pc = $801 "Basic"
|
||||||
|
:BasicUpstart(main)
|
||||||
|
.pc = $80d "Program"
|
||||||
|
//SEG1 Global Constants & labels
|
||||||
|
.label screen = $400
|
||||||
|
//SEG2 @begin
|
||||||
|
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
|
||||||
|
//SEG4 @1
|
||||||
|
//SEG5 [2] call main
|
||||||
|
//SEG6 [3] phi from @1 to @end [phi:@1->@end]
|
||||||
|
//SEG7 @end
|
||||||
|
//SEG8 main
|
||||||
|
main: {
|
||||||
|
//SEG9 [4] *((const byte*) screen#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
|
||||||
|
lda #'a'
|
||||||
|
sta screen
|
||||||
|
//SEG10 main::@return
|
||||||
|
//SEG11 [5] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
|
8
src/test/ref/var-init-problem.sym
Normal file
8
src/test/ref/var-init-problem.sym
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
(label) @1
|
||||||
|
(label) @begin
|
||||||
|
(label) @end
|
||||||
|
(void()) main()
|
||||||
|
(label) main::@return
|
||||||
|
(byte*) screen
|
||||||
|
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user