1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-27 19:50:10 +00:00

Working on interrupts

This commit is contained in:
jespergravgaard 2018-08-04 13:07:21 +02:00
parent 18473295c9
commit 0763a63a66
11 changed files with 111 additions and 11 deletions

View File

@ -121,6 +121,7 @@ public class Compiler {
new Pass1AssertNoLValueIntermediate(program).execute();
new Pass1AddTypePromotions(program).execute();
new Pass1AssertNoRecursion(program).execute();
new Pass1AssertInterrupts(program).execute();
getLog().append("INITIAL CONTROL FLOW GRAPH");
getLog().append(program.getGraph().toString(program));

View File

@ -16,11 +16,13 @@ public class Procedure extends Scope {
private final SymbolType returnType;
private List<String> parameterNames;
private boolean declaredInline;
private boolean declaredInterrupt;
public Procedure(String name, SymbolType returnType, Scope parentScope) {
super(name, parentScope);
this.returnType = returnType;
this.declaredInline = false;
this.declaredInterrupt = false;
}
public List<String> getParameterNames() {
@ -73,6 +75,18 @@ public class Procedure extends Scope {
return declaredInline;
}
public void setDeclaredInline(boolean declaredInline) {
this.declaredInline = declaredInline;
}
public boolean isDeclaredInterrupt() {
return declaredInterrupt;
}
public void setDeclaredInterrupt(boolean declaredInterrupt) {
this.declaredInterrupt = declaredInterrupt;
}
@Override
public String toString() {
return toString(null);
@ -84,6 +98,9 @@ public class Procedure extends Scope {
if(declaredInline) {
res.append("inline ");
}
if(declaredInterrupt) {
res.append("interrupt ");
}
res.append("(" + getType().getTypeName() + ") ");
res.append(getFullName());
res.append("(");
@ -123,8 +140,4 @@ public class Procedure extends Scope {
return result;
}
public void setDeclaredInline(boolean declaredInline) {
this.declaredInline = declaredInline;
}
}

View File

@ -348,6 +348,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
StatementSource source = new StatementSource(directivesCtx.get(0));
if(directive instanceof DirectiveInline) {
procedure.setDeclaredInline(true);
} else if(directive instanceof DirectiveInterrupt) {
procedure.setDeclaredInterrupt(true);
} else {
throw new CompileError("Unsupported function directive " + directive, source);
}
@ -364,6 +366,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
return new DirectiveInline();
}
@Override
public Object visitDirectiveInterrupt(KickCParser.DirectiveInterruptContext ctx) {
return new DirectiveInterrupt();
}
@Override
public Directive visitDirectiveAlign(KickCParser.DirectiveAlignContext ctx) {
Number alignment = NumberParser.parseLiteral(ctx.NUMBER().getText());
@ -831,6 +838,10 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
private static class DirectiveInline implements Directive {
}
/** Function declared interrupt. */
private static class DirectiveInterrupt implements Directive {
}
/** Variable memory alignment. */
private static class DirectiveAlign implements Directive {
private int alignment;

View File

@ -0,0 +1,40 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.ProcedureRef;
/** Asserts that interrupts are never called and are not declared inline */
public class Pass1AssertInterrupts extends Pass1Base {
public Pass1AssertInterrupts(Program program) {
super(program);
}
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();
Procedure procedure = getScope().getProcedure(procedureRef);
if(procedure.isDeclaredInterrupt()) {
throw new CompileError("Error! Interrupts cannot be called.", statement.getSource());
}
}
}
for(Procedure procedure : getScope().getAllProcedures(true)) {
if(procedure.isDeclaredInline() && procedure.isDeclaredInterrupt()) {
throw new CompileError("Error! Interrupts cannot be inlined. " + procedure.toString());
}
}
}
return false;
}
}

View File

@ -37,6 +37,9 @@ public class Pass1ProcedureInline extends Pass1Base {
ProcedureRef procedureRef = call.getProcedure();
Procedure procedure = getScope().getProcedure(procedureRef);
if(procedure.isDeclaredInline()) {
if(procedure.isDeclaredInterrupt()) {
throw new CompileError("Error! Interrupts cannot be inlined. "+procedure.getRef().toString());
}
Scope callScope = getScope().getScope(block.getScope());
// Remove call
statementsIt.remove();

View File

@ -881,6 +881,15 @@ public class TestPrograms {
assertError("no-mod-runtime", "Runtime modulo not supported");
}
@Test
public void testNoInlineInterrupt() throws IOException, URISyntaxException {
assertError("no-inlineinterrupt", "Interrupts cannot be inlined");
}
@Test
public void testNoCalledInterrupt() throws IOException, URISyntaxException {
assertError("no-calledinterrupt", "Interrupts cannot be called.");
}
private void assertError(String kcFile, String expectError) throws IOException, URISyntaxException {
try {

View File

@ -1,4 +1,4 @@
// A flexible sprite multiplexer routine for 24 sprites.
// A flexible sprite multiplexer routine for 32 sprites.
// Usage:
// - Once:
// - plexInit(screen): Initialize the data structures and set the screen address
@ -9,8 +9,8 @@
// - plexFreeNextYpos() Returns the Y-position where the next sprite is available to be shown (ie. the next pos where the next sprite is no longer in use showing something else).
// - plexShowNextYpos() Returns the Y-position of the next sprite to show.
//
// In practice a good method is to wait until the raster is beyond plexFreeNextYpos() and then call plexShowSprite(). Repeat until all 24 sprites have been shown.
// TODO: Let the caller specify the number of sprites (PLEX_COUNT)
// In practice a good method is to wait until the raster is beyond plexFreeNextYpos() and then call plexShowSprite(). Repeat until all 32 sprites have been shown.
// TODO: Let the caller specify the number of sprites to use (or add PLEX_ENABLE[PLEX_COUNT])
import "c64"

View File

@ -0,0 +1,12 @@
// Test that inline interrupts not allowed
byte* SCREEN = $400;
void main() {
SCREEN[0]++;
irq();
}
interrupt void irq() {
SCREEN[1]++;
}

View File

@ -0,0 +1,11 @@
// Test that inline interrupts not allowed
byte* SCREEN = $400;
void main() {
SCREEN[0]++;
}
inline interrupt void irq() {
SCREEN[1]++;
}

View File

@ -3,8 +3,8 @@ import "c64"
import "multiplexer"
// Location of screen & sprites
byte* SPRITE = $2000;
byte* SCREEN = $400;
byte* SPRITE = $2000;
byte* YSIN = $2100;
kickasm(pc YSIN) {{

View File

@ -194,7 +194,7 @@ inline void vicSelectGfxBank(byte* gfx) {
Importing multiplexer
PARSING src/test/java/dk/camelot64/kickc/test/kc/multiplexer.kc
// A flexible sprite multiplexer routine for 24 sprites.
// A flexible sprite multiplexer routine for 32 sprites.
// Usage:
// - Once:
// - plexInit(screen): Initialize the data structures and set the screen address
@ -205,8 +205,8 @@ PARSING src/test/java/dk/camelot64/kickc/test/kc/multiplexer.kc
// - plexFreeNextYpos() Returns the Y-position where the next sprite is available to be shown (ie. the next pos where the next sprite is no longer in use showing something else).
// - plexShowNextYpos() Returns the Y-position of the next sprite to show.
//
// In practice a good method is to wait until the raster is beyond plexFreeNextYpos() and then call plexShowSprite(). Repeat until all 24 sprites have been shown.
// TODO: Let the caller specify the number of sprites (PLEX_COUNT)
// In practice a good method is to wait until the raster is beyond plexFreeNextYpos() and then call plexShowSprite(). Repeat until all 32 sprites have been shown.
// TODO: Let the caller specify the number of sprites to use (or add PLEX_ENABLE[PLEX_COUNT])
import "c64"