introduce StackValue.store(); use it to implement write access to fields and arrays

This commit is contained in:
Dmitry Jemerov
2011-04-15 18:59:57 +02:00
parent 9b0a9b71a2
commit b6f444b0f7
3 changed files with 81 additions and 57 deletions
@@ -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 });