diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 6dedd5217..e04ee5647 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -2,6 +2,7 @@ package dk.camelot64.kickc; import dk.camelot64.kickc.model.*; 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.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCParser; @@ -88,7 +89,7 @@ public class Compiler { Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(program); loadAndParseFile(fileName, program, pass0GenerateStatementSequence); 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); pass1GenerateSSA(); diff --git a/src/main/java/dk/camelot64/kickc/model/CompileError.java b/src/main/java/dk/camelot64/kickc/model/CompileError.java index e75d69538..384c03ddf 100644 --- a/src/main/java/dk/camelot64/kickc/model/CompileError.java +++ b/src/main/java/dk/camelot64/kickc/model/CompileError.java @@ -1,5 +1,8 @@ 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) */ public class CompileError extends RuntimeException { @@ -7,6 +10,14 @@ public class CompileError extends RuntimeException { 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) { super(message, cause); } diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java index a5a157de2..1cd892f89 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java @@ -142,7 +142,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor parameters = origCall.getParameters(); - return new StatementCall(lValue, procedureName, parameters); + return new StatementCall(lValue, procedureName, parameters, origCall.getSource()); } @Override public StatementProcedureBegin visitProcedureBegin(StatementProcedureBegin origProcedureBegin) { - return new StatementProcedureBegin(origProcedureBegin.getProcedure()); + return new StatementProcedureBegin(origProcedureBegin.getProcedure(), origProcedureBegin.getSource()); } @Override public StatementProcedureEnd visitProcedureEnd(StatementProcedureEnd origProcedureEnd) { - return new StatementProcedureEnd(origProcedureEnd.getProcedure()); + return new StatementProcedureEnd(origProcedureEnd.getProcedure(), origProcedureEnd.getSource()); } @Override public StatementReturn visitReturn(StatementReturn origReturn) { - return new StatementReturn(origReturn.getValue()); + return new StatementReturn(origReturn.getValue(), origReturn.getSource()); } @Override public Object visitAsm(StatementAsm asm) { - return new StatementAsm(asm.getAsmLines()); + return new StatementAsm(asm.getAsmLines(), asm.getSource()); } } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/Statement.java b/src/main/java/dk/camelot64/kickc/model/statements/Statement.java index 4e690061d..6c1f74c79 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/Statement.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/Statement.java @@ -16,4 +16,10 @@ public interface Statement { /** Set the index of the statement. Indexes are used during live range analysis. */ void setIndex(Integer idx); + + /** + * Get the source for the statement* + */ + StatementSource getSource(); + } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java index 887fb2678..6ff0d9d64 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java @@ -9,8 +9,9 @@ public class StatementAsm extends StatementBase { /** ASM Fragment code. */ private KickCParser.AsmLinesContext asmLines; - public StatementAsm(KickCParser.AsmLinesContext asmLines) { - super(null); + public StatementAsm(KickCParser.AsmLinesContext asmLines, + StatementSource source) { + super(null, source); this.asmLines = asmLines; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java index 6b0f1ced4..cd9e16fbc 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java @@ -22,24 +22,16 @@ public class StatementAssignment extends StatementBase implements StatementLValu private Operator operator; private RValue rValue2; - public StatementAssignment(LValue lValue, RValue rValue2) { - this(lValue, null, null, rValue2, null); + public StatementAssignment(LValue lValue, RValue rValue2, StatementSource source) { + this(lValue, null, null, rValue2, null, source); } - public StatementAssignment(LValue lValue, Operator operator, RValue rValue2) { - this(lValue, null, operator, rValue2, null); + public StatementAssignment(LValue lValue, Operator operator, RValue rValue2,StatementSource source) { + this(lValue, null, operator, rValue2, null, source); } - public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) { - this(lValue, rValue1, operator, rValue2, null); - } - - public StatementAssignment(Variable lValue, Variable rValue2) { - this(lValue.getRef(), rValue2.getRef()); - } - - public StatementAssignment(Variable lValue, RValue rValue2) { - this(lValue.getRef(), rValue2); + public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2, StatementSource source) { + this(lValue, rValue1, operator, rValue2, null, source); } public StatementAssignment( @@ -47,8 +39,9 @@ public class StatementAssignment extends StatementBase implements StatementLValu RValue rValue1, Operator operator, RValue rValue2, - Integer index) { - super(index); + Integer index, + StatementSource source) { + super(index, source); this.lValue = lValue; this.rValue1 = rValue1; this.operator = operator; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java index 333e75255..cc88eeb9c 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java @@ -12,10 +12,18 @@ import java.util.List; /** Statement base class implementing shared properties and logic */ public abstract class StatementBase implements Statement { + private StatementSource source; + private Integer index; - public StatementBase(Integer index) { + public StatementBase(Integer index, StatementSource source) { this.index = index; + this.source = source; + } + + @Override + public StatementSource getSource() { + return source; } @Override diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java index 180e587ba..dfb86f6c3 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java @@ -22,8 +22,8 @@ public class StatementCall extends StatementBase implements StatementLValue { private ProcedureRef procedure; private List parameters; - public StatementCall(LValue lValue, String procedureName, List parameters) { - super(null); + public StatementCall(LValue lValue, String procedureName, List parameters, StatementSource source) { + super(null, source); this.lValue = lValue; this.procedureName = procedureName; this.parameters = parameters; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java index f92f00214..702ace68e 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java @@ -20,8 +20,8 @@ public class StatementConditionalJump extends StatementBase { private RValue rValue2; private LabelRef destination; - public StatementConditionalJump(RValue condition, LabelRef destination) { - super(null); + public StatementConditionalJump(RValue condition, LabelRef destination,StatementSource source) { + super(null, source); this.rValue1 = null; this.operator = null; this.rValue2 = condition; @@ -32,8 +32,9 @@ public class StatementConditionalJump extends StatementBase { RValue rValue1, Operator operator, RValue rValue2, - LabelRef destination) { - this(rValue1, operator, rValue2, destination, null); + LabelRef destination, + StatementSource source) { + this(rValue1, operator, rValue2, destination, null, source); } public StatementConditionalJump( @@ -41,8 +42,9 @@ public class StatementConditionalJump extends StatementBase { Operator operator, RValue rValue2, LabelRef destination, - Integer index) { - super(index); + Integer index, + StatementSource source) { + super(index, source); this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java index 264e3c3ba..e24a7ca8c 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java @@ -13,8 +13,9 @@ public class StatementJump extends StatementBase { private LabelRef destination; - public StatementJump(LabelRef destination) { - super(null); + public StatementJump(LabelRef destination, + StatementSource source) { + super(null, source); this.destination = destination; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java index b7d15172c..b8731553e 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java @@ -10,8 +10,9 @@ public class StatementLabel extends StatementBase { private LabelRef label; - public StatementLabel(LabelRef label) { - super(null); + public StatementLabel(LabelRef label, + StatementSource source) { + super(null, source); this.label = label; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java index ced6b81e6..d39b3d19f 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java @@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.VariableRef; +import org.antlr.v4.runtime.RuleContext; import java.util.ArrayList; import java.util.Collections; @@ -22,13 +23,14 @@ public class StatementPhiBlock extends StatementBase { public StatementPhiBlock( List phiVariables, - Integer index) { - super(index); + Integer index, + StatementSource source) { + super(index, source); this.phiVariables = phiVariables; } public StatementPhiBlock() { - super(null); + super(null, new StatementSource(RuleContext.EMPTY)); this.phiVariables = new ArrayList<>(); } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java index 13d8da6ca..f085e5f33 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java @@ -10,8 +10,8 @@ public class StatementProcedureBegin extends StatementBase { private Strategy strategy; - public StatementProcedureBegin(ProcedureRef procedure) { - super(null); + public StatementProcedureBegin(ProcedureRef procedure,StatementSource source) { + super(null, source); this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java index 7b1ecbe7f..b62ae1e29 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java @@ -10,8 +10,8 @@ public class StatementProcedureEnd extends StatementBase { private ProcedureRef procedure; - public StatementProcedureEnd(ProcedureRef procedure) { - super(null); + public StatementProcedureEnd(ProcedureRef procedure, StatementSource source) { + super(null, source); this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java index b76addc16..2c72d1d12 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java @@ -13,8 +13,8 @@ public class StatementReturn extends StatementBase { */ private RValue value; - public StatementReturn(RValue value) { - super(null); + public StatementReturn(RValue value, StatementSource source) { + super(null, source); this.value = value; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementSource.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementSource.java new file mode 100644 index 000000000..c4fd04b6e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementSource.java @@ -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; + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index bb5ffdec6..4bf162671 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -102,21 +102,21 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { parameterList = (List) this.visit(ctx.parameterListDecl()); } procedure.setParameters(parameterList); - sequence.addStatement(new StatementProcedureBegin(procedure.getRef())); + sequence.addStatement(new StatementProcedureBegin(procedure.getRef(), new StatementSource(ctx))); if(ctx.stmtSeq() != null) { this.visit(ctx.stmtSeq()); } - sequence.addStatement(new StatementLabel(procExit.getRef())); + sequence.addStatement(new StatementLabel(procExit.getRef(), new StatementSource(ctx))); if(returnVar != null) { - sequence.addStatement(new StatementAssignment(returnVar, returnVar)); + sequence.addStatement(new StatementAssignment(returnVar.getRef(), returnVar.getRef(), new StatementSource(ctx))); } VariableRef returnVarRef = null; if(returnVar != null) { returnVarRef = returnVar.getRef(); } - sequence.addStatement(new StatementReturn(returnVarRef)); + sequence.addStatement(new StatementReturn(returnVarRef, new StatementSource(ctx))); scopeStack.pop(); - sequence.addStatement(new StatementProcedureEnd(procedure.getRef())); + sequence.addStatement(new StatementProcedureEnd(procedure.getRef(), new StatementSource(ctx))); return null; } @@ -158,9 +158,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { SymbolTypeArray typeArray = (SymbolTypeArray) type; Integer size = typeArray.getSize(); 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); } return null; @@ -181,23 +181,24 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { directives.add((Directive) this.visit(directiveContext)); } for(Directive directive : directives) { + StatementSource source = new StatementSource(directivesCtx.get(0)); if(directive instanceof DirectiveConst) { lValue.setDeclaredConstant(true); } else if(directive instanceof DirectiveAlign) { if(type instanceof SymbolTypeArray || type.equals(SymbolType.STRING)) { lValue.setDeclaredAlignment(((DirectiveAlign) directive).getAlignment()); } 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) { DirectiveRegister directiveRegister = (DirectiveRegister) directive; Registers.Register register = Registers.getRegister(directiveRegister.getName()); if(register == null) { - throw new CompileError("Error! Unknown register " + directiveRegister.getName()); + throw new CompileError("Error! Unknown register " + directiveRegister.getName(), source); } lValue.setDeclaredRegister(register); } 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 { directives.add((Directive) this.visit(directiveContext)); } for(Directive directive : directives) { + StatementSource source = new StatementSource(directivesCtx.get(0)); if(directive instanceof DirectiveInline) { procedure.setDeclaredInline(true); } 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 { if(elseStmt==null) { // If without else - skip the entire section if condition not met 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()); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); - sequence.addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef())); + sequence.addStatement(new StatementConditionalJump(notExprVar, endJumpLabel.getRef(), new StatementSource(ctx))); this.visit(ifStmt); // No else statement - just add the label - sequence.addStatement(new StatementLabel(endJumpLabel.getRef())); + sequence.addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx))); } else { // If with else - jump to if section if condition met - fall into else otherwise. PrePostModifierHandler.addPostModifiers(this, ctx.expr()); Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate(); - sequence.addStatement(new StatementConditionalJump(rValue, ifJumpLabel.getRef())); + sequence.addStatement(new StatementConditionalJump(rValue, ifJumpLabel.getRef(), new StatementSource(ctx))); // Add else body this.visit(elseStmt); // There is an else statement - add the if part and any needed labels/jumps Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); - sequence.addStatement(new StatementJump(endJumpLabel.getRef())); - sequence.addStatement(new StatementLabel(ifJumpLabel.getRef())); + sequence.addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx))); + sequence.addStatement(new StatementLabel(ifJumpLabel.getRef(), new StatementSource(ctx))); this.visit(ifStmt); - StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(endJumpTarget); } return null; @@ -310,21 +312,21 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label doJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(beginJumpTarget); PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(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); - Statement endJmpStmt = new StatementJump(endJumpLabel.getRef()); + Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(endJmpStmt); - StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef()); + StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(doJumpTarget); this.visit(ctx.stmt()); - Statement beginJmpStmt = new StatementJump(beginJumpLabel.getRef()); + Statement beginJmpStmt = new StatementJump(beginJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(beginJmpStmt); - StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(endJumpTarget); return null; } @@ -332,7 +334,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(beginJumpTarget); if(ctx.stmt() != null) { this.visit(ctx.stmt()); @@ -340,7 +342,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(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); return null; } @@ -379,7 +381,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { } // Add label Label repeatLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef()); + StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(repeatTarget); // Add body if(stmtForCtx.stmt() != null) { @@ -396,7 +398,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { RValue rValue = (RValue) this.visit(ctx.expr(0)); PrePostModifierHandler.addPostModifiers(this, ctx.expr(0)); // 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); return null; } @@ -417,7 +419,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { lValue = getCurrentSymbols().getVariable(varName); } 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 rangeLastCtx = ctx.expr(1); @@ -426,11 +428,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { ConstantInteger rangeLast = (ConstantInteger) ParseTreeConstantEvaluator.evaluate(rangeLastCtx); // Assign loop variable with first value RValue rValue = (RValue) visit(rangeFirstCtx); - Statement stmtInit = new StatementAssignment(lValue, rValue); + Statement stmtInit = new StatementAssignment(lValue.getRef(), rValue, new StatementSource(ctx)); sequence.addStatement(stmtInit); // Add label Label repeatLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef()); + StatementLabel repeatTarget = new StatementLabel(repeatLabel.getRef(), new StatementSource(ctx)); sequence.addStatement(repeatTarget); // Add body if(stmtForCtx.stmt() != null) { @@ -439,7 +441,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { // Add increment ConstantInteger beyondLastVal; 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); if(rangeLast.getValue() == 0) { beyondLastVal = new ConstantInteger(255L); @@ -447,7 +449,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { beyondLastVal = new ConstantInteger(rangeLast.getValue() - 1); } } 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); if(rangeLast.getValue() == 255) { beyondLastVal = new ConstantInteger(0L); @@ -459,17 +461,17 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { // Add condition i { PrePostModifierHandler.addPreModifiers(this, exprCtx); rValue = (RValue) this.visit(exprCtx); 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); } 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; } private void addInitialAssignment(KickCParser.ExprContext initializer, Variable lValue) { PrePostModifierHandler.addPreModifiers(this, 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); PrePostModifierHandler.addPostModifiers(this, initializer); } @@ -547,7 +549,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { lValue = new LvalueIntermediate((VariableRef) lValue); } 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); return lValue; } @@ -565,7 +567,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); Operator operator = Operators.getBinaryCompound(op); // 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); return lValue; } @@ -577,7 +579,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { Operator operator = Operators.getCastUnary(castType); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableRef tmpVarRef = tmpVar.getRef(); - Statement stmt = new StatementAssignment(tmpVarRef, operator, child); + Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx)); sequence.addStatement(stmt); return tmpVarRef; } @@ -593,7 +595,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { } VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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; } @@ -649,7 +651,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { Operator operator = Operators.getBinary(op); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); 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); return tmpVarRef; } @@ -667,7 +669,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { Operator operator = Operators.getUnary(op); VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); VariableRef tmpVarRef = tmpVar.getRef(); - Statement stmt = new StatementAssignment(tmpVarRef, operator, child); + Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx)); sequence.addStatement(stmt); return tmpVarRef; } @@ -763,21 +765,22 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler prePostModifierHandler = new PrePostModifierHandler(parser); prePostModifierHandler.visit(ctx); List modifiers = prePostModifierHandler.getPostMods(); - addModifierStatements(parser, modifiers); + addModifierStatements(parser, modifiers, new StatementSource(ctx)); } public static void addPreModifiers(Pass0GenerateStatementSequence parser, ParserRuleContext ctx) { PrePostModifierHandler modifierHandler = new PrePostModifierHandler(parser); modifierHandler.visit(ctx); List modifiers = modifierHandler.getPreMods(); - addModifierStatements(parser, modifiers); + addModifierStatements(parser, modifiers, new StatementSource(ctx)); } private static void addModifierStatements( Pass0GenerateStatementSequence parser, - List modifiers) { + List modifiers, + StatementSource source) { 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.program.getLog().append("Adding pre/post-modifier " + stmt.toString(parser.program, true)); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java index 18e3807dd..e8ab0d569 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java @@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.*; 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.statements.Statement; 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() + "). " + "In " + assignment.toString(getProgram(), false); getProgram().getLog().append(msg); - throw new CompileError(msg); + throw new CompileError(msg, assignment.getSource()); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertArrayLengths.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertArrayLengths.java index 384881307..dee963f9b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertArrayLengths.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertArrayLengths.java @@ -32,11 +32,11 @@ public class Pass1AssertArrayLengths extends Pass1Base { RValue value = assignment.getrValue2(); if(value instanceof ValueList) { 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) { 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()); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java index 7a01b3edc..bd03225ea 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertNoLValueIntermediate.java @@ -26,7 +26,7 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base { if(lValue instanceof LvalueIntermediate) { VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable(); 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()); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java index 6ad2ca988..459a36ad0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java @@ -55,7 +55,7 @@ public class Pass1AssertUsedVars extends Pass1Base { Collection used = referenceInfos.getUsedVars(statement); for(VariableRef usedRef : used) { 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 defd = referenceInfos.getDefinedVars(statement); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java index 688ade2f8..3ac6ade93 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java @@ -69,7 +69,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base { statementLValue.setlValue(tmpVarRef); SymbolTypeInference.inferLValue(getProgram(), statementLValue, false); // 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); getLog().append("Fixing lo/hi-lvalue with new tmpVar " + tmpVarRef + " " + statementLValue.toString()); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java index b2aa21906..f975e13f4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java @@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.model.values.SymbolRef; +import org.antlr.v4.runtime.RuleContext; import java.util.ArrayList; 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); Stack blockStack = new Stack<>(); 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()) { ControlFlowBlock currentBlock = blockStack.peek(); Symbol currentBlockLabel = scope.getSymbol(currentBlock.getLabel()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index 8ea41237f..388f68edd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -58,7 +58,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { if(assignedSymbol.isDeclaredConstant()) { Collection versions = assignedVar.getScope().getVersions(assignedSymbol); 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.setDeclaredConstant(true); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java index bd364388d..046aa29cf 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java @@ -43,7 +43,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { for(int i = 0; i < parameterDecls.size(); i++) { Variable parameterDecl = parameterDecls.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(); Variable procReturnVar = procedure.getVariable("return"); @@ -51,7 +51,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { if(procReturnVar != null) { procReturnVarRef = procReturnVar.getRef(); } - StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null); + StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null, origCall.getSource()); copyCall.setProcedure(procedureRef); addStatementToCurrentBlock(copyCall); getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); @@ -64,7 +64,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { } splitCurrentBlock(currentBlockScope.addLabelIntermediate().getRef()); if(!SymbolType.VOID.equals(procedure.getReturnType()) && origCall.getlValue() != null) { - addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef)); + addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef, origCall.getSource())); } else { // No return type. Remove variable receiving the result. LValue lValue = origCall.getlValue(); @@ -77,7 +77,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { // Add self-assignments for all variables modified in the procedure Set modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef()); for(VariableRef modifiedVar : modifiedVars) { - addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar)); + addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, origCall.getSource())); } return null; } @@ -90,7 +90,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { // Add self-assignments for all variables modified in the procedure Set modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef()); for(VariableRef modifiedVar : modifiedVars) { - addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar)); + addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar, origReturn.getSource())); } return super.visitReturn(origReturn); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java index 3ce4b7a6e..adb4a92c7 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.types.SymbolType; +import org.antlr.v4.runtime.RuleContext; import java.util.Set; @@ -32,7 +33,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor ProcedureRef procedureRef = origCall.getProcedure(); Procedure procedure = program.getScope().getProcedure(procedureRef); String procedureName = origCall.getProcedureName(); - StatementCall copyCall = new StatementCall(null, procedureName, null); + StatementCall copyCall = new StatementCall(null, procedureName, null, origCall.getSource()); copyCall.setProcedure(procedureRef); addStatementToCurrentBlock(copyCall); getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); @@ -53,7 +54,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor if(returnVarFinal == null) { 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); } @@ -102,7 +103,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor @Override public StatementReturn visitReturn(StatementReturn origReturn) { - addStatementToCurrentBlock(new StatementReturn(null)); + addStatementToCurrentBlock(new StatementReturn(null, origReturn.getSource())); return null; } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java index 4065f1dd9..4b5e1c7d4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureInline.java @@ -85,7 +85,7 @@ public class Pass1ProcedureInline extends Pass1Base { Variable procReturnVar = procedure.getVariable("return"); String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial); Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName); - restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef())); + restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef(), call.getSource())); } else { // Remove the tmp var receiving the result LValue lValue = call.getlValue(); @@ -165,10 +165,10 @@ public class Pass1ProcedureInline extends Pass1Base { Statement inlinedStatement; if(procStatement instanceof StatementAssignment) { 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) { 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()); inlinedStatement = inlinedCall; } else if(procStatement instanceof StatementConditionalJump) { @@ -180,12 +180,12 @@ public class Pass1ProcedureInline extends Pass1Base { String inlineSymbolName = getInlineSymbolName(procedure, procDestination, serial); 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) { // No statement needed return null; } 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) { 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); Variable inlineParameterVar = callScope.getVariable(inlineParameterVarName); RValue parameterValue = parameterValues.get(i); - statementsIt.add(new StatementAssignment(inlineParameterVar.getRef(), parameterValue)); + statementsIt.add(new StatementAssignment(inlineParameterVar.getRef(), parameterValue, call.getSource())); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ResolveForwardReferences.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ResolveForwardReferences.java index aae526b55..17a8e425a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ResolveForwardReferences.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ResolveForwardReferences.java @@ -27,7 +27,7 @@ public class Pass1ResolveForwardReferences extends Pass1Base { replaceable.set(variable.getRef()); } else { getLog().append("ERROR! Unknown variable " + varName); - throw new CompileError("ERROR! Unknown variable " + varName); + throw new CompileError("ERROR! Unknown variable " + varName, currentStmt.getSource()); } } }); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java index aa7526c0b..56c8bfd6e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java @@ -33,11 +33,11 @@ public class Pass1TypeInference extends Pass1Base { Scope currentScope = getScope().getScope(block.getScope()); Procedure procedure = currentScope.getProcedure(procedureName); 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()); 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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertRValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertRValues.java index c234d72b7..aff9a535e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertRValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertRValues.java @@ -24,12 +24,12 @@ public class Pass2AssertRValues extends Pass2SsaAssertion { ValueReplacer.executeAll(getGraph(), (replaceable, currentStmt, stmtIt, currentBlock) -> { RValue rValue = replaceable.get(); 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) { VariableRef variableRef = (VariableRef) rValue; 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()); } } }); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java index 2e606e744..043814a85 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java @@ -41,7 +41,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion { } // Types do not match 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()); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java index 46d20ae81..5e54d5195 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalAndOrRewriting.java @@ -91,7 +91,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization { Label newBlockLabel = currentScope.addLabelIntermediate(); ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); 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.setConditionalSuccessor(conditional.getDestination()); // 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(); ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef); 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.setDefaultSuccessor(block.getDefaultSuccessor()); // Rewrite the conditional to use only the first part of the && condition expression diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java index 2bf996354..47c086009 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java @@ -109,7 +109,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization { // Move backward - to insert before the current statement stmtIt.previous(); // 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); // Move back before the current statement stmtIt.next(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoMulDivMod.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoMulDivMod.java index f45b2d330..23645cf7a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoMulDivMod.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoMulDivMod.java @@ -23,13 +23,13 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion { if(statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; 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())) { - 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())) { - 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()); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoValueLists.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoValueLists.java index e6cd3552e..0a0eb66e3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoValueLists.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoValueLists.java @@ -23,6 +23,7 @@ public class Pass3AssertNoValueLists extends Pass2SsaAssertion { "Error! Value list not resolved to word constructor or array initializer" + "\n value list: " + value.toString(getProgram()) + "\n statement: " + currentStmt.toString(getProgram(), false) + , currentStmt.getSource() ); } }); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java index 96d7da596..708533423 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java @@ -61,7 +61,7 @@ public class Pass3PhiLifting { if(predecessorStatements.size() > 0) { 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) { // Use or Create a new block between the predecessor and this one - getReplacement labels where appropriate ControlFlowBlock newBlock;