/*
 * 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;


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

DalvikReg::DalvikReg(MethodCompiler& method_compiler, const std::string& name)
: method_compiler_(&method_compiler), irb_(method_compiler.GetIRBuilder()),
  reg_name_(name), reg_32_(NULL), reg_64_(NULL), reg_obj_(NULL) {
}


DalvikReg::~DalvikReg() {
}


llvm::Type* DalvikReg::GetRegCategoryEquivSizeTy(IRBuilder& irb, RegCategory reg_cat) {
  switch (reg_cat) {
  case kRegCat1nr:  return irb.getJIntTy();
  case kRegCat2:    return irb.getJLongTy();
  case kRegObject:  return irb.getJObjectTy();
  default:
    LOG(FATAL) << "Unknown register category: " << reg_cat;
    return NULL;
  }
}


char DalvikReg::GetRegCategoryNamePrefix(RegCategory reg_cat) {
  switch (reg_cat) {
  case kRegCat1nr:  return 'r';
  case kRegCat2:    return 'w';
  case kRegObject:  return 'p';
  default:
    LOG(FATAL) << "Unknown register category: " << reg_cat;
    return '\0';
  }
}


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";

  llvm::Value* value = NULL;
  switch (space) {
  case kReg:
  case kField:
    value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
    break;

  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.
      value = RegCat1Trunc(irb_.CreateLoad(GetAddr(jty), kTBAARegister),
                           irb_.getJType(jty, space));
      break;

    case kInt:
    case kLong:
    case kFloat:
    case kDouble:
    case kObject:
      value = irb_.CreateLoad(GetAddr(jty), kTBAARegister);
      break;

    default:
      LOG(FATAL) << "Unknown java type: " << jty;
      return NULL;
    }
    break;

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

  if (jty == kFloat || jty == kDouble) {
    value = irb_.CreateBitCast(value, irb_.getJType(jty, space));
  }
  return value;
}


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

  if (jty == kFloat || jty == kDouble) {
    value = irb_.CreateBitCast(value, irb_.getJType(jty, kReg));
  }

  switch (space) {
  case kReg:
  case kField:
    irb_.CreateStore(value, GetAddr(jty), kTBAARegister);
    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), kTBAARegister);
      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), kTBAARegister);
      break;

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

    default:
      LOG(FATAL) << "Unknown java type: " << jty;
    }
  }
}


llvm::Value* DalvikReg::GetAddr(JType jty) {
  switch (GetRegCategoryFromJType(jty)) {
  case kRegCat1nr:
    if (reg_32_ == NULL) {
      reg_32_ = method_compiler_->AllocDalvikReg(kRegCat1nr, reg_name_);
    }
    return reg_32_;

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

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

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