diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 46f20bc9c..560c09fb8 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -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")) { diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java index 345f7596d..0cb8c3ebd 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderer.java @@ -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); diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java index 56af0ff40..12e2a0a90 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java @@ -71,6 +71,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor { private WasmModule module; private String[] localVariableNames; private Set 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 + ";"); }