From: Hannu Niemistö Date: Thu, 8 Mar 2018 06:18:56 +0000 (+0200) Subject: SCL compiler generates line numbers to bytecode X-Git-Tag: v1.43.0~136^2~556 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=91682baa9a8252390f09b80fd724f47e5957b234;p=simantics%2Fplatform.git SCL compiler generates line numbers to bytecode refs #6922 Change-Id: I2219d6dc74ae815cdea7d3f6daf3a736be5f1781 --- diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java index 68c584708..082fa2f6d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java @@ -108,7 +108,7 @@ public class CodeGeneration { } public void convertToSSA() { - ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName()); + ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName(), compilationContext.lineLocator); for(SCLValue value : module.getValues()) { //System.out.println(value.getName().name + " :: " + value.getType()); Expression expression = value.getExpression(); @@ -172,7 +172,7 @@ public class CodeGeneration { IVal[] parameterVals = w.getParameters(); for(int i=0;i>i)&1)==1) parameters.add(expressions[i].toVal(context, w)); - w.jump(bodyContinuation, w.apply(location, + w.jump(location, bodyContinuation, w.apply(location, constraint.fetchFromIndex(context, boundMask), parameters.toArray(new IVal[parameters.size()]))); - body.branchAwayIf(body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), + body.branchAwayIf(location, body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), end.getContinuation()); IVal id = body.apply(location, constraint.accessId, fact); for(PartnerFact partnerFact : planContext.partnerFacts) if(partnerFact.active && !passive) { - body.branchAwayUnless(body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id), + body.branchAwayUnless(location, body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id), nextFact.getContinuation()); } else if(partnerFact.constraint == constraint) { - body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id), + body.branchAwayIf(location, body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id), nextFact.getContinuation()); } @@ -82,8 +82,8 @@ public class IterateConstraintOp extends PlanOp { planContext.partnerFacts.add(new PartnerFact(false, id, constraint, fact, constraint.mayBeRemoved(), killAfterMatch, nextElement, bodyContinuation, end.getContinuation())); planContext.nextOp(body); if(body.isUnfinished()) - body.jump(nextFact.getContinuation()); - nextFact.jump(bodyContinuation, nextFact.apply(location, nextElement, fact)); + body.jump(location, nextFact.getContinuation()); + nextFact.jump(location, bodyContinuation, nextFact.apply(location, nextElement, fact)); w.continueAs(end); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/MatchOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/MatchOp.java index cde566949..4a99ac0d9 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/MatchOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/MatchOp.java @@ -35,11 +35,11 @@ public class MatchOp extends PlanOp { ArrayList rows = new ArrayList(1); rows.add(new Row2(new Expression[] {pattern}, body.getContinuation())); - PatternMatchingCompiler2.split(w, context, scrutineeVals, end.getContinuation(), rows); + PatternMatchingCompiler2.split(location, w, context, scrutineeVals, end.getContinuation(), rows); planContext.nextOp(body); if(body.isUnfinished()) - body.jump(end.getContinuation()); + body.jump(location, end.getContinuation()); w.continueAs(end); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java index 2a03c8943..62bcfc958 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java @@ -54,15 +54,15 @@ public abstract class PlanContext { ICont bodyContinuation = body.getContinuation(); CodeWriter end = w.createBlock(); - w.jump(body.getContinuation(), IntegerConstant.ZERO); + w.jump(location, body.getContinuation(), IntegerConstant.ZERO); IVal index = body.getParameters()[0]; - body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, index, listLength), + body.branchAwayIf(location, body.apply(location, JavaComparisonOperation.IEQUAL, index, listLength), end.getContinuation()); variable.setVal(body.apply(location, ListElement.INSTANCE.createSpecialization(componentType), listValue, index)); nextOp(body); if(body.isUnfinished()) - body.jump(bodyContinuation, body.apply(location, IncreaseByOne.INSTANCE, index)); + body.jump(location, bodyContinuation, body.apply(location, IncreaseByOne.INSTANCE, index)); w.continueAs(end); } @@ -72,7 +72,7 @@ public abstract class PlanContext { CodeWriter end = w.createBlock(); CodeWriter body = w.createBlock(componentType); - w.switch_(maybeValue, new Branch[] { + w.switch_(location, maybeValue, new Branch[] { new Branch(JustConstant.INSTANCE, body.getContinuation()), new Branch(null, end.getContinuation()) }); @@ -80,17 +80,17 @@ public abstract class PlanContext { variable.setVal(body.getParameters()[0]); nextOp(body); if(body.isUnfinished()) - body.jump(end.getContinuation()); + body.jump(location, end.getContinuation()); w.continueAs(end); } public void check(long location, CodeWriter w, IVal booleanValue) { CodeWriter end = w.createBlock(); - w.branchAwayUnless(booleanValue, end.getContinuation()); + w.branchAwayUnless(location, booleanValue, end.getContinuation()); nextOp(w); if(w.isUnfinished()) - w.jump(end.getContinuation()); + w.jump(location, end.getContinuation()); w.continueAs(end); } @@ -105,16 +105,16 @@ public abstract class PlanContext { CodeWriter end = w.createBlock(); CodeWriter body = w.createBlock(componentType); - w.switch_(maybeValue, new Branch[] { + w.switch_(location, maybeValue, new Branch[] { new Branch(JustConstant.INSTANCE, body.getContinuation()), new Branch(null, end.getContinuation()) }); - body.branchAwayUnless(body.apply(location, + body.branchAwayUnless(location, body.apply(location, EqualsFunction.INSTANCE.createSpecialization(componentType), value, body.getParameters()[0]), end.getContinuation()); nextOp(body); if(body.isUnfinished()) - body.jump(end.getContinuation()); + body.jump(location, end.getContinuation()); w.continueAs(end); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java index a43e97d4c..5902f9588 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java @@ -32,23 +32,23 @@ public class PostCommitOp extends PlanOp { for(PartnerFact activeFact : planContext.partnerFacts) { if(activeFact.killAfterMatch) { if(activeFact.nextFact == null) - w.jump(activeFact.finishCont); + w.jump(location, activeFact.finishCont); else { CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType); - w.jump(iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar)); + w.jump(location, iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar)); iterateUntilLiveFactFound(iterateAlive, activeFact); } break; } else if(activeFact.mayBeRemoved) { if(activeFact.nextFact == null) { - w.branchAwayUnless(activeFact.isAlive(location, w), activeFact.finishCont); + w.branchAwayUnless(location, activeFact.isAlive(location, w), activeFact.finishCont); } else { CodeWriter failure = w.createBlock(); CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType); - w.branchAwayUnless(activeFact.isAlive(location, w), failure.getContinuation()); - failure.jump(iterateAlive.getContinuation(), failure.apply(location, activeFact.nextFact, activeFact.factVar)); + w.branchAwayUnless(location, activeFact.isAlive(location, w), failure.getContinuation()); + failure.jump(location, iterateAlive.getContinuation(), failure.apply(location, activeFact.nextFact, activeFact.factVar)); iterateUntilLiveFactFound(iterateAlive, activeFact); } } @@ -61,10 +61,10 @@ public class PostCommitOp extends PlanOp { CHRConstraint constraint = activeFact.constraint; IVal fact = w.getParameters()[0]; CodeWriter dead = w.createBlock(); - w.branchAwayIf(w.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), activeFact.finishCont); - w.branchAwayUnless(activeFact.isAlive(location, w, fact), dead.getContinuation()); - w.jump(activeFact.continueCont, fact); - dead.jump(initialContinuation, dead.apply(location, activeFact.nextFact, fact)); + w.branchAwayIf(location, w.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), activeFact.finishCont); + w.branchAwayUnless(location, activeFact.isAlive(location, w, fact), dead.getContinuation()); + w.jump(location, activeFact.continueCont, fact); + dead.jump(location, initialContinuation, dead.apply(location, activeFact.nextFact, fact)); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java index fe6216fe1..149c52f50 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java @@ -47,16 +47,16 @@ public class EIf extends Expression { CodeWriter thenBlock = w.createBlock(); if(else_ != null) { CodeWriter elseBlock = w.createBlock(); - w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation()); + w.if_(location, conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation()); IVal elseVal = else_.toVal(context, elseBlock); - elseBlock.jump(joinPoint.getContinuation(), elseVal); + elseBlock.jump(location, joinPoint.getContinuation(), elseVal); } else { - w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation()); + w.if_(location, conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation()); } IVal thenVal = then_.toVal(context, thenBlock); - thenBlock.jump(joinPoint.getContinuation(), thenVal); + thenBlock.jump(location, joinPoint.getContinuation(), thenVal); w.continueAs(joinPoint); return w.getParameters()[0]; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java index 23c5b0be2..811877aa0 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java @@ -154,7 +154,7 @@ public class ELet extends Expression { IVal[] parameters = newW.getParameters(); for(int j=0;j() { @Override public boolean execute(SCLConstant function) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java index a5d0bdc9f..f83dcd3df 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java @@ -23,7 +23,7 @@ public abstract class SSAStatement implements Printable { SSABlock parent; SSAStatement prev; SSAStatement next; - public long location; + public int lineNumber = -2; public void detach() { if(prev == null) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java index 4eca7d1ae..ee69106cd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java @@ -31,7 +31,8 @@ public class If extends SSAExit implements ValRefBinder { private ContRef thenTarget; private ContRef elseTarget; - public If(ValRef condition, ContRef thenTarget, ContRef elseTarget) { + public If(int lineNumber, ValRef condition, ContRef thenTarget, ContRef elseTarget) { + super(lineNumber); setCondition(condition); setThenTarget(thenTarget); setElseTarget(elseTarget); @@ -54,6 +55,7 @@ public class If extends SSAExit implements ValRefBinder { @Override public void generateCode(MethodBuilder mb) { + mb.lineNumber(lineNumber); Val binding = condition.getBinding(); simplifyTestCode: if(binding instanceof BoundVar) { BoundVar boundVar = (BoundVar)binding; @@ -147,9 +149,11 @@ public class If extends SSAExit implements ValRefBinder { @Override public SSAExit copy(CopyContext context) { - return new If(context.copy(condition), + If copy = new If(lineNumber, + context.copy(condition), context.copy(thenTarget), context.copy(elseTarget)); + return copy; } @Override @@ -163,11 +167,11 @@ public class If extends SSAExit implements ValRefBinder { if(cond instanceof BooleanConstant) { SSAExit newExit; if(((BooleanConstant) cond).getValue()) { - newExit = new Jump(thenTarget); + newExit = new Jump(lineNumber, thenTarget); elseTarget.remove(); } else { - newExit = new Jump(elseTarget); + newExit = new Jump(lineNumber, elseTarget); thenTarget.remove(); } condition.remove(); @@ -177,7 +181,7 @@ public class If extends SSAExit implements ValRefBinder { else if(thenTarget.getBinding() == elseTarget.getBinding()) { elseTarget.remove(); condition.remove(); - getParent().setExit(new Jump(thenTarget)); + getParent().setExit(new Jump(lineNumber, thenTarget)); context.markModified("equal-branches-if"); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java index eb1a3dea9..434e8644a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java @@ -23,7 +23,8 @@ public class Jump extends SSAExit implements ValRefBinder { private ContRef target; private ValRef[] parameters; - public Jump(ContRef target, ValRef ... parameters) { + public Jump(int lineNumber, ContRef target, ValRef ... parameters) { + super(lineNumber); setTarget(target); setParameters(parameters); } @@ -48,7 +49,8 @@ public class Jump extends SSAExit implements ValRefBinder { } @Override - public void generateCode(MethodBuilder mb) { + public void generateCode(MethodBuilder mb) { + mb.lineNumber(lineNumber); mb.jump(target, ValRef.getBindings(parameters)); } @@ -91,7 +93,7 @@ public class Jump extends SSAExit implements ValRefBinder { @Override public SSAExit copy(CopyContext context) { - return new Jump(context.copy(target), context.copy(parameters)); + return new Jump(lineNumber, context.copy(target), context.copy(parameters)); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java index b3584ae7e..55f38f809 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java @@ -34,7 +34,8 @@ public class Switch extends SSAExit implements ValRefBinder { ValRef scrutinee; BranchRef[] branches; - public Switch(ValRef scrutinee, BranchRef[] branches) { + public Switch(int lineNumber, ValRef scrutinee, BranchRef[] branches) { + super(lineNumber); this.scrutinee = scrutinee; this.branches = branches; scrutinee.setParent(this); @@ -90,6 +91,7 @@ public class Switch extends SSAExit implements ValRefBinder { @Override public void generateCode(MethodBuilder mb) { + mb.lineNumber(lineNumber); if(isIntegerSwitch()) { generateIntegerSwitch(mb); return; @@ -168,7 +170,7 @@ public class Switch extends SSAExit implements ValRefBinder { @Override public SSAExit copy(CopyContext context) { - return new Switch(context.copy(scrutinee), + return new Switch(lineNumber, context.copy(scrutinee), BranchRef.copy(context, branches)); } @@ -221,10 +223,11 @@ public class Switch extends SSAExit implements ValRefBinder { SSAExit newExit; if(thenTarget == elseTarget) { scrutinee.remove(); - newExit = new Jump(thenTarget); + newExit = new Jump(lineNumber, thenTarget); } else { - newExit = new If(scrutinee, + newExit = new If(lineNumber, + scrutinee, thenTarget, elseTarget); } @@ -234,7 +237,7 @@ public class Switch extends SSAExit implements ValRefBinder { } else if(branches.length == 1 && isConstructorParameterless(branches[0])) { scrutinee.remove(); - getParent().setExit(new Jump(branches[0].cont)); + getParent().setExit(new Jump(lineNumber, branches[0].cont)); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java index 593b81c63..0193c99c2 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java @@ -30,7 +30,8 @@ public class Throw extends SSAExit { TypeDesc exceptionClass; String description; - public Throw(TypeDesc exceptionClass, String description) { + public Throw(int lineNumber, TypeDesc exceptionClass, String description) { + super(lineNumber); this.exceptionClass = exceptionClass; this.description = description; } @@ -43,8 +44,7 @@ public class Throw extends SSAExit { @Override public void generateCode(MethodBuilder mb) { - //mb.push(exception.getBinding()); - //cb.mapLineNumber(location); + mb.lineNumber(lineNumber); mb.newObject(exceptionClass); mb.dup(); if(description == null) @@ -67,7 +67,7 @@ public class Throw extends SSAExit { @Override public SSAExit copy(CopyContext context) { - return new Throw(exceptionClass, description); + return new Throw(lineNumber, exceptionClass, description); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java index 78353b424..97fba708d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java @@ -21,7 +21,8 @@ public class Throw2 extends SSAExit { ValRef exception; - public Throw2(ValRef exception) { + public Throw2(int lineNumber, ValRef exception) { + super(lineNumber); this.exception = exception; } @@ -34,6 +35,7 @@ public class Throw2 extends SSAExit { @Override public void generateCode(MethodBuilder mb) { + mb.lineNumber(lineNumber); mb.pushBoxed(exception.getBinding()); mb.throwObject(); } @@ -49,7 +51,7 @@ public class Throw2 extends SSAExit { @Override public SSAExit copy(CopyContext context) { - return new Throw2(exception.copy()); + return new Throw2(lineNumber, exception.copy()); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java index 2733868cf..b4c295538 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java @@ -55,7 +55,7 @@ public class LetApply extends LetStatement implements ValRefBinder { } public void push(MethodBuilder mb) { - //mb.getCodeBuilder().mapLineNumber(lineNumber); + int oldLineNumber = mb.lineNumber(lineNumber); Val f = getFunction().getBinding(); Val[] ps = ValRef.getBindings(getParameters()); if(f instanceof Constant) { @@ -70,11 +70,13 @@ public class LetApply extends LetStatement implements ValRefBinder { mb.genericApply(ps.length); mb.unbox(target.getType()); } + mb.lineNumber(oldLineNumber); } @Override public void generateCode(MethodBuilder mb) { if(!target.generateOnFly) { + mb.lineNumber(lineNumber); push(mb); mb.store(target); } @@ -101,6 +103,7 @@ public class LetApply extends LetStatement implements ValRefBinder { public void bodyToString(PrintingContext context) { if(context.getErrorMarker() == this) context.append("!> "); + context.append("L" + lineNumber + ": "); if(hasEffect()) { context.append("<"); context.append(effect); @@ -417,8 +420,7 @@ public class LetApply extends LetStatement implements ValRefBinder { // Merge blocks thisFunction.mergeBlocks(function); - headBlock.setExit(new Jump(function.getFirstBlock().createOccurrence(), - parameters)); + headBlock.setExit(new Jump(lineNumber, function.getFirstBlock().createOccurrence(), parameters)); function.getReturnCont().replaceWith(tailBlock); this.function.remove(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java index bd1a911a1..51a93c53c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java @@ -12,6 +12,7 @@ public class MethodBuilderBase { private MethodVisitor methodVisitor; private LocalVariable[] parameters; private int localVariableCount = 0; + private int currentLineNumber = -1; public MethodBuilderBase(ClassBuilder classBuilder, boolean isStatic, MethodVisitor methodVisitor, TypeDesc[] parameterTypes) { this.classBuilder = classBuilder; @@ -87,6 +88,20 @@ public class MethodBuilderBase { methodVisitor.visitLdcInsn(Type.getType(value.getDescriptor())); } + + public int lineNumber(int lineNumber) { + if(lineNumber != currentLineNumber) { + int oldLineNumber = currentLineNumber; + Label label = createLabel(); + setLocation(label); + methodVisitor.visitLineNumber(lineNumber, label); + currentLineNumber = lineNumber; + return oldLineNumber; + } + else + return currentLineNumber; + } + public void dup() { methodVisitor.visitInsn(Opcodes.DUP); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java index 1125a4bde..bb774bd24 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.internal.codegen.writer; import org.cojen.classfile.TypeDesc; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.codegen.continuations.Branch; import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef; import org.simantics.scl.compiler.internal.codegen.continuations.ICont; @@ -33,11 +34,22 @@ public class CodeWriter { this.moduleWriter = moduleWriter; this.block = block; } + + private int lineNumber(long location) { + if(location == Locations.NO_LOCATION) + return -1; + else { + int position = Locations.beginOf(location); + int line = moduleWriter.lineLocator.lineNumberFromPosition(position); + //System.out.println("location=" + location + ", position=" + position + ", line=" + line); + return line + 1; + } + } - public IVal apply(long lineNumber, IVal function, IVal ... parameters) { + public IVal apply(long location, IVal function, IVal ... parameters) { try { MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length); - return applyWithEffect(lineNumber, + return applyWithEffect(location, mfun.effect, mfun.returnType, function, parameters); @@ -46,7 +58,7 @@ public class CodeWriter { } } - public IVal applyWithEffectChecked(long lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) { + public IVal applyWithEffectChecked(long location, Type effect, Type returnType, IVal function, IVal ... parameters) { try { MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length); if(!Types.equals(effect, mfun.effect)) @@ -56,7 +68,7 @@ public class CodeWriter { } catch (MatchException e) { throw new InternalCompilerError(e); } - return applyWithEffect(lineNumber, effect, returnType, function, parameters); + return applyWithEffect(location, effect, returnType, function, parameters); } public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) { @@ -65,7 +77,7 @@ public class CodeWriter { effect, function.createOccurrence(), ValRef.createOccurrences(parameters)); - apply.location = location; + apply.lineNumber = lineNumber(location); block.addStatement(apply); return var; } @@ -115,49 +127,56 @@ public class CodeWriter { return block; } - public void jump(ICont cont, IVal ... parameters) { - block.setExit(new Jump(cont.createOccurrence(), + public void jump(long location, ICont cont, IVal ... parameters) { + block.setExit(new Jump( + lineNumber(location), + cont.createOccurrence(), ValRef.createOccurrences(parameters))); block = null; } - public void if_(IVal condition, ICont thenTarget, ICont elseTarget) { - block.setExit(new If(condition.createOccurrence(), + public void if_(long location, IVal condition, ICont thenTarget, ICont elseTarget) { + block.setExit(new If( + lineNumber(location), + condition.createOccurrence(), thenTarget.createOccurrence(), elseTarget.createOccurrence())); block = null; } - public void branchAwayIf(IVal condition, ICont target) { + public void branchAwayIf(long location, IVal condition, ICont target) { SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY); block.getParent().addBlock(newBlock); - block.setExit(new If(condition.createOccurrence(), + block.setExit(new If( + lineNumber(location), + condition.createOccurrence(), target.createOccurrence(), newBlock.createOccurrence())); this.block = newBlock; } - public void branchAwayUnless(IVal condition, ICont target) { + public void branchAwayUnless(long location, IVal condition, ICont target) { SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY); block.getParent().addBlock(newBlock); - block.setExit(new If(condition.createOccurrence(), + block.setExit(new If( + lineNumber(location), + condition.createOccurrence(), newBlock.createOccurrence(), target.createOccurrence())); this.block = newBlock; } - public void return_(IVal val) { - jump(block.getParent().getReturnCont(), val); + public void return_(long location, IVal val) { + jump(lineNumber(location), block.getParent().getReturnCont(), val); } - public void switch_(IVal val, Branch[] branches) { - block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches))); + public void switch_(long location, IVal val, Branch[] branches) { + block.setExit(new Switch(lineNumber(location), val.createOccurrence(), BranchRef.toBranchRefs(branches))); block = null; } public void throw_(long location, TypeDesc exceptionClass, String description) { - Throw exit = new Throw(exceptionClass, description); - exit.location = location; + Throw exit = new Throw(lineNumber(location), exceptionClass, description); block.setExit(exit); block = null; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/ModuleWriter.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/ModuleWriter.java index da986195b..e663c814e 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/ModuleWriter.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/ModuleWriter.java @@ -10,6 +10,7 @@ import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock; import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction; import org.simantics.scl.compiler.internal.codegen.ssa.SSAModule; import org.simantics.scl.compiler.internal.codegen.ssa.StaticField; +import org.simantics.scl.compiler.internal.parsing.utils.LineLocator; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.runtime.tuple.Tuple2; @@ -19,15 +20,17 @@ import gnu.trove.map.hash.THashMap; public class ModuleWriter { SSAModule module; + LineLocator lineLocator; String moduleClassName; THashMap externalConstantMap = new THashMap(); int externalConstantId = 0; - public ModuleWriter(String moduleClassName) { + public ModuleWriter(String moduleClassName, LineLocator lineLocator) { this.module = new SSAModule(); this.moduleClassName = moduleClassName; + this.lineLocator = lineLocator; } public CodeWriter createFunction(SCLConstant constant, TVar[] typeParameters, diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java index 62b2ec1aa..64bf7053b 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java @@ -55,7 +55,7 @@ public class PatternMatchingCompiler { return newVals; } - private static void splitByConstructors(CodeWriter w, final CompilationContext context, IVal[] scrutinee, final ICont success, ICont failure, List rows, int columnId) { + private static void splitByConstructors(long location, CodeWriter w, final CompilationContext context, IVal[] scrutinee, final ICont success, ICont failure, List rows, int columnId) { THashMap matrixMap = new THashMap(); ArrayList branches = new ArrayList(); ArrayList matrices = new ArrayList(); @@ -168,7 +168,7 @@ public class PatternMatchingCompiler { CodeWriter newW = w.createBlock(); ICont cont = newW.getContinuation(); branches.add(new Branch(null, cont)); - split(newW, context, scrutinee, success, failure, rows.subList(i, rows.size())); + split(location, newW, context, scrutinee, success, failure, rows.subList(i, rows.size())); failure = cont; } else { @@ -186,11 +186,11 @@ public class PatternMatchingCompiler { } for(ExpressionMatrix mx : matrices) - split(mx.w, context, mx.scrutinee, success, failure, mx.rows); - w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()])); + split(location, mx.w, context, mx.scrutinee, success, failure, mx.rows); + w.switch_(location, scrutinee[columnId], branches.toArray(new Branch[branches.size()])); } - private static void splitByViewPattern(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, + private static void splitByViewPattern(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, ICont failure, List rows, int viewPatternColumn) { Row firstRow = rows.get(0); EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn]; @@ -225,16 +225,16 @@ public class PatternMatchingCompiler { firstViewPattern.expression.toVal(context, w), scrutinee[viewPatternColumn]); if(i == rows.size()) { - split(w, context, newScrutinee, success, failure, rows); + split(location, w, context, newScrutinee, success, failure, rows); } else { CodeWriter cont = w.createBlock(); - split(w, context, newScrutinee, success, cont.getContinuation(), rows.subList(0, i)); - split(cont, context, scrutinee, success, failure, rows.subList(i, rows.size())); + split(location, w, context, newScrutinee, success, cont.getContinuation(), rows.subList(0, i)); + split(location, cont, context, scrutinee, success, failure, rows.subList(i, rows.size())); } } - public static void split(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, ICont failure, List rows) { + public static void split(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, ICont failure, List rows) { Row firstRow = rows.get(0); Expression[] patterns = firstRow.patterns; if(scrutinee.length != patterns.length) @@ -249,13 +249,13 @@ public class PatternMatchingCompiler { viewPatternColumn = i; } else if(!(pattern instanceof EVariable)) { - splitByConstructors(w, context, scrutinee, success, failure, rows, i); + splitByConstructors(location, w, context, scrutinee, success, failure, rows, i); return; } } if(viewPatternColumn >= 0) { - splitByViewPattern(w, context, scrutinee, success, failure, rows, viewPatternColumn); + splitByViewPattern(location, w, context, scrutinee, success, failure, rows, viewPatternColumn); return; } @@ -271,10 +271,10 @@ public class PatternMatchingCompiler { CodeWriter newW = w.createBlock(); ICont cont = newW.getContinuation(); group.compile(context, w, success, cont); - split(newW, context, scrutinee, success, failure, rows.subList(1, rows.size())); + split(location, newW, context, scrutinee, success, failure, rows.subList(1, rows.size())); } } else - w.jump(success, firstRow.value.toVal(context, w)); + w.jump(location, success, firstRow.value.toVal(context, w)); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java index 24a3bfb2e..41882f57a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java @@ -54,7 +54,7 @@ public class PatternMatchingCompiler2 { return newVals; } - private static void splitByConstructors(CodeWriter w, final CompilationContext context, IVal[] scrutinee, ICont failure, List rows, int columnId) { + private static void splitByConstructors(long location, CodeWriter w, final CompilationContext context, IVal[] scrutinee, ICont failure, List rows, int columnId) { THashMap matrixMap = new THashMap(); ArrayList branches = new ArrayList(); ArrayList matrices = new ArrayList(); @@ -167,7 +167,7 @@ public class PatternMatchingCompiler2 { CodeWriter newW = w.createBlock(); ICont cont = newW.getContinuation(); branches.add(new Branch(null, cont)); - split(newW, context, scrutinee, failure, rows.subList(i, rows.size())); + split(location, newW, context, scrutinee, failure, rows.subList(i, rows.size())); failure = cont; } else { @@ -185,11 +185,11 @@ public class PatternMatchingCompiler2 { } for(ExpressionMatrix mx : matrices) - split(mx.w, context, mx.scrutinee, failure, mx.rows); - w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()])); + split(location, mx.w, context, mx.scrutinee, failure, mx.rows); + w.switch_(location, scrutinee[columnId], branches.toArray(new Branch[branches.size()])); } - private static void splitByViewPattern(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List rows, int viewPatternColumn) { + private static void splitByViewPattern(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List rows, int viewPatternColumn) { Row2 firstRow = rows.get(0); EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn]; firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern; @@ -223,16 +223,16 @@ public class PatternMatchingCompiler2 { firstViewPattern.expression.toVal(context, w), scrutinee[viewPatternColumn]); if(i == rows.size()) { - split(w, context, newScrutinee, failure, rows); + split(location, w, context, newScrutinee, failure, rows); } else { CodeWriter cont = w.createBlock(); - split(w, context, newScrutinee, cont.getContinuation(), rows.subList(0, i)); - split(cont, context, scrutinee, failure, rows.subList(i, rows.size())); + split(location, w, context, newScrutinee, cont.getContinuation(), rows.subList(0, i)); + split(location, cont, context, scrutinee, failure, rows.subList(i, rows.size())); } } - public static void split(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List rows) { + public static void split(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List rows) { Row2 firstRow = rows.get(0); Expression[] patterns = firstRow.patterns; if(scrutinee.length != patterns.length) @@ -247,19 +247,19 @@ public class PatternMatchingCompiler2 { viewPatternColumn = i; } else if(!(pattern instanceof EVariable)) { - splitByConstructors(w, context, scrutinee, failure, rows, i); + splitByConstructors(location, w, context, scrutinee, failure, rows, i); return; } } if(viewPatternColumn >= 0) { - splitByViewPattern(w, context, scrutinee, failure, rows, viewPatternColumn); + splitByViewPattern(location, w, context, scrutinee, failure, rows, viewPatternColumn); return; } // The first row has only variable patterns: no matching needed for(int i=0;i= lineNumbers.length) + return maxLine; + return (int)lineNumbers[position]; + } + } + + private static class CharArrayLineLocator extends LineLocator { + private final char[] lineNumbers; + private final int maxLine; + + public CharArrayLineLocator(int[] rowStarts) { + super(rowStarts); + int lastRow = rowStarts.length-1; + this.lineNumbers = new char[rowStarts[lastRow]]; + this.maxLine = rowStarts.length-1; + + int position = 0; + int line = 0; + while(line < maxLine) { + int endPosition = rowStarts[line+1]; + while(position < endPosition) + lineNumbers[position++] = (char)line; + ++line; + } + } + + @Override + public int lineNumberFromPosition(int position) { + if(position <= 0) + return 0; + if(position >= lineNumbers.length) + return maxLine; + return (int)lineNumbers[position]; + } + } + + private static class IntArrayLineLocator extends LineLocator { + private final int[] lineNumbers; + private final int maxLine; + + public IntArrayLineLocator(int[] rowStarts) { + super(rowStarts); + int lastRow = rowStarts.length-1; + this.lineNumbers = new int[rowStarts[lastRow]]; + this.maxLine = rowStarts.length-1; + + int position = 0; + int line = 0; + while(line < maxLine) { + int endPosition = rowStarts[line+1]; + while(position < endPosition) + lineNumbers[position++] = line; + ++line; + } + } + + @Override + public int lineNumberFromPosition(int position) { + if(position <= 0) + return 0; + if(position >= lineNumbers.length) + return maxLine; + return lineNumbers[position]; + } + } + + private static class BinarySearchLineLocator extends LineLocator { + public BinarySearchLineLocator(int[] rowStarts) { + super(rowStarts); + } + + @Override + public int lineNumberFromPosition(int position) { + if(position <= 0) + return 0; + if(position >= rowStarts[rowStarts.length-1]) + return rowStarts.length-1; + int low = 0; + int high = rowStarts.length-1; + // invariant, low <= lineNumber < high + while(low < high-1) { + int middle = (low+high) / 2; + if(position < rowStarts[middle]) + high = middle; + else + low = middle; + } + return low; + } + } + + private static class InterpolationSearchLineLocator extends LineLocator { + public InterpolationSearchLineLocator(int[] rowStarts) { + super(rowStarts); + } + + @Override + public int lineNumberFromPosition(int position) { + if(position <= 0) + return 0; + if(position >= rowStarts[rowStarts.length-1]) + return rowStarts.length-1; + int low = 0; + int lowPosition = 0; + int high = rowStarts.length-1; + int highPosition = rowStarts[high]; + // invariant, low <= lineNumber < high + while(low < high-1) { + int delta = (int)((long)(high - low) * (position - lowPosition) / (highPosition - lowPosition)); + int middle = low + delta; + if(middle == low) + ++middle; + if(position < rowStarts[middle]) { + high = middle; + highPosition = rowStarts[high]; + } + else { + low = middle; + lowPosition = rowStarts[low]; + } + } + return low; + } + } + + public static final LineLocator DUMMY_LOCATOR = new LineLocator(new int[] {0}) { + @Override + public int lineNumberFromPosition(int position) { + return 0; + } + }; + + private static int[] findRowStarts(String source) { + TIntArrayList rowStarts = new TIntArrayList(); + rowStarts.add(0); + + int length = source.length(); + for(int i=0;i getJavaReferenceValidator() { return new RuntimeJavaReferenceValidator(getClassLoader()); } public String getSourceText(UpdateListener listener) throws IOException { Reader reader = getSourceReader(listener); - char[] buffer = new char[65536]; + char[] buffer = new char[4096]; int pos = 0; try { while(true) { @@ -83,7 +87,8 @@ public abstract class TextualModuleSource implements ModuleSource { public Failable compileModule(final ModuleRepository environment, final UpdateListener listener, ModuleCompilationOptions options) { SCLCompiler compiler = new SCLCompiler(options, getJavaReferenceValidatorFactory()); try { - compiler.addSource(getSourceReader(listener)); + String source = getSourceText(listener); + compiler.addSource(source); compiler.compile( new EnvironmentFactoryImpl( environment, diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java index 36994d136..b51b188cd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java @@ -47,6 +47,7 @@ import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorExce import org.simantics.scl.compiler.internal.parsing.parser.SCLBlockParser; import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl; import org.simantics.scl.compiler.internal.parsing.parser.SCLParserOptions; +import org.simantics.scl.compiler.internal.parsing.utils.LineLocators; import org.simantics.scl.compiler.runtime.MutableClassLoader; import org.simantics.scl.compiler.runtime.RuntimeEnvironment; import org.simantics.scl.compiler.types.TVar; @@ -202,6 +203,7 @@ public class ExpressionEvaluator { // Parse expression if(expressionText != null) { + compilationContext.lineLocator = LineLocators.createLineLocator(expressionText); try { switch(parseMode) { case BLOCK: { @@ -230,6 +232,8 @@ public class ExpressionEvaluator { throw new SCLExpressionCompilationException(errorLog.getErrors()); } } + else + compilationContext.lineLocator = LineLocators.DUMMY_LOCATOR; // Store local variables ArrayList lvTypes = new ArrayList(); @@ -364,7 +368,7 @@ public class ExpressionEvaluator { } // Convert to SSA - ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName()); + ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName(), compilationContext.lineLocator); DecomposedExpression decomposed = DecomposedExpression.decompose(errorLog, expression); @@ -387,9 +391,10 @@ public class ExpressionEvaluator { IVal[] parameterVals = w.getParameters(); for(int i=0;i