Fixes bugs with variable debug information tracking

This commit is contained in:
konsoletyper 2014-08-06 18:12:50 +04:00
parent cbe2ccb499
commit 36d76885a7
6 changed files with 75 additions and 91 deletions

View File

@ -56,7 +56,8 @@ public class TeaVMRunner {
.create());
options.addOption(OptionBuilder
.withDescription("causes TeaVM to log bytecode")
.create("logbytecode"));
.withLongOpt("logbytecode")
.create());
options.addOption(OptionBuilder
.withDescription("Generate debug information")
.withLongOpt("debug")

View File

@ -31,16 +31,14 @@ public class InstructionStringifier implements InstructionReader {
this.sb = sb;
}
public InstructionLocation getLocation() {
return location;
}
@Override
public void location(InstructionLocation location) {
if (this.location != location) {
if (location != null) {
sb.append("at " + (location.getFileName() != null ? location.getFileName() : "<unknown>") + ":" +
(location.getLine() >= 0 ? String.valueOf(location.getLine()) : "<unknown>"));
}
this.location = location;
}
}
@Override
public void nop() {

View File

@ -26,6 +26,14 @@ public class ListingBuilder {
public String buildListing(ProgramReader program, String prefix) {
StringBuilder sb = new StringBuilder();
InstructionStringifier stringifier = new InstructionStringifier(sb);
for (int i = 0; i < program.variableCount(); ++i) {
sb.append(prefix).append("var @").append(i);
VariableReader var = program.variableAt(i);
if (var.getDebugName() != null) {
sb.append(" as ").append(var.getDebugName());
}
sb.append('\n');
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlockReader block = program.basicBlockAt(i);
sb.append(prefix).append("$").append(i).append(":\n");

View File

@ -20,7 +20,6 @@ import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.InstructionTransitionExtractor;
/**
@ -50,8 +49,7 @@ public class ProgramParser implements VariableDebugInformation {
private boolean lineNumberChanged;
private InstructionLocation lastInsnLocation;
private Map<Integer, List<LocalVariableNode>> localVariableMap = new HashMap<>();
private Map<Instruction, String> variableDebugNames = new HashMap<>();
private Map<Integer, String> parameterNames = new HashMap<>();
private Map<Instruction, Map<Integer, String>> variableDebugNames = new HashMap<>();
private static class Step {
public final int source;
@ -117,32 +115,11 @@ public class ProgramParser implements VariableDebugInformation {
}
int signatureVars = countSignatureVariables(method.desc);
while (program.variableCount() <= signatureVars) {
program.createVariable(getVariableDebugName(program.variableCount(), 0));
}
for (int i = 0; i <= signatureVars; ++i) {
parameterNames.put(i, getVariableDebugName(i, 0));
program.createVariable(null);
}
return program;
}
private String getVariableDebugName(int var, int location) {
if (var < 0) {
return null;
}
List<LocalVariableNode> nodes = localVariableMap.get(var);
if (nodes == null) {
return null;
}
for (LocalVariableNode node : nodes) {
int start = labelIndexes.get(node.start.getLabel());
int end = labelIndexes.get(node.end.getLabel());
if (location >= start && location < end) {
return node.name;
}
}
return null;
}
private int countSignatureVariables(String desc) {
int count = 1;
for (Type paramType : Type.getArgumentTypes(desc)) {
@ -185,13 +162,9 @@ public class ProgramParser implements VariableDebugInformation {
}
@Override
public String getDefinitionDebugName(Instruction insn) {
return variableDebugNames.get(insn);
}
@Override
public String getParameterDebugName(int index) {
return parameterNames.get(index);
public Map<Integer, String> getDebugNames(Instruction insn) {
Map<Integer, String> map = variableDebugNames.get(insn);
return map != null ? Collections.unmodifiableMap(map) : Collections.<Integer, String>emptyMap();
}
private void prepare(MethodNode method) {
@ -213,10 +186,11 @@ public class ProgramParser implements VariableDebugInformation {
}
}
for (LocalVariableNode localVar : method.localVariables) {
List<LocalVariableNode> vars = localVariableMap.get(localVar.index);
int location = labelIndexes.get(localVar.start.getLabel());
List<LocalVariableNode> vars = localVariableMap.get(location);
if (vars == null) {
vars = new ArrayList<>();
localVariableMap.put(localVar.index, vars);
localVariableMap.put(location, vars);
}
vars.add(localVar);
}
@ -293,24 +267,8 @@ public class ProgramParser implements VariableDebugInformation {
}
private void assemble() {
DefinitionExtractor defExtractor = new DefinitionExtractor();
for (int i = 0; i < targetInstructions.size(); ++i) {
List<Instruction> instructionList = targetInstructions.get(i);
if (instructionList == null) {
continue;
}
for (Instruction insn : instructionList) {
insn.acceptVisitor(defExtractor);
for (Variable var : defExtractor.getDefinedVariables()) {
String debugName = getVariableDebugName(var.getIndex() - minLocal, i);
if (debugName != null) {
variableDebugNames.put(insn, debugName);
}
}
}
}
BasicBlock basicBlock = null;
Map<Integer, String> accumulatedDebugNames = new HashMap<>();
for (int i = 0; i < basicBlocks.size(); ++i) {
BasicBlock newBasicBlock = basicBlocks.get(i);
if (newBasicBlock != null) {
@ -320,8 +278,24 @@ public class ProgramParser implements VariableDebugInformation {
basicBlock.getInstructions().add(insn);
}
basicBlock = newBasicBlock;
if (!basicBlock.getInstructions().isEmpty()) {
Map<Integer, String> debugNames = new HashMap<>(accumulatedDebugNames);
variableDebugNames.put(basicBlock.getInstructions().get(0), debugNames);
}
}
List<Instruction> builtInstructions = targetInstructions.get(i);
List<LocalVariableNode> localVarNodes = localVariableMap.get(i);
if (localVarNodes != null) {
if (builtInstructions == null || builtInstructions.isEmpty()) {
builtInstructions = Arrays.<Instruction>asList(new EmptyInstruction());
}
Map<Integer, String> debugNames = new HashMap<>();
variableDebugNames.put(builtInstructions.get(0), debugNames);
for (LocalVariableNode localVar : localVarNodes) {
debugNames.put(localVar.index + minLocal, localVar.name);
}
accumulatedDebugNames.putAll(debugNames);
}
if (builtInstructions != null) {
basicBlock.getInstructions().addAll(builtInstructions);
}

View File

@ -39,6 +39,7 @@ public class SSATransformer {
private int[][] phiIndexMap;
private ValueType[] arguments;
private VariableDebugInformation variableDebugInfo;
private Map<Integer, String> variableDebugMap = new HashMap<>();
public void transformToSSA(Program program, VariableDebugInformation variableDebugInfo, ValueType[] arguments) {
if (program.basicBlockCount() == 0) {
@ -47,6 +48,7 @@ public class SSATransformer {
this.program = program;
this.variableDebugInfo = variableDebugInfo;
this.arguments = arguments;
variableDebugMap.clear();
cfg = ProgramUtils.buildControlFlowGraphWithoutTryCatch(program);
domTree = GraphUtils.buildDominatorTree(cfg);
domFrontiers = new int[cfg.size()][];
@ -57,9 +59,6 @@ public class SSATransformer {
phiMap[i] = new Phi[program.variableCount()];
phiIndexMap[i] = new int[program.variableCount()];
}
for (int i = 0; i < program.variableCount(); ++i) {
program.variableAt(i).setDebugName(variableDebugInfo.getParameterDebugName(i));
}
applySignature();
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
estimatePhis();
@ -160,6 +159,7 @@ public class SSATransformer {
specialPhis.get(currentBlock.getIndex()).add(phi);
}
for (Instruction insn : currentBlock.getInstructions()) {
variableDebugMap.putAll(variableDebugInfo.getDebugNames(insn));
insn.acceptVisitor(consumer);
}
int[] successors = domGraph.outgoingEdges(currentBlock.getIndex());
@ -216,8 +216,8 @@ public class SSATransformer {
}
}
private Variable define(Variable var, String debugName) {
Variable result = program.createVariable(debugName);
private Variable define(Variable var) {
Variable result = program.createVariable(null);
variableMap[var.getIndex()] = result;
return result;
}
@ -227,6 +227,10 @@ public class SSATransformer {
if (mappedVar == null) {
throw new AssertionError();
}
String debugName = variableDebugMap.get(var.getIndex());
if (debugName != null) {
mappedVar.setDebugName(debugName);
}
return mappedVar;
}
@ -237,56 +241,56 @@ public class SSATransformer {
@Override
public void visit(ClassConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(NullConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(IntegerConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(LongConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(FloatConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(DoubleConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(StringConstantInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(BinaryInstruction insn) {
insn.setFirstOperand(use(insn.getFirstOperand()));
insn.setSecondOperand(use(insn.getSecondOperand()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(NegateInstruction insn) {
insn.setOperand(use(insn.getOperand()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(AssignInstruction insn) {
insn.setAssignee(use(insn.getAssignee()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -324,12 +328,12 @@ public class SSATransformer {
@Override
public void visit(ConstructArrayInstruction insn) {
insn.setSize(use(insn.getSize()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(ConstructInstruction insn) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -338,7 +342,7 @@ public class SSATransformer {
for (int i = 0; i < dimensions.size(); ++i) {
dimensions.set(i, use(dimensions.get(i)));
}
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -346,7 +350,7 @@ public class SSATransformer {
if (insn.getInstance() != null) {
insn.setInstance(use(insn.getInstance()));
}
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -361,7 +365,7 @@ public class SSATransformer {
public void visit(GetElementInstruction insn) {
insn.setArray(use(insn.getArray()));
insn.setIndex(use(insn.getIndex()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -381,50 +385,50 @@ public class SSATransformer {
insn.setInstance(use(insn.getInstance()));
}
if (insn.getReceiver() != null) {
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
}
@Override
public void visit(IsInstanceInstruction insn) {
insn.setValue(use(insn.getValue()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(CastInstruction insn) {
insn.setValue(use(insn.getValue()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(CastNumberInstruction insn) {
insn.setValue(use(insn.getValue()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(CastIntegerInstruction insn) {
insn.setValue(use(insn.getValue()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(ArrayLengthInstruction insn) {
insn.setArray(use(insn.getArray()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(UnwrapArrayInstruction insn) {
insn.setArray(use(insn.getArray()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
public void visit(CloneArrayInstruction insn) {
insn.setArray(use(insn.getArray()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
@Override
@ -434,7 +438,7 @@ public class SSATransformer {
@Override
public void visit(NullCheckInstruction insn) {
insn.setValue(use(insn.getValue()));
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
insn.setReceiver(define(insn.getReceiver()));
}
};
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.parsing;
import java.util.Map;
import org.teavm.model.Instruction;
/**
@ -22,7 +23,5 @@ import org.teavm.model.Instruction;
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface VariableDebugInformation {
String getDefinitionDebugName(Instruction insn);
String getParameterDebugName(int index);
Map<Integer, String> getDebugNames(Instruction insn);
}