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