/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "scoped_thread_state_change.h"
#include "sea_ir/types/type_inference_visitor.h"
#include "sea_ir/types/type_inference.h"
#include "sea_ir/ir/sea.h"

namespace sea_ir {

void TypeInferenceVisitor::Visit(SignatureNode* parameter) {
  FunctionTypeInfo fti(graph_, type_cache_);
  std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes();
  DCHECK_LT(parameter->GetPositionInSignature(), arguments.size())
    << "Signature node position not present in signature.";
  crt_type_.push_back(arguments.at(parameter->GetPositionInSignature()));
}

void TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) {
  crt_type_.push_back(&type_cache_->Integer());
}

void TypeInferenceVisitor::Visit(PhiInstructionNode* instruction) {
  std::vector<const Type*> types_to_merge = GetOperandTypes(instruction);
  const Type* result_type = MergeTypes(types_to_merge);
  crt_type_.push_back(result_type);
}

void TypeInferenceVisitor::Visit(AddIntInstructionNode* instruction) {
  std::vector<const Type*> operand_types = GetOperandTypes(instruction);
  for (std::vector<const Type*>::const_iterator cit = operand_types.begin();
      cit != operand_types.end(); cit++) {
    if (*cit != NULL) {
      DCHECK((*cit)->IsInteger());
    }
  }
  crt_type_.push_back(&type_cache_->Integer());
}

void TypeInferenceVisitor::Visit(MoveResultInstructionNode* instruction) {
  std::vector<const Type*> operand_types = GetOperandTypes(instruction);
  const Type* operand_type = operand_types.at(0);
  crt_type_.push_back(operand_type);
}

void TypeInferenceVisitor::Visit(InvokeStaticInstructionNode* instruction) {
  FunctionTypeInfo fti(graph_, instruction, type_cache_);
  const Type* result_type = fti.GetReturnValueType();
  crt_type_.push_back(result_type);
}

std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(InstructionNode* instruction) {
  std::vector<InstructionNode*> sources = instruction->GetSSAProducers();
  std::vector<const Type*> types_to_merge;
  for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end();
      cit++) {
    const Type* source_type = type_data_->FindTypeOf((*cit)->Id());
    if (source_type != NULL) {
      types_to_merge.push_back(source_type);
    }
  }
  return types_to_merge;
}

const Type* TypeInferenceVisitor::MergeTypes(std::vector<const Type*>& types) const {
  const Type* type = NULL;
  if (types.size()>0) {
    type = *(types.begin());
    if (types.size()>1) {
      for (std::vector<const Type*>::const_iterator cit = types.begin();
          cit != types.end(); cit++) {
        if (!type->Equals(**cit)) {
          type = MergeTypes(type, *cit);
        }
      }
    }
  }
  return type;
}

const Type* TypeInferenceVisitor::MergeTypes(const Type* t1, const Type* t2) const {
  DCHECK(t2 != NULL);
  DCHECK(t1 != NULL);
  art::ScopedObjectAccess soa(art::Thread::Current());
  const Type* result = &(t1->Merge(*t2, type_cache_));
  return result;
}

}   // namespace sea_ir
