Home | History | Annotate | Download | only in code
      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