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(@NotNull 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(@NotNull JetObjectDeclaration declaration, StackValue data) { 301 return visitClassOrObject(declaration); 302 } 303 304 @Override 305 public StackValue visitExpression(@NotNull JetExpression expression, StackValue receiver) { 306 throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented"); 307 } 308 309 @Override 310 public StackValue visitSuperExpression(@NotNull 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(@NotNull JetParenthesizedExpression expression, StackValue receiver) { 343 return genQualified(receiver, expression.getExpression()); 344 } 345 346 @Override 347 public StackValue visitAnnotatedExpression(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull JetBreakExpression expression, StackValue receiver) { 1146 return visitBreakOrContinueExpression(expression, receiver, true); 1147 } 1148 1149 @Override 1150 public StackValue visitContinueExpression(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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(@NotNull 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 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 1628 descriptor = descriptor.getOriginal(); 1629 1630 if (descriptor instanceof CallableMemberDescriptor) { 1631 CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor; 1632 memberDescriptor = unwrapFakeOverride(memberDescriptor); 1633 1634 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1635 if (intrinsic != null) { 1636 Type expectedType = expressionType(expression); 1637 return intrinsic.generate(this, v, expectedType, expression, Collections.<JetExpression>emptyList(), receiver, state); 1638 } 1639 } 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(@NotNull 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.getResultingDescriptor().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 instanceof ExpressionAsFunctionDescriptor) { 2099 JetExpression deparenthesize = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) fd).getExpression()); 2100 return !(deparenthesize instanceof JetCallableReferenceExpression || deparenthesize instanceof JetFunctionLiteralExpression); 2101 } 2102 return false; 2103 } 2104 2105 2106 public void invokeMethodWithArguments( 2107 @NotNull CallableMethod callableMethod, 2108 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 2109 @Nullable Call callToGenerateCallee, 2110 @NotNull StackValue receiver 2111 ) { 2112 Type calleeType = callableMethod.getGenerateCalleeType(); 2113 if (calleeType != null) { 2114 assert !callableMethod.isNeedsThis(); 2115 assert callToGenerateCallee != null : "Call can't be null when generating callee: " + resolvedCall.getResultingDescriptor(); 2116 gen(callToGenerateCallee.getCalleeExpression(), calleeType); 2117 } 2118 2119 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2120 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2121 } 2122 2123 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2124 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2125 receiver.put(receiver.type, v); 2126 } 2127 2128 pushArgumentsAndInvoke(resolvedCall, callableMethod); 2129 } 2130 2131 private void pushArgumentsAndInvoke(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableMethod callable) { 2132 int mask = pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); 2133 if (mask == 0) { 2134 callable.invokeWithNotNullAssertion(v, state, resolvedCall); 2135 } 2136 else { 2137 callable.invokeDefaultWithNotNullAssertion(v, state, resolvedCall, mask); 2138 } 2139 } 2140 2141 private void genThisAndReceiverFromResolvedCall( 2142 StackValue receiver, 2143 ResolvedCall<? extends CallableDescriptor> resolvedCall, 2144 CallableMethod callableMethod 2145 ) { 2146 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2147 receiver.put(receiver.type, v); 2148 } 2149 2150 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) { 2151 if (descriptor instanceof ClassReceiver) { 2152 Type exprType = asmType(descriptor.getType()); 2153 ClassReceiver classReceiver = (ClassReceiver) descriptor; 2154 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor(); 2155 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { 2156 if (context.getContextDescriptor() instanceof FunctionDescriptor && 2157 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) { 2158 v.load(0, OBJECT_TYPE); 2159 } 2160 else { 2161 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper); 2162 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor()); 2163 } 2164 StackValue.onStack(exprType).put(type, v); 2165 } 2166 else { 2167 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v); 2168 } 2169 } 2170 else if (descriptor instanceof ScriptReceiver) { 2171 generateScript((ScriptReceiver) descriptor); 2172 } 2173 else if (descriptor instanceof ExtensionReceiver) { 2174 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; 2175 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v); 2176 } 2177 else if (descriptor instanceof ExpressionReceiver) { 2178 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; 2179 JetExpression expr = expressionReceiver.getExpression(); 2180 gen(expr, type); 2181 } 2182 else if (descriptor instanceof AutoCastReceiver) { 2183 AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor; 2184 Type originalType = asmType(autoCastReceiver.getOriginal().getType()); 2185 generateFromResolvedCall(autoCastReceiver.getOriginal(), originalType); 2186 StackValue.onStack(originalType).put(type, v); 2187 } 2188 else { 2189 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor); 2190 } 2191 } 2192 2193 @Nullable 2194 private static JetExpression getReceiverForSelector(PsiElement expression) { 2195 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2196 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2197 return parent.getReceiverExpression(); 2198 } 2199 return null; 2200 } 2201 2202 private StackValue generateReceiver(DeclarationDescriptor provided) { 2203 if (context.getCallableDescriptorWithReceiver() == provided) { 2204 StackValue result = context.getReceiverExpression(typeMapper); 2205 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2206 } 2207 2208 StackValue result = context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false); 2209 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2210 } 2211 2212 private void generateScript(@NotNull ScriptReceiver receiver) { 2213 CodegenContext cur = context; 2214 StackValue result = StackValue.local(0, OBJECT_TYPE); 2215 while (cur != null) { 2216 if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { 2217 cur = cur.getParentContext(); 2218 } 2219 2220 if (cur instanceof ScriptContext) { 2221 ScriptContext scriptContext = (ScriptContext) cur; 2222 2223 JvmClassName currentScriptClassName = 2224 classNameForScriptDescriptor(bindingContext, 2225 scriptContext.getScriptDescriptor()); 2226 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2227 result.put(currentScriptClassName.getAsmType(), v); 2228 } 2229 else { 2230 JvmClassName className = 2231 classNameForScriptDescriptor(bindingContext, 2232 receiver.getDeclarationDescriptor()); 2233 String fieldName = state.getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); 2234 result.put(currentScriptClassName.getAsmType(), v); 2235 StackValue.field(className.getAsmType(), currentScriptClassName, fieldName, false).put(className.getAsmType(), v); 2236 } 2237 return; 2238 } 2239 2240 assert cur != null; 2241 result = cur.getOuterExpression(result, false); 2242 2243 if (cur instanceof ConstructorContext) { 2244 cur = cur.getParentContext(); 2245 } 2246 assert cur != null; 2247 cur = cur.getParentContext(); 2248 } 2249 2250 throw new UnsupportedOperationException(); 2251 } 2252 2253 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2254 boolean isSingleton = CodegenBinding.isSingleton(bindingContext, calleeContainingClass); 2255 if (isSingleton) { 2256 assert !isSuper; 2257 2258 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) { 2259 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2260 } 2261 else { 2262 return StackValue.singleton(calleeContainingClass, typeMapper); 2263 } 2264 } 2265 2266 CodegenContext cur = context; 2267 Type type = asmType(calleeContainingClass.getDefaultType()); 2268 StackValue result = StackValue.local(0, type); 2269 while (cur != null) { 2270 if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { 2271 cur = cur.getParentContext(); 2272 } 2273 2274 assert cur != null; 2275 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2276 if (!isSuper && thisDescriptor.equals(calleeContainingClass) 2277 || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2278 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2279 } 2280 2281 result = cur.getOuterExpression(result, false); 2282 2283 if (cur instanceof ConstructorContext) { 2284 cur = cur.getParentContext(); 2285 } 2286 assert cur != null; 2287 cur = cur.getParentContext(); 2288 } 2289 2290 throw new UnsupportedOperationException(); 2291 } 2292 2293 private static boolean isReceiver(PsiElement expression) { 2294 PsiElement parent = expression.getParent(); 2295 if (parent instanceof JetQualifiedExpression) { 2296 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2297 return expression == receiverExpression; 2298 } 2299 return false; 2300 } 2301 2302 private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes) { 2303 @SuppressWarnings("unchecked") 2304 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2305 CallableDescriptor fd = resolvedCall.getResultingDescriptor(); 2306 2307 if (fd.getValueParameters().size() != valueArguments.size()) { 2308 throw new IllegalStateException(); 2309 } 2310 2311 int mask = 0; 2312 2313 for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) { 2314 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); 2315 Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); 2316 if (resolvedValueArgument instanceof ExpressionValueArgument) { 2317 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); 2318 assert valueArgument != null; 2319 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 2320 assert argumentExpression != null : valueArgument.asElement().getText(); 2321 2322 gen(argumentExpression, parameterType); 2323 } 2324 else if (resolvedValueArgument instanceof DefaultValueArgument) { 2325 pushDefaultValueOnStack(parameterType, v); 2326 mask |= (1 << valueParameter.getIndex()); 2327 } 2328 else if (resolvedValueArgument instanceof VarargValueArgument) { 2329 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; 2330 genVarargs(valueParameter, valueArgument); 2331 } 2332 else { 2333 throw new UnsupportedOperationException(); 2334 } 2335 } 2336 return mask; 2337 } 2338 2339 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) { 2340 JetType outType = valueParameterDescriptor.getType(); 2341 2342 Type type = asmType(outType); 2343 assert type.getSort() == Type.ARRAY; 2344 Type elementType = correctElementType(type); 2345 List<ValueArgument> arguments = valueArgument.getArguments(); 2346 int size = arguments.size(); 2347 2348 boolean hasSpread = false; 2349 for (int i = 0; i != size; ++i) { 2350 if (arguments.get(i).getSpreadElement() != null) { 2351 hasSpread = true; 2352 break; 2353 } 2354 } 2355 2356 if (hasSpread) { 2357 if (size == 1) { 2358 gen(arguments.get(0).getArgumentExpression(), type); 2359 } 2360 else { 2361 String owner = "jet/runtime/Intrinsics$SpreadBuilder"; 2362 v.anew(Type.getObjectType(owner)); 2363 v.dup(); 2364 v.invokespecial(owner, "<init>", "()V"); 2365 for (int i = 0; i != size; ++i) { 2366 v.dup(); 2367 ValueArgument argument = arguments.get(i); 2368 if (argument.getSpreadElement() != null) { 2369 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2370 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V"); 2371 } 2372 else { 2373 gen(argument.getArgumentExpression(), elementType); 2374 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z"); 2375 v.pop(); 2376 } 2377 } 2378 v.dup(); 2379 v.invokevirtual(owner, "size", "()I"); 2380 v.newarray(elementType); 2381 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); 2382 v.checkcast(type); 2383 } 2384 } 2385 else { 2386 v.iconst(arguments.size()); 2387 v.newarray(elementType); 2388 for (int i = 0; i != size; ++i) { 2389 v.dup(); 2390 v.iconst(i); 2391 gen(arguments.get(i).getArgumentExpression(), elementType); 2392 StackValue.arrayElement(elementType, false).store(elementType, v); 2393 } 2394 } 2395 } 2396 2397 public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) { 2398 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2399 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); 2400 if (resolvedCall != null) { 2401 return pushMethodArguments(resolvedCall, valueParameterTypes); 2402 } 2403 else { 2404 List<? extends ValueArgument> args = expression.getValueArguments(); 2405 for (int i = 0, argsSize = args.size(); i < argsSize; i++) { 2406 ValueArgument arg = args.get(i); 2407 gen(arg.getArgumentExpression(), valueParameterTypes.get(i)); 2408 } 2409 return 0; 2410 } 2411 } 2412 2413 @NotNull 2414 public Type expressionType(JetExpression expr) { 2415 return typeMapper.expressionType(expr); 2416 } 2417 2418 public int indexOfLocal(JetReferenceExpression lhs) { 2419 DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs); 2420 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2421 return -1; 2422 } 2423 return lookupLocalIndex(declarationDescriptor); 2424 } 2425 2426 @Override 2427 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) { 2428 // TODO: properties 2429 final FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2430 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText(); 2431 2432 final ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, expression.getCallableReference()); 2433 assert resolvedCall != null : "Callable reference is not resolved: " + functionDescriptor + " " + expression.getText(); 2434 2435 JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression); 2436 assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText(); 2437 ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType); 2438 assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType; 2439 2440 JvmClassName closureSuperClass = JvmClassName.byType(typeMapper.mapType(kFunctionImpl)); 2441 2442 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context, this, 2443 new FunctionGenerationStrategy.CodegenBased<CallableDescriptor>(state, functionDescriptor) { 2444 2445 @NotNull 2446 @Override 2447 public ExpressionCodegen initializeExpressionCodegen( 2448 JvmMethodSignature signature, MethodContext context, MethodVisitor mv, 2449 Type returnType 2450 ) { 2451 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2452 JetType returnJetType = referencedFunction.getReturnType(); 2453 assert returnJetType != null : "Return type can't be null: " + referencedFunction; 2454 2455 return super.initializeExpressionCodegen(signature, context, 2456 mv, typeMapper.mapReturnType(returnJetType)); 2457 } 2458 2459 @Override 2460 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2461 /* 2462 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2463 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2464 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2465 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2466 every argument boils down to calling LOAD with the corresponding index 2467 */ 2468 2469 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2470 2471 JetCallExpression fakeExpression = constructFakeFunctionCall(referencedFunction); 2472 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2473 2474 final ReceiverValue receiverValue = computeAndSaveReceiver(signature, codegen); 2475 computeAndSaveArguments(codegen.myFrameMap, fakeArguments, codegen); 2476 2477 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2478 @NotNull 2479 @Override 2480 public ReceiverValue getReceiverArgument() { 2481 return resolvedCall.getExplicitReceiverKind() == RECEIVER_ARGUMENT ? receiverValue : NO_RECEIVER; 2482 } 2483 2484 @NotNull 2485 @Override 2486 public ReceiverValue getThisObject() { 2487 return resolvedCall.getExplicitReceiverKind() == THIS_OBJECT ? receiverValue : NO_RECEIVER; 2488 } 2489 2490 @NotNull 2491 @Override 2492 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2493 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2494 for (ValueArgument argument : fakeArguments) { 2495 result.add(new ExpressionValueArgument(argument)); 2496 } 2497 return result; 2498 } 2499 }; 2500 2501 StackValue result; 2502 Type returnType = codegen.returnType; 2503 if (referencedFunction instanceof ConstructorDescriptor) { 2504 if (returnType.getSort() == Type.ARRAY) { 2505 JetType returnJetType = referencedFunction.getReturnType(); 2506 assert returnJetType != null; 2507 codegen.generateNewArray(fakeExpression, returnJetType); 2508 result = StackValue.onStack(returnType); 2509 } 2510 else { 2511 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType); 2512 } 2513 } 2514 else { 2515 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2516 result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall); 2517 } 2518 2519 InstructionAdapter v = codegen.v; 2520 result.put(returnType, v); 2521 v.areturn(returnType); 2522 } 2523 2524 @NotNull 2525 private JetCallExpression constructFakeFunctionCall(@NotNull CallableDescriptor referencedFunction) { 2526 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2527 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); 2528 iterator.hasNext(); ) { 2529 ValueParameterDescriptor descriptor = iterator.next(); 2530 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2531 if (iterator.hasNext()) { 2532 fakeFunctionCall.append(", "); 2533 } 2534 } 2535 fakeFunctionCall.append(")"); 2536 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString()); 2537 } 2538 2539 private void computeAndSaveArguments( 2540 @NotNull FrameMap frameMap, 2541 @NotNull List<? extends ValueArgument> fakeArguments, 2542 @NotNull ExpressionCodegen codegen 2543 ) { 2544 for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) { 2545 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2546 Type type = typeMapper.mapType(parameter); 2547 int localIndex = frameMap.getIndex(parameter); 2548 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2549 } 2550 } 2551 2552 @NotNull 2553 private ReceiverValue computeAndSaveReceiver( 2554 @NotNull JvmMethodSignature signature, 2555 @NotNull ExpressionCodegen codegen 2556 ) { 2557 CallableDescriptor referencedFunction = resolvedCall.getCandidateDescriptor(); 2558 2559 ReceiverParameterDescriptor receiverParameter = referencedFunction.getReceiverParameter(); 2560 ReceiverParameterDescriptor expectedThisObject = referencedFunction.getExpectedThisObject(); 2561 assert receiverParameter == null || expectedThisObject == null : 2562 "Extensions in classes can't be referenced via callable reference expressions: " + referencedFunction; 2563 2564 ReceiverParameterDescriptor receiver = receiverParameter != null ? receiverParameter : expectedThisObject; 2565 2566 if (receiver == null) { 2567 return NO_RECEIVER; 2568 } 2569 2570 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), 2571 "callableReferenceFakeReceiver"); 2572 2573 Type firstParameterType = signature.getAsmMethod().getArgumentTypes()[0]; 2574 // 0 is this (the closure class), 1 is the method's first parameter 2575 codegen.tempVariables.put(receiverExpression, StackValue.local(1, firstParameterType)); 2576 2577 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2578 } 2579 } 2580 ); 2581 2582 closureCodegen.gen(); 2583 2584 return closureCodegen.putInstanceOnStack(v, this); 2585 } 2586 2587 @Override 2588 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) { 2589 StackValue receiverValue = StackValue.none(); 2590 return genQualified(receiverValue, expression.getSelectorExpression()); 2591 } 2592 2593 @Override 2594 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue receiver) { 2595 JetExpression expr = expression.getReceiverExpression(); 2596 Type receiverType = expressionType(expr); 2597 gen(expr, receiverType); 2598 if (isPrimitive(receiverType)) { 2599 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2600 Type type = boxType(propValue.type); 2601 propValue.put(type, v); 2602 2603 return StackValue.onStack(type); 2604 } 2605 else { 2606 Label ifnull = new Label(); 2607 Label end = new Label(); 2608 v.dup(); 2609 v.ifnull(ifnull); 2610 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2611 Type type = boxType(propValue.type); 2612 propValue.put(type, v); 2613 v.goTo(end); 2614 2615 v.mark(ifnull); 2616 v.pop(); 2617 if (!type.equals(Type.VOID_TYPE)) { 2618 v.aconst(null); 2619 } 2620 v.mark(end); 2621 2622 return StackValue.onStack(type); 2623 } 2624 } 2625 2626 @Override 2627 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) { 2628 IElementType opToken = expression.getOperationReference().getReferencedNameElementType(); 2629 if (opToken == JetTokens.EQ) { 2630 return generateAssignmentExpression(expression); 2631 } 2632 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2633 return generateAugmentedAssignment(expression); 2634 } 2635 else if (opToken == JetTokens.ANDAND) { 2636 return generateBooleanAnd(expression); 2637 } 2638 else if (opToken == JetTokens.OROR) { 2639 return generateBooleanOr(expression); 2640 } 2641 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2642 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2643 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2644 } 2645 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2646 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2647 return generateComparison(expression); 2648 } 2649 else if (opToken == JetTokens.ELVIS) { 2650 return generateElvis(expression); 2651 } 2652 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 2653 return generateIn(expression); 2654 } 2655 else { 2656 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2657 assert op instanceof FunctionDescriptor : String.valueOf(op); 2658 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2659 if (callable instanceof IntrinsicMethod) { 2660 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2661 return intrinsic.generate(this, v, expressionType(expression), expression, 2662 Arrays.asList(expression.getLeft(), expression.getRight()), receiver, state); 2663 } 2664 else { 2665 return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable); 2666 } 2667 } 2668 } 2669 2670 private StackValue generateIn(JetBinaryExpression expression) { 2671 boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN; 2672 if (isIntRangeExpr(expression.getRight())) { 2673 StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this); 2674 JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getRight(); 2675 getInIntRange(leftValue, rangeExpression, inverted); 2676 } 2677 else { 2678 invokeFunctionByReference(expression.getOperationReference()); 2679 if (inverted) { 2680 genInvertBoolean(v); 2681 } 2682 } 2683 return StackValue.onStack(Type.BOOLEAN_TYPE); 2684 } 2685 2686 private void getInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression, boolean inverted) { 2687 v.iconst(1); 2688 // 1 2689 leftValue.put(Type.INT_TYPE, v); 2690 // 1 l 2691 v.dup2(); 2692 // 1 l 1 l 2693 2694 //noinspection ConstantConditions 2695 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2696 // 1 l 1 l r 2697 Label lok = new Label(); 2698 v.ificmpge(lok); 2699 // 1 l 1 2700 v.pop(); 2701 v.iconst(0); 2702 v.mark(lok); 2703 // 1 l c 2704 v.dupX2(); 2705 // c 1 l c 2706 v.pop(); 2707 // c 1 l 2708 2709 gen(rangeExpression.getRight(), Type.INT_TYPE); 2710 // c 1 l r 2711 Label rok = new Label(); 2712 v.ificmple(rok); 2713 // c 1 2714 v.pop(); 2715 v.iconst(0); 2716 v.mark(rok); 2717 // c c 2718 2719 v.and(Type.INT_TYPE); 2720 if (inverted) { 2721 genInvertBoolean(v); 2722 } 2723 } 2724 2725 private StackValue generateBooleanAnd(JetBinaryExpression expression) { 2726 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2727 Label ifFalse = new Label(); 2728 v.ifeq(ifFalse); 2729 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2730 Label end = new Label(); 2731 v.goTo(end); 2732 v.mark(ifFalse); 2733 v.iconst(0); 2734 v.mark(end); 2735 return StackValue.onStack(Type.BOOLEAN_TYPE); 2736 } 2737 2738 private StackValue generateBooleanOr(JetBinaryExpression expression) { 2739 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2740 Label ifTrue = new Label(); 2741 v.ifne(ifTrue); 2742 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2743 Label end = new Label(); 2744 v.goTo(end); 2745 v.mark(ifTrue); 2746 v.iconst(1); 2747 v.mark(end); 2748 return StackValue.onStack(Type.BOOLEAN_TYPE); 2749 } 2750 2751 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 2752 Type leftType = expressionType(left); 2753 Type rightType = expressionType(right); 2754 2755 if (JetPsiUtil.isNullConstant(left)) { 2756 return genCmpWithNull(right, rightType, opToken); 2757 } 2758 2759 if (JetPsiUtil.isNullConstant(right)) { 2760 return genCmpWithNull(left, leftType, opToken); 2761 } 2762 2763 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2764 return genCmpWithZero(right, rightType, opToken); 2765 } 2766 2767 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2768 return genCmpWithZero(left, leftType, opToken); 2769 } 2770 2771 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2772 leftType = boxType(leftType); 2773 gen(left, leftType); 2774 rightType = boxType(rightType); 2775 gen(right, rightType); 2776 } 2777 else { 2778 gen(left, leftType); 2779 gen(right, rightType); 2780 } 2781 2782 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType); 2783 } 2784 2785 private boolean isIntZero(JetExpression expr, Type exprType) { 2786 CompileTimeConstant<?> exprValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr); 2787 return isIntPrimitive(exprType) && exprValue != null && exprValue.getValue().equals(0); 2788 } 2789 2790 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) { 2791 v.iconst(1); 2792 gen(exp, expType); 2793 Label ok = new Label(); 2794 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2795 v.ifeq(ok); 2796 } 2797 else { 2798 v.ifne(ok); 2799 } 2800 v.pop(); 2801 v.iconst(0); 2802 v.mark(ok); 2803 return StackValue.onStack(Type.BOOLEAN_TYPE); 2804 } 2805 2806 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { 2807 v.iconst(1); 2808 gen(exp, boxType(expType)); 2809 Label ok = new Label(); 2810 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2811 v.ifnull(ok); 2812 } 2813 else { 2814 v.ifnonnull(ok); 2815 } 2816 v.pop(); 2817 v.iconst(0); 2818 v.mark(ok); 2819 return StackValue.onStack(Type.BOOLEAN_TYPE); 2820 } 2821 2822 private StackValue generateElvis(JetBinaryExpression expression) { 2823 Type exprType = expressionType(expression); 2824 Type leftType = expressionType(expression.getLeft()); 2825 2826 gen(expression.getLeft(), leftType); 2827 2828 if (isPrimitive(leftType)) { 2829 return StackValue.onStack(leftType); 2830 } 2831 2832 v.dup(); 2833 Label ifNull = new Label(); 2834 v.ifnull(ifNull); 2835 StackValue.onStack(leftType).put(exprType, v); 2836 Label end = new Label(); 2837 v.goTo(end); 2838 v.mark(ifNull); 2839 v.pop(); 2840 gen(expression.getRight(), exprType); 2841 v.mark(end); 2842 2843 return StackValue.onStack(exprType); 2844 } 2845 2846 private StackValue generateComparison(JetBinaryExpression expression) { 2847 DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2848 assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target; 2849 FunctionDescriptor descriptor = (FunctionDescriptor) target; 2850 2851 JetExpression left = expression.getLeft(); 2852 JetExpression right = expression.getRight(); 2853 Callable callable = resolveToCallable(descriptor, false); 2854 2855 Type type; 2856 if (callable instanceof IntrinsicMethod) { 2857 // Compare two primitive values 2858 type = comparisonOperandType(expressionType(left), expressionType(right)); 2859 StackValue receiver = gen(left); 2860 receiver.put(type, v); 2861 gen(right, type); 2862 } 2863 else { 2864 type = Type.INT_TYPE; 2865 StackValue result = invokeOperation(expression, descriptor, (CallableMethod) callable); 2866 result.put(type, v); 2867 v.iconst(0); 2868 } 2869 return StackValue.cmp(expression.getOperationToken(), type); 2870 } 2871 2872 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 2873 StackValue stackValue = gen(expression.getLeft()); 2874 JetExpression right = expression.getRight(); 2875 assert right != null : expression.getText(); 2876 gen(right, stackValue.type); 2877 stackValue.store(stackValue.type, v); 2878 return StackValue.none(); 2879 } 2880 2881 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 2882 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2883 assert op instanceof FunctionDescriptor : String.valueOf(op); 2884 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2885 JetExpression lhs = expression.getLeft(); 2886 2887 // if (lhs instanceof JetArrayAccessExpression) { 2888 // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; 2889 // if (arrayAccessExpression.getIndexExpressions().size() != 1) { 2890 // throw new UnsupportedOperationException("Augmented assignment with multi-index"); 2891 // } 2892 // } 2893 2894 Type lhsType = expressionType(lhs); 2895 //noinspection ConstantConditions 2896 if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { 2897 if (callable instanceof IntrinsicMethod) { 2898 StackValue value = gen(lhs); // receiver 2899 value.dupReceiver(v); // receiver receiver 2900 value.put(lhsType, v); // receiver lhs 2901 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2902 //noinspection NullableProblems 2903 JetExpression right = expression.getRight(); 2904 assert right != null; 2905 StackValue stackValue = intrinsic.generate(this, v, lhsType, expression, 2906 Arrays.asList(right), 2907 StackValue.onStack(lhsType), state); 2908 value.store(stackValue.type, v); 2909 } 2910 else { 2911 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); 2912 } 2913 } 2914 else { 2915 JetType type = ((FunctionDescriptor) op).getReturnType(); 2916 assert type != null; 2917 boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType()); 2918 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue); 2919 } 2920 2921 return StackValue.none(); 2922 } 2923 2924 private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) { 2925 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2926 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2927 assert resolvedCall != null; 2928 2929 StackValue value = gen(expression.getLeft()); 2930 if (keepReturnValue) { 2931 value.dupReceiver(v); 2932 } 2933 value.put(lhsType, v); 2934 StackValue receiver = StackValue.onStack(lhsType); 2935 2936 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2937 receiver = StackValue.receiver(resolvedCall, receiver, this, callable); 2938 receiver.put(receiver.type, v); 2939 } 2940 2941 pushArgumentsAndInvoke(resolvedCall, callable); 2942 2943 if (keepReturnValue) { 2944 value.store(callable.getReturnType(), v); 2945 } 2946 } 2947 2948 public void invokeAppend(JetExpression expr) { 2949 if (expr instanceof JetBinaryExpression) { 2950 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 2951 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 2952 JetExpression left = binaryExpression.getLeft(); 2953 JetExpression right = binaryExpression.getRight(); 2954 Type leftType = expressionType(left); 2955 Type rightType = expressionType(right); 2956 2957 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) { 2958 invokeAppend(left); 2959 invokeAppend(right); 2960 return; 2961 } 2962 } 2963 } 2964 Type exprType = expressionType(expr); 2965 gen(expr, exprType); 2966 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 2967 } 2968 2969 @Nullable 2970 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 2971 if (expression.getParent() instanceof JetPrefixExpression) { 2972 JetPrefixExpression parent = (JetPrefixExpression) expression.getParent(); 2973 JetSimpleNameExpression operationSign = parent.getOperationReference(); 2974 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2975 return operationSign; 2976 } 2977 } 2978 return null; 2979 } 2980 2981 @Override 2982 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) { 2983 JetSimpleNameExpression operationSign = expression.getOperationReference(); 2984 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2985 return genQualified(receiver, expression.getBaseExpression()); 2986 } 2987 2988 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2989 assert op instanceof FunctionDescriptor : String.valueOf(op); 2990 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2991 if (callable instanceof IntrinsicMethod) { 2992 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2993 //noinspection ConstantConditions 2994 return intrinsic.generate(this, v, expressionType(expression), expression, 2995 Arrays.asList(expression.getBaseExpression()), receiver, state); 2996 } 2997 else { 2998 DeclarationDescriptor cls = op.getContainingDeclaration(); 2999 CallableMethod callableMethod = (CallableMethod) callable; 3000 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) { 3001 return invokeOperation(expression, (FunctionDescriptor) op, callableMethod); 3002 } 3003 else { 3004 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3005 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3006 assert resolvedCall != null; 3007 3008 StackValue value = gen(expression.getBaseExpression()); 3009 value.dupReceiver(v); 3010 value.dupReceiver(v); 3011 3012 Type type = expressionType(expression.getBaseExpression()); 3013 value.put(type, v); 3014 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3015 3016 value.store(callableMethod.getReturnType(), v); 3017 value.put(type, v); 3018 return StackValue.onStack(type); 3019 } 3020 } 3021 } 3022 3023 private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) { 3024 int functionLocalIndex = lookupLocalIndex(op); 3025 if (functionLocalIndex >= 0) { 3026 stackValueForLocal(op, functionLocalIndex).put(callable.getOwner().getAsmType(), v); 3027 } 3028 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3029 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3030 assert resolvedCall != null; 3031 genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable); 3032 pushArgumentsAndInvoke(resolvedCall, callable); 3033 3034 return returnValueAsStackValue(op, callable.getSignature().getAsmMethod().getReturnType()); 3035 } 3036 3037 @Override 3038 public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) { 3039 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 3040 StackValue base = genQualified(receiver, expression.getBaseExpression()); 3041 if (isPrimitive(base.type)) { 3042 return base; 3043 } 3044 base.put(base.type, v); 3045 v.dup(); 3046 Label ok = new Label(); 3047 v.ifnonnull(ok); 3048 v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V"); 3049 v.mark(ok); 3050 return StackValue.onStack(base.type); 3051 } 3052 3053 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3054 if (!(op instanceof FunctionDescriptor)) { 3055 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op); 3056 } 3057 3058 Type asmType = expressionType(expression); 3059 DeclarationDescriptor cls = op.getContainingDeclaration(); 3060 3061 int increment; 3062 if (op.getName().asString().equals("inc")) { 3063 increment = 1; 3064 } 3065 else if (op.getName().asString().equals("dec")) { 3066 increment = -1; 3067 } 3068 else { 3069 throw new UnsupportedOperationException("Unsupported postfix operation: " + op); 3070 } 3071 3072 if (isPrimitiveNumberClassDescriptor(cls)) { 3073 receiver.put(receiver.type, v); 3074 JetExpression operand = expression.getBaseExpression(); 3075 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { 3076 int index = indexOfLocal((JetReferenceExpression) operand); 3077 if (index >= 0) { 3078 return StackValue.postIncrement(index, increment); 3079 } 3080 } 3081 gen(operand, asmType); // old value 3082 generateIncrement(increment, asmType, operand, receiver); // increment in-place 3083 return StackValue.onStack(asmType); // old value 3084 } 3085 else { 3086 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3087 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3088 assert resolvedCall != null; 3089 3090 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3091 3092 StackValue value = gen(expression.getBaseExpression()); 3093 value.dupReceiver(v); 3094 3095 Type type = expressionType(expression.getBaseExpression()); 3096 value.put(type, v); 3097 3098 switch (value.receiverSize()) { 3099 case 0: 3100 dup(v, type); 3101 break; 3102 3103 case 1: 3104 if (type.getSize() == 2) { 3105 v.dup2X1(); 3106 } 3107 else { 3108 v.dupX1(); 3109 } 3110 break; 3111 3112 case 2: 3113 if (type.getSize() == 2) { 3114 v.dup2X2(); 3115 } 3116 else { 3117 v.dupX2(); 3118 } 3119 break; 3120 3121 case -1: 3122 throw new UnsupportedOperationException(); 3123 } 3124 3125 CallableMethod callableMethod = (CallableMethod) callable; 3126 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3127 3128 value.store(callableMethod.getReturnType(), v); 3129 return StackValue.onStack(type); 3130 } 3131 } 3132 3133 private void generateIncrement(int increment, Type asmType, JetExpression operand, StackValue receiver) { 3134 StackValue value = genQualified(receiver, operand); 3135 value.dupReceiver(v); 3136 value.put(asmType, v); 3137 genIncrement(asmType, increment, v); 3138 value.store(asmType, v); 3139 } 3140 3141 @Override 3142 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) { 3143 final JetExpression initializer = property.getInitializer(); 3144 if (initializer == null) { 3145 return StackValue.none(); 3146 } 3147 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() { 3148 @Override 3149 public Void fun(VariableDescriptor descriptor) { 3150 Type varType = asmType(descriptor.getType()); 3151 gen(initializer, varType); 3152 return null; 3153 } 3154 }); 3155 return StackValue.none(); 3156 } 3157 3158 @Override 3159 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) { 3160 JetExpression initializer = multiDeclaration.getInitializer(); 3161 if (initializer == null) return StackValue.none(); 3162 3163 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3164 assert initializerType != null; 3165 3166 Type initializerAsmType = asmType(initializerType); 3167 3168 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3169 3170 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3171 3172 gen(initializer, initializerAsmType); 3173 v.store(tempVarIndex, initializerAsmType); 3174 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3175 3176 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3177 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() { 3178 @Override 3179 public Void fun(VariableDescriptor descriptor) { 3180 ResolvedCall<FunctionDescriptor> resolvedCall = 3181 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration); 3182 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3183 Call call = makeFakeCall(initializerAsReceiver); 3184 invokeFunction(call, local, resolvedCall); 3185 return null; 3186 } 3187 }); 3188 } 3189 3190 if(initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3191 v.aconst(null); 3192 v.store(tempVarIndex, initializerAsmType); 3193 } 3194 myFrameMap.leaveTemp(initializerAsmType); 3195 3196 return StackValue.none(); 3197 } 3198 3199 private void initializeLocalVariable( 3200 @NotNull JetVariableDeclaration variableDeclaration, 3201 @NotNull Function<VariableDescriptor, Void> generateInitializer 3202 ) { 3203 3204 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 3205 3206 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3207 return; 3208 } 3209 int index = lookupLocalIndex(variableDescriptor); 3210 3211 if (index < 0) { 3212 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3213 } 3214 3215 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3216 assert variableDescriptor != null; 3217 3218 Type varType = asmType(variableDescriptor.getType()); 3219 3220 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3221 generateInitializer.fun(variableDescriptor); 3222 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3223 assert scriptPsi != null; 3224 JvmClassName scriptClassName = classNameForScriptPsi(bindingContext, scriptPsi); 3225 v.putfield(scriptClassName.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); 3226 } 3227 else if (sharedVarType == null) { 3228 generateInitializer.fun(variableDescriptor); 3229 v.store(index, varType); 3230 } 3231 else { 3232 v.load(index, OBJECT_TYPE); 3233 generateInitializer.fun(variableDescriptor); 3234 v.putfield(sharedVarType.getInternalName(), "ref", 3235 sharedVarType == JET_SHARED_VAR_TYPE ? "Ljava/lang/Object;" : varType.getDescriptor()); 3236 } 3237 } 3238 3239 @NotNull 3240 private StackValue generateNewCall( 3241 @NotNull JetCallExpression expression, 3242 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3243 @NotNull StackValue receiver 3244 ) { 3245 Type type = expressionType(expression); 3246 if (type.getSort() == Type.ARRAY) { 3247 generateNewArray(expression); 3248 return StackValue.onStack(type); 3249 } 3250 3251 return generateConstructorCall(resolvedCall, receiver, type); 3252 } 3253 3254 @NotNull 3255 private StackValue generateConstructorCall( 3256 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3257 @NotNull StackValue receiver, 3258 @NotNull Type type 3259 ) { 3260 v.anew(type); 3261 v.dup(); 3262 3263 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 3264 receiver.put(receiver.type, v); 3265 3266 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3267 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); 3268 3269 ClassDescriptor descriptor = getExpectedThisObjectForConstructorCall(constructorDescriptor, closure); 3270 if (receiver.type.getSort() != Type.VOID && descriptor == null) { 3271 v.pop(); 3272 } 3273 3274 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument() 3275 //so we need generate closure on stack 3276 //See StackValue.receiver for more info 3277 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()); 3278 3279 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructorDescriptor); 3280 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); 3281 invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 3282 3283 return StackValue.onStack(type); 3284 } 3285 3286 public void generateNewArray(@NotNull JetCallExpression expression) { 3287 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3288 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3289 3290 generateNewArray(expression, arrayType); 3291 } 3292 3293 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { 3294 List<JetExpression> args = new ArrayList<JetExpression>(); 3295 for (ValueArgument va : expression.getValueArguments()) { 3296 args.add(va.getArgumentExpression()); 3297 } 3298 args.addAll(expression.getFunctionLiteralArguments()); 3299 3300 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); 3301 if (!isArray && args.size() != 1) { 3302 throw new CompilationException("primitive array constructor requires one argument", null, expression); 3303 } 3304 3305 if (isArray) { 3306 gen(args.get(0), Type.INT_TYPE); 3307 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); 3308 } 3309 else { 3310 Type type = typeMapper.mapType(arrayType); 3311 gen(args.get(0), Type.INT_TYPE); 3312 v.newarray(correctElementType(type)); 3313 } 3314 3315 if (args.size() == 2) { 3316 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3317 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3318 3319 v.dup(); 3320 v.arraylength(); 3321 v.store(sizeIndex, Type.INT_TYPE); 3322 3323 v.iconst(0); 3324 v.store(indexIndex, Type.INT_TYPE); 3325 3326 gen(args.get(1), JET_FUNCTION1_TYPE); 3327 3328 Label begin = new Label(); 3329 Label end = new Label(); 3330 v.visitLabel(begin); 3331 v.load(indexIndex, Type.INT_TYPE); 3332 v.load(sizeIndex, Type.INT_TYPE); 3333 v.ificmpge(end); 3334 3335 v.dup2(); 3336 v.load(indexIndex, Type.INT_TYPE); 3337 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 3338 v.invokeinterface("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); 3339 v.load(indexIndex, Type.INT_TYPE); 3340 v.iinc(indexIndex, 1); 3341 v.swap(); 3342 v.astore(OBJECT_TYPE); 3343 3344 v.goTo(begin); 3345 v.visitLabel(end); 3346 v.pop(); 3347 3348 myFrameMap.leaveTemp(Type.INT_TYPE); 3349 myFrameMap.leaveTemp(Type.INT_TYPE); 3350 } 3351 } 3352 3353 @Override 3354 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { 3355 JetExpression array = expression.getArrayExpression(); 3356 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); 3357 Type arrayType = asmTypeOrVoid(type); 3358 List<JetExpression> indices = expression.getIndexExpressions(); 3359 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 3360 assert operationDescriptor != null; 3361 if (arrayType.getSort() == Type.ARRAY && 3362 indices.size() == 1 && 3363 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3364 gen(array, arrayType); 3365 for (JetExpression index : indices) { 3366 gen(index, Type.INT_TYPE); 3367 } 3368 assert type != null; 3369 if (KotlinBuiltIns.getInstance().isArray(type)) { 3370 JetType elementType = type.getArguments().get(0).getType(); 3371 Type notBoxed = asmType(elementType); 3372 return StackValue.arrayElement(notBoxed, true); 3373 } 3374 else { 3375 return StackValue.arrayElement(correctElementType(arrayType), false); 3376 } 3377 } 3378 else { 3379 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); 3380 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); 3381 3382 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3383 3384 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3385 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3386 3387 Callable callable = resolveToCallable(operationDescriptor, false); 3388 if (callable instanceof CallableMethod) { 3389 genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable); 3390 } 3391 else { 3392 gen(array, arrayType); // intrinsic method 3393 } 3394 3395 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0; 3396 3397 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod(); 3398 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3399 for (JetExpression jetExpression : expression.getIndexExpressions()) { 3400 gen(jetExpression, argumentTypes[index]); 3401 index++; 3402 } 3403 3404 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3405 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state); 3406 } 3407 } 3408 3409 @Override 3410 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) { 3411 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3412 v.athrow(); 3413 return StackValue.none(); 3414 } 3415 3416 @Override 3417 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) { 3418 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 3419 if (descriptor instanceof ClassDescriptor) { 3420 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false); 3421 } 3422 else { 3423 if (descriptor instanceof CallableDescriptor) { 3424 return generateReceiver(descriptor); 3425 } 3426 throw new UnsupportedOperationException("neither this nor receiver"); 3427 } 3428 } 3429 3430 @Override 3431 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) { 3432 return generateTryExpression(expression, false); 3433 } 3434 3435 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) { 3436 /* 3437 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 3438 (or blocks). 3439 */ 3440 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3441 FinallyBlockStackElement finallyBlockStackElement = null; 3442 if (finallyBlock != null) { 3443 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3444 blockStackElements.push(finallyBlockStackElement); 3445 } 3446 3447 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); 3448 assert jetType != null; 3449 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3450 3451 Label tryStart = new Label(); 3452 v.mark(tryStart); 3453 v.nop(); // prevent verify error on empty try 3454 3455 gen(expression.getTryBlock(), expectedAsmType); 3456 3457 int savedValue = -1; 3458 if (!isStatement) { 3459 savedValue = myFrameMap.enterTemp(expectedAsmType); 3460 v.store(savedValue, expectedAsmType); 3461 } 3462 3463 Label tryEnd = new Label(); 3464 v.mark(tryEnd); 3465 3466 //do it before finally block generation 3467 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3468 3469 Label end = new Label(); 3470 3471 genFinallyBlockOrGoto(finallyBlockStackElement, end); 3472 3473 List<JetCatchClause> clauses = expression.getCatchClauses(); 3474 for (int i = 0, size = clauses.size(); i < size; i++) { 3475 JetCatchClause clause = clauses.get(i); 3476 3477 Label clauseStart = new Label(); 3478 v.mark(clauseStart); 3479 3480 VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); 3481 assert descriptor != null; 3482 Type descriptorType = asmType(descriptor.getType()); 3483 myFrameMap.enter(descriptor, descriptorType); 3484 int index = lookupLocalIndex(descriptor); 3485 v.store(index, descriptorType); 3486 3487 gen(clause.getCatchBody(), expectedAsmType); 3488 3489 if (!isStatement) { 3490 v.store(savedValue, expectedAsmType); 3491 } 3492 3493 myFrameMap.leave(descriptor); 3494 3495 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); 3496 3497 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3498 } 3499 3500 3501 //for default catch clause 3502 if (finallyBlock != null) { 3503 Label defaultCatchStart = new Label(); 3504 v.mark(defaultCatchStart); 3505 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3506 v.store(savedException, JAVA_THROWABLE_TYPE); 3507 Label defaultCatchEnd = new Label(); 3508 v.mark(defaultCatchEnd); 3509 3510 //do it before finally block generation 3511 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3512 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3513 3514 3515 genFinallyBlockOrGoto(finallyBlockStackElement, null); 3516 3517 v.load(savedException, JAVA_THROWABLE_TYPE); 3518 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3519 3520 v.athrow(); 3521 3522 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3523 } 3524 3525 markLineNumber(expression); 3526 v.mark(end); 3527 3528 if (!isStatement) { 3529 v.load(savedValue, expectedAsmType); 3530 myFrameMap.leaveTemp(expectedAsmType); 3531 } 3532 3533 if (finallyBlock != null) { 3534 blockStackElements.pop(); 3535 } 3536 3537 return StackValue.onStack(expectedAsmType); 3538 } 3539 3540 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3541 for (int i = 0; i < catchedRegions.size(); i += 2) { 3542 Label startRegion = catchedRegions.get(i); 3543 Label endRegion = catchedRegions.get(i+1); 3544 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3545 } 3546 } 3547 3548 3549 private List<Label> getCurrentCatchIntervals( 3550 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3551 @NotNull Label blockStart, 3552 @NotNull Label blockEnd 3553 ) { 3554 List<Label> gapsInBlock = 3555 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3556 assert gapsInBlock.size() % 2 == 0; 3557 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3558 blockRegions.add(blockStart); 3559 blockRegions.addAll(gapsInBlock); 3560 blockRegions.add(blockEnd); 3561 return blockRegions; 3562 } 3563 3564 @Override 3565 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3566 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3567 IElementType opToken = operationSign.getReferencedNameElementType(); 3568 if (opToken == JetTokens.COLON) { 3569 return gen(expression.getLeft()); 3570 } 3571 else { 3572 JetTypeReference typeReference = expression.getRight(); 3573 JetType rightType = bindingContext.get(BindingContext.TYPE, typeReference); 3574 assert rightType != null; 3575 Type rightTypeAsm = boxType(asmType(rightType)); 3576 JetExpression left = expression.getLeft(); 3577 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3578 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3579 StackValue value = genQualified(receiver, left); 3580 value.put(boxType(value.type), v); 3581 3582 if (opToken != JetTokens.AS_SAFE) { 3583 if (!CodegenUtil.isNullableType(rightType)) { 3584 v.dup(); 3585 Label nonnull = new Label(); 3586 v.ifnonnull(nonnull); 3587 JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); 3588 assert leftType != null; 3589 throwNewException(CLASS_TYPE_CAST_EXCEPTION, DescriptorRenderer.TEXT.renderType(leftType) + 3590 " cannot be cast to " + 3591 DescriptorRenderer.TEXT.renderType(rightType)); 3592 v.mark(nonnull); 3593 } 3594 } 3595 else { 3596 v.dup(); 3597 v.instanceOf(rightTypeAsm); 3598 Label ok = new Label(); 3599 v.ifne(ok); 3600 v.pop(); 3601 v.aconst(null); 3602 v.mark(ok); 3603 } 3604 3605 v.checkcast(rightTypeAsm); 3606 return StackValue.onStack(rightTypeAsm); 3607 } 3608 else { 3609 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3610 } 3611 } 3612 } 3613 3614 @Override 3615 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) { 3616 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3617 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated()); 3618 } 3619 3620 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3621 if (expressionToMatch != null) { 3622 Type subjectType = expressionToMatch.type; 3623 expressionToMatch.dupReceiver(v); 3624 expressionToMatch.put(subjectType, v); 3625 JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression); 3626 Type condType; 3627 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3628 assert condJetType != null; 3629 condType = asmType(condJetType); 3630 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3631 subjectType = boxType(subjectType); 3632 expressionToMatch.coerceTo(subjectType, v); 3633 } 3634 } 3635 else { 3636 condType = OBJECT_TYPE; 3637 } 3638 gen(patternExpression, condType); 3639 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType); 3640 } 3641 else { 3642 return gen(patternExpression); 3643 } 3644 } 3645 3646 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3647 JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); 3648 expressionToMatch.dupReceiver(v); 3649 generateInstanceOf(expressionToMatch, jetType, false); 3650 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); 3651 return negated ? StackValue.not(value) : value; 3652 } 3653 3654 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { 3655 expressionToGen.put(OBJECT_TYPE, v); 3656 if (leaveExpressionOnStack) { 3657 v.dup(); 3658 } 3659 Type type = boxType(asmType(jetType)); 3660 if (jetType.isNullable()) { 3661 Label nope = new Label(); 3662 Label end = new Label(); 3663 3664 v.dup(); 3665 v.ifnull(nope); 3666 v.instanceOf(type); 3667 v.goTo(end); 3668 v.mark(nope); 3669 v.pop(); 3670 v.iconst(1); 3671 v.mark(end); 3672 } 3673 else { 3674 v.instanceOf(type); 3675 } 3676 } 3677 3678 @Override 3679 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) { 3680 return generateWhenExpression(expression, false); 3681 } 3682 3683 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) { 3684 JetExpression expr = expression.getSubjectExpression(); 3685 JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr); 3686 Type subjectType = asmTypeOrVoid(subjectJetType); 3687 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3688 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3689 if (subjectLocal != -1) { 3690 gen(expr, subjectType); 3691 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3692 v.store(subjectLocal, subjectType); 3693 } 3694 3695 Label end = new Label(); 3696 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 3697 3698 Label nextCondition = null; 3699 for (JetWhenEntry whenEntry : expression.getEntries()) { 3700 if (nextCondition != null) { 3701 v.mark(nextCondition); 3702 } 3703 nextCondition = new Label(); 3704 FrameMap.Mark mark = myFrameMap.mark(); 3705 Label thisEntry = new Label(); 3706 if (!whenEntry.isElse()) { 3707 JetWhenCondition[] conditions = whenEntry.getConditions(); 3708 for (int i = 0; i < conditions.length; i++) { 3709 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3710 conditionValue.condJump(nextCondition, true, v); 3711 if (i < conditions.length - 1) { 3712 v.goTo(thisEntry); 3713 v.mark(nextCondition); 3714 nextCondition = new Label(); 3715 } 3716 } 3717 } 3718 3719 v.visitLabel(thisEntry); 3720 gen(whenEntry.getExpression(), resultType); 3721 mark.dropTo(); 3722 if (!whenEntry.isElse()) { 3723 v.goTo(end); 3724 } 3725 } 3726 if (!hasElse && nextCondition != null) { 3727 v.mark(nextCondition); 3728 throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION); 3729 } 3730 3731 markLineNumber(expression); 3732 v.mark(end); 3733 3734 myFrameMap.leaveTemp(subjectType); 3735 tempVariables.remove(expr); 3736 return StackValue.onStack(resultType); 3737 } 3738 3739 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 3740 if (condition instanceof JetWhenConditionInRange) { 3741 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 3742 JetExpression rangeExpression = conditionInRange.getRangeExpression(); 3743 while (rangeExpression instanceof JetParenthesizedExpression) { 3744 rangeExpression = ((JetParenthesizedExpression) rangeExpression).getExpression(); 3745 } 3746 JetSimpleNameExpression operationReference = conditionInRange.getOperationReference(); 3747 boolean inverted = operationReference.getReferencedNameElementType() == JetTokens.NOT_IN; 3748 if (isIntRangeExpr(rangeExpression)) { 3749 getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted); 3750 } 3751 else { 3752 //FunctionDescriptor op = 3753 // (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference()); 3754 //genToJVMStack(rangeExpression); 3755 //new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); 3756 //invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); 3757 invokeFunctionByReference(operationReference); 3758 if (inverted) { 3759 genInvertBoolean(v); 3760 } 3761 } 3762 return StackValue.onStack(Type.BOOLEAN_TYPE); 3763 } 3764 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3765 if (condition instanceof JetWhenConditionIsPattern) { 3766 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 3767 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated()); 3768 } 3769 else if (condition instanceof JetWhenConditionWithExpression) { 3770 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3771 return generateExpressionMatch(match, patternExpression); 3772 } 3773 else { 3774 throw new UnsupportedOperationException("unsupported kind of when condition"); 3775 } 3776 } 3777 3778 private void invokeFunctionByReference(JetSimpleNameExpression operationReference) { 3779 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3780 bindingContext.get(RESOLVED_CALL, operationReference); 3781 Call call = bindingContext.get(CALL, operationReference); 3782 invokeFunction(call, StackValue.none(), resolvedCall); 3783 } 3784 3785 private boolean isIntRangeExpr(JetExpression rangeExpression) { 3786 if (rangeExpression instanceof JetBinaryExpression) { 3787 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 3788 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 3789 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); 3790 assert jetType != null; 3791 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3792 return INTEGRAL_RANGES.contains(descriptor); 3793 } 3794 } 3795 return false; 3796 } 3797 3798 private void throwNewException(@NotNull String className) { 3799 throwNewException(className, null); 3800 } 3801 3802 private void throwNewException(@NotNull String className, @Nullable String message) { 3803 v.anew(Type.getObjectType(className)); 3804 v.dup(); 3805 if (message != null) { 3806 v.visitLdcInsn(message); 3807 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V"); 3808 } 3809 else { 3810 v.invokespecial(className, "<init>", "()V"); 3811 } 3812 v.athrow(); 3813 } 3814 3815 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3816 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake"); 3817 return CallMaker.makeCall(fake, initializerAsReceiver); 3818 } 3819 3820 @Override 3821 public String toString() { 3822 return context.getContextDescriptor().toString(); 3823 } 3824 }