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