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