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