mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Keep variable names in generated sources
This commit is contained in:
parent
ef5145d6fd
commit
cc9af93021
|
@ -60,6 +60,10 @@ class UnusedVariableEliminator extends RecursiveVisitor {
|
|||
indexes[variables[var]] = index;
|
||||
reorderedVariables.add(variableNodes[var]);
|
||||
}
|
||||
VariableNode node = variableNodes[var];
|
||||
if (node.getName() != null) {
|
||||
reorderedVariables.get(index).setName(node.getName());
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,10 +137,25 @@ public class WasmCRenderer {
|
|||
}
|
||||
|
||||
private void renderFunction(WasmFunction function) {
|
||||
line(functionDeclaration(function) + " {");
|
||||
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(),
|
||||
function.getLocalVariables().size(), function.getModule());
|
||||
|
||||
StringBuilder declaration = new StringBuilder();
|
||||
renderFunctionModifiers(declaration, function);
|
||||
declaration.append(WasmCRenderingVisitor.mapType(function.getResult())).append(' ');
|
||||
declaration.append(function.getName()).append('(');
|
||||
for (int i = 0; i < function.getParameters().size(); ++i) {
|
||||
if (i > 0) {
|
||||
declaration.append(", ");
|
||||
}
|
||||
declaration.append(WasmCRenderingVisitor.mapType(function.getParameters().get(i)));
|
||||
WasmLocal var = function.getLocalVariables().get(i);
|
||||
declaration.append(' ').append(visitor.getVariableName(var));
|
||||
}
|
||||
declaration.append(") {");
|
||||
line(declaration.toString());
|
||||
indent();
|
||||
|
||||
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(), function.getModule());
|
||||
List<WasmLocal> variables = function.getLocalVariables().subList(function.getParameters().size(),
|
||||
function.getLocalVariables().size());
|
||||
for (WasmLocal variable : variables) {
|
||||
|
@ -175,29 +190,28 @@ public class WasmCRenderer {
|
|||
|
||||
private String functionDeclaration(WasmFunction function) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (function.getImportName() != null) {
|
||||
sb.append("extern ");
|
||||
} else if (function.getExportName() == null) {
|
||||
sb.append("static ");
|
||||
}
|
||||
renderFunctionModifiers(sb, function);
|
||||
sb.append(WasmCRenderingVisitor.mapType(function.getResult())).append(' ');
|
||||
sb.append(function.getName()).append("(");
|
||||
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(), function.getModule());
|
||||
for (int i = 0; i < function.getParameters().size(); ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(WasmCRenderingVisitor.mapType(function.getParameters().get(i)));
|
||||
WasmLocal local = i < function.getLocalVariables().size()
|
||||
? function.getLocalVariables().get(i)
|
||||
: null;
|
||||
sb.append(" ").append(local != null ? visitor.getVariableName(local) : "var_" + i);
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void renderFunctionModifiers(StringBuilder sb, WasmFunction function) {
|
||||
if (function.getImportName() != null) {
|
||||
sb.append("extern ");
|
||||
} else if (function.getExportName() == null) {
|
||||
sb.append("static ");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return out.toString();
|
||||
|
|
|
@ -18,8 +18,10 @@ package org.teavm.backend.wasm.render;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmModule;
|
||||
|
@ -67,8 +69,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
private int blockIndex;
|
||||
private WasmType functionType;
|
||||
private WasmModule module;
|
||||
private String[] localVariableNames;
|
||||
private Set<String> usedVariableNames = new HashSet<>();
|
||||
|
||||
WasmCRenderingVisitor(WasmType functionType, WasmModule module) {
|
||||
WasmCRenderingVisitor(WasmType functionType, int variableCount, WasmModule module) {
|
||||
localVariableNames = new String[variableCount];
|
||||
this.functionType = functionType;
|
||||
this.module = module;
|
||||
}
|
||||
|
@ -1036,9 +1041,23 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
|||
}
|
||||
|
||||
String getVariableName(WasmLocal local) {
|
||||
if (local.getName() != null) {
|
||||
return local.getName();
|
||||
String result = localVariableNames[local.getIndex()];
|
||||
if (result == null) {
|
||||
if (local.getName() != null) {
|
||||
result = local.getName();
|
||||
} else {
|
||||
result = "localVar" + local.getIndex();
|
||||
}
|
||||
if (!usedVariableNames.add(result)) {
|
||||
String base = result;
|
||||
int suffix = 1;
|
||||
while (!usedVariableNames.add(base + suffix)) {
|
||||
++suffix;
|
||||
}
|
||||
result = base + suffix;
|
||||
}
|
||||
localVariableNames[local.getIndex()] = result;
|
||||
}
|
||||
return "var_" + local.getIndex();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class PreOptimizingClassHolderSource implements ClassHolderSource {
|
|||
return null;
|
||||
}
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
new GlobalValueNumbering().optimize(method, method.getProgram());
|
||||
new GlobalValueNumbering(true).optimize(method, method.getProgram());
|
||||
new UnusedVariableElimination().optimize(method, method.getProgram());
|
||||
}
|
||||
cache.put(name, cls);
|
||||
|
|
|
@ -34,12 +34,17 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
private Program program;
|
||||
private int currentBlockIndex;
|
||||
private DominatorTree domTree;
|
||||
private boolean namesPreserved;
|
||||
|
||||
private static class KnownValue {
|
||||
int value;
|
||||
int location;
|
||||
}
|
||||
|
||||
public GlobalValueNumbering(boolean namesPreserved) {
|
||||
this.namesPreserved = namesPreserved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean optimize(MethodReader method, Program program) {
|
||||
boolean affected = false;
|
||||
|
@ -66,28 +71,6 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
int v = stack[--top];
|
||||
currentBlockIndex = v;
|
||||
BasicBlock block = program.basicBlockAt(v);
|
||||
/*for (int i = 0; i < block.getPhis().size(); ++i) {
|
||||
Phi phi = block.getPhis().get(i);
|
||||
int sharedValue = -2;
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
int value = map[incoming.getValue().getIndex()];
|
||||
incoming.setValue(program.variableAt(value));
|
||||
if (sharedValue != -2 && sharedValue != incoming.getValue().getIndex()) {
|
||||
sharedValue = -1;
|
||||
} else {
|
||||
sharedValue = incoming.getValue().getIndex();
|
||||
}
|
||||
}
|
||||
if (sharedValue != -1) {
|
||||
if (sharedValue != -2) {
|
||||
AssignInstruction assignInsn = new AssignInstruction();
|
||||
assignInsn.setReceiver(phi.getReceiver());
|
||||
assignInsn.setAssignee(program.variableAt(sharedValue));
|
||||
block.getInstructions().add(0, assignInsn);
|
||||
}
|
||||
block.getPhis().remove(i--);
|
||||
}
|
||||
}*/
|
||||
|
||||
if (block.getExceptionVariable() != null) {
|
||||
int var = map[block.getExceptionVariable().getIndex()];
|
||||
|
@ -149,21 +132,9 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
stack[top++] = succ;
|
||||
}
|
||||
}
|
||||
|
||||
String[] debugNames = new String[program.variableCount()];
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
debugNames[i] = program.variableAt(i).getDebugName();
|
||||
program.variableAt(i).setDebugName(null);
|
||||
}
|
||||
for (int i = 0; i < map.length; ++i) {
|
||||
if (map[i] != i) {
|
||||
Variable mapVar = program.variableAt(map[i]);
|
||||
if (debugNames[i] != null && mapVar.getDebugName() == null) {
|
||||
mapVar.setDebugName(debugNames[i]);
|
||||
}
|
||||
program.deleteVariable(i);
|
||||
} else {
|
||||
program.variableAt(i).setDebugName(debugNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,19 +145,38 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
|
||||
private void bind(int var, String value) {
|
||||
String name = program.variableAt(map[var]).getDebugName();
|
||||
if (name == null) {
|
||||
if (name == null || namesPreserved) {
|
||||
name = "";
|
||||
}
|
||||
|
||||
KnownValue known = knownValues.get(name + ":" + value);
|
||||
if (known != null && domTree.dominates(known.location, currentBlockIndex) && known.value != var) {
|
||||
if (known == null) {
|
||||
known = knownValues.get(":" + value);
|
||||
}
|
||||
boolean namesCompatible = !namesPreserved;
|
||||
if (!namesCompatible && known != null) {
|
||||
String knownName = program.variableAt(known.value).getDebugName();
|
||||
if (knownName == null) {
|
||||
knownName = "";
|
||||
}
|
||||
namesCompatible = knownName.isEmpty() || name.isEmpty() || knownName.equals(name);
|
||||
}
|
||||
if (known != null && domTree.dominates(known.location, currentBlockIndex) && known.value != var
|
||||
&& namesCompatible) {
|
||||
eliminate = true;
|
||||
map[var] = known.value;
|
||||
if (!name.isEmpty()) {
|
||||
program.variableAt(known.value).setDebugName(name);
|
||||
knownValues.put(name + ":" + value, known);
|
||||
}
|
||||
} else {
|
||||
known = new KnownValue();
|
||||
known.location = currentBlockIndex;
|
||||
known.value = var;
|
||||
knownValues.put(name + ":" + value, known);
|
||||
if (!name.isEmpty()) {
|
||||
knownValues.put(":" + value, known);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,6 +488,16 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
|
||||
@Override
|
||||
public void visit(AssignInstruction insn) {
|
||||
if (namesPreserved) {
|
||||
if (insn.getReceiver().getDebugName() != null && insn.getAssignee().getDebugName() != null) {
|
||||
if (!insn.getAssignee().getDebugName().equals(insn.getReceiver().getDebugName())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (insn.getReceiver().getDebugName() != null) {
|
||||
insn.getAssignee().setDebugName(insn.getReceiver().getDebugName());
|
||||
}
|
||||
map[insn.getReceiver().getIndex()] = map[insn.getAssignee().getIndex()];
|
||||
eliminate = true;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.model.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import org.teavm.common.IntegerArray;
|
||||
|
@ -23,11 +24,12 @@ import org.teavm.common.MutableGraphNode;
|
|||
|
||||
class GraphColorer {
|
||||
public void colorize(List<MutableGraphNode> graph, int[] colors) {
|
||||
colorize(graph, colors, new int[graph.size()]);
|
||||
colorize(graph, colors, new int[graph.size()], new String[graph.size()]);
|
||||
}
|
||||
|
||||
public void colorize(List<MutableGraphNode> graph, int[] colors, int[] categories) {
|
||||
public void colorize(List<MutableGraphNode> graph, int[] colors, int[] categories, String[] names) {
|
||||
IntegerArray colorCategories = new IntegerArray(graph.size());
|
||||
List<String> colorNames = new ArrayList<>();
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
int color = colors[i];
|
||||
if (colors[i] < 0) {
|
||||
|
@ -36,7 +38,11 @@ class GraphColorer {
|
|||
while (colorCategories.size() <= color) {
|
||||
colorCategories.add(-1);
|
||||
}
|
||||
while (colorNames.size() <= color) {
|
||||
colorNames.add(null);
|
||||
}
|
||||
colorCategories.set(color, categories[i]);
|
||||
colorNames.set(color, names[i]);
|
||||
}
|
||||
BitSet usedColors = new BitSet();
|
||||
for (int v : getOrdering(graph)) {
|
||||
|
@ -56,11 +62,19 @@ class GraphColorer {
|
|||
color = usedColors.nextClearBit(color);
|
||||
while (colorCategories.size() <= color) {
|
||||
colorCategories.add(-1);
|
||||
colorNames.add(null);
|
||||
}
|
||||
int category = colorCategories.get(color);
|
||||
if (category < 0 || category == categories[v]) {
|
||||
String name = colorNames.get(color);
|
||||
if ((category < 0 || category == categories[v])
|
||||
&& (name == null || names[v] == null || name.equals(names[v]))) {
|
||||
colors[v] = color;
|
||||
colorCategories.set(color, categories[v]);
|
||||
if (names[v] != null) {
|
||||
colorNames.set(color, names[v]);
|
||||
} else {
|
||||
names[v] = name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++color;
|
||||
|
|
|
@ -67,13 +67,33 @@ public class RegisterAllocator {
|
|||
maxClass = Math.max(maxClass, cls + 1);
|
||||
}
|
||||
int[] categories = getVariableCategories(program, method.getReference());
|
||||
String[] names = getVariableNames(program);
|
||||
int[] classCategories = new int[maxClass];
|
||||
String[] classNames = new String[maxClass];
|
||||
for (int i = 0; i < categories.length; ++i) {
|
||||
classCategories[classArray[i]] = categories[i];
|
||||
classNames[classArray[i]] = names[i];
|
||||
}
|
||||
colorer.colorize(interferenceGraph, colors, classCategories);
|
||||
colorer.colorize(interferenceGraph, colors, classCategories, classNames);
|
||||
|
||||
int maxColor = 0;
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
program.variableAt(i).setRegister(colors[i]);
|
||||
maxColor = Math.max(maxClass, colors[i]);
|
||||
}
|
||||
|
||||
String[] namesByRegister = new String[maxColor];
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
if (var.getDebugName() != null && var.getRegister() >= 0) {
|
||||
namesByRegister[var.getRegister()] = var.getDebugName();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
if (var.getRegister() >= 0) {
|
||||
var.setDebugName(namesByRegister[var.getRegister()]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
|
@ -95,6 +115,14 @@ public class RegisterAllocator {
|
|||
return categories;
|
||||
}
|
||||
|
||||
private String[] getVariableNames(ProgramReader program) {
|
||||
String[] names = new String[program.variableCount()];
|
||||
for (int i = 0; i < names.length; ++i) {
|
||||
names[i] = program.variableAt(i).getDebugName();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
private static void joinClassNodes(List<MutableGraphNode> graph, DisjointSet classes) {
|
||||
int sz = graph.size();
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
|
@ -257,13 +285,15 @@ public class RegisterAllocator {
|
|||
BasicBlock block = program.basicBlockAt(i);
|
||||
mapper.apply(block);
|
||||
}
|
||||
String[] originalNames = new String[program.variableCount()];
|
||||
String[] originalNames = getVariableNames(program);
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
originalNames[i] = var.getDebugName();
|
||||
program.variableAt(i).setDebugName(null);
|
||||
}
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
program.variableAt(varMap[i]).setDebugName(originalNames[i]);
|
||||
Variable var = program.variableAt(varMap[i]);
|
||||
if (originalNames[i] != null) {
|
||||
var.setDebugName(originalNames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -375,7 +375,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
}
|
||||
|
||||
removeDebugNames(classSet);
|
||||
optimize(classSet);
|
||||
if (wasCancelled()) {
|
||||
return;
|
||||
|
@ -451,25 +450,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
}
|
||||
|
||||
private void removeDebugNames(ListableClassHolderSource classes) {
|
||||
if (optimizationLevel == TeaVMOptimizationLevel.SIMPLE) {
|
||||
return;
|
||||
}
|
||||
for (String className : classes.getClassNames()) {
|
||||
ClassHolder cls = classes.get(className);
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getProgram() != null) {
|
||||
for (int i = 0; i < method.getProgram().variableCount(); ++i) {
|
||||
method.getProgram().variableAt(i).setDebugName(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wasCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void optimize(ListableClassHolderSource classSource) {
|
||||
for (String className : classSource.getClassNames()) {
|
||||
ClassHolder cls = classSource.get(className);
|
||||
|
@ -521,7 +501,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
optimizations.add(new LoopInversion());
|
||||
optimizations.add(new LoopInvariantMotion());
|
||||
}
|
||||
optimizations.add(new GlobalValueNumbering());
|
||||
optimizations.add(new GlobalValueNumbering(optimizationLevel == TeaVMOptimizationLevel.SIMPLE));
|
||||
if (optimizationLevel.ordinal() >= TeaVMOptimizationLevel.ADVANCED.ordinal()) {
|
||||
optimizations.add(new ConstantConditionElimination());
|
||||
optimizations.add(new RedundantJumpElimination());
|
||||
|
|
|
@ -64,6 +64,8 @@ public final class TeaVMRunner {
|
|||
.create("m"));
|
||||
options.addOption(OptionBuilder
|
||||
.withDescription("optimization level (1-3)")
|
||||
.hasArg()
|
||||
.withArgName("number")
|
||||
.create("O"));
|
||||
options.addOption(OptionBuilder
|
||||
.withArgName("separate|merge|none")
|
||||
|
|
Loading…
Reference in New Issue
Block a user