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