blob: c825fbf190ab0bf0e53413126f0f8b4b30d98edc [file] [log] [blame]
TDYa127d668a062012-04-13 12:36:57 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "runtime_support_builder.h"
18
Ian Rogers1d54e732013-05-02 21:10:01 -070019#include "gc/accounting/card_table.h"
TDYa127d668a062012-04-13 12:36:57 -070020#include "ir_builder.h"
TDYa127b08ed122012-06-05 23:51:19 -070021#include "monitor.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "mirror/object.h"
Ian Rogers166db042013-07-26 12:05:57 -070023#include "runtime_support_llvm_func_list.h"
TDYa127d668a062012-04-13 12:36:57 -070024#include "thread.h"
25
Brian Carlstrom37d48792013-03-22 14:14:45 -070026#include <llvm/IR/DerivedTypes.h>
27#include <llvm/IR/Function.h>
28#include <llvm/IR/Module.h>
29#include <llvm/IR/Type.h>
TDYa127d668a062012-04-13 12:36:57 -070030
Brian Carlstrom3e3d5912013-07-18 00:19:45 -070031using ::llvm::BasicBlock;
32using ::llvm::CallInst;
33using ::llvm::Function;
34using ::llvm::Value;
TDYa127d668a062012-04-13 12:36:57 -070035
36namespace art {
Ian Rogers4c1c2832013-03-04 18:30:13 -080037namespace llvm {
TDYa127d668a062012-04-13 12:36:57 -070038
Ian Rogers4c1c2832013-03-04 18:30:13 -080039RuntimeSupportBuilder::RuntimeSupportBuilder(::llvm::LLVMContext& context,
40 ::llvm::Module& module,
TDYa127d668a062012-04-13 12:36:57 -070041 IRBuilder& irb)
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070042 : context_(context), module_(module), irb_(irb) {
TDYa12783bb6622012-04-17 02:20:34 -070043 memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
TDYa127d668a062012-04-13 12:36:57 -070044#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
45 do { \
Ian Rogers4c1c2832013-03-04 18:30:13 -080046 ::llvm::Function* fn = module_.getFunction(#NAME); \
Brian Carlstrom2d888622013-07-18 17:02:00 -070047 DCHECK(fn != NULL) << "Function not found: " << #NAME; \
TDYa127de479be2012-05-31 08:03:26 -070048 runtime_support_func_decls_[runtime_support::ID] = fn; \
TDYa127d668a062012-04-13 12:36:57 -070049 } while (0);
50
TDYa127d668a062012-04-13 12:36:57 -070051 RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
TDYa127d668a062012-04-13 12:36:57 -070052}
53
TDYa127de479be2012-05-31 08:03:26 -070054
55/* Thread */
56
Ian Rogers4c1c2832013-03-04 18:30:13 -080057::llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
TDYa127de479be2012-05-31 08:03:26 -070058 Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
TDYa1279a129452012-07-19 03:10:08 -070059 CallInst* call_inst = irb_.CreateCall(func);
TDYa127de479be2012-05-31 08:03:26 -070060 call_inst->setOnlyReadsMemory();
61 irb_.SetTBAA(call_inst, kTBAAConstJObject);
62 return call_inst;
63}
64
Ian Rogers4c1c2832013-03-04 18:30:13 -080065::llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
TDYa127de479be2012-05-31 08:03:26 -070066 TBAASpecialType s_ty) {
TDYa1279a129452012-07-19 03:10:08 -070067 Value* thread = EmitGetCurrentThread();
TDYa127de479be2012-05-31 08:03:26 -070068 return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
69}
70
Ian Rogers4c1c2832013-03-04 18:30:13 -080071void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
TDYa127de479be2012-05-31 08:03:26 -070072 TBAASpecialType s_ty) {
TDYa1279a129452012-07-19 03:10:08 -070073 Value* thread = EmitGetCurrentThread();
TDYa127de479be2012-05-31 08:03:26 -070074 irb_.StoreToObjectOffset(thread, offset, value, s_ty);
75}
76
Ian Rogers4c1c2832013-03-04 18:30:13 -080077::llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(::llvm::Value* thread) {
TDYa127de479be2012-05-31 08:03:26 -070078 Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
TDYa127c1478262012-06-20 20:22:27 -070079 return irb_.CreateCall(func, thread);
TDYa127de479be2012-05-31 08:03:26 -070080}
81
82
83/* ShadowFrame */
84
Ian Rogers4c1c2832013-03-04 18:30:13 -080085::llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(::llvm::Value* new_shadow_frame,
86 ::llvm::Value* method,
TDYa127ce4cc0d2012-11-18 16:59:53 -080087 uint32_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -070088 Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
89 irb_.getArtFrameTy()->getPointerTo(),
90 kTBAARuntimeInfo);
91 EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
92 new_shadow_frame,
93 kTBAARuntimeInfo);
94
95 // Store the method pointer
96 irb_.StoreToObjectOffset(new_shadow_frame,
97 ShadowFrame::MethodOffset(),
98 method,
99 kTBAAShadowFrame);
100
Ian Rogers5438ad82012-10-15 17:22:44 -0700101 // Store the number of vregs
102 irb_.StoreToObjectOffset(new_shadow_frame,
103 ShadowFrame::NumberOfVRegsOffset(),
TDYa127ce4cc0d2012-11-18 16:59:53 -0800104 irb_.getInt32(num_vregs),
TDYa127de479be2012-05-31 08:03:26 -0700105 kTBAAShadowFrame);
106
107 // Store the link to previous shadow frame
108 irb_.StoreToObjectOffset(new_shadow_frame,
109 ShadowFrame::LinkOffset(),
110 old_shadow_frame,
111 kTBAAShadowFrame);
112
113 return old_shadow_frame;
114}
115
Ian Rogers4c1c2832013-03-04 18:30:13 -0800116::llvm::Value*
117RuntimeSupportBuilder::EmitPushShadowFrameNoInline(::llvm::Value* new_shadow_frame,
118 ::llvm::Value* method,
TDYa127ce4cc0d2012-11-18 16:59:53 -0800119 uint32_t num_vregs) {
TDYa127de479be2012-05-31 08:03:26 -0700120 Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
Ian Rogers4c1c2832013-03-04 18:30:13 -0800121 ::llvm::CallInst* call_inst =
TDYa127ce4cc0d2012-11-18 16:59:53 -0800122 irb_.CreateCall4(func,
TDYa127f54f3ac2012-10-16 22:39:00 -0700123 EmitGetCurrentThread(),
124 new_shadow_frame,
125 method,
TDYa127ce4cc0d2012-11-18 16:59:53 -0800126 irb_.getInt32(num_vregs));
TDYa127de479be2012-05-31 08:03:26 -0700127 irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
128 return call_inst;
129}
130
Ian Rogers4c1c2832013-03-04 18:30:13 -0800131void RuntimeSupportBuilder::EmitPopShadowFrame(::llvm::Value* old_shadow_frame) {
TDYa127de479be2012-05-31 08:03:26 -0700132 // Store old shadow frame to TopShadowFrame
133 EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
134 old_shadow_frame,
135 kTBAARuntimeInfo);
136}
137
138
TDYa127823433d2012-09-26 16:03:51 -0700139/* Exception */
140
Ian Rogers4c1c2832013-03-04 18:30:13 -0800141::llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
TDYa127823433d2012-09-26 16:03:51 -0700142 Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
143 return irb_.CreateCall(slow_func, EmitGetCurrentThread());
144}
TDYa127de479be2012-05-31 08:03:26 -0700145
Ian Rogers4c1c2832013-03-04 18:30:13 -0800146::llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
Jeff Haoa8fd2d52013-01-17 23:10:27 +0000147 Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
148 irb_.getJObjectTy(),
149 kTBAARuntimeInfo);
150 // If exception not null
151 return irb_.CreateIsNotNull(exception);
TDYa127de479be2012-05-31 08:03:26 -0700152}
153
TDYa127823433d2012-09-26 16:03:51 -0700154
155/* Suspend */
156
TDYa127de479be2012-05-31 08:03:26 -0700157void RuntimeSupportBuilder::EmitTestSuspend() {
158 Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
TDYa127de479be2012-05-31 08:03:26 -0700159 CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
TDYa127ce4cc0d2012-11-18 16:59:53 -0800160 irb_.SetTBAA(call_inst, kTBAAJRuntime);
TDYa127de479be2012-05-31 08:03:26 -0700161}
162
163
TDYa127b08ed122012-06-05 23:51:19 -0700164/* Monitor */
165
Ian Rogers4c1c2832013-03-04 18:30:13 -0800166void RuntimeSupportBuilder::EmitLockObject(::llvm::Value* object) {
TDYa127b08ed122012-06-05 23:51:19 -0700167 Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
168 irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
169}
170
Ian Rogers4c1c2832013-03-04 18:30:13 -0800171void RuntimeSupportBuilder::EmitUnlockObject(::llvm::Value* object) {
TDYa127b08ed122012-06-05 23:51:19 -0700172 Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
173 irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
TDYa127b08ed122012-06-05 23:51:19 -0700174}
175
176
Ian Rogers4c1c2832013-03-04 18:30:13 -0800177void RuntimeSupportBuilder::EmitMarkGCCard(::llvm::Value* value, ::llvm::Value* target_addr) {
TDYa1279a129452012-07-19 03:10:08 -0700178 Function* parent_func = irb_.GetInsertBlock()->getParent();
179 BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
180 BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);
TDYa127d668a062012-04-13 12:36:57 -0700181
Ian Rogers4c1c2832013-03-04 18:30:13 -0800182 ::llvm::Value* not_null = irb_.CreateIsNotNull(value);
TDYa1279a129452012-07-19 03:10:08 -0700183 irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);
TDYa127d668a062012-04-13 12:36:57 -0700184
TDYa1279a129452012-07-19 03:10:08 -0700185 irb_.SetInsertPoint(bb_mark_gc_card);
186 Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
187 irb_.getInt8Ty()->getPointerTo(),
188 kTBAAConstJObject);
189 Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
Ian Rogers1d54e732013-05-02 21:10:01 -0700190 Value* card_no = irb_.CreateLShr(target_addr_int,
191 irb_.getPtrEquivInt(gc::accounting::CardTable::kCardShift));
TDYa1279a129452012-07-19 03:10:08 -0700192 Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
Ian Rogers1d54e732013-05-02 21:10:01 -0700193 irb_.CreateStore(irb_.getInt8(gc::accounting::CardTable::kCardDirty), card_table_entry,
194 kTBAARuntimeInfo);
TDYa1279a129452012-07-19 03:10:08 -0700195 irb_.CreateBr(bb_cont);
TDYa127d668a062012-04-13 12:36:57 -0700196
TDYa1279a129452012-07-19 03:10:08 -0700197 irb_.SetInsertPoint(bb_cont);
TDYa127d668a062012-04-13 12:36:57 -0700198}
199
TDYa1279a129452012-07-19 03:10:08 -0700200
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700201} // namespace llvm
202} // namespace art