mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Refactor target API. Add ability to generate wast and C from wasm target
This commit is contained in:
parent
de4128b377
commit
9143714168
|
@ -198,8 +198,9 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget target) {
|
||||
try (Writer writer = new OutputStreamWriter(output, "UTF-8")) {
|
||||
public void emit(ListableClassHolderSource classes, BuildTarget target, String outputName) {
|
||||
try (OutputStream output = target.createResource(outputName);
|
||||
Writer writer = new OutputStreamWriter(output, "UTF-8")) {
|
||||
emit(classes, writer, target);
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException(e);
|
||||
|
|
|
@ -17,6 +17,8 @@ package org.teavm.backend.wasm;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -66,6 +68,8 @@ import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
|||
import org.teavm.backend.wasm.patches.ClassPatch;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryRenderer;
|
||||
import org.teavm.backend.wasm.render.WasmBinaryWriter;
|
||||
import org.teavm.backend.wasm.render.WasmCRenderer;
|
||||
import org.teavm.backend.wasm.render.WasmRenderer;
|
||||
import org.teavm.dependency.ClassDependency;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
|
@ -110,6 +114,8 @@ import org.teavm.vm.spi.TeaVMHostExtension;
|
|||
public class WasmTarget implements TeaVMTarget {
|
||||
private TeaVMTargetController controller;
|
||||
private boolean debugging;
|
||||
private boolean wastEmitted;
|
||||
private boolean cEmitted;
|
||||
|
||||
@Override
|
||||
public void setController(TeaVMTargetController controller) {
|
||||
|
@ -149,6 +155,22 @@ public class WasmTarget implements TeaVMTarget {
|
|||
this.debugging = debugging;
|
||||
}
|
||||
|
||||
public boolean isWastEmitted() {
|
||||
return wastEmitted;
|
||||
}
|
||||
|
||||
public void setWastEmitted(boolean wastEmitted) {
|
||||
this.wastEmitted = wastEmitted;
|
||||
}
|
||||
|
||||
public boolean isCEmitted() {
|
||||
return cEmitted;
|
||||
}
|
||||
|
||||
public void setCEmitted(boolean cEmitted) {
|
||||
this.cEmitted = cEmitted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
||||
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
||||
|
@ -189,7 +211,8 @@ public class WasmTarget implements TeaVMTarget {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget buildTarget) {
|
||||
public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName)
|
||||
throws IOException {
|
||||
WasmModule module = new WasmModule();
|
||||
WasmFunction initFunction = new WasmFunction("__start__");
|
||||
|
||||
|
@ -263,11 +286,41 @@ public class WasmTarget implements TeaVMTarget {
|
|||
WasmBinaryRenderer renderer = new WasmBinaryRenderer(writer);
|
||||
renderer.render(module);
|
||||
|
||||
try {
|
||||
try (OutputStream output = buildTarget.createResource(outputName)) {
|
||||
output.write(writer.getData());
|
||||
output.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (wastEmitted) {
|
||||
emitWast(module, buildTarget, getBaseName(outputName) + ".wast");
|
||||
}
|
||||
if (cEmitted) {
|
||||
emitC(module, buildTarget, getBaseName(outputName) + ".c");
|
||||
}
|
||||
}
|
||||
|
||||
private String getBaseName(String name) {
|
||||
int index = name.lastIndexOf('.');
|
||||
return index < 0 ? name : name.substring(0, index);
|
||||
}
|
||||
|
||||
private void emitWast(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException {
|
||||
WasmRenderer renderer = new WasmRenderer();
|
||||
renderer.setLineNumbersEmitted(debugging);
|
||||
renderer.render(module);
|
||||
try (OutputStream output = buildTarget.createResource(outputName);
|
||||
Writer writer = new OutputStreamWriter(output, "UTF-8")) {
|
||||
writer.write(renderer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException {
|
||||
WasmCRenderer renderer = new WasmCRenderer();
|
||||
renderer.setLineNumbersEmitted(debugging);
|
||||
renderer.render(module);
|
||||
try (OutputStream output = buildTarget.createResource(outputName);
|
||||
Writer writer = new OutputStreamWriter(output, "UTF-8")) {
|
||||
writer.write(renderer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class CSingleLine extends CLine {
|
|||
|
||||
@Override
|
||||
void render(WasmCRenderer target) {
|
||||
if (target.outputLineNumbers) {
|
||||
if (target.lineNumbersEmitted) {
|
||||
TextLocation location = this.location;
|
||||
if (location == null) {
|
||||
location = target.lastReportedLocation;
|
||||
|
|
|
@ -29,15 +29,15 @@ public class WasmCRenderer {
|
|||
private int indentLevel;
|
||||
String currentFile = "";
|
||||
int currentLine = -1;
|
||||
boolean outputLineNumbers;
|
||||
boolean lineNumbersEmitted;
|
||||
TextLocation lastReportedLocation;
|
||||
|
||||
public boolean isOutputLineNumbers() {
|
||||
return outputLineNumbers;
|
||||
public boolean isLineNumbersEmitted() {
|
||||
return lineNumbersEmitted;
|
||||
}
|
||||
|
||||
public void setOutputLineNumbers(boolean outputLineNumbers) {
|
||||
this.outputLineNumbers = outputLineNumbers;
|
||||
public void setLineNumbersEmitted(boolean value) {
|
||||
this.lineNumbersEmitted = value;
|
||||
}
|
||||
|
||||
void indent() {
|
||||
|
|
|
@ -45,6 +45,14 @@ public class WasmRenderer {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean isLineNumbersEmitted() {
|
||||
return visitor.lineNumbersEmitted;
|
||||
}
|
||||
|
||||
public void setLineNumbersEmitted(boolean value) {
|
||||
visitor.lineNumbersEmitted = value;
|
||||
}
|
||||
|
||||
public void render(WasmModule module) {
|
||||
visitor.open().append("module");
|
||||
renderMemory(module);
|
||||
|
|
|
@ -67,6 +67,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
private Map<WasmBlock, String> blockIdentifiers = new HashMap<>();
|
||||
private int indentLevel;
|
||||
private boolean lfDeferred;
|
||||
boolean lineNumbersEmitted;
|
||||
List<WasmSignature> signatureList = new ArrayList<>();
|
||||
Map<WasmSignature, Integer> signatureMap = new HashMap<>();
|
||||
|
||||
|
@ -97,7 +98,7 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
|||
}
|
||||
|
||||
WasmRenderingVisitor line(WasmExpression expression) {
|
||||
if (expression.getLocation() != null) {
|
||||
if (expression.getLocation() != null && lineNumbersEmitted) {
|
||||
lf().append(";; " + expression.getLocation().getFileName() + ":" + expression.getLocation().getLine());
|
||||
}
|
||||
lf().append(expression);
|
||||
|
|
|
@ -15,15 +15,12 @@
|
|||
*/
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DirectoryBuildTarget implements BuildTarget {
|
||||
private File directory;
|
||||
|
||||
|
@ -40,6 +37,6 @@ public class DirectoryBuildTarget implements BuildTarget {
|
|||
dir.mkdirs();
|
||||
}
|
||||
}
|
||||
return new FileOutputStream(new File(directory, fileName));
|
||||
return new BufferedOutputStream(new FileOutputStream(new File(directory, fileName)), 65536);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
package org.teavm.vm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -329,11 +326,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
* actual generation happens and no exceptions thrown, but you can further call
|
||||
* {@link #getProblemProvider()} to learn the build state.</p>
|
||||
*
|
||||
* @param output where to generate JavaScript. Should not be null.
|
||||
* @param buildTarget where to generate additional resources. Can be null, but if there are
|
||||
* plugins or inteceptors that generate additional resources, the build process will fail.
|
||||
* plugins or interceptors that generate additional resources, the build process will fail.
|
||||
* @param outputName name of output file within buildTarget. Should not be null.
|
||||
*/
|
||||
public void build(OutputStream output, BuildTarget buildTarget) {
|
||||
public void build(BuildTarget buildTarget, String outputName) {
|
||||
target.setController(targetController);
|
||||
|
||||
// Check dependencies
|
||||
|
@ -381,7 +378,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
|
||||
// Render
|
||||
target.emit(classSet, output, buildTarget);
|
||||
try {
|
||||
target.emit(classSet, buildTarget, outputName);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error generating output files", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
|
@ -513,13 +514,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
|
||||
public void build(File dir, String fileName) {
|
||||
try (OutputStream output = new FileOutputStream(new File(dir, fileName))) {
|
||||
build(output, new DirectoryBuildTarget(dir));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Platform does not support UTF-8", e);
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error occurred", e);
|
||||
}
|
||||
build(new DirectoryBuildTarget(dir), fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
|
@ -36,5 +36,5 @@ public interface TeaVMTarget {
|
|||
|
||||
void contributeDependencies(DependencyChecker dependencyChecker);
|
||||
|
||||
void emit(ListableClassHolderSource classes, OutputStream output, BuildTarget buildTarget);
|
||||
void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class ClassValueTest {
|
|||
TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
|
||||
vm.installPlugins();
|
||||
vm.entryPoint(new MethodReference(getClass().getName(), methodName, ValueType.VOID));
|
||||
vm.build(new ByteArrayOutputStream(), null);
|
||||
vm.build(fileName -> new ByteArrayOutputStream(), "tmp");
|
||||
if (!vm.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||
fail("Code compiled with errors:\n" + describeProblems(vm));
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ public class JSOTest {
|
|||
TeaVM vm = new TeaVMBuilder(new JavaScriptTarget()).build();
|
||||
vm.installPlugins();
|
||||
vm.entryPoint("org/teavm/metaprogramming/test", new MethodReference(JSOTest.class, methodName, void.class));
|
||||
vm.build(new ByteArrayOutputStream(), null);
|
||||
vm.build(name -> new ByteArrayOutputStream(), "tmp");
|
||||
return vm.getProblemProvider().getSevereProblems();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.teavm.tooling;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -406,44 +405,46 @@ public class TeaVMTool implements BaseTeaVMTool {
|
|||
}
|
||||
}
|
||||
targetDirectory.mkdirs();
|
||||
try (OutputStream output = new BufferedOutputStream(
|
||||
new FileOutputStream(new File(targetDirectory, getResolvedTargetFileName())), 65536)) {
|
||||
Writer writer = new OutputStreamWriter(output, "UTF-8");
|
||||
if (runtime == RuntimeCopyOperation.MERGED) {
|
||||
javaScriptTarget.add(runtimeInjector);
|
||||
}
|
||||
vm.build(output, new DirectoryBuildTarget(targetDirectory));
|
||||
if (vm.wasCancelled()) {
|
||||
log.info("Build cancelled");
|
||||
cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ProblemProvider problemProvider = vm.getProblemProvider();
|
||||
if (problemProvider.getProblems().isEmpty()) {
|
||||
log.info("Output file successfully built");
|
||||
} else if (problemProvider.getSevereProblems().isEmpty()) {
|
||||
log.info("Output file built with warnings");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
} else {
|
||||
log.info("Output file built with errors");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
}
|
||||
if (runtime == RuntimeCopyOperation.MERGED) {
|
||||
javaScriptTarget.add(runtimeInjector);
|
||||
}
|
||||
BuildTarget buildTarget = new DirectoryBuildTarget(targetDirectory);
|
||||
String outputName = getResolvedTargetFileName();
|
||||
vm.build(buildTarget, outputName);
|
||||
if (vm.wasCancelled()) {
|
||||
log.info("Build cancelled");
|
||||
cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetType == TeaVMTargetType.JAVASCRIPT) {
|
||||
ProblemProvider problemProvider = vm.getProblemProvider();
|
||||
if (problemProvider.getProblems().isEmpty()) {
|
||||
log.info("Output file successfully built");
|
||||
} else if (problemProvider.getSevereProblems().isEmpty()) {
|
||||
log.info("Output file built with warnings");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
} else {
|
||||
log.info("Output file built with errors");
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
}
|
||||
|
||||
if (targetType == TeaVMTargetType.JAVASCRIPT) {
|
||||
try (OutputStream output = buildTarget.createResource(outputName)) {
|
||||
Writer writer = new OutputStreamWriter(output, "UTF-8");
|
||||
additionalJavaScriptOutput(writer);
|
||||
}
|
||||
}
|
||||
|
||||
if (incremental) {
|
||||
programCache.flush();
|
||||
if (astCache != null) {
|
||||
astCache.flush();
|
||||
}
|
||||
cachedClassSource.flush();
|
||||
symbolTable.flush();
|
||||
fileTable.flush();
|
||||
log.info("Cache updated");
|
||||
if (incremental) {
|
||||
programCache.flush();
|
||||
if (astCache != null) {
|
||||
astCache.flush();
|
||||
}
|
||||
cachedClassSource.flush();
|
||||
symbolTable.flush();
|
||||
fileTable.flush();
|
||||
log.info("Cache updated");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TeaVMToolException("IO error occurred", e);
|
||||
|
|
|
@ -360,16 +360,14 @@ public class TeaVMTestRunner extends Runner {
|
|||
applyProperties(method.getDeclaringClass(), properties);
|
||||
vm.setProperties(properties);
|
||||
|
||||
try (OutputStream innerWriter = new FileOutputStream(outputFile)) {
|
||||
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
|
||||
Throwable.class, String.class);
|
||||
vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async();
|
||||
vm.entryPoint("extractException", exceptionMsg);
|
||||
vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
|
||||
if (!vm.getProblemProvider().getProblems().isEmpty()) {
|
||||
result.success = false;
|
||||
result.errorMessage = buildErrorMessage(vm);
|
||||
}
|
||||
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
|
||||
Throwable.class, String.class);
|
||||
vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async();
|
||||
vm.entryPoint("extractException", exceptionMsg);
|
||||
vm.build(new DirectoryBuildTarget(outputFile.getParentFile()), outputFile.getName());
|
||||
if (!vm.getProblemProvider().getProblems().isEmpty()) {
|
||||
result.success = false;
|
||||
result.errorMessage = buildErrorMessage(vm);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue
Block a user