mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
C: generate '#line' preprocessor directive
This commit is contained in:
parent
7a99258cab
commit
0003ed0bb2
|
@ -144,6 +144,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
private Characteristics characteristics;
|
private Characteristics characteristics;
|
||||||
private Set<MethodReference> asyncMethods;
|
private Set<MethodReference> asyncMethods;
|
||||||
private boolean incremental;
|
private boolean incremental;
|
||||||
|
private boolean lineNumbersGenerated;
|
||||||
private StringPool stringPool;
|
private StringPool stringPool;
|
||||||
|
|
||||||
public CTarget() {
|
public CTarget() {
|
||||||
|
@ -162,6 +163,10 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
this.incremental = incremental;
|
this.incremental = incremental;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLineNumbersGenerated(boolean lineNumbersGenerated) {
|
||||||
|
this.lineNumbersGenerated = lineNumbersGenerated;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClassHolderTransformer> getTransformers() {
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
|
@ -332,8 +337,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
controller.getDependencyInfo(), stringPool, nameProvider, controller.getDiagnostics(), classes,
|
controller.getDependencyInfo(), stringPool, nameProvider, controller.getDiagnostics(), classes,
|
||||||
intrinsics, generators, asyncMethods::contains, buildTarget, incremental);
|
intrinsics, generators, asyncMethods::contains, buildTarget, incremental);
|
||||||
|
|
||||||
BufferedCodeWriter runtimeWriter = new BufferedCodeWriter();
|
BufferedCodeWriter runtimeWriter = new BufferedCodeWriter(false);
|
||||||
BufferedCodeWriter runtimeHeaderWriter = new BufferedCodeWriter();
|
BufferedCodeWriter runtimeHeaderWriter = new BufferedCodeWriter(false);
|
||||||
emitResource(runtimeWriter, "runtime.c");
|
emitResource(runtimeWriter, "runtime.c");
|
||||||
|
|
||||||
runtimeHeaderWriter.println("#pragma once");
|
runtimeHeaderWriter.println("#pragma once");
|
||||||
|
@ -393,8 +398,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
classGenerator.prepare(classes);
|
classGenerator.prepare(classes);
|
||||||
|
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(lineNumbersGenerated);
|
||||||
BufferedCodeWriter headerWriter = new BufferedCodeWriter();
|
BufferedCodeWriter headerWriter = new BufferedCodeWriter(false);
|
||||||
ClassHolder cls = classes.get(className);
|
ClassHolder cls = classes.get(className);
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
classGenerator.generateClass(writer, headerWriter, cls);
|
classGenerator.generateClass(writer, headerWriter, cls);
|
||||||
|
@ -408,8 +413,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
BufferedCodeWriter headerWriter = new BufferedCodeWriter();
|
BufferedCodeWriter headerWriter = new BufferedCodeWriter(false);
|
||||||
classGenerator.generateType(writer, headerWriter, type);
|
classGenerator.generateType(writer, headerWriter, type);
|
||||||
String name = ClassGenerator.fileName(type);
|
String name = ClassGenerator.fileName(type);
|
||||||
OutputFileUtil.write(writer, name + ".c", buildTarget);
|
OutputFileUtil.write(writer, name + ".c", buildTarget);
|
||||||
|
@ -451,8 +456,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
|
|
||||||
private void generateCallSites(BuildTarget buildTarget, GenerationContext context,
|
private void generateCallSites(BuildTarget buildTarget, GenerationContext context,
|
||||||
Collection<? extends String> classNames) throws IOException {
|
Collection<? extends String> classNames) throws IOException {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
BufferedCodeWriter headerWriter = new BufferedCodeWriter();
|
BufferedCodeWriter headerWriter = new BufferedCodeWriter(false);
|
||||||
|
|
||||||
IncludeManager includes = new SimpleIncludeManager(writer);
|
IncludeManager includes = new SimpleIncludeManager(writer);
|
||||||
includes.init("callsites.c");
|
includes.init("callsites.c");
|
||||||
|
@ -491,8 +496,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateStrings(BuildTarget buildTarget, StringPool stringPool) throws IOException {
|
private void generateStrings(BuildTarget buildTarget, StringPool stringPool) throws IOException {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
BufferedCodeWriter headerWriter = new BufferedCodeWriter();
|
BufferedCodeWriter headerWriter = new BufferedCodeWriter(false);
|
||||||
|
|
||||||
headerWriter.println("#pragma once");
|
headerWriter.println("#pragma once");
|
||||||
headerWriter.println("#include \"runtime.h\"");
|
headerWriter.println("#include \"runtime.h\"");
|
||||||
|
@ -588,7 +593,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
|
|
||||||
private void generateMainFile(GenerationContext context, ListableClassHolderSource classes,
|
private void generateMainFile(GenerationContext context, ListableClassHolderSource classes,
|
||||||
List<? extends ValueType> types, BuildTarget buildTarget) throws IOException {
|
List<? extends ValueType> types, BuildTarget buildTarget) throws IOException {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
IncludeManager includes = new SimpleIncludeManager(writer);
|
IncludeManager includes = new SimpleIncludeManager(writer);
|
||||||
includes.init("main.c");
|
includes.init("main.c");
|
||||||
includes.includePath("runtime.h");
|
includes.includePath("runtime.h");
|
||||||
|
@ -601,7 +606,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
|
|
||||||
private void generateAllFile(ListableClassHolderSource classes, List<? extends ValueType> types,
|
private void generateAllFile(ListableClassHolderSource classes, List<? extends ValueType> types,
|
||||||
BuildTarget buildTarget) throws IOException {
|
BuildTarget buildTarget) throws IOException {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
IncludeManager includes = new SimpleIncludeManager(writer);
|
IncludeManager includes = new SimpleIncludeManager(writer);
|
||||||
includes.init("all.c");
|
includes.init("all.c");
|
||||||
includes.includePath("runtime.c");
|
includes.includePath("runtime.c");
|
||||||
|
|
|
@ -18,18 +18,24 @@ package org.teavm.backend.c.generate;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BufferedCodeWriter extends CodeWriter {
|
public class BufferedCodeWriter extends CodeWriter {
|
||||||
private List<Fragment> fragments = new ArrayList<>();
|
private List<Fragment> fragments = new ArrayList<>();
|
||||||
private int currentIndent;
|
private int currentIndent;
|
||||||
private int lastIndent;
|
private int lastIndent;
|
||||||
private StringBuilder buffer = new StringBuilder();
|
private StringBuilder buffer = new StringBuilder();
|
||||||
|
private boolean lineNumbersEmitted;
|
||||||
|
private String lastFileName;
|
||||||
|
private int lastLineNumber;
|
||||||
|
private boolean locationDirty;
|
||||||
|
|
||||||
public BufferedCodeWriter() {
|
public BufferedCodeWriter(boolean lineNumbersEmitted) {
|
||||||
|
this.lineNumbersEmitted = lineNumbersEmitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(PrintWriter writer) {
|
public void writeTo(PrintWriter writer, String fileName) {
|
||||||
WriterWithContext writerWithContext = new WriterWithContext(writer);
|
WriterWithContext writerWithContext = new WriterWithContext(writer, fileName);
|
||||||
for (Fragment fragment : fragments) {
|
for (Fragment fragment : fragments) {
|
||||||
fragment.writeTo(writerWithContext);
|
fragment.writeTo(writerWithContext);
|
||||||
}
|
}
|
||||||
|
@ -38,8 +44,12 @@ public class BufferedCodeWriter extends CodeWriter {
|
||||||
@Override
|
@Override
|
||||||
public CodeWriter fragment() {
|
public CodeWriter fragment() {
|
||||||
flush();
|
flush();
|
||||||
BufferedCodeWriter innerWriter = new BufferedCodeWriter();
|
BufferedCodeWriter innerWriter = new BufferedCodeWriter(lineNumbersEmitted);
|
||||||
|
innerWriter.lastFileName = lastFileName;
|
||||||
|
innerWriter.lastLineNumber = lastLineNumber;
|
||||||
|
innerWriter.locationDirty = locationDirty;
|
||||||
fragments.add(new InnerWriterFragment(innerWriter.fragments));
|
fragments.add(new InnerWriterFragment(innerWriter.fragments));
|
||||||
|
locationDirty = true;
|
||||||
return innerWriter;
|
return innerWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +59,9 @@ public class BufferedCodeWriter extends CodeWriter {
|
||||||
buffer.setLength(0);
|
buffer.setLength(0);
|
||||||
lastIndent = currentIndent;
|
lastIndent = currentIndent;
|
||||||
currentIndent = 0;
|
currentIndent = 0;
|
||||||
|
if (lineNumbersEmitted) {
|
||||||
|
lastLineNumber++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,37 +78,123 @@ public class BufferedCodeWriter extends CodeWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void source(String fileName, int lineNumber) {
|
||||||
|
if (!lineNumbersEmitted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Objects.equals(lastFileName, fileName) || lastLineNumber != lineNumber || locationDirty) {
|
||||||
|
flush();
|
||||||
|
fragments.add(new SourceFragment(fileName, lineNumber));
|
||||||
|
lastFileName = fileName;
|
||||||
|
lastLineNumber = lineNumber;
|
||||||
|
locationDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nosource() {
|
||||||
|
source(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
fragments.add(new SimpleFragment(false, lastIndent, buffer.toString()));
|
if (buffer.length() > 0 || lastIndent != 0 || currentIndent != 0) {
|
||||||
lastIndent = currentIndent;
|
fragments.add(new SimpleFragment(false, lastIndent, buffer.toString()));
|
||||||
currentIndent = 0;
|
lastIndent = currentIndent;
|
||||||
buffer.setLength(0);
|
currentIndent = 0;
|
||||||
|
buffer.setLength(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class WriterWithContext {
|
static class WriterWithContext {
|
||||||
PrintWriter writer;
|
PrintWriter writer;
|
||||||
boolean isNewLine = true;
|
boolean isNewLine = true;
|
||||||
int indentLevel;
|
int indentLevel;
|
||||||
|
String initialFileName;
|
||||||
|
String fileName;
|
||||||
|
int lineNumber;
|
||||||
|
int absLineNumber = 1;
|
||||||
|
String pendingFileName;
|
||||||
|
int pendingLineNumber = -1;
|
||||||
|
|
||||||
WriterWithContext(PrintWriter writer) {
|
WriterWithContext(PrintWriter writer, String fileName) {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
|
this.fileName = fileName;
|
||||||
|
initialFileName = fileName;
|
||||||
|
lineNumber = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(String text) {
|
void append(String text) {
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (isNewLine) {
|
if (isNewLine) {
|
||||||
for (int i = 0; i < indentLevel; ++i) {
|
if (pendingFileName != null || pendingLineNumber >= 0) {
|
||||||
writer.print(" ");
|
printLineDirective(pendingFileName, pendingLineNumber);
|
||||||
|
pendingLineNumber = -1;
|
||||||
|
pendingFileName = null;
|
||||||
}
|
}
|
||||||
|
printIndent();
|
||||||
isNewLine = false;
|
isNewLine = false;
|
||||||
}
|
}
|
||||||
writer.print(text);
|
writer.print(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void printLineDirective(String fileName, int lineNumber) {
|
||||||
|
if (Objects.equals(this.fileName, fileName) && lineNumber == this.lineNumber) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printIndent();
|
||||||
|
writer.print("#line ");
|
||||||
|
if (Objects.equals(fileName, initialFileName)) {
|
||||||
|
lineNumber = absLineNumber + 1;
|
||||||
|
}
|
||||||
|
writer.print(lineNumber);
|
||||||
|
if (!Objects.equals(fileName, this.fileName)) {
|
||||||
|
writer.print(" \"");
|
||||||
|
escape(writer, fileName);
|
||||||
|
writer.print("\"");
|
||||||
|
}
|
||||||
|
writer.println();
|
||||||
|
absLineNumber++;
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.lineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
void newLine() {
|
void newLine() {
|
||||||
|
lineNumber++;
|
||||||
|
absLineNumber++;
|
||||||
writer.println();
|
writer.println();
|
||||||
isNewLine = true;
|
isNewLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void printIndent() {
|
||||||
|
for (int i = 0; i < indentLevel; ++i) {
|
||||||
|
writer.print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void source(String fileName, int lineNumber) {
|
||||||
|
if (fileName == null) {
|
||||||
|
fileName = initialFileName;
|
||||||
|
lineNumber = absLineNumber;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(this.fileName, fileName) || this.lineNumber != lineNumber) {
|
||||||
|
if (isNewLine) {
|
||||||
|
pendingFileName = fileName;
|
||||||
|
pendingLineNumber = lineNumber;
|
||||||
|
} else {
|
||||||
|
this.lineNumber++;
|
||||||
|
absLineNumber++;
|
||||||
|
writer.println();
|
||||||
|
printLineDirective(fileName, lineNumber);
|
||||||
|
isNewLine = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static abstract class Fragment {
|
static abstract class Fragment {
|
||||||
|
@ -123,6 +222,62 @@ public class BufferedCodeWriter extends CodeWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class SourceFragment extends Fragment {
|
||||||
|
private String fileName;
|
||||||
|
private int lineNumber;
|
||||||
|
|
||||||
|
SourceFragment(String fileName, int lineNumber) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.lineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void writeTo(WriterWithContext writer) {
|
||||||
|
writer.source(fileName, lineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void escape(PrintWriter writer, String string) {
|
||||||
|
int chunkSize = 256;
|
||||||
|
for (int i = 0; i < string.length(); i += chunkSize) {
|
||||||
|
int last = Math.min(i + chunkSize, string.length());
|
||||||
|
|
||||||
|
for (int j = i; j < last; ++j) {
|
||||||
|
char c = string.charAt(j);
|
||||||
|
switch (c) {
|
||||||
|
case '\\':
|
||||||
|
writer.print("\\\\");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
writer.print("\\\"");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
writer.print("\\r");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
writer.print("\\n");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
writer.print("\\t");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (c < 32) {
|
||||||
|
writer.print("\\0" + Character.forDigit(c >> 3, 8) + Character.forDigit(c & 0x7, 8));
|
||||||
|
} else if (c > 127) {
|
||||||
|
writer.print("\\u"
|
||||||
|
+ Character.forDigit(c >> 12, 16)
|
||||||
|
+ Character.forDigit((c >> 8) & 15, 16)
|
||||||
|
+ Character.forDigit((c >> 4) & 15, 16)
|
||||||
|
+ Character.forDigit(c & 15, 16));
|
||||||
|
} else {
|
||||||
|
writer.print(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class InnerWriterFragment extends Fragment {
|
static class InnerWriterFragment extends Fragment {
|
||||||
List<Fragment> fragments;
|
List<Fragment> fragments;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,9 @@ import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.LongBuffer;
|
import java.nio.LongBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -78,6 +80,7 @@ import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.classes.VirtualTable;
|
import org.teavm.model.classes.VirtualTable;
|
||||||
import org.teavm.runtime.Allocator;
|
import org.teavm.runtime.Allocator;
|
||||||
|
@ -116,6 +119,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
private IncludeManager includes;
|
private IncludeManager includes;
|
||||||
private boolean end;
|
private boolean end;
|
||||||
private boolean async;
|
private boolean async;
|
||||||
|
private final Deque<LocationStackEntry> locationStack = new ArrayDeque<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
BUFFER_TYPES.put(ByteBuffer.class.getName(), "int8_t");
|
BUFFER_TYPES.put(ByteBuffer.class.getName(), "int8_t");
|
||||||
|
@ -148,137 +152,143 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryExpr expr) {
|
public void visit(BinaryExpr expr) {
|
||||||
switch (expr.getOperation()) {
|
pushLocation(expr.getLocation());
|
||||||
case COMPARE:
|
try {
|
||||||
writer.print("teavm_compare_");
|
switch (expr.getOperation()) {
|
||||||
switch (expr.getType()) {
|
case COMPARE:
|
||||||
case INT:
|
writer.print("teavm_compare_");
|
||||||
writer.print("i32");
|
switch (expr.getType()) {
|
||||||
break;
|
case INT:
|
||||||
case LONG:
|
writer.print("i32");
|
||||||
writer.print("i64");
|
break;
|
||||||
break;
|
case LONG:
|
||||||
case FLOAT:
|
writer.print("i64");
|
||||||
writer.print("float");
|
break;
|
||||||
break;
|
case FLOAT:
|
||||||
case DOUBLE:
|
writer.print("float");
|
||||||
writer.print("double");
|
break;
|
||||||
break;
|
case DOUBLE:
|
||||||
|
writer.print("double");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writer.print("(");
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
writer.print(", ");
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.print(")");
|
||||||
|
return;
|
||||||
|
case UNSIGNED_RIGHT_SHIFT: {
|
||||||
|
String type = expr.getType() == OperationType.LONG ? "int64_t" : "int32_t";
|
||||||
|
writer.print("((" + type + ") ((u" + type + ") ");
|
||||||
|
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
writer.print(" >> ");
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
|
||||||
|
writer.print("))");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
writer.print("(");
|
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
|
||||||
writer.print(", ");
|
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
|
||||||
writer.print(")");
|
|
||||||
return;
|
|
||||||
case UNSIGNED_RIGHT_SHIFT: {
|
|
||||||
String type = expr.getType() == OperationType.LONG ? "int64_t" : "int32_t";
|
|
||||||
writer.print("((" + type + ") ((u" + type + ") ");
|
|
||||||
|
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
case MODULO: {
|
||||||
writer.print(" >> ");
|
switch (expr.getType()) {
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
case FLOAT:
|
||||||
|
writer.print("fmodf(");
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
writer.print(", ");
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.print(")");
|
||||||
|
return;
|
||||||
|
case DOUBLE:
|
||||||
|
writer.print("fmod(");
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
writer.print(", ");
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.print(")");
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
writer.print("))");
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MODULO: {
|
writer.print("(");
|
||||||
switch (expr.getType()) {
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
case FLOAT:
|
|
||||||
writer.print("fmodf(");
|
String op;
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
switch (expr.getOperation()) {
|
||||||
writer.print(", ");
|
case ADD:
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
op = "+";
|
||||||
writer.print(")");
|
break;
|
||||||
return;
|
case SUBTRACT:
|
||||||
case DOUBLE:
|
op = "-";
|
||||||
writer.print("fmod(");
|
break;
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
case MULTIPLY:
|
||||||
writer.print(", ");
|
op = "*";
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
break;
|
||||||
writer.print(")");
|
case DIVIDE:
|
||||||
return;
|
op = "/";
|
||||||
default:
|
break;
|
||||||
break;
|
case MODULO:
|
||||||
}
|
op = "%";
|
||||||
break;
|
break;
|
||||||
|
case BITWISE_AND:
|
||||||
|
op = "&";
|
||||||
|
break;
|
||||||
|
case BITWISE_OR:
|
||||||
|
op = "|";
|
||||||
|
break;
|
||||||
|
case BITWISE_XOR:
|
||||||
|
op = "^";
|
||||||
|
break;
|
||||||
|
case LEFT_SHIFT:
|
||||||
|
op = "<<";
|
||||||
|
break;
|
||||||
|
case RIGHT_SHIFT:
|
||||||
|
op = ">>";
|
||||||
|
break;
|
||||||
|
case EQUALS:
|
||||||
|
op = "==";
|
||||||
|
break;
|
||||||
|
case NOT_EQUALS:
|
||||||
|
op = "!=";
|
||||||
|
break;
|
||||||
|
case GREATER:
|
||||||
|
op = ">";
|
||||||
|
break;
|
||||||
|
case GREATER_OR_EQUALS:
|
||||||
|
op = ">=";
|
||||||
|
break;
|
||||||
|
case LESS:
|
||||||
|
op = "<";
|
||||||
|
break;
|
||||||
|
case LESS_OR_EQUALS:
|
||||||
|
op = "<=";
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
op = "&&";
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
op = "||";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
writer.print(" ").print(op).print(" ");
|
||||||
break;
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
writer.print(")");
|
||||||
|
} finally {
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.print("(");
|
|
||||||
expr.getFirstOperand().acceptVisitor(this);
|
|
||||||
|
|
||||||
String op;
|
|
||||||
switch (expr.getOperation()) {
|
|
||||||
case ADD:
|
|
||||||
op = "+";
|
|
||||||
break;
|
|
||||||
case SUBTRACT:
|
|
||||||
op = "-";
|
|
||||||
break;
|
|
||||||
case MULTIPLY:
|
|
||||||
op = "*";
|
|
||||||
break;
|
|
||||||
case DIVIDE:
|
|
||||||
op = "/";
|
|
||||||
break;
|
|
||||||
case MODULO:
|
|
||||||
op = "%";
|
|
||||||
break;
|
|
||||||
case BITWISE_AND:
|
|
||||||
op = "&";
|
|
||||||
break;
|
|
||||||
case BITWISE_OR:
|
|
||||||
op = "|";
|
|
||||||
break;
|
|
||||||
case BITWISE_XOR:
|
|
||||||
op = "^";
|
|
||||||
break;
|
|
||||||
case LEFT_SHIFT:
|
|
||||||
op = "<<";
|
|
||||||
break;
|
|
||||||
case RIGHT_SHIFT:
|
|
||||||
op = ">>";
|
|
||||||
break;
|
|
||||||
case EQUALS:
|
|
||||||
op = "==";
|
|
||||||
break;
|
|
||||||
case NOT_EQUALS:
|
|
||||||
op = "!=";
|
|
||||||
break;
|
|
||||||
case GREATER:
|
|
||||||
op = ">";
|
|
||||||
break;
|
|
||||||
case GREATER_OR_EQUALS:
|
|
||||||
op = ">=";
|
|
||||||
break;
|
|
||||||
case LESS:
|
|
||||||
op = "<";
|
|
||||||
break;
|
|
||||||
case LESS_OR_EQUALS:
|
|
||||||
op = "<=";
|
|
||||||
break;
|
|
||||||
case AND:
|
|
||||||
op = "&&";
|
|
||||||
break;
|
|
||||||
case OR:
|
|
||||||
op = "||";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.print(" ").print(op).print(" ");
|
|
||||||
expr.getSecondOperand().acceptVisitor(this);
|
|
||||||
writer.print(")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnaryExpr expr) {
|
public void visit(UnaryExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
switch (expr.getOperation()) {
|
switch (expr.getOperation()) {
|
||||||
case NOT:
|
case NOT:
|
||||||
writer.print("(");
|
writer.print("(");
|
||||||
|
@ -316,10 +326,12 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalExpr expr) {
|
public void visit(ConditionalExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
writer.print("(");
|
writer.print("(");
|
||||||
expr.getCondition().acceptVisitor(this);
|
expr.getCondition().acceptVisitor(this);
|
||||||
writer.print(" ? ");
|
writer.print(" ? ");
|
||||||
|
@ -327,34 +339,43 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
writer.print(" : ");
|
writer.print(" : ");
|
||||||
expr.getAlternative().acceptVisitor(this);
|
expr.getAlternative().acceptVisitor(this);
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstantExpr expr) {
|
public void visit(ConstantExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
CodeGeneratorUtil.writeValue(writer, context, includes, expr.getValue());
|
CodeGeneratorUtil.writeValue(writer, context, includes, expr.getValue());
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(VariableExpr expr) {
|
public void visit(VariableExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
if (expr.getIndex() == 0) {
|
if (expr.getIndex() == 0) {
|
||||||
writer.print("teavm_this_");
|
writer.print("teavm_this_");
|
||||||
} else {
|
} else {
|
||||||
writer.print("teavm_local_" + expr.getIndex());
|
writer.print("teavm_local_" + expr.getIndex());
|
||||||
}
|
}
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SubscriptExpr expr) {
|
public void visit(SubscriptExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
writer.print("TEAVM_ARRAY_AT(");
|
writer.print("TEAVM_ARRAY_AT(");
|
||||||
expr.getArray().acceptVisitor(this);
|
expr.getArray().acceptVisitor(this);
|
||||||
writer.print(", ").print(getArrayType(expr.getType())).print(", ");
|
writer.print(", ").print(getArrayType(expr.getType())).print(", ");
|
||||||
expr.getIndex().acceptVisitor(this);
|
expr.getIndex().acceptVisitor(this);
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayExpr expr) {
|
public void visit(UnwrapArrayExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
expr.getArray().acceptVisitor(this);
|
expr.getArray().acceptVisitor(this);
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getArrayType(ArrayType type) {
|
private static String getArrayType(ArrayType type) {
|
||||||
|
@ -393,10 +414,13 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
Intrinsic intrinsic = context.getIntrinsic(expr.getMethod());
|
Intrinsic intrinsic = context.getIntrinsic(expr.getMethod());
|
||||||
if (intrinsic != null) {
|
if (intrinsic != null) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
intrinsic.apply(intrinsicContext, expr);
|
intrinsic.apply(intrinsicContext, expr);
|
||||||
|
popLocation(expr.getLocation());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
switch (expr.getType()) {
|
switch (expr.getType()) {
|
||||||
case CONSTRUCTOR: {
|
case CONSTRUCTOR: {
|
||||||
String receiver = allocTemporaryVariable(CVariableType.PTR);
|
String receiver = allocTemporaryVariable(CVariableType.PTR);
|
||||||
|
@ -482,6 +506,8 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWrappedNativeCall(MethodReader method, InvocationExpr expr) {
|
private void generateWrappedNativeCall(MethodReader method, InvocationExpr expr) {
|
||||||
|
@ -647,6 +673,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
public void visit(QualificationExpr expr) {
|
public void visit(QualificationExpr expr) {
|
||||||
FieldReference field = expr.getField();
|
FieldReference field = expr.getField();
|
||||||
if (isMonitorField(field)) {
|
if (isMonitorField(field)) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
String tmp = allocTemporaryVariable(CVariableType.INT);
|
String tmp = allocTemporaryVariable(CVariableType.INT);
|
||||||
writer.print("(" + tmp + " = TEAVM_FIELD(");
|
writer.print("(" + tmp + " = TEAVM_FIELD(");
|
||||||
expr.getQualified().acceptVisitor(this);
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
@ -654,9 +681,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
writer.print(", ").print(names.forClass(field.getClassName()) + ", "
|
writer.print(", ").print(names.forClass(field.getClassName()) + ", "
|
||||||
+ names.forMemberField(field) + ")");
|
+ names.forMemberField(field) + ")");
|
||||||
writer.print(", TEAVM_UNPACK_MONITOR(" + tmp + "))");
|
writer.print(", TEAVM_UNPACK_MONITOR(" + tmp + "))");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
includes.includeClass(field.getClassName());
|
includes.includeClass(field.getClassName());
|
||||||
if (expr.getQualified() != null) {
|
if (expr.getQualified() != null) {
|
||||||
writer.print("TEAVM_FIELD(");
|
writer.print("TEAVM_FIELD(");
|
||||||
|
@ -665,6 +694,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
} else {
|
} else {
|
||||||
writer.print(names.forStaticField(field));
|
writer.print(names.forStaticField(field));
|
||||||
}
|
}
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMonitorField(FieldReference field) {
|
private boolean isMonitorField(FieldReference field) {
|
||||||
|
@ -673,9 +703,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewExpr expr) {
|
public void visit(NewExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
includes.includeClass(expr.getConstructedClass());
|
includes.includeClass(expr.getConstructedClass());
|
||||||
includes.includeClass(ALLOC_METHOD.getClassName());
|
includes.includeClass(ALLOC_METHOD.getClassName());
|
||||||
allocObject(expr.getConstructedClass());
|
allocObject(expr.getConstructedClass());
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void allocObject(String className) {
|
private void allocObject(String className) {
|
||||||
|
@ -686,6 +718,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewArrayExpr expr) {
|
public void visit(NewArrayExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
ValueType type = ValueType.arrayOf(expr.getType());
|
ValueType type = ValueType.arrayOf(expr.getType());
|
||||||
writer.print(names.forMethod(ALLOC_ARRAY_METHOD)).print("(&")
|
writer.print(names.forMethod(ALLOC_ARRAY_METHOD)).print("(&")
|
||||||
.print(names.forClassInstance(type)).print(", ");
|
.print(names.forClassInstance(type)).print(", ");
|
||||||
|
@ -693,6 +726,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
includes.includeType(type);
|
includes.includeType(type);
|
||||||
expr.getLength().acceptVisitor(this);
|
expr.getLength().acceptVisitor(this);
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -714,10 +748,12 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InstanceOfExpr expr) {
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
writer.print("teavm_instanceof(");
|
writer.print("teavm_instanceof(");
|
||||||
expr.getExpr().acceptVisitor(this);
|
expr.getExpr().acceptVisitor(this);
|
||||||
includes.includeType(expr.getType());
|
includes.includeType(expr.getType());
|
||||||
writer.print(", ").print(names.forSupertypeFunction(expr.getType())).print(")");
|
writer.print(", ").print(names.forSupertypeFunction(expr.getType())).print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -730,14 +766,17 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
writer.print("teavm_checkcast(");
|
writer.print("teavm_checkcast(");
|
||||||
expr.getValue().acceptVisitor(this);
|
expr.getValue().acceptVisitor(this);
|
||||||
includes.includeType(expr.getTarget());
|
includes.includeType(expr.getTarget());
|
||||||
writer.print(", ").print(names.forSupertypeFunction(expr.getTarget())).print(")");
|
writer.print(", ").print(names.forSupertypeFunction(expr.getTarget())).print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PrimitiveCastExpr expr) {
|
public void visit(PrimitiveCastExpr expr) {
|
||||||
|
pushLocation(expr.getLocation());
|
||||||
writer.print("((");
|
writer.print("((");
|
||||||
switch (expr.getTarget()) {
|
switch (expr.getTarget()) {
|
||||||
case INT:
|
case INT:
|
||||||
|
@ -756,10 +795,12 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
writer.print(") ");
|
writer.print(") ");
|
||||||
expr.getValue().acceptVisitor(this);
|
expr.getValue().acceptVisitor(this);
|
||||||
writer.print(")");
|
writer.print(")");
|
||||||
|
popLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement statement) {
|
public void visit(AssignmentStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
if (statement.getLeftValue() != null) {
|
if (statement.getLeftValue() != null) {
|
||||||
if (statement.getLeftValue() instanceof QualificationExpr) {
|
if (statement.getLeftValue() instanceof QualificationExpr) {
|
||||||
QualificationExpr qualification = (QualificationExpr) statement.getLeftValue();
|
QualificationExpr qualification = (QualificationExpr) statement.getLeftValue();
|
||||||
|
@ -772,6 +813,7 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
+ names.forMemberField(field) + ") = TEAVM_PACK_MONITOR(");
|
+ names.forMemberField(field) + ") = TEAVM_PACK_MONITOR(");
|
||||||
statement.getRightValue().acceptVisitor(this);
|
statement.getRightValue().acceptVisitor(this);
|
||||||
writer.println(");");
|
writer.println(");");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,6 +827,8 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
if (statement.isAsync()) {
|
if (statement.isAsync()) {
|
||||||
emitSuspendChecker();
|
emitSuspendChecker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -809,9 +853,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
pushLocation(statement.getCondition().getLocation());
|
||||||
writer.print("if (");
|
writer.print("if (");
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
writer.println(") {").indent();
|
writer.println(") {").indent();
|
||||||
|
popLocation(statement.getCondition().getLocation());
|
||||||
|
|
||||||
visitMany(statement.getConsequent());
|
visitMany(statement.getConsequent());
|
||||||
writer.outdent().print("}");
|
writer.outdent().print("}");
|
||||||
|
@ -836,9 +882,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
|
pushLocation(statement.getValue().getLocation());
|
||||||
writer.print("switch (");
|
writer.print("switch (");
|
||||||
statement.getValue().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
writer.print(") {").println().indent();
|
writer.print(") {").println().indent();
|
||||||
|
popLocation(statement.getValue().getLocation());
|
||||||
|
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
for (int condition : clause.getConditions()) {
|
for (int condition : clause.getConditions()) {
|
||||||
|
@ -906,44 +954,54 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BreakStatement statement) {
|
public void visit(BreakStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
if (statement.getTarget() == null || statement.getTarget().getId() == null) {
|
if (statement.getTarget() == null || statement.getTarget().getId() == null) {
|
||||||
writer.println("break;");
|
writer.println("break;");
|
||||||
} else {
|
} else {
|
||||||
writer.println("goto teavm_label_" + statement.getTarget().getId() + ";");
|
writer.println("goto teavm_label_" + statement.getTarget().getId() + ";");
|
||||||
}
|
}
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ContinueStatement statement) {
|
public void visit(ContinueStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
if (statement.getTarget() == null || statement.getTarget().getId() == null) {
|
if (statement.getTarget() == null || statement.getTarget().getId() == null) {
|
||||||
writer.println("continue;");
|
writer.println("continue;");
|
||||||
} else {
|
} else {
|
||||||
writer.println("goto teavm_cnt_" + statement.getTarget().getId() + ";");
|
writer.println("goto teavm_cnt_" + statement.getTarget().getId() + ";");
|
||||||
}
|
}
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ReturnStatement statement) {
|
public void visit(ReturnStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
writer.print("return");
|
writer.print("return");
|
||||||
if (statement.getResult() != null) {
|
if (statement.getResult() != null) {
|
||||||
writer.print(" ");
|
writer.print(" ");
|
||||||
statement.getResult().acceptVisitor(this);
|
statement.getResult().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
writer.println(";");
|
writer.println(";");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ThrowStatement statement) {
|
public void visit(ThrowStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
includes.includeClass(THROW_EXCEPTION_METHOD.getClassName());
|
includes.includeClass(THROW_EXCEPTION_METHOD.getClassName());
|
||||||
writer.print(names.forMethod(THROW_EXCEPTION_METHOD)).print("(");
|
writer.print(names.forMethod(THROW_EXCEPTION_METHOD)).print("(");
|
||||||
statement.getException().acceptVisitor(this);
|
statement.getException().acceptVisitor(this);
|
||||||
writer.println(");");
|
writer.println(");");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassStatement statement) {
|
public void visit(InitClassStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
includes.includeClass(statement.getClassName());
|
includes.includeClass(statement.getClassName());
|
||||||
writer.println(names.forClassInitializer(statement.getClassName()) + "();");
|
writer.println(names.forClassInitializer(statement.getClassName()) + "();");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -956,18 +1014,22 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterStatement statement) {
|
public void visit(MonitorEnterStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
includes.includeClass("java.lang.Object");
|
includes.includeClass("java.lang.Object");
|
||||||
writer.print(names.forMethod(async ? MONITOR_ENTER : MONITOR_ENTER_SYNC)).print("(");
|
writer.print(names.forMethod(async ? MONITOR_ENTER : MONITOR_ENTER_SYNC)).print("(");
|
||||||
statement.getObjectRef().acceptVisitor(this);
|
statement.getObjectRef().acceptVisitor(this);
|
||||||
writer.println(");");
|
writer.println(");");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitStatement statement) {
|
public void visit(MonitorExitStatement statement) {
|
||||||
|
pushLocation(statement.getLocation());
|
||||||
includes.includeClass("java.lang.Object");
|
includes.includeClass("java.lang.Object");
|
||||||
writer.print(names.forMethod(async ? MONITOR_EXIT : MONITOR_EXIT_SYNC)).print("(");
|
writer.print(names.forMethod(async ? MONITOR_EXIT : MONITOR_EXIT_SYNC)).print("(");
|
||||||
statement.getObjectRef().acceptVisitor(this);
|
statement.getObjectRef().acceptVisitor(this);
|
||||||
writer.println(");");
|
writer.println(");");
|
||||||
|
popLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void emitSuspendChecker() {
|
public void emitSuspendChecker() {
|
||||||
|
@ -1043,4 +1105,46 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
return CVariableType.PTR;
|
return CVariableType.PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pushLocation(TextLocation location) {
|
||||||
|
if (location == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LocationStackEntry prevEntry = locationStack.peek();
|
||||||
|
if (prevEntry == null || !location.equals(prevEntry.location)) {
|
||||||
|
if (location.getFileName() == null) {
|
||||||
|
writer.nosource();
|
||||||
|
} else {
|
||||||
|
writer.source(location.getFileName(), location.getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locationStack.push(new LocationStackEntry(location));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void popLocation(TextLocation location) {
|
||||||
|
if (location == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LocationStackEntry prevEntry = locationStack.pop();
|
||||||
|
LocationStackEntry entry = locationStack.peek();
|
||||||
|
if (entry != null) {
|
||||||
|
if (!entry.location.equals(prevEntry.location)) {
|
||||||
|
if (entry.location.getFileName() == null) {
|
||||||
|
writer.nosource();
|
||||||
|
} else {
|
||||||
|
writer.source(entry.location.getFileName(), entry.location.getLine());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writer.nosource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LocationStackEntry {
|
||||||
|
final TextLocation location;
|
||||||
|
|
||||||
|
LocationStackEntry(TextLocation location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,4 +137,8 @@ public abstract class CodeWriter {
|
||||||
protected abstract void indentBy(int amount);
|
protected abstract void indentBy(int amount);
|
||||||
|
|
||||||
public abstract void flush();
|
public abstract void flush();
|
||||||
|
|
||||||
|
public abstract void source(String fileName, int lineNumber);
|
||||||
|
|
||||||
|
public abstract void nosource();
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,12 +92,12 @@ class GeneratorContextImpl implements GeneratorContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileGenerator createSourceFile(String path) {
|
public FileGenerator createSourceFile(String path) {
|
||||||
return createFile(new BufferedCodeWriter(), path);
|
return createFile(new BufferedCodeWriter(false), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileGenerator createHeaderFile(String path) {
|
public FileGenerator createHeaderFile(String path) {
|
||||||
BufferedCodeWriter writer = new BufferedCodeWriter();
|
BufferedCodeWriter writer = new BufferedCodeWriter(false);
|
||||||
writer.println("#pragma once");
|
writer.println("#pragma once");
|
||||||
return createFile(writer, path);
|
return createFile(writer, path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public final class OutputFileUtil {
|
||||||
public static void write(BufferedCodeWriter code, String name, BuildTarget buildTarget) throws IOException {
|
public static void write(BufferedCodeWriter code, String name, BuildTarget buildTarget) throws IOException {
|
||||||
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
|
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(
|
||||||
buildTarget.createResource(name), StandardCharsets.UTF_8))) {
|
buildTarget.createResource(name), StandardCharsets.UTF_8))) {
|
||||||
code.writeTo(writer);
|
code.writeTo(writer, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class IncrementalCBuilder {
|
||||||
private String mainClass;
|
private String mainClass;
|
||||||
private String[] classPath;
|
private String[] classPath;
|
||||||
private int minHeapSize = 32;
|
private int minHeapSize = 32;
|
||||||
|
private boolean lineNumbersGenerated;
|
||||||
private String targetPath;
|
private String targetPath;
|
||||||
private String externalTool;
|
private String externalTool;
|
||||||
private String externalToolWorkingDir;
|
private String externalToolWorkingDir;
|
||||||
|
@ -107,6 +108,10 @@ public class IncrementalCBuilder {
|
||||||
this.minHeapSize = minHeapSize;
|
this.minHeapSize = minHeapSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLineNumbersGenerated(boolean lineNumbersGenerated) {
|
||||||
|
this.lineNumbersGenerated = lineNumbersGenerated;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTargetPath(String targetPath) {
|
public void setTargetPath(String targetPath) {
|
||||||
this.targetPath = targetPath;
|
this.targetPath = targetPath;
|
||||||
}
|
}
|
||||||
|
@ -316,6 +321,7 @@ public class IncrementalCBuilder {
|
||||||
|
|
||||||
cTarget.setIncremental(true);
|
cTarget.setIncremental(true);
|
||||||
cTarget.setMinHeapSize(minHeapSize * 1024 * 1024);
|
cTarget.setMinHeapSize(minHeapSize * 1024 * 1024);
|
||||||
|
cTarget.setLineNumbersGenerated(lineNumbersGenerated);
|
||||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||||
vm.setCacheStatus(classSource);
|
vm.setCacheStatus(classSource);
|
||||||
vm.addVirtualMethods(m -> true);
|
vm.addVirtualMethods(m -> true);
|
||||||
|
|
|
@ -52,6 +52,10 @@ public class TeaVMCBuilderRunner {
|
||||||
.withDescription("display more messages on server log")
|
.withDescription("display more messages on server log")
|
||||||
.withLongOpt("verbose")
|
.withLongOpt("verbose")
|
||||||
.create('v'));
|
.create('v'));
|
||||||
|
options.addOption(OptionBuilder
|
||||||
|
.withDescription("generate debugger-friendly code")
|
||||||
|
.withLongOpt("debug")
|
||||||
|
.create('g'));
|
||||||
options.addOption(OptionBuilder
|
options.addOption(OptionBuilder
|
||||||
.withLongOpt("min-heap")
|
.withLongOpt("min-heap")
|
||||||
.withArgName("size")
|
.withArgName("size")
|
||||||
|
@ -103,6 +107,7 @@ public class TeaVMCBuilderRunner {
|
||||||
parseExternalTool();
|
parseExternalTool();
|
||||||
|
|
||||||
builder.setLog(new ConsoleTeaVMToolLog(commandLine.hasOption('v')));
|
builder.setLog(new ConsoleTeaVMToolLog(commandLine.hasOption('v')));
|
||||||
|
builder.setLineNumbersGenerated(commandLine.hasOption('g'));
|
||||||
|
|
||||||
String[] args = commandLine.getArgs();
|
String[] args = commandLine.getArgs();
|
||||||
if (args.length != 1) {
|
if (args.length != 1) {
|
||||||
|
|
|
@ -321,6 +321,7 @@ public class TeaVMTool {
|
||||||
private CTarget prepareCTarget() {
|
private CTarget prepareCTarget() {
|
||||||
cTarget = new CTarget();
|
cTarget = new CTarget();
|
||||||
cTarget.setMinHeapSize(minHeapSize);
|
cTarget.setMinHeapSize(minHeapSize);
|
||||||
|
cTarget.setLineNumbersGenerated(debugInformationGenerated);
|
||||||
return cTarget;
|
return cTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user