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