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