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