StackValue.java 41.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright 2010-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17 18
package org.jetbrains.jet.codegen;

19
import com.intellij.psi.tree.IElementType;
20
import org.jetbrains.annotations.NotNull;
21
import org.jetbrains.annotations.Nullable;
22
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
23
import org.jetbrains.jet.lang.descriptors.*;
24
import org.jetbrains.jet.lang.psi.JetExpression;
25
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
26
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
27
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
28 29 30
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
31 32
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
33
import org.objectweb.asm.commons.Method;
34

35 36
import java.util.List;

37 38
/**
 * @author yole
A
Alex Tkachman 已提交
39
 * @author alex.tkachman
40 41
 */
public abstract class StackValue {
42
    public final Type type;
D
Dmitry Jemerov 已提交
43 44 45

    public StackValue(Type type) {
        this.type = type;
46 47 48 49 50 51 52 53 54
    }

    public static void valueOf(InstructionAdapter instructionAdapter, final Type type) {
        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
            return;
        }
        if (type == Type.VOID_TYPE) {
            instructionAdapter.aconst(null);
        } else {
55
            Type boxed = JetTypeMapper.boxType(type);
56 57
            instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
        }
D
Dmitry Jemerov 已提交
58 59
    }

60 61
    public abstract void put(Type type, InstructionAdapter v);

62
    public void store(InstructionAdapter v) {
63 64 65
        throw new UnsupportedOperationException("cannot store to value " + this);
    }

66
    public void dupReceiver(InstructionAdapter v) {
67 68
    }

A
Alex Tkachman 已提交
69 70 71 72
    public int receiverSize() {
        return 0;
    }

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    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");
        }
    }

D
Dmitry Jemerov 已提交
88
    public static StackValue local(int index, Type type) {
89 90 91
        return new Local(index, type);
    }

A
Alex Tkachman 已提交
92 93 94 95
    public static StackValue shared(int index, Type type) {
        return new Shared(index, type);
    }

96
    public static StackValue onStack(Type type) {
97
        return type == Type.VOID_TYPE ? none() : new OnStack(type);
98 99
    }

D
Dmitry Jemerov 已提交
100 101
    public static StackValue constant(Object value, Type type) {
        return new Constant(value, type);
102 103
    }

104
    public static StackValue cmp(IElementType opToken, Type type) {
D
Dmitry Jemerov 已提交
105
        return type.getSort() == Type.OBJECT ? new ObjectCompare(opToken, type) : new NumberCompare(opToken, type);
106 107
    }

D
Dmitry Jemerov 已提交
108 109 110 111
    public static StackValue not(StackValue stackValue) {
        return new Invert(stackValue);
    }

A
Alex Tkachman 已提交
112 113
    public static StackValue arrayElement(Type type, boolean unbox) {
        return new ArrayElement(type, unbox);
114 115
    }

S
Stepan Koltsov 已提交
116 117
    public static StackValue collectionElement(Type type, ResolvedCall<FunctionDescriptor> getter, ResolvedCall<FunctionDescriptor> setter, ExpressionCodegen codegen, GenerationState state) {
        return new CollectionElement(type, getter, setter, codegen, state);
D
Dmitry Jemerov 已提交
118 119
    }

120 121 122
    public static StackValue field(Type type, String owner, String name, boolean isStatic) {
        return new Field(type, owner, name, isStatic);
    }
123

124 125
    public static Property property(String name, String methodOwner, String methodOwnerParam, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter, int invokeOpcode) {
        return new Property(name, methodOwner, methodOwnerParam, getter, setter, isStatic, isInterface, isSuper, type, invokeOpcode);
126 127
    }

128 129 130 131
    public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
        return new Expression(type, expression, generator);
    }

132 133 134
    private static void box(final Type type, final Type toType, InstructionAdapter v) {
        // TODO handle toType correctly
        if (type == Type.INT_TYPE || (JetTypeMapper.isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
D
Dmitry Jemerov 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
            v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
        }
        else if (type == Type.BOOLEAN_TYPE) {
            v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
        }
        else if (type == Type.CHAR_TYPE) {
            v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
        }
        else if (type == Type.SHORT_TYPE) {
            v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
        }
        else if (type == Type.LONG_TYPE) {
            v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
        }
        else if (type == Type.BYTE_TYPE) {
            v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
        }
        else if (type == Type.FLOAT_TYPE) {
            v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
        }
        else if (type == Type.DOUBLE_TYPE) {
            v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
        }
    }

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
    private static void unbox(final Type type, InstructionAdapter v) {
        if (type == Type.INT_TYPE) {
            v.invokevirtual("java/lang/Number", "intValue", "()I");
        }
        else if (type == Type.BOOLEAN_TYPE) {
            v.invokevirtual("java/lang/Boolean", "booleanValue", "()Z");
        }
        else if (type == Type.CHAR_TYPE) {
            v.invokevirtual("java/lang/Character", "charValue", "()C");
        }
        else if (type == Type.SHORT_TYPE) {
            v.invokevirtual("java/lang/Number", "shortValue", "()S");
        }
        else if (type == Type.LONG_TYPE) {
            v.invokevirtual("java/lang/Number", "longValue", "()J");
        }
        else if (type == Type.BYTE_TYPE) {
            v.invokevirtual("java/lang/Number", "byteValue", "()B");
        }
        else if (type == Type.FLOAT_TYPE) {
            v.invokevirtual("java/lang/Number", "floatValue", "()F");
        }
        else if (type == Type.DOUBLE_TYPE) {
            v.invokevirtual("java/lang/Number", "doubleValue", "()D");
        }
    }

M
Maxim Shafirov 已提交
187
    public void upcast(Type type, InstructionAdapter v) {
M
Maxim Shafirov 已提交
188 189 190 191 192
        if (type.equals(this.type)) return;

        if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
            v.checkcast(type);
        }
M
Maxim Shafirov 已提交
193 194 195 196 197 198 199 200
        else {
            coerce(type, v);
        }
    }

    protected void coerce(Type type, InstructionAdapter v) {
        if (type.equals(this.type)) return;

A
Alex Tkachman 已提交
201 202 203 204 205 206 207 208
        if (type.getSort() == Type.VOID && this.type.getSort() != Type.VOID) {
            if(this.type.getSize() == 1)
                v.pop();
            else
                v.pop2();
        }
        else if (type.getSort() != Type.VOID && this.type.getSort() == Type.VOID) {
            if(type.getSort() == Type.OBJECT)
209
                v.visitFieldInsn(Opcodes.GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
A
Alex Tkachman 已提交
210 211 212 213 214 215 216 217 218
            else if(type == Type.LONG_TYPE)
                v.lconst(0);
            else if(type == Type.FLOAT_TYPE)
                v.fconst(0);
            else if(type == Type.DOUBLE_TYPE)
                v.dconst(0);
            else
                v.iconst(0);
        }
A
Alex Tkachman 已提交
219
        else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) {
220
                v.checkcast(type);
M
Maxim Shafirov 已提交
221
        }
M
Maxim Shafirov 已提交
222
        else if (type.getSort() == Type.OBJECT) {
223 224 225 226 227
            if(this.type.getSort() == Type.OBJECT && !type.equals(JetTypeMapper.TYPE_OBJECT)) {
                v.checkcast(type);
            }
            else
                box(this.type, type, v);
D
Dmitry Jemerov 已提交
228
        }
229
        else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
M
Maxim Shafirov 已提交
230
            if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
231
                if (type.getSort() == Type.BOOLEAN) {
232
                    v.checkcast(JvmPrimitiveType.BOOLEAN.getWrapper().getAsmType());
233
                }
A
Alex Tkachman 已提交
234
                else if (type.getSort() == Type.CHAR) {
235
                    v.checkcast(JvmPrimitiveType.CHAR.getWrapper().getAsmType());
A
Alex Tkachman 已提交
236
                }
237
                else {
A
Alex Tkachman 已提交
238
                    v.checkcast(JetTypeMapper.JL_NUMBER_TYPE);
239
                }
M
Maxim Shafirov 已提交
240
            }
241 242
            unbox(type, v);
        }
M
Maxim Shafirov 已提交
243
        else {
D
Dmitry Jemerov 已提交
244 245 246 247
            v.cast(this.type, type);
        }
    }

D
Dmitry Jemerov 已提交
248 249 250
    protected void putAsBoolean(InstructionAdapter v) {
        Label ifTrue = new Label();
        Label end = new Label();
251
        condJump(ifTrue, false, v);
D
Dmitry Jemerov 已提交
252 253 254 255 256 257 258
        v.iconst(0);
        v.goTo(end);
        v.mark(ifTrue);
        v.iconst(1);
        v.mark(end);
    }

259 260 261
    public static StackValue none() {
        return None.INSTANCE;
    }
A
Alex Tkachman 已提交
262 263 264 265 266

    public static StackValue fieldForSharedVar(Type type, String name, String fieldName) {
        return new FieldForSharedVar(type, name, fieldName);
    }

267 268 269 270
    public static StackValue composed(StackValue prefix, StackValue suffix) {
        return new Composed(prefix, suffix);
    }

271 272 273 274
    public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
        return new ThisOuter(codegen, descriptor);
    }

A
Alex Tkachman 已提交
275 276 277 278 279 280 281 282
    public static StackValue postIncrement(int index, int increment) {
        return new PostIncrement(index, increment);
    }

    public static StackValue preIncrement(int index, int increment) {
        return new PreIncrement(index, increment);
    }

S
Stepan Koltsov 已提交
283
    public static StackValue receiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, @Nullable CallableMethod callableMethod, GenerationState state) {
284
        if(resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists())
S
Stepan Koltsov 已提交
285
            return new CallReceiver(resolvedCall, receiver, codegen, state, callableMethod);
286 287 288
        return receiver;
    }

289 290 291 292 293 294 295 296
    private static class None extends StackValue {
        public static None INSTANCE = new None();
        private None() {
            super(Type.VOID_TYPE);
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
297
            coerce(type, v);
298 299 300
        }
    }

301
    public static class Local extends StackValue {
302
        final int index;
303

D
Dmitry Jemerov 已提交
304
        public Local(int index, Type type) {
D
Dmitry Jemerov 已提交
305
            super(type);
306 307 308 309 310
            this.index = index;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
D
Dmitry Jemerov 已提交
311
            v.load(index, this.type);
D
Dmitry Jemerov 已提交
312
            coerce(type, v);
D
Dmitry Jemerov 已提交
313
            // TODO unbox
314
        }
315 316

        @Override
317
        public void store(InstructionAdapter v) {
318
            v.store(index, this.type);
319
        }
320 321 322 323
    }

    public static class OnStack extends StackValue {
        public OnStack(Type type) {
D
Dmitry Jemerov 已提交
324
            super(type);
325 326 327 328
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
329 330 331 332 333 334 335 336 337 338 339
            if (type == Type.VOID_TYPE && this.type != Type.VOID_TYPE) {
                if (this.type.getSize() == 2) {
                    v.pop2();
                }
                else {
                    v.pop();
                }
            }
            else {
                coerce(type, v);
            }
340 341 342 343 344 345
        }
    }

    public static class Constant extends StackValue {
        private final Object value;

D
Dmitry Jemerov 已提交
346 347
        public Constant(Object value, Type type) {
            super(type);
348 349 350 351 352
            this.value = value;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365
            if(value instanceof Integer)
                v.iconst((Integer) value);
            else
            if(value instanceof Long)
                v.lconst((Long) value);
            else
            if(value instanceof Float)
                v.fconst((Float) value);
            else
            if(value instanceof Double)
                v.dconst((Double) value);
            else
                v.aconst(value);
D
Dmitry Jemerov 已提交
366
            coerce(type, v);
367
        }
368 369

        @Override
370
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
D
Dmitry Jemerov 已提交
371
            if (value instanceof Boolean) {
A
Alex Tkachman 已提交
372
                boolean boolValue = (Boolean) value;
373 374 375
                if (boolValue ^ jumpIfFalse) {
                    v.goTo(label);
                }
D
Dmitry Jemerov 已提交
376 377 378 379
            }
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
380 381 382
        }
    }

D
Float  
Dmitry Jemerov 已提交
383
    private static class NumberCompare extends StackValue {
D
Dmitry Jemerov 已提交
384
        protected final IElementType opToken;
D
Dmitry Jemerov 已提交
385
        private final Type operandType;
386

D
Dmitry Jemerov 已提交
387 388
        public NumberCompare(IElementType opToken, Type operandType) {
            super(Type.BOOLEAN_TYPE);
389
            this.opToken = opToken;
D
Dmitry Jemerov 已提交
390
            this.operandType = operandType;
391 392 393 394
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
395 396 397
            if (type == Type.VOID_TYPE) {
                return;
            }
398
            if (type != Type.BOOLEAN_TYPE) {
399
                throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type " + type);
400
            }
D
Dmitry Jemerov 已提交
401
            putAsBoolean(v);
402 403 404
        }

        @Override
405
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
406
            int opcode;
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
            if (opToken == JetTokens.EQEQ) {
                opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ;
            }
            else if (opToken == JetTokens.EXCLEQ) {
                opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE;
            }
            else if (opToken == JetTokens.GT) {
                opcode = jumpIfFalse ? Opcodes.IFLE : Opcodes.IFGT;
            }
            else if (opToken == JetTokens.GTEQ) {
                opcode = jumpIfFalse ? Opcodes.IFLT : Opcodes.IFGE;
            }
            else if (opToken == JetTokens.LT) {
                opcode = jumpIfFalse ? Opcodes.IFGE : Opcodes.IFLT;
            }
            else if (opToken == JetTokens.LTEQ) {
                opcode = jumpIfFalse ? Opcodes.IFGT : Opcodes.IFLE;
            }
425 426 427
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
D
Dmitry Jemerov 已提交
428
            if (operandType == Type.FLOAT_TYPE || operandType == Type.DOUBLE_TYPE) {
D
Float  
Dmitry Jemerov 已提交
429
                if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) {
D
Dmitry Jemerov 已提交
430
                    v.cmpg(operandType);
D
Float  
Dmitry Jemerov 已提交
431 432
                }
                else {
D
Dmitry Jemerov 已提交
433
                    v.cmpl(operandType);
D
Float  
Dmitry Jemerov 已提交
434 435
                }
            }
D
Dmitry Jemerov 已提交
436
            else if (operandType == Type.LONG_TYPE) {
D
Dmitry Jemerov 已提交
437 438
                v.lcmp();
            }
D
Float  
Dmitry Jemerov 已提交
439 440 441
            else {
                opcode += (Opcodes.IF_ICMPEQ - Opcodes.IFEQ);
            }
442
            v.visitJumpInsn(opcode, label);
443
        }
444
    }
D
Dmitry Jemerov 已提交
445

D
Dmitry Jemerov 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
    private static class ObjectCompare extends NumberCompare {
        public ObjectCompare(IElementType opToken, Type operandType) {
            super(opToken, operandType);
        }

        @Override
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
            int opcode;
            if (opToken == JetTokens.EQEQEQ) {
                opcode = jumpIfFalse ? Opcodes.IF_ACMPNE : Opcodes.IF_ACMPEQ;
            }
            else if (opToken == JetTokens.EXCLEQEQEQ) {
                opcode = jumpIfFalse ? Opcodes.IF_ACMPEQ : Opcodes.IF_ACMPNE;
            }
            else {
                throw new UnsupportedOperationException("don't know how to generate this condjump");
            }
            v.visitJumpInsn(opcode, label);
        }
    }

D
Dmitry Jemerov 已提交
467 468 469 470
    private static class Invert extends StackValue {
        private StackValue myOperand;

        private Invert(StackValue operand) {
A
Alex Tkachman 已提交
471
            super(Type.BOOLEAN_TYPE);
D
Dmitry Jemerov 已提交
472
            myOperand = operand;
A
Alex Tkachman 已提交
473 474
            if(myOperand.type != Type.BOOLEAN_TYPE)
                throw new UnsupportedOperationException("operand of ! must be boolean");
D
Dmitry Jemerov 已提交
475 476 477 478 479 480 481 482 483 484 485
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if (type != Type.BOOLEAN_TYPE) {
                throw new UnsupportedOperationException("don't know how to put a compare as a non-boolean type");
            }
            putAsBoolean(v);
        }

        @Override
486 487
        public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
            myOperand.condJump(label, !jumpIfFalse, v);
D
Dmitry Jemerov 已提交
488 489
        }
    }
490 491

    private static class ArrayElement extends StackValue {
A
Alex Tkachman 已提交
492
        private Type boxed;
493

A
Alex Tkachman 已提交
494
        public ArrayElement(Type type, boolean unbox) {
495
            super(type);
A
Alex Tkachman 已提交
496
            this.boxed = unbox ? JetTypeMapper.boxType(type) : type;
497 498 499 500
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
501 502
            v.aload(boxed);    // assumes array and index are on the stack
            onStack(boxed).coerce(type, v);
503 504 505
        }

        @Override
506
        public void store(InstructionAdapter v) {
A
Alex Tkachman 已提交
507 508
            onStack(type).coerce(boxed, v);
            v.astore(boxed);
509
        }
510 511

        @Override
512 513
        public void dupReceiver(InstructionAdapter v) {
            v.dup2();   // array and index
514
        }
A
Alex Tkachman 已提交
515 516 517 518

        public int receiverSize() {
            return 2;
        }
519 520
    }

D
Dmitry Jemerov 已提交
521
    private static class CollectionElement extends StackValue {
522 523
        private final Callable getter;
        private final Callable setter;
524
        private final ExpressionCodegen codegen;
S
Stepan Koltsov 已提交
525
        private final GenerationState state;
526
        private final FrameMap frame;
527 528 529 530
        private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
        private final ResolvedCall<FunctionDescriptor> resolvedSetCall;
        private final FunctionDescriptor setterDescriptor;
        private final FunctionDescriptor getterDescriptor;
D
Dmitry Jemerov 已提交
531

S
Stepan Koltsov 已提交
532
        public CollectionElement(Type type, ResolvedCall<FunctionDescriptor> resolvedGetCall, ResolvedCall<FunctionDescriptor> resolvedSetCall, ExpressionCodegen codegen, GenerationState state) {
D
Dmitry Jemerov 已提交
533
            super(type);
534 535
            this.resolvedGetCall = resolvedGetCall;
            this.resolvedSetCall = resolvedSetCall;
S
Stepan Koltsov 已提交
536
            this.state = state;
537 538
            this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
            this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
539 540
            this.setter = resolvedSetCall == null ? null : codegen.resolveToCallable(setterDescriptor, false);
            this.getter = resolvedGetCall == null ? null : codegen.resolveToCallable(getterDescriptor, false);
541 542
            this.codegen = codegen;
            this.frame = codegen.myFrameMap;
D
Dmitry Jemerov 已提交
543 544 545 546 547 548 549
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if (getter == null) {
                throw new UnsupportedOperationException("no getter specified");
            }
550 551 552
            if(getter instanceof CallableMethod)
                ((CallableMethod)getter).invoke(v);
            else
S
Stepan Koltsov 已提交
553
                ((IntrinsicMethod)getter).generate(codegen, v, null, null, null, null, state);
A
Alex Tkachman 已提交
554
            coerce(type, v);
D
Dmitry Jemerov 已提交
555 556 557 558 559 560 561
        }

        @Override
        public void store(InstructionAdapter v) {
            if (setter == null) {
                throw new UnsupportedOperationException("no setter specified");
            }
562 563 564 565 566 567 568 569 570 571 572
            if(setter instanceof CallableMethod) {
                CallableMethod method = (CallableMethod) setter;
                method.invoke(v);
                Type returnType = method.getSignature().getAsmMethod().getReturnType();
                if(returnType != Type.VOID_TYPE) {
                    if(returnType.getSize() == 2)
                        v.pop2();
                    else
                        v.pop();
                }
            }
573
            else
S
Stepan Koltsov 已提交
574
                ((IntrinsicMethod) setter).generate(codegen, v, null, null, null, null, state);
D
Dmitry Jemerov 已提交
575 576
        }

A
Alex Tkachman 已提交
577
        public int receiverSize() {
578
            if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
A
Alex Tkachman 已提交
579 580 581 582 583 584 585
                return 2;
            }
            else {
                return -1;
            }
        }

D
Dmitry Jemerov 已提交
586
        @Override
587
        public void dupReceiver(InstructionAdapter v) {
588
            if(isStandardStack(resolvedGetCall, 1) && isStandardStack(resolvedSetCall, 2)) {
589
                v.dup2();   // collection and index
D
Dmitry Jemerov 已提交
590 591
            }
            else {
592 593
                int size = 0;
                int lastIndex = frame.enterTemp();
594 595
                frame.leaveTemp();
                
596 597 598 599
                // indexes
                List<ValueParameterDescriptor> valueParameters = resolvedGetCall.getResultingDescriptor().getValueParameters();
                int firstParamIndex = -1;
                for(int i = valueParameters.size()-1; i >= 0; --i) {
600
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
601
                    int sz = type.getSize();
602 603
                    frame.enterTemp(sz);
                    lastIndex += sz;
604 605 606 607 608 609 610 611 612 613 614 615 616
                    size += sz;
                    v.store((firstParamIndex = lastIndex)-sz, type);
                }

                List<TypeParameterDescriptor> typeParameters = resolvedGetCall.getResultingDescriptor().getTypeParameters();
                int firstTypeParamIndex = -1;
                for(int i = typeParameters.size()-1; i >= 0; --i)  {
                    if(typeParameters.get(i).isReified()) {
                        frame.enterTemp();
                        lastIndex++;
                        size++;
                        v.store(firstTypeParamIndex = lastIndex-1, JetTypeMapper.TYPE_OBJECT);
                    }
617 618
                }

619 620 621 622 623 624 625 626 627 628 629 630 631 632
                ReceiverDescriptor receiverParameter = resolvedGetCall.getReceiverArgument();
                int receiverIndex = -1;
                if(receiverParameter.exists()) {
                    Type type = codegen.typeMapper.mapType(receiverParameter.getType());
                    int sz = type.getSize();
                    frame.enterTemp(sz);
                    lastIndex += sz;
                    size += sz;
                    v.store((receiverIndex = lastIndex)-sz, type);
                }

                ReceiverDescriptor thisObject = resolvedGetCall.getThisObject();
                int thisIndex = -1;
                if(thisObject.exists()) {
633 634
                    frame.enterTemp();
                    lastIndex++;
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
                    size++;
                    v.store((thisIndex = lastIndex)-1, JetTypeMapper.TYPE_OBJECT);
                }
                
                // for setter

                int  realReceiverIndex;
                Type realReceiverType;
                if(thisIndex != -1) {
                    if(receiverIndex != -1) {
                        realReceiverIndex = receiverIndex;
                        realReceiverType =  codegen.typeMapper.mapType(receiverParameter.getType());
                    }
                    else {
                        realReceiverIndex = thisIndex;
                        realReceiverType = JetTypeMapper.TYPE_OBJECT;
                    }
                }
                else {
                    if(receiverIndex != -1) {
                        realReceiverType =  codegen.typeMapper.mapType(receiverParameter.getType());
                        realReceiverIndex = receiverIndex;
                    }
                    else {
                        throw new UnsupportedOperationException();
                    }
661 662
                }

663 664
                if(resolvedSetCall.getThisObject().exists()) {
                    if(resolvedSetCall.getReceiverArgument().exists()) {
665
                        codegen.generateFromResolvedCall(resolvedSetCall.getThisObject(), JetTypeMapper.TYPE_OBJECT);
666 667 668 669 670 671 672 673 674 675
                    }
                    v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType);
                }
                else {
                    if(resolvedSetCall.getReceiverArgument().exists()) {
                        v.load(realReceiverIndex - realReceiverType.getSize(), realReceiverType);
                    }
                    else {
                        throw new UnsupportedOperationException();
                    }
676 677
                }

678 679
                int index = firstParamIndex;
                for(int i = 0; i != valueParameters.size(); ++i) {
680
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
681 682 683
                    int sz = type.getSize();
                    v.load(index-sz, type);
                    index -= sz;
684 685
                }

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
                // restoring original
                if(thisIndex != -1) {
                    v.load(thisIndex-1, JetTypeMapper.TYPE_OBJECT);
                }
                
                if(receiverIndex != -1) {
                    Type type = codegen.typeMapper.mapType(receiverParameter.getType());
                    v.load(receiverIndex-type.getSize(), type);
                }

                if(firstTypeParamIndex != -1) {
                    index = firstTypeParamIndex;
                    for(int i = 0; i != typeParameters.size(); ++i)  {
                        if(typeParameters.get(i).isReified()) {
                            v.load(index-1, JetTypeMapper.TYPE_OBJECT);
                            index--;
                        }
                    }
                }
                
                index = firstParamIndex;
                for(int i = 0; i != valueParameters.size(); ++i) {
708
                    Type type = codegen.typeMapper.mapType(valueParameters.get(i).getType());
709 710 711
                    int sz = type.getSize();
                    v.load(index-sz, type);
                    index -= sz;
712 713 714
                }

                frame.leaveTemp(size);
D
Dmitry Jemerov 已提交
715 716
            }
        }
717

718
        private boolean isStandardStack(ResolvedCall call, int valueParamsSize) {
A
Alex Tkachman 已提交
719 720 721
            if(call == null)
                return true;

722 723 724 725 726
            for (TypeParameterDescriptor typeParameterDescriptor : call.getResultingDescriptor().getTypeParameters()) {
                if(typeParameterDescriptor.isReified())
                    return false;
            }

727 728
            List<ValueParameterDescriptor> valueParameters = call.getResultingDescriptor().getValueParameters();
            if(valueParameters.size() != valueParamsSize)
729 730
                return false;

731
            for (ValueParameterDescriptor valueParameter : valueParameters) {
732
                if (codegen.typeMapper.mapType(valueParameter.getType()).getSize() != 1)
733 734 735
                    return false;
            }

736 737 738 739 740 741 742 743 744 745
            if(call.getThisObject().exists()) {
                if(call.getReceiverArgument().exists())
                    return false;
            }
            else {
                if(codegen.typeMapper.mapType(call.getResultingDescriptor().getReceiverParameter().getType()).getSize() != 1)
                    return false;
            }

            return true;
746
        }
D
Dmitry Jemerov 已提交
747 748
    }

M
Maxim Shafirov 已提交
749

A
Alex Tkachman 已提交
750 751 752
    static class Field extends StackValue {
        final String owner;
        final String name;
753 754 755 756 757 758 759 760 761 762 763 764
        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());
765
            coerce(type, v);
766 767 768
        }

        @Override
769
        public void dupReceiver(InstructionAdapter v) {
D
Dmitry Jemerov 已提交
770
            if (!isStatic) {
771
                v.dup();
D
Dmitry Jemerov 已提交
772
            }
773 774
        }

A
Alex Tkachman 已提交
775 776 777 778
        public int receiverSize() {
            return isStatic ? 0 : 1;
        }

779 780
        @Override
        public void store(InstructionAdapter v) {
781 782 783
            v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
        }
    }
784

785
    static class Property extends StackValue {
786
        @NotNull
787
        private final String name;
788
        @Nullable
789
        private final Method getter;
790
        @Nullable
791
        private final Method setter;
792 793 794 795
        @NotNull
        public final String methodOwner;
        @NotNull
        private final String methodOwnerParam;
796
        private final boolean isStatic;
797
        private final boolean isInterface;
798 799
        private final boolean isSuper;
        private final int invokeOpcode;
800

801
        public Property(@NotNull String name, @NotNull String methodOwner, @NotNull String methodOwnerParam, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type, int invokeOpcode) {
802 803
            super(type);
            this.name = name;
804 805
            this.methodOwner = methodOwner;
            this.methodOwnerParam = methodOwnerParam;
806 807
            this.getter = getter;
            this.setter = setter;
808
            isStatic = aStatic;
809
            this.isInterface = isInterface;
A
Alex Tkachman 已提交
810
            this.isSuper = isSuper;
811 812 813 814 815 816
            this.invokeOpcode = invokeOpcode;
            if (invokeOpcode == 0) {
                if (setter != null || getter != null) {
                    throw new IllegalArgumentException();
                }
            }
817 818 819 820
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
A
Alex Tkachman 已提交
821
            if(isSuper && isInterface) {
822
                v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, getter.getName(), getter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";"));
823 824
            }
            else {
A
Alex Tkachman 已提交
825
            if (getter == null) {
826
                v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, methodOwner, name, this.type.getDescriptor());
A
Alex Tkachman 已提交
827 828
            }
            else {
829
                v.visitMethodInsn(invokeOpcode, methodOwner, getter.getName(), getter.getDescriptor());
A
Alex Tkachman 已提交
830
            }
831
            }
832
            coerce(type, v);
833 834 835 836
        }

        @Override
        public void store(InstructionAdapter v) {
A
Alex Tkachman 已提交
837
            if(isSuper && isInterface) {
838
                v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, setter.getName(), setter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";"));
839 840
            }
            else {
A
Alex Tkachman 已提交
841
            if (setter == null) {
842
                v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, methodOwner, name, this.type.getDescriptor());
A
Alex Tkachman 已提交
843 844
            }
            else {
845
                v.visitMethodInsn(invokeOpcode, methodOwner, setter.getName(), setter.getDescriptor());
A
Alex Tkachman 已提交
846
                }
847 848
            }
        }
849 850

        @Override
851
        public void dupReceiver(InstructionAdapter v) {
852
            if (!isStatic) {
853
                v.dup();
854 855
            }
        }
A
Alex Tkachman 已提交
856 857 858 859

        public int receiverSize() {
            return isStatic ? 0 : 1;
        }
860
    }
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876

    private static class Expression extends StackValue {
        private final JetExpression expression;
        private final ExpressionCodegen generator;

        public Expression(Type type, JetExpression expression, ExpressionCodegen generator) {
            super(type);
            this.expression = expression;
            this.generator = generator;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            generator.gen(expression, type);
        }
    }
A
Alex Tkachman 已提交
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923

    public static class Shared extends StackValue {
        private final int index;

        public Shared(int index, Type type) {
            super(type);
            this.index = index;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            v.load(index, JetTypeMapper.TYPE_OBJECT);
            Type refType = refType(this.type);
            Type sharedType = sharedTypeForType(this.type);
            v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
            StackValue.onStack(refType).coerce(this.type, v);
            StackValue.onStack(this.type).coerce(type, v);
        }

        @Override
        public void store(InstructionAdapter v) {
            v.load(index, JetTypeMapper.TYPE_OBJECT);
            v.swap();
            Type refType = refType(this.type);
            Type sharedType = sharedTypeForType(this.type);
            v.visitFieldInsn(Opcodes.PUTFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
        }
    }

    public static Type sharedTypeForType(Type type) {
        switch(type.getSort()) {
            case Type.OBJECT:
            case Type.ARRAY:
                return JetTypeMapper.TYPE_SHARED_VAR;

            case Type.BYTE:
                return JetTypeMapper.TYPE_SHARED_BYTE;

            case Type.SHORT:
                return JetTypeMapper.TYPE_SHARED_SHORT;

            case Type.CHAR:
                return JetTypeMapper.TYPE_SHARED_CHAR;

            case Type.INT:
                return JetTypeMapper.TYPE_SHARED_INT;

A
varargs  
Alex Tkachman 已提交
924 925 926
            case Type.LONG:
                return JetTypeMapper.TYPE_SHARED_LONG;

A
Alex Tkachman 已提交
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
            case Type.BOOLEAN:
                return JetTypeMapper.TYPE_SHARED_BOOLEAN;

            case Type.FLOAT:
                return JetTypeMapper.TYPE_SHARED_FLOAT;

            case Type.DOUBLE:
                return JetTypeMapper.TYPE_SHARED_DOUBLE;

            default:
                throw new UnsupportedOperationException();
        }
    }

    public static Type refType(Type type) {
        if(type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY)
            return JetTypeMapper.TYPE_OBJECT;

        return type;
    }

    static class FieldForSharedVar extends StackValue {
        final String owner;
        final String name;

        public FieldForSharedVar(Type type, String owner, String name) {
            super(type);
            this.owner = owner;
            this.name = name;
        }

        @Override
959 960
        public void dupReceiver(InstructionAdapter v) {
            v.dup();
A
Alex Tkachman 已提交
961 962
        }

A
Alex Tkachman 已提交
963 964 965 966
        public int receiverSize() {
            return 1;
        }

A
Alex Tkachman 已提交
967 968 969 970 971 972 973 974 975 976 977 978 979 980
        @Override
        public void put(Type type, InstructionAdapter v) {
            Type sharedType = sharedTypeForType(this.type);
            Type refType = refType(this.type);
            v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
            StackValue.onStack(refType).coerce(this.type, v);
            StackValue.onStack(this.type).coerce(type, v);
        }

        @Override
        public void store(InstructionAdapter v) {
            v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
        }
    }
981

A
Alex Tkachman 已提交
982 983 984
    public static class Composed extends StackValue {
        public final StackValue prefix;
        public final StackValue suffix;
985 986 987 988 989 990 991 992 993 994 995 996

        public Composed(StackValue prefix, StackValue suffix) {
            super(suffix.type);
            this.prefix = prefix;
            this.suffix = suffix;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            prefix.put(prefix.type, v);
            suffix.put(type, v);
        }
A
Alex Tkachman 已提交
997 998 999 1000 1001 1002

        @Override
        public void store(InstructionAdapter v) {
            prefix.put(JetTypeMapper.TYPE_OBJECT, v);
            suffix.store(v);
        }
1003
    }
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019

    private static class ThisOuter extends StackValue {
        private ExpressionCodegen codegen;
        private ClassDescriptor descriptor;

        public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
            super(JetTypeMapper.TYPE_OBJECT);
            this.codegen = codegen;
            this.descriptor = descriptor;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            codegen.generateThisOrOuter(descriptor);
        }
    }
A
Alex Tkachman 已提交
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059

    private static class PostIncrement extends StackValue {
        private int index;
        private int increment;

        public PostIncrement(int index, int increment) {
            super(Type.INT_TYPE);
            this.index = index;
            this.increment = increment;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            if(!type.equals(Type.VOID_TYPE)) {
                v.load(index, Type.INT_TYPE);
                coerce(type, v);
            }
            v.iinc(index, increment);
        }
    }

    private static class PreIncrement extends StackValue {
        private int index;
        private int increment;

        public PreIncrement(int index, int increment) {
            super(Type.INT_TYPE);
            this.index = index;
            this.increment = increment;
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            v.iinc(index, increment);
            if(!type.equals(Type.VOID_TYPE)) {
                v.load(index, Type.INT_TYPE);
                coerce(type, v);
            }
        }
    }
1060 1061 1062 1063 1064

    public static class CallReceiver extends StackValue {
        private ResolvedCall<? extends CallableDescriptor> resolvedCall;
        StackValue receiver;
        private ExpressionCodegen codegen;
S
Stepan Koltsov 已提交
1065 1066
        @NotNull
        private final GenerationState state;
1067 1068
        private CallableMethod callableMethod;

S
Stepan Koltsov 已提交
1069
        public CallReceiver(ResolvedCall<? extends CallableDescriptor> resolvedCall, StackValue receiver, ExpressionCodegen codegen, @NotNull GenerationState state, CallableMethod callableMethod) {
1070 1071 1072 1073
            super(calcType(resolvedCall, codegen, callableMethod));
            this.resolvedCall = resolvedCall;
            this.receiver = receiver;
            this.codegen = codegen;
S
Stepan Koltsov 已提交
1074
            this.state = state;
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
            this.callableMethod = callableMethod;
        }

        private static Type calcType(ResolvedCall<? extends CallableDescriptor> resolvedCall, ExpressionCodegen codegen, CallableMethod callableMethod) {
            ReceiverDescriptor thisObject = resolvedCall.getThisObject();
            ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();

            CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();

            if (thisObject.exists()) {
                if(callableMethod != null) {
                    if(receiverArgument.exists()) {
                        return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
                    }
                    else {
A
Alex Tkachman 已提交
1090
                        return codegen.typeMapper.mapType(callableMethod.getThisType());
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
                    }
                }
                else {
                    if(receiverArgument.exists()) {
                        return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
                    }
                    else {
                        return codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType());
                    }
                }
            }
            else {
                if (receiverArgument.exists()) {
                    if(callableMethod != null)
                        return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
                    else
                        return codegen.typeMapper.mapType(descriptor.getReceiverParameter().getType());
                }
                else {
                    return Type.VOID_TYPE;
                }
            }
        }

        @Override
        public void put(Type type, InstructionAdapter v) {
            CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();

            ReceiverDescriptor thisObject = resolvedCall.getThisObject();
            ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
            if (thisObject.exists()) {
                if(receiverArgument.exists()) {
1123
                    codegen.generateFromResolvedCall(thisObject, callableMethod != null ? Type.getObjectType(callableMethod.getOwner()) : codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType()));
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
                    genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
                }
                else {
                    genReceiver(v, thisObject, type, null);
                }
            }
            else {
                if (receiverArgument.exists()) {
                    genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
                }
            }
        }

        private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, ReceiverDescriptor receiverParameter) {
            if(receiver == StackValue.none()) {
                if(receiverParameter != null) {
                    Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType());
                    codegen.generateFromResolvedCall(receiverArgument, receiverType);
                    StackValue.onStack(receiverType).put(type, v);
                }
                else {
                    codegen.generateFromResolvedCall(receiverArgument, type);
                }
            }
            else {
                receiver.put(type, v);
            }
        }
    }
1153
}