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