001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Maps;
021 import com.intellij.openapi.editor.Document;
022 import com.intellij.openapi.progress.ProcessCanceledException;
023 import com.intellij.psi.PsiElement;
024 import com.intellij.psi.tree.IElementType;
025 import com.intellij.util.ArrayUtil;
026 import com.intellij.util.Function;
027 import com.intellij.util.containers.Stack;
028 import org.jetbrains.annotations.NotNull;
029 import org.jetbrains.annotations.Nullable;
030 import org.jetbrains.asm4.Label;
031 import org.jetbrains.asm4.MethodVisitor;
032 import org.jetbrains.asm4.Type;
033 import org.jetbrains.asm4.commons.InstructionAdapter;
034 import org.jetbrains.asm4.commons.Method;
035 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
036 import org.jetbrains.jet.codegen.binding.CodegenBinding;
037 import org.jetbrains.jet.codegen.binding.MutableClosure;
038 import org.jetbrains.jet.codegen.context.*;
039 import org.jetbrains.jet.codegen.inline.InlineCodegen;
040 import org.jetbrains.jet.codegen.inline.NameGenerator;
041 import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
042 import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
043 import org.jetbrains.jet.codegen.state.GenerationState;
044 import org.jetbrains.jet.codegen.state.JetTypeMapper;
045 import org.jetbrains.jet.lang.descriptors.*;
046 import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
047 import org.jetbrains.jet.lang.evaluate.EvaluatePackage;
048 import org.jetbrains.jet.lang.psi.*;
049 import org.jetbrains.jet.lang.resolve.BindingContext;
050 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
051 import org.jetbrains.jet.lang.resolve.calls.model.*;
052 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
053 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
054 import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant;
055 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
056 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
057 import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor;
058 import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
059 import org.jetbrains.jet.lang.resolve.name.Name;
060 import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
061 import org.jetbrains.jet.lang.types.JetType;
062 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
063 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
064 import org.jetbrains.jet.lexer.JetTokens;
065 import org.jetbrains.jet.renderer.DescriptorRenderer;
066
067 import java.util.*;
068
069 import static org.jetbrains.asm4.Opcodes.*;
070 import static org.jetbrains.jet.codegen.AsmUtil.*;
071 import static org.jetbrains.jet.codegen.CodegenUtil.*;
072 import static org.jetbrains.jet.codegen.FunctionTypesUtil.functionTypeToImpl;
073 import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplType;
074 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
075 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
076 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
077 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
078 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
079 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
080 import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
081
082 public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup, ParentCodegenAware {
083 private static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges();
084
085 private int myLastLineNumber = -1;
086
087 public final InstructionAdapter v;
088 final MethodVisitor methodVisitor;
089 final FrameMap myFrameMap;
090 final JetTypeMapper typeMapper;
091
092 private final GenerationState state;
093 private final Type returnType;
094
095 private final BindingContext bindingContext;
096 final MethodContext context;
097 private final CodegenStatementVisitor statementVisitor;
098
099 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
100
101 @Nullable
102 private final MemberCodegen parentCodegen;
103
104 /*
105 * When we create a temporary variable to hold some value not to compute it many times
106 * we put it into this map to emit access to that variable instead of evaluating the whole expression
107 */
108 private final Map<JetElement, StackValue.Local> tempVariables = Maps.newHashMap();
109 @NotNull
110 private final TailRecursionCodegen tailRecursionCodegen;
111
112 public final CallGenerator defaulCallGenerator;
113
114 public CalculatedClosure generateObjectLiteral(GenerationState state, JetObjectLiteralExpression literal) {
115 JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
116
117 Type asmType = asmTypeForAnonymousClass(bindingContext, objectDeclaration);
118 ClassBuilder classBuilder = state.getFactory().newVisitor(asmType, literal.getContainingFile());
119
120 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration);
121 assert classDescriptor != null;
122
123 //noinspection SuspiciousMethodCalls
124 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
125
126 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this);
127 ImplementationBodyCodegen implementationBodyCodegen =
128 new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, getParentCodegen());
129
130 implementationBodyCodegen.generate();
131
132 return closure;
133 }
134
135 static class BlockStackElement {
136 }
137
138 static class LoopBlockStackElement extends BlockStackElement {
139 final Label continueLabel;
140 final Label breakLabel;
141 public final JetSimpleNameExpression targetLabel;
142
143 LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) {
144 this.breakLabel = breakLabel;
145 this.continueLabel = continueLabel;
146 this.targetLabel = targetLabel;
147 }
148 }
149
150 static class FinallyBlockStackElement extends BlockStackElement {
151 List<Label> gaps = new ArrayList<Label>();
152
153 final JetTryExpression expression;
154
155 FinallyBlockStackElement(JetTryExpression expression) {
156 this.expression = expression;
157 }
158
159 private void addGapLabel(Label label){
160 gaps.add(label);
161 }
162 }
163
164 public ExpressionCodegen(
165 @NotNull MethodVisitor v,
166 @NotNull FrameMap myMap,
167 @NotNull Type returnType,
168 @NotNull MethodContext context,
169 @NotNull GenerationState state,
170 @Nullable MemberCodegen parentCodegen
171 ) {
172 this.myFrameMap = myMap;
173 this.parentCodegen = parentCodegen;
174 this.typeMapper = state.getTypeMapper();
175 this.returnType = returnType;
176 this.state = state;
177 this.methodVisitor = v;
178 this.v = new InstructionAdapter(methodVisitor);
179 this.bindingContext = state.getBindingContext();
180 this.context = context;
181 this.statementVisitor = new CodegenStatementVisitor(this);
182 this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
183 this.defaulCallGenerator = new CallGenerator.DefaultCallGenerator(this);
184 }
185
186 public GenerationState getState() {
187 return state;
188 }
189
190 @NotNull
191 private StackValue castToRequiredTypeOfInterfaceIfNeeded(
192 StackValue inner,
193 @NotNull ClassDescriptor provided,
194 @NotNull ClassDescriptor required
195 ) {
196 if (!isInterface(provided) && isInterface(required)) {
197 inner.put(OBJECT_TYPE, v);
198 Type type = asmType(required.getDefaultType());
199 v.checkcast(type);
200 return StackValue.onStack(type);
201 }
202
203 return inner;
204 }
205
206 public BindingContext getBindingContext() {
207 return bindingContext;
208 }
209
210 @Nullable
211 @Override
212 public MemberCodegen getParentCodegen() {
213 return parentCodegen;
214 }
215
216 public StackValue genQualified(StackValue receiver, JetElement selector) {
217 return genQualified(receiver, selector, this);
218 }
219
220 private StackValue genQualified(StackValue receiver, JetElement selector, JetVisitor<StackValue, StackValue> visitor) {
221 if (tempVariables.containsKey(selector)) {
222 throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector");
223 }
224 if (!(selector instanceof JetBlockExpression)) {
225 markLineNumber(selector);
226 }
227 try {
228 if (selector instanceof JetExpression) {
229 JetExpression expression = (JetExpression) selector;
230 JavaClassDescriptor samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression);
231 if (samInterface != null) {
232 return genSamInterfaceValue(expression, samInterface, visitor);
233 }
234 }
235
236 return selector.accept(visitor, receiver);
237 }
238 catch (ProcessCanceledException e) {
239 throw e;
240 }
241 catch (CompilationException e) {
242 throw e;
243 }
244 catch (Throwable error) {
245 String message = error.getMessage();
246 throw new CompilationException(message != null ? message : "null", error, selector);
247 }
248 }
249
250 public StackValue gen(JetElement expr) {
251 StackValue tempVar = tempVariables.get(expr);
252 return tempVar != null ? tempVar : genQualified(StackValue.none(), expr);
253 }
254
255 public void gen(JetElement expr, Type type) {
256 StackValue value = gen(expr);
257 value.put(type, v);
258 }
259
260 public void genToJVMStack(JetExpression expr) {
261 gen(expr, expressionType(expr));
262 }
263
264 private StackValue genStatement(JetElement statement) {
265 return genQualified(StackValue.none(), statement, statementVisitor);
266 }
267
268 @Override
269 public StackValue visitClass(@NotNull JetClass klass, StackValue data) {
270 return visitClassOrObject(klass);
271 }
272
273 private StackValue visitClassOrObject(JetClassOrObject declaration) {
274 ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration);
275 assert descriptor != null;
276
277 Type asmType = asmTypeForAnonymousClass(bindingContext, declaration);
278 ClassBuilder classBuilder = state.getFactory().newVisitor(asmType, declaration.getContainingFile());
279
280 ClassContext objectContext = context.intoAnonymousClass(descriptor, this);
281 new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen()).generate();
282 classBuilder.done();
283
284 return StackValue.none();
285 }
286
287 @Override
288 public StackValue visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, StackValue data) {
289 return visitClassOrObject(declaration);
290 }
291
292 @Override
293 public StackValue visitExpression(@NotNull JetExpression expression, StackValue receiver) {
294 throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented");
295 }
296
297 @Override
298 public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) {
299 return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true, true);
300 }
301
302 private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
303 return getSuperCallLabelTarget(expression, bindingContext, context);
304 }
305
306 @NotNull
307 private static ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression, BindingContext bindingContext, CodegenContext context) {
308 PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
309 ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
310 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
311 // "super<descriptor>@labelTarget"
312 if (labelTarget != null) {
313 return labelTarget;
314 }
315 assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
316 return getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor();
317 }
318
319 @NotNull
320 private Type asmType(@NotNull JetType type) {
321 return typeMapper.mapType(type);
322 }
323
324 @NotNull
325 private Type asmTypeOrVoid(@Nullable JetType type) {
326 return type == null ? Type.VOID_TYPE : asmType(type);
327 }
328
329 @Override
330 public StackValue visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, StackValue receiver) {
331 return genQualified(receiver, expression.getExpression());
332 }
333
334 @Override
335 public StackValue visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, StackValue receiver) {
336 return genQualified(receiver, expression.getBaseExpression());
337 }
338
339 private static boolean isEmptyExpression(@Nullable JetElement expr) {
340 if (expr == null) {
341 return true;
342 }
343 if (expr instanceof JetBlockExpression) {
344 JetBlockExpression blockExpression = (JetBlockExpression) expr;
345 List<JetElement> statements = blockExpression.getStatements();
346 if (statements.size() == 0 || statements.size() == 1 && isEmptyExpression(statements.get(0))) {
347 return true;
348 }
349 }
350 return false;
351 }
352
353 @Override
354 public StackValue visitIfExpression(@NotNull JetIfExpression expression, StackValue receiver) {
355 return generateIfExpression(expression, false);
356 }
357
358 /* package */ StackValue generateIfExpression(JetIfExpression expression, boolean isStatement) {
359 Type asmType = isStatement ? Type.VOID_TYPE : expressionType(expression);
360 StackValue condition = gen(expression.getCondition());
361
362 JetExpression thenExpression = expression.getThen();
363 JetExpression elseExpression = expression.getElse();
364
365 if (isEmptyExpression(thenExpression)) {
366 if (isEmptyExpression(elseExpression)) {
367 condition.put(asmType, v);
368 return StackValue.onStack(asmType);
369 }
370 return generateSingleBranchIf(condition, expression, elseExpression, false, isStatement);
371 }
372 else {
373 if (isEmptyExpression(elseExpression)) {
374 return generateSingleBranchIf(condition, expression, thenExpression, true, isStatement);
375 }
376 }
377
378 Label elseLabel = new Label();
379 condition.condJump(elseLabel, true, v); // == 0, i.e. false
380
381 Label end = new Label();
382
383 gen(thenExpression, asmType);
384
385 v.goTo(end);
386 v.mark(elseLabel);
387
388 gen(elseExpression, asmType);
389
390 markLineNumber(expression);
391 v.mark(end);
392
393 return StackValue.onStack(asmType);
394 }
395
396 @Override
397 public StackValue visitWhileExpression(@NotNull JetWhileExpression expression, StackValue receiver) {
398 Label condition = new Label();
399 v.mark(condition);
400
401 Label end = new Label();
402 blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression)));
403
404 StackValue conditionValue = gen(expression.getCondition());
405 conditionValue.condJump(end, true, v);
406
407 JetExpression body = expression.getBody();
408 if (body != null) {
409 gen(body, Type.VOID_TYPE);
410 }
411
412 v.goTo(condition);
413
414 v.mark(end);
415
416 blockStackElements.pop();
417
418 return StackValue.onStack(Type.VOID_TYPE);
419 }
420
421
422 @Override
423 public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) {
424 Label continueLabel = new Label();
425 v.mark(continueLabel);
426
427 Label breakLabel = new Label();
428
429 blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression)));
430
431 JetExpression body = expression.getBody();
432 JetExpression condition = expression.getCondition();
433 StackValue conditionValue;
434
435 if (body instanceof JetBlockExpression) {
436 // If body's a block, it can contain variable declarations which may be used in the condition of a do-while loop.
437 // We handle this case separately because otherwise such variable will be out of the frame map after the block ends
438 List<JetElement> doWhileStatements = ((JetBlockExpression) body).getStatements();
439
440 List<JetElement> statements = new ArrayList<JetElement>(doWhileStatements.size() + 1);
441 statements.addAll(doWhileStatements);
442 statements.add(condition);
443
444 conditionValue = generateBlock(statements, true);
445 }
446 else {
447 if (body != null) {
448 gen(body, Type.VOID_TYPE);
449 }
450
451 conditionValue = gen(condition);
452 }
453
454 conditionValue.condJump(continueLabel, false, v);
455 v.mark(breakLabel);
456
457 blockStackElements.pop();
458 return StackValue.none();
459 }
460
461 @Override
462 public StackValue visitForExpression(@NotNull JetForExpression forExpression, StackValue receiver) {
463 // Is it a "1..2" or so
464 RangeCodegenUtil.BinaryCall binaryCall = RangeCodegenUtil.getRangeAsBinaryCall(forExpression);
465 if (binaryCall != null) {
466 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, binaryCall.op);
467 if (resolvedCall != null) {
468 if (RangeCodegenUtil.isOptimizableRangeTo(resolvedCall.getResultingDescriptor())) {
469 generateForLoop(new ForInRangeLiteralLoopGenerator(forExpression, binaryCall));
470 return StackValue.none();
471 }
472 }
473 }
474
475 JetExpression loopRange = forExpression.getLoopRange();
476 JetType loopRangeType = bindingContext.get(BindingContext.EXPRESSION_TYPE, loopRange);
477 assert loopRangeType != null;
478 Type asmLoopRangeType = asmType(loopRangeType);
479 if (asmLoopRangeType.getSort() == Type.ARRAY) {
480 generateForLoop(new ForInArrayLoopGenerator(forExpression));
481 return StackValue.none();
482 }
483 else {
484 if (RangeCodegenUtil.isRange(loopRangeType)) {
485 generateForLoop(new ForInRangeInstanceLoopGenerator(forExpression));
486 return StackValue.none();
487 }
488
489 if (RangeCodegenUtil.isProgression(loopRangeType)) {
490 generateForLoop(new ForInProgressionExpressionLoopGenerator(forExpression));
491 return StackValue.none();
492 }
493
494 generateForLoop(new IteratorForLoopGenerator(forExpression));
495 return StackValue.none();
496 }
497 }
498
499 private OwnerKind contextKind() {
500 return context.getContextKind();
501 }
502
503 private void generateForLoop(AbstractForLoopGenerator generator) {
504 Label loopExit = new Label();
505 Label loopEntry = new Label();
506 Label continueLabel = new Label();
507
508 generator.beforeLoop();
509 generator.checkEmptyLoop(loopExit);
510
511 v.mark(loopEntry);
512 generator.checkPreCondition(loopExit);
513
514 generator.beforeBody();
515 blockStackElements.push(new LoopBlockStackElement(loopExit, continueLabel, targetLabel(generator.forExpression)));
516 generator.body();
517 blockStackElements.pop();
518 v.mark(continueLabel);
519 generator.afterBody(loopExit);
520
521 v.goTo(loopEntry);
522
523 v.mark(loopExit);
524 generator.afterLoop();
525 }
526
527 private abstract class AbstractForLoopGenerator {
528
529 // for (e : E in c) {...}
530 protected final JetForExpression forExpression;
531 private final Label bodyStart = new Label();
532 private final Label bodyEnd = new Label();
533 private final List<Runnable> leaveVariableTasks = Lists.newArrayList();
534
535 protected final JetType elementType;
536 protected final Type asmElementType;
537
538 protected int loopParameterVar;
539
540 private AbstractForLoopGenerator(@NotNull JetForExpression forExpression) {
541 this.forExpression = forExpression;
542 this.elementType = getElementType(forExpression);
543 this.asmElementType = asmType(elementType);
544 }
545
546 @NotNull
547 private JetType getElementType(JetForExpression forExpression) {
548 JetExpression loopRange = forExpression.getLoopRange();
549 assert loopRange != null;
550 ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext,
551 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
552 "No next() function " + DiagnosticUtils.atLocation(loopRange));
553 //noinspection ConstantConditions
554 return nextCall.getResultingDescriptor().getReturnType();
555 }
556
557 public void beforeLoop() {
558 JetParameter loopParameter = forExpression.getLoopParameter();
559 if (loopParameter != null) {
560 // E e = tmp<iterator>.next()
561 final VariableDescriptor parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, loopParameter);
562 @SuppressWarnings("ConstantConditions") final Type asmTypeForParameter = asmType(parameterDescriptor.getType());
563 loopParameterVar = myFrameMap.enter(parameterDescriptor, asmTypeForParameter);
564 scheduleLeaveVariable(new Runnable() {
565 @Override
566 public void run() {
567 myFrameMap.leave(parameterDescriptor);
568 v.visitLocalVariable(parameterDescriptor.getName().asString(),
569 asmTypeForParameter.getDescriptor(), null,
570 bodyStart, bodyEnd,
571 loopParameterVar);
572 }
573 });
574 }
575 else {
576 JetMultiDeclaration multiParameter = forExpression.getMultiParameter();
577 assert multiParameter != null;
578
579 // E tmp<e> = tmp<iterator>.next()
580 loopParameterVar = createLoopTempVariable(asmElementType);
581 }
582 }
583
584 public abstract void checkEmptyLoop(@NotNull Label loopExit);
585
586 public abstract void checkPreCondition(@NotNull Label loopExit);
587
588 public void beforeBody() {
589 v.mark(bodyStart);
590
591 assignToLoopParameter();
592
593 if (forExpression.getLoopParameter() == null) {
594 JetMultiDeclaration multiParameter = forExpression.getMultiParameter();
595 assert multiParameter != null;
596
597 generateMultiVariables(multiParameter.getEntries());
598 }
599 }
600
601 private void generateMultiVariables(List<JetMultiDeclarationEntry> entries) {
602 for (JetMultiDeclarationEntry variableDeclaration : entries) {
603 final VariableDescriptor componentDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration);
604
605 @SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType());
606 final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType);
607 scheduleLeaveVariable(new Runnable() {
608 @Override
609 public void run() {
610 myFrameMap.leave(componentDescriptor);
611 v.visitLocalVariable(componentDescriptor.getName().asString(),
612 componentAsmType.getDescriptor(), null,
613 bodyStart, bodyEnd,
614 componentVarIndex);
615 }
616 });
617
618
619 ResolvedCall<FunctionDescriptor> resolvedCall =
620 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration);
621 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
622 Call call = makeFakeCall(new TransientReceiver(elementType));
623 invokeFunction(call, StackValue.local(loopParameterVar, asmElementType), resolvedCall);
624
625 v.store(componentVarIndex, componentAsmType);
626 }
627 }
628
629 protected abstract void assignToLoopParameter();
630
631 protected abstract void increment(@NotNull Label loopExit);
632
633 public void body() {
634 JetExpression body = forExpression.getBody();
635 if (body != null) {
636 gen(body, Type.VOID_TYPE);
637 }
638 }
639
640 private void scheduleLeaveVariable(Runnable runnable) {
641 leaveVariableTasks.add(runnable);
642 }
643
644 protected int createLoopTempVariable(final Type type) {
645 int varIndex = myFrameMap.enterTemp(type);
646 scheduleLeaveVariable(new Runnable() {
647 @Override
648 public void run() {
649 myFrameMap.leaveTemp(type);
650 }
651 });
652 return varIndex;
653 }
654
655 public void afterBody(@NotNull Label loopExit) {
656 increment(loopExit);
657
658 v.mark(bodyEnd);
659 }
660
661 public void afterLoop() {
662 for (Runnable task : Lists.reverse(leaveVariableTasks)) {
663 task.run();
664 }
665 }
666
667 // This method consumes range/progression from stack
668 // The result is stored to local variable
669 protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) {
670 Type boxedType = boxType(elementType);
671 v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor());
672 StackValue.coerce(boxedType, elementType, v);
673 v.store(varToStore, elementType);
674 }
675 }
676
677 private class IteratorForLoopGenerator extends AbstractForLoopGenerator {
678
679 private int iteratorVarIndex;
680 private final ResolvedCall<FunctionDescriptor> iteratorCall;
681 private final ResolvedCall<FunctionDescriptor> nextCall;
682 private final Type asmTypeForIterator;
683
684 private IteratorForLoopGenerator(@NotNull JetForExpression forExpression) {
685 super(forExpression);
686
687 JetExpression loopRange = forExpression.getLoopRange();
688 assert loopRange != null;
689 this.iteratorCall = getNotNull(bindingContext,
690 LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange,
691 "No .iterator() function " + DiagnosticUtils.atLocation(loopRange));
692
693 JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType();
694 assert iteratorType != null;
695 this.asmTypeForIterator = asmType(iteratorType);
696
697 this.nextCall = getNotNull(bindingContext,
698 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange,
699 "No next() function " + DiagnosticUtils.atLocation(loopRange));
700 }
701
702 @Override
703 public void beforeLoop() {
704 super.beforeLoop();
705
706 // Iterator<E> tmp<iterator> = c.iterator()
707
708 iteratorVarIndex = createLoopTempVariable(asmTypeForIterator);
709
710 Call call = bindingContext.get(LOOP_RANGE_ITERATOR_CALL, forExpression.getLoopRange());
711 invokeFunction(call, StackValue.none(), iteratorCall);
712 v.store(iteratorVarIndex, asmTypeForIterator);
713 }
714
715 @Override
716 public void checkEmptyLoop(@NotNull Label loopExit) {
717 }
718
719 @Override
720 public void checkPreCondition(@NotNull Label loopExit) {
721 // tmp<iterator>.hasNext()
722
723 JetExpression loopRange = forExpression.getLoopRange();
724 @SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext,
725 LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange,
726 "No hasNext() function " + DiagnosticUtils.atLocation(loopRange));
727 @SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
728 invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall);
729
730 JetType type = hasNextCall.getResultingDescriptor().getReturnType();
731 assert type != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
732
733 Type asmType = asmType(type);
734 StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v);
735 v.ifeq(loopExit);
736 }
737
738 @Override
739 protected void assignToLoopParameter() {
740 @SuppressWarnings("ConstantConditions") Call fakeCall =
741 makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType()));
742 invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), nextCall);
743 //noinspection ConstantConditions
744 v.store(loopParameterVar, asmType(nextCall.getResultingDescriptor().getReturnType()));
745 }
746
747 @Override
748 protected void increment(@NotNull Label loopExit) {
749 }
750 }
751
752 private class ForInArrayLoopGenerator extends AbstractForLoopGenerator {
753 private int indexVar;
754 private int arrayVar;
755 private final JetType loopRangeType;
756
757 private ForInArrayLoopGenerator(@NotNull JetForExpression forExpression) {
758 super(forExpression);
759 loopRangeType = bindingContext.get(BindingContext.EXPRESSION_TYPE, forExpression.getLoopRange());
760 }
761
762 @Override
763 public void beforeLoop() {
764 super.beforeLoop();
765
766 indexVar = createLoopTempVariable(Type.INT_TYPE);
767
768 JetExpression loopRange = forExpression.getLoopRange();
769 StackValue value = gen(loopRange);
770 Type asmLoopRangeType = asmType(loopRangeType);
771 if (value instanceof StackValue.Local && value.type.equals(asmLoopRangeType)) {
772 arrayVar = ((StackValue.Local) value).index; // no need to copy local variable into another variable
773 }
774 else {
775 arrayVar = createLoopTempVariable(OBJECT_TYPE);
776 value.put(asmLoopRangeType, v);
777 v.store(arrayVar, OBJECT_TYPE);
778 }
779
780 v.iconst(0);
781 v.store(indexVar, Type.INT_TYPE);
782 }
783
784 @Override
785 public void checkEmptyLoop(@NotNull Label loopExit) {
786 }
787
788 @Override
789 public void checkPreCondition(@NotNull Label loopExit) {
790 v.load(indexVar, Type.INT_TYPE);
791 v.load(arrayVar, OBJECT_TYPE);
792 v.arraylength();
793 v.ificmpge(loopExit);
794 }
795
796 @Override
797 protected void assignToLoopParameter() {
798 Type arrayElParamType;
799 if (KotlinBuiltIns.getInstance().isArray(loopRangeType)) {
800 arrayElParamType = boxType(asmElementType);
801 }
802 else {
803 arrayElParamType = asmElementType;
804 }
805
806 v.load(arrayVar, OBJECT_TYPE);
807 v.load(indexVar, Type.INT_TYPE);
808 v.aload(arrayElParamType);
809 StackValue.onStack(arrayElParamType).put(asmElementType, v);
810 v.store(loopParameterVar, asmElementType);
811 }
812
813 @Override
814 protected void increment(@NotNull Label loopExit) {
815 v.iinc(indexVar, 1);
816 }
817 }
818
819 private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator {
820 protected int endVar;
821
822 // For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether
823 // loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop)
824 protected final boolean isIntegerProgression;
825
826 private AbstractForInProgressionOrRangeLoopGenerator(@NotNull JetForExpression forExpression) {
827 super(forExpression);
828
829 switch (asmElementType.getSort()) {
830 case Type.INT:
831 case Type.BYTE:
832 case Type.SHORT:
833 case Type.CHAR:
834 case Type.LONG:
835 isIntegerProgression = true;
836 break;
837
838 case Type.DOUBLE:
839 case Type.FLOAT:
840 isIntegerProgression = false;
841 break;
842
843 default:
844 throw new IllegalStateException("Unexpected range element type: " + asmElementType);
845 }
846 }
847
848 @Override
849 public void beforeLoop() {
850 super.beforeLoop();
851
852 endVar = createLoopTempVariable(asmElementType);
853 }
854
855 // Index of the local variable holding the actual last value of the loop parameter.
856 // For ranges it equals end, for progressions it's a function of start, end and increment
857 protected abstract int getFinalVar();
858
859 protected void checkPostCondition(@NotNull Label loopExit) {
860 int finalVar = getFinalVar();
861 assert isIntegerProgression && finalVar != -1 :
862 "Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar;
863
864 v.load(loopParameterVar, asmElementType);
865 v.load(finalVar, asmElementType);
866 if (asmElementType.getSort() == Type.LONG) {
867 v.lcmp();
868 v.ifeq(loopExit);
869 }
870 else {
871 v.ificmpeq(loopExit);
872 }
873 }
874 }
875
876 private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
877 private AbstractForInRangeLoopGenerator(@NotNull JetForExpression forExpression) {
878 super(forExpression);
879 }
880
881 @Override
882 public void beforeLoop() {
883 super.beforeLoop();
884
885 storeRangeStartAndEnd();
886 }
887
888 protected abstract void storeRangeStartAndEnd();
889
890 @Override
891 protected int getFinalVar() {
892 return endVar;
893 }
894
895 @Override
896 public void checkPreCondition(@NotNull Label loopExit) {
897 if (isIntegerProgression) return;
898
899 v.load(loopParameterVar, asmElementType);
900 v.load(endVar, asmElementType);
901
902 v.cmpg(asmElementType);
903 v.ifgt(loopExit);
904 }
905
906 @Override
907 public void checkEmptyLoop(@NotNull Label loopExit) {
908 if (!isIntegerProgression) return;
909
910 v.load(loopParameterVar, asmElementType);
911 v.load(endVar, asmElementType);
912 if (asmElementType.getSort() == Type.LONG) {
913 v.lcmp();
914 v.ifgt(loopExit);
915 }
916 else {
917 v.ificmpgt(loopExit);
918 }
919 }
920
921 @Override
922 protected void assignToLoopParameter() {
923 }
924
925 @Override
926 protected void increment(@NotNull Label loopExit) {
927 if (isIntegerProgression) {
928 checkPostCondition(loopExit);
929 }
930
931 if (asmElementType == Type.INT_TYPE) {
932 v.iinc(loopParameterVar, 1);
933 }
934 else {
935 v.load(loopParameterVar, asmElementType);
936 genIncrement(asmElementType, 1, v);
937 v.store(loopParameterVar, asmElementType);
938 }
939 }
940 }
941
942 private class ForInRangeLiteralLoopGenerator extends AbstractForInRangeLoopGenerator {
943 private final RangeCodegenUtil.BinaryCall rangeCall;
944
945 private ForInRangeLiteralLoopGenerator(
946 @NotNull JetForExpression forExpression,
947 @NotNull RangeCodegenUtil.BinaryCall rangeCall
948 ) {
949 super(forExpression);
950 this.rangeCall = rangeCall;
951 }
952
953 @Override
954 protected void storeRangeStartAndEnd() {
955 gen(rangeCall.left, asmElementType);
956 v.store(loopParameterVar, asmElementType);
957
958 gen(rangeCall.right, asmElementType);
959 v.store(endVar, asmElementType);
960 }
961 }
962
963 private class ForInRangeInstanceLoopGenerator extends AbstractForInRangeLoopGenerator {
964 private ForInRangeInstanceLoopGenerator(@NotNull JetForExpression forExpression) {
965 super(forExpression);
966 }
967
968 @Override
969 protected void storeRangeStartAndEnd() {
970 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange());
971 assert loopRangeType != null;
972 Type asmLoopRangeType = asmType(loopRangeType);
973 gen(forExpression.getLoopRange(), asmLoopRangeType);
974 v.dup();
975
976 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
977 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
978 }
979 }
980
981 private class ForInProgressionExpressionLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator {
982 private int incrementVar;
983 private Type incrementType;
984
985 private int finalVar;
986
987 private ForInProgressionExpressionLoopGenerator(@NotNull JetForExpression forExpression) {
988 super(forExpression);
989 }
990
991 @Override
992 protected int getFinalVar() {
993 return finalVar;
994 }
995
996 @Override
997 public void beforeLoop() {
998 super.beforeLoop();
999
1000 incrementVar = createLoopTempVariable(asmElementType);
1001
1002 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange());
1003 assert loopRangeType != null;
1004 Type asmLoopRangeType = asmType(loopRangeType);
1005
1006 Collection<VariableDescriptor> incrementProp = loopRangeType.getMemberScope().getProperties(Name.identifier("increment"));
1007 assert incrementProp.size() == 1 : loopRangeType + " " + incrementProp.size();
1008 incrementType = asmType(incrementProp.iterator().next().getType());
1009
1010 gen(forExpression.getLoopRange(), asmLoopRangeType);
1011 v.dup();
1012 v.dup();
1013
1014 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar);
1015 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar);
1016 generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar);
1017
1018 storeFinalVar();
1019 }
1020
1021 private void storeFinalVar() {
1022 if (!isIntegerProgression) {
1023 finalVar = -1;
1024 return;
1025 }
1026
1027 v.load(loopParameterVar, asmElementType);
1028 v.load(endVar, asmElementType);
1029 v.load(incrementVar, incrementType);
1030
1031 Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE;
1032 v.invokestatic("kotlin/internal/InternalPackage", "getProgressionFinalElement",
1033 Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType));
1034
1035 finalVar = createLoopTempVariable(asmElementType);
1036 v.store(finalVar, asmElementType);
1037 }
1038
1039 @Override
1040 public void checkPreCondition(@NotNull Label loopExit) {
1041 if (isIntegerProgression) return;
1042
1043 v.load(loopParameterVar, asmElementType);
1044 v.load(endVar, asmElementType);
1045 v.load(incrementVar, incrementType);
1046
1047 Label negativeIncrement = new Label();
1048 Label afterIf = new Label();
1049
1050 if (incrementType.getSort() == Type.DOUBLE) {
1051 v.dconst(0.0);
1052 }
1053 else {
1054 v.fconst(0.0f);
1055 }
1056 v.cmpl(incrementType);
1057 v.ifle(negativeIncrement); // if increment < 0, jump
1058
1059 // increment > 0
1060 v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well
1061 v.ifgt(loopExit);
1062 v.goTo(afterIf);
1063
1064 // increment < 0
1065 v.mark(negativeIncrement);
1066 v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well
1067 v.iflt(loopExit);
1068 v.mark(afterIf);
1069 }
1070
1071 @Override
1072 public void checkEmptyLoop(@NotNull Label loopExit) {
1073 if (!isIntegerProgression) return;
1074
1075 v.load(loopParameterVar, asmElementType);
1076 v.load(endVar, asmElementType);
1077 v.load(incrementVar, incrementType);
1078
1079 Label negativeIncrement = new Label();
1080 Label afterIf = new Label();
1081
1082 if (asmElementType.getSort() == Type.LONG) {
1083 v.lconst(0L);
1084 v.lcmp();
1085 v.ifle(negativeIncrement); // if increment < 0, jump
1086
1087 // increment > 0
1088 v.lcmp();
1089 v.ifgt(loopExit);
1090 v.goTo(afterIf);
1091
1092 // increment < 0
1093 v.mark(negativeIncrement);
1094 v.lcmp();
1095 v.iflt(loopExit);
1096 v.mark(afterIf);
1097 }
1098 else {
1099 v.ifle(negativeIncrement); // if increment < 0, jump
1100
1101 // increment > 0
1102 v.ificmpgt(loopExit);
1103 v.goTo(afterIf);
1104
1105 // increment < 0
1106 v.mark(negativeIncrement);
1107 v.ificmplt(loopExit);
1108 v.mark(afterIf);
1109 }
1110 }
1111
1112 @Override
1113 protected void assignToLoopParameter() {
1114 }
1115
1116 @Override
1117 protected void increment(@NotNull Label loopExit) {
1118 if (isIntegerProgression) {
1119 checkPostCondition(loopExit);
1120 }
1121
1122 v.load(loopParameterVar, asmElementType);
1123 v.load(incrementVar, asmElementType);
1124 v.add(asmElementType);
1125
1126 if (asmElementType == Type.BYTE_TYPE || asmElementType == Type.SHORT_TYPE || asmElementType == Type.CHAR_TYPE) {
1127 StackValue.coerce(Type.INT_TYPE, asmElementType, v);
1128 }
1129
1130 v.store(loopParameterVar, asmElementType);
1131 }
1132 }
1133
1134
1135 @Override
1136 public StackValue visitBreakExpression(@NotNull JetBreakExpression expression, StackValue receiver) {
1137 return generateBreakOrContinueExpression(expression, true);
1138 }
1139
1140 @Override
1141 public StackValue visitContinueExpression(@NotNull JetContinueExpression expression, StackValue receiver) {
1142 return generateBreakOrContinueExpression(expression, false);
1143 }
1144
1145 @NotNull
1146 private StackValue generateBreakOrContinueExpression(@NotNull JetLabelQualifiedExpression expression, boolean isBreak) {
1147 assert expression instanceof JetContinueExpression || expression instanceof JetBreakExpression;
1148
1149 if (!blockStackElements.isEmpty()) {
1150 BlockStackElement stackElement = blockStackElements.peek();
1151
1152 if (stackElement instanceof FinallyBlockStackElement) {
1153 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
1154 //noinspection ConstantConditions
1155 genFinallyBlockOrGoto(finallyBlockStackElement, null);
1156 }
1157 else if (stackElement instanceof LoopBlockStackElement) {
1158 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
1159 JetSimpleNameExpression labelElement = expression.getTargetLabel();
1160 //noinspection ConstantConditions
1161 if (labelElement == null ||
1162 loopBlockStackElement.targetLabel != null &&
1163 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) {
1164 v.goTo(isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel);
1165 return StackValue.none();
1166 }
1167 }
1168 else {
1169 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack");
1170 }
1171
1172 blockStackElements.pop();
1173 StackValue result = generateBreakOrContinueExpression(expression, isBreak);
1174 blockStackElements.push(stackElement);
1175 return result;
1176 }
1177
1178 throw new UnsupportedOperationException("Target label for break/continue not found");
1179 }
1180
1181 private StackValue generateSingleBranchIf(
1182 StackValue condition,
1183 JetIfExpression ifExpression,
1184 JetExpression expression,
1185 boolean inverse,
1186 boolean isStatement
1187 ) {
1188 Label elseLabel = new Label();
1189 condition.condJump(elseLabel, inverse, v);
1190
1191 if (isStatement) {
1192 gen(expression, Type.VOID_TYPE);
1193 v.mark(elseLabel);
1194 return StackValue.none();
1195 }
1196 else {
1197 Type type = expressionType(expression);
1198 Type targetType = type.equals(UNIT_TYPE) ? type : OBJECT_TYPE;
1199
1200 gen(expression, targetType);
1201
1202 Label end = new Label();
1203 v.goTo(end);
1204
1205 markLineNumber(ifExpression);
1206 v.mark(elseLabel);
1207 StackValue.putUnitInstance(v);
1208
1209 v.mark(end);
1210 return StackValue.onStack(targetType);
1211 }
1212 }
1213
1214 @Override
1215 public StackValue visitConstantExpression(@NotNull JetConstantExpression expression, StackValue receiver) {
1216 CompileTimeConstant<?> compileTimeValue = getCompileTimeConstant(expression, bindingContext);
1217 assert compileTimeValue != null;
1218 return StackValue.constant(compileTimeValue.getValue(), expressionType(expression));
1219 }
1220
1221 @Nullable
1222 public static CompileTimeConstant getCompileTimeConstant(@NotNull JetExpression expression, @NotNull BindingContext bindingContext) {
1223 CompileTimeConstant<?> compileTimeValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression);
1224 if (compileTimeValue instanceof IntegerValueTypeConstant) {
1225 JetType expectedType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
1226 return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) compileTimeValue, expectedType);
1227 }
1228 return compileTimeValue;
1229 }
1230
1231 @Override
1232 public StackValue visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, StackValue receiver) {
1233 StringBuilder constantValue = new StringBuilder("");
1234 JetStringTemplateEntry[] entries = expression.getEntries();
1235
1236 if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) {
1237 JetExpression expr = entries[0].getExpression();
1238 return genToString(v, gen(expr), expressionType(expr));
1239 }
1240
1241 for (JetStringTemplateEntry entry : entries) {
1242 if (entry instanceof JetLiteralStringTemplateEntry) {
1243 constantValue.append(entry.getText());
1244 }
1245 else if (entry instanceof JetEscapeStringTemplateEntry) {
1246 constantValue.append(((JetEscapeStringTemplateEntry) entry).getUnescapedValue());
1247 }
1248 else {
1249 constantValue = null;
1250 break;
1251 }
1252 }
1253 if (constantValue != null) {
1254 Type type = expressionType(expression);
1255 return StackValue.constant(constantValue.toString(), type);
1256 }
1257 else {
1258 genStringBuilderConstructor(v);
1259 for (JetStringTemplateEntry entry : entries) {
1260 if (entry instanceof JetStringTemplateEntryWithExpression) {
1261 invokeAppend(entry.getExpression());
1262 }
1263 else {
1264 String text = entry instanceof JetEscapeStringTemplateEntry
1265 ? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
1266 : entry.getText();
1267 v.aconst(text);
1268 genInvokeAppendMethod(v, JAVA_STRING_TYPE);
1269 }
1270 }
1271 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
1272 return StackValue.onStack(AsmTypeConstants.JAVA_STRING_TYPE);
1273 }
1274 }
1275
1276 @Override
1277 public StackValue visitBlockExpression(@NotNull JetBlockExpression expression, StackValue receiver) {
1278 List<JetElement> statements = expression.getStatements();
1279 JetType unitType = KotlinBuiltIns.getInstance().getUnitType();
1280 boolean lastStatementIsExpression = !unitType.equals(bindingContext.get(EXPRESSION_TYPE, expression));
1281 return generateBlock(statements, lastStatementIsExpression);
1282 }
1283
1284 @Override
1285 public StackValue visitNamedFunction(@NotNull JetNamedFunction function, StackValue data) {
1286 assert data == StackValue.none();
1287
1288 if (JetPsiUtil.isScriptDeclaration(function)) {
1289 return StackValue.none();
1290 }
1291
1292 StackValue closure = genClosure(function, null, KotlinSyntheticClass.Kind.LOCAL_FUNCTION);
1293 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
1294 int index = lookupLocalIndex(descriptor);
1295 closure.put(OBJECT_TYPE, v);
1296 v.store(index, OBJECT_TYPE);
1297 return StackValue.none();
1298 }
1299
1300 @Override
1301 public StackValue visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, StackValue receiver) {
1302 //noinspection ConstantConditions
1303 if (bindingContext.get(BindingContext.BLOCK, expression)) {
1304 //noinspection ConstantConditions
1305 return gen(expression.getFunctionLiteral().getBodyExpression());
1306 }
1307 else {
1308 return genClosure(expression.getFunctionLiteral(), null, KotlinSyntheticClass.Kind.ANONYMOUS_FUNCTION);
1309 }
1310 }
1311
1312 @NotNull
1313 private StackValue genClosure(
1314 JetDeclarationWithBody declaration,
1315 @Nullable ClassDescriptor samInterfaceClass,
1316 @NotNull KotlinSyntheticClass.Kind kind
1317 ) {
1318 FunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, declaration);
1319 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText();
1320
1321 Type closureSuperClass = samInterfaceClass == null ? getFunctionImplType(descriptor) : OBJECT_TYPE;
1322
1323 ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context,
1324 kind, this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), parentCodegen);
1325
1326 closureCodegen.gen();
1327
1328 return closureCodegen.putInstanceOnStack(v, this);
1329 }
1330
1331 @Override
1332 public StackValue visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression, StackValue receiver) {
1333 CalculatedClosure closure = this.generateObjectLiteral(state, expression);
1334
1335 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, expression.getObjectDeclaration());
1336 assert constructorDescriptor != null;
1337 CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor);
1338
1339 Type type = bindingContext.get(ASM_TYPE, constructorDescriptor.getContainingDeclaration());
1340 assert type != null;
1341
1342 v.anew(type);
1343 v.dup();
1344
1345 pushClosureOnStack(closure, false, defaulCallGenerator);
1346
1347 JetDelegatorToSuperCall superCall = closure.getSuperCall();
1348 if (superCall != null) {
1349 ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET,
1350 superCall
1351 .getCalleeExpression()
1352 .getConstructorReferenceExpression());
1353 assert superConstructor != null;
1354 //noinspection SuspiciousMethodCalls
1355 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
1356 Type[] argumentTypes = superCallable.getAsmMethod().getArgumentTypes();
1357 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression());
1358 assert resolvedCall != null;
1359 pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes), defaulCallGenerator);
1360 }
1361
1362 v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor());
1363 return StackValue.onStack(type);
1364 }
1365
1366 public void pushClosureOnStack(@Nullable CalculatedClosure closure, boolean ignoreThisAndReceiver, @NotNull CallGenerator callGenerator) {
1367 if (closure != null) {
1368 int paramIndex = 0;
1369 if (!ignoreThisAndReceiver) {
1370 ClassDescriptor captureThis = closure.getCaptureThis();
1371 if (captureThis != null) {
1372 StackValue thisOrOuter = generateThisOrOuter(captureThis, false);
1373
1374 assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type;
1375 callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++);
1376 }
1377
1378 JetType captureReceiver = closure.getCaptureReceiverType();
1379 if (captureReceiver != null) {
1380 Type asmType = typeMapper.mapType(captureReceiver);
1381 StackValue.Local capturedReceiver = StackValue.local(context.isStatic() ? 0 : 1, asmType);
1382 callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++);
1383 }
1384 }
1385
1386 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
1387 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey());
1388 if (sharedVarType == null) {
1389 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey());
1390 }
1391 StackValue capturedVar = entry.getValue().getOuterValue(this);
1392 callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++);
1393 }
1394 }
1395 }
1396
1397 private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) {
1398 Label blockEnd = new Label();
1399
1400 List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
1401
1402 StackValue answer = StackValue.none();
1403
1404 for (Iterator<JetElement> iterator = statements.iterator(); iterator.hasNext(); ) {
1405 JetElement statement = iterator.next();
1406
1407 if (statement instanceof JetNamedDeclaration) {
1408 JetNamedDeclaration declaration = (JetNamedDeclaration) statement;
1409 if (JetPsiUtil.isScriptDeclaration(declaration)) {
1410 continue;
1411 }
1412 }
1413
1414 if (statement instanceof JetMultiDeclaration) {
1415 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement;
1416 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
1417 generateLocalVariableDeclaration(entry, blockEnd, leaveTasks);
1418 }
1419 }
1420
1421 if (statement instanceof JetVariableDeclaration) {
1422 generateLocalVariableDeclaration((JetVariableDeclaration) statement, blockEnd, leaveTasks);
1423 }
1424
1425 if (statement instanceof JetNamedFunction) {
1426 generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks);
1427 }
1428
1429 boolean isExpression = !iterator.hasNext() && lastStatementIsExpression;
1430
1431 StackValue result = isExpression ? gen(statement) : genStatement(statement);
1432
1433 if (!iterator.hasNext()) {
1434 answer = result;
1435 }
1436 else {
1437 result.put(Type.VOID_TYPE, v);
1438 }
1439 }
1440
1441 v.mark(blockEnd);
1442
1443 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) {
1444 task.fun(answer);
1445 }
1446
1447 return answer;
1448 }
1449
1450 private void generateLocalVariableDeclaration(
1451 @NotNull JetVariableDeclaration variableDeclaration,
1452 final @NotNull Label blockEnd,
1453 @NotNull List<Function<StackValue, Void>> leaveTasks
1454 ) {
1455 final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration);
1456 assert variableDescriptor != null;
1457
1458 final Label scopeStart = new Label();
1459 v.mark(scopeStart);
1460
1461 final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
1462 final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType());
1463 int index = myFrameMap.enter(variableDescriptor, type);
1464
1465 if (sharedVarType != null) {
1466 v.anew(sharedVarType);
1467 v.dup();
1468 v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V");
1469 v.store(index, OBJECT_TYPE);
1470 }
1471
1472 leaveTasks.add(new Function<StackValue, Void>() {
1473 @Override
1474 public Void fun(StackValue answer) {
1475 int index = myFrameMap.leave(variableDescriptor);
1476
1477 if (sharedVarType != null) {
1478 if (answer instanceof StackValue.Shared && index == ((StackValue.Shared) answer).getIndex()) {
1479 ((StackValue.Shared) answer).releaseOnPut();
1480 }
1481 else {
1482 v.aconst(null);
1483 v.store(index, OBJECT_TYPE);
1484 }
1485 }
1486 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd,
1487 index);
1488 return null;
1489 }
1490 });
1491 }
1492
1493 private void generateLocalFunctionDeclaration(
1494 @NotNull JetNamedFunction namedFunction,
1495 @NotNull List<Function<StackValue, Void>> leaveTasks
1496 ) {
1497 final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, namedFunction);
1498 myFrameMap.enter(descriptor, OBJECT_TYPE);
1499
1500 leaveTasks.add(new Function<StackValue, Void>() {
1501 @Override
1502 public Void fun(StackValue value) {
1503 myFrameMap.leave(descriptor);
1504 return null;
1505 }
1506 });
1507 }
1508
1509 private void markLineNumber(@NotNull JetElement statement) {
1510 Document document = statement.getContainingFile().getViewProvider().getDocument();
1511 if (document != null) {
1512 int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based
1513 if (lineNumber == myLastLineNumber) {
1514 return;
1515 }
1516 myLastLineNumber = lineNumber;
1517
1518 Label label = new Label();
1519 v.visitLabel(label);
1520 v.visitLineNumber(lineNumber + 1, label); // 1-based
1521 }
1522 }
1523
1524 private void doFinallyOnReturn() {
1525 if(!blockStackElements.isEmpty()) {
1526 BlockStackElement stackElement = blockStackElements.peek();
1527 if (stackElement instanceof FinallyBlockStackElement) {
1528 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
1529 genFinallyBlockOrGoto(finallyBlockStackElement, null);
1530 }
1531 else if (stackElement instanceof LoopBlockStackElement) {
1532
1533 } else {
1534 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack");
1535 }
1536
1537 blockStackElements.pop();
1538 doFinallyOnReturn();
1539 blockStackElements.push(stackElement);
1540 }
1541 }
1542
1543 private boolean hasFinallyBLocks() {
1544 for (BlockStackElement element : blockStackElements) {
1545 if (element instanceof FinallyBlockStackElement) {
1546 return true;
1547 }
1548 }
1549 return false;
1550 }
1551
1552 private void genFinallyBlockOrGoto(
1553 @Nullable FinallyBlockStackElement finallyBlockStackElement,
1554 @Nullable Label tryCatchBlockEnd
1555 ) {
1556
1557 if (finallyBlockStackElement != null) {
1558 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent";
1559
1560 BlockStackElement topOfStack = blockStackElements.pop();
1561 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block";
1562
1563 JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
1564 Label finallyStart = new Label();
1565 v.mark(finallyStart);
1566 finallyBlockStackElement.addGapLabel(finallyStart);
1567
1568 //noinspection ConstantConditions
1569 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
1570 }
1571
1572 if (tryCatchBlockEnd != null) {
1573 v.goTo(tryCatchBlockEnd);
1574 }
1575
1576 if (finallyBlockStackElement != null) {
1577 Label finallyEnd = new Label();
1578 v.mark(finallyEnd);
1579 finallyBlockStackElement.addGapLabel(finallyEnd);
1580
1581 blockStackElements.push(finallyBlockStackElement);
1582 }
1583 }
1584
1585 @Override
1586 public StackValue visitReturnExpression(@NotNull JetReturnExpression expression, StackValue receiver) {
1587 JetExpression returnedExpression = expression.getReturnedExpression();
1588 if (returnedExpression != null) {
1589 gen(returnedExpression, returnType);
1590 boolean hasFinallyBLocks = hasFinallyBLocks();
1591 if (hasFinallyBLocks) {
1592 int returnValIndex = myFrameMap.enterTemp(returnType);
1593 StackValue.local(returnValIndex, returnType).store(returnType, v);
1594 doFinallyOnReturn();
1595 StackValue.local(returnValIndex, returnType).put(returnType, v);
1596 myFrameMap.leaveTemp(returnType);
1597 }
1598 v.areturn(returnType);
1599 }
1600 else {
1601 doFinallyOnReturn();
1602 v.visitInsn(RETURN);
1603 }
1604 return StackValue.none();
1605 }
1606
1607 public void returnExpression(JetExpression expr) {
1608 StackValue lastValue = gen(expr);
1609
1610 if (!endsWithReturn(expr)) {
1611 lastValue.put(returnType, v);
1612 v.areturn(returnType);
1613 }
1614 }
1615
1616 private static boolean endsWithReturn(JetElement bodyExpression) {
1617 if (bodyExpression instanceof JetBlockExpression) {
1618 List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
1619 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof JetReturnExpression;
1620 }
1621
1622 return bodyExpression instanceof JetReturnExpression;
1623 }
1624
1625 @Override
1626 public StackValue visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, StackValue receiver) {
1627 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression);
1628
1629 DeclarationDescriptor descriptor;
1630 if (resolvedCall == null) {
1631 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
1632 }
1633 else {
1634 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
1635 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall;
1636 resolvedCall = call.getVariableCall();
1637 }
1638 receiver = StackValue.receiver(resolvedCall, receiver, this, null);
1639 descriptor = resolvedCall.getResultingDescriptor();
1640 }
1641
1642 //if (descriptor instanceof VariableAsFunctionDescriptor) {
1643 // descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
1644 //}
1645
1646 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'";
1647 descriptor = descriptor.getOriginal();
1648
1649 if (descriptor instanceof CallableMemberDescriptor) {
1650 CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor);
1651
1652 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor);
1653 if (intrinsic != null) {
1654 Type returnType = typeMapper.mapType(memberDescriptor);
1655 intrinsic.generate(this, v, returnType, expression, Collections.<JetExpression>emptyList(), receiver);
1656 return StackValue.onStack(returnType);
1657 }
1658 }
1659
1660 int index = lookupLocalIndex(descriptor);
1661 if (index >= 0) {
1662 return stackValueForLocal(descriptor, index);
1663 }
1664
1665 if (descriptor instanceof PropertyDescriptor) {
1666 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
1667
1668 boolean directToField =
1669 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL;
1670 JetExpression r = getReceiverForSelector(expression);
1671 boolean isSuper = r instanceof JetSuperExpression;
1672 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor);
1673 StackValue.Property iValue =
1674 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null);
1675 if (directToField) {
1676 receiver = StackValue.receiverWithoutReceiverArgument(receiver);
1677 }
1678
1679 //pop receiver via put(VOID_TYPE) in case of access to backing field that moved to outer class!!!
1680 receiver.put(!iValue.isPropertyWithBackingFieldInOuterClass() ? receiver.type : Type.VOID_TYPE, v);
1681
1682 return iValue;
1683 }
1684
1685 if (descriptor instanceof ClassDescriptor) {
1686 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
1687 if (classDescriptor.getKind() == ClassKind.OBJECT) {
1688 return StackValue.singleton(classDescriptor, typeMapper);
1689 }
1690 if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
1691 DeclarationDescriptor enumClass = classDescriptor.getContainingDeclaration();
1692 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor;
1693 Type type = typeMapper.mapType((ClassDescriptor) enumClass);
1694 return StackValue.field(type, type, descriptor.getName().asString(), true);
1695 }
1696 ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor();
1697 assert classObjectDescriptor != null : "Class object is not found for " + descriptor;
1698 return StackValue.singleton(classObjectDescriptor, typeMapper);
1699 }
1700
1701 if (descriptor instanceof TypeParameterDescriptor) {
1702 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
1703 v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
1704 JetType type = typeParameterDescriptor.getClassObjectType();
1705 assert type != null;
1706 v.checkcast(asmType(type));
1707
1708 return StackValue.onStack(OBJECT_TYPE);
1709 }
1710
1711 StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false);
1712 if (value != null) {
1713 if (context.isSpecialStackValue(value)) {
1714 return value;
1715 }
1716
1717 if (value instanceof StackValue.Composed) {
1718 StackValue.Composed composed = (StackValue.Composed) value;
1719 composed.prefix.put(OBJECT_TYPE, v);
1720 value = composed.suffix;
1721 }
1722
1723 if (value instanceof StackValue.FieldForSharedVar) {
1724 StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
1725 Type sharedType = StackValue.sharedTypeForType(value.type);
1726 v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name,
1727 sharedType.getDescriptor());
1728 }
1729
1730 return value;
1731 }
1732
1733 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
1734 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration();
1735 Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor);
1736 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
1737 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor);
1738 StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false);
1739 script.put(script.type, v);
1740 Type fieldType = typeMapper.mapType(valueParameterDescriptor);
1741 return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false);
1742 }
1743
1744 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
1745 }
1746
1747 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) {
1748 if (descriptor instanceof VariableDescriptor) {
1749 Type sharedVarType = typeMapper.getSharedVarType(descriptor);
1750 JetType outType = ((VariableDescriptor) descriptor).getType();
1751 if (sharedVarType != null) {
1752 return StackValue.shared(index, asmType(outType));
1753 }
1754 else {
1755 return StackValue.local(index, asmType(outType));
1756 }
1757 }
1758 else {
1759 return StackValue.local(index, OBJECT_TYPE);
1760 }
1761 }
1762
1763 @Override
1764 public boolean lookupLocal(DeclarationDescriptor descriptor) {
1765 return lookupLocalIndex(descriptor) != -1;
1766 }
1767
1768 public int lookupLocalIndex(DeclarationDescriptor descriptor) {
1769 return myFrameMap.getIndex(descriptor);
1770 }
1771
1772 @Nullable
1773 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) {
1774 PropertyGetterDescriptor getter = descriptor.getGetter();
1775 if (getter != null) {
1776 Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, getter);
1777 return call != null ? call.getExplicitReceiver().getType() : null;
1778 }
1779 return null;
1780 }
1781
1782 @NotNull
1783 public StackValue.Property intermediateValueForProperty(
1784 @NotNull PropertyDescriptor propertyDescriptor,
1785 boolean forceField,
1786 @Nullable JetSuperExpression superExpression
1787 ) {
1788 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL);
1789 }
1790
1791 public StackValue.Property intermediateValueForProperty(
1792 @NotNull PropertyDescriptor propertyDescriptor,
1793 boolean forceField,
1794 @Nullable JetSuperExpression superExpression,
1795 @NotNull MethodKind methodKind
1796 ) {
1797 JetTypeMapper typeMapper = state.getTypeMapper();
1798
1799 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
1800
1801 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
1802 boolean isStatic = containingDeclaration instanceof PackageFragmentDescriptor;
1803 boolean isSuper = superExpression != null;
1804 boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
1805
1806 JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
1807 boolean isDelegatedProperty = delegateType != null;
1808
1809
1810 CallableMethod callableGetter = null;
1811 CallableMethod callableSetter = null;
1812
1813 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
1814
1815 CodegenContext backingFieldContext = context.getParentContext();
1816
1817 if (isBackingFieldInAnotherClass && forceField) {
1818 //delegate call to classObject owner : OWNER
1819 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
1820 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
1821 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
1822 if (!skipPropertyAccessors) {
1823 //noinspection ConstantConditions
1824 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType);
1825 }
1826 isStatic = true;
1827 }
1828
1829 if (!skipPropertyAccessors) {
1830 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty, context)) {
1831 callableGetter = null;
1832 }
1833 else {
1834 if (isSuper && !isInterface(containingDeclaration)) {
1835 ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context);
1836 CodegenContext c = context.findParentContextWithDescriptor(owner);
1837 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
1838 if (c != context.getParentContext()) {
1839 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor);
1840 }
1841 }
1842
1843 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor);
1844
1845 PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
1846 if (getter != null) {
1847 callableGetter = typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
1848 }
1849 }
1850
1851 if (propertyDescriptor.isVar()) {
1852 PropertySetterDescriptor setter = propertyDescriptor.getSetter();
1853 if (setter != null) {
1854 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty, context)) {
1855 callableSetter = null;
1856 }
1857 else {
1858 callableSetter = typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
1859 }
1860 }
1861 }
1862 }
1863
1864 Type owner;
1865 CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter;
1866
1867 propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
1868 if (callableMethod == null) {
1869 owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
1870 context.getContextKind(), isCallInsideSameModuleAsDeclared(propertyDescriptor, context));
1871 }
1872 else {
1873 owner = callableMethod.getOwner();
1874 }
1875
1876 String name;
1877 //noinspection ConstantConditions
1878 if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) {
1879 assert backingFieldContext instanceof FieldOwnerContext : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext" ;
1880 name = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty);
1881 } else {
1882 name = JvmAbi.getDefaultPropertyName(propertyDescriptor.getName(), isDelegatedProperty, propertyDescriptor.getReceiverParameter() != null);
1883 }
1884
1885 return StackValue.property(propertyDescriptor, owner,
1886 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
1887 isStatic, name, callableGetter, callableSetter, state);
1888
1889 }
1890
1891 @Override
1892 public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) {
1893 JetExpression callee = expression.getCalleeExpression();
1894 assert callee != null;
1895
1896 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee);
1897 if (resolvedCall == null) {
1898 throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression);
1899 }
1900
1901 DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor();
1902
1903 if (!(funDescriptor instanceof FunctionDescriptor)) {
1904 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor);
1905 }
1906
1907 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor);
1908
1909 if (funDescriptor instanceof ConstructorDescriptor) {
1910 return generateNewCall(expression, resolvedCall, receiver);
1911 }
1912
1913 Call call = bindingContext.get(CALL, expression.getCalleeExpression());
1914 if (funDescriptor instanceof SimpleFunctionDescriptor) {
1915 SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) funDescriptor).getOriginal();
1916 if (original instanceof SamConstructorDescriptor) {
1917 return invokeSamConstructor(expression, resolvedCall, ((SamConstructorDescriptor) original).getBaseForSynthesized());
1918 }
1919 }
1920
1921 return invokeFunction(call, receiver, resolvedCall);
1922 }
1923
1924 @NotNull
1925 private StackValue invokeSamConstructor(JetCallExpression expression, ResolvedCall<?> resolvedCall, JavaClassDescriptor samInterface) {
1926 List<ResolvedValueArgument> arguments = resolvedCall.getValueArgumentsByIndex();
1927 if (arguments == null) {
1928 throw new IllegalStateException("Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor());
1929 }
1930 ResolvedValueArgument argument = arguments.get(0);
1931 if (!(argument instanceof ExpressionValueArgument)) {
1932 throw new IllegalStateException(
1933 "argument of SAM constructor is " + argument.getClass().getName() + " " + expression.getText());
1934 }
1935 ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument();
1936 assert valueArgument != null : "getValueArgument() is null for " + expression.getText();
1937 JetExpression argumentExpression = valueArgument.getArgumentExpression();
1938 assert argumentExpression != null : "getArgumentExpression() is null for " + expression.getText();
1939
1940 return genSamInterfaceValue(argumentExpression, samInterface, this);
1941 }
1942
1943 @NotNull
1944 private StackValue genSamInterfaceValue(
1945 @NotNull JetExpression expression,
1946 @NotNull JavaClassDescriptor samInterface,
1947 @NotNull JetVisitor<StackValue, StackValue> visitor
1948 ) {
1949 if (expression instanceof JetFunctionLiteralExpression) {
1950 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samInterface,
1951 KotlinSyntheticClass.Kind.SAM_LAMBDA);
1952 }
1953
1954 Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samInterface, (JetFile) expression.getContainingFile());
1955
1956 v.anew(asmType);
1957 v.dup();
1958
1959 @SuppressWarnings("ConstantConditions")
1960 Type functionType = typeMapper.mapType(samInterface.getFunctionTypeForSamInterface());
1961 expression.accept(visitor, StackValue.none()).put(functionType, v);
1962
1963 Label ifNonNull = new Label();
1964 Label afterAll = new Label();
1965
1966 v.dup();
1967 v.ifnonnull(ifNonNull);
1968
1969 // if null: pop function value and wrapper objects, put null
1970 v.pop();
1971 v.pop2();
1972 v.aconst(null);
1973 v.goTo(afterAll);
1974
1975 v.mark(ifNonNull);
1976 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType));
1977
1978 v.mark(afterAll);
1979 return StackValue.onStack(asmType);
1980 }
1981
1982 @NotNull
1983 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) {
1984 return context.accessiblePropertyDescriptor(propertyDescriptor);
1985 }
1986
1987 @NotNull
1988 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) {
1989 return context.accessibleFunctionDescriptor(fd);
1990 }
1991
1992 @NotNull
1993 public StackValue invokeFunction(Call call, StackValue receiver, ResolvedCall<?> resolvedCall) {
1994 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
1995 return invokeFunction(call, receiver, ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall());
1996 }
1997
1998 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
1999 JetSuperExpression superCallExpression = getSuperCallExpression(call);
2000 boolean superCall = superCallExpression != null;
2001
2002 if (superCall && !isInterface(fd.getContainingDeclaration())) {
2003 ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression);
2004 CodegenContext c = context.findParentContextWithDescriptor(owner);
2005 assert c != null : "Couldn't find a context for a super-call: " + fd;
2006 if (c != context.getParentContext()) {
2007 fd = (FunctionDescriptor) c.getAccessor(fd);
2008 }
2009 }
2010
2011 Callable callable = resolveToCallable(accessibleFunctionDescriptor(fd), superCall);
2012
2013 if (callable instanceof CallableMethod) {
2014 CallableMethod callableMethod = (CallableMethod) callable;
2015 Type calleeType = callableMethod.getGenerateCalleeType();
2016 if (calleeType != null) {
2017 assert !callableMethod.isNeedsThis() : "Method should have a receiver: " + resolvedCall.getResultingDescriptor();
2018 gen(call.getCalleeExpression(), calleeType);
2019 }
2020 }
2021
2022 return invokeFunctionWithCalleeOnStack(call, receiver, resolvedCall, callable);
2023 }
2024
2025 @NotNull
2026 private StackValue invokeFunctionWithCalleeOnStack(
2027 @NotNull Call call,
2028 @NotNull StackValue receiver,
2029 @NotNull ResolvedCall<?> resolvedCall,
2030 @NotNull Callable callable
2031 ) {
2032 if (callable instanceof CallableMethod) {
2033 CallableMethod callableMethod = (CallableMethod) callable;
2034 invokeMethodWithArguments(call, callableMethod, resolvedCall, receiver);
2035 //noinspection ConstantConditions
2036 Type returnType = typeMapper.mapReturnType(resolvedCall.getResultingDescriptor());
2037 StackValue.coerce(callableMethod.getReturnType(), returnType, v);
2038 return StackValue.onStack(returnType);
2039 }
2040 else {
2041 receiver = StackValue.receiver(resolvedCall, receiver, this, null);
2042
2043 List<JetExpression> args = new ArrayList<JetExpression>();
2044 for (ValueArgument argument : call.getValueArguments()) {
2045 args.add(argument.getArgumentExpression());
2046 }
2047
2048 Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor());
2049
2050 ((IntrinsicMethod) callable).generate(this, v, returnType, call.getCallElement(), args, receiver);
2051 return StackValue.onStack(returnType);
2052 }
2053 }
2054
2055 @Nullable
2056 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) {
2057 ReceiverValue explicitReceiver = call.getExplicitReceiver();
2058 if (explicitReceiver instanceof ExpressionReceiver) {
2059 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
2060 if (receiverExpression instanceof JetSuperExpression) {
2061 return (JetSuperExpression) receiverExpression;
2062 }
2063 }
2064 return null;
2065 }
2066
2067 // Find the first parent of the current context which corresponds to a subclass of a given class
2068 @NotNull
2069 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
2070 CodegenContext c = context;
2071 while (true) {
2072 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) {
2073 return c;
2074 }
2075 c = c.getParentContext();
2076 assert c != null;
2077 }
2078 }
2079
2080 @NotNull
2081 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) {
2082 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd);
2083 if (intrinsic != null) {
2084 return intrinsic;
2085 }
2086
2087 return resolveToCallableMethod(fd, superCall, context);
2088 }
2089
2090 @NotNull
2091 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) {
2092 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd);
2093 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, context);
2094 }
2095
2096 public void invokeMethodWithArguments(
2097 @Nullable Call call,
2098 @NotNull CallableMethod callableMethod,
2099 @NotNull ResolvedCall<?> resolvedCall,
2100 @NotNull StackValue receiver
2101 ) {
2102 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
2103 boolean isInline = state.isInlineEnabled() &&
2104 call != null &&
2105 descriptor instanceof SimpleFunctionDescriptor &&
2106 ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
2107
2108 CallGenerator callGenerator = !isInline ? defaulCallGenerator :
2109 new InlineCodegen(this, state, (SimpleFunctionDescriptor) DescriptorUtils.unwrapFakeOverride(
2110 (CallableMemberDescriptor) descriptor.getOriginal()), call);
2111
2112 if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
2113 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall();
2114 }
2115
2116 if (!(descriptor instanceof ConstructorDescriptor)) { // otherwise already
2117 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
2118 receiver.put(receiver.type, v);
2119 }
2120
2121 assert callGenerator == defaulCallGenerator || !hasDefaultArguments(resolvedCall) && !tailRecursionCodegen.isTailRecursion(resolvedCall) :
2122 "Method with defaults or tail recursive couldn't be inlined " + descriptor;
2123
2124 pushArgumentsAndInvoke(resolvedCall, callableMethod, callGenerator);
2125 }
2126
2127 private void pushArgumentsAndInvoke(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableMethod callable, @NotNull CallGenerator callGenerator) {
2128 callGenerator.putHiddenParams();
2129
2130 int mask = pushMethodArguments(resolvedCall, callable.getValueParameterTypes(), callGenerator);
2131
2132 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
2133 tailRecursionCodegen.generateTailRecursion(resolvedCall);
2134 return;
2135 }
2136
2137 callGenerator.genCall(callable, resolvedCall, mask, this);
2138 }
2139
2140 private void genThisAndReceiverFromResolvedCall(StackValue receiver, ResolvedCall<?> resolvedCall, CallableMethod callableMethod) {
2141 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
2142 receiver.put(receiver.type, v);
2143 }
2144
2145 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) {
2146 if (descriptor instanceof ClassReceiver) {
2147 Type exprType = asmType(descriptor.getType());
2148 ClassReceiver classReceiver = (ClassReceiver) descriptor;
2149 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor();
2150 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) {
2151 if (context.getContextDescriptor() instanceof FunctionDescriptor &&
2152 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) {
2153 v.load(0, OBJECT_TYPE);
2154 }
2155 else {
2156 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper);
2157 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor());
2158 }
2159 StackValue.onStack(exprType).put(type, v);
2160 }
2161 else {
2162 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false, false).put(type, v);
2163 }
2164 }
2165 else if (descriptor instanceof ScriptReceiver) {
2166 generateScript((ScriptReceiver) descriptor);
2167 }
2168 else if (descriptor instanceof ExtensionReceiver) {
2169 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
2170 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v);
2171 }
2172 else if (descriptor instanceof ExpressionReceiver) {
2173 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
2174 JetExpression expr = expressionReceiver.getExpression();
2175 gen(expr, type);
2176 }
2177 else {
2178 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor);
2179 }
2180 }
2181
2182 @Nullable
2183 private static JetExpression getReceiverForSelector(PsiElement expression) {
2184 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
2185 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
2186 return parent.getReceiverExpression();
2187 }
2188 return null;
2189 }
2190
2191 private StackValue generateReceiver(DeclarationDescriptor provided) {
2192 if (context.getCallableDescriptorWithReceiver() == provided) {
2193 return context.getReceiverExpression(typeMapper);
2194 }
2195
2196 return context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false);
2197 }
2198
2199 private void generateScript(@NotNull ScriptReceiver receiver) {
2200 CodegenContext cur = context;
2201 StackValue result = StackValue.local(0, OBJECT_TYPE);
2202 boolean inStartConstructorContext = cur instanceof ConstructorContext;
2203 while (cur != null) {
2204 if (!inStartConstructorContext) {
2205 cur = getNotNullParentContextForMethod(cur);
2206 }
2207
2208 if (cur instanceof ScriptContext) {
2209 ScriptContext scriptContext = (ScriptContext) cur;
2210
2211 Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor());
2212 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) {
2213 result.put(currentScriptType, v);
2214 }
2215 else {
2216 Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor());
2217 String fieldName = getParentScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor());
2218 result.put(currentScriptType, v);
2219 StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v);
2220 }
2221 return;
2222 }
2223
2224 result = cur.getOuterExpression(result, false);
2225
2226 if (inStartConstructorContext) {
2227 cur = getNotNullParentContextForMethod(cur);
2228 inStartConstructorContext = false;
2229 }
2230
2231 cur = cur.getParentContext();
2232 }
2233
2234 throw new UnsupportedOperationException();
2235 }
2236
2237 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
2238 boolean isSingleton = calleeContainingClass.getKind().isSingleton();
2239 if (isSingleton) {
2240 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) {
2241 return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
2242 }
2243 else {
2244 return StackValue.singleton(calleeContainingClass, typeMapper);
2245 }
2246 }
2247
2248 CodegenContext cur = context;
2249 Type type = asmType(calleeContainingClass.getDefaultType());
2250 StackValue result = StackValue.local(0, type);
2251 boolean inStartConstructorContext = cur instanceof ConstructorContext;
2252 while (cur != null) {
2253 ClassDescriptor thisDescriptor = cur.getThisDescriptor();
2254 if (!isSuper && thisDescriptor.equals(calleeContainingClass)
2255 || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
2256 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass);
2257 }
2258
2259 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer
2260 if (inStartConstructorContext) {
2261 result = cur.getOuterExpression(result, false);
2262 cur = getNotNullParentContextForMethod(cur);
2263 inStartConstructorContext = false;
2264 }
2265 else {
2266 cur = getNotNullParentContextForMethod(cur);
2267 result = cur.getOuterExpression(result, false);
2268 }
2269
2270 cur = cur.getParentContext();
2271 }
2272
2273 throw new UnsupportedOperationException();
2274 }
2275
2276 @NotNull
2277 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) {
2278 if (cur instanceof MethodContext) {
2279 cur = cur.getParentContext();
2280 }
2281 assert cur != null;
2282 return cur;
2283 }
2284
2285
2286 private static boolean isReceiver(PsiElement expression) {
2287 PsiElement parent = expression.getParent();
2288 if (parent instanceof JetQualifiedExpression) {
2289 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression();
2290 return expression == receiverExpression;
2291 }
2292 return false;
2293 }
2294
2295 public int pushMethodArguments(@NotNull ResolvedCall<?> resolvedCall, List<Type> valueParameterTypes, @NotNull CallGenerator callGenerator) {
2296 return pushMethodArguments(resolvedCall, valueParameterTypes, false, callGenerator);
2297 }
2298
2299 private int pushMethodArguments(@NotNull ResolvedCall<?> resolvedCall, List<Type> valueParameterTypes, boolean skipLast, @NotNull CallGenerator callGenerator) {
2300 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
2301 CallableDescriptor fd = resolvedCall.getResultingDescriptor();
2302 if (valueArguments == null) {
2303 throw new IllegalStateException("Failed to arrange value arguments by index: " + fd);
2304 }
2305 List<ValueParameterDescriptor> valueParameters = fd.getValueParameters();
2306
2307 if (valueParameters.size() != valueArguments.size()) {
2308 throw new IllegalStateException("Parameters and arguments size mismatch: " + valueParameters.size() + " != " + valueArguments.size());
2309 }
2310
2311 int mask = 0;
2312
2313 for (Iterator<ValueParameterDescriptor> iterator = valueParameters.iterator(); iterator.hasNext(); ) {
2314 ValueParameterDescriptor valueParameter = iterator.next();
2315 if (skipLast && !iterator.hasNext()) {
2316 continue;
2317 }
2318
2319 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
2320 Type parameterType = valueParameterTypes.get(valueParameter.getIndex());
2321 if (resolvedValueArgument instanceof ExpressionValueArgument) {
2322 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
2323 assert valueArgument != null;
2324 JetExpression argumentExpression = valueArgument.getArgumentExpression();
2325 assert argumentExpression != null : valueArgument.asElement().getText();
2326
2327 callGenerator.genValueAndPut(valueParameter, argumentExpression, parameterType);
2328 } else if (resolvedValueArgument instanceof DefaultValueArgument) {
2329 pushDefaultValueOnStack(parameterType, v);
2330 mask |= (1 << valueParameter.getIndex());
2331 callGenerator.afterParameterPut(parameterType, null, valueParameter);
2332 }
2333 else if (resolvedValueArgument instanceof VarargValueArgument) {
2334 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
2335 genVarargs(valueParameter, valueArgument);
2336 callGenerator.afterParameterPut(parameterType, null, valueParameter);
2337 }
2338 else {
2339 throw new UnsupportedOperationException();
2340 }
2341 }
2342 return mask;
2343 }
2344
2345 private static boolean hasDefaultArguments(@NotNull ResolvedCall<?> resolvedCall) {
2346 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
2347 CallableDescriptor fd = resolvedCall.getResultingDescriptor();
2348 if (valueArguments == null) {
2349 throw new IllegalStateException("Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor());
2350 }
2351
2352 for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
2353 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
2354 if (resolvedValueArgument instanceof DefaultValueArgument) {
2355 return true;
2356 }
2357 }
2358 return false;
2359 }
2360
2361 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) {
2362 JetType outType = valueParameterDescriptor.getType();
2363
2364 Type type = asmType(outType);
2365 assert type.getSort() == Type.ARRAY;
2366 Type elementType = correctElementType(type);
2367 List<ValueArgument> arguments = valueArgument.getArguments();
2368 int size = arguments.size();
2369
2370 boolean hasSpread = false;
2371 for (int i = 0; i != size; ++i) {
2372 if (arguments.get(i).getSpreadElement() != null) {
2373 hasSpread = true;
2374 break;
2375 }
2376 }
2377
2378 if (hasSpread) {
2379 if (size == 1) {
2380 gen(arguments.get(0).getArgumentExpression(), type);
2381 }
2382 else {
2383 String owner = "kotlin/jvm/internal/SpreadBuilder";
2384 v.anew(Type.getObjectType(owner));
2385 v.dup();
2386 v.invokespecial(owner, "<init>", "()V");
2387 for (int i = 0; i != size; ++i) {
2388 v.dup();
2389 ValueArgument argument = arguments.get(i);
2390 if (argument.getSpreadElement() != null) {
2391 gen(argument.getArgumentExpression(), OBJECT_TYPE);
2392 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V");
2393 }
2394 else {
2395 gen(argument.getArgumentExpression(), elementType);
2396 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z");
2397 v.pop();
2398 }
2399 }
2400 v.dup();
2401 v.invokevirtual(owner, "size", "()I");
2402 v.newarray(elementType);
2403 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
2404 v.checkcast(type);
2405 }
2406 }
2407 else {
2408 v.iconst(arguments.size());
2409 v.newarray(elementType);
2410 for (int i = 0; i != size; ++i) {
2411 v.dup();
2412 v.iconst(i);
2413 gen(arguments.get(i).getArgumentExpression(), elementType);
2414 StackValue.arrayElement(elementType, false).store(elementType, v);
2415 }
2416 }
2417 }
2418
2419 @NotNull
2420 public Type expressionType(JetExpression expr) {
2421 return asmTypeOrVoid(bindingContext.get(EXPRESSION_TYPE, expr));
2422 }
2423
2424 public int indexOfLocal(JetReferenceExpression lhs) {
2425 DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs);
2426 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) {
2427 return -1;
2428 }
2429 return lookupLocalIndex(declarationDescriptor);
2430 }
2431
2432 @Override
2433 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) {
2434 // TODO: properties
2435 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
2436 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText();
2437
2438 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, expression.getCallableReference());
2439 assert resolvedCall != null : "Callable reference is not resolved: " + functionDescriptor + " " + expression.getText();
2440
2441 JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression);
2442 assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText();
2443 ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType);
2444 assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType;
2445
2446 Type closureSuperClass = typeMapper.mapType(kFunctionImpl);
2447
2448 CallableReferenceGenerationStrategy strategy = new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall);
2449 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context,
2450 KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER,
2451 this, strategy, getParentCodegen());
2452
2453 closureCodegen.gen();
2454
2455 return closureCodegen.putInstanceOnStack(v, this);
2456 }
2457
2458 private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
2459 private final ResolvedCall<?> resolvedCall;
2460 private final FunctionDescriptor referencedFunction;
2461
2462 public CallableReferenceGenerationStrategy(
2463 @NotNull GenerationState state,
2464 @NotNull FunctionDescriptor functionDescriptor,
2465 @NotNull ResolvedCall<?> resolvedCall
2466 ) {
2467 super(state, functionDescriptor);
2468 this.resolvedCall = resolvedCall;
2469 this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
2470 }
2471
2472 @Override
2473 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
2474 /*
2475 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation
2476 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of
2477 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every
2478 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of
2479 every argument boils down to calling LOAD with the corresponding index
2480 */
2481
2482 JetCallExpression fakeExpression = constructFakeFunctionCall();
2483 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments();
2484
2485 final ReceiverValue thisObject = computeAndSaveReceiver(signature, codegen, referencedFunction.getExpectedThisObject());
2486 final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getReceiverParameter());
2487 computeAndSaveArguments(fakeArguments, codegen);
2488
2489 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
2490 @NotNull
2491 @Override
2492 public ReceiverValue getReceiverArgument() {
2493 return extensionReceiver;
2494 }
2495
2496 @NotNull
2497 @Override
2498 public ReceiverValue getThisObject() {
2499 return thisObject;
2500 }
2501
2502 @NotNull
2503 @Override
2504 public List<ResolvedValueArgument> getValueArgumentsByIndex() {
2505 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size());
2506 for (ValueArgument argument : fakeArguments) {
2507 result.add(new ExpressionValueArgument(argument));
2508 }
2509 return result;
2510 }
2511 };
2512
2513 StackValue result;
2514 Type returnType = codegen.returnType;
2515 if (referencedFunction instanceof ConstructorDescriptor) {
2516 if (returnType.getSort() == Type.ARRAY) {
2517 //noinspection ConstantConditions
2518 codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType());
2519 result = StackValue.onStack(returnType);
2520 }
2521 else {
2522 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType);
2523 }
2524 }
2525 else {
2526 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments);
2527 Callable callable = codegen.resolveToCallable(codegen.accessibleFunctionDescriptor(referencedFunction), false);
2528 StackValue receiver = generateCallee(codegen, callable);
2529 if (extensionReceiver.exists()) {
2530 receiver = StackValue.composed(receiver, receiverParameterStackValue(signature));
2531 }
2532 result = codegen.invokeFunctionWithCalleeOnStack(call, receiver, fakeResolvedCall, callable);
2533 }
2534
2535 InstructionAdapter v = codegen.v;
2536 result.put(returnType, v);
2537 v.areturn(returnType);
2538 }
2539
2540 @NotNull
2541 private StackValue generateCallee(@NotNull ExpressionCodegen codegen, @NotNull Callable callable) {
2542 if (!(callable instanceof CallableMethod) || ((CallableMethod) callable).getGenerateCalleeType() == null) {
2543 return StackValue.none();
2544 }
2545
2546 // If referenced method is a CallableMethod with generateCalleeType != null, this means it's some kind of a closure
2547 // (e.g. a local named function) and a non-trivial callee should be generated before calling invoke()
2548
2549 BindingContext bindingContext = codegen.bindingContext;
2550 ClassDescriptor closureClassOfReferenced = bindingContext.get(CLASS_FOR_FUNCTION, referencedFunction);
2551 MutableClosure closureOfReferenced = bindingContext.get(CLOSURE, closureClassOfReferenced);
2552 assert closureOfReferenced != null :
2553 "Function mapped to CallableMethod with generateCalleeType != null must be a closure: " + referencedFunction;
2554 if (isConst(closureOfReferenced)) {
2555 // This is an optimization: we can obtain an instance of a const closure simply by GETSTATIC ...$instance
2556 // (instead of passing this instance to the constructor and storing as a field)
2557 Type asmType = asmTypeForAnonymousClass(bindingContext, referencedFunction);
2558 codegen.v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
2559 return StackValue.onStack(asmType);
2560 }
2561 else {
2562 Type asmCallRefType = asmTypeForAnonymousClass(bindingContext, callableDescriptor);
2563 return codegen.context.lookupInContext(referencedFunction, StackValue.local(0, asmCallRefType), state, false);
2564 }
2565 }
2566
2567 @NotNull
2568 private JetCallExpression constructFakeFunctionCall() {
2569 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall(");
2570 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); iterator.hasNext(); ) {
2571 ValueParameterDescriptor descriptor = iterator.next();
2572 fakeFunctionCall.append("p").append(descriptor.getIndex());
2573 if (iterator.hasNext()) {
2574 fakeFunctionCall.append(", ");
2575 }
2576 }
2577 fakeFunctionCall.append(")");
2578 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString());
2579 }
2580
2581 private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) {
2582 for (ValueParameterDescriptor parameter : callableDescriptor.getValueParameters()) {
2583 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex());
2584 Type type = state.getTypeMapper().mapType(parameter);
2585 int localIndex = codegen.myFrameMap.getIndex(parameter);
2586 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type));
2587 }
2588 }
2589
2590 @NotNull
2591 private ReceiverValue computeAndSaveReceiver(
2592 @NotNull JvmMethodSignature signature,
2593 @NotNull ExpressionCodegen codegen,
2594 @Nullable ReceiverParameterDescriptor receiver
2595 ) {
2596 if (receiver == null) return NO_RECEIVER;
2597
2598 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), "callableReferenceFakeReceiver");
2599 codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
2600 return new ExpressionReceiver(receiverExpression, receiver.getType());
2601 }
2602
2603 @NotNull
2604 private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) {
2605 // 0 is this (the callable reference class), 1 is the invoke() method's first parameter
2606 return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]);
2607 }
2608 }
2609
2610 @Override
2611 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) {
2612 StackValue receiverValue = StackValue.none();
2613 return genQualified(receiverValue, expression.getSelectorExpression());
2614 }
2615
2616 @Override
2617 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
2618 JetExpression receiver = expression.getReceiverExpression();
2619 JetExpression selector = expression.getSelectorExpression();
2620 Type type = boxType(expressionType(expression));
2621 Type receiverType = expressionType(receiver);
2622
2623 gen(receiver, receiverType);
2624
2625 if (isPrimitive(receiverType)) {
2626 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
2627 propValue.put(type, v);
2628
2629 return StackValue.onStack(type);
2630 }
2631
2632 Label ifnull = new Label();
2633 Label end = new Label();
2634 v.dup();
2635 v.ifnull(ifnull);
2636 StackValue propValue = genQualified(StackValue.onStack(receiverType), selector);
2637 propValue.put(type, v);
2638 v.goTo(end);
2639
2640 v.mark(ifnull);
2641 v.pop();
2642 if (!type.equals(Type.VOID_TYPE)) {
2643 v.aconst(null);
2644 }
2645 v.mark(end);
2646
2647 return StackValue.onStack(type);
2648 }
2649
2650 @Override
2651 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) {
2652 JetSimpleNameExpression reference = expression.getOperationReference();
2653 IElementType opToken = reference.getReferencedNameElementType();
2654 if (opToken == JetTokens.EQ) {
2655 return generateAssignmentExpression(expression);
2656 }
2657 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
2658 return generateAugmentedAssignment(expression);
2659 }
2660 else if (opToken == JetTokens.ANDAND) {
2661 return generateBooleanAnd(expression);
2662 }
2663 else if (opToken == JetTokens.OROR) {
2664 return generateBooleanOr(expression);
2665 }
2666 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ ||
2667 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
2668 return generateEquals(expression.getLeft(), expression.getRight(), opToken);
2669 }
2670 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ ||
2671 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) {
2672 return generateComparison(expression, receiver);
2673 }
2674 else if (opToken == JetTokens.ELVIS) {
2675 return generateElvis(expression);
2676 }
2677 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) {
2678 return generateIn(StackValue.expression(Type.INT_TYPE, expression.getLeft(), this), expression.getRight(), reference);
2679 }
2680 else {
2681 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference);
2682 Call call = bindingContext.get(BindingContext.CALL, reference);
2683
2684 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, reference);
2685 assert op instanceof FunctionDescriptor : String.valueOf(op);
2686 Callable callable = resolveToCallable((FunctionDescriptor) op, false);
2687 if (callable instanceof IntrinsicMethod) {
2688 //noinspection ConstantConditions
2689 Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor());
2690 ((IntrinsicMethod) callable).generate(this, v, returnType, expression,
2691 Arrays.asList(expression.getLeft(), expression.getRight()), receiver);
2692 return StackValue.onStack(returnType);
2693 }
2694 else {
2695 return invokeFunction(call, receiver, resolvedCall);
2696 }
2697 }
2698 }
2699
2700 private StackValue generateIn(StackValue leftValue, JetExpression rangeExpression, JetSimpleNameExpression operationReference) {
2701 JetExpression deparenthesized = JetPsiUtil.deparenthesize(rangeExpression);
2702 if (isIntRangeExpr(deparenthesized)) {
2703 genInIntRange(leftValue, (JetBinaryExpression) deparenthesized);
2704 }
2705 else {
2706 invokeFunctionByReference(operationReference);
2707 }
2708 if (operationReference.getReferencedNameElementType() == JetTokens.NOT_IN) {
2709 genInvertBoolean(v);
2710 }
2711 return StackValue.onStack(Type.BOOLEAN_TYPE);
2712 }
2713
2714 private void genInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression) {
2715 v.iconst(1);
2716 // 1
2717 leftValue.put(Type.INT_TYPE, v);
2718 // 1 l
2719 v.dup2();
2720 // 1 l 1 l
2721
2722 //noinspection ConstantConditions
2723 gen(rangeExpression.getLeft(), Type.INT_TYPE);
2724 // 1 l 1 l r
2725 Label lok = new Label();
2726 v.ificmpge(lok);
2727 // 1 l 1
2728 v.pop();
2729 v.iconst(0);
2730 v.mark(lok);
2731 // 1 l c
2732 v.dupX2();
2733 // c 1 l c
2734 v.pop();
2735 // c 1 l
2736
2737 gen(rangeExpression.getRight(), Type.INT_TYPE);
2738 // c 1 l r
2739 Label rok = new Label();
2740 v.ificmple(rok);
2741 // c 1
2742 v.pop();
2743 v.iconst(0);
2744 v.mark(rok);
2745 // c c
2746
2747 v.and(Type.INT_TYPE);
2748 }
2749
2750 private StackValue generateBooleanAnd(JetBinaryExpression expression) {
2751 gen(expression.getLeft(), Type.BOOLEAN_TYPE);
2752 Label ifFalse = new Label();
2753 v.ifeq(ifFalse);
2754 gen(expression.getRight(), Type.BOOLEAN_TYPE);
2755 Label end = new Label();
2756 v.goTo(end);
2757 v.mark(ifFalse);
2758 v.iconst(0);
2759 v.mark(end);
2760 return StackValue.onStack(Type.BOOLEAN_TYPE);
2761 }
2762
2763 private StackValue generateBooleanOr(JetBinaryExpression expression) {
2764 gen(expression.getLeft(), Type.BOOLEAN_TYPE);
2765 Label ifTrue = new Label();
2766 v.ifne(ifTrue);
2767 gen(expression.getRight(), Type.BOOLEAN_TYPE);
2768 Label end = new Label();
2769 v.goTo(end);
2770 v.mark(ifTrue);
2771 v.iconst(1);
2772 v.mark(end);
2773 return StackValue.onStack(Type.BOOLEAN_TYPE);
2774 }
2775
2776 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) {
2777 Type leftType = expressionType(left);
2778 Type rightType = expressionType(right);
2779
2780 if (JetPsiUtil.isNullConstant(left)) {
2781 return genCmpWithNull(right, rightType, opToken);
2782 }
2783
2784 if (JetPsiUtil.isNullConstant(right)) {
2785 return genCmpWithNull(left, leftType, opToken);
2786 }
2787
2788 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) {
2789 return genCmpWithZero(right, rightType, opToken);
2790 }
2791
2792 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) {
2793 return genCmpWithZero(left, leftType, opToken);
2794 }
2795
2796 if (isPrimitive(leftType) != isPrimitive(rightType)) {
2797 leftType = boxType(leftType);
2798 gen(left, leftType);
2799 rightType = boxType(rightType);
2800 gen(right, rightType);
2801 }
2802 else {
2803 gen(left, leftType);
2804 gen(right, rightType);
2805 }
2806
2807 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType);
2808 }
2809
2810 private boolean isIntZero(JetExpression expr, Type exprType) {
2811 CompileTimeConstant<?> exprValue = getCompileTimeConstant(expr, bindingContext);
2812 return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue());
2813 }
2814
2815 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) {
2816 v.iconst(1);
2817 gen(exp, expType);
2818 Label ok = new Label();
2819 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) {
2820 v.ifeq(ok);
2821 }
2822 else {
2823 v.ifne(ok);
2824 }
2825 v.pop();
2826 v.iconst(0);
2827 v.mark(ok);
2828 return StackValue.onStack(Type.BOOLEAN_TYPE);
2829 }
2830
2831 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
2832 v.iconst(1);
2833 gen(exp, boxType(expType));
2834 Label ok = new Label();
2835 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) {
2836 v.ifnull(ok);
2837 }
2838 else {
2839 v.ifnonnull(ok);
2840 }
2841 v.pop();
2842 v.iconst(0);
2843 v.mark(ok);
2844 return StackValue.onStack(Type.BOOLEAN_TYPE);
2845 }
2846
2847 private StackValue generateElvis(JetBinaryExpression expression) {
2848 Type exprType = expressionType(expression);
2849 Type leftType = expressionType(expression.getLeft());
2850
2851 gen(expression.getLeft(), leftType);
2852
2853 if (isPrimitive(leftType)) {
2854 return StackValue.onStack(leftType);
2855 }
2856
2857 v.dup();
2858 Label ifNull = new Label();
2859 v.ifnull(ifNull);
2860 StackValue.onStack(leftType).put(exprType, v);
2861 Label end = new Label();
2862 v.goTo(end);
2863 v.mark(ifNull);
2864 v.pop();
2865 gen(expression.getRight(), exprType);
2866 v.mark(end);
2867
2868 return StackValue.onStack(exprType);
2869 }
2870
2871 private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) {
2872 DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
2873 assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target;
2874 FunctionDescriptor descriptor = (FunctionDescriptor) target;
2875
2876 JetExpression left = expression.getLeft();
2877 JetExpression right = expression.getRight();
2878 Callable callable = resolveToCallable(descriptor, false);
2879
2880 Type type;
2881 if (callable instanceof IntrinsicMethod) {
2882 // Compare two primitive values
2883 type = comparisonOperandType(expressionType(left), expressionType(right));
2884 StackValue recv = gen(left);
2885 recv.put(type, v);
2886 gen(right, type);
2887 }
2888 else {
2889 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
2890 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference());
2891 StackValue result = invokeFunction(call, receiver, resolvedCall);
2892 type = Type.INT_TYPE;
2893 result.put(type, v);
2894 v.iconst(0);
2895 }
2896 return StackValue.cmp(expression.getOperationToken(), type);
2897 }
2898
2899 private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
2900 StackValue stackValue = gen(expression.getLeft());
2901 JetExpression right = expression.getRight();
2902 assert right != null : expression.getText();
2903 gen(right, stackValue.type);
2904 stackValue.store(stackValue.type, v);
2905 return StackValue.none();
2906 }
2907
2908 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) {
2909 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
2910 assert op instanceof FunctionDescriptor : String.valueOf(op);
2911 Callable callable = resolveToCallable((FunctionDescriptor) op, false);
2912 JetExpression lhs = expression.getLeft();
2913
2914 // if (lhs instanceof JetArrayAccessExpression) {
2915 // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs;
2916 // if (arrayAccessExpression.getIndexExpressions().size() != 1) {
2917 // throw new UnsupportedOperationException("Augmented assignment with multi-index");
2918 // }
2919 // }
2920
2921 Type lhsType = expressionType(lhs);
2922 //noinspection ConstantConditions
2923 if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) {
2924 if (callable instanceof IntrinsicMethod) {
2925 StackValue value = gen(lhs); // receiver
2926 value.dupReceiver(v); // receiver receiver
2927 value.put(lhsType, v); // receiver lhs
2928 IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
2929 JetExpression right = expression.getRight();
2930 assert right != null;
2931 Type returnType = typeMapper.mapType((FunctionDescriptor) op);
2932 intrinsic.generate(this, v, returnType, expression, Collections.singletonList(right), StackValue.onStack(lhsType));
2933 value.store(lhsType, v);
2934 }
2935 else {
2936 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true);
2937 }
2938 }
2939 else {
2940 JetType type = ((FunctionDescriptor) op).getReturnType();
2941 assert type != null;
2942 boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType());
2943 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue);
2944 }
2945
2946 return StackValue.none();
2947 }
2948
2949 private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) {
2950 JetSimpleNameExpression reference = expression.getOperationReference();
2951 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference);
2952 Call call = bindingContext.get(BindingContext.CALL, reference);
2953
2954 assert resolvedCall != null : "Resolved call should be not null for operation reference in " + expression.getText();
2955 assert call != null : "Call should be not null for operation reference in " + expression.getText();
2956
2957 StackValue value = gen(expression.getLeft());
2958 if (keepReturnValue) {
2959 value.dupReceiver(v);
2960 }
2961 value.put(lhsType, v);
2962 StackValue receiver = StackValue.onStack(lhsType);
2963
2964 invokeMethodWithArguments(call, callable, resolvedCall, receiver);
2965
2966 if (keepReturnValue) {
2967 value.store(callable.getReturnType(), v);
2968 }
2969 }
2970
2971 public void invokeAppend(JetExpression expr) {
2972 if (expr instanceof JetBinaryExpression) {
2973 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr;
2974 if (binaryExpression.getOperationToken() == JetTokens.PLUS) {
2975 JetExpression left = binaryExpression.getLeft();
2976 JetExpression right = binaryExpression.getRight();
2977 Type leftType = expressionType(left);
2978 Type rightType = expressionType(right);
2979
2980 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) {
2981 invokeAppend(left);
2982 invokeAppend(right);
2983 return;
2984 }
2985 }
2986 }
2987 Type exprType = expressionType(expr);
2988 gen(expr, exprType);
2989 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
2990 }
2991
2992 @Nullable
2993 private static JetSimpleNameExpression targetLabel(JetExpression expression) {
2994 if (expression.getParent() instanceof JetPrefixExpression) {
2995 JetPrefixExpression parent = (JetPrefixExpression) expression.getParent();
2996 JetSimpleNameExpression operationSign = parent.getOperationReference();
2997 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
2998 return operationSign;
2999 }
3000 }
3001 return null;
3002 }
3003
3004 @Override
3005 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) {
3006 JetSimpleNameExpression operationSign = expression.getOperationReference();
3007 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
3008 return genQualified(receiver, expression.getBaseExpression());
3009 }
3010
3011 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
3012 assert op instanceof FunctionDescriptor : String.valueOf(op);
3013 Callable callable = resolveToCallable((FunctionDescriptor) op, false);
3014 if (callable instanceof IntrinsicMethod) {
3015 Type returnType = typeMapper.mapType((FunctionDescriptor) op);
3016 ((IntrinsicMethod) callable).generate(this, v, returnType, expression,
3017 Collections.singletonList(expression.getBaseExpression()), receiver);
3018 return StackValue.onStack(returnType);
3019 }
3020
3021 DeclarationDescriptor cls = op.getContainingDeclaration();
3022 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
3023 assert resolvedCall != null;
3024
3025 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) {
3026 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference());
3027 return invokeFunction(call, receiver, resolvedCall);
3028 }
3029
3030 CallableMethod callableMethod = (CallableMethod) callable;
3031
3032 StackValue value = gen(expression.getBaseExpression());
3033 value.dupReceiver(v);
3034 value.dupReceiver(v);
3035
3036 Type type = expressionType(expression.getBaseExpression());
3037 value.put(type, v);
3038 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall);
3039
3040 value.store(callableMethod.getReturnType(), v);
3041 value.put(type, v);
3042 return StackValue.onStack(type);
3043 }
3044
3045 @Override
3046 public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) {
3047 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) {
3048 StackValue base = genQualified(receiver, expression.getBaseExpression());
3049 if (isPrimitive(base.type)) {
3050 return base;
3051 }
3052 base.put(base.type, v);
3053 v.dup();
3054 Label ok = new Label();
3055 v.ifnonnull(ok);
3056 v.invokestatic("kotlin/jvm/internal/Intrinsics", "throwNpe", "()V");
3057 v.mark(ok);
3058 return StackValue.onStack(base.type);
3059 }
3060
3061 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
3062 if (!(op instanceof FunctionDescriptor)) {
3063 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op);
3064 }
3065
3066 Type asmType = expressionType(expression);
3067 DeclarationDescriptor cls = op.getContainingDeclaration();
3068
3069 int increment;
3070 if (op.getName().asString().equals("inc")) {
3071 increment = 1;
3072 }
3073 else if (op.getName().asString().equals("dec")) {
3074 increment = -1;
3075 }
3076 else {
3077 throw new UnsupportedOperationException("Unsupported postfix operation: " + op);
3078 }
3079
3080 boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls);
3081 if (isPrimitiveNumberClassDescriptor) {
3082 JetExpression operand = expression.getBaseExpression();
3083 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) {
3084 int index = indexOfLocal((JetReferenceExpression) operand);
3085 if (index >= 0) {
3086 return StackValue.postIncrement(index, increment);
3087 }
3088 }
3089 }
3090
3091 StackValue value = gen(expression.getBaseExpression());
3092 value.dupReceiver(v);
3093
3094 Type type = expressionType(expression.getBaseExpression());
3095 value.put(type, v); // old value
3096
3097 pushReceiverAndValueViaDup(value, type); // receiver and new value
3098
3099 Type storeType;
3100 if (isPrimitiveNumberClassDescriptor) {
3101 genIncrement(asmType, increment, v);
3102 storeType = type;
3103 }
3104 else {
3105 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
3106 assert resolvedCall != null;
3107 Callable callable = resolveToCallable((FunctionDescriptor) op, false);
3108 CallableMethod callableMethod = (CallableMethod) callable;
3109 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall);
3110 storeType = callableMethod.getReturnType();
3111 }
3112
3113 value.store(storeType, v);
3114 return StackValue.onStack(asmType); // old value
3115 }
3116
3117 private void pushReceiverAndValueViaDup(StackValue value, Type type) {
3118 switch (value.receiverSize()) {
3119 case 0:
3120 dup(v, type);
3121 break;
3122
3123 case 1:
3124 if (type.getSize() == 2) {
3125 v.dup2X1();
3126 }
3127 else {
3128 v.dupX1();
3129 }
3130 break;
3131
3132 case 2:
3133 if (type.getSize() == 2) {
3134 v.dup2X2();
3135 }
3136 else {
3137 v.dupX2();
3138 }
3139 break;
3140
3141 case -1:
3142 throw new UnsupportedOperationException();
3143 }
3144 }
3145
3146 @Override
3147 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) {
3148 final JetExpression initializer = property.getInitializer();
3149 if (initializer == null) {
3150 return StackValue.none();
3151 }
3152 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() {
3153 @Override
3154 public Void fun(VariableDescriptor descriptor) {
3155 Type varType = asmType(descriptor.getType());
3156 gen(initializer, varType);
3157 return null;
3158 }
3159 });
3160 return StackValue.none();
3161 }
3162
3163 @Override
3164 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) {
3165 JetExpression initializer = multiDeclaration.getInitializer();
3166 if (initializer == null) return StackValue.none();
3167
3168 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer);
3169 assert initializerType != null;
3170
3171 Type initializerAsmType = asmType(initializerType);
3172
3173 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType);
3174
3175 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType);
3176
3177 gen(initializer, initializerAsmType);
3178 v.store(tempVarIndex, initializerAsmType);
3179 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType);
3180
3181 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) {
3182 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() {
3183 @Override
3184 public Void fun(VariableDescriptor descriptor) {
3185 ResolvedCall<FunctionDescriptor> resolvedCall =
3186 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration);
3187 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText();
3188 Call call = makeFakeCall(initializerAsReceiver);
3189 invokeFunction(call, local, resolvedCall);
3190 return null;
3191 }
3192 });
3193 }
3194
3195 if(initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) {
3196 v.aconst(null);
3197 v.store(tempVarIndex, initializerAsmType);
3198 }
3199 myFrameMap.leaveTemp(initializerAsmType);
3200
3201 return StackValue.none();
3202 }
3203
3204 private void initializeLocalVariable(
3205 @NotNull JetVariableDeclaration variableDeclaration,
3206 @NotNull Function<VariableDescriptor, Void> generateInitializer
3207 ) {
3208
3209 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration);
3210
3211 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) {
3212 return;
3213 }
3214 int index = lookupLocalIndex(variableDescriptor);
3215
3216 if (index < 0) {
3217 throw new IllegalStateException("Local variable not found for " + variableDescriptor);
3218 }
3219
3220 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor);
3221 assert variableDescriptor != null;
3222
3223 Type varType = asmType(variableDescriptor.getType());
3224
3225 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) {
3226 generateInitializer.fun(variableDescriptor);
3227 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration);
3228 assert scriptPsi != null;
3229 Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi);
3230 v.putfield(scriptClassType.getInternalName(), variableDeclaration.getName(), varType.getDescriptor());
3231 }
3232 else if (sharedVarType == null) {
3233 generateInitializer.fun(variableDescriptor);
3234 v.store(index, varType);
3235 }
3236 else {
3237 v.load(index, OBJECT_TYPE);
3238 generateInitializer.fun(variableDescriptor);
3239 v.putfield(sharedVarType.getInternalName(), "element",
3240 sharedVarType.equals(OBJECT_REF_TYPE) ? "Ljava/lang/Object;" : varType.getDescriptor());
3241 }
3242 }
3243
3244 @NotNull
3245 private StackValue generateNewCall(
3246 @NotNull JetCallExpression expression,
3247 @NotNull ResolvedCall<?> resolvedCall,
3248 @NotNull StackValue receiver
3249 ) {
3250 Type type = expressionType(expression);
3251 if (type.getSort() == Type.ARRAY) {
3252 generateNewArray(expression);
3253 return StackValue.onStack(type);
3254 }
3255
3256 return generateConstructorCall(resolvedCall, receiver, type);
3257 }
3258
3259 @NotNull
3260 private StackValue generateConstructorCall(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver, @NotNull Type type) {
3261 v.anew(type);
3262 v.dup();
3263
3264 receiver = StackValue.receiver(resolvedCall, receiver, this, null);
3265 receiver.put(receiver.type, v);
3266
3267 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
3268 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration());
3269
3270 ClassDescriptor descriptor = getExpectedThisObjectForConstructorCall(constructorDescriptor, closure);
3271 if (receiver.type.getSort() != Type.VOID && descriptor == null) {
3272 v.pop();
3273 }
3274
3275 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument()
3276 //so we need generate closure on stack
3277 //See StackValue.receiver for more info
3278 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists(), defaulCallGenerator);
3279
3280 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor);
3281 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
3282 invokeMethodWithArguments(null, method, resolvedCall, StackValue.none());
3283
3284 return StackValue.onStack(type);
3285 }
3286
3287 public void generateNewArray(@NotNull JetCallExpression expression) {
3288 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression);
3289 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText();
3290
3291 generateNewArray(expression, arrayType);
3292 }
3293
3294 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) {
3295 List<JetExpression> args = new ArrayList<JetExpression>();
3296 for (ValueArgument va : expression.getValueArguments()) {
3297 args.add(va.getArgumentExpression());
3298 }
3299 args.addAll(expression.getFunctionLiteralArguments());
3300
3301 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType);
3302 if (!isArray && args.size() != 1) {
3303 throw new CompilationException("primitive array constructor requires one argument", null, expression);
3304 }
3305
3306 if (isArray) {
3307 gen(args.get(0), Type.INT_TYPE);
3308 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType())));
3309 }
3310 else {
3311 Type type = typeMapper.mapType(arrayType);
3312 gen(args.get(0), Type.INT_TYPE);
3313 v.newarray(correctElementType(type));
3314 }
3315
3316 if (args.size() == 2) {
3317 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE);
3318 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE);
3319
3320 v.dup();
3321 v.arraylength();
3322 v.store(sizeIndex, Type.INT_TYPE);
3323
3324 v.iconst(0);
3325 v.store(indexIndex, Type.INT_TYPE);
3326
3327 gen(args.get(1), FUNCTION1_TYPE);
3328
3329 Label begin = new Label();
3330 Label end = new Label();
3331 v.visitLabel(begin);
3332 v.load(indexIndex, Type.INT_TYPE);
3333 v.load(sizeIndex, Type.INT_TYPE);
3334 v.ificmpge(end);
3335
3336 v.dup2();
3337 v.load(indexIndex, Type.INT_TYPE);
3338 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
3339 v.invokeinterface(FUNCTION1_TYPE.getInternalName(), "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;");
3340 v.load(indexIndex, Type.INT_TYPE);
3341 v.iinc(indexIndex, 1);
3342 v.swap();
3343 v.astore(OBJECT_TYPE);
3344
3345 v.goTo(begin);
3346 v.visitLabel(end);
3347 v.pop();
3348
3349 myFrameMap.leaveTemp(Type.INT_TYPE);
3350 myFrameMap.leaveTemp(Type.INT_TYPE);
3351 }
3352 }
3353
3354 @Override
3355 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) {
3356 JetExpression array = expression.getArrayExpression();
3357 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
3358 Type arrayType = asmTypeOrVoid(type);
3359 List<JetExpression> indices = expression.getIndexExpressions();
3360 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
3361 assert operationDescriptor != null;
3362 if (arrayType.getSort() == Type.ARRAY &&
3363 indices.size() == 1 &&
3364 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) {
3365 gen(array, arrayType);
3366 for (JetExpression index : indices) {
3367 gen(index, Type.INT_TYPE);
3368 }
3369 assert type != null;
3370 if (KotlinBuiltIns.getInstance().isArray(type)) {
3371 JetType elementType = type.getArguments().get(0).getType();
3372 Type notBoxed = asmType(elementType);
3373 return StackValue.arrayElement(notBoxed, true);
3374 }
3375 else {
3376 return StackValue.arrayElement(correctElementType(arrayType), false);
3377 }
3378 }
3379 else {
3380 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
3381 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
3382
3383 boolean isGetter = "get".equals(operationDescriptor.getName().asString());
3384
3385 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall;
3386 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText();
3387
3388 Callable callable = resolveToCallable(operationDescriptor, false);
3389 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getAsmMethod();
3390 Type[] argumentTypes = asmMethod.getArgumentTypes();
3391
3392 if (callable instanceof CallableMethod) {
3393 genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable);
3394 boolean skipLast = !isGetter;
3395 pushMethodArguments(resolvedCall, ((CallableMethod) callable).getValueParameterTypes(), skipLast, defaulCallGenerator);
3396 }
3397 else {
3398 gen(array, arrayType); // intrinsic method
3399
3400 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0;
3401
3402 for (JetExpression jetExpression : expression.getIndexExpressions()) {
3403 gen(jetExpression, argumentTypes[index]);
3404 index++;
3405 }
3406 }
3407
3408 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes);
3409 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state);
3410 }
3411 }
3412
3413 @Override
3414 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) {
3415 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE);
3416 v.athrow();
3417 return StackValue.none();
3418 }
3419
3420 @Override
3421 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) {
3422 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
3423 if (descriptor instanceof ClassDescriptor) {
3424 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true);
3425 }
3426 else {
3427 if (descriptor instanceof CallableDescriptor) {
3428 return generateReceiver(descriptor);
3429 }
3430 throw new UnsupportedOperationException("neither this nor receiver");
3431 }
3432 }
3433
3434 @Override
3435 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) {
3436 return generateTryExpression(expression, false);
3437 }
3438
3439 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) {
3440 /*
3441 The "returned" value of try expression with no finally is either the last expression in the try block or the last expression in the catch block
3442 (or blocks).
3443 */
3444 JetFinallySection finallyBlock = expression.getFinallyBlock();
3445 FinallyBlockStackElement finallyBlockStackElement = null;
3446 if (finallyBlock != null) {
3447 finallyBlockStackElement = new FinallyBlockStackElement(expression);
3448 blockStackElements.push(finallyBlockStackElement);
3449 }
3450
3451 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
3452 assert jetType != null;
3453 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType);
3454
3455 Label tryStart = new Label();
3456 v.mark(tryStart);
3457 v.nop(); // prevent verify error on empty try
3458
3459 gen(expression.getTryBlock(), expectedAsmType);
3460
3461 int savedValue = -1;
3462 if (!isStatement) {
3463 savedValue = myFrameMap.enterTemp(expectedAsmType);
3464 v.store(savedValue, expectedAsmType);
3465 }
3466
3467 Label tryEnd = new Label();
3468 v.mark(tryEnd);
3469
3470 //do it before finally block generation
3471 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd);
3472
3473 Label end = new Label();
3474
3475 genFinallyBlockOrGoto(finallyBlockStackElement, end);
3476
3477 List<JetCatchClause> clauses = expression.getCatchClauses();
3478 for (int i = 0, size = clauses.size(); i < size; i++) {
3479 JetCatchClause clause = clauses.get(i);
3480
3481 Label clauseStart = new Label();
3482 v.mark(clauseStart);
3483
3484 VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter());
3485 assert descriptor != null;
3486 Type descriptorType = asmType(descriptor.getType());
3487 myFrameMap.enter(descriptor, descriptorType);
3488 int index = lookupLocalIndex(descriptor);
3489 v.store(index, descriptorType);
3490
3491 gen(clause.getCatchBody(), expectedAsmType);
3492
3493 if (!isStatement) {
3494 v.store(savedValue, expectedAsmType);
3495 }
3496
3497 myFrameMap.leave(descriptor);
3498
3499 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null);
3500
3501 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName());
3502 }
3503
3504
3505 //for default catch clause
3506 if (finallyBlock != null) {
3507 Label defaultCatchStart = new Label();
3508 v.mark(defaultCatchStart);
3509 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE);
3510 v.store(savedException, JAVA_THROWABLE_TYPE);
3511 Label defaultCatchEnd = new Label();
3512 v.mark(defaultCatchEnd);
3513
3514 //do it before finally block generation
3515 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter
3516 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd);
3517
3518
3519 genFinallyBlockOrGoto(finallyBlockStackElement, null);
3520
3521 v.load(savedException, JAVA_THROWABLE_TYPE);
3522 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE);
3523
3524 v.athrow();
3525
3526 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null);
3527 }
3528
3529 markLineNumber(expression);
3530 v.mark(end);
3531
3532 if (!isStatement) {
3533 v.load(savedValue, expectedAsmType);
3534 myFrameMap.leaveTemp(expectedAsmType);
3535 }
3536
3537 if (finallyBlock != null) {
3538 blockStackElements.pop();
3539 }
3540
3541 return StackValue.onStack(expectedAsmType);
3542 }
3543
3544 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) {
3545 for (int i = 0; i < catchedRegions.size(); i += 2) {
3546 Label startRegion = catchedRegions.get(i);
3547 Label endRegion = catchedRegions.get(i+1);
3548 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception);
3549 }
3550 }
3551
3552 @NotNull
3553 private static List<Label> getCurrentCatchIntervals(
3554 @Nullable FinallyBlockStackElement finallyBlockStackElement,
3555 @NotNull Label blockStart,
3556 @NotNull Label blockEnd
3557 ) {
3558 List<Label> gapsInBlock =
3559 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList();
3560 assert gapsInBlock.size() % 2 == 0;
3561 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2);
3562 blockRegions.add(blockStart);
3563 blockRegions.addAll(gapsInBlock);
3564 blockRegions.add(blockEnd);
3565 return blockRegions;
3566 }
3567
3568 @Override
3569 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) {
3570 JetSimpleNameExpression operationSign = expression.getOperationReference();
3571 IElementType opToken = operationSign.getReferencedNameElementType();
3572 if (opToken == JetTokens.COLON) {
3573 return gen(expression.getLeft());
3574 }
3575 else {
3576 JetTypeReference typeReference = expression.getRight();
3577 JetType rightType = bindingContext.get(BindingContext.TYPE, typeReference);
3578 assert rightType != null;
3579 Type rightTypeAsm = boxType(asmType(rightType));
3580 JetExpression left = expression.getLeft();
3581 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor();
3582 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
3583 StackValue value = genQualified(receiver, left);
3584 value.put(boxType(value.type), v);
3585
3586 if (opToken != JetTokens.AS_SAFE) {
3587 if (!CodegenUtil.isNullableType(rightType)) {
3588 v.dup();
3589 Label nonnull = new Label();
3590 v.ifnonnull(nonnull);
3591 JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left);
3592 assert leftType != null;
3593 throwNewException("kotlin/TypeCastException", DescriptorRenderer.TEXT.renderType(leftType) +
3594 " cannot be cast to " +
3595 DescriptorRenderer.TEXT.renderType(rightType));
3596 v.mark(nonnull);
3597 }
3598 }
3599 else {
3600 v.dup();
3601 v.instanceOf(rightTypeAsm);
3602 Label ok = new Label();
3603 v.ifne(ok);
3604 v.pop();
3605 v.aconst(null);
3606 v.mark(ok);
3607 }
3608
3609 v.checkcast(rightTypeAsm);
3610 return StackValue.onStack(rightTypeAsm);
3611 }
3612 else {
3613 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor);
3614 }
3615 }
3616 }
3617
3618 @Override
3619 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) {
3620 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this);
3621 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated());
3622 }
3623
3624 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) {
3625 if (expressionToMatch != null) {
3626 Type subjectType = expressionToMatch.type;
3627 expressionToMatch.dupReceiver(v);
3628 expressionToMatch.put(subjectType, v);
3629 JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression);
3630 Type condType;
3631 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
3632 assert condJetType != null;
3633 condType = asmType(condJetType);
3634 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
3635 subjectType = boxType(subjectType);
3636 expressionToMatch.coerceTo(subjectType, v);
3637 }
3638 }
3639 else {
3640 condType = OBJECT_TYPE;
3641 }
3642 gen(patternExpression, condType);
3643 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType);
3644 }
3645 else {
3646 return gen(patternExpression);
3647 }
3648 }
3649
3650 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) {
3651 JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
3652 expressionToMatch.dupReceiver(v);
3653 generateInstanceOf(expressionToMatch, jetType, false);
3654 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
3655 return negated ? StackValue.not(value) : value;
3656 }
3657
3658 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
3659 expressionToGen.put(OBJECT_TYPE, v);
3660 if (leaveExpressionOnStack) {
3661 v.dup();
3662 }
3663 Type type = boxType(asmType(jetType));
3664 if (jetType.isNullable()) {
3665 Label nope = new Label();
3666 Label end = new Label();
3667
3668 v.dup();
3669 v.ifnull(nope);
3670 v.instanceOf(type);
3671 v.goTo(end);
3672 v.mark(nope);
3673 v.pop();
3674 v.iconst(1);
3675 v.mark(end);
3676 }
3677 else {
3678 v.instanceOf(type);
3679 }
3680 }
3681
3682 @Override
3683 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) {
3684 return generateWhenExpression(expression, false);
3685 }
3686
3687 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) {
3688 JetExpression expr = expression.getSubjectExpression();
3689 JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
3690 Type subjectType = asmTypeOrVoid(subjectJetType);
3691 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression);
3692 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
3693 if (subjectLocal != -1) {
3694 gen(expr, subjectType);
3695 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType));
3696 v.store(subjectLocal, subjectType);
3697 }
3698
3699 Label end = new Label();
3700 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression);
3701
3702 Label nextCondition = null;
3703 for (JetWhenEntry whenEntry : expression.getEntries()) {
3704 if (nextCondition != null) {
3705 v.mark(nextCondition);
3706 }
3707 nextCondition = new Label();
3708 FrameMap.Mark mark = myFrameMap.mark();
3709 Label thisEntry = new Label();
3710 if (!whenEntry.isElse()) {
3711 JetWhenCondition[] conditions = whenEntry.getConditions();
3712 for (int i = 0; i < conditions.length; i++) {
3713 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]);
3714 conditionValue.condJump(nextCondition, true, v);
3715 if (i < conditions.length - 1) {
3716 v.goTo(thisEntry);
3717 v.mark(nextCondition);
3718 nextCondition = new Label();
3719 }
3720 }
3721 }
3722
3723 v.visitLabel(thisEntry);
3724 gen(whenEntry.getExpression(), resultType);
3725 mark.dropTo();
3726 if (!whenEntry.isElse()) {
3727 v.goTo(end);
3728 }
3729 }
3730 if (!hasElse && nextCondition != null) {
3731 v.mark(nextCondition);
3732 if (!isStatement) {
3733 // a result is expected
3734 if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) {
3735 // when() is supposed to be exhaustive
3736 throwNewException("kotlin/NoWhenBranchMatchedException");
3737 }
3738 else {
3739 // non-exhaustive when() with no else -> Unit must be expected
3740 StackValue.putUnitInstance(v);
3741 }
3742 }
3743 }
3744
3745 markLineNumber(expression);
3746 v.mark(end);
3747
3748 myFrameMap.leaveTemp(subjectType);
3749 tempVariables.remove(expr);
3750 return StackValue.onStack(resultType);
3751 }
3752
3753 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) {
3754 if (condition instanceof JetWhenConditionInRange) {
3755 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition;
3756 return generateIn(StackValue.local(subjectLocal, subjectType),
3757 conditionInRange.getRangeExpression(),
3758 conditionInRange.getOperationReference());
3759 }
3760 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType);
3761 if (condition instanceof JetWhenConditionIsPattern) {
3762 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition;
3763 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated());
3764 }
3765 else if (condition instanceof JetWhenConditionWithExpression) {
3766 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression();
3767 return generateExpressionMatch(match, patternExpression);
3768 }
3769 else {
3770 throw new UnsupportedOperationException("unsupported kind of when condition");
3771 }
3772 }
3773
3774 private void invokeFunctionByReference(JetSimpleNameExpression operationReference) {
3775 ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, operationReference);
3776 Call call = bindingContext.get(CALL, operationReference);
3777 invokeFunction(call, StackValue.none(), resolvedCall);
3778 }
3779
3780 private boolean isIntRangeExpr(JetExpression rangeExpression) {
3781 if (rangeExpression instanceof JetBinaryExpression) {
3782 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression;
3783 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) {
3784 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression);
3785 assert jetType != null;
3786 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
3787 return INTEGRAL_RANGES.contains(descriptor);
3788 }
3789 }
3790 return false;
3791 }
3792
3793 private void throwNewException(@NotNull String className) {
3794 throwNewException(className, null);
3795 }
3796
3797 private void throwNewException(@NotNull String className, @Nullable String message) {
3798 v.anew(Type.getObjectType(className));
3799 v.dup();
3800 if (message != null) {
3801 v.visitLdcInsn(message);
3802 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V");
3803 }
3804 else {
3805 v.invokespecial(className, "<init>", "()V");
3806 }
3807 v.athrow();
3808 }
3809
3810 private Call makeFakeCall(ReceiverValue initializerAsReceiver) {
3811 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake");
3812 return CallMaker.makeCall(fake, initializerAsReceiver);
3813 }
3814
3815 @Override
3816 public String toString() {
3817 return context.getContextDescriptor().toString();
3818 }
3819
3820 @NotNull
3821 private ScriptCodegen getParentScriptCodegen() {
3822 MemberCodegen codegen = parentCodegen;
3823 while (codegen != null) {
3824 if (codegen instanceof ScriptCodegen) {
3825 return (ScriptCodegen) codegen;
3826 }
3827 codegen = codegen.getParentCodegen();
3828 }
3829 throw new IllegalStateException("Script codegen should be present in codegen tree");
3830 }
3831
3832 @NotNull
3833 public FrameMap getFrameMap() {
3834 return myFrameMap;
3835 }
3836
3837 @NotNull
3838 public MethodContext getContext() {
3839 return context;
3840 }
3841
3842 @NotNull
3843 public NameGenerator getInlineNameGenerator() {
3844 NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator();
3845 Name name = context.getContextDescriptor().getName();
3846 return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" );
3847 }
3848 }