blob: 65d53b96e679cf4ce555be33ce1a5d186ca0f8f2 [file] [log] [blame]
Shih-wei Liaod1fec812012-02-13 09:51:10 -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
17#include "compiler_llvm.h"
18
Shih-wei Liaoc4c98812012-03-10 21:55:51 -080019#include "class_linker.h"
Logan Chien8b977d32012-02-21 19:14:55 +080020#include "compilation_unit.h"
Logan Chienf7015fd2012-03-18 01:19:37 +080021#include "compiled_method.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080022#include "compiler.h"
Shih-wei Liaoc4c98812012-03-10 21:55:51 -080023#include "dex_cache.h"
Logan Chien0f0899a2012-03-23 10:48:18 +080024#include "elf_image.h"
Logan Chienf7015fd2012-03-18 01:19:37 +080025#include "elf_loader.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080026#include "ir_builder.h"
Logan Chien88894ee2012-02-13 16:42:22 +080027#include "jni_compiler.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080028#include "method_compiler.h"
Logan Chien4dd96f52012-02-29 01:26:58 +080029#include "oat_compilation_unit.h"
Logan Chien7f767612012-03-01 18:54:49 +080030#include "stl_util.h"
Logan Chienf04364f2012-02-10 12:01:39 +080031#include "upcall_compiler.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080032
Logan Chiendd7cf5b2012-03-01 12:55:19 +080033#include <llvm/LinkAllPasses.h>
34#include <llvm/LinkAllVMCore.h>
Logan Chien4c17dff2012-03-02 20:15:46 +080035#include <llvm/Support/CommandLine.h>
Logan Chien013b6f22012-03-02 17:20:33 +080036#include <llvm/Support/ManagedStatic.h>
Logan Chien8b977d32012-02-21 19:14:55 +080037#include <llvm/Support/TargetSelect.h>
38#include <llvm/Support/Threading.h>
39
Logan Chien013b6f22012-03-02 17:20:33 +080040namespace llvm {
41 extern bool TimePassesIsEnabled;
42}
43
Logan Chien4c17dff2012-03-02 20:15:46 +080044extern llvm::cl::opt<bool> EnableARMLongCalls;
45// NOTE: Although EnableARMLongCalls is defined in llvm/lib/Target/ARM/
46// ARMISelLowering.cpp, however, it is not in the llvm namespace.
47
Logan Chien8b977d32012-02-21 19:14:55 +080048
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080049namespace {
Logan Chien8b977d32012-02-21 19:14:55 +080050
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080051pthread_once_t llvm_initialized = PTHREAD_ONCE_INIT;
52
53void InitializeLLVM() {
Logan Chien013b6f22012-03-02 17:20:33 +080054 // NOTE: Uncomment following line to show the time consumption of LLVM passes
55 //llvm::TimePassesIsEnabled = true;
56
Logan Chien8b977d32012-02-21 19:14:55 +080057 // Initialize LLVM target, MC subsystem, asm printer, and asm parser
58 llvm::InitializeAllTargets();
59 llvm::InitializeAllTargetMCs();
60 llvm::InitializeAllAsmPrinters();
61 llvm::InitializeAllAsmParsers();
62 // TODO: Maybe we don't have to initialize "all" targets.
63
Logan Chien4c17dff2012-03-02 20:15:46 +080064 // Enable -arm-long-calls
65 EnableARMLongCalls = true;
66
Logan Chiendd7cf5b2012-03-01 12:55:19 +080067 // Initialize LLVM optimization passes
68 llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
69
70 llvm::initializeCore(registry);
71 llvm::initializeScalarOpts(registry);
72 llvm::initializeIPO(registry);
73 llvm::initializeAnalysis(registry);
74 llvm::initializeIPA(registry);
75 llvm::initializeTransformUtils(registry);
76 llvm::initializeInstCombine(registry);
77 llvm::initializeInstrumentation(registry);
78 llvm::initializeTarget(registry);
79
Logan Chien8b977d32012-02-21 19:14:55 +080080 // Initialize LLVM internal data structure for multithreading
81 llvm::llvm_start_multithreaded();
82}
83
Logan Chienf1306552012-03-16 11:17:53 +080084// The Guard to Shutdown LLVM
Logan Chienaeb53032012-03-18 02:29:38 +080085// llvm::llvm_shutdown_obj llvm_guard;
86// TODO: We are commenting out this line because this will cause SEGV from
87// time to time.
88// Two reasons: (1) the order of the destruction of static objects, or
89// (2) dlopen/dlclose side-effect on static objects.
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080090
91} // anonymous namespace
92
93
94namespace art {
95namespace compiler_llvm {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080096
97
Logan Chiene75a8cc2012-02-24 12:26:43 +080098llvm::Module* makeLLVMModuleContents(llvm::Module* module);
Logan Chien42e0e152012-01-13 15:42:36 +080099
100
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800101CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -0800102 : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
Logan Chien7f767612012-03-01 18:54:49 +0800103 insn_set_(insn_set), curr_cunit_(NULL) {
Shih-wei Liaofc34adb2012-03-07 08:51:44 -0800104
105
106 // Initialize LLVM libraries
107 pthread_once(&llvm_initialized, InitializeLLVM);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800108}
109
110
111CompilerLLVM::~CompilerLLVM() {
Logan Chien7f767612012-03-01 18:54:49 +0800112 STLDeleteElements(&cunits_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800113}
114
115
Logan Chience119062012-03-02 11:57:34 +0800116void CompilerLLVM::EnsureCompilationUnit() {
Logan Chience119062012-03-02 11:57:34 +0800117 compiler_lock_.AssertHeld();
Logan Chien7f767612012-03-01 18:54:49 +0800118
119 if (curr_cunit_ != NULL) {
120 return;
Logan Chien8b977d32012-02-21 19:14:55 +0800121 }
Logan Chien7f767612012-03-01 18:54:49 +0800122
123 // Allocate compilation unit
124 size_t cunit_idx = cunits_.size();
125
Logan Chien6546ec52012-03-17 20:08:29 +0800126 curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx);
Logan Chien7f767612012-03-01 18:54:49 +0800127
128 // Setup output filename
129 curr_cunit_->SetElfFileName(
130 StringPrintf("%s-%zu", elf_filename_.c_str(), cunit_idx));
131
132 if (IsBitcodeFileNameAvailable()) {
133 curr_cunit_->SetBitcodeFileName(
134 StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
135 }
136
137 // Register compilation unit
138 cunits_.push_back(curr_cunit_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800139}
140
141
Logan Chien7f767612012-03-01 18:54:49 +0800142void CompilerLLVM::MaterializeRemainder() {
Logan Chien8b977d32012-02-21 19:14:55 +0800143 MutexLock GUARD(compiler_lock_);
Logan Chien7f767612012-03-01 18:54:49 +0800144 if (curr_cunit_ != NULL) {
Logan Chience119062012-03-02 11:57:34 +0800145 Materialize();
Logan Chien7f767612012-03-01 18:54:49 +0800146 }
147}
Logan Chien8b977d32012-02-21 19:14:55 +0800148
Logan Chien8b977d32012-02-21 19:14:55 +0800149
Logan Chien7f767612012-03-01 18:54:49 +0800150void CompilerLLVM::MaterializeIfThresholdReached() {
151 MutexLock GUARD(compiler_lock_);
152 if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
Logan Chience119062012-03-02 11:57:34 +0800153 Materialize();
Logan Chien7f767612012-03-01 18:54:49 +0800154 }
155}
156
157
Logan Chience119062012-03-02 11:57:34 +0800158void CompilerLLVM::Materialize() {
159 compiler_lock_.AssertHeld();
160
Logan Chien7f767612012-03-01 18:54:49 +0800161 DCHECK(curr_cunit_ != NULL);
162 DCHECK(!curr_cunit_->IsMaterialized());
163
164 // Write bitcode to file when filename is set
165 if (IsBitcodeFileNameAvailable()) {
166 curr_cunit_->WriteBitcodeToFile();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800167 }
168
Logan Chien8b977d32012-02-21 19:14:55 +0800169 // Materialize the llvm::Module into ELF object file
Logan Chien7f767612012-03-01 18:54:49 +0800170 curr_cunit_->Materialize();
Logan Chien8b977d32012-02-21 19:14:55 +0800171
Logan Chienf7015fd2012-03-18 01:19:37 +0800172 // Load ELF image when automatic ELF loading is enabled
173 if (IsAutoElfLoadingEnabled()) {
174 LoadElfFromCompilationUnit(curr_cunit_);
175 }
176
Logan Chien8b977d32012-02-21 19:14:55 +0800177 // Delete the compilation unit
Logan Chien7f767612012-03-01 18:54:49 +0800178 curr_cunit_ = NULL;
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800179}
180
181
Logan Chienf7015fd2012-03-18 01:19:37 +0800182void CompilerLLVM::EnableAutoElfLoading() {
183 MutexLock GUARD(compiler_lock_);
184
185 if (IsAutoElfLoadingEnabled()) {
186 // If there is an existing ELF loader, then do nothing.
187 // Because the existing ELF loader may have returned some code address
188 // already. If we replace the existing ELF loader with
189 // elf_loader_.reset(...), then it is possible to have some dangling
190 // pointer.
191 return;
192 }
193
194 // Create ELF loader and load the materialized CompilationUnit
195 elf_loader_.reset(new ElfLoader());
196
197 for (size_t i = 0; i < cunits_.size(); ++i) {
198 if (cunits_[i]->IsMaterialized()) {
199 LoadElfFromCompilationUnit(cunits_[i]);
200 }
201 }
202}
203
204
205void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
206 compiler_lock_.AssertHeld();
207 DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
208
Logan Chien0f0899a2012-03-23 10:48:18 +0800209 if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(), cunit->GetElfImage())) {
Logan Chienf7015fd2012-03-18 01:19:37 +0800210 LOG(ERROR) << "Failed to load ELF from compilation unit "
211 << cunit->GetElfIndex();
212 }
213}
214
215
216const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm,
217 const Method* method) const {
218 return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(), method);
219}
220
221
222const Method::InvokeStub* CompilerLLVM::
223GetMethodInvokeStubAddr(const CompiledInvokeStub* cm, const Method* method) const {
224 return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(), method);
225}
226
227
Logan Chien7f767612012-03-01 18:54:49 +0800228CompiledMethod* CompilerLLVM::
229CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800230 MutexLock GUARD(compiler_lock_);
231
Logan Chience119062012-03-02 11:57:34 +0800232 EnsureCompilationUnit();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800233
Logan Chien8b977d32012-02-21 19:14:55 +0800234 UniquePtr<MethodCompiler> method_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800235 new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));
Logan Chien8b977d32012-02-21 19:14:55 +0800236
Logan Chien7f767612012-03-01 18:54:49 +0800237 return method_compiler->Compile();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800238}
Logan Chien83426162011-12-09 09:29:50 +0800239
240
Logan Chien7f767612012-03-01 18:54:49 +0800241CompiledMethod* CompilerLLVM::
242CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
Logan Chien88894ee2012-02-13 16:42:22 +0800243 MutexLock GUARD(compiler_lock_);
244
Logan Chience119062012-03-02 11:57:34 +0800245 EnsureCompilationUnit();
Logan Chien88894ee2012-02-13 16:42:22 +0800246
Logan Chien8b977d32012-02-21 19:14:55 +0800247 UniquePtr<JniCompiler> jni_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800248 new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));
Logan Chien8b977d32012-02-21 19:14:55 +0800249
Logan Chien7f767612012-03-01 18:54:49 +0800250 return jni_compiler->Compile();
Logan Chien88894ee2012-02-13 16:42:22 +0800251}
252
253
Logan Chienf04364f2012-02-10 12:01:39 +0800254CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
255 char const *shorty) {
Logan Chienf04364f2012-02-10 12:01:39 +0800256 MutexLock GUARD(compiler_lock_);
257
Logan Chience119062012-03-02 11:57:34 +0800258 EnsureCompilationUnit();
Logan Chienf04364f2012-02-10 12:01:39 +0800259
Logan Chien8b977d32012-02-21 19:14:55 +0800260 UniquePtr<UpcallCompiler> upcall_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800261 new UpcallCompiler(curr_cunit_, *compiler_));
Logan Chien8b977d32012-02-21 19:14:55 +0800262
Logan Chien7f767612012-03-01 18:54:49 +0800263 return upcall_compiler->CreateStub(is_static, shorty);
Logan Chienf04364f2012-02-10 12:01:39 +0800264}
265
Logan Chien83426162011-12-09 09:29:50 +0800266} // namespace compiler_llvm
267} // namespace art
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800268
Logan Chien106b2a02012-03-18 04:41:38 +0800269inline static art::compiler_llvm::CompilerLLVM* ContextOf(art::Compiler& compiler) {
270 void *compiler_context = compiler.GetCompilerContext();
271 CHECK(compiler_context != NULL);
272 return reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler_context);
273}
274
275inline static const art::compiler_llvm::CompilerLLVM* ContextOf(const art::Compiler& compiler) {
276 void *compiler_context = compiler.GetCompilerContext();
277 CHECK(compiler_context != NULL);
278 return reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler_context);
279}
280
281extern "C" void ArtInitCompilerContext(art::Compiler& compiler) {
282 CHECK(compiler.GetCompilerContext() == NULL);
283
284 art::compiler_llvm::CompilerLLVM* compiler_llvm =
285 new art::compiler_llvm::CompilerLLVM(&compiler,
286 compiler.GetInstructionSet());
287
288 compiler.SetCompilerContext(compiler_llvm);
289}
290
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700291extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800292 const art::DexFile::CodeItem* code_item,
293 uint32_t access_flags, uint32_t method_idx,
294 const art::ClassLoader* class_loader,
295 const art::DexFile& dex_file)
296{
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800297 art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
298 art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
299
300 art::OatCompilationUnit oat_compilation_unit(
301 class_loader, class_linker, dex_file, *dex_cache, code_item,
302 method_idx, access_flags);
303
Logan Chien106b2a02012-03-18 04:41:38 +0800304 return ContextOf(compiler)->CompileDexMethod(&oat_compilation_unit);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800305}
306
307extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
308 uint32_t access_flags, uint32_t method_idx,
309 const art::ClassLoader* class_loader,
310 const art::DexFile& dex_file) {
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800311 art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
312 art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
313
314 art::OatCompilationUnit oat_compilation_unit(
315 class_loader, class_linker, dex_file, *dex_cache, NULL,
316 method_idx, access_flags);
317
Logan Chien106b2a02012-03-18 04:41:38 +0800318 art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700319 art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
320 compiler_llvm->MaterializeIfThresholdReached();
Elliott Hughes13b835a2012-03-13 19:45:22 -0700321 return result;
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800322}
323
324extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static,
325 const char* shorty, uint32_t shorty_len) {
Logan Chien106b2a02012-03-18 04:41:38 +0800326 return ContextOf(compiler)->CreateInvokeStub(is_static, shorty);
327}
328
329extern "C" void compilerLLVMSetElfFileName(art::Compiler& compiler,
330 std::string const& filename) {
331 ContextOf(compiler)->SetElfFileName(filename);
332}
333
334extern "C" void compilerLLVMSetBitcodeFileName(art::Compiler& compiler,
335 std::string const& filename) {
336 ContextOf(compiler)->SetBitcodeFileName(filename);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800337}
338
339extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
Logan Chien106b2a02012-03-18 04:41:38 +0800340 ContextOf(compiler)->MaterializeRemainder();
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800341}
342
Logan Chienf7015fd2012-03-18 01:19:37 +0800343extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
344 art::compiler_llvm::CompilerLLVM* compiler_llvm =
345 reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
346 return compiler_llvm->EnableAutoElfLoading();
347}
348
349extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
350 const art::CompiledMethod* cm,
351 const art::Method* method) {
352 const art::compiler_llvm::CompilerLLVM* compiler_llvm =
353 reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
354 return compiler_llvm->GetMethodCodeAddr(cm, method);
355}
356
357extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
358 const art::CompiledInvokeStub* cm,
359 const art::Method* method) {
360 const art::compiler_llvm::CompilerLLVM* compiler_llvm =
361 reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
362 return compiler_llvm->GetMethodInvokeStubAddr(cm, method);
363}
364
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800365// Note: Using this function carefully!!! This is temporary solution, we will remove it.
366extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
Logan Chien106b2a02012-03-18 04:41:38 +0800367 return new art::MutexLock(ContextOf(compiler)->compiler_lock_);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800368}
369
370extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
Logan Chien106b2a02012-03-18 04:41:38 +0800371 delete ContextOf(compiler);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800372}