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