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

#include "gc/card_table.h"
#include "ir_builder.h"
#include "monitor.h"
#include "mirror/object.h"
#include "thread.h"

#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Type.h>

using namespace llvm;

namespace art {
namespace compiler_llvm {

using namespace runtime_support;


RuntimeSupportBuilder::RuntimeSupportBuilder(llvm::LLVMContext& context,
                                             llvm::Module& module,
                                             IRBuilder& irb)
    : context_(context), module_(module), irb_(irb)
{
  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
  do { \
    llvm::Function* fn = module_.getFunction(#NAME); \
    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
    runtime_support_func_decls_[runtime_support::ID] = fn; \
  } while (0);

#include "runtime_support_func_list.h"
  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}


/* Thread */

llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  CallInst* call_inst = irb_.CreateCall(func);
  call_inst->setOnlyReadsMemory();
  irb_.SetTBAA(call_inst, kTBAAConstJObject);
  return call_inst;
}

llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
                                                             TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}

void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
                                                    TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}

llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) {
  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
  return irb_.CreateCall(func, thread);
}


/* ShadowFrame */

llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                                        llvm::Value* method,
                                                        uint32_t num_vregs) {
  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                     irb_.getArtFrameTy()->getPointerTo(),
                                                     kTBAARuntimeInfo);
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          new_shadow_frame,
                          kTBAARuntimeInfo);

  // Store the method pointer
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::MethodOffset(),
                           method,
                           kTBAAShadowFrame);

  // Store the number of vregs
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::NumberOfVRegsOffset(),
                           irb_.getInt32(num_vregs),
                           kTBAAShadowFrame);

  // Store the link to previous shadow frame
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::LinkOffset(),
                           old_shadow_frame,
                           kTBAAShadowFrame);

  return old_shadow_frame;
}

llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
                                                   llvm::Value* method,
                                                   uint32_t num_vregs) {
  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
  llvm::CallInst* call_inst =
      irb_.CreateCall4(func,
                       EmitGetCurrentThread(),
                       new_shadow_frame,
                       method,
                       irb_.getInt32(num_vregs));
  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
  return call_inst;
}

void RuntimeSupportBuilder::EmitPopShadowFrame(llvm::Value* old_shadow_frame) {
  // Store old shadow frame to TopShadowFrame
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          old_shadow_frame,
                          kTBAARuntimeInfo);
}


/* Exception */

llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
}

llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
  Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
                                              irb_.getJObjectTy(),
                                              kTBAARuntimeInfo);
  // If exception not null
  return irb_.CreateIsNotNull(exception);
}


/* Suspend */

void RuntimeSupportBuilder::EmitTestSuspend() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
  irb_.SetTBAA(call_inst, kTBAAJRuntime);
}


/* Monitor */

void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                mirror::Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* real_monitor =
      irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, unheld and not recursively acquired.
  Value* unheld = irb_.CreateICmpEQ(real_monitor, irb_.getInt32(0));

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "lock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "lock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "lock_cont", parent_func);
  irb_.CreateCondBr(unheld, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);

  // Calculate new monitor: new = old | (lock_id << LW_LOCK_OWNER_SHIFT)
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getInt32Ty(), kTBAARuntimeInfo);

  Value* owner = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* new_monitor = irb_.CreateOr(monitor, owner);

  // Atomically update monitor.
  Value* old_monitor =
      irb_.CompareExchangeObjectOffset(object,
                                       mirror::Object::MonitorOffset().Int32Value(),
                                       monitor, new_monitor, kTBAARuntimeInfo);

  Value* retry_slow_path = irb_.CreateICmpEQ(old_monitor, monitor);
  irb_.CreateCondBr(retry_slow_path, bb_cont, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getJIntTy(),
                               kTBAARuntimeInfo);
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                mirror::Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, held by us and not recursively acquired
  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);
  // Set all bits to zero (except hash state)
  irb_.StoreToObjectOffset(object,
                           mirror::Object::MonitorOffset().Int32Value(),
                           hash_state,
                           kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}


void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);

  llvm::Value* not_null = irb_.CreateIsNotNull(value);
  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);

  irb_.SetInsertPoint(bb_mark_gc_card);
  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
                                               irb_.getInt8Ty()->getPointerTo(),
                                               kTBAAConstJObject);
  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
  Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(CardTable::kCardShift));
  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
  irb_.CreateStore(irb_.getInt8(CardTable::kCardDirty), card_table_entry, kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}


} // namespace compiler_llvm
} // namespace art
