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