1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 package com.android.tools.r8.ir.code; 5 6 import com.android.tools.r8.code.ReturnObject; 7 import com.android.tools.r8.code.ReturnVoid; 8 import com.android.tools.r8.code.ReturnWide; 9 import com.android.tools.r8.dex.Constants; 10 import com.android.tools.r8.errors.Unreachable; 11 import com.android.tools.r8.graph.AppInfo; 12 import com.android.tools.r8.graph.DexType; 13 import com.android.tools.r8.ir.conversion.DexBuilder; 14 import com.android.tools.r8.ir.optimize.Inliner.Constraint; 15 16 public class Return extends JumpInstruction { 17 18 // Need to keep track of the original return type, as a null value will have MoveType.SINGLE. 19 final private MoveType returnType; 20 Return()21 public Return() { 22 super(null); 23 returnType = null; 24 } 25 Return(Value value, MoveType returnType)26 public Return(Value value, MoveType returnType) { 27 super(null, value); 28 this.returnType = returnType; 29 } 30 isReturnVoid()31 public boolean isReturnVoid() { 32 return inValues.size() == 0; 33 } 34 getReturnType()35 public MoveType getReturnType() { 36 return returnType; 37 } 38 returnValue()39 public Value returnValue() { 40 assert !isReturnVoid(); 41 return inValues.get(0); 42 } 43 createDexInstruction(DexBuilder builder)44 public com.android.tools.r8.code.Instruction createDexInstruction(DexBuilder builder) { 45 if (isReturnVoid()) { 46 return new ReturnVoid(); 47 } else { 48 switch (returnValue().type) { 49 case OBJECT: 50 assert returnType == MoveType.OBJECT; 51 return new ReturnObject(builder.allocatedRegister(returnValue(), getNumber())); 52 case SINGLE: 53 if (returnType == MoveType.OBJECT) { 54 return new ReturnObject(builder.allocatedRegister(returnValue(), getNumber())); 55 } else { 56 assert returnType == MoveType.SINGLE; 57 return new com.android.tools.r8.code.Return(builder.allocatedRegister(returnValue(), getNumber())); 58 } 59 case WIDE: 60 assert returnType == MoveType.WIDE; 61 return new ReturnWide(builder.allocatedRegister(returnValue(), getNumber())); 62 default: 63 throw new Unreachable(); 64 } 65 } 66 } 67 68 @Override buildDex(DexBuilder builder)69 public void buildDex(DexBuilder builder) { 70 builder.add(this, createDexInstruction(builder)); 71 } 72 73 @Override identicalNonValueParts(Instruction other)74 public boolean identicalNonValueParts(Instruction other) { 75 if (isReturnVoid()) { 76 return other.asReturn().isReturnVoid(); 77 } else { 78 return other.asReturn().returnValue().type == returnValue().type; 79 } 80 } 81 82 @Override compareNonValueParts(Instruction other)83 public int compareNonValueParts(Instruction other) { 84 if (isReturnVoid()) { 85 return other.asReturn().isReturnVoid() ? 0 : -1; 86 } else { 87 return returnValue().type.ordinal() - other.asReturn().returnValue().type.ordinal(); 88 } 89 } 90 91 @Override maxInValueRegister()92 public int maxInValueRegister() { 93 return Constants.U8BIT_MAX; 94 } 95 96 @Override maxOutValueRegister()97 public int maxOutValueRegister() { 98 assert false : "Return defines no values."; 99 return 0; 100 } 101 102 @Override isReturn()103 public boolean isReturn() { 104 return true; 105 } 106 107 @Override asReturn()108 public Return asReturn() { 109 return this; 110 } 111 112 @Override inliningConstraint(AppInfo info, DexType holder)113 public Constraint inliningConstraint(AppInfo info, DexType holder) { 114 return Constraint.ALWAYS; 115 } 116 } 117