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 int index = lookupLocalIndex(descriptor); 1646 if (index >= 0) { 1647 return stackValueForLocal(descriptor, index); 1648 } 1649 1650 if (descriptor instanceof PropertyDescriptor) { 1651 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1652 1653 boolean directToField = 1654 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; 1655 JetExpression r = getReceiverForSelector(expression); 1656 boolean isSuper = r instanceof JetSuperExpression; 1657 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1658 StackValue.Property iValue = 1659 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null); 1660 if (directToField) { 1661 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1662 } 1663 1664 //pop receiver via put(VOID_TYPE) in case of access to backing field that moved to outer class!!! 1665 receiver.put(!iValue.isPropertyWithBackingFieldInOuterClass() ? receiver.type : Type.VOID_TYPE, v); 1666 1667 return iValue; 1668 } 1669 1670 if (descriptor instanceof ClassDescriptor) { 1671 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 1672 if (classDescriptor.getKind() == ClassKind.OBJECT) { 1673 return StackValue.singleton(classDescriptor, typeMapper); 1674 } 1675 if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { 1676 DeclarationDescriptor enumClass = classDescriptor.getContainingDeclaration(); 1677 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor; 1678 Type type = typeMapper.mapType((ClassDescriptor) enumClass); 1679 return StackValue.field(type, type, descriptor.getName().asString(), true); 1680 } 1681 ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); 1682 assert classObjectDescriptor != null : "Class object is not found for " + descriptor; 1683 return StackValue.singleton(classObjectDescriptor, typeMapper); 1684 } 1685 1686 if (descriptor instanceof TypeParameterDescriptor) { 1687 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 1688 v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); 1689 JetType type = typeParameterDescriptor.getClassObjectType(); 1690 assert type != null; 1691 v.checkcast(asmType(type)); 1692 1693 return StackValue.onStack(OBJECT_TYPE); 1694 } 1695 1696 StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false); 1697 if (value != null) { 1698 1699 if (value instanceof StackValue.Composed) { 1700 StackValue.Composed composed = (StackValue.Composed) value; 1701 composed.prefix.put(OBJECT_TYPE, v); 1702 value = composed.suffix; 1703 } 1704 1705 if (value instanceof StackValue.FieldForSharedVar) { 1706 StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; 1707 Type sharedType = StackValue.sharedTypeForType(value.type); 1708 v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, 1709 sharedType.getDescriptor()); 1710 } 1711 1712 return value; 1713 } 1714 1715 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { 1716 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); 1717 assert scriptDescriptor != null; 1718 Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); 1719 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; 1720 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); 1721 StackValue script = StackValue.thisOrOuter(this, scriptClass, false); 1722 script.put(script.type, v); 1723 Type fieldType = typeMapper.mapType(valueParameterDescriptor); 1724 return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false); 1725 } 1726 1727 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1728 } 1729 1730 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 1731 if (descriptor instanceof VariableDescriptor) { 1732 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 1733 JetType outType = ((VariableDescriptor) descriptor).getType(); 1734 if (sharedVarType != null) { 1735 return StackValue.shared(index, asmType(outType)); 1736 } 1737 else { 1738 return StackValue.local(index, asmType(outType)); 1739 } 1740 } 1741 else { 1742 return StackValue.local(index, OBJECT_TYPE); 1743 } 1744 } 1745 1746 @Override 1747 public boolean lookupLocal(DeclarationDescriptor descriptor) { 1748 return lookupLocalIndex(descriptor) != -1; 1749 } 1750 1751 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 1752 return myFrameMap.getIndex(descriptor); 1753 } 1754 1755 @Nullable 1756 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 1757 PropertyGetterDescriptor getter = descriptor.getGetter(); 1758 if (getter != null) { 1759 Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, getter); 1760 return call != null ? call.getExplicitReceiver().getType() : null; 1761 } 1762 return null; 1763 } 1764 1765 @NotNull 1766 public StackValue.Property intermediateValueForProperty( 1767 @NotNull PropertyDescriptor propertyDescriptor, 1768 boolean forceField, 1769 @Nullable JetSuperExpression superExpression 1770 ) { 1771 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL); 1772 } 1773 1774 public StackValue.Property intermediateValueForProperty( 1775 @NotNull PropertyDescriptor propertyDescriptor, 1776 boolean forceField, 1777 @Nullable JetSuperExpression superExpression, 1778 @NotNull MethodKind methodKind 1779 ) { 1780 JetTypeMapper typeMapper = state.getTypeMapper(); 1781 1782 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 1783 1784 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 1785 boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; 1786 boolean isSuper = superExpression != null; 1787 boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context); 1788 boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context); 1789 1790 JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext()); 1791 boolean isDelegatedProperty = delegateType != null; 1792 1793 1794 CallableMethod callableGetter = null; 1795 CallableMethod callableSetter = null; 1796 1797 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; 1798 1799 CodegenContext backingFieldContext = context.getParentContext(); 1800 1801 if (isBackingFieldInAnotherClass && forceField) { 1802 //delegate call to classObject owner : OWNER 1803 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 1804 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 1805 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; 1806 if (!skipPropertyAccessors) { 1807 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType); 1808 } 1809 isStatic = true; 1810 } 1811 1812 if (!skipPropertyAccessors) { 1813 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) { 1814 callableGetter = null; 1815 } 1816 else { 1817 if (isSuper && !isInterface(containingDeclaration)) { 1818 ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context); 1819 CodegenContext c = context.findParentContextWithDescriptor(owner); 1820 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 1821 if (c != context.getParentContext()) { 1822 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); 1823 } 1824 } 1825 1826 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1827 1828 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 1829 if (getter != null) { 1830 callableGetter = typeMapper.mapToCallableMethod( 1831 getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1832 OwnerKind.IMPLEMENTATION); 1833 } 1834 } 1835 1836 if (propertyDescriptor.isVar()) { 1837 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 1838 if (setter != null) { 1839 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty)) { 1840 callableSetter = null; 1841 } 1842 else { 1843 callableSetter = typeMapper.mapToCallableMethod( 1844 setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1845 OwnerKind.IMPLEMENTATION); 1846 } 1847 } 1848 } 1849 } 1850 1851 Type owner; 1852 CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter; 1853 1854 propertyDescriptor = unwrapFakeOverride(propertyDescriptor); 1855 if (callableMethod == null) { 1856 owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, 1857 context.getContextKind(), isInsideModule); 1858 } 1859 else { 1860 owner = callableMethod.getOwner(); 1861 } 1862 1863 String name; 1864 if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 1865 assert backingFieldContext instanceof FieldOwnerContext : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext" ; 1866 name = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 1867 } else { 1868 name = JvmAbi.getDefaultPropertyName(propertyDescriptor.getName(), isDelegatedProperty, propertyDescriptor.getReceiverParameter() != null); 1869 } 1870 1871 return StackValue.property(propertyDescriptor, owner, 1872 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 1873 isStatic, name, callableGetter, callableSetter, state); 1874 1875 } 1876 1877 @Override 1878 public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) { 1879 JetExpression callee = expression.getCalleeExpression(); 1880 assert callee != null; 1881 1882 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); 1883 if (resolvedCall == null) { 1884 throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); 1885 } 1886 1887 DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); 1888 1889 if (!(funDescriptor instanceof FunctionDescriptor)) { 1890 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); 1891 } 1892 1893 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor); 1894 1895 if (funDescriptor instanceof ConstructorDescriptor) { 1896 return generateNewCall(expression, resolvedCall, receiver); 1897 } 1898 1899 Call call = bindingContext.get(CALL, expression.getCalleeExpression()); 1900 if (funDescriptor instanceof SimpleFunctionDescriptor) { 1901 SimpleFunctionDescriptor original = ((SimpleFunctionDescriptor) funDescriptor).getOriginal(); 1902 if (original instanceof SamConstructorDescriptor) { 1903 return invokeSamConstructor(expression, resolvedCall, ((SamConstructorDescriptor) original).getBaseForSynthesized()); 1904 } 1905 } 1906 1907 return invokeFunction(call, receiver, resolvedCall); 1908 } 1909 1910 private StackValue invokeSamConstructor( 1911 JetCallExpression expression, 1912 ResolvedCall<? extends CallableDescriptor> resolvedCall, 1913 JavaClassDescriptor samInterface 1914 ) { 1915 ResolvedValueArgument argument = resolvedCall.getValueArgumentsByIndex().get(0); 1916 if (!(argument instanceof ExpressionValueArgument)) { 1917 throw new IllegalStateException( 1918 "argument of SAM constructor is " + argument.getClass().getName() + " " + expression.getText()); 1919 } 1920 ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); 1921 assert valueArgument != null : "getValueArgument() is null for " + expression.getText(); 1922 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 1923 assert argumentExpression != null : "getArgumentExpression() is null for " + expression.getText(); 1924 1925 return genSamInterfaceValue(argumentExpression, samInterface, this); 1926 } 1927 1928 private StackValue genSamInterfaceValue( 1929 @NotNull JetExpression expression, 1930 @NotNull JavaClassDescriptor samInterface, 1931 @NotNull JetVisitor<StackValue, StackValue> visitor 1932 ) { 1933 if (expression instanceof JetFunctionLiteralExpression) { 1934 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samInterface); 1935 } 1936 else { 1937 Type asmType = state.getSamWrapperClasses().getSamWrapperClass(samInterface, (JetFile) expression.getContainingFile()); 1938 1939 v.anew(asmType); 1940 v.dup(); 1941 1942 Type functionType = typeMapper.mapType(samInterface.getFunctionTypeForSamInterface()); 1943 expression.accept(visitor, StackValue.none()).put(functionType, v); 1944 1945 Label ifNonNull = new Label(); 1946 Label afterAll = new Label(); 1947 1948 v.dup(); 1949 v.ifnonnull(ifNonNull); 1950 1951 // if null: pop function value and wrapper objects, put null 1952 v.pop(); 1953 v.pop2(); 1954 v.aconst(null); 1955 v.goTo(afterAll); 1956 1957 v.mark(ifNonNull); 1958 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType)); 1959 1960 v.mark(afterAll); 1961 return StackValue.onStack(asmType); 1962 } 1963 } 1964 1965 @NotNull 1966 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) { 1967 return context.accessiblePropertyDescriptor(propertyDescriptor); 1968 } 1969 1970 @NotNull 1971 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) { 1972 return context.accessibleFunctionDescriptor(fd); 1973 } 1974 1975 @NotNull 1976 public StackValue invokeFunction( 1977 Call call, 1978 StackValue receiver, 1979 ResolvedCall<? extends CallableDescriptor> resolvedCall 1980 ) { 1981 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1982 VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; 1983 ResolvedCallWithTrace<FunctionDescriptor> functionCall = variableAsFunctionResolvedCall.getFunctionCall(); 1984 return invokeFunction(call, receiver, functionCall); 1985 } 1986 1987 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 1988 boolean superCall = isSuperCall(call); 1989 1990 if (superCall && !isInterface(fd.getContainingDeclaration())) { 1991 JetSuperExpression expression = getSuperCallExpression(call); 1992 ClassDescriptor owner = getSuperCallLabelTarget(expression); 1993 CodegenContext c = context.findParentContextWithDescriptor(owner); 1994 assert c != null : "Couldn't find a context for a super-call: " + fd; 1995 if (c != context.getParentContext()) { 1996 fd = (FunctionDescriptor) c.getAccessor(fd); 1997 } 1998 } 1999 2000 fd = accessibleFunctionDescriptor(fd); 2001 2002 Callable callable = resolveToCallable(fd, superCall); 2003 if (callable instanceof CallableMethod) { 2004 CallableMethod callableMethod = (CallableMethod) callable; 2005 invokeMethodWithArguments(callableMethod, resolvedCall, call, receiver); 2006 2007 Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType(); 2008 return returnValueAsStackValue(fd, callReturnType); 2009 } 2010 else { 2011 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 2012 2013 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2014 List<JetExpression> args = new ArrayList<JetExpression>(); 2015 for (ValueArgument argument : call.getValueArguments()) { 2016 args.add(argument.getArgumentExpression()); 2017 } 2018 JetType type = resolvedCall.getResultingDescriptor().getReturnType(); 2019 assert type != null; 2020 Type callType = typeMapper.mapType(type); 2021 2022 Type exprType = asmTypeOrVoid(type); 2023 StackValue stackValue = intrinsic.generate(this, v, callType, call.getCallElement(), args, receiver, state); 2024 stackValue.put(exprType, v); 2025 return StackValue.onStack(exprType); 2026 } 2027 } 2028 2029 @Nullable 2030 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) { 2031 ReceiverValue explicitReceiver = call.getExplicitReceiver(); 2032 if (explicitReceiver instanceof ExpressionReceiver) { 2033 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression(); 2034 if (receiverExpression instanceof JetSuperExpression) { 2035 return (JetSuperExpression) receiverExpression; 2036 } 2037 } 2038 return null; 2039 } 2040 2041 private static boolean isSuperCall(@NotNull Call call) { 2042 return getSuperCallExpression(call) != null; 2043 } 2044 2045 // Find the first parent of the current context which corresponds to a subclass of a given class 2046 @NotNull 2047 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2048 CodegenContext c = context; 2049 while (true) { 2050 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2051 return c; 2052 } 2053 c = c.getParentContext(); 2054 assert c != null; 2055 } 2056 } 2057 2058 @NotNull 2059 private StackValue returnValueAsStackValue(FunctionDescriptor fd, Type callReturnType) { 2060 if (callReturnType != Type.VOID_TYPE) { 2061 JetType type = fd.getReturnType(); 2062 assert type != null; 2063 Type retType = typeMapper.mapReturnType(type); 2064 StackValue.coerce(callReturnType, retType, v); 2065 return StackValue.onStack(retType); 2066 } 2067 return StackValue.none(); 2068 } 2069 2070 @NotNull 2071 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) { 2072 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2073 if (intrinsic != null) { 2074 return intrinsic; 2075 } 2076 2077 return resolveToCallableMethod(fd, superCall, context); 2078 } 2079 2080 @NotNull 2081 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) { 2082 if (isCallAsFunctionObject(fd)) { 2083 return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd)); 2084 } 2085 else { 2086 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd); 2087 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, 2088 isCallInsideSameClassAsDeclared(fd, context), 2089 isCallInsideSameModuleAsDeclared(fd, context), 2090 OwnerKind.IMPLEMENTATION); 2091 } 2092 } 2093 2094 private boolean isCallAsFunctionObject(FunctionDescriptor fd) { 2095 if (fd instanceof ExpressionAsFunctionDescriptor) { 2096 JetExpression deparenthesize = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) fd).getExpression()); 2097 return !(deparenthesize instanceof JetCallableReferenceExpression || deparenthesize instanceof JetFunctionLiteralExpression); 2098 } 2099 return false; 2100 } 2101 2102 2103 public void invokeMethodWithArguments( 2104 @NotNull CallableMethod callableMethod, 2105 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 2106 @Nullable Call callToGenerateCallee, 2107 @NotNull StackValue receiver 2108 ) { 2109 Type calleeType = callableMethod.getGenerateCalleeType(); 2110 if (calleeType != null) { 2111 assert !callableMethod.isNeedsThis(); 2112 assert callToGenerateCallee != null : "Call can't be null when generating callee: " + resolvedCall.getResultingDescriptor(); 2113 gen(callToGenerateCallee.getCalleeExpression(), calleeType); 2114 } 2115 2116 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2117 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2118 } 2119 2120 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2121 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2122 receiver.put(receiver.type, v); 2123 } 2124 2125 pushArgumentsAndInvoke(resolvedCall, callableMethod); 2126 } 2127 2128 private void pushArgumentsAndInvoke(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableMethod callable) { 2129 int mask = pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); 2130 if (mask == 0) { 2131 callable.invokeWithNotNullAssertion(v, state, resolvedCall); 2132 } 2133 else { 2134 callable.invokeDefaultWithNotNullAssertion(v, state, resolvedCall, mask); 2135 } 2136 } 2137 2138 private void genThisAndReceiverFromResolvedCall( 2139 StackValue receiver, 2140 ResolvedCall<? extends CallableDescriptor> resolvedCall, 2141 CallableMethod callableMethod 2142 ) { 2143 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2144 receiver.put(receiver.type, v); 2145 } 2146 2147 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) { 2148 if (descriptor instanceof ClassReceiver) { 2149 Type exprType = asmType(descriptor.getType()); 2150 ClassReceiver classReceiver = (ClassReceiver) descriptor; 2151 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor(); 2152 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { 2153 if (context.getContextDescriptor() instanceof FunctionDescriptor && 2154 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) { 2155 v.load(0, OBJECT_TYPE); 2156 } 2157 else { 2158 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper); 2159 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor()); 2160 } 2161 StackValue.onStack(exprType).put(type, v); 2162 } 2163 else { 2164 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v); 2165 } 2166 } 2167 else if (descriptor instanceof ScriptReceiver) { 2168 generateScript((ScriptReceiver) descriptor); 2169 } 2170 else if (descriptor instanceof ExtensionReceiver) { 2171 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; 2172 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v); 2173 } 2174 else if (descriptor instanceof ExpressionReceiver) { 2175 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; 2176 JetExpression expr = expressionReceiver.getExpression(); 2177 gen(expr, type); 2178 } 2179 else if (descriptor instanceof AutoCastReceiver) { 2180 AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor; 2181 Type originalType = asmType(autoCastReceiver.getOriginal().getType()); 2182 generateFromResolvedCall(autoCastReceiver.getOriginal(), originalType); 2183 StackValue.onStack(originalType).put(type, v); 2184 } 2185 else { 2186 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor); 2187 } 2188 } 2189 2190 @Nullable 2191 private static JetExpression getReceiverForSelector(PsiElement expression) { 2192 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2193 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2194 return parent.getReceiverExpression(); 2195 } 2196 return null; 2197 } 2198 2199 private StackValue generateReceiver(DeclarationDescriptor provided) { 2200 if (context.getCallableDescriptorWithReceiver() == provided) { 2201 StackValue result = context.getReceiverExpression(typeMapper); 2202 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2203 } 2204 2205 StackValue result = context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false); 2206 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2207 } 2208 2209 private void generateScript(@NotNull ScriptReceiver receiver) { 2210 CodegenContext cur = context; 2211 StackValue result = StackValue.local(0, OBJECT_TYPE); 2212 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2213 while (cur != null) { 2214 if (!inStartConstructorContext) { 2215 cur = getNotNullParentContextForMethod(cur); 2216 } 2217 2218 if (cur instanceof ScriptContext) { 2219 ScriptContext scriptContext = (ScriptContext) cur; 2220 2221 Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); 2222 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2223 result.put(currentScriptType, v); 2224 } 2225 else { 2226 Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor()); 2227 String fieldName = getParentScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); 2228 result.put(currentScriptType, v); 2229 StackValue.field(classType, currentScriptType, fieldName, false).put(classType, v); 2230 } 2231 return; 2232 } 2233 2234 result = cur.getOuterExpression(result, false); 2235 2236 if (inStartConstructorContext) { 2237 cur = getNotNullParentContextForMethod(cur); 2238 inStartConstructorContext = false; 2239 } 2240 2241 cur = cur.getParentContext(); 2242 } 2243 2244 throw new UnsupportedOperationException(); 2245 } 2246 2247 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2248 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2249 if (isSingleton) { 2250 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) { 2251 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2252 } 2253 else { 2254 return StackValue.singleton(calleeContainingClass, typeMapper); 2255 } 2256 } 2257 2258 CodegenContext cur = context; 2259 Type type = asmType(calleeContainingClass.getDefaultType()); 2260 StackValue result = StackValue.local(0, type); 2261 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2262 while (cur != null) { 2263 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2264 if (!isSuper && thisDescriptor.equals(calleeContainingClass) 2265 || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2266 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2267 } 2268 2269 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2270 if (inStartConstructorContext) { 2271 result = cur.getOuterExpression(result, false); 2272 cur = getNotNullParentContextForMethod(cur); 2273 inStartConstructorContext = false; 2274 } 2275 else { 2276 cur = getNotNullParentContextForMethod(cur); 2277 result = cur.getOuterExpression(result, false); 2278 } 2279 2280 cur = cur.getParentContext(); 2281 } 2282 2283 throw new UnsupportedOperationException(); 2284 } 2285 2286 @NotNull 2287 private CodegenContext getNotNullParentContextForMethod(@NotNull CodegenContext cur) { 2288 if (cur instanceof MethodContext) { 2289 cur = cur.getParentContext(); 2290 } 2291 assert cur != null; 2292 return cur; 2293 } 2294 2295 2296 private static boolean isReceiver(PsiElement expression) { 2297 PsiElement parent = expression.getParent(); 2298 if (parent instanceof JetQualifiedExpression) { 2299 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2300 return expression == receiverExpression; 2301 } 2302 return false; 2303 } 2304 2305 private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes) { 2306 @SuppressWarnings("unchecked") 2307 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2308 CallableDescriptor fd = resolvedCall.getResultingDescriptor(); 2309 2310 if (fd.getValueParameters().size() != valueArguments.size()) { 2311 throw new IllegalStateException(); 2312 } 2313 2314 int mask = 0; 2315 2316 for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) { 2317 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); 2318 Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); 2319 if (resolvedValueArgument instanceof ExpressionValueArgument) { 2320 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); 2321 assert valueArgument != null; 2322 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 2323 assert argumentExpression != null : valueArgument.asElement().getText(); 2324 2325 gen(argumentExpression, parameterType); 2326 } 2327 else if (resolvedValueArgument instanceof DefaultValueArgument) { 2328 pushDefaultValueOnStack(parameterType, v); 2329 mask |= (1 << valueParameter.getIndex()); 2330 } 2331 else if (resolvedValueArgument instanceof VarargValueArgument) { 2332 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; 2333 genVarargs(valueParameter, valueArgument); 2334 } 2335 else { 2336 throw new UnsupportedOperationException(); 2337 } 2338 } 2339 return mask; 2340 } 2341 2342 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) { 2343 JetType outType = valueParameterDescriptor.getType(); 2344 2345 Type type = asmType(outType); 2346 assert type.getSort() == Type.ARRAY; 2347 Type elementType = correctElementType(type); 2348 List<ValueArgument> arguments = valueArgument.getArguments(); 2349 int size = arguments.size(); 2350 2351 boolean hasSpread = false; 2352 for (int i = 0; i != size; ++i) { 2353 if (arguments.get(i).getSpreadElement() != null) { 2354 hasSpread = true; 2355 break; 2356 } 2357 } 2358 2359 if (hasSpread) { 2360 if (size == 1) { 2361 gen(arguments.get(0).getArgumentExpression(), type); 2362 } 2363 else { 2364 String owner = "jet/runtime/Intrinsics$SpreadBuilder"; 2365 v.anew(Type.getObjectType(owner)); 2366 v.dup(); 2367 v.invokespecial(owner, "<init>", "()V"); 2368 for (int i = 0; i != size; ++i) { 2369 v.dup(); 2370 ValueArgument argument = arguments.get(i); 2371 if (argument.getSpreadElement() != null) { 2372 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2373 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V"); 2374 } 2375 else { 2376 gen(argument.getArgumentExpression(), elementType); 2377 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z"); 2378 v.pop(); 2379 } 2380 } 2381 v.dup(); 2382 v.invokevirtual(owner, "size", "()I"); 2383 v.newarray(elementType); 2384 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); 2385 v.checkcast(type); 2386 } 2387 } 2388 else { 2389 v.iconst(arguments.size()); 2390 v.newarray(elementType); 2391 for (int i = 0; i != size; ++i) { 2392 v.dup(); 2393 v.iconst(i); 2394 gen(arguments.get(i).getArgumentExpression(), elementType); 2395 StackValue.arrayElement(elementType, false).store(elementType, v); 2396 } 2397 } 2398 } 2399 2400 public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) { 2401 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2402 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); 2403 if (resolvedCall != null) { 2404 return pushMethodArguments(resolvedCall, valueParameterTypes); 2405 } 2406 else { 2407 List<? extends ValueArgument> args = expression.getValueArguments(); 2408 for (int i = 0, argsSize = args.size(); i < argsSize; i++) { 2409 ValueArgument arg = args.get(i); 2410 gen(arg.getArgumentExpression(), valueParameterTypes.get(i)); 2411 } 2412 return 0; 2413 } 2414 } 2415 2416 @NotNull 2417 public Type expressionType(JetExpression expr) { 2418 return typeMapper.expressionType(expr); 2419 } 2420 2421 public int indexOfLocal(JetReferenceExpression lhs) { 2422 DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs); 2423 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2424 return -1; 2425 } 2426 return lookupLocalIndex(declarationDescriptor); 2427 } 2428 2429 @Override 2430 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) { 2431 // TODO: properties 2432 final FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2433 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText(); 2434 2435 final ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, expression.getCallableReference()); 2436 assert resolvedCall != null : "Callable reference is not resolved: " + functionDescriptor + " " + expression.getText(); 2437 2438 JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression); 2439 assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText(); 2440 ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType); 2441 assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType; 2442 2443 Type closureSuperClass = typeMapper.mapType(kFunctionImpl); 2444 2445 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context, this, 2446 new FunctionGenerationStrategy.CodegenBased<CallableDescriptor>(state, functionDescriptor) { 2447 2448 @NotNull 2449 @Override 2450 public ExpressionCodegen initializeExpressionCodegen( 2451 JvmMethodSignature signature, MethodContext context, MethodVisitor mv, 2452 Type returnType, 2453 MemberCodegen parentCodegen 2454 ) { 2455 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2456 JetType returnJetType = referencedFunction.getReturnType(); 2457 assert returnJetType != null : "Return type can't be null: " + referencedFunction; 2458 2459 return super.initializeExpressionCodegen(signature, context, 2460 mv, typeMapper.mapReturnType(returnJetType), parentCodegen); 2461 } 2462 2463 @Override 2464 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2465 /* 2466 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2467 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2468 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2469 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2470 every argument boils down to calling LOAD with the corresponding index 2471 */ 2472 2473 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2474 2475 JetCallExpression fakeExpression = constructFakeFunctionCall(referencedFunction); 2476 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2477 2478 final ReceiverValue receiverValue = computeAndSaveReceiver(signature, codegen); 2479 computeAndSaveArguments(codegen.myFrameMap, fakeArguments, codegen); 2480 2481 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2482 @NotNull 2483 @Override 2484 public ReceiverValue getReceiverArgument() { 2485 return resolvedCall.getExplicitReceiverKind() == RECEIVER_ARGUMENT ? receiverValue : NO_RECEIVER; 2486 } 2487 2488 @NotNull 2489 @Override 2490 public ReceiverValue getThisObject() { 2491 return resolvedCall.getExplicitReceiverKind() == THIS_OBJECT ? receiverValue : NO_RECEIVER; 2492 } 2493 2494 @NotNull 2495 @Override 2496 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2497 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2498 for (ValueArgument argument : fakeArguments) { 2499 result.add(new ExpressionValueArgument(argument)); 2500 } 2501 return result; 2502 } 2503 }; 2504 2505 StackValue result; 2506 Type returnType = codegen.returnType; 2507 if (referencedFunction instanceof ConstructorDescriptor) { 2508 if (returnType.getSort() == Type.ARRAY) { 2509 JetType returnJetType = referencedFunction.getReturnType(); 2510 assert returnJetType != null; 2511 codegen.generateNewArray(fakeExpression, returnJetType); 2512 result = StackValue.onStack(returnType); 2513 } 2514 else { 2515 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType); 2516 } 2517 } 2518 else { 2519 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2520 result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall); 2521 } 2522 2523 InstructionAdapter v = codegen.v; 2524 result.put(returnType, v); 2525 v.areturn(returnType); 2526 } 2527 2528 @NotNull 2529 private JetCallExpression constructFakeFunctionCall(@NotNull CallableDescriptor referencedFunction) { 2530 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2531 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); 2532 iterator.hasNext(); ) { 2533 ValueParameterDescriptor descriptor = iterator.next(); 2534 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2535 if (iterator.hasNext()) { 2536 fakeFunctionCall.append(", "); 2537 } 2538 } 2539 fakeFunctionCall.append(")"); 2540 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString()); 2541 } 2542 2543 private void computeAndSaveArguments( 2544 @NotNull FrameMap frameMap, 2545 @NotNull List<? extends ValueArgument> fakeArguments, 2546 @NotNull ExpressionCodegen codegen 2547 ) { 2548 for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) { 2549 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2550 Type type = typeMapper.mapType(parameter); 2551 int localIndex = frameMap.getIndex(parameter); 2552 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2553 } 2554 } 2555 2556 @NotNull 2557 private ReceiverValue computeAndSaveReceiver( 2558 @NotNull JvmMethodSignature signature, 2559 @NotNull ExpressionCodegen codegen 2560 ) { 2561 CallableDescriptor referencedFunction = resolvedCall.getCandidateDescriptor(); 2562 2563 ReceiverParameterDescriptor receiverParameter = referencedFunction.getReceiverParameter(); 2564 ReceiverParameterDescriptor expectedThisObject = referencedFunction.getExpectedThisObject(); 2565 assert receiverParameter == null || expectedThisObject == null : 2566 "Extensions in classes can't be referenced via callable reference expressions: " + referencedFunction; 2567 2568 ReceiverParameterDescriptor receiver = receiverParameter != null ? receiverParameter : expectedThisObject; 2569 2570 if (receiver == null) { 2571 return NO_RECEIVER; 2572 } 2573 2574 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), 2575 "callableReferenceFakeReceiver"); 2576 2577 Type firstParameterType = signature.getAsmMethod().getArgumentTypes()[0]; 2578 // 0 is this (the closure class), 1 is the method's first parameter 2579 codegen.tempVariables.put(receiverExpression, StackValue.local(1, firstParameterType)); 2580 2581 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2582 } 2583 }, 2584 getParentCodegen()); 2585 2586 closureCodegen.gen(); 2587 2588 return closureCodegen.putInstanceOnStack(v, this); 2589 } 2590 2591 @Override 2592 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) { 2593 StackValue receiverValue = StackValue.none(); 2594 return genQualified(receiverValue, expression.getSelectorExpression()); 2595 } 2596 2597 @Override 2598 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue receiver) { 2599 JetExpression expr = expression.getReceiverExpression(); 2600 Type receiverType = expressionType(expr); 2601 gen(expr, receiverType); 2602 if (isPrimitive(receiverType)) { 2603 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2604 Type type = boxType(propValue.type); 2605 propValue.put(type, v); 2606 2607 return StackValue.onStack(type); 2608 } 2609 else { 2610 Label ifnull = new Label(); 2611 Label end = new Label(); 2612 v.dup(); 2613 v.ifnull(ifnull); 2614 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2615 Type type = boxType(propValue.type); 2616 propValue.put(type, v); 2617 v.goTo(end); 2618 2619 v.mark(ifnull); 2620 v.pop(); 2621 if (!type.equals(Type.VOID_TYPE)) { 2622 v.aconst(null); 2623 } 2624 v.mark(end); 2625 2626 return StackValue.onStack(type); 2627 } 2628 } 2629 2630 @Override 2631 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) { 2632 JetSimpleNameExpression reference = expression.getOperationReference(); 2633 IElementType opToken = reference.getReferencedNameElementType(); 2634 if (opToken == JetTokens.EQ) { 2635 return generateAssignmentExpression(expression); 2636 } 2637 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2638 return generateAugmentedAssignment(expression); 2639 } 2640 else if (opToken == JetTokens.ANDAND) { 2641 return generateBooleanAnd(expression); 2642 } 2643 else if (opToken == JetTokens.OROR) { 2644 return generateBooleanOr(expression); 2645 } 2646 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2647 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2648 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2649 } 2650 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2651 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2652 return generateComparison(expression, receiver); 2653 } 2654 else if (opToken == JetTokens.ELVIS) { 2655 return generateElvis(expression); 2656 } 2657 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 2658 return generateIn(expression); 2659 } 2660 else { 2661 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference); 2662 Call call = bindingContext.get(BindingContext.CALL, reference); 2663 2664 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, reference); 2665 assert op instanceof FunctionDescriptor : String.valueOf(op); 2666 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2667 if (callable instanceof IntrinsicMethod) { 2668 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2669 return intrinsic.generate(this, v, expressionType(expression), expression, 2670 Arrays.asList(expression.getLeft(), expression.getRight()), receiver, state); 2671 } 2672 else { 2673 return invokeFunction(call, receiver, resolvedCall); 2674 } 2675 } 2676 } 2677 2678 private StackValue generateIn(JetBinaryExpression expression) { 2679 boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN; 2680 if (isIntRangeExpr(expression.getRight())) { 2681 StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this); 2682 JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getRight(); 2683 getInIntRange(leftValue, rangeExpression, inverted); 2684 } 2685 else { 2686 invokeFunctionByReference(expression.getOperationReference()); 2687 if (inverted) { 2688 genInvertBoolean(v); 2689 } 2690 } 2691 return StackValue.onStack(Type.BOOLEAN_TYPE); 2692 } 2693 2694 private void getInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression, boolean inverted) { 2695 v.iconst(1); 2696 // 1 2697 leftValue.put(Type.INT_TYPE, v); 2698 // 1 l 2699 v.dup2(); 2700 // 1 l 1 l 2701 2702 //noinspection ConstantConditions 2703 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2704 // 1 l 1 l r 2705 Label lok = new Label(); 2706 v.ificmpge(lok); 2707 // 1 l 1 2708 v.pop(); 2709 v.iconst(0); 2710 v.mark(lok); 2711 // 1 l c 2712 v.dupX2(); 2713 // c 1 l c 2714 v.pop(); 2715 // c 1 l 2716 2717 gen(rangeExpression.getRight(), Type.INT_TYPE); 2718 // c 1 l r 2719 Label rok = new Label(); 2720 v.ificmple(rok); 2721 // c 1 2722 v.pop(); 2723 v.iconst(0); 2724 v.mark(rok); 2725 // c c 2726 2727 v.and(Type.INT_TYPE); 2728 if (inverted) { 2729 genInvertBoolean(v); 2730 } 2731 } 2732 2733 private StackValue generateBooleanAnd(JetBinaryExpression expression) { 2734 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2735 Label ifFalse = new Label(); 2736 v.ifeq(ifFalse); 2737 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2738 Label end = new Label(); 2739 v.goTo(end); 2740 v.mark(ifFalse); 2741 v.iconst(0); 2742 v.mark(end); 2743 return StackValue.onStack(Type.BOOLEAN_TYPE); 2744 } 2745 2746 private StackValue generateBooleanOr(JetBinaryExpression expression) { 2747 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2748 Label ifTrue = new Label(); 2749 v.ifne(ifTrue); 2750 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2751 Label end = new Label(); 2752 v.goTo(end); 2753 v.mark(ifTrue); 2754 v.iconst(1); 2755 v.mark(end); 2756 return StackValue.onStack(Type.BOOLEAN_TYPE); 2757 } 2758 2759 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 2760 Type leftType = expressionType(left); 2761 Type rightType = expressionType(right); 2762 2763 if (JetPsiUtil.isNullConstant(left)) { 2764 return genCmpWithNull(right, rightType, opToken); 2765 } 2766 2767 if (JetPsiUtil.isNullConstant(right)) { 2768 return genCmpWithNull(left, leftType, opToken); 2769 } 2770 2771 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2772 return genCmpWithZero(right, rightType, opToken); 2773 } 2774 2775 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2776 return genCmpWithZero(left, leftType, opToken); 2777 } 2778 2779 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2780 leftType = boxType(leftType); 2781 gen(left, leftType); 2782 rightType = boxType(rightType); 2783 gen(right, rightType); 2784 } 2785 else { 2786 gen(left, leftType); 2787 gen(right, rightType); 2788 } 2789 2790 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType); 2791 } 2792 2793 private boolean isIntZero(JetExpression expr, Type exprType) { 2794 CompileTimeConstant<?> exprValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr); 2795 return isIntPrimitive(exprType) && exprValue != null && exprValue.getValue().equals(0); 2796 } 2797 2798 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) { 2799 v.iconst(1); 2800 gen(exp, expType); 2801 Label ok = new Label(); 2802 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2803 v.ifeq(ok); 2804 } 2805 else { 2806 v.ifne(ok); 2807 } 2808 v.pop(); 2809 v.iconst(0); 2810 v.mark(ok); 2811 return StackValue.onStack(Type.BOOLEAN_TYPE); 2812 } 2813 2814 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { 2815 v.iconst(1); 2816 gen(exp, boxType(expType)); 2817 Label ok = new Label(); 2818 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2819 v.ifnull(ok); 2820 } 2821 else { 2822 v.ifnonnull(ok); 2823 } 2824 v.pop(); 2825 v.iconst(0); 2826 v.mark(ok); 2827 return StackValue.onStack(Type.BOOLEAN_TYPE); 2828 } 2829 2830 private StackValue generateElvis(JetBinaryExpression expression) { 2831 Type exprType = expressionType(expression); 2832 Type leftType = expressionType(expression.getLeft()); 2833 2834 gen(expression.getLeft(), leftType); 2835 2836 if (isPrimitive(leftType)) { 2837 return StackValue.onStack(leftType); 2838 } 2839 2840 v.dup(); 2841 Label ifNull = new Label(); 2842 v.ifnull(ifNull); 2843 StackValue.onStack(leftType).put(exprType, v); 2844 Label end = new Label(); 2845 v.goTo(end); 2846 v.mark(ifNull); 2847 v.pop(); 2848 gen(expression.getRight(), exprType); 2849 v.mark(end); 2850 2851 return StackValue.onStack(exprType); 2852 } 2853 2854 private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) { 2855 DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2856 assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target; 2857 FunctionDescriptor descriptor = (FunctionDescriptor) target; 2858 2859 JetExpression left = expression.getLeft(); 2860 JetExpression right = expression.getRight(); 2861 Callable callable = resolveToCallable(descriptor, false); 2862 2863 Type type; 2864 if (callable instanceof IntrinsicMethod) { 2865 // Compare two primitive values 2866 type = comparisonOperandType(expressionType(left), expressionType(right)); 2867 StackValue recv = gen(left); 2868 recv.put(type, v); 2869 gen(right, type); 2870 } 2871 else { 2872 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2873 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2874 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); 2875 StackValue result = invokeFunction(call, receiver, resolvedCall); 2876 type = Type.INT_TYPE; 2877 result.put(type, v); 2878 v.iconst(0); 2879 } 2880 return StackValue.cmp(expression.getOperationToken(), type); 2881 } 2882 2883 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 2884 StackValue stackValue = gen(expression.getLeft()); 2885 JetExpression right = expression.getRight(); 2886 assert right != null : expression.getText(); 2887 gen(right, stackValue.type); 2888 stackValue.store(stackValue.type, v); 2889 return StackValue.none(); 2890 } 2891 2892 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 2893 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2894 assert op instanceof FunctionDescriptor : String.valueOf(op); 2895 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2896 JetExpression lhs = expression.getLeft(); 2897 2898 // if (lhs instanceof JetArrayAccessExpression) { 2899 // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; 2900 // if (arrayAccessExpression.getIndexExpressions().size() != 1) { 2901 // throw new UnsupportedOperationException("Augmented assignment with multi-index"); 2902 // } 2903 // } 2904 2905 Type lhsType = expressionType(lhs); 2906 //noinspection ConstantConditions 2907 if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { 2908 if (callable instanceof IntrinsicMethod) { 2909 StackValue value = gen(lhs); // receiver 2910 value.dupReceiver(v); // receiver receiver 2911 value.put(lhsType, v); // receiver lhs 2912 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2913 //noinspection NullableProblems 2914 JetExpression right = expression.getRight(); 2915 assert right != null; 2916 StackValue stackValue = intrinsic.generate(this, v, lhsType, expression, 2917 Arrays.asList(right), 2918 StackValue.onStack(lhsType), state); 2919 value.store(stackValue.type, v); 2920 } 2921 else { 2922 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); 2923 } 2924 } 2925 else { 2926 JetType type = ((FunctionDescriptor) op).getReturnType(); 2927 assert type != null; 2928 boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType()); 2929 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue); 2930 } 2931 2932 return StackValue.none(); 2933 } 2934 2935 private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) { 2936 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2937 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2938 assert resolvedCall != null; 2939 2940 StackValue value = gen(expression.getLeft()); 2941 if (keepReturnValue) { 2942 value.dupReceiver(v); 2943 } 2944 value.put(lhsType, v); 2945 StackValue receiver = StackValue.onStack(lhsType); 2946 2947 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2948 receiver = StackValue.receiver(resolvedCall, receiver, this, callable); 2949 receiver.put(receiver.type, v); 2950 } 2951 2952 pushArgumentsAndInvoke(resolvedCall, callable); 2953 2954 if (keepReturnValue) { 2955 value.store(callable.getReturnType(), v); 2956 } 2957 } 2958 2959 public void invokeAppend(JetExpression expr) { 2960 if (expr instanceof JetBinaryExpression) { 2961 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 2962 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 2963 JetExpression left = binaryExpression.getLeft(); 2964 JetExpression right = binaryExpression.getRight(); 2965 Type leftType = expressionType(left); 2966 Type rightType = expressionType(right); 2967 2968 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) { 2969 invokeAppend(left); 2970 invokeAppend(right); 2971 return; 2972 } 2973 } 2974 } 2975 Type exprType = expressionType(expr); 2976 gen(expr, exprType); 2977 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 2978 } 2979 2980 @Nullable 2981 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 2982 if (expression.getParent() instanceof JetPrefixExpression) { 2983 JetPrefixExpression parent = (JetPrefixExpression) expression.getParent(); 2984 JetSimpleNameExpression operationSign = parent.getOperationReference(); 2985 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2986 return operationSign; 2987 } 2988 } 2989 return null; 2990 } 2991 2992 @Override 2993 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) { 2994 JetSimpleNameExpression operationSign = expression.getOperationReference(); 2995 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2996 return genQualified(receiver, expression.getBaseExpression()); 2997 } 2998 2999 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3000 assert op instanceof FunctionDescriptor : String.valueOf(op); 3001 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3002 if (callable instanceof IntrinsicMethod) { 3003 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 3004 //noinspection ConstantConditions 3005 return intrinsic.generate(this, v, expressionType(expression), expression, 3006 Arrays.asList(expression.getBaseExpression()), receiver, state); 3007 } 3008 else { 3009 DeclarationDescriptor cls = op.getContainingDeclaration(); 3010 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3011 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3012 assert resolvedCall != null; 3013 3014 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) { 3015 Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); 3016 return invokeFunction(call, receiver, resolvedCall); 3017 } 3018 else { 3019 CallableMethod callableMethod = (CallableMethod) callable; 3020 3021 StackValue value = gen(expression.getBaseExpression()); 3022 value.dupReceiver(v); 3023 value.dupReceiver(v); 3024 3025 Type type = expressionType(expression.getBaseExpression()); 3026 value.put(type, v); 3027 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3028 3029 value.store(callableMethod.getReturnType(), v); 3030 value.put(type, v); 3031 return StackValue.onStack(type); 3032 } 3033 } 3034 } 3035 3036 @Override 3037 public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) { 3038 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 3039 StackValue base = genQualified(receiver, expression.getBaseExpression()); 3040 if (isPrimitive(base.type)) { 3041 return base; 3042 } 3043 base.put(base.type, v); 3044 v.dup(); 3045 Label ok = new Label(); 3046 v.ifnonnull(ok); 3047 v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V"); 3048 v.mark(ok); 3049 return StackValue.onStack(base.type); 3050 } 3051 3052 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3053 if (!(op instanceof FunctionDescriptor)) { 3054 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op); 3055 } 3056 3057 Type asmType = expressionType(expression); 3058 DeclarationDescriptor cls = op.getContainingDeclaration(); 3059 3060 int increment; 3061 if (op.getName().asString().equals("inc")) { 3062 increment = 1; 3063 } 3064 else if (op.getName().asString().equals("dec")) { 3065 increment = -1; 3066 } 3067 else { 3068 throw new UnsupportedOperationException("Unsupported postfix operation: " + op); 3069 } 3070 3071 boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 3072 if (isPrimitiveNumberClassDescriptor) { 3073 JetExpression operand = expression.getBaseExpression(); 3074 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { 3075 int index = indexOfLocal((JetReferenceExpression) operand); 3076 if (index >= 0) { 3077 return StackValue.postIncrement(index, increment); 3078 } 3079 } 3080 } 3081 3082 StackValue value = gen(expression.getBaseExpression()); 3083 value.dupReceiver(v); 3084 3085 Type type = expressionType(expression.getBaseExpression()); 3086 value.put(type, v); // old value 3087 3088 pushReceiverAndValueViaDup(value, type); // receiver and new value 3089 3090 Type storeType; 3091 if (isPrimitiveNumberClassDescriptor) { 3092 genIncrement(asmType, increment, v); 3093 storeType = type; 3094 } 3095 else { 3096 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3097 assert resolvedCall != null; 3098 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3099 CallableMethod callableMethod = (CallableMethod) callable; 3100 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3101 storeType = callableMethod.getReturnType(); 3102 } 3103 3104 value.store(storeType, v); 3105 return StackValue.onStack(asmType); // old value 3106 } 3107 3108 private void pushReceiverAndValueViaDup(StackValue value, Type type) { 3109 switch (value.receiverSize()) { 3110 case 0: 3111 dup(v, type); 3112 break; 3113 3114 case 1: 3115 if (type.getSize() == 2) { 3116 v.dup2X1(); 3117 } 3118 else { 3119 v.dupX1(); 3120 } 3121 break; 3122 3123 case 2: 3124 if (type.getSize() == 2) { 3125 v.dup2X2(); 3126 } 3127 else { 3128 v.dupX2(); 3129 } 3130 break; 3131 3132 case -1: 3133 throw new UnsupportedOperationException(); 3134 } 3135 } 3136 3137 @Override 3138 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) { 3139 final JetExpression initializer = property.getInitializer(); 3140 if (initializer == null) { 3141 return StackValue.none(); 3142 } 3143 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() { 3144 @Override 3145 public Void fun(VariableDescriptor descriptor) { 3146 Type varType = asmType(descriptor.getType()); 3147 gen(initializer, varType); 3148 return null; 3149 } 3150 }); 3151 return StackValue.none(); 3152 } 3153 3154 @Override 3155 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) { 3156 JetExpression initializer = multiDeclaration.getInitializer(); 3157 if (initializer == null) return StackValue.none(); 3158 3159 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3160 assert initializerType != null; 3161 3162 Type initializerAsmType = asmType(initializerType); 3163 3164 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3165 3166 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3167 3168 gen(initializer, initializerAsmType); 3169 v.store(tempVarIndex, initializerAsmType); 3170 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3171 3172 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3173 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() { 3174 @Override 3175 public Void fun(VariableDescriptor descriptor) { 3176 ResolvedCall<FunctionDescriptor> resolvedCall = 3177 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration); 3178 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3179 Call call = makeFakeCall(initializerAsReceiver); 3180 invokeFunction(call, local, resolvedCall); 3181 return null; 3182 } 3183 }); 3184 } 3185 3186 if(initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3187 v.aconst(null); 3188 v.store(tempVarIndex, initializerAsmType); 3189 } 3190 myFrameMap.leaveTemp(initializerAsmType); 3191 3192 return StackValue.none(); 3193 } 3194 3195 private void initializeLocalVariable( 3196 @NotNull JetVariableDeclaration variableDeclaration, 3197 @NotNull Function<VariableDescriptor, Void> generateInitializer 3198 ) { 3199 3200 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 3201 3202 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3203 return; 3204 } 3205 int index = lookupLocalIndex(variableDescriptor); 3206 3207 if (index < 0) { 3208 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3209 } 3210 3211 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3212 assert variableDescriptor != null; 3213 3214 Type varType = asmType(variableDescriptor.getType()); 3215 3216 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3217 generateInitializer.fun(variableDescriptor); 3218 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3219 assert scriptPsi != null; 3220 Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi); 3221 v.putfield(scriptClassType.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); 3222 } 3223 else if (sharedVarType == null) { 3224 generateInitializer.fun(variableDescriptor); 3225 v.store(index, varType); 3226 } 3227 else { 3228 v.load(index, OBJECT_TYPE); 3229 generateInitializer.fun(variableDescriptor); 3230 v.putfield(sharedVarType.getInternalName(), "ref", 3231 sharedVarType == JET_SHARED_VAR_TYPE ? "Ljava/lang/Object;" : varType.getDescriptor()); 3232 } 3233 } 3234 3235 @NotNull 3236 private StackValue generateNewCall( 3237 @NotNull JetCallExpression expression, 3238 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3239 @NotNull StackValue receiver 3240 ) { 3241 Type type = expressionType(expression); 3242 if (type.getSort() == Type.ARRAY) { 3243 generateNewArray(expression); 3244 return StackValue.onStack(type); 3245 } 3246 3247 return generateConstructorCall(resolvedCall, receiver, type); 3248 } 3249 3250 @NotNull 3251 private StackValue generateConstructorCall( 3252 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3253 @NotNull StackValue receiver, 3254 @NotNull Type type 3255 ) { 3256 v.anew(type); 3257 v.dup(); 3258 3259 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 3260 receiver.put(receiver.type, v); 3261 3262 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3263 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); 3264 3265 ClassDescriptor descriptor = getExpectedThisObjectForConstructorCall(constructorDescriptor, closure); 3266 if (receiver.type.getSort() != Type.VOID && descriptor == null) { 3267 v.pop(); 3268 } 3269 3270 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument() 3271 //so we need generate closure on stack 3272 //See StackValue.receiver for more info 3273 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()); 3274 3275 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor); 3276 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); 3277 invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 3278 3279 return StackValue.onStack(type); 3280 } 3281 3282 public void generateNewArray(@NotNull JetCallExpression expression) { 3283 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3284 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3285 3286 generateNewArray(expression, arrayType); 3287 } 3288 3289 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { 3290 List<JetExpression> args = new ArrayList<JetExpression>(); 3291 for (ValueArgument va : expression.getValueArguments()) { 3292 args.add(va.getArgumentExpression()); 3293 } 3294 args.addAll(expression.getFunctionLiteralArguments()); 3295 3296 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); 3297 if (!isArray && args.size() != 1) { 3298 throw new CompilationException("primitive array constructor requires one argument", null, expression); 3299 } 3300 3301 if (isArray) { 3302 gen(args.get(0), Type.INT_TYPE); 3303 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); 3304 } 3305 else { 3306 Type type = typeMapper.mapType(arrayType); 3307 gen(args.get(0), Type.INT_TYPE); 3308 v.newarray(correctElementType(type)); 3309 } 3310 3311 if (args.size() == 2) { 3312 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3313 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3314 3315 v.dup(); 3316 v.arraylength(); 3317 v.store(sizeIndex, Type.INT_TYPE); 3318 3319 v.iconst(0); 3320 v.store(indexIndex, Type.INT_TYPE); 3321 3322 gen(args.get(1), JET_FUNCTION1_TYPE); 3323 3324 Label begin = new Label(); 3325 Label end = new Label(); 3326 v.visitLabel(begin); 3327 v.load(indexIndex, Type.INT_TYPE); 3328 v.load(sizeIndex, Type.INT_TYPE); 3329 v.ificmpge(end); 3330 3331 v.dup2(); 3332 v.load(indexIndex, Type.INT_TYPE); 3333 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 3334 v.invokeinterface("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); 3335 v.load(indexIndex, Type.INT_TYPE); 3336 v.iinc(indexIndex, 1); 3337 v.swap(); 3338 v.astore(OBJECT_TYPE); 3339 3340 v.goTo(begin); 3341 v.visitLabel(end); 3342 v.pop(); 3343 3344 myFrameMap.leaveTemp(Type.INT_TYPE); 3345 myFrameMap.leaveTemp(Type.INT_TYPE); 3346 } 3347 } 3348 3349 @Override 3350 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { 3351 JetExpression array = expression.getArrayExpression(); 3352 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); 3353 Type arrayType = asmTypeOrVoid(type); 3354 List<JetExpression> indices = expression.getIndexExpressions(); 3355 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 3356 assert operationDescriptor != null; 3357 if (arrayType.getSort() == Type.ARRAY && 3358 indices.size() == 1 && 3359 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3360 gen(array, arrayType); 3361 for (JetExpression index : indices) { 3362 gen(index, Type.INT_TYPE); 3363 } 3364 assert type != null; 3365 if (KotlinBuiltIns.getInstance().isArray(type)) { 3366 JetType elementType = type.getArguments().get(0).getType(); 3367 Type notBoxed = asmType(elementType); 3368 return StackValue.arrayElement(notBoxed, true); 3369 } 3370 else { 3371 return StackValue.arrayElement(correctElementType(arrayType), false); 3372 } 3373 } 3374 else { 3375 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); 3376 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); 3377 3378 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3379 3380 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3381 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3382 3383 Callable callable = resolveToCallable(operationDescriptor, false); 3384 if (callable instanceof CallableMethod) { 3385 genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable); 3386 } 3387 else { 3388 gen(array, arrayType); // intrinsic method 3389 } 3390 3391 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0; 3392 3393 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod(); 3394 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3395 for (JetExpression jetExpression : expression.getIndexExpressions()) { 3396 gen(jetExpression, argumentTypes[index]); 3397 index++; 3398 } 3399 3400 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3401 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state); 3402 } 3403 } 3404 3405 @Override 3406 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) { 3407 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3408 v.athrow(); 3409 return StackValue.none(); 3410 } 3411 3412 @Override 3413 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) { 3414 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 3415 if (descriptor instanceof ClassDescriptor) { 3416 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false); 3417 } 3418 else { 3419 if (descriptor instanceof CallableDescriptor) { 3420 return generateReceiver(descriptor); 3421 } 3422 throw new UnsupportedOperationException("neither this nor receiver"); 3423 } 3424 } 3425 3426 @Override 3427 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) { 3428 return generateTryExpression(expression, false); 3429 } 3430 3431 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) { 3432 /* 3433 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 3434 (or blocks). 3435 */ 3436 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3437 FinallyBlockStackElement finallyBlockStackElement = null; 3438 if (finallyBlock != null) { 3439 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3440 blockStackElements.push(finallyBlockStackElement); 3441 } 3442 3443 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); 3444 assert jetType != null; 3445 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3446 3447 Label tryStart = new Label(); 3448 v.mark(tryStart); 3449 v.nop(); // prevent verify error on empty try 3450 3451 gen(expression.getTryBlock(), expectedAsmType); 3452 3453 int savedValue = -1; 3454 if (!isStatement) { 3455 savedValue = myFrameMap.enterTemp(expectedAsmType); 3456 v.store(savedValue, expectedAsmType); 3457 } 3458 3459 Label tryEnd = new Label(); 3460 v.mark(tryEnd); 3461 3462 //do it before finally block generation 3463 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3464 3465 Label end = new Label(); 3466 3467 genFinallyBlockOrGoto(finallyBlockStackElement, end); 3468 3469 List<JetCatchClause> clauses = expression.getCatchClauses(); 3470 for (int i = 0, size = clauses.size(); i < size; i++) { 3471 JetCatchClause clause = clauses.get(i); 3472 3473 Label clauseStart = new Label(); 3474 v.mark(clauseStart); 3475 3476 VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); 3477 assert descriptor != null; 3478 Type descriptorType = asmType(descriptor.getType()); 3479 myFrameMap.enter(descriptor, descriptorType); 3480 int index = lookupLocalIndex(descriptor); 3481 v.store(index, descriptorType); 3482 3483 gen(clause.getCatchBody(), expectedAsmType); 3484 3485 if (!isStatement) { 3486 v.store(savedValue, expectedAsmType); 3487 } 3488 3489 myFrameMap.leave(descriptor); 3490 3491 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); 3492 3493 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3494 } 3495 3496 3497 //for default catch clause 3498 if (finallyBlock != null) { 3499 Label defaultCatchStart = new Label(); 3500 v.mark(defaultCatchStart); 3501 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3502 v.store(savedException, JAVA_THROWABLE_TYPE); 3503 Label defaultCatchEnd = new Label(); 3504 v.mark(defaultCatchEnd); 3505 3506 //do it before finally block generation 3507 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3508 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3509 3510 3511 genFinallyBlockOrGoto(finallyBlockStackElement, null); 3512 3513 v.load(savedException, JAVA_THROWABLE_TYPE); 3514 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3515 3516 v.athrow(); 3517 3518 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3519 } 3520 3521 markLineNumber(expression); 3522 v.mark(end); 3523 3524 if (!isStatement) { 3525 v.load(savedValue, expectedAsmType); 3526 myFrameMap.leaveTemp(expectedAsmType); 3527 } 3528 3529 if (finallyBlock != null) { 3530 blockStackElements.pop(); 3531 } 3532 3533 return StackValue.onStack(expectedAsmType); 3534 } 3535 3536 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3537 for (int i = 0; i < catchedRegions.size(); i += 2) { 3538 Label startRegion = catchedRegions.get(i); 3539 Label endRegion = catchedRegions.get(i+1); 3540 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3541 } 3542 } 3543 3544 3545 private List<Label> getCurrentCatchIntervals( 3546 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3547 @NotNull Label blockStart, 3548 @NotNull Label blockEnd 3549 ) { 3550 List<Label> gapsInBlock = 3551 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3552 assert gapsInBlock.size() % 2 == 0; 3553 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3554 blockRegions.add(blockStart); 3555 blockRegions.addAll(gapsInBlock); 3556 blockRegions.add(blockEnd); 3557 return blockRegions; 3558 } 3559 3560 @Override 3561 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3562 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3563 IElementType opToken = operationSign.getReferencedNameElementType(); 3564 if (opToken == JetTokens.COLON) { 3565 return gen(expression.getLeft()); 3566 } 3567 else { 3568 JetTypeReference typeReference = expression.getRight(); 3569 JetType rightType = bindingContext.get(BindingContext.TYPE, typeReference); 3570 assert rightType != null; 3571 Type rightTypeAsm = boxType(asmType(rightType)); 3572 JetExpression left = expression.getLeft(); 3573 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3574 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3575 StackValue value = genQualified(receiver, left); 3576 value.put(boxType(value.type), v); 3577 3578 if (opToken != JetTokens.AS_SAFE) { 3579 if (!CodegenUtil.isNullableType(rightType)) { 3580 v.dup(); 3581 Label nonnull = new Label(); 3582 v.ifnonnull(nonnull); 3583 JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); 3584 assert leftType != null; 3585 throwNewException(CLASS_TYPE_CAST_EXCEPTION, DescriptorRenderer.TEXT.renderType(leftType) + 3586 " cannot be cast to " + 3587 DescriptorRenderer.TEXT.renderType(rightType)); 3588 v.mark(nonnull); 3589 } 3590 } 3591 else { 3592 v.dup(); 3593 v.instanceOf(rightTypeAsm); 3594 Label ok = new Label(); 3595 v.ifne(ok); 3596 v.pop(); 3597 v.aconst(null); 3598 v.mark(ok); 3599 } 3600 3601 v.checkcast(rightTypeAsm); 3602 return StackValue.onStack(rightTypeAsm); 3603 } 3604 else { 3605 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3606 } 3607 } 3608 } 3609 3610 @Override 3611 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) { 3612 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3613 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated()); 3614 } 3615 3616 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3617 if (expressionToMatch != null) { 3618 Type subjectType = expressionToMatch.type; 3619 expressionToMatch.dupReceiver(v); 3620 expressionToMatch.put(subjectType, v); 3621 JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression); 3622 Type condType; 3623 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3624 assert condJetType != null; 3625 condType = asmType(condJetType); 3626 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3627 subjectType = boxType(subjectType); 3628 expressionToMatch.coerceTo(subjectType, v); 3629 } 3630 } 3631 else { 3632 condType = OBJECT_TYPE; 3633 } 3634 gen(patternExpression, condType); 3635 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType); 3636 } 3637 else { 3638 return gen(patternExpression); 3639 } 3640 } 3641 3642 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3643 JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); 3644 expressionToMatch.dupReceiver(v); 3645 generateInstanceOf(expressionToMatch, jetType, false); 3646 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); 3647 return negated ? StackValue.not(value) : value; 3648 } 3649 3650 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { 3651 expressionToGen.put(OBJECT_TYPE, v); 3652 if (leaveExpressionOnStack) { 3653 v.dup(); 3654 } 3655 Type type = boxType(asmType(jetType)); 3656 if (jetType.isNullable()) { 3657 Label nope = new Label(); 3658 Label end = new Label(); 3659 3660 v.dup(); 3661 v.ifnull(nope); 3662 v.instanceOf(type); 3663 v.goTo(end); 3664 v.mark(nope); 3665 v.pop(); 3666 v.iconst(1); 3667 v.mark(end); 3668 } 3669 else { 3670 v.instanceOf(type); 3671 } 3672 } 3673 3674 @Override 3675 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) { 3676 return generateWhenExpression(expression, false); 3677 } 3678 3679 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) { 3680 JetExpression expr = expression.getSubjectExpression(); 3681 JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr); 3682 Type subjectType = asmTypeOrVoid(subjectJetType); 3683 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3684 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3685 if (subjectLocal != -1) { 3686 gen(expr, subjectType); 3687 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3688 v.store(subjectLocal, subjectType); 3689 } 3690 3691 Label end = new Label(); 3692 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 3693 3694 Label nextCondition = null; 3695 for (JetWhenEntry whenEntry : expression.getEntries()) { 3696 if (nextCondition != null) { 3697 v.mark(nextCondition); 3698 } 3699 nextCondition = new Label(); 3700 FrameMap.Mark mark = myFrameMap.mark(); 3701 Label thisEntry = new Label(); 3702 if (!whenEntry.isElse()) { 3703 JetWhenCondition[] conditions = whenEntry.getConditions(); 3704 for (int i = 0; i < conditions.length; i++) { 3705 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3706 conditionValue.condJump(nextCondition, true, v); 3707 if (i < conditions.length - 1) { 3708 v.goTo(thisEntry); 3709 v.mark(nextCondition); 3710 nextCondition = new Label(); 3711 } 3712 } 3713 } 3714 3715 v.visitLabel(thisEntry); 3716 gen(whenEntry.getExpression(), resultType); 3717 mark.dropTo(); 3718 if (!whenEntry.isElse()) { 3719 v.goTo(end); 3720 } 3721 } 3722 if (!hasElse && nextCondition != null) { 3723 v.mark(nextCondition); 3724 if (!isStatement) { 3725 // a result is expected 3726 if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { 3727 // when() is supposed to be exhaustive 3728 throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION); 3729 } 3730 else { 3731 // non-exhaustive when() with no else -> Unit must be expected 3732 StackValue.putUnitInstance(v); 3733 } 3734 } 3735 } 3736 3737 markLineNumber(expression); 3738 v.mark(end); 3739 3740 myFrameMap.leaveTemp(subjectType); 3741 tempVariables.remove(expr); 3742 return StackValue.onStack(resultType); 3743 } 3744 3745 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 3746 if (condition instanceof JetWhenConditionInRange) { 3747 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 3748 JetExpression rangeExpression = conditionInRange.getRangeExpression(); 3749 while (rangeExpression instanceof JetParenthesizedExpression) { 3750 rangeExpression = ((JetParenthesizedExpression) rangeExpression).getExpression(); 3751 } 3752 JetSimpleNameExpression operationReference = conditionInRange.getOperationReference(); 3753 boolean inverted = operationReference.getReferencedNameElementType() == JetTokens.NOT_IN; 3754 if (isIntRangeExpr(rangeExpression)) { 3755 getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted); 3756 } 3757 else { 3758 //FunctionDescriptor op = 3759 // (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference()); 3760 //genToJVMStack(rangeExpression); 3761 //new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); 3762 //invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); 3763 invokeFunctionByReference(operationReference); 3764 if (inverted) { 3765 genInvertBoolean(v); 3766 } 3767 } 3768 return StackValue.onStack(Type.BOOLEAN_TYPE); 3769 } 3770 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3771 if (condition instanceof JetWhenConditionIsPattern) { 3772 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 3773 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated()); 3774 } 3775 else if (condition instanceof JetWhenConditionWithExpression) { 3776 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3777 return generateExpressionMatch(match, patternExpression); 3778 } 3779 else { 3780 throw new UnsupportedOperationException("unsupported kind of when condition"); 3781 } 3782 } 3783 3784 private void invokeFunctionByReference(JetSimpleNameExpression operationReference) { 3785 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3786 bindingContext.get(RESOLVED_CALL, operationReference); 3787 Call call = bindingContext.get(CALL, operationReference); 3788 invokeFunction(call, StackValue.none(), resolvedCall); 3789 } 3790 3791 private boolean isIntRangeExpr(JetExpression rangeExpression) { 3792 if (rangeExpression instanceof JetBinaryExpression) { 3793 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 3794 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 3795 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); 3796 assert jetType != null; 3797 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3798 return INTEGRAL_RANGES.contains(descriptor); 3799 } 3800 } 3801 return false; 3802 } 3803 3804 private void throwNewException(@NotNull String className) { 3805 throwNewException(className, null); 3806 } 3807 3808 private void throwNewException(@NotNull String className, @Nullable String message) { 3809 v.anew(Type.getObjectType(className)); 3810 v.dup(); 3811 if (message != null) { 3812 v.visitLdcInsn(message); 3813 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V"); 3814 } 3815 else { 3816 v.invokespecial(className, "<init>", "()V"); 3817 } 3818 v.athrow(); 3819 } 3820 3821 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3822 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake"); 3823 return CallMaker.makeCall(fake, initializerAsReceiver); 3824 } 3825 3826 @Override 3827 public String toString() { 3828 return context.getContextDescriptor().toString(); 3829 } 3830 3831 @NotNull 3832 private ScriptCodegen getParentScriptCodegen() { 3833 MemberCodegen codegen = parentCodegen; 3834 while (codegen != null) { 3835 if (codegen instanceof ScriptCodegen) { 3836 return (ScriptCodegen) codegen; 3837 } 3838 codegen = codegen.getParentCodegen(); 3839 } 3840 throw new IllegalStateException("Script codegen should be present in codegen tree"); 3841 } 3842 }