1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added printable error context to statements

This commit is contained in:
jespergravgaard 2018-05-05 21:34:24 +02:00
parent 21478bd5b6
commit 808b60d06a
36 changed files with 190 additions and 134 deletions

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc;
import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.StatementCall; import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCLexer;
import dk.camelot64.kickc.parser.KickCParser; import dk.camelot64.kickc.parser.KickCParser;
@ -88,7 +89,7 @@ public class Compiler {
Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(program); Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(program);
loadAndParseFile(fileName, program, pass0GenerateStatementSequence); loadAndParseFile(fileName, program, pass0GenerateStatementSequence);
StatementSequence sequence = pass0GenerateStatementSequence.getSequence(); StatementSequence sequence = pass0GenerateStatementSequence.getSequence();
sequence.addStatement(new StatementCall(null, "main", new ArrayList<>())); sequence.addStatement(new StatementCall(null, "main", new ArrayList<>(), new StatementSource(RuleContext.EMPTY)));
program.setStatementSequence(sequence); program.setStatementSequence(sequence);
pass1GenerateSSA(); pass1GenerateSSA();

View File

@ -1,5 +1,8 @@
package dk.camelot64.kickc.model; package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
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 {
@ -7,6 +10,14 @@ public class CompileError extends RuntimeException {
super(message); super(message);
} }
public CompileError(String message, StatementSource source) {
super(message+"\n"+source.toString());
}
public CompileError(String message, Statement statement) {
this(message, statement.getSource());
}
public CompileError(String message, Throwable cause) { public CompileError(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -142,7 +142,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
RValue rValue1 = origAssignment.getrValue1(); RValue rValue1 = origAssignment.getrValue1();
Operator operator = origAssignment.getOperator(); Operator operator = origAssignment.getOperator();
RValue rValue2 = origAssignment.getrValue2(); RValue rValue2 = origAssignment.getrValue2();
return new StatementAssignment(lValue, rValue1, operator, rValue2); return new StatementAssignment(lValue, rValue1, operator, rValue2, origAssignment.getSource());
} }
@Override @Override
@ -151,19 +151,19 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
Operator operator = origConditionalJump.getOperator(); Operator operator = origConditionalJump.getOperator();
RValue rValue2 = origConditionalJump.getrValue2(); RValue rValue2 = origConditionalJump.getrValue2();
LabelRef destination = origConditionalJump.getDestination(); LabelRef destination = origConditionalJump.getDestination();
return new StatementConditionalJump(rValue1, operator, rValue2, destination); return new StatementConditionalJump(rValue1, operator, rValue2, destination, origConditionalJump.getSource());
} }
@Override @Override
public StatementJump visitJump(StatementJump origJump) { public StatementJump visitJump(StatementJump origJump) {
LabelRef destination = origJump.getDestination(); LabelRef destination = origJump.getDestination();
return new StatementJump(destination); return new StatementJump(destination, origJump.getSource());
} }
@Override @Override
public StatementLabel visitJumpTarget(StatementLabel origJump) { public StatementLabel visitJumpTarget(StatementLabel origJump) {
LabelRef label = origJump.getLabel(); LabelRef label = origJump.getLabel();
return new StatementLabel(label); return new StatementLabel(label, origJump.getSource());
} }
@Override @Override
@ -171,26 +171,26 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
LValue lValue = origCall.getlValue(); LValue lValue = origCall.getlValue();
String procedureName = origCall.getProcedureName(); String procedureName = origCall.getProcedureName();
List<RValue> parameters = origCall.getParameters(); List<RValue> parameters = origCall.getParameters();
return new StatementCall(lValue, procedureName, parameters); return new StatementCall(lValue, procedureName, parameters, origCall.getSource());
} }
@Override @Override
public StatementProcedureBegin visitProcedureBegin(StatementProcedureBegin origProcedureBegin) { public StatementProcedureBegin visitProcedureBegin(StatementProcedureBegin origProcedureBegin) {
return new StatementProcedureBegin(origProcedureBegin.getProcedure()); return new StatementProcedureBegin(origProcedureBegin.getProcedure(), origProcedureBegin.getSource());
} }
@Override @Override
public StatementProcedureEnd visitProcedureEnd(StatementProcedureEnd origProcedureEnd) { public StatementProcedureEnd visitProcedureEnd(StatementProcedureEnd origProcedureEnd) {
return new StatementProcedureEnd(origProcedureEnd.getProcedure()); return new StatementProcedureEnd(origProcedureEnd.getProcedure(), origProcedureEnd.getSource());
} }
@Override @Override
public StatementReturn visitReturn(StatementReturn origReturn) { public StatementReturn visitReturn(StatementReturn origReturn) {
return new StatementReturn(origReturn.getValue()); return new StatementReturn(origReturn.getValue(), origReturn.getSource());
} }
@Override @Override
public Object visitAsm(StatementAsm asm) { public Object visitAsm(StatementAsm asm) {
return new StatementAsm(asm.getAsmLines()); return new StatementAsm(asm.getAsmLines(), asm.getSource());
} }
} }

View File

@ -16,4 +16,10 @@ public interface Statement {
/** Set the index of the statement. Indexes are used during live range analysis. */ /** Set the index of the statement. Indexes are used during live range analysis. */
void setIndex(Integer idx); void setIndex(Integer idx);
/**
* Get the source for the statement*
*/
StatementSource getSource();
} }

View File

@ -9,8 +9,9 @@ public class StatementAsm extends StatementBase {
/** ASM Fragment code. */ /** ASM Fragment code. */
private KickCParser.AsmLinesContext asmLines; private KickCParser.AsmLinesContext asmLines;
public StatementAsm(KickCParser.AsmLinesContext asmLines) { public StatementAsm(KickCParser.AsmLinesContext asmLines,
super(null); StatementSource source) {
super(null, source);
this.asmLines = asmLines; this.asmLines = asmLines;
} }

View File

@ -22,24 +22,16 @@ public class StatementAssignment extends StatementBase implements StatementLValu
private Operator operator; private Operator operator;
private RValue rValue2; private RValue rValue2;
public StatementAssignment(LValue lValue, RValue rValue2) { public StatementAssignment(LValue lValue, RValue rValue2, StatementSource source) {
this(lValue, null, null, rValue2, null); this(lValue, null, null, rValue2, null, source);
} }
public StatementAssignment(LValue lValue, Operator operator, RValue rValue2) { public StatementAssignment(LValue lValue, Operator operator, RValue rValue2,StatementSource source) {
this(lValue, null, operator, rValue2, null); this(lValue, null, operator, rValue2, null, source);
} }
public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) { public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2, StatementSource source) {
this(lValue, rValue1, operator, rValue2, null); this(lValue, rValue1, operator, rValue2, null, source);
}
public StatementAssignment(Variable lValue, Variable rValue2) {
this(lValue.getRef(), rValue2.getRef());
}
public StatementAssignment(Variable lValue, RValue rValue2) {
this(lValue.getRef(), rValue2);
} }
public StatementAssignment( public StatementAssignment(
@ -47,8 +39,9 @@ public class StatementAssignment extends StatementBase implements StatementLValu
RValue rValue1, RValue rValue1,
Operator operator, Operator operator,
RValue rValue2, RValue rValue2,
Integer index) { Integer index,
super(index); StatementSource source) {
super(index, source);
this.lValue = lValue; this.lValue = lValue;
this.rValue1 = rValue1; this.rValue1 = rValue1;
this.operator = operator; this.operator = operator;

View File

@ -12,10 +12,18 @@ import java.util.List;
/** Statement base class implementing shared properties and logic */ /** Statement base class implementing shared properties and logic */
public abstract class StatementBase implements Statement { public abstract class StatementBase implements Statement {
private StatementSource source;
private Integer index; private Integer index;
public StatementBase(Integer index) { public StatementBase(Integer index, StatementSource source) {
this.index = index; this.index = index;
this.source = source;
}
@Override
public StatementSource getSource() {
return source;
} }
@Override @Override

View File

@ -22,8 +22,8 @@ public class StatementCall extends StatementBase implements StatementLValue {
private ProcedureRef procedure; private ProcedureRef procedure;
private List<RValue> parameters; private List<RValue> parameters;
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters) { public StatementCall(LValue lValue, String procedureName, List<RValue> parameters, StatementSource source) {
super(null); super(null, source);
this.lValue = lValue; this.lValue = lValue;
this.procedureName = procedureName; this.procedureName = procedureName;
this.parameters = parameters; this.parameters = parameters;

View File

@ -20,8 +20,8 @@ public class StatementConditionalJump extends StatementBase {
private RValue rValue2; private RValue rValue2;
private LabelRef destination; private LabelRef destination;
public StatementConditionalJump(RValue condition, LabelRef destination) { public StatementConditionalJump(RValue condition, LabelRef destination,StatementSource source) {
super(null); super(null, source);
this.rValue1 = null; this.rValue1 = null;
this.operator = null; this.operator = null;
this.rValue2 = condition; this.rValue2 = condition;
@ -32,8 +32,9 @@ public class StatementConditionalJump extends StatementBase {
RValue rValue1, RValue rValue1,
Operator operator, Operator operator,
RValue rValue2, RValue rValue2,
LabelRef destination) { LabelRef destination,
this(rValue1, operator, rValue2, destination, null); StatementSource source) {
this(rValue1, operator, rValue2, destination, null, source);
} }
public StatementConditionalJump( public StatementConditionalJump(
@ -41,8 +42,9 @@ public class StatementConditionalJump extends StatementBase {
Operator operator, Operator operator,
RValue rValue2, RValue rValue2,
LabelRef destination, LabelRef destination,
Integer index) { Integer index,
super(index); StatementSource source) {
super(index, source);
this.rValue1 = rValue1; this.rValue1 = rValue1;
this.operator = operator; this.operator = operator;
this.rValue2 = rValue2; this.rValue2 = rValue2;

View File

@ -13,8 +13,9 @@ public class StatementJump extends StatementBase {
private LabelRef destination; private LabelRef destination;
public StatementJump(LabelRef destination) { public StatementJump(LabelRef destination,
super(null); StatementSource source) {
super(null, source);
this.destination = destination; this.destination = destination;
} }

View File

@ -10,8 +10,9 @@ public class StatementLabel extends StatementBase {
private LabelRef label; private LabelRef label;
public StatementLabel(LabelRef label) { public StatementLabel(LabelRef label,
super(null); StatementSource source) {
super(null, source);
this.label = label; this.label = label;
} }

View File

@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef; import dk.camelot64.kickc.model.values.VariableRef;
import org.antlr.v4.runtime.RuleContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -22,13 +23,14 @@ public class StatementPhiBlock extends StatementBase {
public StatementPhiBlock( public StatementPhiBlock(
List<PhiVariable> phiVariables, List<PhiVariable> phiVariables,
Integer index) { Integer index,
super(index); StatementSource source) {
super(index, source);
this.phiVariables = phiVariables; this.phiVariables = phiVariables;
} }
public StatementPhiBlock() { public StatementPhiBlock() {
super(null); super(null, new StatementSource(RuleContext.EMPTY));
this.phiVariables = new ArrayList<>(); this.phiVariables = new ArrayList<>();
} }

View File

@ -10,8 +10,8 @@ public class StatementProcedureBegin extends StatementBase {
private Strategy strategy; private Strategy strategy;
public StatementProcedureBegin(ProcedureRef procedure) { public StatementProcedureBegin(ProcedureRef procedure,StatementSource source) {
super(null); super(null, source);
this.procedure = procedure; this.procedure = procedure;
} }

View File

@ -10,8 +10,8 @@ public class StatementProcedureEnd extends StatementBase {
private ProcedureRef procedure; private ProcedureRef procedure;
public StatementProcedureEnd(ProcedureRef procedure) { public StatementProcedureEnd(ProcedureRef procedure, StatementSource source) {
super(null); super(null, source);
this.procedure = procedure; this.procedure = procedure;
} }

View File

@ -13,8 +13,8 @@ public class StatementReturn extends StatementBase {
*/ */
private RValue value; private RValue value;
public StatementReturn(RValue value) { public StatementReturn(RValue value, StatementSource source) {
super(null); super(null, source);
this.value = value; this.value = value;
} }

View File

@ -0,0 +1,23 @@
package dk.camelot64.kickc.model.statements;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.Interval;
/** Contains information about the source of a program statement */
public class StatementSource {
private ParserRuleContext context;
public StatementSource(ParserRuleContext context) {
this.context = context;
}
@Override
public String toString() {
CharStream stream = context.getStart().getInputStream();
Interval interval = new Interval(context.getStart().getStartIndex(), context.getStop().getStopIndex());
String sourceMessage = "File "+stream.getSourceName()+"\nLine "+context.getStart().getLine()+ "\n" +stream.getText(interval);
return sourceMessage;
}
}

View File

@ -102,21 +102,21 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
parameterList = (List<Variable>) this.visit(ctx.parameterListDecl()); parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
} }
procedure.setParameters(parameterList); procedure.setParameters(parameterList);
sequence.addStatement(new StatementProcedureBegin(procedure.getRef())); sequence.addStatement(new StatementProcedureBegin(procedure.getRef(), new StatementSource(ctx)));
if(ctx.stmtSeq() != null) { if(ctx.stmtSeq() != null) {
this.visit(ctx.stmtSeq()); this.visit(ctx.stmtSeq());
} }
sequence.addStatement(new StatementLabel(procExit.getRef())); sequence.addStatement(new StatementLabel(procExit.getRef(), new StatementSource(ctx)));
if(returnVar != null) { if(returnVar != null) {
sequence.addStatement(new StatementAssignment(returnVar, returnVar)); sequence.addStatement(new StatementAssignment(returnVar.getRef(), returnVar.getRef(), new StatementSource(ctx)));
} }
VariableRef returnVarRef = null; VariableRef returnVarRef = null;
if(returnVar != null) { if(returnVar != null) {
returnVarRef = returnVar.getRef(); returnVarRef = returnVar.getRef();
} }
sequence.addStatement(new StatementReturn(returnVarRef)); sequence.addStatement(new StatementReturn(returnVarRef, new StatementSource(ctx)));
scopeStack.pop(); scopeStack.pop();
sequence.addStatement(new StatementProcedureEnd(procedure.getRef())); sequence.addStatement(new StatementProcedureEnd(procedure.getRef(), new StatementSource(ctx)));
return null; return null;
} }
@ -158,9 +158,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
SymbolTypeArray typeArray = (SymbolTypeArray) type; SymbolTypeArray typeArray = (SymbolTypeArray) type;
Integer size = typeArray.getSize(); Integer size = typeArray.getSize();
if(size == null) { if(size == null) {
throw new CompileError("Error! Cannot determine array size. " + lValue.toString(program)); throw new CompileError("Error! Cannot determine array size. " + lValue.toString(program), new StatementSource(ctx));
} }
Statement stmt = new StatementAssignment(lValue, new ConstantArrayFilled(typeArray.getElementType(), size)); Statement stmt = new StatementAssignment(lValue.getRef(), new ConstantArrayFilled(typeArray.getElementType(), size), new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
} }
return null; return null;
@ -181,23 +181,24 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
directives.add((Directive) this.visit(directiveContext)); directives.add((Directive) this.visit(directiveContext));
} }
for(Directive directive : directives) { for(Directive directive : directives) {
StatementSource source = new StatementSource(directivesCtx.get(0));
if(directive instanceof DirectiveConst) { if(directive instanceof DirectiveConst) {
lValue.setDeclaredConstant(true); lValue.setDeclaredConstant(true);
} else if(directive instanceof DirectiveAlign) { } else if(directive instanceof DirectiveAlign) {
if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) { if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) {
lValue.setDeclaredAlignment(((DirectiveAlign) directive).getAlignment()); lValue.setDeclaredAlignment(((DirectiveAlign) directive).getAlignment());
} else { } else {
throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(program)); throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(program), source);
} }
} else if(directive instanceof DirectiveRegister) { } else if(directive instanceof DirectiveRegister) {
DirectiveRegister directiveRegister = (DirectiveRegister) directive; DirectiveRegister directiveRegister = (DirectiveRegister) directive;
Registers.Register register = Registers.getRegister(directiveRegister.getName()); Registers.Register register = Registers.getRegister(directiveRegister.getName());
if(register == null) { if(register == null) {
throw new CompileError("Error! Unknown register " + directiveRegister.getName()); throw new CompileError("Error! Unknown register " + directiveRegister.getName(), source);
} }
lValue.setDeclaredRegister(register); lValue.setDeclaredRegister(register);
} else { } else {
throw new CompileError("Unsupported variable directive " + directive); throw new CompileError("Unsupported variable directive " + directive, source);
} }
} }
} }
@ -214,10 +215,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
directives.add((Directive) this.visit(directiveContext)); directives.add((Directive) this.visit(directiveContext));
} }
for(Directive directive : directives) { for(Directive directive : directives) {
StatementSource source = new StatementSource(directivesCtx.get(0));
if(directive instanceof DirectiveInline) { if(directive instanceof DirectiveInline) {
procedure.setDeclaredInline(true); procedure.setDeclaredInline(true);
} else { } else {
throw new CompileError("Unsupported function directive " + directive); throw new CompileError("Unsupported function directive " + directive, source);
} }
} }
} }
@ -280,26 +282,26 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
if(elseStmt==null) { if(elseStmt==null) {
// If without else - skip the entire section if condition not met // If without else - skip the entire section if condition not met
VariableRef notExprVar = getCurrentSymbols().addVariableIntermediate().getRef(); VariableRef notExprVar = getCurrentSymbols().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(notExprVar, null, Operators.LOGIC_NOT, rValue)); sequence.addStatement(new StatementAssignment(notExprVar, null, Operators.LOGIC_NOT, rValue, new StatementSource(ctx)));
PrePostModifierHandler.addPostModifiers(this, ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr());
Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate();
sequence.addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef())); sequence.addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef(), new StatementSource(ctx)));
this.visit(ifStmt); this.visit(ifStmt);
// No else statement - just add the label // No else statement - just add the label
sequence.addStatement(new StatementLabel(endJumpLabel.getRef())); sequence.addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx)));
} else { } else {
// If with else - jump to if section if condition met - fall into else otherwise. // If with else - jump to if section if condition met - fall into else otherwise.
PrePostModifierHandler.addPostModifiers(this, ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr());
Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate();
sequence.addStatement(new StatementConditionalJump(rValue, ifJumpLabel.getRef())); sequence.addStatement(new StatementConditionalJump(rValue, ifJumpLabel.getRef(), new StatementSource(ctx)));
// Add else body // Add else body
this.visit(elseStmt); this.visit(elseStmt);
// There is an else statement - add the if part and any needed labels/jumps // There is an else statement - add the if part and any needed labels/jumps
Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate();
sequence.addStatement(new StatementJump(endJumpLabel.getRef())); sequence.addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx)));
sequence.addStatement(new StatementLabel(ifJumpLabel.getRef())); sequence.addStatement(new StatementLabel(ifJumpLabel.getRef(), new StatementSource(ctx)));
this.visit(ifStmt); this.visit(ifStmt);
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(endJumpTarget); sequence.addStatement(endJumpTarget);
} }
return null; return null;
@ -310,21 +312,21 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate();
Label doJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label doJumpLabel = getCurrentSymbols().addLabelIntermediate();
Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate();
StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(beginJumpTarget); sequence.addStatement(beginJumpTarget);
PrePostModifierHandler.addPreModifiers(this, ctx.expr()); PrePostModifierHandler.addPreModifiers(this, ctx.expr());
RValue rValue = (RValue) this.visit(ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr());
PrePostModifierHandler.addPostModifiers(this, ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr());
Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef()); Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(doJmpStmt); sequence.addStatement(doJmpStmt);
Statement endJmpStmt = new StatementJump(endJumpLabel.getRef()); Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(endJmpStmt); sequence.addStatement(endJmpStmt);
StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef()); StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(doJumpTarget); sequence.addStatement(doJumpTarget);
this.visit(ctx.stmt()); this.visit(ctx.stmt());
Statement beginJmpStmt = new StatementJump(beginJumpLabel.getRef()); Statement beginJmpStmt = new StatementJump(beginJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(beginJmpStmt); sequence.addStatement(beginJmpStmt);
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(endJumpTarget); sequence.addStatement(endJumpTarget);
return null; return null;
} }
@ -332,7 +334,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override @Override
public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) {
Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate();
StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(beginJumpTarget); sequence.addStatement(beginJumpTarget);
if(ctx.stmt() != null) { if(ctx.stmt() != null) {
this.visit(ctx.stmt()); this.visit(ctx.stmt());
@ -340,7 +342,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
PrePostModifierHandler.addPreModifiers(this, ctx.expr()); PrePostModifierHandler.addPreModifiers(this, ctx.expr());
RValue rValue = (RValue) this.visit(ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr());
PrePostModifierHandler.addPostModifiers(this, ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr());
Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel.getRef()); Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(doJmpStmt); sequence.addStatement(doJmpStmt);
return null; return null;
} }
@ -379,7 +381,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
} }
// Add label // Add label
Label repeatLabel = getCurrentSymbols().addLabelIntermediate(); Label repeatLabel = getCurrentSymbols().addLabelIntermediate();
StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef()); StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(repeatTarget); sequence.addStatement(repeatTarget);
// Add body // Add body
if(stmtForCtx.stmt() != null) { if(stmtForCtx.stmt() != null) {
@ -396,7 +398,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
RValue rValue = (RValue) this.visit(ctx.expr(0)); RValue rValue = (RValue) this.visit(ctx.expr(0));
PrePostModifierHandler.addPostModifiers(this, ctx.expr(0)); PrePostModifierHandler.addPostModifiers(this, ctx.expr(0));
// Add jump if condition was met // Add jump if condition was met
Statement doJmpStmt = new StatementConditionalJump(rValue, repeatLabel.getRef()); Statement doJmpStmt = new StatementConditionalJump(rValue, repeatLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(doJmpStmt); sequence.addStatement(doJmpStmt);
return null; return null;
} }
@ -417,7 +419,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
lValue = getCurrentSymbols().getVariable(varName); lValue = getCurrentSymbols().getVariable(varName);
} }
if(lValue == null) { if(lValue == null) {
throw new CompileError("Unknown variable! " + varName); throw new CompileError("Unknown variable! " + varName, new StatementSource(ctx));
} }
KickCParser.ExprContext rangeFirstCtx = ctx.expr(0); KickCParser.ExprContext rangeFirstCtx = ctx.expr(0);
KickCParser.ExprContext rangeLastCtx = ctx.expr(1); KickCParser.ExprContext rangeLastCtx = ctx.expr(1);
@ -426,11 +428,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
ConstantInteger rangeLast = (ConstantInteger) ParseTreeConstantEvaluator.evaluate(rangeLastCtx); ConstantInteger rangeLast = (ConstantInteger) ParseTreeConstantEvaluator.evaluate(rangeLastCtx);
// Assign loop variable with first value // Assign loop variable with first value
RValue rValue = (RValue) visit(rangeFirstCtx); RValue rValue = (RValue) visit(rangeFirstCtx);
Statement stmtInit = new StatementAssignment(lValue, rValue); Statement stmtInit = new StatementAssignment(lValue.getRef(), rValue, new StatementSource(ctx));
sequence.addStatement(stmtInit); sequence.addStatement(stmtInit);
// Add label // Add label
Label repeatLabel = getCurrentSymbols().addLabelIntermediate(); Label repeatLabel = getCurrentSymbols().addLabelIntermediate();
StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef()); StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(repeatTarget); sequence.addStatement(repeatTarget);
// Add body // Add body
if(stmtForCtx.stmt() != null) { if(stmtForCtx.stmt() != null) {
@ -439,7 +441,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
// Add increment // Add increment
ConstantInteger beyondLastVal; ConstantInteger beyondLastVal;
if(rangeFirst.getValue() > rangeLast.getValue()) { if(rangeFirst.getValue() > rangeLast.getValue()) {
Statement stmtInc = new StatementAssignment(lValue.getRef(), Operators.DECREMENT, lValue.getRef()); Statement stmtInc = new StatementAssignment(lValue.getRef(), Operators.DECREMENT, lValue.getRef(), new StatementSource(ctx));
sequence.addStatement(stmtInc); sequence.addStatement(stmtInc);
if(rangeLast.getValue() == 0) { if(rangeLast.getValue() == 0) {
beyondLastVal = new ConstantInteger(255L); beyondLastVal = new ConstantInteger(255L);
@ -447,7 +449,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
beyondLastVal = new ConstantInteger(rangeLast.getValue() - 1); beyondLastVal = new ConstantInteger(rangeLast.getValue() - 1);
} }
} else { } else {
Statement stmtInc = new StatementAssignment(lValue.getRef(), Operators.INCREMENT, lValue.getRef()); Statement stmtInc = new StatementAssignment(lValue.getRef(), Operators.INCREMENT, lValue.getRef(), new StatementSource(ctx));
sequence.addStatement(stmtInc); sequence.addStatement(stmtInc);
if(rangeLast.getValue() == 255) { if(rangeLast.getValue() == 255) {
beyondLastVal = new ConstantInteger(0L); beyondLastVal = new ConstantInteger(0L);
@ -459,17 +461,17 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
// Add condition i<last+1 or i<last-1 // Add condition i<last+1 or i<last-1
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef(); VariableRef tmpVarRef = tmpVar.getRef();
Statement stmtTmpVar = new StatementAssignment(tmpVarRef, lValue.getRef(), Operators.NEQ, beyondLastVal); Statement stmtTmpVar = new StatementAssignment(tmpVarRef, lValue.getRef(), Operators.NEQ, beyondLastVal, new StatementSource(ctx));
sequence.addStatement(stmtTmpVar); sequence.addStatement(stmtTmpVar);
// Add jump if condition was met // Add jump if condition was met
Statement doJmpStmt = new StatementConditionalJump(tmpVarRef, repeatLabel.getRef()); Statement doJmpStmt = new StatementConditionalJump(tmpVarRef, repeatLabel.getRef(), new StatementSource(ctx));
sequence.addStatement(doJmpStmt); sequence.addStatement(doJmpStmt);
return null; return null;
} }
@Override @Override
public Object visitStmtAsm(KickCParser.StmtAsmContext ctx) { public Object visitStmtAsm(KickCParser.StmtAsmContext ctx) {
sequence.addStatement(new StatementAsm(ctx.asmLines())); sequence.addStatement(new StatementAsm(ctx.asmLines(), new StatementSource(ctx)));
return null; return null;
} }
@ -482,18 +484,18 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
PrePostModifierHandler.addPreModifiers(this, exprCtx); PrePostModifierHandler.addPreModifiers(this, exprCtx);
rValue = (RValue) this.visit(exprCtx); rValue = (RValue) this.visit(exprCtx);
Variable returnVar = procedure.getVariable("return"); Variable returnVar = procedure.getVariable("return");
sequence.addStatement(new StatementAssignment(returnVar, rValue)); sequence.addStatement(new StatementAssignment(returnVar.getRef(), rValue, new StatementSource(ctx)));
PrePostModifierHandler.addPostModifiers(this, exprCtx); PrePostModifierHandler.addPostModifiers(this, exprCtx);
} }
Label returnLabel = procedure.getLabel(SymbolRef.PROCEXIT_BLOCK_NAME); Label returnLabel = procedure.getLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
sequence.addStatement(new StatementJump(returnLabel.getRef())); sequence.addStatement(new StatementJump(returnLabel.getRef(), new StatementSource(ctx)));
return null; return null;
} }
private void addInitialAssignment(KickCParser.ExprContext initializer, Variable lValue) { private void addInitialAssignment(KickCParser.ExprContext initializer, Variable lValue) {
PrePostModifierHandler.addPreModifiers(this, initializer); PrePostModifierHandler.addPreModifiers(this, initializer);
RValue rValue = (RValue) visit(initializer); RValue rValue = (RValue) visit(initializer);
Statement stmt = new StatementAssignment(lValue, rValue); Statement stmt = new StatementAssignment(lValue.getRef(), rValue, new StatementSource(initializer));
sequence.addStatement(stmt); sequence.addStatement(stmt);
PrePostModifierHandler.addPostModifiers(this, initializer); PrePostModifierHandler.addPostModifiers(this, initializer);
} }
@ -547,7 +549,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
lValue = new LvalueIntermediate((VariableRef) lValue); lValue = new LvalueIntermediate((VariableRef) lValue);
} }
RValue rValue = (RValue) this.visit(ctx.expr(1)); RValue rValue = (RValue) this.visit(ctx.expr(1));
Statement stmt = new StatementAssignment(lValue, rValue); Statement stmt = new StatementAssignment(lValue, rValue, new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
return lValue; return lValue;
} }
@ -565,7 +567,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText();
Operator operator = Operators.getBinaryCompound(op); Operator operator = Operators.getBinaryCompound(op);
// Assignment with operator // Assignment with operator
Statement stmt = new StatementAssignment(lValue, lValue, operator, rValue); Statement stmt = new StatementAssignment(lValue, lValue, operator, rValue, new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
return lValue; return lValue;
} }
@ -577,7 +579,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
Operator operator = Operators.getCastUnary(castType); Operator operator = Operators.getCastUnary(castType);
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef(); VariableRef tmpVarRef = tmpVar.getRef();
Statement stmt = new StatementAssignment(tmpVarRef, operator, child); Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
return tmpVarRef; return tmpVarRef;
} }
@ -593,7 +595,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
} }
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef(); VariableRef tmpVarRef = tmpVar.getRef();
sequence.addStatement(new StatementCall(tmpVarRef, ctx.NAME().getText(), parameters)); sequence.addStatement(new StatementCall(tmpVarRef, ctx.NAME().getText(), parameters, new StatementSource(ctx)));
return tmpVarRef; return tmpVarRef;
} }
@ -649,7 +651,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
Operator operator = Operators.getBinary(op); Operator operator = Operators.getBinary(op);
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef(); VariableRef tmpVarRef = tmpVar.getRef();
Statement stmt = new StatementAssignment(tmpVarRef, left, operator, right); Statement stmt = new StatementAssignment(tmpVarRef, left, operator, right, new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
return tmpVarRef; return tmpVarRef;
} }
@ -667,7 +669,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
Operator operator = Operators.getUnary(op); Operator operator = Operators.getUnary(op);
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef(); VariableRef tmpVarRef = tmpVar.getRef();
Statement stmt = new StatementAssignment(tmpVarRef, operator, child); Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx));
sequence.addStatement(stmt); sequence.addStatement(stmt);
return tmpVarRef; return tmpVarRef;
} }
@ -763,21 +765,22 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
PrePostModifierHandler prePostModifierHandler = new PrePostModifierHandler(parser); PrePostModifierHandler prePostModifierHandler = new PrePostModifierHandler(parser);
prePostModifierHandler.visit(ctx); prePostModifierHandler.visit(ctx);
List<PrePostModifier> modifiers = prePostModifierHandler.getPostMods(); List<PrePostModifier> modifiers = prePostModifierHandler.getPostMods();
addModifierStatements(parser, modifiers); addModifierStatements(parser, modifiers, new StatementSource(ctx));
} }
public static void addPreModifiers(Pass0GenerateStatementSequence parser, ParserRuleContext ctx) { public static void addPreModifiers(Pass0GenerateStatementSequence parser, ParserRuleContext ctx) {
PrePostModifierHandler modifierHandler = new PrePostModifierHandler(parser); PrePostModifierHandler modifierHandler = new PrePostModifierHandler(parser);
modifierHandler.visit(ctx); modifierHandler.visit(ctx);
List<PrePostModifier> modifiers = modifierHandler.getPreMods(); List<PrePostModifier> modifiers = modifierHandler.getPreMods();
addModifierStatements(parser, modifiers); addModifierStatements(parser, modifiers, new StatementSource(ctx));
} }
private static void addModifierStatements( private static void addModifierStatements(
Pass0GenerateStatementSequence parser, Pass0GenerateStatementSequence parser,
List<PrePostModifier> modifiers) { List<PrePostModifier> modifiers,
StatementSource source) {
for(PrePostModifier mod : modifiers) { for(PrePostModifier mod : modifiers) {
Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child); Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child, source);
parser.sequence.addStatement(stmt); parser.sequence.addStatement(stmt);
parser.program.getLog().append("Adding pre/post-modifier " + stmt.toString(parser.program, true)); parser.program.getLog().append("Adding pre/post-modifier " + stmt.toString(parser.program, true));
} }

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -67,7 +68,7 @@ public class Pass1AddTypePromotions extends Pass1Base {
String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " + String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " +
"In " + assignment.toString(getProgram(), false); "In " + assignment.toString(getProgram(), false);
getProgram().getLog().append(msg); getProgram().getLog().append(msg);
throw new CompileError(msg); throw new CompileError(msg, assignment.getSource());
} }
} }

View File

@ -32,11 +32,11 @@ public class Pass1AssertArrayLengths extends Pass1Base {
RValue value = assignment.getrValue2(); RValue value = assignment.getrValue2();
if(value instanceof ValueList) { if(value instanceof ValueList) {
if(((ValueList) value).getList().size() != declaredSize) { if(((ValueList) value).getList().size() != declaredSize) {
throw new CompileError("Error! Array length mismatch " + statement.toString(getProgram(), false)); throw new CompileError("Error! Array length mismatch " + statement.toString(getProgram(), false), statement.getSource());
} }
} else if(value instanceof ConstantString) { } else if(value instanceof ConstantString) {
if(((ConstantString) value).getValue().length() != declaredSize) { if(((ConstantString) value).getValue().length() != declaredSize) {
throw new CompileError("Error! Array length mismatch " + statement.toString(getProgram(), false)); throw new CompileError("Error! Array length mismatch " + statement.toString(getProgram(), false), statement.getSource());
} }
} }
} }

View File

@ -26,7 +26,7 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
if(lValue instanceof LvalueIntermediate) { if(lValue instanceof LvalueIntermediate) {
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable(); VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
StatementAssignment assignment = getGraph().getAssignment(intermediateVar); StatementAssignment assignment = getGraph().getAssignment(intermediateVar);
throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + assignment); throw new CompileError("Error! LValue is illegal. " + statement + " - definition of lValue " + assignment, assignment.getSource());
} }
} }
} }

View File

@ -55,7 +55,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
Collection<VariableRef> used = referenceInfos.getUsedVars(statement); Collection<VariableRef> used = referenceInfos.getUsedVars(statement);
for(VariableRef usedRef : used) { for(VariableRef usedRef : used) {
if(!defined.contains(usedRef)) { if(!defined.contains(usedRef)) {
throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + statement.toString(getProgram(), false)); throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + statement.toString(getProgram(), false), statement.getSource());
} }
} }
Collection<VariableRef> defd = referenceInfos.getDefinedVars(statement); Collection<VariableRef> defd = referenceInfos.getDefinedVars(statement);

View File

@ -69,7 +69,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
statementLValue.setlValue(tmpVarRef); statementLValue.setlValue(tmpVarRef);
SymbolTypeInference.inferLValue(getProgram(), statementLValue, false); SymbolTypeInference.inferLValue(getProgram(), statementLValue, false);
// Insert an extra "set low" assignment statement // Insert an extra "set low" assignment statement
Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef); Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource());
statementsIt.add(setLoHiAssignment); statementsIt.add(setLoHiAssignment);
getLog().append("Fixing lo/hi-lvalue with new tmpVar " + tmpVarRef + " " + statementLValue.toString()); getLog().append("Fixing lo/hi-lvalue with new tmpVar " + tmpVarRef + " " + statementLValue.toString());
} }

View File

@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.SymbolRef; import dk.camelot64.kickc.model.values.SymbolRef;
import org.antlr.v4.runtime.RuleContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -32,7 +33,7 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
ControlFlowBlock firstBlock = getOrCreateBlock(scope.addLabel(SymbolRef.BEGIN_BLOCK_NAME).getRef(), ScopeRef.ROOT); ControlFlowBlock firstBlock = getOrCreateBlock(scope.addLabel(SymbolRef.BEGIN_BLOCK_NAME).getRef(), ScopeRef.ROOT);
Stack<ControlFlowBlock> blockStack = new Stack<>(); Stack<ControlFlowBlock> blockStack = new Stack<>();
blockStack.push(firstBlock); blockStack.push(firstBlock);
sequence.addStatement(new StatementLabel(scope.addLabel(SymbolRef.END_BLOCK_NAME).getRef())); sequence.addStatement(new StatementLabel(scope.addLabel(SymbolRef.END_BLOCK_NAME).getRef(), new StatementSource(RuleContext.EMPTY)));
for(Statement statement : sequence.getStatements()) { for(Statement statement : sequence.getStatements()) {
ControlFlowBlock currentBlock = blockStack.peek(); ControlFlowBlock currentBlock = blockStack.peek();
Symbol currentBlockLabel = scope.getSymbol(currentBlock.getLabel()); Symbol currentBlockLabel = scope.getSymbol(currentBlock.getLabel());

View File

@ -58,7 +58,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
if(assignedSymbol.isDeclaredConstant()) { if(assignedSymbol.isDeclaredConstant()) {
Collection<VariableVersion> versions = assignedVar.getScope().getVersions(assignedSymbol); Collection<VariableVersion> versions = assignedVar.getScope().getVersions(assignedSymbol);
if(versions.size() != 0) { if(versions.size() != 0) {
throw new CompileError("Error! Constants can not be modified " + statement); throw new CompileError("Error! Constants can not be modified " + statement, statement.getSource());
} }
version = assignedSymbol.createVersion(); version = assignedSymbol.createVersion();
version.setDeclaredConstant(true); version.setDeclaredConstant(true);

View File

@ -43,7 +43,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
for(int i = 0; i < parameterDecls.size(); i++) { for(int i = 0; i < parameterDecls.size(); i++) {
Variable parameterDecl = parameterDecls.get(i); Variable parameterDecl = parameterDecls.get(i);
RValue parameterValue = parameterValues.get(i); RValue parameterValue = parameterValues.get(i);
addStatementToCurrentBlock(new StatementAssignment(parameterDecl.getRef(), parameterValue)); addStatementToCurrentBlock(new StatementAssignment(parameterDecl.getRef(), parameterValue, origCall.getSource()));
} }
String procedureName = origCall.getProcedureName(); String procedureName = origCall.getProcedureName();
Variable procReturnVar = procedure.getVariable("return"); Variable procReturnVar = procedure.getVariable("return");
@ -51,7 +51,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
if(procReturnVar != null) { if(procReturnVar != null) {
procReturnVarRef = procReturnVar.getRef(); procReturnVarRef = procReturnVar.getRef();
} }
StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null); StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null, origCall.getSource());
copyCall.setProcedure(procedureRef); copyCall.setProcedure(procedureRef);
addStatementToCurrentBlock(copyCall); addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef());
@ -64,7 +64,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
} }
splitCurrentBlock(currentBlockScope.addLabelIntermediate().getRef()); splitCurrentBlock(currentBlockScope.addLabelIntermediate().getRef());
if(!SymbolType.VOID.equals(procedure.getReturnType()) && origCall.getlValue() != null) { if(!SymbolType.VOID.equals(procedure.getReturnType()) && origCall.getlValue() != null) {
addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef)); addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef, origCall.getSource()));
} else { } else {
// No return type. Remove variable receiving the result. // No return type. Remove variable receiving the result.
LValue lValue = origCall.getlValue(); LValue lValue = origCall.getlValue();
@ -77,7 +77,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
// Add self-assignments for all variables modified in the procedure // Add self-assignments for all variables modified in the procedure
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef()); Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
for(VariableRef modifiedVar : modifiedVars) { for(VariableRef modifiedVar : modifiedVars) {
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar)); addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, origCall.getSource()));
} }
return null; return null;
} }
@ -90,7 +90,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
// Add self-assignments for all variables modified in the procedure // Add self-assignments for all variables modified in the procedure
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef()); Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
for(VariableRef modifiedVar : modifiedVars) { for(VariableRef modifiedVar : modifiedVars) {
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar)); addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, origReturn.getSource()));
} }
return super.visitReturn(origReturn); return super.visitReturn(origReturn);
} }

View File

@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import org.antlr.v4.runtime.RuleContext;
import java.util.Set; import java.util.Set;
@ -32,7 +33,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
ProcedureRef procedureRef = origCall.getProcedure(); ProcedureRef procedureRef = origCall.getProcedure();
Procedure procedure = program.getScope().getProcedure(procedureRef); Procedure procedure = program.getScope().getProcedure(procedureRef);
String procedureName = origCall.getProcedureName(); String procedureName = origCall.getProcedureName();
StatementCall copyCall = new StatementCall(null, procedureName, null); StatementCall copyCall = new StatementCall(null, procedureName, null, origCall.getSource());
copyCall.setProcedure(procedureRef); copyCall.setProcedure(procedureRef);
addStatementToCurrentBlock(copyCall); addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef());
@ -53,7 +54,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
if(returnVarFinal == null) { if(returnVarFinal == null) {
throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName()); throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName());
} }
StatementAssignment returnAssignment = new StatementAssignment(origCall.getlValue(), returnVarFinal); StatementAssignment returnAssignment = new StatementAssignment(origCall.getlValue(), returnVarFinal, origCall.getSource());
addStatementToCurrentBlock(returnAssignment); addStatementToCurrentBlock(returnAssignment);
} }
@ -102,7 +103,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
@Override @Override
public StatementReturn visitReturn(StatementReturn origReturn) { public StatementReturn visitReturn(StatementReturn origReturn) {
addStatementToCurrentBlock(new StatementReturn(null)); addStatementToCurrentBlock(new StatementReturn(null, origReturn.getSource()));
return null; return null;
} }
} }

View File

@ -85,7 +85,7 @@ public class Pass1ProcedureInline extends Pass1Base {
Variable procReturnVar = procedure.getVariable("return"); Variable procReturnVar = procedure.getVariable("return");
String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial); String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial);
Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName); Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName);
restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef())); restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef(), call.getSource()));
} else { } else {
// Remove the tmp var receiving the result // Remove the tmp var receiving the result
LValue lValue = call.getlValue(); LValue lValue = call.getlValue();
@ -165,10 +165,10 @@ public class Pass1ProcedureInline extends Pass1Base {
Statement inlinedStatement; Statement inlinedStatement;
if(procStatement instanceof StatementAssignment) { if(procStatement instanceof StatementAssignment) {
StatementAssignment procAssignment = (StatementAssignment) procStatement; StatementAssignment procAssignment = (StatementAssignment) procStatement;
inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2()); inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2(), procAssignment.getSource());
} else if(procStatement instanceof StatementCall) { } else if(procStatement instanceof StatementCall) {
StatementCall procCall = (StatementCall) procStatement; StatementCall procCall = (StatementCall) procStatement;
StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters())); StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters()), procCall.getSource());
inlinedCall.setProcedure(procCall.getProcedure()); inlinedCall.setProcedure(procCall.getProcedure());
inlinedStatement = inlinedCall; inlinedStatement = inlinedCall;
} else if(procStatement instanceof StatementConditionalJump) { } else if(procStatement instanceof StatementConditionalJump) {
@ -180,12 +180,12 @@ public class Pass1ProcedureInline extends Pass1Base {
String inlineSymbolName = getInlineSymbolName(procedure, procDestination, serial); String inlineSymbolName = getInlineSymbolName(procedure, procDestination, serial);
inlinedDest = callScope.getLabel(inlineSymbolName); inlinedDest = callScope.getLabel(inlineSymbolName);
} }
inlinedStatement = new StatementConditionalJump(procConditional.getrValue1(), procConditional.getOperator(), procConditional.getrValue2(), inlinedDest.getRef()); inlinedStatement = new StatementConditionalJump(procConditional.getrValue1(), procConditional.getOperator(), procConditional.getrValue2(), inlinedDest.getRef(), procConditional.getSource());
} else if(procStatement instanceof StatementReturn) { } else if(procStatement instanceof StatementReturn) {
// No statement needed // No statement needed
return null; return null;
} else { } else {
throw new CompileError("Statement type of Inline function not handled " + procStatement); throw new CompileError("Statement type of Inline function not handled " + procStatement, procStatement.getSource());
} }
if(inlinedStatement!=null) { if(inlinedStatement!=null) {
ValueReplacer.executeAll(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null); ValueReplacer.executeAll(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
@ -252,7 +252,7 @@ public class Pass1ProcedureInline extends Pass1Base {
String inlineParameterVarName = getInlineSymbolName(procedure, parameterDecl, serial); String inlineParameterVarName = getInlineSymbolName(procedure, parameterDecl, serial);
Variable inlineParameterVar = callScope.getVariable(inlineParameterVarName); Variable inlineParameterVar = callScope.getVariable(inlineParameterVarName);
RValue parameterValue = parameterValues.get(i); RValue parameterValue = parameterValues.get(i);
statementsIt.add(new StatementAssignment(inlineParameterVar.getRef(), parameterValue)); statementsIt.add(new StatementAssignment(inlineParameterVar.getRef(), parameterValue, call.getSource()));
} }
} }

View File

@ -27,7 +27,7 @@ public class Pass1ResolveForwardReferences extends Pass1Base {
replaceable.set(variable.getRef()); replaceable.set(variable.getRef());
} else { } else {
getLog().append("ERROR! Unknown variable " + varName); getLog().append("ERROR! Unknown variable " + varName);
throw new CompileError("ERROR! Unknown variable " + varName); throw new CompileError("ERROR! Unknown variable " + varName, currentStmt.getSource());
} }
} }
}); });

View File

@ -33,11 +33,11 @@ public class Pass1TypeInference extends Pass1Base {
Scope currentScope = getScope().getScope(block.getScope()); Scope currentScope = getScope().getScope(block.getScope());
Procedure procedure = currentScope.getProcedure(procedureName); Procedure procedure = currentScope.getProcedure(procedureName);
if(procedure == null) { if(procedure == null) {
throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false)); throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource());
} }
call.setProcedure(procedure.getRef()); call.setProcedure(procedure.getRef());
if(procedure.getParameters().size() != call.getParameters().size()) { if(procedure.getParameters().size() != call.getParameters().size()) {
throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString()); throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString(), statement.getSource());
} }
SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false); SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false);
} }

View File

@ -24,12 +24,12 @@ public class Pass2AssertRValues extends Pass2SsaAssertion {
ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> { ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> {
RValue rValue = replaceable.get(); RValue rValue = replaceable.get();
if(rValue instanceof ForwardVariableRef) { if(rValue instanceof ForwardVariableRef) {
throw new CompileError("No forward references allowed "+currentStmt.toString(getProgram(), false)); throw new CompileError("No forward references allowed "+currentStmt.toString(getProgram(), false), currentStmt.getSource());
} }
if(rValue instanceof VariableRef) { if(rValue instanceof VariableRef) {
VariableRef variableRef = (VariableRef) rValue; VariableRef variableRef = (VariableRef) rValue;
if(!variableRef.isIntermediate() && !variableRef.isVersion()) { if(!variableRef.isIntermediate() && !variableRef.isVersion()) {
throw new CompileError("No unversioned variable references allowed "+currentStmt.toString(getProgram(), false)); throw new CompileError("No unversioned variable references allowed "+currentStmt.toString(getProgram(), false), currentStmt.getSource());
} }
} }
}); });

View File

@ -41,7 +41,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
} }
// Types do not match // Types do not match
getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false)); throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
} }
} }

View File

@ -91,7 +91,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
Label newBlockLabel = currentScope.addLabelIntermediate(); Label newBlockLabel = currentScope.addLabelIntermediate();
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
getGraph().addBlock(newBlock); getGraph().addBlock(newBlock);
newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination())); newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource()));
newBlock.setDefaultSuccessor(block.getDefaultSuccessor()); newBlock.setDefaultSuccessor(block.getDefaultSuccessor());
newBlock.setConditionalSuccessor(conditional.getDestination()); newBlock.setConditionalSuccessor(conditional.getDestination());
// Rewrite the conditional to use only the first part of the && condition expression // Rewrite the conditional to use only the first part of the && condition expression
@ -114,7 +114,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
Label newBlockLabel = currentScope.addLabelIntermediate(); Label newBlockLabel = currentScope.addLabelIntermediate();
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
getGraph().addBlock(newBlock); getGraph().addBlock(newBlock);
newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination())); newBlock.getStatements().add(new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource()));
newBlock.setConditionalSuccessor(conditional.getDestination()); newBlock.setConditionalSuccessor(conditional.getDestination());
newBlock.setDefaultSuccessor(block.getDefaultSuccessor()); newBlock.setDefaultSuccessor(block.getDefaultSuccessor());
// Rewrite the conditional to use only the first part of the && condition expression // Rewrite the conditional to use only the first part of the && condition expression

View File

@ -109,7 +109,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
// Move backward - to insert before the current statement // Move backward - to insert before the current statement
stmtIt.previous(); stmtIt.previous();
// Add assignment of the new tmpVar // Add assignment of the new tmpVar
StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), constructOperator, list.getList().get(1)); StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), constructOperator, list.getList().get(1), currentStmt.getSource());
stmtIt.add(assignment); stmtIt.add(assignment);
// Move back before the current statement // Move back before the current statement
stmtIt.next(); stmtIt.next();

View File

@ -23,13 +23,13 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion {
if(statement instanceof StatementAssignment) { if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement; StatementAssignment assignment = (StatementAssignment) statement;
if(Operators.MULTIPLY.equals(assignment.getOperator())) { if(Operators.MULTIPLY.equals(assignment.getOperator())) {
throw new CompileError("ERROR! Runtime multiplication not supported. "+statement.toString(getProgram(), false)); throw new CompileError("ERROR! Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
} }
if(Operators.DIVIDE.equals(assignment.getOperator())) { if(Operators.DIVIDE.equals(assignment.getOperator())) {
throw new CompileError("ERROR! Runtime division not supported. "+statement.toString(getProgram(), false)); throw new CompileError("ERROR! Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
} }
if(Operators.MODULO.equals(assignment.getOperator())) { if(Operators.MODULO.equals(assignment.getOperator())) {
throw new CompileError("ERROR! Runtime modulo not supported. "+statement.toString(getProgram(), false)); throw new CompileError("ERROR! Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
} }
} }

View File

@ -23,6 +23,7 @@ public class Pass3AssertNoValueLists extends Pass2SsaAssertion {
"Error! Value list not resolved to word constructor or array initializer" + "Error! Value list not resolved to word constructor or array initializer" +
"\n value list: " + value.toString(getProgram()) + "\n value list: " + value.toString(getProgram()) +
"\n statement: " + currentStmt.toString(getProgram(), false) "\n statement: " + currentStmt.toString(getProgram(), false)
, currentStmt.getSource()
); );
} }
}); });

View File

@ -61,7 +61,7 @@ public class Pass3PhiLifting {
if(predecessorStatements.size() > 0) { if(predecessorStatements.size() > 0) {
lastPredecessorStatement = predecessorStatements.get(predecessorStatements.size() - 1); lastPredecessorStatement = predecessorStatements.get(predecessorStatements.size() - 1);
} }
StatementAssignment newAssignment = new StatementAssignment(newVar, phiRValue.getrValue()); StatementAssignment newAssignment = new StatementAssignment(newVar.getRef(), phiRValue.getrValue(), phiBlock.getSource());
if(lastPredecessorStatement instanceof StatementConditionalJump) { if(lastPredecessorStatement instanceof StatementConditionalJump) {
// Use or Create a new block between the predecessor and this one - getReplacement labels where appropriate // Use or Create a new block between the predecessor and this one - getReplacement labels where appropriate
ControlFlowBlock newBlock; ControlFlowBlock newBlock;