Working on textual IR

This commit is contained in:
Alexey Andreev 2016-11-26 23:27:07 +03:00
parent 6f92dadad5
commit e5fe82f0fe
8 changed files with 550 additions and 42 deletions

View File

@ -21,10 +21,6 @@ import java.util.List;
import java.util.function.IntPredicate;
import java.util.stream.Collectors;
/**
*
* @author Alexey Andreev
*/
public final class GraphUtils {
static final byte NONE = 0;
static final byte VISITING = 1;
@ -233,12 +229,6 @@ public final class GraphUtils {
return components.toArray(new int[0][]);
}
private static class SCCFinder {
int[] index;
int[] lowlink;
boolean[] onStack;
}
public static DominatorTree buildDominatorTree(Graph graph) {
DominatorTreeBuilder builder = new DominatorTreeBuilder(graph);
builder.build();

View File

@ -17,10 +17,6 @@ package org.teavm.model;
import java.util.Arrays;
/**
*
* @author Alexey Andreev
*/
public class MethodHandle {
private MethodHandleType kind;
private String className;

View File

@ -21,10 +21,6 @@ import java.util.stream.Collectors;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
/**
*
* @author Alexey Andreev
*/
public class InstructionStringifier implements InstructionReader {
private TextLocation location;
private StringBuilder sb;
@ -64,12 +60,12 @@ public class InstructionStringifier implements InstructionReader {
@Override
public void longConstant(VariableReader receiver, long cst) {
sb.append("@").append(receiver.getIndex()).append(" := ").append(cst);
sb.append("@").append(receiver.getIndex()).append(" := ").append(cst).append("L");
}
@Override
public void floatConstant(VariableReader receiver, float cst) {
sb.append("@").append(receiver.getIndex()).append(" := ").append(cst);
sb.append("@").append(receiver.getIndex()).append(" := ").append(cst).append('F');
}
@Override
@ -267,38 +263,35 @@ public class InstructionStringifier implements InstructionReader {
@Override
public void create(VariableReader receiver, String type) {
sb.append("@").append(receiver.getIndex()).append(" = new ").append(type).append("()");
sb.append("@").append(receiver.getIndex()).append(" = new ").append(type).append("");
}
@Override
public void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType) {
sb.append("@").append(receiver.getIndex()).append(" := ");
sb.append("@").append(receiver.getIndex()).append(" := field " + field);
sb.append(field);
if (instance != null) {
sb.append(" @").append(instance.getIndex());
} else {
sb.append(field.getClassName());
}
sb.append(".").append(field.getFieldName());
}
@Override
public void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType) {
sb.append("field " + field);
if (instance != null) {
sb.append(" @").append(instance.getIndex());
} else {
sb.append(field.getClassName());
}
sb.append(".").append(field.getFieldName()).append(" := @").append(value.getIndex());
sb.append(" := @").append(value.getIndex());
}
@Override
public void arrayLength(VariableReader receiver, VariableReader array) {
sb.append("@").append(receiver.getIndex()).append(" := @").append(array.getIndex()).append(".length");
sb.append("@").append(receiver.getIndex()).append(" := lengthOf @").append(array.getIndex());
}
@Override
public void cloneArray(VariableReader receiver, VariableReader array) {
sb.append("@").append(receiver.getIndex()).append(" := @").append(array.getIndex()).append(".clone()");
sb.append("@").append(receiver.getIndex()).append(" := clone @").append(array.getIndex()).append("");
}
@Override
@ -325,19 +318,25 @@ public class InstructionStringifier implements InstructionReader {
if (receiver != null) {
sb.append("@").append(receiver.getIndex()).append(" := ");
}
switch (type) {
case SPECIAL:
sb.append("invoke ");
break;
case VIRTUAL:
sb.append("invokeVirtual ");
break;
}
if (instance != null) {
sb.append("@").append(instance.getIndex());
} else {
sb.append(method.getClassName());
}
sb.append(".").append(method.getName()).append("(");
for (int i = 0; i < arguments.size(); ++i) {
if (i > 0) {
if (instance != null || i > 0) {
sb.append(", ");
}
sb.append("@").append(arguments.get(i).getIndex());
}
sb.append(")");
}
@Override
@ -410,12 +409,12 @@ public class InstructionStringifier implements InstructionReader {
@Override
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
sb.append("@").append(receiver.getIndex()).append(" := @").append(value.getIndex())
.append(" instanceof ").append(type);
.append(" instanceOf ").append(type);
}
@Override
public void initClass(String className) {
sb.append("initclass ").append(className);
sb.append("initClass ").append(className);
}
@Override
@ -425,11 +424,11 @@ public class InstructionStringifier implements InstructionReader {
@Override
public void monitorEnter(VariableReader objectRef) {
sb.append("monitorenter @").append(objectRef.getIndex());
sb.append("monitorEnter @").append(objectRef.getIndex());
}
@Override
public void monitorExit(VariableReader objectRef) {
sb.append("monitorexit @").append(objectRef.getIndex());
sb.append("monitorExit @").append(objectRef.getIndex());
}
}

View File

@ -46,7 +46,7 @@ public class ListingBuilder {
for (PhiReader phi : block.readPhis()) {
sb.append(prefix).append(" ");
sb.append("@").append(phi.getReceiver().getIndex()).append(" := ");
sb.append("@").append(phi.getReceiver().getIndex()).append(" := phi ");
List<? extends IncomingReader> incomings = phi.readIncomings();
for (int j = 0; j < incomings.size(); ++j) {
if (j > 0) {

View File

@ -0,0 +1,424 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model.util;
import java.io.IOException;
import java.io.Reader;
class ListingLexer {
private Reader reader;
private int c;
private ListingToken token;
private Object tokenValue;
private int index = -1;
private int tokenStart;
public ListingLexer(Reader reader) {
this.reader = reader;
}
public ListingToken getToken() {
return token;
}
public Object getTokenValue() {
return tokenValue;
}
public int getIndex() {
return index;
}
public int getTokenStart() {
return tokenStart;
}
public void nextToken() throws IOException, ListingParseException {
if (token == ListingToken.EOF) {
return;
}
tokenStart = index;
if (index < 0) {
tokenStart = 0;
nextChar();
}
skipWhiteSpace();
do {
switch (c) {
case -1:
token = ListingToken.EOF;
break;
case '@':
nextChar();
readVariable();
break;
case '$':
readLabel();
break;
case '\'':
readString();
break;
case ':':
nextChar();
if (c == '=') {
nextChar();
token = ListingToken.ASSIGN;
} else {
token = ListingToken.COLON;
}
break;
case '=':
nextChar();
expect('=');
token = ListingToken.EQUAL;
break;
case '!':
nextChar();
expect('=');
token = ListingToken.NOT_EQUAL;
break;
case '<':
nextChar();
if (c == '=') {
nextChar();
token = ListingToken.LESS_OR_EQUAL;
} else if (c == '<') {
nextChar();
token = ListingToken.SHIFT_LEFT;
} else {
token = ListingToken.LESS;
}
break;
case '>':
nextChar();
if (c == '=') {
nextChar();
token = ListingToken.GREATER_OR_EQUAL;
} else if (c == '>') {
nextChar();
if (c == '>') {
nextChar();
token = ListingToken.SHIFT_RIGHT_UNSIGNED;
} else {
token = ListingToken.SHIFT_RIGHT;
}
} else {
token = ListingToken.GREATER;
}
break;
case '+':
nextChar();
token = ListingToken.ADD;
break;
case '-':
nextChar();
token = ListingToken.SUBTRACT;
break;
case '*':
nextChar();
token = ListingToken.SUBTRACT;
break;
case '/':
nextChar();
if (c == '/') {
if (skipComment()) {
continue;
} else {
token = ListingToken.EOF;
}
} else {
token = ListingToken.DIVIDE;
}
break;
case '%':
nextChar();
token = ListingToken.REMAINDER;
break;
case '&':
nextChar();
token = ListingToken.AND;
break;
case '|':
nextChar();
token = ListingToken.OR;
break;
case '^':
nextChar();
token = ListingToken.XOR;
break;
case '.':
nextChar();
token = ListingToken.DOT;
break;
case ',':
nextChar();
token = ListingToken.COMMA;
break;
case '[':
nextChar();
token = ListingToken.LEFT_SQUARE_BRACKET;
break;
case ']':
nextChar();
token = ListingToken.RIGHT_SQUARE_BRACKET;
break;
default:
if (isIdentifierStart()) {
readIdentifier();
} else if (c >= '0' && c <= '9') {
readNumber();
} else {
unexpected();
}
break;
}
} while (false);
}
private void readVariable() throws IOException {
nextChar();
token = ListingToken.VARIABLE;
readIdentifierLike();
}
private void readLabel() throws IOException {
readIdentifierLike();
token = ListingToken.LABEL;
readIdentifierLike();
}
private void readIdentifierLike() throws IOException {
StringBuilder sb = new StringBuilder();
while (isIdentifierPart()) {
sb.append(c);
nextChar();
}
tokenValue = sb.toString();
}
private void readIdentifier() throws IOException {
token = ListingToken.IDENTIFIER;
StringBuilder sb = new StringBuilder();
sb.append(c);
while (isIdentifierPart()) {
sb.append(c);
nextChar();
}
tokenValue = sb.toString();
}
private boolean isIdentifierStart() {
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
return true;
}
switch (c) {
case '_':
return true;
default:
return false;
}
}
private boolean isIdentifierPart() {
if (isIdentifierStart() || c >= '0' && c <= '9') {
return true;
}
switch (c) {
case '<':
case '>':
case '(':
case ')':
case '.':
case '$':
case '#':
return true;
default:
return false;
}
}
private void readString() throws IOException, ListingParseException {
nextChar();
token = ListingToken.STRING;
StringBuilder sb = new StringBuilder();
while (true) {
switch (c) {
case '\'':
nextChar();
tokenValue = sb.toString();
return;
case '\\':
switch (c) {
case 'n':
sb.append('\n');
break;
case 't':
sb.append('\t');
break;
case '\'':
case '\\':
sb.append(c);
break;
case 'u':
int codePoint = 0;
for (int i = 0; i < 4; ++i) {
if (c == -1) {
throw new ListingParseException("Wrong escape sequence", index);
}
int digit = Character.digit((char) c, 16);
if (digit < 0) {
throw new ListingParseException("Wrong escape sequence", index);
}
codePoint = codePoint * 16 + digit;
}
sb.appendCodePoint(codePoint);
break;
default:
throw new ListingParseException("Wrong escape sequence", index);
}
break;
default:
if (c < ' ') {
throw new ListingParseException("Unexpected character in string literal: " + c, index);
}
sb.append(c);
nextChar();
break;
}
}
}
private void readNumber() throws IOException, ListingParseException {
StringBuilder sb = new StringBuilder();
sb.append(c);
nextChar();
token = ListingToken.INTEGER;
while (c >= '0' && c <= '9') {
sb.append(c);
nextChar();
}
if (c == '.') {
sb.append('.');
token = ListingToken.DOUBLE;
nextChar();
if (c < '0' || c > '9') {
throw new ListingParseException("Wrong number", index);
}
while (c >= '0' && c <= '9') {
sb.append(c);
nextChar();
}
}
if (c == 'E' || c == 'e') {
sb.append('e');
nextChar();
if (c == '+' || c == '-') {
sb.append(c);
nextChar();
}
if (c < '0' || c > '9') {
throw new ListingParseException("Wrong number", index);
}
while (c >= '0' && c <= '9') {
sb.append(c);
nextChar();
}
}
if (c == 'F' || c == 'f') {
nextChar();
token = ListingToken.FLOAT;
} else if (c == 'l' || c == 'L') {
nextChar();
token = ListingToken.LONG;
} else if (isIdentifierStart()) {
throw new ListingParseException("Wrong number", index);
}
switch (token) {
case INTEGER:
tokenValue = Integer.parseInt(sb.toString());
break;
case LONG:
tokenValue = Long.parseLong(sb.toString());
break;
case FLOAT:
tokenValue = Float.parseFloat(sb.toString());
break;
case DOUBLE:
tokenValue = Double.parseDouble(sb.toString());
break;
default:
break;
}
}
private void expect(char expected) throws IOException, ListingParseException {
if (c != expected) {
unexpected();
}
nextChar();
}
private void unexpected() throws ListingParseException {
throw new ListingParseException("Unexpected character: " + c, index);
}
private void skipWhiteSpace() throws IOException {
while (true) {
switch (c) {
case ' ':
case '\n':
case '\t':
nextChar();
break;
default:
return;
}
}
}
private boolean skipComment() throws IOException {
while (true) {
switch (c) {
case '\n':
nextChar();
return true;
case -1:
return false;
default:
nextChar();
break;
}
}
}
private void nextChar() throws IOException {
c = reader.read();
++index;
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model.util;
public class ListingParseException extends Exception {
private final int index;
public ListingParseException(String message, int index) {
super(message);
this.index = index;
}
public int getIndex() {
return index;
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model.util;
public class ListingParser {
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model.util;
enum ListingToken {
IDENTIFIER,
INTEGER,
LONG,
FLOAT,
DOUBLE,
STRING,
VARIABLE,
LABEL,
ASSIGN,
EQUAL,
NOT_EQUAL,
LESS,
LESS_OR_EQUAL,
GREATER,
GREATER_OR_EQUAL,
ADD,
SUBTRACT,
MULTIPLY,
DIVIDE,
REMAINDER,
AND,
OR,
XOR,
SHIFT_LEFT,
SHIFT_RIGHT,
SHIFT_RIGHT_UNSIGNED,
DOT,
LEFT_SQUARE_BRACKET,
RIGHT_SQUARE_BRACKET,
COMMA,
COLON,
EOF
}