mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fixes bugs with variable debug information tracking
This commit is contained in:
parent
cbe2ccb499
commit
36d76885a7
|
@ -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")
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user