blob: 6639ca7c87bb8267c50cb3fd3a9a1a95a6f52d1e [file] [log] [blame]
Logan Chienf04364f2012-02-10 12:01:39 +08001/*
2 * Copyright (C) 2012 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
TDYa127eead4ac2012-06-03 07:15:25 -070017#include "stub_compiler.h"
Logan Chienf04364f2012-02-10 12:01:39 +080018
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Logan Chienf04364f2012-02-10 12:01:39 +080020#include "compiled_method.h"
Ian Rogers1212a022013-03-04 10:48:41 -080021#include "compiler/driver/compiler_driver.h"
Logan Chienf04364f2012-02-10 12:01:39 +080022#include "compiler_llvm.h"
23#include "ir_builder.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080024#include "llvm_compilation_unit.h"
Ian Rogers98573f92013-01-30 17:26:32 -080025#include "mirror/abstract_method.h"
Logan Chienf04364f2012-02-10 12:01:39 +080026#include "runtime_support_func.h"
Logan Chien937105a2012-04-02 02:37:37 +080027#include "utils_llvm.h"
Logan Chienf04364f2012-02-10 12:01:39 +080028
Logan Chienf04364f2012-02-10 12:01:39 +080029#include <llvm/BasicBlock.h>
30#include <llvm/Function.h>
31#include <llvm/GlobalVariable.h>
32#include <llvm/Intrinsics.h>
33
34#include <string>
35#include <string.h>
36
37namespace art {
38namespace compiler_llvm {
39
40using namespace runtime_support;
41
42
Ian Rogers1212a022013-03-04 10:48:41 -080043StubCompiler::StubCompiler(LlvmCompilationUnit* cunit, const CompilerDriver& driver)
44: cunit_(cunit), driver_(&driver), module_(cunit_->GetModule()),
TDYa127eead4ac2012-06-03 07:15:25 -070045 context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()) {
Logan Chienf04364f2012-02-10 12:01:39 +080046}
47
48
Logan Chien7a2a23a2012-06-06 11:01:00 +080049CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static,
Logan Chien12584172012-07-10 04:07:28 -070050 const char* shorty) {
Logan Chien7a2a23a2012-06-06 11:01:00 +080051 CHECK(shorty != NULL);
Logan Chienf04364f2012-02-10 12:01:39 +080052 size_t shorty_size = strlen(shorty);
53
54 // Function name
Logan Chien971bf3f2012-05-01 15:47:55 +080055 std::string func_name(ElfFuncName(cunit_->GetIndex()));
Logan Chienf04364f2012-02-10 12:01:39 +080056
57 // Get argument types
58 llvm::Type* arg_types[] = {
Logan Chienf04364f2012-02-10 12:01:39 +080059 irb_.getJObjectTy(), // Method object pointer
60 irb_.getJObjectTy(), // "this" object pointer (NULL for static)
61 irb_.getJObjectTy(), // Thread object pointer
62 irb_.getJValueTy()->getPointerTo(),
63 irb_.getJValueTy()->getPointerTo(),
64 };
65
66 // Function type
67 llvm::FunctionType* func_type =
68 llvm::FunctionType::get(irb_.getVoidTy(), arg_types, false);
69
70 // Create function
71 llvm::Function* func =
72 llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
73 func_name, module_);
74
75
76 // Create basic block for the body of this function
77 llvm::BasicBlock* block_body =
78 llvm::BasicBlock::Create(*context_, "upcall", func);
79
80 irb_.SetInsertPoint(block_body);
81
82 // Actual arguments
83 llvm::Function::arg_iterator arg_iter = func->arg_begin();
84
Logan Chienf04364f2012-02-10 12:01:39 +080085 llvm::Value* method_object_addr = arg_iter++;
86 llvm::Value* callee_this_addr = arg_iter++;
87 llvm::Value* thread_object_addr = arg_iter++;
88 llvm::Value* actual_args_array_addr = arg_iter++;
89 llvm::Value* retval_addr = arg_iter++;
90
91 // Setup thread pointer
TDYa127c1478262012-06-20 20:22:27 -070092 llvm::Value* old_thread_register = irb_.Runtime().EmitSetCurrentThread(thread_object_addr);
Logan Chienf04364f2012-02-10 12:01:39 +080093
94 // Accurate function type
Ian Rogers76ae4fe2013-02-27 16:03:41 -080095 llvm::Type* accurate_ret_type = irb_.getJType(shorty[0]);
Logan Chienf04364f2012-02-10 12:01:39 +080096
97 std::vector<llvm::Type*> accurate_arg_types;
98
99 accurate_arg_types.push_back(irb_.getJObjectTy()); // method object pointer
100
101 if (!is_static) {
102 accurate_arg_types.push_back(irb_.getJObjectTy());
103 }
104
105 for (size_t i = 1; i < shorty_size; ++i) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800106 accurate_arg_types.push_back(irb_.getJType(shorty[i]));
Logan Chienf04364f2012-02-10 12:01:39 +0800107 }
108
109 llvm::FunctionType* accurate_func_type =
110 llvm::FunctionType::get(accurate_ret_type, accurate_arg_types, false);
111
112 // Load actual arguments
113 std::vector<llvm::Value*> args;
114
115 args.push_back(method_object_addr);
116
117 if (!is_static) {
118 args.push_back(callee_this_addr);
119 }
120
121 for (size_t i = 1; i < shorty_size; ++i) {
122 char arg_shorty = shorty[i];
123
124 if (arg_shorty == 'Z' || arg_shorty == 'B' || arg_shorty == 'C' ||
125 arg_shorty == 'S' || arg_shorty == 'I' || arg_shorty == 'J' ||
126 arg_shorty == 'F' || arg_shorty == 'D' || arg_shorty == 'L') {
127
128 llvm::Type* arg_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800129 irb_.getJType(shorty[i])->getPointerTo();
Logan Chienf04364f2012-02-10 12:01:39 +0800130
131 llvm::Value* arg_jvalue_addr =
132 irb_.CreateConstGEP1_32(actual_args_array_addr, i - 1);
133
134 llvm::Value* arg_addr = irb_.CreateBitCast(arg_jvalue_addr, arg_type);
135
TDYa127aba61122012-05-04 18:28:36 -0700136 args.push_back(irb_.CreateLoad(arg_addr, kTBAAStackTemp));
Logan Chienf04364f2012-02-10 12:01:39 +0800137
138 } else {
Shih-wei Liao90d50992012-02-19 03:32:05 -0800139 LOG(FATAL) << "Unexpected arg shorty for invoke stub: " << shorty[i];
Logan Chienf04364f2012-02-10 12:01:39 +0800140 }
141 }
142
143 // Invoke managed method now!
144 llvm::Value* code_field_offset_value =
Ian Rogers98573f92013-01-30 17:26:32 -0800145 irb_.getPtrEquivInt(mirror::AbstractMethod::GetCodeOffset().Int32Value());
Logan Chienf04364f2012-02-10 12:01:39 +0800146
147 llvm::Value* code_field_addr =
148 irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
149 accurate_func_type->getPointerTo()->getPointerTo());
150
TDYa127ce4cc0d2012-11-18 16:59:53 -0800151 llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAARuntimeInfo);
Logan Chienf04364f2012-02-10 12:01:39 +0800152
TDYa1273fdb33a2012-08-21 20:09:35 -0700153 llvm::CallInst* retval = irb_.CreateCall(code_addr, args);
TDYa1273fdb33a2012-08-21 20:09:35 -0700154 for (size_t i = 1; i < shorty_size; ++i) {
155 switch(shorty[i]) {
156 case 'Z':
157 case 'C':
158 retval->addAttribute(i + (is_static ? 1 : 2), llvm::Attribute::ZExt);
159 break;
160
161 case 'B':
162 case 'S':
163 retval->addAttribute(i + (is_static ? 1 : 2), llvm::Attribute::SExt);
164 break;
165
166 default: break;
167 }
168 }
Logan Chienf04364f2012-02-10 12:01:39 +0800169
170 // Store the returned value
171 if (shorty[0] != 'V') {
172 llvm::Value* ret_addr =
173 irb_.CreateBitCast(retval_addr, accurate_ret_type->getPointerTo());
174
TDYa127aba61122012-05-04 18:28:36 -0700175 irb_.CreateStore(retval, ret_addr, kTBAAStackTemp);
Logan Chienf04364f2012-02-10 12:01:39 +0800176 }
177
TDYa127c1478262012-06-20 20:22:27 -0700178 // Restore thread register
179 irb_.Runtime().EmitSetCurrentThread(old_thread_register);
Logan Chienf04364f2012-02-10 12:01:39 +0800180 irb_.CreateRetVoid();
181
Logan Chien8b977d32012-02-21 19:14:55 +0800182 // Verify the generated function
TDYa127853cd092012-04-21 22:15:31 -0700183 VERIFY_LLVM_FUNCTION(*func);
Logan Chienf04364f2012-02-10 12:01:39 +0800184
Logan Chien971bf3f2012-05-01 15:47:55 +0800185 cunit_->Materialize();
Logan Chien8b977d32012-02-21 19:14:55 +0800186
Logan Chien598c5132012-04-28 22:00:44 +0800187 return new CompiledInvokeStub(cunit_->GetInstructionSet(),
Logan Chien971bf3f2012-05-01 15:47:55 +0800188 cunit_->GetCompiledCode());
TDYa127eead4ac2012-06-03 07:15:25 -0700189}
190
TDYa127eead4ac2012-06-03 07:15:25 -0700191
Logan Chien12584172012-07-10 04:07:28 -0700192CompiledInvokeStub* StubCompiler::CreateProxyStub(const char* shorty) {
Logan Chien7a2a23a2012-06-06 11:01:00 +0800193 CHECK(shorty != NULL);
TDYa127eead4ac2012-06-03 07:15:25 -0700194 size_t shorty_size = strlen(shorty);
195
TDYa127eead4ac2012-06-03 07:15:25 -0700196 // Function name
Logan Chien971bf3f2012-05-01 15:47:55 +0800197 std::string func_name(ElfFuncName(cunit_->GetIndex()));
TDYa127eead4ac2012-06-03 07:15:25 -0700198
199 // Accurate function type
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800200 llvm::Type* accurate_ret_type = irb_.getJType(shorty[0]);
Logan Chien7a2a23a2012-06-06 11:01:00 +0800201
TDYa127eead4ac2012-06-03 07:15:25 -0700202 std::vector<llvm::Type*> accurate_arg_types;
203 accurate_arg_types.push_back(irb_.getJObjectTy()); // method
204 accurate_arg_types.push_back(irb_.getJObjectTy()); // this
Logan Chien7a2a23a2012-06-06 11:01:00 +0800205
TDYa127eead4ac2012-06-03 07:15:25 -0700206 for (size_t i = 1; i < shorty_size; ++i) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800207 accurate_arg_types.push_back(irb_.getJType(shorty[i]));
TDYa127eead4ac2012-06-03 07:15:25 -0700208 }
Logan Chien7a2a23a2012-06-06 11:01:00 +0800209
TDYa127eead4ac2012-06-03 07:15:25 -0700210 llvm::FunctionType* accurate_func_type =
211 llvm::FunctionType::get(accurate_ret_type, accurate_arg_types, false);
212
213 // Create function
214 llvm::Function* func =
215 llvm::Function::Create(accurate_func_type, llvm::Function::ExternalLinkage,
216 func_name, module_);
TDYa1273fdb33a2012-08-21 20:09:35 -0700217 switch(shorty[0]) {
218 case 'Z':
219 case 'C':
220 func->addAttribute(0, llvm::Attribute::ZExt);
221 break;
222
223 case 'B':
224 case 'S':
225 func->addAttribute(0, llvm::Attribute::SExt);
226 break;
227
228 default: break;
229 }
TDYa127eead4ac2012-06-03 07:15:25 -0700230
231 // Create basic block for the body of this function
232 llvm::BasicBlock* block_body =
233 llvm::BasicBlock::Create(*context_, "proxy", func);
234 irb_.SetInsertPoint(block_body);
235
236 // JValue for proxy return
237 llvm::AllocaInst* jvalue_temp = irb_.CreateAlloca(irb_.getJValueTy());
238
239 // Load actual arguments
240 llvm::Function::arg_iterator arg_iter = func->arg_begin();
Logan Chien7a2a23a2012-06-06 11:01:00 +0800241
TDYa127eead4ac2012-06-03 07:15:25 -0700242 std::vector<llvm::Value*> args;
243 args.push_back(arg_iter++); // method
244 args.push_back(arg_iter++); // this
245 args.push_back(irb_.Runtime().EmitGetCurrentThread()); // thread
Logan Chien7a2a23a2012-06-06 11:01:00 +0800246
TDYa127eead4ac2012-06-03 07:15:25 -0700247 for (size_t i = 1; i < shorty_size; ++i) {
248 args.push_back(arg_iter++);
249 }
Logan Chien7a2a23a2012-06-06 11:01:00 +0800250
TDYa127eead4ac2012-06-03 07:15:25 -0700251 if (shorty[0] != 'V') {
252 args.push_back(jvalue_temp);
253 }
254
255 // Call ProxyInvokeHandler
256 // TODO: Partial inline ProxyInvokeHandler, don't use VarArg.
257 irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
Logan Chien7a2a23a2012-06-06 11:01:00 +0800258
TDYa127eead4ac2012-06-03 07:15:25 -0700259 if (shorty[0] != 'V') {
260 llvm::Value* result_addr =
261 irb_.CreateBitCast(jvalue_temp, accurate_ret_type->getPointerTo());
262 llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
263 irb_.CreateRet(retval);
264 } else {
265 irb_.CreateRetVoid();
266 }
267
268 // Verify the generated function
269 VERIFY_LLVM_FUNCTION(*func);
270
Logan Chien971bf3f2012-05-01 15:47:55 +0800271 cunit_->Materialize();
TDYa127eead4ac2012-06-03 07:15:25 -0700272
Logan Chien598c5132012-04-28 22:00:44 +0800273 return new CompiledInvokeStub(cunit_->GetInstructionSet(),
Logan Chien971bf3f2012-05-01 15:47:55 +0800274 cunit_->GetCompiledCode());
Logan Chienf04364f2012-02-10 12:01:39 +0800275}
276
277
278} // namespace compiler_llvm
279} // namespace art