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 
Visit(SeaGraph * graph)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 
Visit(SignatureNode * parameter)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 
Visit(UnnamedConstInstructionNode * instruction)38 void TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) {
39   crt_type_.push_back(&type_cache_->Integer());
40 }
41 
Visit(PhiInstructionNode * instruction)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 
Visit(AddIntInstructionNode * instruction)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 
Visit(MoveResultInstructionNode * instruction)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 
Visit(InvokeStaticInstructionNode * instruction)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 
GetOperandTypes(InstructionNode * instruction) const71 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 
MergeTypes(std::vector<const Type * > & types) const85 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 
MergeTypes(const Type * t1,const Type * t2) const101 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