1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dx.cf.code; 18 19 import com.android.dx.rop.type.Type; 20 import com.android.dx.rop.type.TypeBearer; 21 22 /** 23 * Utility methods to merge various frame information. 24 */ 25 public final class Merger { 26 /** 27 * Merges two frame types. 28 * 29 * @param ft1 {@code non-null;} a frame type 30 * @param ft2 {@code non-null;} another frame type 31 * @return {@code non-null;} the result of merging the two types 32 */ 33 public static TypeBearer mergeType(TypeBearer ft1, TypeBearer ft2) { 34 if ((ft1 == null) || ft1.equals(ft2)) { 35 return ft1; 36 } else if (ft2 == null) { 37 return null; 38 } else { 39 Type type1 = ft1.getType(); 40 Type type2 = ft2.getType(); 41 42 if (type1 == type2) { 43 return type1; 44 } else if (type1.isReference() && type2.isReference()) { 45 if (type1 == Type.KNOWN_NULL) { 46 /* 47 * A known-null merges with any other reference type to 48 * be that reference type. 49 */ 50 return type2; 51 } else if (type2 == Type.KNOWN_NULL) { 52 /* 53 * The same as above, but this time it's type2 that's 54 * the known-null. 55 */ 56 return type1; 57 } else if (type1.isArray() && type2.isArray()) { 58 TypeBearer componentUnion = 59 mergeType(type1.getComponentType(), 60 type2.getComponentType()); 61 if (componentUnion == null) { 62 /* 63 * At least one of the types is a primitive type, 64 * so the merged result is just Object. 65 */ 66 return Type.OBJECT; 67 } 68 return ((Type) componentUnion).getArrayType(); 69 } else { 70 /* 71 * All other unequal reference types get merged to be 72 * Object in this phase. This is fine here, but it 73 * won't be the right thing to do in the verifier. 74 */ 75 return Type.OBJECT; 76 } 77 } else if (type1.isIntlike() && type2.isIntlike()) { 78 /* 79 * Merging two non-identical int-like types results in 80 * the type int. 81 */ 82 return Type.INT; 83 } else { 84 return null; 85 } 86 } 87 } 88 } 89