提交 739fce33 编写于 作者: D Dmitry Jemerov

work in progress on codegen rewrite (no boxing for primitive types)

上级 d05066f8
......@@ -19,15 +19,21 @@ import java.util.Stack;
public class ExpressionCodegen extends JetVisitor {
private final Stack<Label> myLoopStarts = new Stack<Label>();
private final Stack<Label> myLoopEnds = new Stack<Label>();
private final Stack<StackValue> myStack = new Stack<StackValue>();
private final InstructionAdapter v;
private final JetStandardLibrary stdlib;
private final FrameMap myMap;
private final JetTypeMapper typeMapper;
private final Type returnType;
private final BindingContext bindingContext;
public ExpressionCodegen(MethodVisitor v, BindingContext bindingContext, JetStandardLibrary stdlib, FrameMap myMap) {
public ExpressionCodegen(MethodVisitor v, BindingContext bindingContext, JetStandardLibrary stdlib, FrameMap myMap,
JetTypeMapper typeMapper, Type returnType) {
this.stdlib = stdlib;
this.myMap = myMap;
this.typeMapper = typeMapper;
this.returnType = returnType;
this.v = new InstructionAdapter(v);
this.bindingContext = bindingContext;
}
......@@ -37,6 +43,15 @@ public class ExpressionCodegen extends JetVisitor {
expr.accept(this);
}
private void gen(JetElement expr, Type type) {
int oldStackDepth = myStack.size();
gen(expr);
if (myStack.size() == oldStackDepth+1) {
StackValue value = myStack.pop();
value.put(type, v);
}
}
@Override
public void visitExpression(JetExpression expression) {
throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented");
......@@ -54,8 +69,9 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitIfExpression(JetIfExpression expression) {
gen(expression.getCondition());
unboxBoolean();
JetType expressionType = bindingContext.getExpressionType(expression);
Type asmType = typeMapper.mapType(expressionType);
gen(expression.getCondition(), Type.BOOLEAN_TYPE);
JetExpression thenExpression = expression.getThen();
JetExpression elseExpression = expression.getElse();
......@@ -78,13 +94,13 @@ public class ExpressionCodegen extends JetVisitor {
Label elseLabel = new Label();
v.ifeq(elseLabel); // == 0, i.e. false
gen(thenExpression);
gen(thenExpression, asmType);
Label endLabel = new Label();
v.goTo(endLabel);
v.mark(elseLabel);
gen(elseExpression);
gen(elseExpression, asmType);
v.mark(endLabel);
}
......@@ -178,6 +194,8 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitConstantExpression(JetConstantExpression expression) {
myStack.push(StackValue.constant(expression.getValue()));
/*
Object value = expression.getValue();
v.aconst(value);
......@@ -205,6 +223,7 @@ public class ExpressionCodegen extends JetVisitor {
else if (value instanceof Double) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
}
*/
}
@Override
......@@ -229,8 +248,11 @@ public class ExpressionCodegen extends JetVisitor {
for (JetElement statement : statements) {
if (statement instanceof JetProperty) {
JetProperty var = (JetProperty) statement;
int index = myMap.leave(bindingContext.getPropertyDescriptor(var));
v.visitLocalVariable(var.getName(), getType(var).getDescriptor(), null, blockStart, blockEnd, index);
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(var);
Type outType = typeMapper.mapType(propertyDescriptor.getOutType());
int index = myMap.leave(propertyDescriptor);
v.visitLocalVariable(var.getName(), outType.getDescriptor(), null, blockStart, blockEnd, index);
}
}
......@@ -240,14 +262,22 @@ public class ExpressionCodegen extends JetVisitor {
public void visitReturnExpression(JetReturnExpression expression) {
final JetExpression returnedExpression = expression.getReturnedExpression();
if (returnedExpression != null) {
returnedExpression.accept(this);
v.visitInsn(Opcodes.ARETURN);
gen(returnedExpression, returnType);
v.areturn(returnType);
}
else {
v.visitInsn(Opcodes.RETURN);
}
}
public void returnTopOfStack() {
if (myStack.size() > 0) {
StackValue value = myStack.pop();
value.put(returnType, v);
v.areturn(returnType);
}
}
@Override
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
......@@ -267,7 +297,7 @@ public class ExpressionCodegen extends JetVisitor {
else {
int index = myMap.getIndex(descriptor);
if (index >= 0) {
v.visitVarInsn(Opcodes.ALOAD, index);
myStack.push(StackValue.local(index, ((PropertyDescriptor) descriptor).getOutType()));
}
else {
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
......@@ -277,11 +307,6 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitCallExpression(JetCallExpression expression) {
List<JetArgument> args = expression.getValueArguments();
for (JetArgument arg : args) {
gen(arg.getArgumentExpression());
}
JetExpression callee = expression.getCalleeExpression();
if (callee instanceof JetSimpleNameExpression) {
......@@ -290,6 +315,14 @@ public class ExpressionCodegen extends JetVisitor {
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
if (declarationPsiElement instanceof PsiMethod) {
PsiMethod method = (PsiMethod) declarationPsiElement;
PsiParameter[] parameters = method.getParameterList().getParameters();
List<JetArgument> args = expression.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
JetArgument arg = args.get(i);
gen(arg.getArgumentExpression(), psiTypeToAsm(parameters [i].getType()));
}
if (method.hasModifierProperty(PsiModifier.STATIC)) {
v.visitMethodInsn(Opcodes.INVOKESTATIC,
jvmName(method.getContainingClass()),
......@@ -302,7 +335,7 @@ public class ExpressionCodegen extends JetVisitor {
method.getName(),
getMethodDescriptor(method));
}
boxIfNeeded(method.getReturnType());
myStack.push(StackValue.onStack(psiTypeToAsm(method.getReturnType())));
}
}
else {
......@@ -422,12 +455,10 @@ public class ExpressionCodegen extends JetVisitor {
if (op.getName().equals("plus")) {
JetType returnType = ((FunctionDescriptor) op).getUnsubstitutedReturnType();
if (returnType.equals(stdlib.getIntType())) {
gen(expression.getLeft());
unbox(PsiType.INT);
gen(expression.getRight());
unbox(PsiType.INT);
gen(expression.getLeft(), Type.INT_TYPE);
gen(expression.getRight(), Type.INT_TYPE);
v.add(Type.INT_TYPE);
boxIfNeeded(PsiType.INT);
myStack.push(StackValue.onStack(Type.INT_TYPE));
return;
}
}
......@@ -436,24 +467,22 @@ public class ExpressionCodegen extends JetVisitor {
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
}
private Type getType(JetProperty var) {
return InstructionAdapter.OBJECT_TYPE; // TODO:
}
private boolean isUnitType(JetExpression e) {
return false; // TODO:!!!
}
@Override
public void visitProperty(JetProperty property) {
int index = myMap.getIndex(bindingContext.getPropertyDescriptor(property));
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(property);
int index = myMap.getIndex(propertyDescriptor);
assert index >= 0;
JetExpression initializer = property.getInitializer();
if (initializer != null) {
gen(initializer);
v.store(index, getType(property));
Type type = typeMapper.mapType(propertyDescriptor.getOutType());
gen(initializer, type);
v.store(index, type);
}
}
......
......@@ -56,20 +56,21 @@ public class FunctionCodegen {
frameMap.enter(parameter);
}
bodyExpression.accept(new ExpressionCodegen(mv, bindingContext, standardLibrary, frameMap));
generateReturn(mv, bodyExpression);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, standardLibrary, frameMap, typeMapper, returnType);
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression) {
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen) {
if (!endsWithReturn(bodyExpression)) {
final JetType expressionType = bindingContext.getExpressionType(bodyExpression);
if (expressionType.equals(JetStandardClasses.getUnitType())) {
mv.visitInsn(Opcodes.RETURN);
}
else {
mv.visitInsn(Opcodes.ARETURN);
codegen.returnTopOfStack();
}
}
}
......
......@@ -18,10 +18,13 @@ public class JetTypeMapper {
return Type.VOID_TYPE;
}
if (jetType.equals(standardLibrary.getIntType())) {
return Type.getType(Integer.class);
return Type.INT_TYPE;
}
if (jetType.equals(standardLibrary.getLongType())) {
return Type.getType(Long.class);
return Type.LONG_TYPE;
}
if (jetType.equals(standardLibrary.getBooleanType())) {
return Type.BOOLEAN_TYPE;
}
if (jetType.equals(standardLibrary.getStringType())) {
return Type.getType(String.class);
......
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.types.JetType;
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) {
return new OnStack(type);
}
public static StackValue constant(Object value) {
return new Constant(value);
}
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
}
}
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) {
}
}
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) {
if (type == Type.INT_TYPE) {
if (value instanceof Number) {
v.iconst(((Number) value).intValue());
}
else {
throw new UnsupportedOperationException("don't know how to put this value");
}
}
// TODO other primitive types
else {
v.aconst(value);
}
}
}
}
fun f(): Int {
var x: Int = 1
x = x + 1
return x
}
fun foo(b: Boolean): Int { return if (b) 15 else 20 }
\ No newline at end of file
fun foo(b: Boolean) : Int {
if (b) return 15;
return 20;
}
......@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.objectweb.asm.Type;
import org.objectweb.asm.util.TraceMethodVisitor;
import java.io.IOException;
......@@ -13,36 +14,7 @@ import java.io.StringWriter;
* @author max
*/
public class ExpressionGenTest extends LightDaemonAnalyzerTestCase {
public void testIntegerZeroExpression() throws Exception {
checkCode("0",
"LDC 0\n" +
"INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;");
}
public void testIf() throws Exception {
checkCode("if (false) 15 else 20",
"LDC false\n" +
"INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;\n" +
"INVOKEVIRTUAL java/lang/Boolean.booleanValue ()Z\n" +
"IFEQ L0\n" +
"LDC 15\n" +
"INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;\n" +
"GOTO L1\n" +
"L0\n" +
"LDC 20\n" +
"INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;\n" +
"L1");
checkCode("if (false) 15",
"LDC false\n" +
"INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;\n" +
"INVOKEVIRTUAL java/lang/Boolean.booleanValue ()Z\n" +
"IFEQ L0\n" +
"LDC 15\n" +
"INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;\n" +
"POP\n" +
"L0");
checkCode("if (false) else 20",
"LDC false\n" +
"INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;\n" +
......@@ -60,7 +32,7 @@ public class ExpressionGenTest extends LightDaemonAnalyzerTestCase {
JetProperty p = PsiTreeUtil.getParentOfType(getFile().findElementAt(0), JetProperty.class);
TraceMethodVisitor trace = new TraceMethodVisitor();
p.getInitializer().accept(new ExpressionCodegen(trace, null, null, new FrameMap()));
p.getInitializer().accept(new ExpressionCodegen(trace, null, null, new FrameMap(), new JetTypeMapper(null), Type.VOID_TYPE));
StringWriter out = new StringWriter();
trace.print(new PrintWriter(out));
......
......@@ -28,8 +28,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
final String text = generateToText();
System.out.println(text);
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
Object[] args = new Object[] { new String[0] };
main.invoke(null, args);
}
......@@ -39,8 +38,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
final String text = generateToText();
System.out.println(text);
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, new Object[0]);
assertEquals(new Integer(42), returnValue);
}
......@@ -50,8 +48,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
final String text = generateToText();
System.out.println(text);
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, 50);
assertEquals(new Integer(50), returnValue);
}
......@@ -61,16 +58,15 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
final String text = generateToText();
System.out.println(text);
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
final Object returnValue = main.invoke(null, 76);
assertEquals(new Integer(50), returnValue);
}
public void testCurrentTime() throws Exception {
loadFile("currentTime.jet");
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
System.out.println(generateToText());
final Method main = generateFunction();
final long returnValue = (Long) main.invoke(null);
long currentTime = System.currentTimeMillis();
assertTrue(Math.abs(returnValue - currentTime) <= 1L);
......@@ -78,8 +74,8 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
public void testIdentityHashCode() throws Exception {
loadFile("identityHashCode.jet");
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
System.out.println(generateToText());
final Method main = generateFunction();
Object o = new Object();
final int returnValue = (Integer) main.invoke(null, o);
assertEquals(returnValue, System.identityHashCode(o));
......@@ -87,8 +83,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
public void testSystemOut() throws Exception {
loadFile("systemOut.jet");
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
final Object returnValue = main.invoke(null);
assertEquals(returnValue, System.out);
}
......@@ -98,8 +93,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
System.out.println(generateToText());
final Class aClass = generateToClass();
final Method main = firstMethod(aClass); // assert that it can be verified
generateFunction(); // assert that it can be verified
}
public void testPlus() throws Exception {
......@@ -107,12 +101,37 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
System.out.println(generateToText());
final Class aClass = generateToClass();
final Method main = firstMethod(aClass);
final Method main = generateFunction();
final int returnValue = (Integer) main.invoke(null, 37, 5);
assertEquals(42, returnValue);
}
public void testIf() throws Exception {
loadFile("if.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(15, main.invoke(null, true));
assertEquals(20, main.invoke(null, false));
}
public void testSingleBranchIf() throws Exception {
loadFile("singleBranchIf.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(15, main.invoke(null, true));
assertEquals(20, main.invoke(null, false));
}
public void testAssign() throws Exception {
loadFile("assign.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(2, main.invoke(null));
}
private void loadFile(final String name) {
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
}
......@@ -143,7 +162,8 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
return aClass;
}
private static Method firstMethod(Class aClass) {
private Method generateFunction() {
Class aClass = generateToClass();
return aClass.getMethods()[0];
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册