/*
 * Copyright (C) 2012 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 "dalvik_reg.h"

#include "ir_builder.h"
#include "method_compiler.h"

using namespace art;
using namespace art::compiler_llvm;


namespace {

  class DalvikLocalVarReg : public DalvikReg {
   public:
    DalvikLocalVarReg(MethodCompiler& method_compiler, uint32_t reg_idx);

    virtual ~DalvikLocalVarReg();

   private:
    virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);

   private:
    uint32_t reg_idx_;
    llvm::Value* reg_32_;
    llvm::Value* reg_64_;
    llvm::Value* reg_obj_;
  };

  class DalvikRetValReg : public DalvikReg {
   public:
    DalvikRetValReg(MethodCompiler& method_compiler);

    virtual ~DalvikRetValReg();

   private:
    virtual llvm::Value* GetRawAddr(JType jty, JTypeSpace space);

   private:
    llvm::Value* reg_32_;
    llvm::Value* reg_64_;
    llvm::Value* reg_obj_;
  };

} // anonymous namespace


//----------------------------------------------------------------------------
// Dalvik Register
//----------------------------------------------------------------------------

DalvikReg* DalvikReg::CreateLocalVarReg(MethodCompiler& method_compiler,
                                        uint32_t reg_idx) {
  return new DalvikLocalVarReg(method_compiler, reg_idx);
}


DalvikReg* DalvikReg::CreateRetValReg(MethodCompiler& method_compiler) {
  return new DalvikRetValReg(method_compiler);
}


DalvikReg::DalvikReg(MethodCompiler& method_compiler)
: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()) {
}


DalvikReg::~DalvikReg() {
}


inline llvm::Value* DalvikReg::RegCat1SExt(llvm::Value* value) {
  return irb_.CreateSExt(value, irb_.getJIntTy());
}


inline llvm::Value* DalvikReg::RegCat1ZExt(llvm::Value* value) {
  return irb_.CreateZExt(value, irb_.getJIntTy());
}


inline llvm::Value* DalvikReg::RegCat1Trunc(llvm::Value* value,
                                            llvm::Type* ty) {
  return irb_.CreateTrunc(value, ty);
}


llvm::Value* DalvikReg::GetValue(JType jty, JTypeSpace space) {
  DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";

  switch (space) {
  case kReg:
  case kField:
    return irb_.CreateLoad(GetAddr(jty, space));

  case kAccurate:
  case kArray:
    switch (jty) {
    case kVoid:
      LOG(FATAL) << "Dalvik register with void type has no value";
      return NULL;

    case kBoolean:
    case kChar:
    case kByte:
    case kShort:
      // NOTE: In array type space, boolean is truncated from i32 to i8, while
      // in accurate type space, boolean is truncated from i32 to i1.
      // For the other cases, array type space is equal to accurate type space.
      return RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space)),
                          irb_.getJType(jty, space));

    case kInt:
    case kLong:
    case kFloat:
    case kDouble:
    case kObject:
      return irb_.CreateLoad(GetAddr(jty, space));
    }
  }

  LOG(FATAL) << "Couldn't GetValue of JType " << jty;
  return NULL;
}


void DalvikReg::SetValue(JType jty, JTypeSpace space, llvm::Value* value) {
  DCHECK_NE(jty, kVoid) << "Dalvik register will never be void type";

  switch (space) {
  case kReg:
  case kField:
    irb_.CreateStore(value, GetAddr(jty, space));
    return;

  case kAccurate:
  case kArray:
    switch (jty) {
    case kVoid:
      break;

    case kBoolean:
    case kChar:
      // NOTE: In accurate type space, we have to zero extend boolean from
      // i1 to i32, and char from i16 to i32.  In array type space, we have
      // to zero extend boolean from i8 to i32, and char from i16 to i32.
      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space));
      break;

    case kByte:
    case kShort:
      // NOTE: In accurate type space, we have to signed extend byte from
      // i8 to i32, and short from i16 to i32.  In array type space, we have
      // to sign extend byte from i8 to i32, and short from i16 to i32.
      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space));
      break;

    case kInt:
    case kLong:
    case kFloat:
    case kDouble:
    case kObject:
      irb_.CreateStore(value, GetAddr(jty, space));
      break;
    }
  }
}


llvm::Value* DalvikReg::GetAddr(JType jty, JTypeSpace space) {
  if (jty == kFloat) {
    return irb_.CreateBitCast(GetRawAddr(jty, space),
                              irb_.getJFloatTy()->getPointerTo());
  } else if (jty == kDouble) {
    return irb_.CreateBitCast(GetRawAddr(jty, space),
                              irb_.getJDoubleTy()->getPointerTo());
  } else {
    return GetRawAddr(jty, space);
  }
}


//----------------------------------------------------------------------------
// Dalvik Local Variable Register
//----------------------------------------------------------------------------

DalvikLocalVarReg::DalvikLocalVarReg(MethodCompiler& method_compiler,
                                     uint32_t reg_idx)
: DalvikReg(method_compiler), reg_idx_(reg_idx),
  reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
}


DalvikLocalVarReg::~DalvikLocalVarReg() {
}


llvm::Value* DalvikLocalVarReg::GetRawAddr(JType jty, JTypeSpace space) {
  switch (GetRegCategoryFromJType(jty)) {
  case kRegCat1nr:
    if (reg_32_ == NULL) {
      reg_32_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat1nr, reg_idx_);
    }
    return reg_32_;

  case kRegCat2:
    if (reg_64_ == NULL) {
      reg_64_ = method_compiler_->AllocDalvikLocalVarReg(kRegCat2, reg_idx_);
    }
    return reg_64_;

  case kRegObject:
    if (reg_obj_ == NULL) {
      reg_obj_ = method_compiler_->AllocDalvikLocalVarReg(kRegObject, reg_idx_);
    }
    return reg_obj_;

  default:
    LOG(FATAL) << "Unexpected register category: "
               << GetRegCategoryFromJType(jty);
    return NULL;
  }
}


//----------------------------------------------------------------------------
// Dalvik Returned Value Temporary Register
//----------------------------------------------------------------------------

DalvikRetValReg::DalvikRetValReg(MethodCompiler& method_compiler)
: DalvikReg(method_compiler), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
}


DalvikRetValReg::~DalvikRetValReg() {
}


llvm::Value* DalvikRetValReg::GetRawAddr(JType jty, JTypeSpace space) {
  switch (GetRegCategoryFromJType(jty)) {
  case kRegCat1nr:
    if (reg_32_ == NULL) {
      reg_32_ = method_compiler_->AllocDalvikRetValReg(kRegCat1nr);
    }
    return reg_32_;

  case kRegCat2:
    if (reg_64_ == NULL) {
      reg_64_ = method_compiler_->AllocDalvikRetValReg(kRegCat2);
    }
    return reg_64_;

  case kRegObject:
    if (reg_obj_ == NULL) {
      reg_obj_ = method_compiler_->AllocDalvikRetValReg(kRegObject);
    }
    return reg_obj_;

  default:
    LOG(FATAL) << "Unexpected register category: "
               << GetRegCategoryFromJType(jty);
    return NULL;
  }
}
