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