16447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea/*
26447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Copyright (C) 2013 The Android Open Source Project
36447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
46447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Licensed under the Apache License, Version 2.0 (the "License");
56447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * you may not use this file except in compliance with the License.
66447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * You may obtain a copy of the License at
76447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
86447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *      http://www.apache.org/licenses/LICENSE-2.0
96447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea *
106447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * Unless required by applicable law or agreed to in writing, software
116447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * distributed under the License is distributed on an "AS IS" BASIS,
126447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * See the License for the specific language governing permissions and
146447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea * limitations under the License.
156447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea */
166447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
176547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea#include "scoped_thread_state_change.h"
186447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea#include "sea_ir/types/type_inference_visitor.h"
196447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea#include "sea_ir/types/type_inference.h"
20bfaf44fa3366955a2bacb2c38c79b53df2434582Dragos Sbirlea#include "sea_ir/ir/sea.h"
216447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
226447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleanamespace sea_ir {
236447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
2490af14d2743614e3e1453984b14258a6f145501dDragos Sbirleavoid TypeInferenceVisitor::Visit(SeaGraph* graph) {
2590af14d2743614e3e1453984b14258a6f145501dDragos Sbirlea  FunctionTypeInfo fti(graph_, type_cache_);
2690af14d2743614e3e1453984b14258a6f145501dDragos Sbirlea  const Type* return_type = fti.GetReturnValueType();
2790af14d2743614e3e1453984b14258a6f145501dDragos Sbirlea  crt_type_.push_back(return_type);
2890af14d2743614e3e1453984b14258a6f145501dDragos Sbirlea}
2990af14d2743614e3e1453984b14258a6f145501dDragos Sbirlea
306447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirleavoid TypeInferenceVisitor::Visit(SignatureNode* parameter) {
316447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  FunctionTypeInfo fti(graph_, type_cache_);
326447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
336447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
346447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea    << "Signature node position not present in signature.";
356447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea  crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
366447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}
376447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea
386547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleavoid TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) {
396547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  crt_type_.push_back(&type_cache_->Integer());
406547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
416547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
426547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleavoid TypeInferenceVisitor::Visit(PhiInstructionNode* instruction) {
436547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  std::vector<const Type*> types_to_merge = GetOperandTypes(instruction);
446547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  const Type* result_type = MergeTypes(types_to_merge);
456547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  crt_type_.push_back(result_type);
466547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
476547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
486547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleavoid TypeInferenceVisitor::Visit(AddIntInstructionNode* instruction) {
496547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  std::vector<const Type*> operand_types = GetOperandTypes(instruction);
506547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  for (std::vector<const Type*>::const_iterator cit = operand_types.begin();
516547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      cit != operand_types.end(); cit++) {
526547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    if (*cit != NULL) {
536547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      DCHECK((*cit)->IsInteger());
546547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    }
556547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  }
566547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  crt_type_.push_back(&type_cache_->Integer());
576547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
586547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
596547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleavoid TypeInferenceVisitor::Visit(MoveResultInstructionNode* instruction) {
606547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  std::vector<const Type*> operand_types = GetOperandTypes(instruction);
616547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  const Type* operand_type = operand_types.at(0);
626547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  crt_type_.push_back(operand_type);
636547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
646547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
656547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleavoid TypeInferenceVisitor::Visit(InvokeStaticInstructionNode* instruction) {
666547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  FunctionTypeInfo fti(graph_, instruction, type_cache_);
676547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  const Type* result_type = fti.GetReturnValueType();
686547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  crt_type_.push_back(result_type);
696547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
706547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
71423fb4d70f2ac36bf9f630146b4150771a8e7e76Dragos Sbirleastd::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(
72423fb4d70f2ac36bf9f630146b4150771a8e7e76Dragos Sbirlea    InstructionNode* instruction) const {
736547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  std::vector<InstructionNode*> sources = instruction->GetSSAProducers();
746547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  std::vector<const Type*> types_to_merge;
756547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end();
766547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      cit++) {
776547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    const Type* source_type = type_data_->FindTypeOf((*cit)->Id());
786547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    if (source_type != NULL) {
796547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      types_to_merge.push_back(source_type);
806547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    }
816547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  }
826547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  return types_to_merge;
836547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
846547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
856547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleaconst Type* TypeInferenceVisitor::MergeTypes(std::vector<const Type*>& types) const {
866547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  const Type* type = NULL;
8702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  if (types.size() > 0) {
886547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    type = *(types.begin());
8902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    if (types.size() > 1) {
906547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      for (std::vector<const Type*>::const_iterator cit = types.begin();
916547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea          cit != types.end(); cit++) {
926547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea        if (!type->Equals(**cit)) {
936547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea          type = MergeTypes(type, *cit);
946547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea        }
956547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea      }
966547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea    }
976547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  }
986547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  return type;
996547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
1006547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
1016547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirleaconst Type* TypeInferenceVisitor::MergeTypes(const Type* t1, const Type* t2) const {
1026547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  DCHECK(t2 != NULL);
1036547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  DCHECK(t1 != NULL);
1046547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  art::ScopedObjectAccess soa(art::Thread::Current());
1056547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  const Type* result = &(t1->Merge(*t2, type_cache_));
1066547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea  return result;
1076547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea}
1086547fa9749d0e32cc367d64f8cc6b3d65bf43a5dDragos Sbirlea
1096447919b5ee8d34c4767f908c7cd7223c224544cDragos Sbirlea}   // namespace sea_ir
110