1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-17 10:30:43 +00:00

Improved error reporting when generating ASM statement fails. Added missing fragment. Added another test showing problems with number resolving.

This commit is contained in:
jespergravgaard 2019-09-07 16:14:08 +02:00
parent f09b1616c2
commit 71fc963145
6 changed files with 52 additions and 7 deletions

View File

@ -0,0 +1,18 @@
lda {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
lda {z2}+2
sta {z1}+2
lda {z2}+3
sta {z1}+3
cpx #0
beq !e+
!:
lsr {z1}+3
ror {z1}+2
ror {z1}+1
ror {z1}
dex
bne !-
!e:

View File

@ -3,6 +3,7 @@ package dk.camelot64.kickc.fragment;
import dk.camelot64.kickc.NumberParser; import dk.camelot64.kickc.NumberParser;
import dk.camelot64.kickc.asm.*; import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.model.ConstantNotLiteral; import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.Registers; import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.symbols.ConstantVar; import dk.camelot64.kickc.model.symbols.ConstantVar;
@ -100,7 +101,7 @@ public class AsmFragmentInstance {
String param = AsmFormat.asmFix(((Label) boundValue).getLocalName()); String param = AsmFormat.asmFix(((Label) boundValue).getLocalName());
return new AsmParameter(param, false); return new AsmParameter(param, false);
} else { } else {
throw new RuntimeException("Bound Value Type not implemented " + boundValue); throw new InternalError("Bound Value Type not implemented " + boundValue);
} }
} }
@ -296,7 +297,7 @@ public class AsmFragmentInstance {
addressingMode, addressingMode,
parameter.isZp()); parameter.isZp());
if(type == null) { if(type == null) {
throw new RuntimeException("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter); throw new InternalError("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
} }
return new AsmInstruction(type, parameter.getParam()); return new AsmInstruction(type, parameter.getParam());
} }

View File

@ -6,12 +6,15 @@ import dk.camelot64.kickc.model.statements.StatementSource;
/** Signals some error in the code (or compilation) */ /** Signals some error in the code (or compilation) */
public class CompileError extends RuntimeException { public class CompileError extends RuntimeException {
private String source;
public CompileError(String message) { public CompileError(String message) {
super(message); super(message);
} }
public CompileError(String message, StatementSource source) { public CompileError(String message, StatementSource source) {
super(message+"\n"+source.toString()); super(message+"\n"+source.toString());
this.source = source.toString();
} }
public CompileError(String message, Statement statement) { public CompileError(String message, Statement statement) {
@ -21,4 +24,8 @@ public class CompileError extends RuntimeException {
public CompileError(String message, Throwable cause) { public CompileError(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
public String getSource() {
return source;
}
} }

View File

@ -654,6 +654,10 @@ public class Pass4CodeGeneration {
} else { } else {
throw new CompileError("Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature(), statement.getSource()); throw new CompileError("Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature(), statement.getSource());
} }
} catch(CompileError e) {
if(e.getSource()==null) {
throw new CompileError(e.getMessage(), statement);
}
} }
} }
} }
@ -668,8 +672,7 @@ public class Pass4CodeGeneration {
* @param aluState State of the special ALU register. Used to generate composite fragments when two consecutive statements can be executed effectively. * @param aluState State of the special ALU register. Used to generate composite fragments when two consecutive statements can be executed effectively.
* For example ADC $1100,x combines two statements $0 = $1100 staridx X, A = A+$0 . * For example ADC $1100,x combines two statements $0 = $1100 staridx X, A = A+$0 .
*/ */
public void generateStatementAsm(AsmProgram asm, ControlFlowBlock block, Statement statement, AsmCodegenAluState public void generateStatementAsm(AsmProgram asm, ControlFlowBlock block, Statement statement, AsmCodegenAluState aluState, boolean genCallPhiEntry) {
aluState, boolean genCallPhiEntry) {
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
generateComments(asm, statement.getComments()); generateComments(asm, statement.getComments());
@ -722,7 +725,7 @@ public class Pass4CodeGeneration {
if(callSuccessor != null && callSuccessor.hasPhiBlock()) { if(callSuccessor != null && callSuccessor.hasPhiBlock()) {
PhiTransitions.PhiTransition transition = getTransitions(callSuccessor).getTransition(block); PhiTransitions.PhiTransition transition = getTransitions(callSuccessor).getTransition(block);
if(transitionIsGenerated(transition)) { if(transitionIsGenerated(transition)) {
throw new RuntimeException("Error! JSR transition already generated. Must modify PhiTransitions code to ensure this does not happen."); throw new InternalError("Error! JSR transition already generated. Must modify PhiTransitions code to ensure this does not happen.");
} }
genBlockPhiTransition(asm, block, callSuccessor, block.getScope()); genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
} }
@ -812,10 +815,10 @@ public class Pass4CodeGeneration {
asm.getCurrentChunk().setClobberOverwrite(AsmClobber.CLOBBER_ALL); asm.getCurrentChunk().setClobberOverwrite(AsmClobber.CLOBBER_ALL);
} }
if(!supported) { if(!supported) {
throw new RuntimeException("Call Pointer not supported " + statement); throw new InternalError("Call Pointer not supported " + statement);
} }
} else { } else {
throw new RuntimeException("Statement not supported " + statement); throw new InternalError("Statement not supported " + statement);
} }
} }
} }

View File

@ -44,6 +44,13 @@ public class TestPrograms {
} }
*/ */
/** Fix number type resolving https://gitlab.com/camelot/kickc/issues/199
@Test
public void testConstBool0() throws IOException, URISyntaxException {
compileAndCompare("const-bool-0");
}
*/
@Test @Test
public void testAsmCullingJmp() throws IOException, URISyntaxException { public void testAsmCullingJmp() throws IOException, URISyntaxException {
compileAndCompare("asm-culling-jmp"); compileAndCompare("asm-culling-jmp");

View File

@ -0,0 +1,9 @@
// Tests a complex constant binary
void main() {
char bError = 7;
bError &= ~(0x10 | 0x20 | 0x40);
const char* screen = 0x0400;
*screen = bError;
}