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 {
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);
try (OutputStream output = buildTarget.createResource(outputName);
Writer writer = new OutputStreamWriter(output, "UTF-8")) {

View File

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

View File

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