introduce StackValue.store(); use it to implement write access to fields and arrays
This commit is contained in:
@@ -62,7 +62,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genToStack(JetExpression expr) {
|
private void genToJVMStack(JetExpression expr) {
|
||||||
gen(expr, expressionType(expr));
|
gen(expr, expressionType(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,14 +349,11 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
PsiField psiField = (PsiField) declaration;
|
PsiField psiField = (PsiField) declaration;
|
||||||
final String owner = JetTypeMapper.jvmName(psiField.getContainingClass());
|
final String owner = JetTypeMapper.jvmName(psiField.getContainingClass());
|
||||||
final Type fieldType = psiTypeToAsm(psiField.getType());
|
final Type fieldType = psiTypeToAsm(psiField.getType());
|
||||||
if (psiField.hasModifierProperty(PsiModifier.STATIC)) {
|
final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
|
||||||
v.visitFieldInsn(Opcodes.GETSTATIC, owner, psiField.getName(), fieldType.getDescriptor());
|
if (!isStatic) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
ensureReceiverOnStack(expression);
|
ensureReceiverOnStack(expression);
|
||||||
v.visitFieldInsn(Opcodes.GETFIELD, owner, psiField.getName(), fieldType.getDescriptor());
|
|
||||||
}
|
}
|
||||||
myStack.push(StackValue.onStack(fieldType));
|
myStack.push(StackValue.field(fieldType, owner, psiField.getName(), isStatic));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int index = myMap.getIndex(descriptor);
|
int index = myMap.getIndex(descriptor);
|
||||||
@@ -553,7 +550,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSafeQualifiedExpression(JetSafeQualifiedExpression expression) {
|
public void visitSafeQualifiedExpression(JetSafeQualifiedExpression expression) {
|
||||||
genToStack(expression.getReceiverExpression());
|
genToJVMStack(expression.getReceiverExpression());
|
||||||
Label ifnull = new Label();
|
Label ifnull = new Label();
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
v.dup();
|
v.dup();
|
||||||
@@ -773,32 +770,16 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
||||||
if (expression.getLeft() instanceof JetArrayAccessExpression) {
|
int oldStackSize = myStack.size();
|
||||||
final JetArrayAccessExpression arrayAccess = (JetArrayAccessExpression) expression.getLeft();
|
gen(expression.getLeft());
|
||||||
final Type arrayType = expressionType(arrayAccess.getArrayExpression());
|
genToJVMStack(expression.getRight());
|
||||||
if (arrayType.getSort() == Type.ARRAY) {
|
if (myStack.size() != oldStackSize+1) {
|
||||||
gen(arrayAccess.getArrayExpression(), arrayType);
|
throw new UnsupportedClassVersionError("generated something which doesn't seem to be an lvalue");
|
||||||
generateArrayIndex(arrayAccess);
|
|
||||||
final Type elementType = arrayType.getElementType();
|
|
||||||
gen(expression.getRight(), elementType);
|
|
||||||
v.astore(elementType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("Don't know how to generate assignment to non-Java array " + expression.getLeft().getText());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (expression.getLeft() instanceof JetReferenceExpression) {
|
|
||||||
final JetReferenceExpression lhs = (JetReferenceExpression) expression.getLeft();
|
|
||||||
final int index = indexOfLocal(lhs);
|
|
||||||
final Type type = typeMapper.mapType(bindingContext.getExpressionType(lhs));
|
|
||||||
gen(expression.getRight(), type);
|
|
||||||
v.store(index, type);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("Don't know how to generate assignment to " + expression.getLeft().getText());
|
|
||||||
}
|
}
|
||||||
|
myStack.pop().store(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void generateAugmentedAssignment(JetBinaryExpression expression) {
|
private void generateAugmentedAssignment(JetBinaryExpression expression) {
|
||||||
final JetExpression lhs = expression.getLeft();
|
final JetExpression lhs = expression.getLeft();
|
||||||
if (lhs instanceof JetReferenceExpression) {
|
if (lhs instanceof JetReferenceExpression) {
|
||||||
@@ -995,8 +976,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
gen(array, arrayType);
|
gen(array, arrayType);
|
||||||
generateArrayIndex(expression);
|
generateArrayIndex(expression);
|
||||||
final Type elementType = arrayType.getElementType();
|
final Type elementType = arrayType.getElementType();
|
||||||
v.aload(elementType);
|
myStack.push(StackValue.arrayElement(elementType));
|
||||||
myStack.push(StackValue.onStack(elementType));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("array access to non-Java arrays is not supported");
|
throw new UnsupportedOperationException("array access to non-Java arrays is not supported");
|
||||||
|
|||||||
@@ -19,6 +19,25 @@ public abstract class StackValue {
|
|||||||
|
|
||||||
public abstract void put(Type type, InstructionAdapter v);
|
public abstract void put(Type type, InstructionAdapter v);
|
||||||
|
|
||||||
|
public void store(InstructionAdapter v) {
|
||||||
|
throw new UnsupportedOperationException("cannot store to value " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
||||||
|
if (this.type == Type.BOOLEAN_TYPE) {
|
||||||
|
put(Type.BOOLEAN_TYPE, v);
|
||||||
|
if (jumpIfFalse) {
|
||||||
|
v.ifeq(label);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.ifne(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static StackValue local(int index, Type type) {
|
public static StackValue local(int index, Type type) {
|
||||||
return new Local(index, type);
|
return new Local(index, type);
|
||||||
}
|
}
|
||||||
@@ -40,7 +59,13 @@ public abstract class StackValue {
|
|||||||
return new Invert(stackValue);
|
return new Invert(stackValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v);
|
public static StackValue arrayElement(Type type) {
|
||||||
|
return new ArrayElement(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StackValue field(Type type, String owner, String name, boolean isStatic) {
|
||||||
|
return new Field(type, owner, name, isStatic);
|
||||||
|
}
|
||||||
|
|
||||||
private static void box(final Type type, InstructionAdapter v) {
|
private static void box(final Type type, InstructionAdapter v) {
|
||||||
if (type == Type.INT_TYPE) {
|
if (type == Type.INT_TYPE) {
|
||||||
@@ -135,14 +160,8 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
public void store(InstructionAdapter v) {
|
||||||
put(Type.INT_TYPE, v);
|
v.store(index, this.type);
|
||||||
if (jumpIfFalse) {
|
|
||||||
v.ifeq(label);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.ifne(label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,21 +184,6 @@ public abstract class StackValue {
|
|||||||
coerce(type, v);
|
coerce(type, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
|
||||||
if (this.type == Type.BOOLEAN_TYPE) {
|
|
||||||
if (jumpIfFalse) {
|
|
||||||
v.ifeq(label);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.ifne(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value on stack");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Constant extends StackValue {
|
public static class Constant extends StackValue {
|
||||||
@@ -312,4 +316,43 @@ public abstract class StackValue {
|
|||||||
myOperand.condJump(label, !jumpIfFalse, v);
|
myOperand.condJump(label, !jumpIfFalse, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ArrayElement extends StackValue {
|
||||||
|
public ArrayElement(Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Type type, InstructionAdapter v) {
|
||||||
|
v.aload(type); // assumes array and index are on the stack
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(InstructionAdapter v) {
|
||||||
|
v.astore(type); // assumes array and index are on the stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Field extends StackValue {
|
||||||
|
private final String owner;
|
||||||
|
private final String name;
|
||||||
|
private final boolean isStatic;
|
||||||
|
|
||||||
|
public Field(Type type, String owner, String name, boolean isStatic) {
|
||||||
|
super(type);
|
||||||
|
this.owner = owner;
|
||||||
|
this.name = name;
|
||||||
|
this.isStatic = isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(Type type, InstructionAdapter v) {
|
||||||
|
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(InstructionAdapter v) {
|
||||||
|
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ public class NamespaceGenTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testArrayWrite() throws Exception {
|
public void testArrayWrite() throws Exception {
|
||||||
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
|
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
|
||||||
|
System.out.println(generateToText());
|
||||||
final Method main = generateFunction();
|
final Method main = generateFunction();
|
||||||
String[] array = new String[] { null };
|
String[] array = new String[] { null };
|
||||||
main.invoke(null, new Object[] { array });
|
main.invoke(null, new Object[] { array });
|
||||||
|
|||||||
Reference in New Issue
Block a user