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