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));
|
||||
}
|
||||
|
||||
@@ -349,14 +349,11 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
PsiField psiField = (PsiField) declaration;
|
||||
final String owner = JetTypeMapper.jvmName(psiField.getContainingClass());
|
||||
final Type fieldType = psiTypeToAsm(psiField.getType());
|
||||
if (psiField.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
v.visitFieldInsn(Opcodes.GETSTATIC, owner, psiField.getName(), fieldType.getDescriptor());
|
||||
}
|
||||
else {
|
||||
final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
|
||||
if (!isStatic) {
|
||||
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 {
|
||||
int index = myMap.getIndex(descriptor);
|
||||
@@ -553,7 +550,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
@Override
|
||||
public void visitSafeQualifiedExpression(JetSafeQualifiedExpression expression) {
|
||||
genToStack(expression.getReceiverExpression());
|
||||
genToJVMStack(expression.getReceiverExpression());
|
||||
Label ifnull = new Label();
|
||||
Label end = new Label();
|
||||
v.dup();
|
||||
@@ -773,32 +770,16 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
|
||||
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
||||
if (expression.getLeft() instanceof JetArrayAccessExpression) {
|
||||
final JetArrayAccessExpression arrayAccess = (JetArrayAccessExpression) expression.getLeft();
|
||||
final Type arrayType = expressionType(arrayAccess.getArrayExpression());
|
||||
if (arrayType.getSort() == Type.ARRAY) {
|
||||
gen(arrayAccess.getArrayExpression(), arrayType);
|
||||
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());
|
||||
int oldStackSize = myStack.size();
|
||||
gen(expression.getLeft());
|
||||
genToJVMStack(expression.getRight());
|
||||
if (myStack.size() != oldStackSize+1) {
|
||||
throw new UnsupportedClassVersionError("generated something which doesn't seem to be an lvalue");
|
||||
}
|
||||
myStack.pop().store(v);
|
||||
}
|
||||
|
||||
|
||||
private void generateAugmentedAssignment(JetBinaryExpression expression) {
|
||||
final JetExpression lhs = expression.getLeft();
|
||||
if (lhs instanceof JetReferenceExpression) {
|
||||
@@ -995,8 +976,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
gen(array, arrayType);
|
||||
generateArrayIndex(expression);
|
||||
final Type elementType = arrayType.getElementType();
|
||||
v.aload(elementType);
|
||||
myStack.push(StackValue.onStack(elementType));
|
||||
myStack.push(StackValue.arrayElement(elementType));
|
||||
}
|
||||
else {
|
||||
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 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) {
|
||||
return new Local(index, type);
|
||||
}
|
||||
@@ -40,7 +59,13 @@ public abstract class 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) {
|
||||
if (type == Type.INT_TYPE) {
|
||||
@@ -135,14 +160,8 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
||||
put(Type.INT_TYPE, v);
|
||||
if (jumpIfFalse) {
|
||||
v.ifeq(label);
|
||||
}
|
||||
else {
|
||||
v.ifne(label);
|
||||
}
|
||||
public void store(InstructionAdapter v) {
|
||||
v.store(index, this.type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,21 +184,6 @@ public abstract class StackValue {
|
||||
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 {
|
||||
@@ -312,4 +316,43 @@ public abstract class StackValue {
|
||||
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 {
|
||||
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
String[] array = new String[] { null };
|
||||
main.invoke(null, new Object[] { array });
|
||||
|
||||
Reference in New Issue
Block a user