Move compiler_llvm to art::llvm.

Also move the invoke stubs (soon to be removed) under compiler.
Start moving LLVM code under compiler. Will move GBC expander to dex/portable
once it is disentangled from other builds (moving toward solving Bug: 8195425).

Change-Id: I8829f9db6ade9ac8e32bd16198b90f83619769f1
diff --git a/src/compiler/llvm/runtime_support_builder.cc b/src/compiler/llvm/runtime_support_builder.cc
new file mode 100644
index 0000000..4548d18
--- /dev/null
+++ b/src/compiler/llvm/runtime_support_builder.cc
@@ -0,0 +1,279 @@
+/*
+ * 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 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 llvm
+} // namespace art