Creating Wasm -> C translator

This commit is contained in:
Alexey Andreev 2016-08-25 15:31:38 +03:00
parent 199d91d28c
commit 0ac61919d5
8 changed files with 429 additions and 81 deletions

View File

@ -60,7 +60,7 @@ import org.teavm.backend.wasm.model.expression.WasmReturn;
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
import org.teavm.backend.wasm.patches.ClassPatch;
import org.teavm.backend.wasm.patches.ObjectPatch;
import org.teavm.backend.wasm.render.WasmRenderer;
import org.teavm.backend.wasm.render.WasmCRenderer;
import org.teavm.dependency.ClassDependency;
import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyListener;
@ -103,6 +103,7 @@ import org.teavm.vm.spi.TeaVMHostExtension;
public class WasmTarget implements TeaVMTarget {
private TeaVMTargetController controller;
private boolean debugging;
@Override
public void setController(TeaVMTargetController controller) {
@ -134,6 +135,14 @@ public class WasmTarget implements TeaVMTarget {
return listeners;
}
public boolean isDebugging() {
return debugging;
}
public void setDebugging(boolean debugging) {
this.debugging = debugging;
}
@Override
public void contributeDependencies(DependencyChecker dependencyChecker) {
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
@ -301,7 +310,8 @@ public class WasmTarget implements TeaVMTarget {
module.getFunctionTable().add(module.getFunctions().get(function));
}
WasmRenderer renderer = new WasmRenderer();
WasmCRenderer renderer = new WasmCRenderer();
renderer.setOutputLineNumbers(debugging);
renderer.render(module);
try {

View File

@ -31,4 +31,13 @@ class CBlock extends CLine {
public List<CLine> getLines() {
return lines;
}
@Override
void render(WasmCRenderer target) {
target.indent();
for (CLine line : lines) {
line.render(target);
}
target.outdent();
}
}

View File

@ -17,6 +17,7 @@ package org.teavm.backend.wasm.render;
import java.util.ArrayList;
import java.util.List;
import org.teavm.model.TextLocation;
class CExpression {
private String text;
@ -50,6 +51,14 @@ class CExpression {
return lines;
}
public void addLine(String text, TextLocation location) {
lines.add(new CSingleLine(text, location));
}
public void addLine(String text) {
addLine(text, null);
}
public static CExpression relocatable(String text) {
CExpression expression = new CExpression(text);
expression.setRelocatable(true);

View File

@ -16,4 +16,5 @@
package org.teavm.backend.wasm.render;
abstract class CLine {
abstract void render(WasmCRenderer target);
}

View File

@ -15,14 +15,52 @@
*/
package org.teavm.backend.wasm.render;
import java.util.Objects;
import org.teavm.model.TextLocation;
class CSingleLine extends CLine {
private String text;
private TextLocation location;
public CSingleLine(String text) {
this(text, null);
}
public CSingleLine(String text, TextLocation location) {
this.text = text;
this.location = location;
}
public String getText() {
return text;
}
public TextLocation getLocation() {
return location;
}
public void setLocation(TextLocation location) {
this.location = location;
}
@Override
void render(WasmCRenderer target) {
if (target.outputLineNumbers) {
TextLocation location = this.location;
if (location == null) {
location = target.lastReportedLocation;
}
if (location != null) {
if (!Objects.equals(target.currentFile, location.getFileName())) {
target.line("#line " + (location.getLine() - 1) + " \"" + location.getFileName() + "\"");
} else if (location.getLine() != target.currentLine) {
target.line("#line " + (location.getLine() - 1));
}
target.currentFile = location.getFileName();
target.currentLine = location.getLine() + 1;
target.lastReportedLocation = location;
}
}
target.line(text);
}
}

View File

@ -15,5 +15,187 @@
*/
package org.teavm.backend.wasm.render;
import java.util.ArrayList;
import java.util.List;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmMemorySegment;
import org.teavm.backend.wasm.model.WasmModule;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.TextLocation;
public class WasmCRenderer {
private StringBuilder out = new StringBuilder();
private int indentLevel;
String currentFile = "";
int currentLine = -1;
boolean outputLineNumbers;
TextLocation lastReportedLocation;
public boolean isOutputLineNumbers() {
return outputLineNumbers;
}
public void setOutputLineNumbers(boolean outputLineNumbers) {
this.outputLineNumbers = outputLineNumbers;
}
void indent() {
++indentLevel;
}
void outdent() {
--indentLevel;
}
void line(String line) {
for (int i = 0; i < indentLevel; ++i) {
out.append(" ");
}
out.append(line).append("\n");
}
public void render(WasmModule module) {
line("#include <inttypes.h>");
line("#include <string.h>");
line("#include <stdlib.h>");
line("#include <assert.h>");
line("");
renderFunctionDeclarations(module);
line("static int8_t *wasm_heap;");
renderFunctionTable(module);
for (WasmFunction function : module.getFunctions().values()) {
if (function.getImportName() == null) {
renderFunction(function);
}
}
line("void main() {");
indent();
renderHeap(module);
if (module.getStartFunction() != null) {
line(module.getStartFunction().getName() + "();");
}
for (WasmFunction function : module.getFunctions().values()) {
if (function.getExportName() != null && function.getExportName().equals("main")) {
line(function.getName() + "(0);");
}
}
outdent();
line("}");
}
private void renderHeap(WasmModule module) {
line("wasm_heap = malloc(" + 65535 * module.getMemorySize() + ");");
for (WasmMemorySegment segment : module.getSegments()) {
line("memcpy(wasm_heap + " + segment.getOffset() + ",");
indent();
for (int i = 0; i < segment.getLength(); i += 48) {
byte[] data = segment.getData(i, Math.min(i + 48, segment.getLength()) - i);
boolean last = i + data.length >= segment.getLength();
StringBuilder sb = new StringBuilder("\"");
for (int j = 0; j < data.length; ++j) {
byte b = data[j];
sb.append("\\x")
.append(Character.forDigit((b >>> 4) & 0xF, 16))
.append(Character.forDigit(b & 0xF, 16));
}
sb.append("\"");
if (last) {
sb.append(", " + segment.getLength() + ");");
}
line(sb.toString());
}
outdent();
}
}
private void renderFunctionTable(WasmModule module) {
line("static void *wasm_table[] = {");
if (!module.getFunctionTable().isEmpty()) {
indent();
for (int i = 0; i < module.getFunctionTable().size() - 1; ++i) {
WasmFunction function = module.getFunctionTable().get(i);
line(function.getName() + ",");
}
line(module.getFunctionTable().get(module.getFunctionTable().size() - 1).getName());
outdent();
}
line("};");
line("");
}
private void renderFunctionDeclarations(WasmModule module) {
for (WasmFunction function : module.getFunctions().values()) {
line(functionDeclaration(function) + ";");
}
}
private void renderFunction(WasmFunction function) {
line(functionDeclaration(function) + " {");
indent();
List<WasmLocal> variables = function.getLocalVariables().subList(function.getParameters().size(),
function.getLocalVariables().size());
for (WasmLocal variable : variables) {
line(WasmCRenderingVisitor.mapType(variable.getType()) + " var_" + variable.getIndex() + ";");
}
WasmCRenderingVisitor visitor = new WasmCRenderingVisitor(function.getResult(), function.getModule());
List<WasmExpression> body = function.getBody();
List<CLine> lines = new ArrayList<>();
if (!body.isEmpty()) {
for (int i = 0; i < body.size() - 1; ++i) {
visitor.setRequiredType(null);
body.get(i).acceptVisitor(visitor);
lines.addAll(visitor.getValue().getLines());
}
visitor.setRequiredType(function.getResult());
body.get(body.size() - 1).acceptVisitor(visitor);
lines.addAll(visitor.getValue().getLines());
if (visitor.getValue().getText() != null) {
lines.add(new CSingleLine(visitor.getValue().getText()));
}
}
for (CLine line : lines) {
line.render(this);
}
outdent();
line("}");
line("");
}
private String functionDeclaration(WasmFunction function) {
StringBuilder sb = new StringBuilder();
if (function.getImportName() != null) {
sb.append("extern ");
} else if (function.getExportName() == null) {
sb.append("static ");
}
sb.append(WasmCRenderingVisitor.mapType(function.getResult())).append(' ');
sb.append(function.getName()).append("(");
for (int i = 0; i < function.getParameters().size(); ++i) {
if (i > 0) {
sb.append(", ");
}
sb.append(WasmCRenderingVisitor.mapType(function.getParameters().get(i)));
sb.append(" var_" + i);
}
sb.append(")");
return sb.toString();
}
@Override
public String toString() {
return out.toString();
}
}

View File

@ -67,7 +67,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
private WasmType functionType;
private WasmModule module;
public WasmCRenderingVisitor(WasmType functionType, WasmModule module) {
WasmCRenderingVisitor(WasmType functionType, WasmModule module) {
this.functionType = functionType;
this.module = module;
}
@ -76,6 +76,10 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
return value;
}
void setRequiredType(WasmType requiredType) {
this.requiredType = requiredType;
}
@Override
public void visit(WasmBlock expression) {
BlockInfo info = new BlockInfo();
@ -99,7 +103,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
result.getLines().addAll(value.getLines());
if (info.type != null) {
if (info.temporaryVariable != null) {
result.getLines().add(new CSingleLine(info.temporaryVariable + " = " + result.getText()));
result.getLines().add(new CSingleLine(info.temporaryVariable + " = " + value.getText() + ";"));
result.setText(info.temporaryVariable);
} else {
result.setText(value.getText());
@ -110,14 +114,15 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
result.getLines().add(0, declareVariable(info.temporaryVariable, info.type));
}
if (info.label != null || expression.isLoop()) {
if (expression.isLoop()) {
List<CLine> lines = new ArrayList<>();
String header = expression.isLoop() ? "for(;;) " : "";
lines.add(new CSingleLine(info.label + ": " + header + "{"));
lines.add(new CSingleLine(getLabel(info) + ": do {"));
lines.add(new CBlock(result.getLines()));
lines.add(new CSingleLine("}"));
lines.add(new CSingleLine("} while(0);"));
result.getLines().clear();
result.getLines().addAll(lines);
} else if (info.label != null) {
result.getLines().add(new CSingleLine(info.label + ": ;"));
}
}
@ -132,9 +137,9 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32;
expression.getCondition().acceptVisitor(this);
result.getLines().addAll(value.getLines());
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine("if (" + value.getText() + ") {"));
CBlock breakBlock = new CBlock(generateBreak(expression.getResult(), expression.getTarget()));
result.addLine("if (" + value.getText() + ") {", expression.getLocation());
CBlock breakBlock = new CBlock(generateBreak(expression.getResult(), expression.getTarget(),
expression.getLocation()));
result.getLines().add(breakBlock);
result.getLines().add(new CSingleLine("}"));
@ -144,11 +149,12 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
@Override
public void visit(WasmBreak expression) {
CExpression result = new CExpression();
result.getLines().addAll(generateBreak(expression.getResult(), expression.getTarget()));
result.getLines().addAll(generateBreak(expression.getResult(), expression.getTarget(),
expression.getLocation()));
value = result;
}
private List<CLine> generateBreak(WasmExpression result, WasmBlock target) {
private List<CLine> generateBreak(WasmExpression result, WasmBlock target, TextLocation location) {
List<CLine> lines = new ArrayList<>();
BlockInfo targetInfo = blockInfoMap.get(target);
@ -156,25 +162,24 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
if (targetInfo.temporaryVariable == null) {
targetInfo.temporaryVariable = "tmp_" + temporaryIndex++;
}
if (targetInfo.label == null) {
targetInfo.label = "block_" + blockIndex++;
}
requiredType = targetInfo.type;
result.acceptVisitor(this);
lines.addAll(value.getLines());
reportLocation(result.getLocation(), lines);
lines.add(new CSingleLine(targetInfo.temporaryVariable + " = " + value.getText() + ";"));
}
reportLocation(result.getLocation(), lines);
if (target.isLoop()) {
lines.add(new CSingleLine("break " + targetInfo.label + ";"));
} else {
lines.add(new CSingleLine("continue " + targetInfo.label + ";"));
lines.add(new CSingleLine(targetInfo.temporaryVariable + " = " + value.getText() + ";",
result.getLocation()));
}
lines.add(new CSingleLine("goto " + getLabel(targetInfo) + ";", location));
return lines;
}
private String getLabel(BlockInfo blockInfo) {
if (blockInfo.label == null) {
blockInfo.label = "block_" + blockIndex++;
}
return blockInfo.label;
}
@Override
public void visit(WasmSwitch expression) {
CExpression result = new CExpression();
@ -182,24 +187,17 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = WasmType.INT32;
expression.getSelector().acceptVisitor(this);
result.getLines().addAll(value.getLines());
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine("switch (" + value.getLines() + ") {"));
result.addLine("switch (" + value.getText() + ") {", expression.getLocation());
CBlock switchBlock = new CBlock();
result.getLines().add(switchBlock);
for (int i = 0; i < expression.getTargets().size(); ++i) {
BlockInfo targetInfo = blockInfoMap.get(expression.getTargets().get(i));
if (targetInfo.label == null) {
targetInfo.label = "block_" + blockIndex++;
}
switchBlock.getLines().add(new CSingleLine("case " + i + ": break " + targetInfo.label + ";"));
switchBlock.getLines().add(new CSingleLine("case " + i + ": goto " + getLabel(targetInfo) + ";"));
}
BlockInfo defaultTargetInfo = blockInfoMap.get(expression.getDefaultTarget());
if (defaultTargetInfo.label == null) {
defaultTargetInfo.label = "block_" + blockIndex++;
}
switchBlock.getLines().add(new CSingleLine("default: break " + defaultTargetInfo.label + ";"));
switchBlock.getLines().add(new CSingleLine("default: goto " + getLabel(defaultTargetInfo) + ";"));
result.getLines().add(new CSingleLine("}"));
@ -241,17 +239,18 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
CBlock thenBlock = new CBlock();
thenBlock.getLines().addAll(thenExpression.getLines());
if (temporary != null) {
thenBlock.getLines().add(new CSingleLine(temporary + " = " + thenExpression.getText()));
thenBlock.getLines().add(new CSingleLine(temporary + " = " + thenExpression.getText() + ";"));
}
result.getLines().add(thenBlock);
if (!elseExpression.getText().isEmpty() || elseExpression.getText() != null) {
if (elseExpression.getText() != null || !elseExpression.getLines().isEmpty()) {
result.getLines().add(new CSingleLine("} else {"));
CBlock elseBlock = new CBlock();
elseBlock.getLines().addAll(elseBlock.getLines());
elseBlock.getLines().addAll(elseExpression.getLines());
if (temporary != null) {
elseBlock.getLines().add(new CSingleLine(temporary + " = " + elseExpression.getText()));
elseBlock.getLines().add(new CSingleLine(temporary + " = " + elseExpression.getText() + ";"));
}
result.getLines().add(elseBlock);
}
result.getLines().add(new CSingleLine("}"));
@ -267,11 +266,9 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
requiredType = functionType;
expression.getValue().acceptVisitor(this);
result.getLines().addAll(value.getLines());
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine("return " + value.getText() + ";"));
result.addLine("return " + value.getText() + ";", expression.getLocation());
} else {
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine("return;"));
result.addLine("return;", expression.getLocation());
}
value = result;
@ -280,8 +277,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
@Override
public void visit(WasmUnreachable expression) {
CExpression result = new CExpression();
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine("assert(false);"));
result.addLine("assert(0);", expression.getLocation());
value = result;
}
@ -317,7 +313,8 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
expression.getValue().acceptVisitor(this);
result.getLines().addAll(value.getLines());
reportLocation(expression.getLocation(), result.getLines());
result.addLine("var_" + expression.getLocal().getIndex() + " = " + value.getText() + ";",
expression.getLocation());
value = result;
}
@ -514,7 +511,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
if (expression.isRelocatable()) {
return expression;
}
String var = "tmp_" + temporaryIndex;
String var = "tmp_" + temporaryIndex++;
target.getLines().add(new CSingleLine(mapType(type) + " " + var + " = " + expression.getText() + ";"));
return CExpression.relocatable(var);
}
@ -615,7 +612,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
CExpression operand = value;
result.getLines().addAll(operand.getLines());
if (type != null && expression.getSourceType() != expression.getSourceType()) {
if (type != null && expression.getSourceType() != expression.getTargetType()) {
switch (expression.getTargetType()) {
case INT32:
if (expression.isSigned()) {
@ -652,7 +649,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
}
}
value = operand;
value = result;
}
@Override
@ -668,8 +665,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
result.setText(sb.toString());
if (type == null) {
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine(result.getText()));
result.addLine(result.getText() + ";", expression.getLocation());
result.setText(null);
}
value = result;
@ -688,19 +684,19 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
}
sb.append(mapType(expression.getParameterTypes().get(i)));
}
sb.append(") ");
sb.append(")) ");
requiredType = WasmType.INT32;
expression.getSelector().acceptVisitor(this);
value = cacheIfNeeded(WasmType.INT32, value, result);
result.getLines().addAll(value.getLines());
sb.append("wasm_table[" + result.getText() + "])(");
sb.append("wasm_table[" + value.getText() + "])(");
translateArguments(expression.getArguments(), expression.getParameterTypes(), result, sb);
sb.append(")");
result.setText(sb.toString());
if (type == null) {
reportLocation(expression.getLocation(), result.getLines());
result.getLines().add(new CSingleLine(result.getText()));
result.addLine(result.getText() + ";", expression.getLocation());
result.setText(null);
}
value = result;
@ -742,7 +738,6 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
public void visit(WasmDrop expression) {
CExpression result = new CExpression();
requiredType = null;
reportLocation(expression.getLocation(), result.getLines());
expression.getOperand().acceptVisitor(this);
result.getLines().addAll(value.getLines());
value = result;
@ -754,7 +749,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
WasmType type = requiredType;
requiredType = WasmType.INT32;
expression.getIndex();
expression.getIndex().acceptVisitor(this);
CExpression index = value;
if (type == null) {
value = index;
@ -764,19 +759,19 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
result.getLines().addAll(index.getLines());
switch (expression.getConvertFrom()) {
case INT8:
result.setText("(int32_t) (int8_t) wasm_heap[" + index + "]");
result.setText("(int32_t) (int8_t) wasm_heap[" + index.getText() + "]");
break;
case UINT8:
result.setText("(int32_t) (uint8_t) wasm_heap[" + index + "]");
result.setText("(int32_t) (uint8_t) wasm_heap[" + index.getText() + "]");
break;
case INT16:
result.setText("(int32_t) *((int16_t *) &wasm_heap[" + index + "])");
result.setText("(int32_t) *((int16_t *) &wasm_heap[" + index.getText() + "])");
break;
case UINT16:
result.setText("(int32_t) *((uint16_t *) &wasm_heap[" + index + "])");
result.setText("(int32_t) *((uint16_t *) &wasm_heap[" + index.getText() + "])");
break;
case INT32:
result.setText("*((int32_t *) &wasm_heap[" + index + "])");
result.setText("*((int32_t *) &wasm_heap[" + index.getText() + "])");
break;
}
@ -789,7 +784,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
WasmType type = requiredType;
requiredType = WasmType.INT32;
expression.getIndex();
expression.getIndex().acceptVisitor(this);
CExpression index = value;
if (type == null) {
value = index;
@ -799,25 +794,25 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
result.getLines().addAll(index.getLines());
switch (expression.getConvertFrom()) {
case INT8:
result.setText("(int64_t) (int8_t) wasm_heap[" + index + "]");
result.setText("(int64_t) (int8_t) wasm_heap[" + index.getText() + "]");
break;
case UINT8:
result.setText("(int64_t) (uint8_t) wasm_heap[" + index + "]");
result.setText("(int64_t) (uint8_t) wasm_heap[" + index.getText() + "]");
break;
case INT16:
result.setText("(int64_t) *((int16_t *) &wasm_heap[" + index + "])");
result.setText("(int64_t) *((int16_t *) &wasm_heap[" + index.getText() + "])");
break;
case UINT16:
result.setText("(int64_t) *((uint16_t *) &wasm_heap[" + index + "])");
result.setText("(int64_t) *((uint16_t *) &wasm_heap[" + index.getText() + "])");
break;
case INT32:
result.setText("(int64_t) *((int32_t *) &wasm_heap[" + index + "])");
result.setText("(int64_t) *((int32_t *) &wasm_heap[" + index.getText() + "])");
break;
case UINT32:
result.setText("(int64_t) *((uint32_t *) &wasm_heap[" + index + "])");
result.setText("(int64_t) *((uint32_t *) &wasm_heap[" + index.getText() + "])");
break;
case INT64:
result.setText("*((int64_t *) &wasm_heap[" + index + "])");
result.setText("*((int64_t *) &wasm_heap[" + index.getText() + "])");
break;
}
@ -830,7 +825,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
WasmType type = requiredType;
requiredType = WasmType.INT32;
expression.getIndex();
expression.getIndex().acceptVisitor(this);
CExpression index = value;
if (type == null) {
value = index;
@ -838,7 +833,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
}
result.getLines().addAll(index.getLines());
result.setText("*((float *) &wasm_heap[" + index + "])");
result.setText("*((float *) &wasm_heap[" + index.getText() + "])");
value = result;
}
@ -849,7 +844,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
WasmType type = requiredType;
requiredType = WasmType.INT32;
expression.getIndex();
expression.getIndex().acceptVisitor(this);
CExpression index = value;
if (type == null) {
value = index;
@ -857,42 +852,145 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
}
result.getLines().addAll(index.getLines());
result.setText("*((double *) &wasm_heap[" + index + "])");
result.setText("*((double *) &wasm_heap[" + index.getText() + "])");
value = result;
}
@Override
public void visit(WasmStoreInt32 expression) {
CExpression result = new CExpression();
requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this);
CExpression index = value;
requiredType = WasmType.INT32;
expression.getValue().acceptVisitor(this);
CExpression valueToStore = value;
result.getLines().addAll(index.getLines());
result.getLines().addAll(valueToStore.getLines());
String line;
switch (expression.getConvertTo()) {
case INT8:
line = "wasm_heap[" + index.getText() + "] = " + valueToStore.getText() + ";";
break;
case UINT8:
line = "*((uint8_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case INT16:
line = "*((int16_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case UINT16:
line = "*((uint16_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case INT32:
line = "*((int32_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
default:
throw new AssertionError(expression.getConvertTo().toString());
}
result.addLine(line, expression.getLocation());
value = result;
}
@Override
public void visit(WasmStoreInt64 expression) {
CExpression result = new CExpression();
requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this);
CExpression index = value;
requiredType = WasmType.INT64;
expression.getValue().acceptVisitor(this);
CExpression valueToStore = value;
result.getLines().addAll(index.getLines());
result.getLines().addAll(valueToStore.getLines());
String line;
switch (expression.getConvertTo()) {
case INT8:
line = "wasm_heap[" + index.getText() + "] = " + valueToStore.getText();
break;
case UINT8:
line = "*((uint8_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case INT16:
line = "*((int16_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case UINT16:
line = "*((uint16_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case INT32:
line = "*((int32_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case UINT32:
line = "*((uint32_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
case INT64:
line = "*((int64_t *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";";
break;
default:
throw new AssertionError();
}
result.addLine(line, expression.getLocation());
value = result;
}
@Override
public void visit(WasmStoreFloat32 expression) {
CExpression result = new CExpression();
requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this);
CExpression index = value;
requiredType = WasmType.FLOAT32;
expression.getValue().acceptVisitor(this);
CExpression valueToStore = value;
result.getLines().addAll(index.getLines());
result.getLines().addAll(valueToStore.getLines());
result.addLine("*((float *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";",
expression.getLocation());
value = result;
}
@Override
public void visit(WasmStoreFloat64 expression) {
CExpression result = new CExpression();
requiredType = WasmType.INT32;
expression.getIndex().acceptVisitor(this);
CExpression index = value;
requiredType = WasmType.FLOAT64;
expression.getValue().acceptVisitor(this);
CExpression valueToStore = value;
result.getLines().addAll(index.getLines());
result.getLines().addAll(valueToStore.getLines());
result.addLine("*((double *) &wasm_heap[" + index.getText() + "]) = " + valueToStore.getText() + ";",
expression.getLocation());
value = result;
}
private CLine declareVariable(String name, WasmType type) {
return new CSingleLine(mapType(type) + " " + name + ";");
}
private void reportLocation(TextLocation location, List<CLine> lines) {
if (location != null) {
lines.add(new CSingleLine("#line " + location.getFileName() + " " + location.getLine()));
}
}
private static String mapType(WasmType type) {
static String mapType(WasmType type) {
if (type == null) {
return "void";
}
@ -929,7 +1027,7 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
throw new AssertionError(type.toString());
}
static class BlockInfo {
private static class BlockInfo {
int index;
String label;
String temporaryVariable;

View File

@ -320,6 +320,7 @@ public class TeaVMTool implements BaseTeaVMTool {
private WasmTarget prepareWebAssemblyTarget() {
webAssemblyTarget = new WasmTarget();
webAssemblyTarget.setDebugging(debugInformationGenerated);
return webAssemblyTarget;
}