Home | History | Annotate | Download | only in types
      1 /*
      2  * Copyright (C) 2013 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 #include "scoped_thread_state_change.h"
     18 #include "sea_ir/types/type_inference_visitor.h"
     19 #include "sea_ir/types/type_inference.h"
     20 #include "sea_ir/ir/sea.h"
     21 
     22 namespace sea_ir {
     23 
     24 void TypeInferenceVisitor::Visit(SeaGraph* graph) {
     25   FunctionTypeInfo fti(graph_, type_cache_);
     26   const Type* return_type = fti.GetReturnValueType();
     27   crt_type_.push_back(return_type);
     28 }
     29 
     30 void TypeInferenceVisitor::Visit(SignatureNode* parameter) {
     31   FunctionTypeInfo fti(graph_, type_cache_);
     32   std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
     33   DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
     34     << "Signature node position not present in signature.";
     35   crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
     36 }
     37 
     38 void TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) {
     39   crt_type_.push_back(&type_cache_->Integer());
     40 }
     41 
     42 void TypeInferenceVisitor::Visit(PhiInstructionNode* instruction) {
     43   std::vector<const Type*> types_to_merge = GetOperandTypes(instruction);
     44   const Type* result_type = MergeTypes(types_to_merge);
     45   crt_type_.push_back(result_type);
     46 }
     47 
     48 void TypeInferenceVisitor::Visit(AddIntInstructionNode* instruction) {
     49   std::vector<const Type*> operand_types = GetOperandTypes(instruction);
     50   for (std::vector<const Type*>::const_iterator cit = operand_types.begin();
     51       cit != operand_types.end(); cit++) {
     52     if (*cit != NULL) {
     53       DCHECK((*cit)->IsInteger());
     54     }
     55   }
     56   crt_type_.push_back(&type_cache_->Integer());
     57 }
     58 
     59 void TypeInferenceVisitor::Visit(MoveResultInstructionNode* instruction) {
     60   std::vector<const Type*> operand_types = GetOperandTypes(instruction);
     61   const Type* operand_type = operand_types.at(0);
     62   crt_type_.push_back(operand_type);
     63 }
     64 
     65 void TypeInferenceVisitor::Visit(InvokeStaticInstructionNode* instruction) {
     66   FunctionTypeInfo fti(graph_, instruction, type_cache_);
     67   const Type* result_type = fti.GetReturnValueType();
     68   crt_type_.push_back(result_type);
     69 }
     70 
     71 std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(
     72     InstructionNode* instruction) const {
     73   std::vector<InstructionNode*> sources = instruction->GetSSAProducers();
     74   std::vector<const Type*> types_to_merge;
     75   for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end();
     76       cit++) {
     77     const Type* source_type = type_data_->FindTypeOf((*cit)->Id());
     78     if (source_type != NULL) {
     79       types_to_merge.push_back(source_type);
     80     }
     81   }
     82   return types_to_merge;
     83 }
     84 
     85 const Type* TypeInferenceVisitor::MergeTypes(std::vector<const Type*>& types) const {
     86   const Type* type = NULL;
     87   if (types.size() > 0) {
     88     type = *(types.begin());
     89     if (types.size() > 1) {
     90       for (std::vector<const Type*>::const_iterator cit = types.begin();
     91           cit != types.end(); cit++) {
     92         if (!type->Equals(**cit)) {
     93           type = MergeTypes(type, *cit);
     94         }
     95       }
     96     }
     97   }
     98   return type;
     99 }
    100 
    101 const Type* TypeInferenceVisitor::MergeTypes(const Type* t1, const Type* t2) const {
    102   DCHECK(t2 != NULL);
    103   DCHECK(t1 != NULL);
    104   art::ScopedObjectAccess soa(art::Thread::Current());
    105   const Type* result = &(t1->Merge(*t2, type_cache_));
    106   return result;
    107 }
    108 
    109 }   // namespace sea_ir
    110