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