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