mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-11 20:30:08 +00:00
Added support for int main(int argc, char **argv). Closes #562
This commit is contained in:
parent
e58bff087e
commit
dddf6db181
src
main/java/dk/camelot64/kickc/passes
test
java/dk/camelot64/kickc/test
kc
main-missing.cmain-param-0.cmain-param-1.cmain-return.cmain-wrong-0.cmain-wrong-1.cmain-wrong-2.cmain-wrong-3.c
ref
@ -197,7 +197,29 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
startSequence.addStatement(new StatementProcedureBegin(startProcedure.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
if(initCompilation != null)
|
||||
startSequence.addStatement(new StatementCall(null, SymbolRef.INIT_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
startSequence.addStatement(new StatementCall(null, SymbolRef.MAIN_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
final Procedure mainProc = program.getScope().getLocalProcedure(SymbolRef.MAIN_PROC_NAME);
|
||||
if(mainProc==null)
|
||||
throw new CompileError("Required main() not defined in program.");
|
||||
if(!SymbolType.VOID.equals(mainProc.getReturnType()) && !SymbolType.SWORD.equals(mainProc.getReturnType()))
|
||||
throw new CompileError("return of main() must be 'void' or of type 'int'.", mainProc.getDefinitionSource());
|
||||
if(mainProc.getParameterNames().size()==0) {
|
||||
startSequence.addStatement(new StatementCall(null, SymbolRef.MAIN_PROC_NAME, new ArrayList<>(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
} else if(mainProc.getParameterNames().size()==2) {
|
||||
final List<Variable> parameters = mainProc.getParameters();
|
||||
final Variable argc = parameters.get(0);
|
||||
if(!SymbolType.SWORD.equals(argc.getType()))
|
||||
throw new CompileError("first parameter of main() must be of type 'int'.", mainProc.getDefinitionSource());
|
||||
final Variable argv = parameters.get(1);
|
||||
if(!argv.getType().equals(new SymbolTypePointer(new SymbolTypePointer(SymbolType.BYTE))))
|
||||
throw new CompileError("second parameter of main() must be of type 'char **'.", mainProc.getDefinitionSource());
|
||||
final ArrayList<RValue> params = new ArrayList<>();
|
||||
params.add(new ConstantInteger(0L, SymbolType.SWORD));
|
||||
params.add(new ConstantPointer(0L, new SymbolTypePointer(SymbolType.BYTE)));
|
||||
startSequence.addStatement(new StatementCall(null, SymbolRef.MAIN_PROC_NAME, params, new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
} else
|
||||
throw new CompileError("main() has wrong number of parameters. It must have zero or 2 parameters.", mainProc.getDefinitionSource());
|
||||
|
||||
|
||||
final Label startReturnLabel = startProcedure.addLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
|
||||
startSequence.addStatement(new StatementLabel(startReturnLabel.getRef(), new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
startSequence.addStatement(new StatementReturn(null, new StatementSource(RuleContext.EMPTY), Comment.NO_COMMENTS));
|
||||
|
@ -14,6 +14,46 @@ public class TestProgramsFast extends TestPrograms {
|
||||
// compileAndCompare("shadow-variable-error-1.c");
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testMainWrong3() throws IOException {
|
||||
assertError("main-wrong-3.c", "return of main() must be 'void' or of type 'int'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainWrong2() throws IOException {
|
||||
assertError("main-wrong-2.c", "second parameter of main() must be of type 'char **'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainWrong1() throws IOException {
|
||||
assertError("main-wrong-1.c", "first parameter of main() must be of type 'int'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainWrong0() throws IOException {
|
||||
assertError("main-wrong-0.c", "main() has wrong number of parameters. It must have zero or 2 parameters");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainMissing() throws IOException {
|
||||
assertError("main-missing.c", "Required main() not defined in program.", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainParam1() throws IOException {
|
||||
compileAndCompare("main-param-1.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainParam0() throws IOException {
|
||||
compileAndCompare("main-param-0.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMainReturn() throws IOException {
|
||||
compileAndCompare("main-return.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullConstant() throws IOException {
|
||||
compileAndCompare("null-constant.c");
|
||||
|
4
src/test/kc/main-missing.c
Normal file
4
src/test/kc/main-missing.c
Normal file
@ -0,0 +1,4 @@
|
||||
// Test program with missing main()
|
||||
|
||||
void xmain() {
|
||||
}
|
6
src/test/kc/main-param-0.c
Normal file
6
src/test/kc/main-param-0.c
Normal file
@ -0,0 +1,6 @@
|
||||
// Test main() with parameters
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char * SCREEN = (char*) 0x0400;
|
||||
return (int)*SCREEN;
|
||||
}
|
8
src/test/kc/main-param-1.c
Normal file
8
src/test/kc/main-param-1.c
Normal file
@ -0,0 +1,8 @@
|
||||
// Test main() with parameters
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char * SCREEN = (char*) 0x0400;
|
||||
SCREEN[0] = (char)argc;
|
||||
SCREEN[1] = (char) argv;
|
||||
return -1;
|
||||
}
|
6
src/test/kc/main-return.c
Normal file
6
src/test/kc/main-return.c
Normal file
@ -0,0 +1,6 @@
|
||||
// Test main() with int return
|
||||
|
||||
int main() {
|
||||
char * SCREEN = (char*) 0x0400;
|
||||
return (int)*SCREEN;
|
||||
}
|
5
src/test/kc/main-wrong-0.c
Normal file
5
src/test/kc/main-wrong-0.c
Normal file
@ -0,0 +1,5 @@
|
||||
// Test program with main() with wrong number of parameters
|
||||
|
||||
int main(int x) {
|
||||
|
||||
}
|
5
src/test/kc/main-wrong-1.c
Normal file
5
src/test/kc/main-wrong-1.c
Normal file
@ -0,0 +1,5 @@
|
||||
// Test program with main() with wrong type of parameter 0
|
||||
|
||||
int main(long argc, char *argv[]) {
|
||||
|
||||
}
|
5
src/test/kc/main-wrong-2.c
Normal file
5
src/test/kc/main-wrong-2.c
Normal file
@ -0,0 +1,5 @@
|
||||
// Test program with main() with wrong type of parameter 0
|
||||
|
||||
int main(int argc, int *argv[]) {
|
||||
|
||||
}
|
5
src/test/kc/main-wrong-3.c
Normal file
5
src/test/kc/main-wrong-3.c
Normal file
@ -0,0 +1,5 @@
|
||||
// Test program with main() with wrong type of return value
|
||||
|
||||
char main(int argc, char **argv) {
|
||||
|
||||
}
|
14
src/test/ref/main-param-0.asm
Normal file
14
src/test/ref/main-param-0.asm
Normal file
@ -0,0 +1,14 @@
|
||||
// Test main() with parameters
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-0.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)
|
||||
.segment Code
|
||||
main: {
|
||||
// }
|
||||
rts
|
||||
}
|
8
src/test/ref/main-param-0.cfg
Normal file
8
src/test/ref/main-param-0.cfg
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
to:@return
|
158
src/test/ref/main-param-0.log
Normal file
158
src/test/ref/main-param-0.log
Normal file
@ -0,0 +1,158 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from __start
|
||||
main::return#0 = (signed word)*main::SCREEN
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
main::return#3 = phi( main/main::return#0 )
|
||||
main::return#1 = main::return#3
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
main::argc#0 = 0
|
||||
main::argv#0 = (byte**) 0
|
||||
call main
|
||||
main::return#2 = main::return#1
|
||||
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
|
||||
void __start()
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
constant byte* main::SCREEN = (byte*)$400
|
||||
signed word main::argc
|
||||
signed word main::argc#0
|
||||
byte** main::argv
|
||||
byte** main::argv#0
|
||||
signed word main::return
|
||||
signed word main::return#0
|
||||
signed word main::return#1
|
||||
signed word main::return#2
|
||||
signed word main::return#3
|
||||
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Alias main::return#0 = main::return#3 main::return#1
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Constant main::argc#0 = 0
|
||||
Constant main::argv#0 = (byte**) 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Eliminating unused variable main::return#2 and assignment [3] main::return#2 = main::return#0
|
||||
Eliminating unused constant main::argc#0
|
||||
Eliminating unused constant main::argv#0
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused variable main::return#0 and assignment [0] main::return#0 = (signed word)*main::SCREEN
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused constant main::SCREEN
|
||||
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 NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 36 combination
|
||||
Uplifting [] best 36 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test main() with parameters
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-0.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [1] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 6
|
||||
|
||||
// File Comments
|
||||
// Test main() with parameters
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-0.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// main::@return
|
||||
// }
|
||||
// [1] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
5
src/test/ref/main-param-0.sym
Normal file
5
src/test/ref/main-param-0.sym
Normal file
@ -0,0 +1,5 @@
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
20
src/test/ref/main-param-1.asm
Normal file
20
src/test/ref/main-param-1.asm
Normal file
@ -0,0 +1,20 @@
|
||||
// Test main() with parameters
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-1.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)
|
||||
.segment Code
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// SCREEN[0] = (char)argc
|
||||
lda #0
|
||||
sta SCREEN
|
||||
// SCREEN[1] = (char) argv
|
||||
sta SCREEN+1
|
||||
// }
|
||||
rts
|
||||
}
|
9
src/test/ref/main-param-1.cfg
Normal file
9
src/test/ref/main-param-1.cfg
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from
|
||||
[0] *main::SCREEN = 0
|
||||
[1] *(main::SCREEN+1) = 0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[2] return
|
||||
to:@return
|
210
src/test/ref/main-param-1.log
Normal file
210
src/test/ref/main-param-1.log
Normal file
@ -0,0 +1,210 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from __start
|
||||
main::argv#1 = phi( __start/main::argv#0 )
|
||||
main::argc#1 = phi( __start/main::argc#0 )
|
||||
main::SCREEN[0] = (byte)main::argc#1
|
||||
main::SCREEN[1] = (byte)main::argv#1
|
||||
main::return#0 = -1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
main::return#3 = phi( main/main::return#0 )
|
||||
main::return#1 = main::return#3
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
main::argc#0 = 0
|
||||
main::argv#0 = (byte**) 0
|
||||
call main
|
||||
main::return#2 = main::return#1
|
||||
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
|
||||
void __start()
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
constant byte* main::SCREEN = (byte*)$400
|
||||
signed word main::argc
|
||||
signed word main::argc#0
|
||||
signed word main::argc#1
|
||||
byte** main::argv
|
||||
byte** main::argv#0
|
||||
byte** main::argv#1
|
||||
signed word main::return
|
||||
signed word main::return#0
|
||||
signed word main::return#1
|
||||
signed word main::return#2
|
||||
signed word main::return#3
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::SCREEN[0] = (byte)main::argc#1
|
||||
Adding number conversion cast (unumber) 1 in main::SCREEN[1] = (byte)main::argv#1
|
||||
Adding number conversion cast (snumber) -1 in main::return#0 = -1
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast main::return#0 = (snumber)-1
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast -1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized signed number type (signed byte) -1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias main::return#0 = main::return#3 main::return#1
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values main::argc#1 main::argc#0
|
||||
Identical Phi Values main::argv#1 main::argv#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Constant main::return#0 = -1
|
||||
Constant main::argc#0 = 0
|
||||
Constant main::argv#0 = (byte**) 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant main::return#2 = main::return#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte)main::argc#0 in [1] main::SCREEN[0] = (byte)main::argc#0
|
||||
Constant value identified (byte)main::argv#0 in [2] main::SCREEN[1] = (byte)main::argv#0
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Simplifying constant evaluating to zero (byte)main::argc#0 in [1] main::SCREEN[0] = (byte)main::argc#0
|
||||
Simplifying constant evaluating to zero (byte)main::argv#0 in [2] main::SCREEN[1] = (byte)main::argv#0
|
||||
Successful SSA optimization PassNSimplifyConstantZero
|
||||
Simplifying expression containing zero main::SCREEN in [1] main::SCREEN[0] = 0
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant main::argc#0
|
||||
Eliminating unused constant main::argv#0
|
||||
Eliminating unused constant main::return#2
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused constant main::return#0
|
||||
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
|
||||
Consolidated array index constant in *(main::SCREEN+1)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
main: scope:[main] from
|
||||
[0] *main::SCREEN = 0
|
||||
[1] *(main::SCREEN+1) = 0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[2] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *main::SCREEN = 0 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [1] *(main::SCREEN+1) = 0 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 21 combination
|
||||
Uplifting [] best 21 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test main() with parameters
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-1.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// [0] *main::SCREEN = 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta SCREEN
|
||||
// [1] *(main::SCREEN+1) = 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta SCREEN+1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
constant byte* main::SCREEN = (byte*) 1024
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 16
|
||||
|
||||
// File Comments
|
||||
// Test main() with parameters
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-param-1.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label SCREEN = $400
|
||||
// SCREEN[0] = (char)argc
|
||||
// [0] *main::SCREEN = 0 -- _deref_pbuc1=vbuc2
|
||||
lda #0
|
||||
sta SCREEN
|
||||
// SCREEN[1] = (char) argv
|
||||
// [1] *(main::SCREEN+1) = 0 -- _deref_pbuc1=vbuc2
|
||||
sta SCREEN+1
|
||||
// main::@return
|
||||
// }
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
6
src/test/ref/main-param-1.sym
Normal file
6
src/test/ref/main-param-1.sym
Normal file
@ -0,0 +1,6 @@
|
||||
signed word main(signed word main::argc , byte** main::argv)
|
||||
constant byte* main::SCREEN = (byte*) 1024
|
||||
signed word main::argc
|
||||
byte** main::argv
|
||||
signed word main::return
|
||||
|
14
src/test/ref/main-return.asm
Normal file
14
src/test/ref/main-return.asm
Normal file
@ -0,0 +1,14 @@
|
||||
// Test main() with int return
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-return.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)
|
||||
.segment Code
|
||||
main: {
|
||||
// }
|
||||
rts
|
||||
}
|
8
src/test/ref/main-return.cfg
Normal file
8
src/test/ref/main-return.cfg
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
signed word main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
to:@return
|
143
src/test/ref/main-return.log
Normal file
143
src/test/ref/main-return.log
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
signed word main()
|
||||
main: scope:[main] from __start
|
||||
main::return#0 = (signed word)*main::SCREEN
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
main::return#3 = phi( main/main::return#0 )
|
||||
main::return#1 = main::return#3
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
main::return#2 = main::return#1
|
||||
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
|
||||
void __start()
|
||||
signed word main()
|
||||
constant byte* main::SCREEN = (byte*)$400
|
||||
signed word main::return
|
||||
signed word main::return#0
|
||||
signed word main::return#1
|
||||
signed word main::return#2
|
||||
signed word main::return#3
|
||||
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Alias main::return#0 = main::return#3 main::return#1
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Eliminating unused variable main::return#2 and assignment [3] main::return#2 = main::return#0
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused variable main::return#0 and assignment [0] main::return#0 = (signed word)*main::SCREEN
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused constant main::SCREEN
|
||||
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 NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
signed word main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
signed word main()
|
||||
signed word main::return
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 36 combination
|
||||
Uplifting [] best 36 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test main() with int return
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-return.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [1] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
signed word main()
|
||||
signed word main::return
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 6
|
||||
|
||||
// File Comments
|
||||
// Test main() with int return
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="main-return.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// main::@return
|
||||
// }
|
||||
// [1] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
3
src/test/ref/main-return.sym
Normal file
3
src/test/ref/main-return.sym
Normal file
@ -0,0 +1,3 @@
|
||||
signed word main()
|
||||
signed word main::return
|
||||
|
Loading…
x
Reference in New Issue
Block a user