/*
 * 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 "runtime_support_builder_arm.h"

#include "ir_builder.h"
#include "thread.h"
#include "utils_llvm.h"

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

#include <vector>

using ::llvm::CallInst;
using ::llvm::Function;
using ::llvm::FunctionType;
using ::llvm::InlineAsm;
using ::llvm::IntegerType;
using ::llvm::Type;
using ::llvm::Value;

namespace {

char LDRSTRSuffixByType(art::llvm::IRBuilder& irb, Type* type) {
  int width = type->isPointerTy() ?
              irb.getSizeOfPtrEquivInt()*8 :
              ::llvm::cast<IntegerType>(type)->getBitWidth();
  switch (width) {
    case 8:  return 'b';
    case 16: return 'h';
    case 32: return ' ';
    default:
      LOG(FATAL) << "Unsupported width: " << width;
      return ' ';
  }
}

} // namespace

namespace art {
namespace llvm {

/* Thread */

Value* RuntimeSupportBuilderARM::EmitGetCurrentThread() {
  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), "mov $0, r9", "=r", false);
  CallInst* thread = irb_.CreateCall(func);
  thread->setDoesNotAccessMemory();
  irb_.SetTBAA(thread, kTBAAConstJObject);
  return thread;
}

Value* RuntimeSupportBuilderARM::EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
                                                          TBAASpecialType s_ty) {
  FunctionType* func_ty = FunctionType::get(/*Result=*/type,
                                            /*isVarArg=*/false);
  std::string inline_asm(StringPrintf("ldr%c $0, [r9, #%d]",
                                      LDRSTRSuffixByType(irb_, type),
                                      static_cast<int>(offset)));
  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "=r", true);
  CallInst* result = irb_.CreateCall(func);
  result->setOnlyReadsMemory();
  irb_.SetTBAA(result, s_ty);
  return result;
}

void RuntimeSupportBuilderARM::EmitStoreToThreadOffset(int64_t offset, Value* value,
                                                       TBAASpecialType s_ty) {
  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                            /*Params=*/value->getType(),
                                            /*isVarArg=*/false);
  std::string inline_asm(StringPrintf("str%c $0, [r9, #%d]",
                                      LDRSTRSuffixByType(irb_, value->getType()),
                                      static_cast<int>(offset)));
  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "r", true);
  CallInst* call_inst = irb_.CreateCall(func, value);
  irb_.SetTBAA(call_inst, s_ty);
}

Value* RuntimeSupportBuilderARM::EmitSetCurrentThread(Value* thread) {
  // Separate to two InlineAsm: The first one produces the return value, while the second,
  // sets the current thread.
  // LLVM can delete the first one if the caller in LLVM IR doesn't use the return value.
  //
  // Here we don't call EmitGetCurrentThread, because we mark it as DoesNotAccessMemory and
  // ConstJObject. We denote side effect to "true" below instead, so LLVM won't
  // reorder these instructions incorrectly.
  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), "mov $0, r9", "=r", true);
  CallInst* old_thread_register = irb_.CreateCall(func);
  old_thread_register->setOnlyReadsMemory();

  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                            /*Params=*/irb_.getJObjectTy(),
                                            /*isVarArg=*/false);
  func = InlineAsm::get(func_ty, "mov r9, $0", "r", true);
  irb_.CreateCall(func, thread);
  return old_thread_register;
}


/* Monitor */

void RuntimeSupportBuilderARM::EmitLockObject(Value* object) {
  RuntimeSupportBuilder::EmitLockObject(object);
  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                            /*isVarArg=*/false);
  InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true);
  irb_.CreateCall(func);
}

void RuntimeSupportBuilderARM::EmitUnlockObject(Value* object) {
  RuntimeSupportBuilder::EmitUnlockObject(object);
  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
                                            /*isVarArg=*/false);
  InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true);
  irb_.CreateCall(func);
}

} // namespace llvm
} // namespace art
