mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix bugs in debugger
This commit is contained in:
parent
5c90d786a0
commit
89189c7454
|
@ -18,15 +18,25 @@ package org.teavm.ast;
|
|||
import java.util.List;
|
||||
|
||||
public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
||||
protected void beforeVisit(Expr expr) {
|
||||
}
|
||||
|
||||
protected void afterVisit(Expr expr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getFirstOperand().acceptVisitor(this);
|
||||
expr.getSecondOperand().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnaryExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getOperand().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,9 +49,11 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ConditionalExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getCondition().acceptVisitor(this);
|
||||
expr.getConsequent().acceptVisitor(this);
|
||||
expr.getAlternative().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
public void visit(List<Statement> statements) {
|
||||
|
@ -57,6 +69,8 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(ConstantExpr expr) {
|
||||
beforeVisit(expr);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,12 +82,16 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(VariableExpr expr) {
|
||||
beforeVisit(expr);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SubscriptExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getArray().acceptVisitor(this);
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,7 +105,9 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(UnwrapArrayExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getArray().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,9 +120,11 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(InvocationExpr expr) {
|
||||
beforeVisit(expr);
|
||||
for (Expr argument : expr.getArguments()) {
|
||||
argument.acceptVisitor(this);
|
||||
}
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,9 +134,11 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(QualificationExpr expr) {
|
||||
beforeVisit(expr);
|
||||
if (expr.getQualified() != null) {
|
||||
expr.getQualified().acceptVisitor(this);
|
||||
}
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,6 +147,8 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(NewExpr expr) {
|
||||
beforeVisit(expr);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,14 +157,18 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(NewArrayExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getLength().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewMultiArrayExpr expr) {
|
||||
beforeVisit(expr);
|
||||
for (Expr dimension : expr.getDimensions()) {
|
||||
dimension.acceptVisitor(this);
|
||||
}
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,7 +180,9 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(InstanceOfExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getExpr().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,7 +192,9 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(CastExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getValue().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -169,7 +203,9 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(PrimitiveCastExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getValue().acceptVisitor(this);
|
||||
afterVisit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.ast.analysis;
|
||||
|
||||
import com.carrotsearch.hppc.IntArrayDeque;
|
||||
import com.carrotsearch.hppc.IntArrayList;
|
||||
import com.carrotsearch.hppc.IntDeque;
|
||||
import com.carrotsearch.hppc.IntHashSet;
|
||||
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||
import com.carrotsearch.hppc.ObjectIntMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
import org.teavm.ast.ConditionalStatement;
|
||||
import org.teavm.ast.ContinueStatement;
|
||||
import org.teavm.ast.Expr;
|
||||
import org.teavm.ast.IdentifiedStatement;
|
||||
import org.teavm.ast.InitClassStatement;
|
||||
import org.teavm.ast.MonitorEnterStatement;
|
||||
import org.teavm.ast.MonitorExitStatement;
|
||||
import org.teavm.ast.RecursiveVisitor;
|
||||
import org.teavm.ast.ReturnStatement;
|
||||
import org.teavm.ast.Statement;
|
||||
import org.teavm.ast.SwitchClause;
|
||||
import org.teavm.ast.SwitchStatement;
|
||||
import org.teavm.ast.ThrowStatement;
|
||||
import org.teavm.ast.TryCatchStatement;
|
||||
import org.teavm.ast.WhileStatement;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphBuilder;
|
||||
import org.teavm.model.TextLocation;
|
||||
|
||||
public final class LocationGraphBuilder {
|
||||
private LocationGraphBuilder() {
|
||||
}
|
||||
|
||||
public static Map<TextLocation, TextLocation[]> build(Statement node) {
|
||||
Visitor visitor = new Visitor();
|
||||
node.acceptVisitor(visitor);
|
||||
Graph graph = visitor.builder.build();
|
||||
TextLocation[][] locations = propagate(visitor.locations.toArray(new TextLocation[0]), graph);
|
||||
|
||||
Map<TextLocation, Set<TextLocation>> builder = new LinkedHashMap<>();
|
||||
for (int i = 0; i < graph.size(); ++i) {
|
||||
for (int j : graph.outgoingEdges(i)) {
|
||||
for (TextLocation from : locations[i]) {
|
||||
for (TextLocation to : locations[j]) {
|
||||
builder.computeIfAbsent(from, k -> new LinkedHashSet<>()).add(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<TextLocation, TextLocation[]> result = new LinkedHashMap<>();
|
||||
for (Map.Entry<TextLocation, Set<TextLocation>> entry : builder.entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().toArray(new TextLocation[0]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static TextLocation[][] propagate(TextLocation[] locations, Graph graph) {
|
||||
List<Set<TextLocation>> result = new ArrayList<>();
|
||||
boolean[] stop = new boolean[graph.size()];
|
||||
IntDeque queue = new IntArrayDeque();
|
||||
for (int i = 0; i < stop.length; ++i) {
|
||||
Set<TextLocation> set = new LinkedHashSet<>();
|
||||
result.add(set);
|
||||
if (locations[i] != null) {
|
||||
stop[i] = true;
|
||||
queue.addLast(i);
|
||||
set.add(locations[i]);
|
||||
}
|
||||
}
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
int node = queue.removeFirst();
|
||||
for (int successor : graph.outgoingEdges(node)) {
|
||||
if (stop[successor]) {
|
||||
continue;
|
||||
}
|
||||
if (result.get(successor).addAll(result.get(node))) {
|
||||
queue.addLast(successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.stream().map(s -> s.toArray(new TextLocation[0])).toArray(TextLocation[][]::new);
|
||||
}
|
||||
|
||||
static class Visitor extends RecursiveVisitor {
|
||||
static final int[] EMPTY = new int[0];
|
||||
int[] nodes = EMPTY;
|
||||
ObjectIntMap<IdentifiedStatement> breakNodes = new ObjectIntHashMap<>();
|
||||
ObjectIntMap<IdentifiedStatement> continueNodes = new ObjectIntHashMap<>();
|
||||
IdentifiedStatement defaultBreakTarget;
|
||||
IdentifiedStatement defaultContinueTarget;
|
||||
GraphBuilder builder = new GraphBuilder();
|
||||
List<TextLocation> locations = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected void afterVisit(Expr expr) {
|
||||
setLocation(expr.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
int exit = createNode(null);
|
||||
breakNodes.put(statement, exit);
|
||||
super.visit(statement);
|
||||
breakNodes.remove(statement);
|
||||
|
||||
setNode(exit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(WhileStatement statement) {
|
||||
IdentifiedStatement oldDefaultBreakTarget = defaultBreakTarget;
|
||||
IdentifiedStatement oldDefaultContinueTarget = defaultContinueTarget;
|
||||
|
||||
int head = createNode(null);
|
||||
int exit = createNode(null);
|
||||
|
||||
setNode(head);
|
||||
|
||||
breakNodes.put(statement, exit);
|
||||
continueNodes.put(statement, head);
|
||||
defaultBreakTarget = statement;
|
||||
defaultContinueTarget = statement;
|
||||
|
||||
if (statement.getCondition() != null) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
}
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, exit);
|
||||
}
|
||||
visit(statement.getBody());
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, head);
|
||||
}
|
||||
nodes = new int[] { exit };
|
||||
|
||||
defaultBreakTarget = oldDefaultBreakTarget;
|
||||
defaultContinueTarget = oldDefaultContinueTarget;
|
||||
breakNodes.remove(statement);
|
||||
continueNodes.remove(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchStatement statement) {
|
||||
IdentifiedStatement oldDefaultBreakTarget = defaultBreakTarget;
|
||||
|
||||
int exit = createNode(null);
|
||||
|
||||
breakNodes.put(statement, exit);
|
||||
defaultBreakTarget = statement;
|
||||
|
||||
statement.getValue().acceptVisitor(this);
|
||||
int[] headNodes = nodes;
|
||||
for (SwitchClause clause : statement.getClauses()) {
|
||||
nodes = headNodes;
|
||||
visit(clause.getBody());
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, exit);
|
||||
}
|
||||
}
|
||||
nodes = headNodes;
|
||||
visit(statement.getDefaultClause());
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, exit);
|
||||
}
|
||||
|
||||
nodes = new int[] { exit };
|
||||
|
||||
defaultBreakTarget = oldDefaultBreakTarget;
|
||||
breakNodes.remove(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
IntArrayList exit = new IntArrayList();
|
||||
|
||||
int[] head = nodes;
|
||||
visit(statement.getConsequent());
|
||||
exit.add(nodes);
|
||||
|
||||
nodes = head;
|
||||
visit(statement.getAlternative());
|
||||
exit.add(nodes);
|
||||
|
||||
nodes = distinct(exit);
|
||||
}
|
||||
|
||||
private int[] distinct(IntArrayList list) {
|
||||
IntHashSet set = new IntHashSet();
|
||||
int j = 0;
|
||||
int[] result = new int[list.size()];
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
int e = list.get(i);
|
||||
if (set.add(e)) {
|
||||
result[j++] = e;
|
||||
}
|
||||
}
|
||||
if (j < result.length) {
|
||||
result = Arrays.copyOf(result, j);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BreakStatement statement) {
|
||||
IdentifiedStatement target = statement.getTarget();
|
||||
if (target == null) {
|
||||
target = defaultBreakTarget;
|
||||
}
|
||||
int targetNode = breakNodes.get(target);
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, targetNode);
|
||||
}
|
||||
nodes = EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ContinueStatement statement) {
|
||||
IdentifiedStatement target = statement.getTarget();
|
||||
if (target == null) {
|
||||
target = defaultContinueTarget;
|
||||
}
|
||||
int targetNode = continueNodes.get(target);
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, targetNode);
|
||||
}
|
||||
nodes = EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ThrowStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
nodes = EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ReturnStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
nodes = EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(TryCatchStatement statement) {
|
||||
int catchNode = createNode(null);
|
||||
for (Statement s : statement.getProtectedBody()) {
|
||||
s.acceptVisitor(this);
|
||||
for (int node : nodes) {
|
||||
builder.addEdge(node, catchNode);
|
||||
}
|
||||
}
|
||||
|
||||
nodes = new int[] { catchNode };
|
||||
visit(statement.getHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignmentStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorEnterStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitStatement statement) {
|
||||
super.visit(statement);
|
||||
setLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConditionalExpr expr) {
|
||||
expr.getCondition().acceptVisitor(this);
|
||||
IntArrayList exit = new IntArrayList();
|
||||
|
||||
int[] head = nodes;
|
||||
expr.getConsequent().acceptVisitor(this);
|
||||
exit.add(nodes);
|
||||
|
||||
nodes = head;
|
||||
expr.getAlternative().acceptVisitor(this);
|
||||
exit.add(nodes);
|
||||
|
||||
nodes = distinct(exit);
|
||||
}
|
||||
|
||||
private void setNode(int node) {
|
||||
for (int prevNode : nodes) {
|
||||
builder.addEdge(prevNode, node);
|
||||
}
|
||||
nodes = new int[] { node };
|
||||
}
|
||||
|
||||
private void setLocation(TextLocation location) {
|
||||
if (location == null) {
|
||||
return;
|
||||
}
|
||||
int node = createNode(location);
|
||||
for (int prevNode : nodes) {
|
||||
builder.addEdge(prevNode, node);
|
||||
}
|
||||
nodes = new int[] { node };
|
||||
}
|
||||
|
||||
private int createNode(TextLocation location) {
|
||||
int index = locations.size();
|
||||
locations.add(location);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -270,12 +270,13 @@ class StatementGenerator implements InstructionVisitor {
|
|||
insn.getConsequent(), insn.getAlternative());
|
||||
break;
|
||||
case NOT_NULL:
|
||||
branch(Expr.binary(BinaryOperation.NOT_EQUALS, null, Expr.var(insn.getOperand().getIndex()),
|
||||
Expr.constant(null)), insn.getConsequent(), insn.getAlternative());
|
||||
branch(withLocation(Expr.binary(BinaryOperation.NOT_EQUALS, null,
|
||||
Expr.var(insn.getOperand().getIndex()), Expr.constant(null), currentLocation)),
|
||||
insn.getConsequent(), insn.getAlternative());
|
||||
break;
|
||||
case NULL:
|
||||
branch(Expr.binary(BinaryOperation.EQUALS, null, Expr.var(insn.getOperand().getIndex()),
|
||||
Expr.constant(null)), insn.getConsequent(), insn.getAlternative());
|
||||
branch(withLocation(Expr.binary(BinaryOperation.EQUALS, null, Expr.var(insn.getOperand().getIndex()),
|
||||
Expr.constant(null))), insn.getConsequent(), insn.getAlternative());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,10 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import org.teavm.ast.ClassNode;
|
||||
import org.teavm.ast.MethodNode;
|
||||
import org.teavm.ast.RegularMethodNode;
|
||||
import org.teavm.ast.Statement;
|
||||
import org.teavm.ast.analysis.LocationGraphBuilder;
|
||||
import org.teavm.ast.decompilation.Decompiler;
|
||||
import org.teavm.backend.javascript.codegen.AliasProvider;
|
||||
import org.teavm.backend.javascript.codegen.DefaultAliasProvider;
|
||||
|
@ -331,11 +335,16 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
renderer.setMinifying(minifying);
|
||||
renderer.setProgressConsumer(controller::reportProgress);
|
||||
if (debugEmitter != null) {
|
||||
for (String className : classes.getClassNames()) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
emitCFG(debugEmitter, method.getProgram());
|
||||
for (ClassNode classNode : clsNodes) {
|
||||
ClassHolder cls = classes.get(classNode.getName());
|
||||
for (MethodNode methodNode : classNode.getMethods()) {
|
||||
if (methodNode instanceof RegularMethodNode) {
|
||||
emitCFG(debugEmitter, ((RegularMethodNode) methodNode).getBody());
|
||||
} else {
|
||||
MethodHolder method = cls.getMethod(methodNode.getReference().getDescriptor());
|
||||
if (method != null && method.getProgram() != null) {
|
||||
emitCFG(debugEmitter, method.getProgram());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.wasCancelled()) {
|
||||
|
@ -575,7 +584,14 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
}
|
||||
|
||||
private void emitCFG(DebugInformationEmitter emitter, Program program) {
|
||||
Map<TextLocation, TextLocation[]> cfg = ProgramUtils.getLocationCFG(program);
|
||||
emitCFG(emitter, ProgramUtils.getLocationCFG(program));
|
||||
}
|
||||
|
||||
private void emitCFG(DebugInformationEmitter emitter, Statement program) {
|
||||
emitCFG(emitter, LocationGraphBuilder.build(program));
|
||||
}
|
||||
|
||||
private void emitCFG(DebugInformationEmitter emitter, Map<TextLocation, TextLocation[]> cfg) {
|
||||
for (Map.Entry<TextLocation, TextLocation[]> entry : cfg.entrySet()) {
|
||||
SourceLocation location = map(entry.getKey());
|
||||
SourceLocation[] successors = new SourceLocation[entry.getValue().length];
|
||||
|
|
|
@ -276,21 +276,16 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
|||
public void visit(WhileStatement statement) {
|
||||
try {
|
||||
debugEmitter.emitStatementStart();
|
||||
if (statement.getCondition() != null && statement.getCondition().getLocation() != null) {
|
||||
pushLocation(statement.getCondition().getLocation());
|
||||
}
|
||||
if (statement.getId() != null) {
|
||||
writer.append(mapBlockId(statement.getId())).append(":").ws();
|
||||
}
|
||||
writer.append("while").ws().append("(");
|
||||
writer.append("while");
|
||||
writer.ws().append("(");
|
||||
if (statement.getCondition() != null) {
|
||||
prevCallSite = debugEmitter.emitCallSite();
|
||||
precedence = Precedence.min();
|
||||
statement.getCondition().acceptVisitor(this);
|
||||
debugEmitter.emitCallSite();
|
||||
if (statement.getCondition().getLocation() != null) {
|
||||
popLocation();
|
||||
}
|
||||
} else {
|
||||
writer.append("true");
|
||||
}
|
||||
|
|
|
@ -209,6 +209,10 @@ class DebugInformationWriter {
|
|||
}
|
||||
|
||||
private void writeCFG(RecordArray mapping) throws IOException {
|
||||
if (mapping == null) {
|
||||
writeUnsignedNumber(0);
|
||||
return;
|
||||
}
|
||||
writeUnsignedNumber(mapping.size());
|
||||
writeRle(mapping.cut(0));
|
||||
IntegerArray sizes = new IntegerArray(1);
|
||||
|
|
Loading…
Reference in New Issue
Block a user