001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.intellij.openapi.progress.ProcessCanceledException; 022 import com.intellij.psi.PsiElement; 023 import com.intellij.psi.tree.IElementType; 024 import com.intellij.util.ArrayUtil; 025 import com.intellij.util.Function; 026 import com.intellij.util.containers.Stack; 027 import kotlin.CollectionsKt; 028 import kotlin.Unit; 029 import kotlin.jvm.functions.Function1; 030 import org.jetbrains.annotations.NotNull; 031 import org.jetbrains.annotations.Nullable; 032 import org.jetbrains.kotlin.backend.common.CodegenUtil; 033 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 034 import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; 035 import org.jetbrains.kotlin.codegen.binding.CodegenBinding; 036 import org.jetbrains.kotlin.codegen.context.*; 037 import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension; 038 import org.jetbrains.kotlin.codegen.inline.*; 039 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod; 040 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; 041 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicPropertyGetter; 042 import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics; 043 import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsKt; 044 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; 045 import org.jetbrains.kotlin.codegen.state.GenerationState; 046 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 047 import org.jetbrains.kotlin.codegen.when.SwitchCodegen; 048 import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; 049 import org.jetbrains.kotlin.descriptors.*; 050 import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor; 051 import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; 052 import org.jetbrains.kotlin.diagnostics.Errors; 053 import org.jetbrains.kotlin.incremental.components.NoLookupLocation; 054 import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo; 055 import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesKt; 056 import org.jetbrains.kotlin.lexer.KtTokens; 057 import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; 058 import org.jetbrains.kotlin.name.Name; 059 import org.jetbrains.kotlin.psi.*; 060 import org.jetbrains.kotlin.renderer.DescriptorRenderer; 061 import org.jetbrains.kotlin.resolve.BindingContext; 062 import org.jetbrains.kotlin.resolve.BindingContextUtils; 063 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 064 import org.jetbrains.kotlin.resolve.DescriptorUtils; 065 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 066 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt; 067 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; 068 import org.jetbrains.kotlin.resolve.calls.model.*; 069 import org.jetbrains.kotlin.resolve.calls.util.CallMaker; 070 import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; 071 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 072 import org.jetbrains.kotlin.resolve.constants.ConstantValue; 073 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 074 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; 075 import org.jetbrains.kotlin.resolve.inline.InlineUtil; 076 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; 077 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind; 078 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature; 079 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; 080 import org.jetbrains.kotlin.resolve.scopes.receivers.*; 081 import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; 082 import org.jetbrains.kotlin.types.KotlinType; 083 import org.jetbrains.kotlin.types.TypeProjection; 084 import org.jetbrains.kotlin.types.TypeUtils; 085 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; 086 import org.jetbrains.org.objectweb.asm.Label; 087 import org.jetbrains.org.objectweb.asm.MethodVisitor; 088 import org.jetbrains.org.objectweb.asm.Opcodes; 089 import org.jetbrains.org.objectweb.asm.Type; 090 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 091 092 import java.util.*; 093 094 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isInt; 095 import static org.jetbrains.kotlin.codegen.AsmUtil.*; 096 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.couldUseDirectAccessToProperty; 097 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; 098 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; 099 import static org.jetbrains.kotlin.resolve.BindingContext.*; 100 import static org.jetbrains.kotlin.resolve.BindingContextUtils.*; 101 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry; 102 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject; 103 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 104 import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation; 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 KtMultiDeclaration multiParameter = forExpression.getMultiParameter(); 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 KtMultiDeclaration multiParameter = forExpression.getMultiParameter(); 691 assert multiParameter != null; 692 693 generateMultiVariables(multiParameter.getEntries()); 694 } 695 } 696 697 private void generateMultiVariables(List<KtMultiDeclarationEntry> entries) { 698 for (KtMultiDeclarationEntry 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("increment"), 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 CompileTimeConstant<?> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, bindingContext); 1247 if (compileTimeValue == null) { 1248 return null; 1249 } 1250 KotlinType expectedType = bindingContext.getType(expression); 1251 return compileTimeValue.toConstantValue(expectedType); 1252 } 1253 1254 @Override 1255 public StackValue visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, StackValue receiver) { 1256 StringBuilder constantValue = new StringBuilder(""); 1257 final KtStringTemplateEntry[] entries = expression.getEntries(); 1258 1259 if (entries.length == 1 && entries[0] instanceof KtStringTemplateEntryWithExpression) { 1260 KtExpression expr = entries[0].getExpression(); 1261 return genToString(gen(expr), expressionType(expr)); 1262 } 1263 1264 for (KtStringTemplateEntry entry : entries) { 1265 if (entry instanceof KtLiteralStringTemplateEntry) { 1266 constantValue.append(entry.getText()); 1267 } 1268 else if (entry instanceof KtEscapeStringTemplateEntry) { 1269 constantValue.append(((KtEscapeStringTemplateEntry) entry).getUnescapedValue()); 1270 } 1271 else { 1272 constantValue = null; 1273 break; 1274 } 1275 } 1276 if (constantValue != null) { 1277 Type type = expressionType(expression); 1278 return StackValue.constant(constantValue.toString(), type); 1279 } 1280 else { 1281 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 1282 @Override 1283 public Unit invoke(InstructionAdapter v) { 1284 genStringBuilderConstructor(v); 1285 for (KtStringTemplateEntry entry : entries) { 1286 if (entry instanceof KtStringTemplateEntryWithExpression) { 1287 invokeAppend(entry.getExpression()); 1288 } 1289 else { 1290 String text = entry instanceof KtEscapeStringTemplateEntry 1291 ? ((KtEscapeStringTemplateEntry) entry).getUnescapedValue() 1292 : entry.getText(); 1293 v.aconst(text); 1294 genInvokeAppendMethod(v, JAVA_STRING_TYPE); 1295 } 1296 } 1297 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 1298 return Unit.INSTANCE$; 1299 } 1300 }); 1301 } 1302 } 1303 1304 @Override 1305 public StackValue visitBlockExpression(@NotNull KtBlockExpression expression, StackValue receiver) { 1306 return generateBlock(expression, false); 1307 } 1308 1309 @Override 1310 public StackValue visitNamedFunction(@NotNull KtNamedFunction function, StackValue data) { 1311 return visitNamedFunction(function, data, false); 1312 } 1313 1314 public StackValue visitNamedFunction(@NotNull KtNamedFunction function, StackValue data, boolean isStatement) { 1315 assert data == StackValue.none(); 1316 1317 if (KtPsiUtil.isScriptDeclaration(function)) { 1318 return StackValue.none(); 1319 } 1320 1321 StackValue closure = genClosure(function, null); 1322 if (isStatement) { 1323 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); 1324 int index = lookupLocalIndex(descriptor); 1325 closure.put(OBJECT_TYPE, v); 1326 v.store(index, OBJECT_TYPE); 1327 return StackValue.none(); 1328 } 1329 else { 1330 return closure; 1331 } 1332 } 1333 1334 @Override 1335 public StackValue visitFunctionLiteralExpression(@NotNull KtFunctionLiteralExpression expression, StackValue receiver) { 1336 if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) { 1337 return gen(expression.getFunctionLiteral().getBodyExpression()); 1338 } 1339 else { 1340 return genClosure(expression.getFunctionLiteral(), null); 1341 } 1342 } 1343 1344 @NotNull 1345 private StackValue genClosure(KtDeclarationWithBody declaration, @Nullable SamType samType) { 1346 FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration); 1347 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); 1348 1349 return genClosure( 1350 declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, null 1351 ); 1352 } 1353 1354 @NotNull 1355 private StackValue genClosure( 1356 @NotNull KtElement declaration, 1357 @NotNull FunctionDescriptor descriptor, 1358 @NotNull FunctionGenerationStrategy strategy, 1359 @Nullable SamType samType, 1360 @Nullable FunctionDescriptor functionReferenceTarget 1361 ) { 1362 ClassBuilder cv = state.getFactory().newVisitor( 1363 JvmDeclarationOriginKt.OtherOrigin(declaration, descriptor), 1364 asmTypeForAnonymousClass(bindingContext, descriptor), 1365 declaration.getContainingFile() 1366 ); 1367 1368 ClosureCodegen closureCodegen = new ClosureCodegen( 1369 state, declaration, samType, context.intoClosure(descriptor, this, typeMapper), 1370 functionReferenceTarget, strategy, parentCodegen, cv 1371 ); 1372 1373 closureCodegen.generate(); 1374 1375 if (closureCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) { 1376 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1377 propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages()); 1378 } 1379 1380 return closureCodegen.putInstanceOnStack(this); 1381 } 1382 1383 @Override 1384 public StackValue visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, StackValue receiver) { 1385 final ObjectLiteralResult objectLiteralResult = generateObjectLiteral(expression); 1386 final ClassDescriptor classDescriptor = objectLiteralResult.classDescriptor; 1387 final Type type = typeMapper.mapType(classDescriptor); 1388 1389 return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() { 1390 @Override 1391 public Unit invoke(InstructionAdapter v) { 1392 if (objectLiteralResult.wereReifiedMarkers) { 1393 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1394 } 1395 v.anew(type); 1396 v.dup(); 1397 1398 pushClosureOnStack(classDescriptor, true, defaultCallGenerator); 1399 1400 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 1401 assert primaryConstructor != null : "There should be primary constructor for object literal"; 1402 ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, primaryConstructor); 1403 if (superCall != null) { 1404 // For an anonymous object, we should also generate all non-default arguments that it captures for its super call 1405 ConstructorDescriptor superConstructor = superCall.getResultingDescriptor(); 1406 ConstructorDescriptor constructorToCall = SamCodegenUtil.resolveSamAdapter(superConstructor); 1407 List<ValueParameterDescriptor> superValueParameters = superConstructor.getValueParameters(); 1408 int params = superValueParameters.size(); 1409 List<Type> superMappedTypes = typeMapper.mapToCallableMethod(constructorToCall, false).getValueParameterTypes(); 1410 assert superMappedTypes.size() >= params : String 1411 .format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", 1412 superMappedTypes.size(), params, classDescriptor); 1413 1414 List<ResolvedValueArgument> valueArguments = new ArrayList<ResolvedValueArgument>(params); 1415 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(params); 1416 List<Type> mappedTypes = new ArrayList<Type>(params); 1417 for (ValueParameterDescriptor parameter : superValueParameters) { 1418 ResolvedValueArgument argument = superCall.getValueArguments().get(parameter); 1419 if (!(argument instanceof DefaultValueArgument)) { 1420 valueArguments.add(argument); 1421 valueParameters.add(parameter); 1422 mappedTypes.add(superMappedTypes.get(parameter.getIndex())); 1423 } 1424 } 1425 ArgumentGenerator argumentGenerator = 1426 new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes); 1427 1428 argumentGenerator.generate(valueArguments, valueArguments); 1429 } 1430 1431 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 1432 assert constructors.size() == 1 : "Unexpected number of constructors for class: " + classDescriptor + " " + constructors; 1433 ConstructorDescriptor constructorDescriptor = CollectionsKt.single(constructors); 1434 1435 JvmMethodSignature constructor = typeMapper.mapSignature(SamCodegenUtil.resolveSamAdapter(constructorDescriptor)); 1436 v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor(), false); 1437 return Unit.INSTANCE$; 1438 } 1439 }); 1440 } 1441 1442 public void pushClosureOnStack(@NotNull ClassDescriptor classDescriptor, boolean putThis, @NotNull CallGenerator callGenerator) { 1443 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); 1444 if (closure == null) return; 1445 1446 int paramIndex = 0; 1447 1448 if (putThis) { 1449 ClassDescriptor captureThis = closure.getCaptureThis(); 1450 if (captureThis != null) { 1451 StackValue thisOrOuter = generateThisOrOuter(captureThis, false); 1452 assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type; 1453 callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++); 1454 } 1455 } 1456 1457 KotlinType captureReceiver = closure.getCaptureReceiverType(); 1458 if (captureReceiver != null) { 1459 Type asmType = typeMapper.mapType(captureReceiver); 1460 StackValue.Local capturedReceiver = StackValue.local(AsmUtil.getReceiverIndex(context, context.getContextDescriptor()), asmType); 1461 callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); 1462 } 1463 1464 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1465 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1466 if (sharedVarType == null) { 1467 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1468 } 1469 StackValue capturedVar = lookupOuterValue(entry.getValue()); 1470 callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); 1471 } 1472 1473 1474 ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(classDescriptor); 1475 if (superClass != null) { 1476 pushClosureOnStack( 1477 superClass, 1478 putThis && closure.getCaptureThis() == null, 1479 callGenerator 1480 ); 1481 } 1482 } 1483 1484 /* package */ StackValue generateBlock(@NotNull KtBlockExpression expression, boolean isStatement) { 1485 if (expression.getParent() instanceof KtNamedFunction) { 1486 // For functions end of block should be end of function label 1487 return generateBlock(expression.getStatements(), isStatement, null, context.getMethodEndLabel()); 1488 } 1489 return generateBlock(expression.getStatements(), isStatement, null, null); 1490 } 1491 1492 @NotNull 1493 public StackValue lookupOuterValue(EnclosedValueDescriptor d) { 1494 DeclarationDescriptor descriptor = d.getDescriptor(); 1495 for (LocalLookup.LocalLookupCase aCase : LocalLookup.LocalLookupCase.values()) { 1496 if (aCase.isCase(descriptor)) { 1497 return aCase.outerValue(d, this); 1498 } 1499 } 1500 throw new IllegalStateException("Can't get outer value in " + this + " for " + d); 1501 } 1502 1503 private StackValue generateBlock( 1504 List<KtExpression> statements, 1505 boolean isStatement, 1506 Label labelBeforeLastExpression, 1507 @Nullable final Label labelBlockEnd 1508 ) { 1509 final Label blockEnd = labelBlockEnd != null ? labelBlockEnd : new Label(); 1510 1511 final List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1512 1513 StackValue answer = StackValue.none(); 1514 1515 for (Iterator<KtExpression> iterator = statements.iterator(); iterator.hasNext(); ) { 1516 KtExpression possiblyLabeledStatement = iterator.next(); 1517 1518 KtElement statement = KtPsiUtil.safeDeparenthesize(possiblyLabeledStatement); 1519 1520 if (statement instanceof KtNamedDeclaration) { 1521 KtNamedDeclaration declaration = (KtNamedDeclaration) statement; 1522 if (KtPsiUtil.isScriptDeclaration(declaration)) { 1523 continue; 1524 } 1525 } 1526 1527 putDescriptorIntoFrameMap(statement); 1528 1529 boolean isExpression = !iterator.hasNext() && !isStatement; 1530 if (isExpression && labelBeforeLastExpression != null) { 1531 v.mark(labelBeforeLastExpression); 1532 } 1533 1534 StackValue result = isExpression ? gen(possiblyLabeledStatement) : genStatement(possiblyLabeledStatement); 1535 1536 if (!iterator.hasNext()) { 1537 answer = result; 1538 } 1539 else { 1540 result.put(Type.VOID_TYPE, v); 1541 } 1542 1543 addLeaveTaskToRemoveDescriptorFromFrameMap(statement, blockEnd, leaveTasks); 1544 } 1545 1546 return new StackValueWithLeaveTask(answer, new Function1<StackValue, Unit>() { 1547 @Override 1548 public Unit invoke(StackValue value) { 1549 if (labelBlockEnd == null) { 1550 v.mark(blockEnd); 1551 } 1552 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1553 task.fun(value); 1554 } 1555 return Unit.INSTANCE$; 1556 } 1557 }); 1558 } 1559 1560 @NotNull 1561 private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) { 1562 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1563 return sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1564 } 1565 1566 private static boolean isSharedVarType(@NotNull Type type) { 1567 return type.getSort() == Type.OBJECT && type.getInternalName().startsWith(REF_TYPE_PREFIX); 1568 } 1569 1570 1571 private void putDescriptorIntoFrameMap(@NotNull KtElement statement) { 1572 if (statement instanceof KtMultiDeclaration) { 1573 KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement; 1574 for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1575 putLocalVariableIntoFrameMap(entry); 1576 } 1577 } 1578 1579 if (statement instanceof KtVariableDeclaration) { 1580 putLocalVariableIntoFrameMap((KtVariableDeclaration) statement); 1581 } 1582 1583 if (statement instanceof KtNamedFunction) { 1584 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1585 assert descriptor instanceof FunctionDescriptor : "Couldn't find function declaration in binding context " + statement.getText(); 1586 Type type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor); 1587 myFrameMap.enter(descriptor, type); 1588 } 1589 } 1590 1591 private void putLocalVariableIntoFrameMap(@NotNull KtVariableDeclaration statement) { 1592 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1593 assert variableDescriptor != null : "Couldn't find variable declaration in binding context " + statement.getText(); 1594 1595 Type type = getVariableType(variableDescriptor); 1596 int index = myFrameMap.enter(variableDescriptor, type); 1597 1598 if (isSharedVarType(type)) { 1599 markLineNumber(statement, false); 1600 v.anew(type); 1601 v.dup(); 1602 v.invokespecial(type.getInternalName(), "<init>", "()V", false); 1603 v.store(index, OBJECT_TYPE); 1604 } 1605 } 1606 1607 private void addLeaveTaskToRemoveDescriptorFromFrameMap( 1608 @NotNull KtElement statement, 1609 @NotNull Label blockEnd, 1610 @NotNull List<Function<StackValue, Void>> leaveTasks 1611 ) { 1612 if (statement instanceof KtMultiDeclaration) { 1613 KtMultiDeclaration multiDeclaration = (KtMultiDeclaration) statement; 1614 for (KtMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1615 addLeaveTaskToRemoveLocalVariableFromFrameMap(entry, blockEnd, leaveTasks); 1616 } 1617 } 1618 1619 if (statement instanceof KtVariableDeclaration) { 1620 addLeaveTaskToRemoveLocalVariableFromFrameMap((KtVariableDeclaration) statement, blockEnd, leaveTasks); 1621 } 1622 1623 if (statement instanceof KtNamedFunction) { 1624 addLeaveTaskToRemoveNamedFunctionFromFrameMap((KtNamedFunction) statement, blockEnd, leaveTasks); 1625 } 1626 } 1627 1628 private void addLeaveTaskToRemoveLocalVariableFromFrameMap( 1629 @NotNull KtVariableDeclaration statement, 1630 final Label blockEnd, 1631 @NotNull List<Function<StackValue, Void>> leaveTasks 1632 ) { 1633 final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1634 assert variableDescriptor != null; 1635 1636 final Type type = getVariableType(variableDescriptor); 1637 1638 final Label scopeStart = new Label(); 1639 v.mark(scopeStart); 1640 1641 leaveTasks.add(new Function<StackValue, Void>() { 1642 @Override 1643 public Void fun(StackValue answer) { 1644 int index = myFrameMap.leave(variableDescriptor); 1645 1646 if (isSharedVarType(type)) { 1647 v.aconst(null); 1648 v.store(index, OBJECT_TYPE); 1649 } 1650 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, index); 1651 return null; 1652 } 1653 }); 1654 } 1655 1656 private void addLeaveTaskToRemoveNamedFunctionFromFrameMap( 1657 @NotNull final KtNamedFunction statement, 1658 final Label blockEnd, 1659 @NotNull List<Function<StackValue, Void>> leaveTasks 1660 ) { 1661 final FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1662 assert functionDescriptor != null; 1663 1664 final Type type = asmTypeForAnonymousClass(bindingContext, functionDescriptor); 1665 1666 final Label scopeStart = new Label(); 1667 v.mark(scopeStart); 1668 1669 leaveTasks.add(new Function<StackValue, Void>() { 1670 @Override 1671 public Void fun(StackValue answer) { 1672 int index = myFrameMap.leave(functionDescriptor); 1673 1674 assert !functionDescriptor.getName().isSpecial() : "Local variable should be generated only for function with name: " + statement.getText(); 1675 v.visitLocalVariable(functionDescriptor.getName().asString() + "$", type.getDescriptor(), null, scopeStart, blockEnd, index); 1676 return null; 1677 } 1678 }); 1679 } 1680 1681 public boolean isShouldMarkLineNumbers() { 1682 return shouldMarkLineNumbers; 1683 } 1684 1685 public void setShouldMarkLineNumbers(boolean shouldMarkLineNumbers) { 1686 this.shouldMarkLineNumbers = shouldMarkLineNumbers; 1687 } 1688 1689 public void markStartLineNumber(@NotNull KtElement element) { 1690 markLineNumber(element, false); 1691 } 1692 1693 public void markLineNumber(@NotNull KtElement statement, boolean markEndOffset) { 1694 if (!shouldMarkLineNumbers) return; 1695 1696 Integer lineNumber = CodegenUtil.getLineNumberForElement(statement, markEndOffset); 1697 if (lineNumber == null || lineNumber == myLastLineNumber) { 1698 return; 1699 } 1700 myLastLineNumber = lineNumber; 1701 1702 Label label = new Label(); 1703 v.visitLabel(label); 1704 v.visitLineNumber(lineNumber, label); 1705 } 1706 1707 //we should generate additional linenumber info after inline call only if it used as argument 1708 public void markLineNumberAfterInlineIfNeeded() { 1709 if (!shouldMarkLineNumbers) { 1710 //if it used as general argument 1711 if (myLastLineNumber > -1) { 1712 Label label = new Label(); 1713 v.visitLabel(label); 1714 v.visitLineNumber(myLastLineNumber, label); 1715 } 1716 } else { 1717 //if it used as argument of infix call (in this case lineNumber for simple inlineCall also would be reset) 1718 myLastLineNumber = -1; 1719 } 1720 } 1721 1722 private void doFinallyOnReturn(@NotNull Label afterReturnLabel) { 1723 if(!blockStackElements.isEmpty()) { 1724 BlockStackElement stackElement = blockStackElements.peek(); 1725 if (stackElement instanceof FinallyBlockStackElement) { 1726 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1727 genFinallyBlockOrGoto(finallyBlockStackElement, null, afterReturnLabel); 1728 } 1729 else if (stackElement instanceof LoopBlockStackElement) { 1730 1731 } else { 1732 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1733 } 1734 1735 blockStackElements.pop(); 1736 doFinallyOnReturn(afterReturnLabel); 1737 blockStackElements.push(stackElement); 1738 } 1739 } 1740 1741 public boolean hasFinallyBlocks() { 1742 for (BlockStackElement element : blockStackElements) { 1743 if (element instanceof FinallyBlockStackElement) { 1744 return true; 1745 } 1746 } 1747 return false; 1748 } 1749 1750 private void genFinallyBlockOrGoto( 1751 @Nullable FinallyBlockStackElement finallyBlockStackElement, 1752 @Nullable Label tryCatchBlockEnd, 1753 @Nullable Label afterJumpLabel 1754 ) { 1755 if (finallyBlockStackElement != null) { 1756 finallyDepth++; 1757 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; 1758 1759 BlockStackElement topOfStack = blockStackElements.pop(); 1760 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block"; 1761 1762 KtTryExpression jetTryExpression = finallyBlockStackElement.expression; 1763 Label finallyStart = new Label(); 1764 v.mark(finallyStart); 1765 finallyBlockStackElement.addGapLabel(finallyStart); 1766 if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { 1767 InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, true); 1768 } 1769 //noinspection ConstantConditions 1770 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1771 1772 if (InlineCodegenUtil.isFinallyMarkerRequired(context)) { 1773 InlineCodegenUtil.generateFinallyMarker(v, finallyDepth, false); 1774 } 1775 } 1776 1777 if (tryCatchBlockEnd != null) { 1778 v.goTo(tryCatchBlockEnd); 1779 } 1780 1781 if (finallyBlockStackElement != null) { 1782 finallyDepth--; 1783 Label finallyEnd = afterJumpLabel != null ? afterJumpLabel : new Label(); 1784 if (afterJumpLabel == null) { 1785 v.mark(finallyEnd); 1786 } 1787 finallyBlockStackElement.addGapLabel(finallyEnd); 1788 1789 blockStackElements.push(finallyBlockStackElement); 1790 } 1791 } 1792 1793 @Override 1794 public StackValue visitReturnExpression(@NotNull final KtReturnExpression expression, StackValue receiver) { 1795 return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() { 1796 @Override 1797 public Unit invoke(InstructionAdapter adapter) { 1798 KtExpression returnedExpression = expression.getReturnedExpression(); 1799 CallableMemberDescriptor descriptor = getContext().getContextDescriptor(); 1800 NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression); 1801 boolean isNonLocalReturn = nonLocalReturn != null; 1802 if (isNonLocalReturn && !state.isInlineEnabled()) { 1803 state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression)); 1804 genThrow(v, "java/lang/UnsupportedOperationException", 1805 "Non-local returns are not allowed with inlining disabled"); 1806 return Unit.INSTANCE; 1807 } 1808 1809 Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType; 1810 if (returnedExpression != null) { 1811 gen(returnedExpression, returnType); 1812 } 1813 1814 Label afterReturnLabel = new Label(); 1815 generateFinallyBlocksIfNeeded(returnType, afterReturnLabel); 1816 1817 if (isNonLocalReturn) { 1818 InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName); 1819 } 1820 v.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 1821 v.mark(afterReturnLabel); 1822 return Unit.INSTANCE; 1823 } 1824 }); 1825 } 1826 1827 public void generateFinallyBlocksIfNeeded(Type returnType, @NotNull Label afterReturnLabel) { 1828 if (hasFinallyBlocks()) { 1829 if (!Type.VOID_TYPE.equals(returnType)) { 1830 int returnValIndex = myFrameMap.enterTemp(returnType); 1831 StackValue.Local localForReturnValue = StackValue.local(returnValIndex, returnType); 1832 localForReturnValue.store(StackValue.onStack(returnType), v); 1833 doFinallyOnReturn(afterReturnLabel); 1834 localForReturnValue.put(returnType, v); 1835 myFrameMap.leaveTemp(returnType); 1836 } 1837 else { 1838 doFinallyOnReturn(afterReturnLabel); 1839 } 1840 } 1841 } 1842 1843 @Nullable 1844 private NonLocalReturnInfo getNonLocalReturnInfo(@NotNull CallableMemberDescriptor descriptor, @NotNull KtReturnExpression expression) { 1845 //call inside lambda 1846 if (isFunctionLiteral(descriptor) || isFunctionExpression(descriptor)) { 1847 if (expression.getLabelName() == null) { 1848 if (isFunctionLiteral(descriptor)) { 1849 //non labeled return couldn't be local in lambda 1850 FunctionDescriptor containingFunction = 1851 BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst(); 1852 //FIRST_FUN_LABEL to prevent clashing with existing labels 1853 return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL); 1854 } else { 1855 //local 1856 return null; 1857 } 1858 } 1859 1860 PsiElement element = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); 1861 if (element != DescriptorToSourceUtils.getSourceFromDescriptor(context.getContextDescriptor())) { 1862 DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element); 1863 assert element != null : "Expression should be not null " + expression.getText(); 1864 assert elementDescriptor != null : "Descriptor should be not null: " + element.getText(); 1865 return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName()); 1866 } 1867 } 1868 return null; 1869 } 1870 1871 public void returnExpression(KtExpression expr) { 1872 boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction; 1873 1874 // If generating body for named block-bodied function, generate it as sequence of statements 1875 gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType); 1876 1877 // If it does not end with return we should return something 1878 // because if we don't there can be VerifyError (specific cases with Nothing-typed expressions) 1879 if (!endsWithReturn(expr)) { 1880 markLineNumber(expr, true); 1881 1882 if (isLambdaVoidBody(expr, returnType)) { 1883 markLineNumber((KtFunctionLiteral) expr.getParent(), true); 1884 } 1885 1886 if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) { 1887 StackValue.none().put(returnType, v); 1888 } 1889 1890 v.areturn(returnType); 1891 } 1892 } 1893 1894 private static boolean endsWithReturn(KtElement bodyExpression) { 1895 if (bodyExpression instanceof KtBlockExpression) { 1896 List<KtExpression> statements = ((KtBlockExpression) bodyExpression).getStatements(); 1897 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof KtReturnExpression; 1898 } 1899 1900 return bodyExpression instanceof KtReturnExpression; 1901 } 1902 1903 private static boolean isLambdaVoidBody(KtElement bodyExpression, Type returnType) { 1904 if (bodyExpression instanceof KtBlockExpression) { 1905 PsiElement parent = bodyExpression.getParent(); 1906 if (parent instanceof KtFunctionLiteral) { 1907 return Type.VOID_TYPE.equals(returnType); 1908 } 1909 } 1910 1911 return false; 1912 } 1913 1914 @Override 1915 public StackValue visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, @NotNull StackValue receiver) { 1916 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext); 1917 1918 DeclarationDescriptor descriptor; 1919 if (resolvedCall == null) { 1920 descriptor = bindingContext.get(REFERENCE_TARGET, expression); 1921 } 1922 else { 1923 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1924 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 1925 resolvedCall = call.getVariableCall(); 1926 } 1927 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1928 descriptor = resolvedCall.getResultingDescriptor(); 1929 if (descriptor instanceof FakeCallableDescriptorForObject) { 1930 descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); 1931 } 1932 } 1933 1934 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 1935 descriptor = descriptor.getOriginal(); 1936 1937 boolean isSyntheticField = descriptor instanceof SyntheticFieldDescriptor; 1938 if (isSyntheticField) { 1939 descriptor = ((SyntheticFieldDescriptor) descriptor).getPropertyDescriptor(); 1940 } 1941 if (descriptor instanceof CallableMemberDescriptor) { 1942 CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor); 1943 1944 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1945 if (intrinsic instanceof IntrinsicPropertyGetter) { 1946 //TODO: intrinsic properties (see intermediateValueForProperty) 1947 Type returnType = typeMapper.mapType(memberDescriptor); 1948 StackValue intrinsicResult = ((IntrinsicPropertyGetter) intrinsic).generate(resolvedCall, this, returnType, receiver); 1949 if (intrinsicResult != null) return intrinsicResult; 1950 } 1951 } 1952 1953 if (descriptor instanceof PropertyDescriptor) { 1954 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1955 1956 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject()); 1957 if (!codegenExtensions.isEmpty() && resolvedCall != null) { 1958 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 1959 KotlinType returnType = propertyDescriptor.getReturnType(); 1960 for (ExpressionCodegenExtension extension : codegenExtensions) { 1961 if (returnType != null) { 1962 StackValue value = extension.applyProperty(receiver, resolvedCall, context); 1963 if (value != null) return value; 1964 } 1965 } 1966 } 1967 1968 boolean directToField = isSyntheticField && contextKind() != OwnerKind.DEFAULT_IMPLS; 1969 ClassDescriptor superCallTarget = resolvedCall == null ? null : getSuperCallTarget(resolvedCall.getCall()); 1970 1971 if (directToField) { 1972 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1973 } 1974 1975 return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver); 1976 } 1977 1978 if (descriptor instanceof ClassDescriptor) { 1979 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 1980 if (isObject(classDescriptor)) { 1981 return StackValue.singleton(classDescriptor, typeMapper); 1982 } 1983 if (isEnumEntry(classDescriptor)) { 1984 return StackValue.enumEntry(classDescriptor, typeMapper); 1985 } 1986 ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor(); 1987 if (companionObjectDescriptor != null) { 1988 return StackValue.singleton(companionObjectDescriptor, typeMapper); 1989 } 1990 return StackValue.none(); 1991 } 1992 1993 StackValue localOrCaptured = findLocalOrCapturedValue(descriptor); 1994 if (localOrCaptured != null) { 1995 return localOrCaptured; 1996 } 1997 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1998 } 1999 2000 @Nullable 2001 private ClassDescriptor getSuperCallTarget(@NotNull Call call) { 2002 KtSuperExpression superExpression = CallResolverUtilKt.getSuperCallExpression(call); 2003 return superExpression == null ? null : getSuperCallLabelTarget(context, superExpression); 2004 } 2005 2006 @Nullable 2007 public StackValue findLocalOrCapturedValue(@NotNull DeclarationDescriptor descriptor) { 2008 int index = lookupLocalIndex(descriptor); 2009 if (index >= 0) { 2010 return stackValueForLocal(descriptor, index); 2011 } 2012 2013 return findCapturedValue(descriptor); 2014 } 2015 2016 @Nullable 2017 public StackValue findCapturedValue(@NotNull DeclarationDescriptor descriptor) { 2018 if (context instanceof ConstructorContext) { 2019 return lookupCapturedValueInConstructorParameters(descriptor); 2020 } 2021 2022 return context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 2023 } 2024 2025 @Nullable 2026 private StackValue lookupCapturedValueInConstructorParameters(@NotNull DeclarationDescriptor descriptor) { 2027 StackValue parentResult = context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 2028 if (context.closure == null || parentResult == null) return parentResult; 2029 2030 int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor); 2031 // when captured parameter is singleton 2032 // see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A) 2033 if (parameterOffsetInConstructor == -1) return parentResult; 2034 2035 assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar 2036 : "Part of closure should be either Field or FieldForSharedVar"; 2037 2038 if (parentResult instanceof StackValue.FieldForSharedVar) { 2039 return StackValue.shared(parameterOffsetInConstructor, parentResult.type); 2040 } 2041 2042 return StackValue.local(parameterOffsetInConstructor, parentResult.type); 2043 } 2044 2045 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 2046 if (descriptor instanceof VariableDescriptor) { 2047 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 2048 KotlinType outType = ((VariableDescriptor) descriptor).getType(); 2049 if (sharedVarType != null) { 2050 return StackValue.shared(index, asmType(outType)); 2051 } 2052 else { 2053 return StackValue.local(index, asmType(outType)); 2054 } 2055 } 2056 else { 2057 return StackValue.local(index, OBJECT_TYPE); 2058 } 2059 } 2060 2061 @Override 2062 public boolean lookupLocal(DeclarationDescriptor descriptor) { 2063 return lookupLocalIndex(descriptor) != -1; 2064 } 2065 2066 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 2067 return myFrameMap.getIndex(descriptor); 2068 } 2069 2070 @Nullable 2071 private static KotlinType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 2072 PropertyGetterDescriptor getter = descriptor.getGetter(); 2073 if (getter != null) { 2074 Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter); 2075 return call != null ? ((ReceiverValue) call.getExplicitReceiver()).getType() : null; 2076 } 2077 return null; 2078 } 2079 2080 @NotNull 2081 public StackValue.Property intermediateValueForProperty( 2082 @NotNull PropertyDescriptor propertyDescriptor, 2083 boolean forceField, 2084 @Nullable ClassDescriptor superCallTarget, 2085 @NotNull StackValue receiver 2086 ) { 2087 return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver); 2088 } 2089 2090 private CodegenContext getBackingFieldContext( 2091 @NotNull FieldAccessorKind accessorKind, 2092 @NotNull DeclarationDescriptor containingDeclaration 2093 ) { 2094 switch (accessorKind) { 2095 case NORMAL: return context.getParentContext(); 2096 // For companion object property, backing field lives in object containing class 2097 // Otherwise, it lives in its containing declaration 2098 case IN_CLASS_COMPANION: return context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 2099 case FIELD_FROM_LOCAL: return context.findParentContextWithDescriptor(containingDeclaration); 2100 default: throw new IllegalStateException(); 2101 } 2102 } 2103 2104 public StackValue.Property intermediateValueForProperty( 2105 @NotNull PropertyDescriptor propertyDescriptor, 2106 boolean forceField, 2107 boolean syntheticBackingField, 2108 @Nullable ClassDescriptor superCallTarget, 2109 boolean skipAccessorsForPrivateFieldInOuterClass, 2110 StackValue receiver 2111 ) { 2112 if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) { 2113 return intermediateValueForSyntheticExtensionProperty((SyntheticJavaPropertyDescriptor) propertyDescriptor, receiver); 2114 } 2115 2116 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 2117 2118 FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL; 2119 boolean isBackingFieldInClassCompanion = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 2120 if (isBackingFieldInClassCompanion && forceField) { 2121 fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION; 2122 } 2123 else if (syntheticBackingField && context.getParentContext().getContextDescriptor() != containingDeclaration) { 2124 fieldAccessorKind = FieldAccessorKind.FIELD_FROM_LOCAL; 2125 } 2126 boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) || 2127 AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor); 2128 boolean isSuper = superCallTarget != null; 2129 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 2130 2131 KotlinType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext); 2132 boolean isDelegatedProperty = delegateType != null; 2133 2134 CallableMethod callableGetter = null; 2135 CallableMethod callableSetter = null; 2136 2137 CodegenContext backingFieldContext = getBackingFieldContext(fieldAccessorKind, containingDeclaration); 2138 DeclarationDescriptor ownerDescriptor = containingDeclaration; 2139 boolean skipPropertyAccessors; 2140 2141 PropertyDescriptor originalPropertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 2142 if (fieldAccessorKind != FieldAccessorKind.NORMAL) { 2143 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 2144 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || skipAccessorsForPrivateFieldInOuterClass; 2145 if (!skipPropertyAccessors) { 2146 //noinspection ConstantConditions 2147 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor( 2148 propertyDescriptor, fieldAccessorKind, delegateType, superCallTarget 2149 ); 2150 assert propertyDescriptor instanceof AccessorForPropertyBackingField : 2151 "Unexpected accessor descriptor: " + propertyDescriptor; 2152 ownerDescriptor = propertyDescriptor; 2153 } 2154 } 2155 else { 2156 if (!isBackingFieldInClassCompanion) { 2157 ownerDescriptor = propertyDescriptor; 2158 } 2159 skipPropertyAccessors = forceField; 2160 } 2161 2162 if (!skipPropertyAccessors) { 2163 if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) { 2164 if (isSuper && !isJvmInterface(containingDeclaration)) { 2165 CodegenContext c = context.findParentContextWithDescriptor(superCallTarget); 2166 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 2167 if (c != context.getParentContext()) { 2168 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor, superCallTarget); 2169 } 2170 } 2171 2172 propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superCallTarget); 2173 2174 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 2175 if (getter != null && !hasJvmFieldAnnotation(propertyDescriptor)) { 2176 callableGetter = typeMapper.mapToCallableMethod(getter, isSuper); 2177 } 2178 } 2179 2180 if (propertyDescriptor.isVar()) { 2181 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 2182 if (setter != null && 2183 !couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context) && 2184 !hasJvmFieldAnnotation(propertyDescriptor)) { 2185 callableSetter = typeMapper.mapToCallableMethod(setter, isSuper); 2186 } 2187 } 2188 } 2189 2190 if (!isStaticBackingField) { 2191 propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 2192 } 2193 2194 Type backingFieldOwner = typeMapper.mapOwner(ownerDescriptor); 2195 2196 String fieldName; 2197 if (isExtensionProperty && !isDelegatedProperty) { 2198 fieldName = null; 2199 } 2200 else if (originalPropertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 2201 assert backingFieldContext instanceof FieldOwnerContext 2202 : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext"; 2203 fieldName = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 2204 } 2205 else { 2206 fieldName = JetTypeMapper.mapDefaultFieldName(propertyDescriptor, isDelegatedProperty); 2207 } 2208 2209 return StackValue.property(propertyDescriptor, backingFieldOwner, 2210 typeMapper.mapType( 2211 isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 2212 isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver); 2213 } 2214 2215 @NotNull 2216 private StackValue.Property intermediateValueForSyntheticExtensionProperty( 2217 @NotNull SyntheticJavaPropertyDescriptor propertyDescriptor, 2218 StackValue receiver 2219 ) { 2220 Type type = typeMapper.mapType(propertyDescriptor.getOriginal().getType()); 2221 CallableMethod callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetMethod(), false); 2222 FunctionDescriptor setMethod = propertyDescriptor.getSetMethod(); 2223 CallableMethod callableSetter = setMethod != null ? typeMapper.mapToCallableMethod(setMethod, false) : null; 2224 return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, state, receiver); 2225 } 2226 2227 @Override 2228 public StackValue visitCallExpression(@NotNull KtCallExpression expression, StackValue receiver) { 2229 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 2230 FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); 2231 2232 if (descriptor instanceof ConstructorDescriptor) { 2233 return generateNewCall(expression, resolvedCall); 2234 } 2235 2236 if (descriptor.getOriginal() instanceof SamConstructorDescriptor) { 2237 KtExpression argumentExpression = bindingContext.get(SAM_CONSTRUCTOR_TO_ARGUMENT, expression); 2238 assert argumentExpression != null : "Argument expression is not saved for a SAM constructor: " + descriptor; 2239 return genSamInterfaceValue(argumentExpression, this); 2240 } 2241 2242 return invokeFunction(resolvedCall, receiver); 2243 } 2244 2245 @Nullable 2246 private StackValue genSamInterfaceValue( 2247 @NotNull KtExpression probablyParenthesizedExpression, 2248 @NotNull final KtVisitor<StackValue, StackValue> visitor 2249 ) { 2250 final KtExpression expression = KtPsiUtil.deparenthesize(probablyParenthesizedExpression); 2251 final SamType samType = bindingContext.get(SAM_VALUE, probablyParenthesizedExpression); 2252 if (samType == null || expression == null) return null; 2253 2254 if (expression instanceof KtFunctionLiteralExpression) { 2255 return genClosure(((KtFunctionLiteralExpression) expression).getFunctionLiteral(), samType); 2256 } 2257 2258 if (expression instanceof KtNamedFunction) { 2259 return genClosure((KtNamedFunction) expression, samType); 2260 } 2261 2262 final Type asmType = 2263 state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingKtFile(), getParentCodegen()); 2264 2265 return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() { 2266 @Override 2267 public Unit invoke(InstructionAdapter v) { 2268 v.anew(asmType); 2269 v.dup(); 2270 2271 Type functionType = typeMapper.mapType(samType.getKotlinFunctionType()); 2272 expression.accept(visitor, StackValue.none()).put(functionType, v); 2273 2274 Label ifNonNull = new Label(); 2275 Label afterAll = new Label(); 2276 2277 v.dup(); 2278 v.ifnonnull(ifNonNull); 2279 2280 // if null: pop function value and wrapper objects, put null 2281 v.pop(); 2282 v.pop2(); 2283 v.aconst(null); 2284 v.goTo(afterAll); 2285 2286 v.mark(ifNonNull); 2287 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false); 2288 2289 v.mark(afterAll); 2290 return null; 2291 } 2292 }); 2293 } 2294 2295 @NotNull 2296 protected FunctionDescriptor accessibleFunctionDescriptor(@NotNull ResolvedCall<?> resolvedCall) { 2297 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2298 FunctionDescriptor originalIfSamAdapter = SamCodegenUtil.getOriginalIfSamAdapter(descriptor); 2299 if (originalIfSamAdapter != null) { 2300 descriptor = originalIfSamAdapter; 2301 } 2302 // $default method is not private, so you need no accessor to call it 2303 return usesDefaultArguments(resolvedCall) 2304 ? descriptor 2305 : context.accessibleDescriptor(descriptor, getSuperCallTarget(resolvedCall.getCall())); 2306 } 2307 2308 private static boolean usesDefaultArguments(@NotNull ResolvedCall<?> resolvedCall) { 2309 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2310 if (valueArguments == null) return false; 2311 2312 for (ResolvedValueArgument argument : valueArguments) { 2313 if (argument instanceof DefaultValueArgument) return true; 2314 } 2315 2316 return false; 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 boolean superCall = superCallTarget != null; 2329 2330 if (superCall && !isJvmInterface(fd.getContainingDeclaration())) { 2331 CodegenContext c = context.findParentContextWithDescriptor(superCallTarget); 2332 assert c != null : "Couldn't find a context for a super-call: " + fd; 2333 if (c != context.getParentContext()) { 2334 fd = (FunctionDescriptor) c.getAccessor(fd, superCallTarget); 2335 } 2336 } 2337 2338 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject()); 2339 if (!codegenExtensions.isEmpty()) { 2340 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 2341 for (ExpressionCodegenExtension extension : codegenExtensions) { 2342 StackValue stackValue = extension.applyFunction(receiver, resolvedCall, context); 2343 if (stackValue != null) return stackValue; 2344 } 2345 } 2346 2347 Callable callable = resolveToCallable(fd, superCall, resolvedCall); 2348 2349 return callable.invokeMethodWithArguments(resolvedCall, receiver, this); 2350 } 2351 2352 @Nullable 2353 // Find the first parent of the current context which corresponds to a subclass of a given class 2354 public static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2355 CodegenContext c = context; 2356 while (c != null) { 2357 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2358 return c; 2359 } 2360 c = c.getParentContext(); 2361 } 2362 return null; 2363 } 2364 2365 @NotNull 2366 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull ResolvedCall resolvedCall) { 2367 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2368 if (intrinsic != null) { 2369 return intrinsic.toCallable(fd, superCall, resolvedCall, this); 2370 } 2371 2372 return resolveToCallableMethod(fd, superCall); 2373 } 2374 2375 @NotNull 2376 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall) { 2377 return typeMapper.mapToCallableMethod(SamCodegenUtil.resolveSamAdapter(fd), superCall); 2378 } 2379 2380 public void invokeMethodWithArguments( 2381 @NotNull Callable callableMethod, 2382 @NotNull ResolvedCall<?> resolvedCall, 2383 @NotNull StackValue receiver 2384 ) { 2385 CallGenerator callGenerator = getOrCreateCallGenerator(resolvedCall); 2386 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 2387 2388 assert callGenerator == defaultCallGenerator || !tailRecursionCodegen.isTailRecursion(resolvedCall) : 2389 "Tail recursive method can't be inlined: " + descriptor; 2390 2391 ArgumentGenerator argumentGenerator = new CallBasedArgumentGenerator(this, callGenerator, descriptor.getValueParameters(), 2392 callableMethod.getValueParameterTypes()); 2393 2394 invokeMethodWithArguments(callableMethod, resolvedCall, receiver, callGenerator, argumentGenerator); 2395 } 2396 2397 public void invokeMethodWithArguments( 2398 @NotNull Callable callableMethod, 2399 @NotNull ResolvedCall<?> resolvedCall, 2400 @NotNull StackValue receiver, 2401 @NotNull CallGenerator callGenerator, 2402 @NotNull ArgumentGenerator argumentGenerator 2403 ) { 2404 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2405 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2406 receiver.put(receiver.type, v); 2407 callableMethod.afterReceiverGeneration(v); 2408 } 2409 2410 callGenerator.putHiddenParams(); 2411 2412 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2413 assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); 2414 2415 DefaultCallMask masks = 2416 argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values())); 2417 2418 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { 2419 tailRecursionCodegen.generateTailRecursion(resolvedCall); 2420 return; 2421 } 2422 2423 boolean defaultMaskWasGenerated = masks.generateOnStackIfNeeded(callGenerator); 2424 2425 // Extra constructor marker argument 2426 if (callableMethod instanceof CallableMethod) { 2427 List<JvmMethodParameterSignature> callableParameters = ((CallableMethod) callableMethod).getValueParameters(); 2428 for (JvmMethodParameterSignature parameter: callableParameters) { 2429 if (parameter.getKind() == JvmMethodParameterKind.CONSTRUCTOR_MARKER) { 2430 callGenerator.putValueIfNeeded(null, parameter.getAsmType(), StackValue.constant(null, parameter.getAsmType())); 2431 } 2432 } 2433 } 2434 2435 callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this); 2436 } 2437 2438 @NotNull 2439 protected CallGenerator getOrCreateCallGenerator( 2440 @NotNull CallableDescriptor descriptor, 2441 @Nullable KtElement callElement, 2442 @Nullable ReifiedTypeParameterMappings reifiedTypeParameterMappings 2443 ) { 2444 if (callElement == null) return defaultCallGenerator; 2445 2446 // We should inline callable containing reified type parameters even if inline is disabled 2447 // because they may contain something to reify and straight call will probably fail at runtime 2448 boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) && 2449 InlineUtil.isInline(descriptor); 2450 2451 if (!isInline) return defaultCallGenerator; 2452 2453 SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal()); 2454 return new InlineCodegen(this, state, original, callElement, reifiedTypeParameterMappings); 2455 } 2456 2457 @NotNull 2458 public CallGenerator getOrCreateCallGenerator(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) { 2459 return getOrCreateCallGenerator(descriptor, function, null); 2460 } 2461 2462 @NotNull 2463 private CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) { 2464 Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments(); 2465 ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings(); 2466 for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) { 2467 TypeParameterDescriptor key = entry.getKey(); 2468 if (!key.isReified()) continue; 2469 2470 KotlinType type = entry.getValue(); 2471 TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type); 2472 if (parameterDescriptor == null) { 2473 // type is not generic 2474 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE); 2475 Type asmType = typeMapper.mapTypeParameter(type, signatureWriter); 2476 2477 mappings.addParameterMappingToType( 2478 key.getName().getIdentifier(), 2479 type, 2480 asmType, 2481 signatureWriter.toString() 2482 ); 2483 } 2484 else { 2485 mappings.addParameterMappingToNewParameter( 2486 key.getName().getIdentifier(), 2487 parameterDescriptor.getName().getIdentifier() 2488 ); 2489 } 2490 } 2491 return getOrCreateCallGenerator( 2492 resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings 2493 ); 2494 } 2495 2496 @NotNull 2497 public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) { 2498 if (receiverValue instanceof ImplicitClassReceiver) { 2499 ClassDescriptor receiverDescriptor = ((ImplicitClassReceiver) receiverValue).getDeclarationDescriptor(); 2500 if (DescriptorUtils.isCompanionObject(receiverDescriptor)) { 2501 CallableMemberDescriptor contextDescriptor = context.getContextDescriptor(); 2502 if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) { 2503 return StackValue.LOCAL_0; 2504 } 2505 else { 2506 return StackValue.singleton(receiverDescriptor, typeMapper); 2507 } 2508 } 2509 else if (receiverDescriptor instanceof ScriptDescriptor) { 2510 return generateScriptReceiver 2511 ((ScriptDescriptor) receiverDescriptor); 2512 } 2513 else { 2514 return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, 2515 receiverValue instanceof CastImplicitClassReceiver || isEnumEntry(receiverDescriptor)); 2516 } 2517 } 2518 else if (receiverValue instanceof ExtensionReceiver) { 2519 return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor()); 2520 } 2521 else if (receiverValue instanceof ExpressionReceiver) { 2522 return gen(((ExpressionReceiver) receiverValue).getExpression()); 2523 } 2524 else { 2525 throw new UnsupportedOperationException("Unsupported receiver value: " + receiverValue); 2526 } 2527 } 2528 2529 @NotNull 2530 private StackValue generateReceiver(@NotNull CallableDescriptor descriptor) { 2531 return context.generateReceiver(descriptor, state, false); 2532 } 2533 2534 @NotNull 2535 private StackValue generateScriptReceiver(@NotNull ScriptDescriptor receiver) { 2536 CodegenContext cur = context; 2537 StackValue result = StackValue.LOCAL_0; 2538 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2539 while (cur != null) { 2540 if (!inStartConstructorContext) { 2541 cur = getNotNullParentContextForMethod(cur); 2542 } 2543 2544 if (cur instanceof ScriptContext) { 2545 ScriptContext scriptContext = (ScriptContext) cur; 2546 2547 if (scriptContext.getScriptDescriptor() == receiver) { 2548 //TODO lazy 2549 return result; 2550 } 2551 Type currentScriptType = typeMapper.mapType(scriptContext.getScriptDescriptor()); 2552 Type classType = typeMapper.mapType(receiver); 2553 String fieldName = scriptContext.getScriptFieldName(receiver); 2554 return StackValue.field(classType, currentScriptType, fieldName, false, result, receiver); 2555 } 2556 2557 result = cur.getOuterExpression(result, false); 2558 2559 if (inStartConstructorContext) { 2560 cur = getNotNullParentContextForMethod(cur); 2561 inStartConstructorContext = false; 2562 } 2563 2564 cur = cur.getParentContext(); 2565 } 2566 2567 throw new UnsupportedOperationException(); 2568 } 2569 2570 @NotNull 2571 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2572 return generateThisOrOuter(calleeContainingClass, isSuper, false); 2573 } 2574 2575 @NotNull 2576 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) { 2577 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2578 if (isSingleton) { 2579 if (calleeContainingClass.equals(context.getThisDescriptor()) && 2580 !AnnotationUtilKt.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) { 2581 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2582 } 2583 else if (isEnumEntry(calleeContainingClass)) { 2584 return StackValue.enumEntry(calleeContainingClass, typeMapper); 2585 } 2586 else { 2587 return StackValue.singleton(calleeContainingClass, typeMapper); 2588 } 2589 } 2590 2591 CodegenContext cur = context; 2592 Type type = asmType(calleeContainingClass.getDefaultType()); 2593 StackValue result = StackValue.local(0, type); 2594 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2595 while (cur != null) { 2596 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2597 2598 if (!isSuper && thisDescriptor == calleeContainingClass) { 2599 return result; 2600 } 2601 2602 if (!forceOuter && isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2603 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2604 } 2605 2606 forceOuter = false; 2607 2608 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2609 if (inStartConstructorContext) { 2610 result = cur.getOuterExpression(result, false); 2611 cur = getNotNullParentContextForMethod(cur); 2612 inStartConstructorContext = false; 2613 } 2614 else { 2615 cur = getNotNullParentContextForMethod(cur); 2616 result = cur.getOuterExpression(result, false); 2617 } 2618 2619 cur = cur.getParentContext(); 2620 } 2621 2622 throw new UnsupportedOperationException(); 2623 } 2624 2625 @NotNull 2626 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) { 2627 if (cur instanceof MethodContext) { 2628 cur = cur.getParentContext(); 2629 } 2630 assert cur != null; 2631 return cur; 2632 } 2633 2634 2635 public void genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull KotlinType outType) { 2636 Type type = asmType(outType); 2637 assert type.getSort() == Type.ARRAY; 2638 Type elementType = correctElementType(type); 2639 List<ValueArgument> arguments = valueArgument.getArguments(); 2640 int size = arguments.size(); 2641 2642 boolean hasSpread = false; 2643 for (int i = 0; i != size; ++i) { 2644 if (arguments.get(i).getSpreadElement() != null) { 2645 hasSpread = true; 2646 break; 2647 } 2648 } 2649 2650 if (hasSpread) { 2651 boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); 2652 if (size == 1) { 2653 // Arrays.copyOf(array, newLength) 2654 ValueArgument argument = arguments.get(0); 2655 Type arrayType = arrayOfReferences ? Type.getType("[Ljava/lang/Object;") 2656 : Type.getType("[" + elementType.getDescriptor()); 2657 gen(argument.getArgumentExpression(), type); 2658 v.dup(); 2659 v.arraylength(); 2660 v.invokestatic("java/util/Arrays", "copyOf", Type.getMethodDescriptor(arrayType, arrayType, Type.INT_TYPE), false); 2661 if (arrayOfReferences) { 2662 v.checkcast(type); 2663 } 2664 } 2665 else { 2666 String owner; 2667 String addDescriptor; 2668 String toArrayDescriptor; 2669 if (arrayOfReferences) { 2670 owner = "kotlin/jvm/internal/SpreadBuilder"; 2671 addDescriptor = "(Ljava/lang/Object;)V"; 2672 toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;"; 2673 } 2674 else { 2675 String spreadBuilderClassName = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(elementType).getTypeName().getIdentifier() + "SpreadBuilder"; 2676 owner = "kotlin/jvm/internal/" + spreadBuilderClassName; 2677 addDescriptor = "(" + elementType.getDescriptor() + ")V"; 2678 toArrayDescriptor = "()" + type.getDescriptor(); 2679 } 2680 v.anew(Type.getObjectType(owner)); 2681 v.dup(); 2682 v.iconst(size); 2683 v.invokespecial(owner, "<init>", "(I)V", false); 2684 for (int i = 0; i != size; ++i) { 2685 v.dup(); 2686 ValueArgument argument = arguments.get(i); 2687 if (argument.getSpreadElement() != null) { 2688 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2689 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false); 2690 } 2691 else { 2692 gen(argument.getArgumentExpression(), elementType); 2693 v.invokevirtual(owner, "add", addDescriptor, false); 2694 } 2695 } 2696 if (arrayOfReferences) { 2697 v.dup(); 2698 v.invokevirtual(owner, "size", "()I", false); 2699 newArrayInstruction(outType); 2700 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2701 v.checkcast(type); 2702 } 2703 else { 2704 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2705 } 2706 } 2707 } 2708 else { 2709 v.iconst(arguments.size()); 2710 newArrayInstruction(outType); 2711 for (int i = 0; i != size; ++i) { 2712 v.dup(); 2713 StackValue rightSide = gen(arguments.get(i).getArgumentExpression()); 2714 StackValue.arrayElement(elementType, StackValue.onStack(type), StackValue.constant(i, Type.INT_TYPE)).store(rightSide, v); 2715 } 2716 } 2717 } 2718 2719 public int indexOfLocal(KtReferenceExpression lhs) { 2720 DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs); 2721 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2722 return -1; 2723 } 2724 return lookupLocalIndex(declarationDescriptor); 2725 } 2726 2727 @Override 2728 public StackValue visitClassLiteralExpression(@NotNull KtClassLiteralExpression expression, StackValue data) { 2729 KotlinType type = bindingContext.getType(expression); 2730 assert type != null; 2731 2732 assert state.getReflectionTypes().getKClass().getTypeConstructor().equals(type.getConstructor()) 2733 : "::class expression should be type checked to a KClass: " + type; 2734 2735 return generateClassLiteralReference(typeMapper, CollectionsKt.single(type.getArguments()).getType(), this); 2736 } 2737 2738 @Override 2739 public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) { 2740 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext); 2741 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2742 if (functionDescriptor != null) { 2743 FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall); 2744 return genClosure(expression, functionDescriptor, strategy, null, (FunctionDescriptor) resolvedCall.getResultingDescriptor()); 2745 } 2746 2747 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression); 2748 if (variableDescriptor != null) { 2749 return generatePropertyReference(expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(), 2750 resolvedCall.getDispatchReceiver()); 2751 } 2752 2753 throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText()); 2754 } 2755 2756 @NotNull 2757 public StackValue generatePropertyReference( 2758 @NotNull KtElement element, 2759 @NotNull VariableDescriptor variableDescriptor, 2760 @NotNull VariableDescriptor target, 2761 @NotNull ReceiverValue dispatchReceiver 2762 ) { 2763 ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor); 2764 2765 ClassBuilder classBuilder = state.getFactory().newVisitor( 2766 JvmDeclarationOriginKt.OtherOrigin(element), 2767 typeMapper.mapClass(classDescriptor), 2768 element.getContainingFile() 2769 ); 2770 2771 PropertyReferenceCodegen codegen = new PropertyReferenceCodegen( 2772 state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION), 2773 element, classBuilder, classDescriptor, target, dispatchReceiver 2774 ); 2775 codegen.generate(); 2776 2777 return codegen.putInstanceOnStack(); 2778 } 2779 2780 @NotNull 2781 public static StackValue generateClassLiteralReference(@NotNull JetTypeMapper typeMapper, @NotNull KotlinType type) { 2782 return generateClassLiteralReference(typeMapper, type, null); 2783 } 2784 2785 @NotNull 2786 private static StackValue generateClassLiteralReference(@NotNull final JetTypeMapper typeMapper, @NotNull final KotlinType type, @Nullable final ExpressionCodegen codegen) { 2787 return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() { 2788 @Override 2789 public Unit invoke(InstructionAdapter v) { 2790 Type classAsmType = typeMapper.mapType(type); 2791 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 2792 if (descriptor instanceof TypeParameterDescriptor) { 2793 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 2794 assert typeParameterDescriptor.isReified() : 2795 "Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor; 2796 assert codegen != null : 2797 "Reference to member of reified type should be rejected by type checker " + typeParameterDescriptor; 2798 codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME); 2799 } 2800 2801 putJavaLangClassInstance(v, classAsmType); 2802 wrapJavaClassIntoKClass(v); 2803 2804 return Unit.INSTANCE$; 2805 } 2806 }); 2807 } 2808 2809 @Override 2810 public StackValue visitDotQualifiedExpression(@NotNull KtDotQualifiedExpression expression, StackValue receiver) { 2811 StackValue receiverValue = StackValue.none(); //gen(expression.getReceiverExpression()) 2812 return genQualified(receiverValue, expression.getSelectorExpression()); 2813 } 2814 2815 private StackValue generateExpressionWithNullFallback(@NotNull KtExpression expression, @NotNull Label ifnull) { 2816 KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression); 2817 assert deparenthesized != null : "Unexpected empty expression"; 2818 2819 expression = deparenthesized; 2820 Type type = expressionType(expression); 2821 2822 if (expression instanceof KtSafeQualifiedExpression && !isPrimitive(type)) { 2823 return StackValue.coercion(generateSafeQualifiedExpression((KtSafeQualifiedExpression) expression, ifnull), type); 2824 } 2825 else { 2826 return genLazy(expression, type); 2827 } 2828 } 2829 2830 private StackValue generateSafeQualifiedExpression(@NotNull KtSafeQualifiedExpression expression, @NotNull Label ifNull) { 2831 KtExpression receiver = expression.getReceiverExpression(); 2832 KtExpression selector = expression.getSelectorExpression(); 2833 2834 Type receiverType = expressionType(receiver); 2835 StackValue receiverValue = generateExpressionWithNullFallback(receiver, ifNull); 2836 2837 //Do not optimize for primitives cause in case of safe call extension receiver should be generated before dispatch one 2838 StackValue newReceiver = new StackValue.SafeCall(receiverType, receiverValue, isPrimitive(receiverType) ? null : ifNull); 2839 return genQualified(newReceiver, selector); 2840 } 2841 2842 @Override 2843 public StackValue visitSafeQualifiedExpression(@NotNull KtSafeQualifiedExpression expression, StackValue unused) { 2844 Label ifnull = new Label(); 2845 Type type = boxType(expressionType(expression)); 2846 2847 StackValue value = generateSafeQualifiedExpression(expression, ifnull); 2848 StackValue newReceiver = StackValue.coercion(value, type); 2849 StackValue result; 2850 2851 if (!isPrimitive(expressionType(expression.getReceiverExpression()))) { 2852 result = new StackValue.SafeFallback(type, ifnull, newReceiver); 2853 } else { 2854 result = newReceiver; 2855 } 2856 2857 return result; 2858 } 2859 2860 @Override 2861 public StackValue visitBinaryExpression(@NotNull KtBinaryExpression expression, @NotNull StackValue receiver) { 2862 KtSimpleNameExpression reference = expression.getOperationReference(); 2863 IElementType opToken = reference.getReferencedNameElementType(); 2864 if (opToken == KtTokens.EQ) { 2865 return generateAssignmentExpression(expression); 2866 } 2867 else if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2868 return generateAugmentedAssignment(expression); 2869 } 2870 else if (opToken == KtTokens.ANDAND) { 2871 return generateBooleanAnd(expression); 2872 } 2873 else if (opToken == KtTokens.OROR) { 2874 return generateBooleanOr(expression); 2875 } 2876 else if (opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ || 2877 opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) { 2878 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2879 } 2880 else if (opToken == KtTokens.LT || opToken == KtTokens.LTEQ || 2881 opToken == KtTokens.GT || opToken == KtTokens.GTEQ) { 2882 return generateComparison(expression, receiver); 2883 } 2884 else if (opToken == KtTokens.ELVIS) { 2885 return generateElvis(expression); 2886 } 2887 else if (opToken == KtTokens.IN_KEYWORD || opToken == KtTokens.NOT_IN) { 2888 return generateIn(StackValue.expression(expressionType(expression.getLeft()), expression.getLeft(), this), 2889 expression.getRight(), reference); 2890 } 2891 else { 2892 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 2893 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2894 2895 if (descriptor instanceof ConstructorDescriptor) { 2896 return generateConstructorCall(resolvedCall, expressionType(expression)); 2897 } 2898 2899 return invokeFunction(resolvedCall, receiver); 2900 } 2901 } 2902 2903 private StackValue generateIn(final StackValue leftValue, KtExpression rangeExpression, final KtSimpleNameExpression operationReference) { 2904 final KtExpression deparenthesized = KtPsiUtil.deparenthesize(rangeExpression); 2905 2906 assert deparenthesized != null : "For with empty range expression"; 2907 2908 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 2909 @Override 2910 public Unit invoke(InstructionAdapter v) { 2911 if (isIntRangeExpr(deparenthesized) && AsmUtil.isIntPrimitive(leftValue.type)) { 2912 genInIntRange(leftValue, (KtBinaryExpression) deparenthesized); 2913 } 2914 else { 2915 ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt 2916 .getResolvedCallWithAssert(operationReference, bindingContext); 2917 StackValue result = invokeFunction(resolvedCall.getCall(), resolvedCall, StackValue.none()); 2918 result.put(result.type, v); 2919 } 2920 if (operationReference.getReferencedNameElementType() == KtTokens.NOT_IN) { 2921 genInvertBoolean(v); 2922 } 2923 return null; 2924 } 2925 }); 2926 } 2927 2928 private void genInIntRange(StackValue leftValue, KtBinaryExpression rangeExpression) { 2929 v.iconst(1); 2930 // 1 2931 leftValue.put(Type.INT_TYPE, v); 2932 // 1 l 2933 v.dup2(); 2934 // 1 l 1 l 2935 2936 //noinspection ConstantConditions 2937 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2938 // 1 l 1 l r 2939 Label lok = new Label(); 2940 v.ificmpge(lok); 2941 // 1 l 1 2942 v.pop(); 2943 v.iconst(0); 2944 v.mark(lok); 2945 // 1 l c 2946 v.dupX2(); 2947 // c 1 l c 2948 v.pop(); 2949 // c 1 l 2950 2951 gen(rangeExpression.getRight(), Type.INT_TYPE); 2952 // c 1 l r 2953 Label rok = new Label(); 2954 v.ificmple(rok); 2955 // c 1 2956 v.pop(); 2957 v.iconst(0); 2958 v.mark(rok); 2959 // c c 2960 2961 v.and(Type.INT_TYPE); 2962 } 2963 2964 private StackValue generateBooleanAnd(KtBinaryExpression expression) { 2965 return StackValue.and(gen(expression.getLeft()), gen(expression.getRight())); 2966 } 2967 2968 private StackValue generateBooleanOr(KtBinaryExpression expression) { 2969 return StackValue.or(gen(expression.getLeft()), gen(expression.getRight())); 2970 } 2971 2972 private StackValue generateEquals(KtExpression left, KtExpression right, IElementType opToken) { 2973 Type leftType = expressionType(left); 2974 Type rightType = expressionType(right); 2975 2976 if (KtPsiUtil.isNullConstant(left)) { 2977 return genCmpWithNull(right, opToken); 2978 } 2979 2980 if (KtPsiUtil.isNullConstant(right)) { 2981 return genCmpWithNull(left, opToken); 2982 } 2983 2984 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2985 return genCmpWithZero(right, opToken); 2986 } 2987 2988 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2989 return genCmpWithZero(left, opToken); 2990 } 2991 2992 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2993 leftType = boxType(leftType); 2994 rightType = boxType(rightType); 2995 } 2996 2997 StackValue leftValue = genLazy(left, leftType); 2998 StackValue rightValue = genLazy(right, rightType); 2999 3000 if (opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) { 3001 // TODO: always casting to the type of the left operand in case of primitives looks wrong 3002 Type operandType = isPrimitive(leftType) ? leftType : OBJECT_TYPE; 3003 return StackValue.cmp(opToken, operandType, leftValue, rightValue); 3004 } 3005 3006 return genEqualsForExpressionsOnStack(opToken, leftValue, rightValue); 3007 } 3008 3009 private boolean isIntZero(KtExpression expr, Type exprType) { 3010 ConstantValue<?> exprValue = getCompileTimeConstant(expr, bindingContext); 3011 return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue()); 3012 } 3013 3014 private StackValue genCmpWithZero(KtExpression exp, IElementType opToken) { 3015 return StackValue.compareIntWithZero(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ); 3016 } 3017 3018 private StackValue genCmpWithNull(KtExpression exp, IElementType opToken) { 3019 return StackValue.compareWithNull(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL); 3020 } 3021 3022 private StackValue generateElvis(@NotNull final KtBinaryExpression expression) { 3023 KtExpression left = expression.getLeft(); 3024 3025 final Type exprType = expressionType(expression); 3026 final Type leftType = expressionType(left); 3027 3028 final Label ifNull = new Label(); 3029 3030 3031 assert left != null : "left expression in elvis should be not null: " + expression.getText(); 3032 final StackValue value = generateExpressionWithNullFallback(left, ifNull); 3033 3034 if (isPrimitive(leftType)) { 3035 return value; 3036 } 3037 3038 return StackValue.operation(exprType, new Function1<InstructionAdapter, Unit>() { 3039 @Override 3040 public Unit invoke(InstructionAdapter v) { 3041 value.put(value.type, v); 3042 v.dup(); 3043 3044 v.ifnull(ifNull); 3045 StackValue.onStack(leftType).put(exprType, v); 3046 3047 Label end = new Label(); 3048 v.goTo(end); 3049 3050 v.mark(ifNull); 3051 v.pop(); 3052 gen(expression.getRight(), exprType); 3053 v.mark(end); 3054 return null; 3055 } 3056 }); 3057 } 3058 3059 private StackValue generateComparison(KtBinaryExpression expression, StackValue receiver) { 3060 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3061 3062 KtExpression left = expression.getLeft(); 3063 KtExpression right = expression.getRight(); 3064 3065 Type type; 3066 StackValue leftValue; 3067 StackValue rightValue; 3068 Type leftType = expressionType(left); 3069 Type rightType = expressionType(right); 3070 if (isPrimitive(leftType) && isPrimitive(rightType)) { 3071 type = comparisonOperandType(leftType, rightType); 3072 leftValue = gen(left); 3073 rightValue = gen(right); 3074 } 3075 else { 3076 type = Type.INT_TYPE; 3077 leftValue = invokeFunction(resolvedCall, receiver); 3078 rightValue = StackValue.constant(0, type); 3079 } 3080 return StackValue.cmp(expression.getOperationToken(), type, leftValue, rightValue); 3081 } 3082 3083 private StackValue generateAssignmentExpression(KtBinaryExpression expression) { 3084 StackValue stackValue = gen(expression.getLeft()); 3085 KtExpression right = expression.getRight(); 3086 assert right != null : expression.getText(); 3087 stackValue.store(gen(right), v); 3088 return StackValue.none(); 3089 } 3090 3091 private StackValue generateAugmentedAssignment(KtBinaryExpression expression) { 3092 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3093 FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); 3094 Callable callable = resolveToCallable(descriptor, false, resolvedCall); 3095 KtExpression lhs = expression.getLeft(); 3096 Type lhsType = expressionType(lhs); 3097 3098 boolean keepReturnValue = Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression)) 3099 || !KotlinBuiltIns.isUnit(descriptor.getReturnType()); 3100 3101 callAugAssignMethod(expression, resolvedCall, callable, lhsType, keepReturnValue); 3102 3103 return StackValue.none(); 3104 } 3105 3106 private void callAugAssignMethod( 3107 @NotNull KtBinaryExpression expression, 3108 @NotNull ResolvedCall<?> resolvedCall, 3109 @NotNull Callable callable, 3110 @NotNull Type lhsType, 3111 boolean keepReturnValue 3112 ) { 3113 StackValue value = gen(expression.getLeft()); 3114 if (keepReturnValue) { 3115 value = StackValue.complexWriteReadReceiver(value); 3116 } 3117 value.put(lhsType, v); 3118 StackValue receiver = StackValue.onStack(lhsType); 3119 3120 callable.invokeMethodWithArguments(resolvedCall, receiver, this).put(callable.getReturnType(), v); 3121 3122 if (keepReturnValue) { 3123 value.store(StackValue.onStack(callable.getReturnType()), v, true); 3124 } 3125 } 3126 3127 public void invokeAppend(KtExpression expr) { 3128 if (expr instanceof KtBinaryExpression) { 3129 KtBinaryExpression binaryExpression = (KtBinaryExpression) expr; 3130 if (binaryExpression.getOperationToken() == KtTokens.PLUS) { 3131 KtExpression left = binaryExpression.getLeft(); 3132 KtExpression right = binaryExpression.getRight(); 3133 Type leftType = expressionType(left); 3134 3135 if (leftType.equals(JAVA_STRING_TYPE)) { 3136 invokeAppend(left); 3137 invokeAppend(right); 3138 return; 3139 } 3140 } 3141 } 3142 Type exprType = expressionType(expr); 3143 gen(expr, exprType); 3144 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 3145 } 3146 3147 @Nullable 3148 private static KtSimpleNameExpression targetLabel(KtExpression expression) { 3149 if (expression.getParent() instanceof KtLabeledExpression) { 3150 return ((KtLabeledExpression) expression.getParent()).getTargetLabel(); 3151 } 3152 return null; 3153 } 3154 3155 @Override 3156 public StackValue visitLabeledExpression( 3157 @NotNull KtLabeledExpression expression, StackValue receiver 3158 ) { 3159 return genQualified(receiver, expression.getBaseExpression()); 3160 } 3161 3162 @Override 3163 public StackValue visitPrefixExpression(@NotNull KtPrefixExpression expression, @NotNull StackValue receiver) { 3164 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3165 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3166 CallableDescriptor op = resolvedCall.getResultingDescriptor(); 3167 3168 assert op instanceof FunctionDescriptor || originalOperation == null : String.valueOf(op); 3169 String operationName = originalOperation == null ? "" : originalOperation.getName().asString(); 3170 if (!(operationName.equals("inc") || operationName.equals("dec"))) { 3171 return invokeFunction(resolvedCall, receiver); 3172 } 3173 3174 int increment = operationName.equals("inc") ? 1 : -1; 3175 Type type = expressionType(expression.getBaseExpression()); 3176 StackValue value = gen(expression.getBaseExpression()); 3177 return StackValue.preIncrement(type, value, increment, resolvedCall, this); 3178 } 3179 3180 @Override 3181 public StackValue visitPostfixExpression(@NotNull final KtPostfixExpression expression, StackValue receiver) { 3182 if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) { 3183 final StackValue base = genQualified(receiver, expression.getBaseExpression()); 3184 if (isPrimitive(base.type)) { 3185 return base; 3186 } else { 3187 return StackValue.operation(base.type, new Function1<InstructionAdapter, Unit>() { 3188 @Override 3189 public Unit invoke(InstructionAdapter v) { 3190 base.put(base.type, v); 3191 v.dup(); 3192 Label ok = new Label(); 3193 v.ifnonnull(ok); 3194 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwNpe", "()V", false); 3195 v.mark(ok); 3196 return null; 3197 } 3198 }); 3199 } 3200 } 3201 3202 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3203 String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null; 3204 final ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); 3205 DeclarationDescriptor op = resolvedCall.getResultingDescriptor(); 3206 if (!(op instanceof FunctionDescriptor) || originalOperation == null) { 3207 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + originalOperationName + " " + op); 3208 } 3209 3210 3211 final Type asmResultType = expressionType(expression); 3212 final Type asmBaseType = expressionType(expression.getBaseExpression()); 3213 3214 DeclarationDescriptor cls = op.getContainingDeclaration(); 3215 3216 final int increment; 3217 if (originalOperationName.equals("inc")) { 3218 increment = 1; 3219 } 3220 else if (originalOperationName.equals("dec")) { 3221 increment = -1; 3222 } 3223 else { 3224 throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op); 3225 } 3226 3227 final boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 3228 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3229 KtExpression operand = expression.getBaseExpression(); 3230 // Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int 3231 if (operand instanceof KtReferenceExpression && asmResultType == Type.INT_TYPE && 3232 bindingContext.get(BindingContext.SMARTCAST, operand) == null) { 3233 int index = indexOfLocal((KtReferenceExpression) operand); 3234 if (index >= 0) { 3235 return StackValue.postIncrement(index, increment); 3236 } 3237 } 3238 } 3239 3240 return StackValue.operation(asmBaseType, new Function1<InstructionAdapter, Unit>() { 3241 @Override 3242 public Unit invoke(InstructionAdapter v) { 3243 StackValue value = gen(expression.getBaseExpression()); 3244 value = StackValue.complexWriteReadReceiver(value); 3245 3246 Type type = expressionType(expression.getBaseExpression()); 3247 value.put(type, v); // old value 3248 3249 value.dup(v, true); 3250 3251 Type storeType; 3252 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3253 genIncrement(asmResultType, increment, v); 3254 storeType = type; 3255 } 3256 else { 3257 StackValue result = invokeFunction(resolvedCall, StackValue.onStack(type)); 3258 result.put(result.type, v); 3259 storeType = result.type; 3260 } 3261 3262 value.store(StackValue.onStack(storeType), v, true); 3263 return Unit.INSTANCE$; 3264 } 3265 }); 3266 } 3267 3268 @Override 3269 public StackValue visitProperty(@NotNull KtProperty property, StackValue receiver) { 3270 KtExpression initializer = property.getInitializer(); 3271 if (initializer == null) { 3272 return StackValue.none(); 3273 } 3274 initializeLocalVariable(property, gen(initializer)); 3275 return StackValue.none(); 3276 } 3277 3278 @Override 3279 public StackValue visitMultiDeclaration(@NotNull KtMultiDeclaration multiDeclaration, StackValue receiver) { 3280 KtExpression initializer = multiDeclaration.getInitializer(); 3281 if (initializer == null) return StackValue.none(); 3282 3283 KotlinType initializerType = bindingContext.getType(initializer); 3284 assert initializerType != null; 3285 3286 Type initializerAsmType = asmType(initializerType); 3287 3288 TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3289 3290 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3291 3292 gen(initializer, initializerAsmType); 3293 v.store(tempVarIndex, initializerAsmType); 3294 StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3295 3296 for (KtMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3297 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 3298 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3299 Call call = makeFakeCall(initializerAsReceiver); 3300 initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, local)); 3301 } 3302 3303 if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3304 v.aconst(null); 3305 v.store(tempVarIndex, initializerAsmType); 3306 } 3307 myFrameMap.leaveTemp(initializerAsmType); 3308 3309 return StackValue.none(); 3310 } 3311 3312 private void initializeLocalVariable( 3313 @NotNull KtVariableDeclaration variableDeclaration, 3314 @NotNull StackValue initializer 3315 ) { 3316 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 3317 3318 if (KtPsiUtil.isScriptDeclaration(variableDeclaration)) { 3319 return; 3320 } 3321 int index = lookupLocalIndex(variableDescriptor); 3322 3323 if (index < 0) { 3324 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3325 } 3326 3327 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3328 assert variableDescriptor != null; 3329 3330 Type varType = asmType(variableDescriptor.getType()); 3331 3332 StackValue storeTo = sharedVarType == null ? StackValue.local(index, varType) : StackValue.shared(index, varType); 3333 3334 storeTo.putReceiver(v, false); 3335 initializer.put(initializer.type, v); 3336 3337 markLineNumber(variableDeclaration, false); 3338 3339 storeTo.storeSelector(initializer.type, v); 3340 } 3341 3342 @NotNull 3343 private StackValue generateNewCall(@NotNull KtCallExpression expression, @NotNull ResolvedCall<?> resolvedCall) { 3344 Type type = expressionType(expression); 3345 if (type.getSort() == Type.ARRAY) { 3346 //noinspection ConstantConditions 3347 return generateNewArray(expression, bindingContext.getType(expression)); 3348 } 3349 3350 return generateConstructorCall(resolvedCall, type); 3351 } 3352 3353 @NotNull 3354 public ConstructorDescriptor getConstructorDescriptor(@NotNull ResolvedCall<?> resolvedCall) { 3355 FunctionDescriptor accessibleDescriptor = accessibleFunctionDescriptor(resolvedCall); 3356 assert accessibleDescriptor instanceof ConstructorDescriptor : 3357 "getConstructorDescriptor must be called only for constructors: " + accessibleDescriptor; 3358 return (ConstructorDescriptor) accessibleDescriptor; 3359 } 3360 3361 @NotNull 3362 public StackValue generateConstructorCall(@NotNull final ResolvedCall<?> resolvedCall, @NotNull final Type objectType) { 3363 return StackValue.functionCall(objectType, new Function1<InstructionAdapter, Unit>() { 3364 @Override 3365 public Unit invoke(InstructionAdapter v) { 3366 v.anew(objectType); 3367 v.dup(); 3368 3369 ConstructorDescriptor constructor = getConstructorDescriptor(resolvedCall); 3370 3371 ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter(); 3372 ClassDescriptor containingDeclaration = constructor.getContainingDeclaration(); 3373 if (dispatchReceiver != null) { 3374 Type receiverType = typeMapper.mapType(dispatchReceiver.getType()); 3375 ReceiverValue receiver = resolvedCall.getDispatchReceiver(); 3376 boolean callSuper = containingDeclaration.isInner() && receiver instanceof ImplicitClassReceiver; 3377 generateReceiverValue(receiver, callSuper).put(receiverType, v); 3378 } 3379 3380 // Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack 3381 // See StackValue.receiver for more info 3382 pushClosureOnStack(containingDeclaration, dispatchReceiver == null, defaultCallGenerator); 3383 3384 constructor = SamCodegenUtil.resolveSamAdapter(constructor); 3385 CallableMethod method = typeMapper.mapToCallableMethod(constructor, false); 3386 invokeMethodWithArguments(method, resolvedCall, StackValue.none()); 3387 3388 return Unit.INSTANCE$; 3389 } 3390 }); 3391 } 3392 3393 public StackValue generateNewArray(@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType) { 3394 assert expression.getValueArguments().size() == 1 : "Size argument expected"; 3395 3396 final KtExpression sizeExpression = expression.getValueArguments().get(0).getArgumentExpression(); 3397 Type type = typeMapper.mapType(arrayType); 3398 3399 return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() { 3400 @Override 3401 public Unit invoke(InstructionAdapter v) { 3402 gen(sizeExpression, Type.INT_TYPE); 3403 newArrayInstruction(arrayType); 3404 return Unit.INSTANCE$; 3405 } 3406 }); 3407 } 3408 3409 public void newArrayInstruction(@NotNull KotlinType arrayType) { 3410 if (KotlinBuiltIns.isArray(arrayType)) { 3411 KotlinType elementJetType = arrayType.getArguments().get(0).getType(); 3412 putReifierMarkerIfTypeIsReifiedParameter( 3413 elementJetType, 3414 ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME 3415 ); 3416 v.newarray(boxType(asmType(elementJetType))); 3417 } 3418 else { 3419 Type type = typeMapper.mapType(arrayType); 3420 v.newarray(correctElementType(type)); 3421 } 3422 } 3423 3424 @Override 3425 public StackValue visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression, StackValue receiver) { 3426 KtExpression array = expression.getArrayExpression(); 3427 KotlinType type = array != null ? bindingContext.getType(array) : null; 3428 Type arrayType = expressionType(array); 3429 List<KtExpression> indices = expression.getIndexExpressions(); 3430 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(REFERENCE_TARGET, expression); 3431 assert operationDescriptor != null; 3432 if (arrayType.getSort() == Type.ARRAY && 3433 indices.size() == 1 && 3434 isInt(operationDescriptor.getValueParameters().get(0).getType())) { 3435 assert type != null; 3436 Type elementType; 3437 if (KotlinBuiltIns.isArray(type)) { 3438 KotlinType jetElementType = type.getArguments().get(0).getType(); 3439 elementType = boxType(asmType(jetElementType)); 3440 } 3441 else { 3442 elementType = correctElementType(arrayType); 3443 } 3444 StackValue arrayValue = genLazy(array, arrayType); 3445 StackValue index = genLazy(indices.get(0), Type.INT_TYPE); 3446 3447 return StackValue.arrayElement(elementType, arrayValue, index); 3448 } 3449 else { 3450 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression); 3451 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(INDEXED_LVALUE_GET, expression); 3452 3453 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3454 3455 Callable callable = resolveToCallable(operationDescriptor, false, isGetter ? resolvedGetCall : resolvedSetCall); 3456 Callable callableMethod = resolveToCallableMethod(operationDescriptor, false); 3457 Type[] argumentTypes = callableMethod.getParameterTypes(); 3458 3459 StackValue.CollectionElementReceiver collectionElementReceiver = createCollectionElementReceiver( 3460 expression, receiver, operationDescriptor, isGetter, resolvedGetCall, resolvedSetCall, callable 3461 ); 3462 3463 Type elementType = isGetter ? callableMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3464 return StackValue.collectionElement(collectionElementReceiver, elementType, resolvedGetCall, resolvedSetCall, this); 3465 } 3466 } 3467 3468 @NotNull 3469 private StackValue.CollectionElementReceiver createCollectionElementReceiver( 3470 @NotNull KtArrayAccessExpression expression, 3471 @NotNull StackValue receiver, 3472 @NotNull FunctionDescriptor operationDescriptor, 3473 boolean isGetter, 3474 ResolvedCall<FunctionDescriptor> resolvedGetCall, 3475 ResolvedCall<FunctionDescriptor> resolvedSetCall, 3476 @NotNull Callable callable 3477 ) { 3478 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3479 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3480 3481 ArgumentGenerator argumentGenerator = new CallBasedArgumentGenerator( 3482 this, defaultCallGenerator, resolvedCall.getResultingDescriptor().getValueParameters(), callable.getValueParameterTypes() 3483 ); 3484 3485 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 3486 assert valueArguments != null : "Failed to arrange value arguments by index: " + operationDescriptor; 3487 3488 if (!isGetter) { 3489 assert valueArguments.size() >= 2 : "Setter call should have at least 2 arguments: " + operationDescriptor; 3490 // Skip generation of the right hand side of an indexed assignment, which is the last value argument 3491 valueArguments.remove(valueArguments.size() - 1); 3492 } 3493 3494 return new StackValue.CollectionElementReceiver( 3495 callable, receiver, resolvedGetCall, resolvedSetCall, isGetter, this, argumentGenerator, valueArguments 3496 ); 3497 } 3498 3499 @Override 3500 public StackValue visitThrowExpression(@NotNull final KtThrowExpression expression, StackValue receiver) { 3501 return StackValue.operation(Type.VOID_TYPE, new Function1<InstructionAdapter, Unit>() { 3502 @Override 3503 public Unit invoke(InstructionAdapter adapter) { 3504 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3505 v.athrow(); 3506 return Unit.INSTANCE; 3507 } 3508 }); 3509 } 3510 3511 @Override 3512 public StackValue visitThisExpression(@NotNull KtThisExpression expression, StackValue receiver) { 3513 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 3514 if (descriptor instanceof ClassDescriptor) { 3515 //TODO rewrite with context.lookupInContext() 3516 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true); 3517 } 3518 if (descriptor instanceof CallableDescriptor) { 3519 return generateReceiver((CallableDescriptor) descriptor); 3520 } 3521 throw new UnsupportedOperationException("Neither this nor receiver: " + descriptor); 3522 } 3523 3524 @Override 3525 public StackValue visitTryExpression(@NotNull KtTryExpression expression, StackValue receiver) { 3526 return generateTryExpression(expression, false); 3527 } 3528 3529 public StackValue generateTryExpression(final KtTryExpression expression, final boolean isStatement) { 3530 /* 3531 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 3532 (or blocks). 3533 */ 3534 3535 KotlinType jetType = bindingContext.getType(expression); 3536 assert jetType != null; 3537 final Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3538 3539 return StackValue.operation(expectedAsmType, new Function1<InstructionAdapter, Unit>() { 3540 @Override 3541 public Unit invoke(InstructionAdapter v) { 3542 KtFinallySection finallyBlock = expression.getFinallyBlock(); 3543 FinallyBlockStackElement finallyBlockStackElement = null; 3544 if (finallyBlock != null) { 3545 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3546 blockStackElements.push(finallyBlockStackElement); 3547 } 3548 3549 //PseudoInsnsPackage.saveStackBeforeTryExpr(v); 3550 3551 Label tryStart = new Label(); 3552 v.mark(tryStart); 3553 v.nop(); // prevent verify error on empty try 3554 3555 gen(expression.getTryBlock(), expectedAsmType); 3556 3557 int savedValue = -1; 3558 if (!isStatement) { 3559 savedValue = myFrameMap.enterTemp(expectedAsmType); 3560 v.store(savedValue, expectedAsmType); 3561 } 3562 3563 Label tryEnd = new Label(); 3564 v.mark(tryEnd); 3565 3566 //do it before finally block generation 3567 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3568 3569 Label end = new Label(); 3570 3571 genFinallyBlockOrGoto(finallyBlockStackElement, end, null); 3572 3573 List<KtCatchClause> clauses = expression.getCatchClauses(); 3574 for (int i = 0, size = clauses.size(); i < size; i++) { 3575 KtCatchClause clause = clauses.get(i); 3576 3577 Label clauseStart = new Label(); 3578 v.mark(clauseStart); 3579 3580 VariableDescriptor descriptor = bindingContext.get(VALUE_PARAMETER, clause.getCatchParameter()); 3581 assert descriptor != null; 3582 Type descriptorType = asmType(descriptor.getType()); 3583 myFrameMap.enter(descriptor, descriptorType); 3584 int index = lookupLocalIndex(descriptor); 3585 v.store(index, descriptorType); 3586 3587 gen(clause.getCatchBody(), expectedAsmType); 3588 3589 if (!isStatement) { 3590 v.store(savedValue, expectedAsmType); 3591 } 3592 3593 myFrameMap.leave(descriptor); 3594 3595 Label clauseEnd = new Label(); 3596 v.mark(clauseEnd); 3597 3598 v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, 3599 index); 3600 3601 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null, null); 3602 3603 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3604 } 3605 3606 3607 //for default catch clause 3608 if (finallyBlock != null) { 3609 Label defaultCatchStart = new Label(); 3610 v.mark(defaultCatchStart); 3611 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3612 v.store(savedException, JAVA_THROWABLE_TYPE); 3613 3614 Label defaultCatchEnd = new Label(); 3615 v.mark(defaultCatchEnd); 3616 3617 //do it before finally block generation 3618 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3619 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3620 3621 3622 genFinallyBlockOrGoto(finallyBlockStackElement, null, null); 3623 3624 v.load(savedException, JAVA_THROWABLE_TYPE); 3625 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3626 3627 v.athrow(); 3628 3629 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3630 } 3631 3632 markLineNumber(expression, isStatement); 3633 v.mark(end); 3634 3635 if (!isStatement) { 3636 v.load(savedValue, expectedAsmType); 3637 myFrameMap.leaveTemp(expectedAsmType); 3638 } 3639 3640 if (finallyBlock != null) { 3641 blockStackElements.pop(); 3642 } 3643 return Unit.INSTANCE$; 3644 } 3645 }); 3646 } 3647 3648 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3649 for (int i = 0; i < catchedRegions.size(); i += 2) { 3650 Label startRegion = catchedRegions.get(i); 3651 Label endRegion = catchedRegions.get(i+1); 3652 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3653 } 3654 } 3655 3656 @NotNull 3657 private static List<Label> getCurrentCatchIntervals( 3658 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3659 @NotNull Label blockStart, 3660 @NotNull Label blockEnd 3661 ) { 3662 List<Label> gapsInBlock = 3663 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3664 assert gapsInBlock.size() % 2 == 0; 3665 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3666 blockRegions.add(blockStart); 3667 blockRegions.addAll(gapsInBlock); 3668 blockRegions.add(blockEnd); 3669 return blockRegions; 3670 } 3671 3672 @Override 3673 public StackValue visitBinaryWithTypeRHSExpression(@NotNull KtBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3674 KtExpression left = expression.getLeft(); 3675 final IElementType opToken = expression.getOperationReference().getReferencedNameElementType(); 3676 3677 final KotlinType rightType = bindingContext.get(TYPE, expression.getRight()); 3678 assert rightType != null; 3679 3680 final StackValue value = genQualified(receiver, left); 3681 3682 return StackValue.operation(boxType(asmType(rightType)), new Function1<InstructionAdapter, Unit>() { 3683 @Override 3684 public Unit invoke(InstructionAdapter v) { 3685 value.put(boxType(value.type), v); 3686 3687 if (value.type == Type.VOID_TYPE) { 3688 StackValue.putUnitInstance(v); 3689 } 3690 3691 if (opToken != KtTokens.AS_SAFE) { 3692 if (!TypeUtils.isNullableType(rightType)) { 3693 v.dup(); 3694 Label nonnull = new Label(); 3695 v.ifnonnull(nonnull); 3696 genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + 3697 DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType)); 3698 v.mark(nonnull); 3699 } 3700 } 3701 else { 3702 v.dup(); 3703 generateInstanceOfInstruction(rightType); 3704 Label ok = new Label(); 3705 v.ifne(ok); 3706 v.pop(); 3707 v.aconst(null); 3708 v.mark(ok); 3709 } 3710 3711 generateCheckCastInstruction(rightType, opToken == KtTokens.AS_SAFE); 3712 return Unit.INSTANCE$; 3713 } 3714 }); 3715 } 3716 3717 @Override 3718 public StackValue visitIsExpression(@NotNull KtIsExpression expression, StackValue receiver) { 3719 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3720 return generateIsCheck(match, expression.getTypeReference(), expression.isNegated()); 3721 } 3722 3723 private StackValue generateExpressionMatch(StackValue expressionToMatch, KtExpression patternExpression) { 3724 if (expressionToMatch != null) { 3725 Type subjectType = expressionToMatch.type; 3726 markStartLineNumber(patternExpression); 3727 KotlinType condJetType = bindingContext.getType(patternExpression); 3728 Type condType; 3729 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3730 assert condJetType != null; 3731 condType = asmType(condJetType); 3732 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3733 subjectType = boxType(subjectType); 3734 } 3735 } 3736 else { 3737 condType = OBJECT_TYPE; 3738 } 3739 StackValue condition = genLazy(patternExpression, condType); 3740 return genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.coercion(expressionToMatch, subjectType), condition); 3741 } 3742 else { 3743 return gen(patternExpression); 3744 } 3745 } 3746 3747 private StackValue generateIsCheck(StackValue expressionToMatch, KtTypeReference typeReference, boolean negated) { 3748 KotlinType jetType = bindingContext.get(TYPE, typeReference); 3749 markStartLineNumber(typeReference); 3750 StackValue value = generateInstanceOf(expressionToMatch, jetType, false); 3751 return negated ? StackValue.not(value) : value; 3752 } 3753 3754 private StackValue generateInstanceOf(final StackValue expressionToGen, final KotlinType kotlinType, final boolean leaveExpressionOnStack) { 3755 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3756 @Override 3757 public Unit invoke(InstructionAdapter v) { 3758 expressionToGen.put(OBJECT_TYPE, v); 3759 if (leaveExpressionOnStack) { 3760 v.dup(); 3761 } 3762 CodegenUtilKt.generateIsCheck(v, kotlinType, new Function1<InstructionAdapter, Unit>() { 3763 @Override 3764 public Unit invoke(InstructionAdapter adapter) { 3765 generateInstanceOfInstruction(kotlinType); 3766 return Unit.INSTANCE; 3767 } 3768 }); 3769 return null; 3770 } 3771 }); 3772 } 3773 3774 private void generateInstanceOfInstruction(@NotNull KotlinType jetType) { 3775 Type type = boxType(asmType(jetType)); 3776 putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.INSTANCEOF_MARKER_METHOD_NAME); 3777 TypeIntrinsics.instanceOf(v, jetType, type); 3778 } 3779 3780 @NotNull 3781 private StackValue generateCheckCastInstruction(@NotNull KotlinType jetType, boolean safeAs) { 3782 Type type = boxType(asmType(jetType)); 3783 putReifierMarkerIfTypeIsReifiedParameter(jetType, 3784 safeAs ? ReifiedTypeInliner.SAFE_CHECKCAST_MARKER_METHOD_NAME 3785 : ReifiedTypeInliner.CHECKCAST_MARKER_METHOD_NAME); 3786 TypeIntrinsics.checkcast(v, jetType, type, safeAs); 3787 return StackValue.onStack(type); 3788 } 3789 3790 public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull KotlinType type, @NotNull String markerMethodName) { 3791 TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type); 3792 if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) { 3793 if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) { 3794 parentCodegen.getReifiedTypeParametersUsages(). 3795 addUsedReifiedParameter(typeParameterDescriptor.getName().asString()); 3796 } 3797 3798 v.visitLdcInsn(typeParameterDescriptor.getName().asString()); 3799 v.invokestatic( 3800 IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName, 3801 Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false 3802 ); 3803 } 3804 } 3805 3806 public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) { 3807 parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context); 3808 } 3809 3810 @Override 3811 public StackValue visitWhenExpression(@NotNull KtWhenExpression expression, StackValue receiver) { 3812 return generateWhenExpression(expression, false); 3813 } 3814 3815 public StackValue generateWhenExpression(final KtWhenExpression expression, final boolean isStatement) { 3816 final KtExpression expr = expression.getSubjectExpression(); 3817 final Type subjectType = expressionType(expr); 3818 3819 final Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3820 3821 return StackValue.operation(resultType, new Function1<InstructionAdapter, Unit>() { 3822 @Override 3823 public Unit invoke(InstructionAdapter v) { 3824 SwitchCodegen switchCodegen = 3825 SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(expression, isStatement, ExpressionCodegen.this); 3826 if (switchCodegen != null) { 3827 switchCodegen.generate(); 3828 return Unit.INSTANCE$; 3829 } 3830 3831 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3832 if (subjectLocal != -1) { 3833 gen(expr, subjectType); 3834 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3835 v.store(subjectLocal, subjectType); 3836 } 3837 3838 Label end = new Label(); 3839 boolean hasElse = KtPsiUtil.checkWhenExpressionHasSingleElse(expression); 3840 3841 Label nextCondition = null; 3842 for (KtWhenEntry whenEntry : expression.getEntries()) { 3843 if (nextCondition != null) { 3844 v.mark(nextCondition); 3845 } 3846 nextCondition = new Label(); 3847 FrameMap.Mark mark = myFrameMap.mark(); 3848 Label thisEntry = new Label(); 3849 if (!whenEntry.isElse()) { 3850 KtWhenCondition[] conditions = whenEntry.getConditions(); 3851 for (int i = 0; i < conditions.length; i++) { 3852 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3853 BranchedValue.Companion.condJump(conditionValue, nextCondition, true, v); 3854 if (i < conditions.length - 1) { 3855 v.goTo(thisEntry); 3856 v.mark(nextCondition); 3857 nextCondition = new Label(); 3858 } 3859 } 3860 } 3861 3862 v.visitLabel(thisEntry); 3863 gen(whenEntry.getExpression(), resultType); 3864 mark.dropTo(); 3865 if (!whenEntry.isElse()) { 3866 v.goTo(end); 3867 } 3868 } 3869 if (!hasElse && nextCondition != null) { 3870 v.mark(nextCondition); 3871 if (!isStatement) { 3872 putUnitInstanceOntoStackForNonExhaustiveWhen(expression); 3873 } 3874 } 3875 3876 markLineNumber(expression, isStatement); 3877 v.mark(end); 3878 3879 myFrameMap.leaveTemp(subjectType); 3880 tempVariables.remove(expr); 3881 return null; 3882 } 3883 }); 3884 } 3885 3886 public void putUnitInstanceOntoStackForNonExhaustiveWhen( 3887 @NotNull KtWhenExpression expression 3888 ) { 3889 if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { 3890 // when() is supposed to be exhaustive 3891 genThrow(v, "kotlin/NoWhenBranchMatchedException", null); 3892 } 3893 else { 3894 // non-exhaustive when() with no else -> Unit must be expected 3895 StackValue.putUnitInstance(v); 3896 } 3897 } 3898 3899 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, KtWhenCondition condition) { 3900 if (condition instanceof KtWhenConditionInRange) { 3901 KtWhenConditionInRange conditionInRange = (KtWhenConditionInRange) condition; 3902 return generateIn(StackValue.local(subjectLocal, subjectType), 3903 conditionInRange.getRangeExpression(), 3904 conditionInRange.getOperationReference()); 3905 } 3906 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3907 if (condition instanceof KtWhenConditionIsPattern) { 3908 KtWhenConditionIsPattern patternCondition = (KtWhenConditionIsPattern) condition; 3909 return generateIsCheck(match, patternCondition.getTypeReference(), patternCondition.isNegated()); 3910 } 3911 else if (condition instanceof KtWhenConditionWithExpression) { 3912 KtExpression patternExpression = ((KtWhenConditionWithExpression) condition).getExpression(); 3913 return generateExpressionMatch(match, patternExpression); 3914 } 3915 else { 3916 throw new UnsupportedOperationException("unsupported kind of when condition"); 3917 } 3918 } 3919 3920 private boolean isIntRangeExpr(KtExpression rangeExpression) { 3921 if (rangeExpression instanceof KtBinaryExpression) { 3922 KtBinaryExpression binaryExpression = (KtBinaryExpression) rangeExpression; 3923 if (binaryExpression.getOperationReference().getReferencedNameElementType() == KtTokens.RANGE) { 3924 KotlinType jetType = bindingContext.getType(rangeExpression); 3925 assert jetType != null; 3926 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3927 return DescriptorUtilsKt.getBuiltIns(descriptor).getIntegralRanges().contains(descriptor); 3928 } 3929 } 3930 return false; 3931 } 3932 3933 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3934 KtSimpleNameExpression fake = KtPsiFactoryKt.KtPsiFactory(state.getProject()).createSimpleName("fake"); 3935 return CallMaker.makeCall(fake, initializerAsReceiver); 3936 } 3937 3938 @Override 3939 public String toString() { 3940 return context.getContextDescriptor().toString(); 3941 } 3942 3943 @NotNull 3944 public FrameMap getFrameMap() { 3945 return myFrameMap; 3946 } 3947 3948 @NotNull 3949 public MethodContext getContext() { 3950 return context; 3951 } 3952 3953 @NotNull 3954 public NameGenerator getInlineNameGenerator() { 3955 NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator(); 3956 Name name = context.getContextDescriptor().getName(); 3957 return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" ); 3958 } 3959 3960 public Type getReturnType() { 3961 return returnType; 3962 } 3963 3964 public Stack<BlockStackElement> getBlockStackElements() { 3965 return new Stack<BlockStackElement>(blockStackElements); 3966 } 3967 3968 public void addBlockStackElementsForNonLocalReturns(@NotNull Stack<BlockStackElement> elements, int finallyDepth) { 3969 blockStackElements.addAll(elements); 3970 this.finallyDepth = finallyDepth; 3971 } 3972 3973 private static class NonLocalReturnInfo { 3974 3975 final Type returnType; 3976 3977 final String labelName; 3978 3979 private NonLocalReturnInfo(Type type, String name) { 3980 returnType = type; 3981 labelName = name; 3982 } 3983 } 3984 }