163 lines
4.8 KiB
Java
163 lines
4.8 KiB
Java
package org.jetbrains.jet.codegen;
|
|
|
|
import com.intellij.psi.tree.IElementType;
|
|
import org.jetbrains.jet.lang.types.JetType;
|
|
import org.jetbrains.jet.lexer.JetTokens;
|
|
import org.objectweb.asm.Label;
|
|
import org.objectweb.asm.Opcodes;
|
|
import org.objectweb.asm.Type;
|
|
import org.objectweb.asm.commons.InstructionAdapter;
|
|
|
|
/**
|
|
* @author yole
|
|
*/
|
|
public abstract class StackValue {
|
|
public abstract void put(Type type, InstructionAdapter v);
|
|
|
|
public static StackValue local(int index, JetType type) {
|
|
return new Local(index, type);
|
|
}
|
|
|
|
public static StackValue onStack(Type type) {
|
|
assert type != Type.VOID_TYPE;
|
|
return new OnStack(type);
|
|
}
|
|
|
|
public static StackValue constant(Object value) {
|
|
return new Constant(value);
|
|
}
|
|
|
|
public static StackValue icmp(IElementType opToken) {
|
|
return new IntCompare(opToken);
|
|
}
|
|
|
|
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v);
|
|
|
|
public static class Local extends StackValue {
|
|
private final int index;
|
|
private final JetType type;
|
|
|
|
public Local(int index, JetType type) {
|
|
this.index = index;
|
|
this.type = type;
|
|
}
|
|
|
|
@Override
|
|
public void put(Type type, InstructionAdapter v) {
|
|
v.load(index, type);
|
|
// TODO box/unbox
|
|
}
|
|
|
|
@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 static class OnStack extends StackValue {
|
|
private final Type type;
|
|
|
|
public OnStack(Type type) {
|
|
this.type = type;
|
|
}
|
|
|
|
@Override
|
|
public void put(Type type, InstructionAdapter v) {
|
|
}
|
|
|
|
@Override
|
|
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
|
if (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 {
|
|
private final Object value;
|
|
|
|
public Constant(Object value) {
|
|
this.value = value;
|
|
}
|
|
|
|
@Override
|
|
public void put(Type type, InstructionAdapter v) {
|
|
v.aconst(value);
|
|
}
|
|
|
|
@Override
|
|
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
|
if (value instanceof Boolean) {
|
|
boolean boolValue = ((Boolean) value).booleanValue();
|
|
if (boolValue ^ jumpIfFalse) {
|
|
v.goTo(label);
|
|
}
|
|
}
|
|
else {
|
|
throw new UnsupportedOperationException("don't know how to generate this condjump");
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class IntCompare extends StackValue {
|
|
private final IElementType opToken;
|
|
|
|
public IntCompare(IElementType opToken) {
|
|
this.opToken = opToken;
|
|
}
|
|
|
|
@Override
|
|
public void put(Type type, InstructionAdapter v) {
|
|
Label ifTrue = new Label();
|
|
Label end = new Label();
|
|
condJump(ifTrue, false, v);
|
|
v.iconst(0);
|
|
v.goTo(end);
|
|
v.mark(ifTrue);
|
|
v.iconst(1);
|
|
v.mark(end);
|
|
}
|
|
|
|
@Override
|
|
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
|
int opcode;
|
|
if (opToken == JetTokens.EQEQ) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPNE : Opcodes.IF_ICMPEQ;
|
|
}
|
|
else if (opToken == JetTokens.EXCLEQ) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPEQ : Opcodes.IF_ICMPNE;
|
|
}
|
|
else if (opToken == JetTokens.GT) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPLE : Opcodes.IF_ICMPGT;
|
|
}
|
|
else if (opToken == JetTokens.GTEQ) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPLT : Opcodes.IF_ICMPGE;
|
|
}
|
|
else if (opToken == JetTokens.LT) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPGE : Opcodes.IF_ICMPLT;
|
|
}
|
|
else if (opToken == JetTokens.LTEQ) {
|
|
opcode = jumpIfFalse ? Opcodes.IF_ICMPGT : Opcodes.IF_ICMPLE;
|
|
}
|
|
else {
|
|
throw new UnsupportedOperationException("don't know how to generate this condjump");
|
|
}
|
|
v.visitJumpInsn(opcode, label);
|
|
}
|
|
}
|
|
}
|