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