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