WASM: add flag that allows to insert assertions before each memory access in C code

This commit is contained in:
Alexey Andreev 2016-09-19 22:34:16 +03:00
parent 033e57e7e7
commit fcf0394214
3 changed files with 51 additions and 10 deletions

View File

@ -375,7 +375,8 @@ public class WasmTarget implements TeaVMTarget {
private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException { private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException {
WasmCRenderer renderer = new WasmCRenderer(); WasmCRenderer renderer = new WasmCRenderer();
//renderer.setLineNumbersEmitted(debugging); renderer.setLineNumbersEmitted(Boolean.parseBoolean(System.getProperty("wasm.c.lineNumbers", "false")));
renderer.setMemoryAccessChecked(Boolean.parseBoolean(System.getProperty("wasm.c.assertMemory", "false")));
renderer.render(module); renderer.render(module);
try (OutputStream output = buildTarget.createResource(outputName); try (OutputStream output = buildTarget.createResource(outputName);
Writer writer = new OutputStreamWriter(output, "UTF-8")) { Writer writer = new OutputStreamWriter(output, "UTF-8")) {

View File

@ -30,6 +30,7 @@ public class WasmCRenderer {
String currentFile = ""; String currentFile = "";
int currentLine = -1; int currentLine = -1;
boolean lineNumbersEmitted; boolean lineNumbersEmitted;
boolean memoryAccessChecked;
TextLocation lastReportedLocation; TextLocation lastReportedLocation;
public boolean isLineNumbersEmitted() { public boolean isLineNumbersEmitted() {
@ -40,6 +41,14 @@ public class WasmCRenderer {
this.lineNumbersEmitted = value; this.lineNumbersEmitted = value;
} }
public boolean isMemoryAccessChecked() {
return memoryAccessChecked;
}
public void setMemoryAccessChecked(boolean memoryAccessChecked) {
this.memoryAccessChecked = memoryAccessChecked;
}
void indent() { void indent() {
++indentLevel; ++indentLevel;
} }
@ -141,6 +150,7 @@ public class WasmCRenderer {
private void renderFunction(WasmFunction function) { private void renderFunction(WasmFunction function) {
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(), WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(),
function.getLocalVariables().size(), function.getModule()); function.getLocalVariables().size(), function.getModule());
visitor.setMemoryAccessChecked(memoryAccessChecked);
StringBuilder declaration = new StringBuilder(); StringBuilder declaration = new StringBuilder();
renderFunctionModifiers(declaration, function); renderFunctionModifiers(declaration, function);

View File

@ -71,6 +71,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
private WasmModule module; private WasmModule module;
private String[] localVariableNames; private String[] localVariableNames;
private Set<String> usedVariableNames = new HashSet<>(); private Set<String> usedVariableNames = new HashSet<>();
private boolean memoryAccessChecked;
WasmCRenderingVisitor(WasmType functionType, int variableCount, WasmModule module) { WasmCRenderingVisitor(WasmType functionType, int variableCount, WasmModule module) {
localVariableNames = new String[variableCount]; localVariableNames = new String[variableCount];
@ -78,6 +79,14 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
this.module = module; this.module = module;
} }
public boolean isMemoryAccessChecked() {
return memoryAccessChecked;
}
public void setMemoryAccessChecked(boolean memoryAccessChecked) {
this.memoryAccessChecked = memoryAccessChecked;
}
public CExpression getValue() { public CExpression getValue() {
return value; return value;
} }
@ -699,8 +708,8 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getSelector().acceptVisitor(this); expression.getSelector().acceptVisitor(this);
value = cacheIfNeeded(WasmType.INT32, value, result);
result.getLines().addAll(value.getLines()); result.getLines().addAll(value.getLines());
value = cacheIfNeeded(WasmType.INT32, value, result);
sb.append("wasm_table[" + value.getText() + "])("); sb.append("wasm_table[" + value.getText() + "])(");
translateArguments(expression.getArguments(), expression.getParameterTypes(), result, sb); translateArguments(expression.getArguments(), expression.getParameterTypes(), result, sb);
sb.append(")"); sb.append(")");
@ -761,7 +770,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
if (type == null) { if (type == null) {
value = index; value = index;
return; return;
@ -796,7 +805,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
if (type == null) { if (type == null) {
value = index; value = index;
return; return;
@ -837,7 +846,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
if (type == null) { if (type == null) {
value = index; value = index;
return; return;
@ -856,7 +865,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
if (type == null) { if (type == null) {
value = index; value = index;
return; return;
@ -874,7 +883,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
@ -914,7 +923,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
requiredType = WasmType.INT64; requiredType = WasmType.INT64;
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
@ -961,7 +970,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
requiredType = WasmType.FLOAT32; requiredType = WasmType.FLOAT32;
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
@ -982,7 +991,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32; requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this); expression.getIndex().acceptVisitor(this);
CExpression index = value; CExpression index = checkAddress(value);
requiredType = WasmType.FLOAT64; requiredType = WasmType.FLOAT64;
expression.getValue().acceptVisitor(this); expression.getValue().acceptVisitor(this);
@ -997,6 +1006,27 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
value = result; value = result;
} }
private CExpression checkAddress(CExpression index) {
if (!memoryAccessChecked) {
return index;
}
CExpression checked = new CExpression();
checked.getLines().addAll(index.getLines());
String var;
if (!index.isRelocatable()) {
var = "tmp_" + temporaryIndex++;
checked.addLine("int32_t " + var + " = " + index.getText() + ";");
} else {
var = index.getText();
}
checked.addLine("assert(" + var + " < " + module.getMemorySize() * 65536 + ");");
checked.setText(var);
checked.setRelocatable(index.isRelocatable());
return checked;
}
private CLine declareVariable(String name, WasmType type) { private CLine declareVariable(String name, WasmType type) {
return new CSingleLine(mapType(type) + " " + name + ";"); return new CSingleLine(mapType(type) + " " + name + ";");
} }