1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Added main method to flipper. Fixed a few bugs in compiler.

This commit is contained in:
Jesper Gravgaard 2017-07-16 11:09:32 +02:00
parent f6eeb5ff83
commit a7e0e2b1d0
11 changed files with 2425 additions and 1949 deletions

View File

@ -12,6 +12,7 @@ public class CompileLog {
public void append(String msg) {
log.append(msg);
log.append("\n");
//System.out.printf(msg+"\n");
}
public StringBuilder getLog() {

View File

@ -43,113 +43,131 @@ public class Compiler {
}
}
public CompilationResult compile(final CharStream input) throws IOException {
public CompilationResult compile(final CharStream input) {
CompileLog log = new CompileLog();
log.append(input.toString());
KickCLexer lexer = new KickCLexer(input);
KickCParser parser = new KickCParser(new CommonTokenStream(lexer));
parser.setBuildParseTree(true);
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("Error parsing file "+input.getSourceName()+"\n - Line: "+line+"\n - Message: "+msg);
}
});
KickCParser.FileContext file = parser.file();
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(log);
pass1GenerateStatementSequence.generate(file);
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
Scope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference();
pass1TypeInference.inferTypes(statementSequence, programScope);
try {
log.append(input.toString());
KickCLexer lexer = new KickCLexer(input);
KickCParser parser = new KickCParser(new CommonTokenStream(lexer));
parser.setBuildParseTree(true);
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(
Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e) {
throw new RuntimeException("Error parsing file " + input.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
}
});
KickCParser.FileContext file = parser.file();
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(log);
pass1GenerateStatementSequence.generate(file);
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
Scope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference();
pass1TypeInference.inferTypes(statementSequence, programScope);
log.append("PROGRAM");
log.append(statementSequence.toString());
log.append("SYMBOLS");
log.append(programScope.getSymbolTableContents());
log.append("PROGRAM");
log.append(statementSequence.toString());
log.append("SYMBOLS");
log.append(programScope.getSymbolTableContents());
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
log.append("INITIAL CONTROL FLOW GRAPH");
log.append(controlFlowGraph.toString());
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
log.append("INITIAL CONTROL FLOW GRAPH");
log.append(controlFlowGraph.toString());
Pass1ProcedureCallParameters pass1ProcedureCallParameters =
new Pass1ProcedureCallParameters(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallParameters.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
log.append(controlFlowGraph.toString());
Pass1ProcedureCallParameters pass1ProcedureCallParameters =
new Pass1ProcedureCallParameters(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallParameters.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
log.append(controlFlowGraph.toString());
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph);
pass1GenerateSingleStaticAssignmentForm.generate();
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(log, programScope, controlFlowGraph);
pass1GenerateSingleStaticAssignmentForm.generate();
log.append("CONTROL FLOW GRAPH SSA");
log.append(controlFlowGraph.toString());
log.append("CONTROL FLOW GRAPH SSA");
log.append(controlFlowGraph.toString());
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
log.append(controlFlowGraph.toString());
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
log.append(controlFlowGraph.toString());
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2AliasElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, programScope, log));
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2AliasElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, programScope, log));
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, programScope, log));
List<Pass2SsaAssertion> assertions = new ArrayList<>();
assertions.add(new Pass2AssertSymbols(controlFlowGraph, programScope));
assertions.add(new Pass2AssertBlocks(controlFlowGraph, programScope));
List<Pass2SsaAssertion> assertions = new ArrayList<>();
assertions.add(new Pass2AssertSymbols(controlFlowGraph, programScope));
assertions.add(new Pass2AssertBlocks(controlFlowGraph, programScope));
boolean ssaOptimized = true;
while (ssaOptimized) {
for (Pass2SsaAssertion assertion : assertions) {
assertion.check();
}
ssaOptimized = false;
for (Pass2SsaOptimization optimization : optimizations) {
boolean stepOptimized = optimization.optimize();
if (stepOptimized) {
log.append("Succesful SSA optimization "+optimization.getClass().getSimpleName()+"");
ssaOptimized = true;
log.append("CONTROL FLOW GRAPH");
log.append(controlFlowGraph.toString());
boolean ssaOptimized = true;
while (ssaOptimized) {
for (Pass2SsaAssertion assertion : assertions) {
assertion.check();
}
ssaOptimized = false;
for (Pass2SsaOptimization optimization : optimizations) {
boolean stepOptimized = optimization.optimize();
if (stepOptimized) {
log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
ssaOptimized = true;
log.append("CONTROL FLOW GRAPH");
log.append(controlFlowGraph.toString());
}
}
}
}
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(controlFlowGraph, programScope);
pass3BlockSequencePlanner.plan();
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, programScope);
pass3RegisterAllocation.allocate();
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, programScope);
AsmProgram asmProgram = pass3CodeGeneration.generate();
Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(
controlFlowGraph,
programScope);
pass3BlockSequencePlanner.plan();
Pass3RegisterAllocation pass3RegisterAllocation = new Pass3RegisterAllocation(controlFlowGraph, programScope);
pass3RegisterAllocation.allocate();
Pass3CodeGeneration pass3CodeGeneration = new Pass3CodeGeneration(controlFlowGraph, programScope);
AsmProgram asmProgram = pass3CodeGeneration.generate();
log.append("INITIAL ASM");
log.append(asmProgram.toString());
log.append("INITIAL ASM");
log.append(asmProgram.toString());
List<Pass4AsmOptimization> pass4Optimizations = new ArrayList<>();
pass4Optimizations.add(new Pass4NextJumpElimination(asmProgram, log));
pass4Optimizations.add(new Pass4UnnecesaryLoadElimination(asmProgram, log));
boolean asmOptimized = true;
while(asmOptimized) {
asmOptimized = false;
for (Pass4AsmOptimization optimization : pass4Optimizations) {
boolean stepOtimized = optimization.optimize();
if(stepOtimized) {
log.append("Succesful ASM optimization "+optimization.getClass().getSimpleName());
asmOptimized = true;
log.append("ASSEMBLER");
log.append(asmProgram.toString());
List<Pass4AsmOptimization> pass4Optimizations = new ArrayList<>();
pass4Optimizations.add(new Pass4NextJumpElimination(asmProgram, log));
pass4Optimizations.add(new Pass4UnnecesaryLoadElimination(asmProgram, log));
boolean asmOptimized = true;
while (asmOptimized) {
asmOptimized = false;
for (Pass4AsmOptimization optimization : pass4Optimizations) {
boolean stepOtimized = optimization.optimize();
if (stepOtimized) {
log.append("Succesful ASM optimization " + optimization.getClass().getSimpleName());
asmOptimized = true;
log.append("ASSEMBLER");
log.append(asmProgram.toString());
}
}
}
}
return new CompilationResult(asmProgram, controlFlowGraph, programScope, log);
log.append("FINAL SYMBOL TABLE");
log.append(programScope.getSymbolTableContents());
log.append("FINAL CODE");
log.append(asmProgram.toString());
return new CompilationResult(asmProgram, controlFlowGraph, programScope, log);
} catch (Exception e) {
System.out.println(log.getLog());
throw e;
}
}
}

View File

@ -1,8 +1,8 @@
Features
- Move the main code into a main() function, and disallow code outside functions. The main function per default has no parameters and exits with RTS.
- Add a for loop for(init;condition;increment) {stmt} -> { init; do { stmt; increment } while (condition) }
- Implement Register Allocation (that utilize real registers - and non-zeropage memory)
- Add Fixed Point number types
- Add a for loop for(init;condition;increment) {stmt} -> { init; do { stmt; increment } while (condition) }
- Add imports
- Add structs
- Let { stmt } introduce a new anonymous scope.

View File

@ -44,7 +44,8 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
// No return type. Remove variable receiving the result.
LValue lValue = origCall.getLValue();
if(lValue instanceof Variable) {
scope.remove((Variable) lValue);
Variable lVar = (Variable) lValue;
lVar.getScope().remove(lVar);
}
}

View File

@ -62,7 +62,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
};
phiFixVisitor.visitBlock(successor);
getGraph().getAllBlocks().remove(removeBlock);
getSymbols().remove(removeBlock.getLabel());
removeBlock.getLabel().getScope().remove(removeBlock.getLabel());
log.append("Culled Empty Block " + removeBlock.getLabel());
}
return remove.size()>0;

View File

@ -139,13 +139,13 @@ public class Pass3RegisterAllocation {
allocation.allocate(symbols.getVariable("flip::$0"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("flip::$8"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("flip::$4"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("$1"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("$3"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("c#0"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("c#1"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("c#2"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("c#3"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("c#4"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("main::$1"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("main::$3"), RegisterAllocation.getRegisterA());
allocation.allocate(symbols.getVariable("main::c#0"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("main::c#1"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("main::c#2"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("main::c#3"), RegisterAllocation.getRegisterX());
allocation.allocate(symbols.getVariable("main::c#4"), RegisterAllocation.getRegisterX());
symbols.setAllocation(allocation);
}

View File

@ -1,20 +1,23 @@
byte[1000] SCREEN = $0400;
byte[16*16] buffer1 = $1000;
byte[16*16] buffer2 = $1100;
byte *RASTER = $d012;
prepare();
do {
byte c = 25;
do{
do { } while(*RASTER!=254)
do { } while(*RASTER!=255)
c--;
} while(c!=0)
flip();
plot();
} while(true)
main();
void main() {
prepare();
do {
byte c = 25;
do{
do { } while(*RASTER!=254)
do { } while(*RASTER!=255)
c--;
} while(c!=0)
flip();
plot();
} while(true)
}
// Prepare buffer
void prepare() {

View File

@ -1,31 +1,35 @@
BBEGIN:
jsr main
BEND:
main:
jsr prepare
B2_from_BBEGIN:
main__B2_from_main:
ldx #25
jmp B2
B2_from_B20:
jmp main__B2
main__B2_from_B18:
ldx #25
B2_from_B6:
B2:
B3:
main__B2_from_B2:
main__B2:
main__B3:
lda 53266
cmp #254
bne B3
B4:
bne main__main__B3
main__B4:
lda 53266
cmp #255
bne B4
B6:
bne main__main__B4
B2:
dex
cpx #0
bne B2_from_B6
B7:
bne main__B2_from_B2
B3:
jsr flip
B19:
B17:
jsr plot
B20:
jmp B2_from_B20
BEND:
B18:
jmp main__B2_from_B18
main__Breturn:
rts
plot:
plot__B1_from_plot:
lda #16
@ -35,7 +39,7 @@ plot__B1_from_plot:
sta 101
lda #>1236
sta 101+1
plot__B1_from_B15:
plot__B1_from_B12:
plot__B1:
plot__B2_from_B1:
ldy #0
@ -47,7 +51,7 @@ plot__B2:
iny
cpy #16
bcc plot__B2_from_B2
B15:
B12:
lda 101
clc
adc #40
@ -57,7 +61,7 @@ B15:
!:
dec 100
lda 100
bne plot__B1_from_B15
bne plot__B1_from_B12
plot__Breturn:
rts
flip:
@ -66,7 +70,7 @@ flip__B1_from_flip:
sta 104
ldx #0
ldy #15
flip__B1_from_B11:
flip__B1_from_B8:
flip__B1:
flip__B2_from_B1:
lda #16
@ -83,12 +87,12 @@ flip__B2:
dec 103
lda 103
bne flip__B2_from_B2
B11:
B8:
dey
dec 104
lda 104
bne flip__B1_from_B11
flip__B3_from_B11:
bne flip__B1_from_B8
flip__B3_from_B8:
ldx #0
flip__B3_from_B3:
flip__B3:

View File

@ -1,31 +1,37 @@
@BEGIN: from
call prepare param-assignment
to:@2
@2: from @20 @6 @BEGIN
(byte) c#2 ← phi( @20/(byte) 25 @6/(byte) c#1 @BEGIN/(byte) 25 )
to:@3
@3: from @2 @3
(byte~) $1 ← * (word) 53266
if((byte~) $1!=(byte) 254) goto @3
to:@4
@4: from @3 @4
(byte~) $3 ← * (word) 53266
if((byte~) $3!=(byte) 255) goto @4
to:@6
@6: from @4
(byte) c#1 ← -- (byte) c#2
if((byte) c#1!=(byte) 0) goto @2
to:@7
@7: from @6
call flip param-assignment
to:@19
@19: from @7
call plot param-assignment
to:@20
@20: from @19
if(true) goto @2
call main param-assignment
to:@END
prepare: from @BEGIN
main: from @BEGIN
call prepare param-assignment
to:main::@2
main::@2: from @18 @2 main
(byte) main::c#2 ← phi( @2/(byte) main::c#1 @18/(byte) 25 main/(byte) 25 )
to:main::@3
main::@3: from main::@2 main::@3
(byte~) main::$1 ← * (word) 53266
if((byte~) main::$1!=(byte) 254) goto main::@3
to:main::@4
main::@4: from main::@3 main::@4
(byte~) main::$3 ← * (word) 53266
if((byte~) main::$3!=(byte) 255) goto main::@4
to:@2
@2: from main::@4
(byte) main::c#1 ← -- (byte) main::c#2
if((byte) main::c#1!=(byte) 0) goto main::@2
to:@3
@3: from @2
call flip param-assignment
to:@17
@17: from @3
call plot param-assignment
to:@18
@18: from @17
if(true) goto main::@2
to:main::@return
main::@return: from @18
return
to:@RETURN
prepare: from main
to:prepare::@1
prepare::@1: from prepare prepare::@1
(byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 )
@ -36,12 +42,12 @@ prepare::@1: from prepare prepare::@1
prepare::@return: from prepare::@1
return
to:@RETURN
flip: from @7
flip: from @3
to:flip::@1
flip::@1: from @11 flip
(byte) flip::r#2 ← phi( @11/(byte) flip::r#1 flip/(byte) 16 )
(byte) flip::srcIdx#3 ← phi( @11/(byte) flip::srcIdx#1 flip/(byte) 0 )
(byte) flip::dstIdx#5 ← phi( @11/(byte) flip::dstIdx#2 flip/(byte) 15 )
flip::@1: from @8 flip
(byte) flip::r#2 ← phi( @8/(byte) flip::r#1 flip/(byte) 16 )
(byte) flip::srcIdx#3 ← phi( @8/(byte) flip::srcIdx#1 flip/(byte) 0 )
(byte) flip::dstIdx#5 ← phi( @8/(byte) flip::dstIdx#2 flip/(byte) 15 )
to:flip::@2
flip::@2: from flip::@1 flip::@2
(byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 )
@ -53,14 +59,14 @@ flip::@2: from flip::@1 flip::@2
(byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16
(byte) flip::c#1 ← -- (byte) flip::c#2
if((byte) flip::c#1!=(byte) 0) goto flip::@2
to:@11
@11: from flip::@2
to:@8
@8: from flip::@2
(byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1
(byte) flip::r#1 ← -- (byte) flip::r#2
if((byte) flip::r#1!=(byte) 0) goto flip::@1
to:flip::@3
flip::@3: from @11 flip::@3
(byte) flip::i#2 ← phi( @11/(byte) 0 flip::@3/(byte) flip::i#1 )
flip::@3: from @8 flip::@3
(byte) flip::i#2 ← phi( @8/(byte) 0 flip::@3/(byte) flip::i#1 )
(byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2
*((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4
(byte) flip::i#1 ← ++ (byte) flip::i#2
@ -69,12 +75,12 @@ flip::@3: from @11 flip::@3
flip::@return: from flip::@3
return
to:@RETURN
plot: from @19
plot: from @17
to:plot::@1
plot::@1: from @15 plot
(byte) plot::y#2 ← phi( @15/(byte) plot::y#1 plot/(byte) 16 )
(byte) plot::i#3 ← phi( @15/(byte) plot::i#1 plot/(byte) 0 )
(byte*) plot::line#2 ← phi( @15/(byte*) plot::line#1 plot/(word) 1236 )
plot::@1: from @12 plot
(byte) plot::y#2 ← phi( @12/(byte) plot::y#1 plot/(byte) 16 )
(byte) plot::i#3 ← phi( @12/(byte) plot::i#1 plot/(byte) 0 )
(byte*) plot::line#2 ← phi( @12/(byte*) plot::line#1 plot/(word) 1236 )
to:plot::@2
plot::@2: from plot::@1 plot::@2
(byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 )
@ -84,13 +90,13 @@ plot::@2: from plot::@1 plot::@2
(byte) plot::i#1 ← ++ (byte) plot::i#2
(byte) plot::x#1 ← ++ (byte) plot::x#2
if((byte) plot::x#1<(byte) 16) goto plot::@2
to:@15
@15: from plot::@2
to:@12
@12: from plot::@2
(byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40
(byte) plot::y#1 ← -- (byte) plot::y#2
if((byte) plot::y#1!=(byte) 0) goto plot::@1
to:plot::@return
plot::@return: from @15
plot::@return: from @12
return
to:@RETURN
@END: from @20
@END: from @BEGIN

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,15 @@
(byte~) $1 reg byte a
(byte~) $3 reg byte a
(label) @11
(label) @15
(label) @19
(label) @12
(label) @17
(label) @18
(label) @2
(label) @20
(label) @3
(label) @4
(label) @6
(label) @7
(label) @8
(label) @BEGIN
(label) @END
(byte*) RASTER
(byte[1000]) SCREEN
(byte[256]) buffer1
(byte[256]) buffer2
(byte) c
(byte) c#1 reg byte x
(byte) c#2 reg byte x
(void()) flip()
(byte~) flip::$0 reg byte a
(byte~) flip::$4 reg byte a
@ -44,6 +36,17 @@
(byte) flip::srcIdx#2 reg byte x
(byte) flip::srcIdx#3 reg byte x
(void()) main()
(byte~) main::$1 reg byte a
(byte~) main::$3 reg byte a
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte) main::c
(byte) main::c#1 reg byte x
(byte) main::c#2 reg byte x
(void()) plot()
(byte~) plot::$3 reg byte a
(label) plot::@1