/*
 * 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 <llvm/Support/raw_ostream.h>
#include "sea.h"
#include "code_gen.h"

namespace sea_ir {

void CodeGenPrepassVisitor::Visit(PhiInstructionNode* phi) {
  Region* r = phi->GetRegion();
  const std::vector<Region*>* predecessors = r->GetPredecessors();
  DCHECK(NULL != predecessors);
  DCHECK_GT(predecessors->size(), 0u);
  llvm::PHINode *llvm_phi  = llvm_data_->builder_.CreatePHI(
      llvm::Type::getInt32Ty(*llvm_data_->context_), predecessors->size(), phi->StringId());
  llvm_data_->AddValue(phi, llvm_phi);
}

void CodeGenPassVisitor::Initialize(SeaGraph* graph) {
  Region* root_region;
  ordered_regions_.clear();
  for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
        cit != graph->GetRegions()->end(); cit++ ) {
    if ((*cit)->GetIDominator() == (*cit)) {
      root_region = *cit;
    }
  }
  ordered_regions_.push_back(root_region);
  for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
    Region* current_region = ordered_regions_.at(id);
    const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
    for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
            cit != dominated_regions->end(); cit++ ) {
      ordered_regions_.push_back(*cit);
    }
  }
}

void CodeGenPostpassVisitor::Visit(SeaGraph* graph) {
  std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
  std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
}
void CodeGenVisitor::Visit(SeaGraph* graph) {
  std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
  std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
}
void CodeGenPrepassVisitor::Visit(SeaGraph* graph) {
  std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
  std::cout << "=== SeaGraph ===" << parameters->size() << std::endl;
  // TODO: Extract correct types from dex for params and return value.
  DCHECK(parameters != NULL);
  std::vector<llvm::Type*> parameter_types(parameters->size(),
      llvm::Type::getInt32Ty(*llvm_data_->context_));
  // Build llvm function name.
  std::string function_name = art::StringPrintf("class=%d_method=%d", graph->class_def_idx_, graph->method_idx_);

  // Build llvm function type and parameters.
  llvm::FunctionType *function_type = llvm::FunctionType::get(
      llvm::Type::getInt32Ty(*llvm_data_->context_),
      parameter_types, false);
  llvm_data_->function_ = llvm::Function::Create(function_type,
      llvm::Function::ExternalLinkage, function_name, &llvm_data_->module_);
  unsigned param_id = 0;
  for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin();
      param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) {
    DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature";
    // Build parameter register name for LLVM IR clarity.
    std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister());
    arg_it->setName(arg_name);
    SignatureNode* parameter = parameters->at(param_id);
    llvm_data_->AddValue(parameter, arg_it);
  }

  std::vector<Region*>* regions = &ordered_regions_;
  DCHECK_GT(regions->size(), 0u);
  // Then create all other basic blocks.
  for (std::vector<Region*>::const_iterator cit = regions->begin(); cit != regions->end(); cit++) {
    llvm::BasicBlock* new_basic_block = llvm::BasicBlock::Create(*llvm_data_->context_,
        (*cit)->StringId(), llvm_data_->function_);
    llvm_data_->AddBlock((*cit), new_basic_block);
  }
}

void CodeGenPrepassVisitor::Visit(Region* region) {
  std::cout << " == Region " << region->StringId() << " ==" << std::endl;
  llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
}
void CodeGenPostpassVisitor::Visit(Region* region) {
  std::cout << " == Region " << region->StringId() << " ==" << std::endl;
  llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
}
void CodeGenVisitor::Visit(Region* region) {
  std::cout << " == Region " << region->StringId() << " ==" << std::endl;
  llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
}


void CodeGenVisitor::Visit(InstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  DCHECK(0); // This whole function is useful only during development.
}
void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "1.Instruction: " << instr << std::endl;
  llvm_data_->AddValue(instruction,
      llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
}
void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "2.Instruction: " << instr << std::endl;
  DCHECK_GT(instruction->GetSSAUses().size(), 0u);
  llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAUses().at(0));
  llvm_data_->builder_.CreateRet(return_value);
}
void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "3.Instruction: " << instr << std::endl;
  std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
  DCHECK_GT(ssa_uses.size(), 1u);
  InstructionNode* use_l = ssa_uses.at(0);
  llvm::Value* left = llvm_data_->GetValue(use_l);

  InstructionNode* use_r = ssa_uses.at(1);
  llvm::Value* right = llvm_data_->GetValue(use_r);
  llvm::Value* ifne = llvm_data_->builder_.CreateICmpNE(left, right, instruction->StringId());
  DCHECK(instruction->GetRegion() != NULL);
  std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
  DCHECK_GT(successors->size(), 0u);
  llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
  llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));

  llvm_data_->builder_.CreateCondBr(ifne, then_block, else_block);
}

/*
void CodeGenVisitor::Visit(AddIntLitInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "4.Instruction: " << instr << std::endl;
  std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
  InstructionNode* use_l = ssa_uses.at(0);
  llvm::Value* left = llvm_data->GetValue(use_l);
  llvm::Value* right = llvm::ConstantInt::get(*llvm_data->context_,
      llvm::APInt(32, instruction->GetConstValue()));
  llvm::Value* result = llvm_data->builder_.CreateAdd(left, right);
  llvm_data->AddValue(instruction, result);
}
*/
void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "5.Instruction: " << instr << std::endl;
  // TODO: Currently, this "mov" instruction is simulated by "res = return_register + 0".
  // This is inefficient, but should be optimized out by the coalescing phase of the reg alloc.
  // The TODO is to either ensure that this happens, or to
  // remove the move-result instructions completely from the IR
  // by merging them with the invoke-* instructions,
  // since their purpose of minimizing the number of opcodes in dex is
  // not relevant for the IR. (Will need to have different
  // instruction subclasses for functions and procedures.)
  std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
  InstructionNode* use_l = ssa_uses.at(0);
  llvm::Value* left = llvm_data_->GetValue(use_l);
  llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
  llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
  llvm_data_->AddValue(instruction, result);
}
void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
  std::string instr = invoke->GetInstruction()->DumpString(NULL);
  std::cout << "6.Instruction: " << instr << std::endl;
  // TODO: Build callee llvm function name.
  std::string function_name = art::StringPrintf("class=%d_method=%d", 0, 1);
  llvm::Function *callee = llvm_data_->module_.getFunction(function_name);
  // TODO: Add proper checking of the matching between formal and actual signature.
  DCHECK(NULL != callee);
  std::vector<llvm::Value*> parameter_values;
  std::vector<InstructionNode*> parameter_sources = invoke->GetSSAUses();
  for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
      cit != parameter_sources.end(); ++cit) {
    llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
    DCHECK(NULL != parameter_value);
    parameter_values.push_back(parameter_value);
  }
  llvm::Value* return_value = llvm_data_->builder_.CreateCall(callee,
      parameter_values, invoke->StringId());
  llvm_data_->AddValue(invoke, return_value);
}
void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "7.Instruction: " << instr << std::endl;
  std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
  DCHECK_GT(ssa_uses.size(), 1u);
  InstructionNode* use_l = ssa_uses.at(0);
  InstructionNode* use_r = ssa_uses.at(1);
  llvm::Value* left = llvm_data_->GetValue(use_l);
  llvm::Value* right = llvm_data_->GetValue(use_r);
  llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
  llvm_data_->AddValue(instruction, result);
}
void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "8.Instruction: " << instr << std::endl;
  std::vector<sea_ir::Region*>* targets = instruction->GetRegion()->GetSuccessors();
  DCHECK_EQ(targets->size(), 1u);
  llvm::BasicBlock* target_block = llvm_data_->GetBlock(targets->at(0));
  llvm_data_->builder_.CreateBr(target_block);
}
void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
  std::string instr = instruction->GetInstruction()->DumpString(NULL);
  std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
  std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
  DCHECK_GT(ssa_uses.size(), 0u);
  InstructionNode* use_l = ssa_uses.at(0);
  llvm::Value* left = llvm_data_->GetValue(use_l);
  llvm::Value* ifeqz = llvm_data_->builder_.CreateICmpEQ(left,
      llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt::getNullValue(32)),
      instruction->StringId());
  DCHECK(instruction->GetRegion() != NULL);
  std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
  DCHECK_GT(successors->size(), 0u);
  llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
  llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
  llvm_data_->builder_.CreateCondBr(ifeqz, then_block, else_block);
}

void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) {
  std::cout << "Phi node for: " << phi->GetRegisterNumber() << std::endl;
  Region* r = phi->GetRegion();
  const std::vector<Region*>* predecessors = r->GetPredecessors();
  DCHECK(NULL != predecessors);
  DCHECK_GT(predecessors->size(), 0u);
  // Prepass (CodeGenPrepassVisitor) should create the phi function value.
  llvm::PHINode* llvm_phi = (llvm::PHINode*) llvm_data_->GetValue(phi);
  int predecessor_pos = 0;
  for (std::vector<Region*>::const_iterator cit = predecessors->begin();
      cit != predecessors->end(); ++cit) {
    std::vector<InstructionNode*>* defining_instructions = phi->GetSSAUses(predecessor_pos++);
    DCHECK_EQ(defining_instructions->size(), 1u);
    InstructionNode* defining_instruction = defining_instructions->at(0);
    DCHECK(NULL != defining_instruction);
    Region* incoming_region = *cit;
    llvm::BasicBlock* incoming_basic_block = llvm_data_->GetBlock(incoming_region);
    llvm::Value* incoming_value = llvm_data_->GetValue(defining_instruction);
    llvm_phi->addIncoming(incoming_value, incoming_basic_block);
  }
}

void CodeGenVisitor::Visit(SignatureNode* signature) {
  std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
  DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register.";
}
void CodeGenPrepassVisitor::Visit(SignatureNode* signature) {
  std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
  DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register.";
}
void CodeGenPostpassVisitor::Visit(SignatureNode* signature) {
  std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl;
  DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register.";
}

} // end namespace sea_ir
