blob: 48c606241033b3fdb2ab0c6469097c5bdd82172b [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"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080021#include "compiler.h"
Shih-wei Liaoc4c98812012-03-10 21:55:51 -080022#include "dex_cache.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080023#include "ir_builder.h"
Logan Chien88894ee2012-02-13 16:42:22 +080024#include "jni_compiler.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080025#include "method_compiler.h"
Logan Chien4dd96f52012-02-29 01:26:58 +080026#include "oat_compilation_unit.h"
Logan Chien7f767612012-03-01 18:54:49 +080027#include "stl_util.h"
Logan Chienf04364f2012-02-10 12:01:39 +080028#include "upcall_compiler.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080029
Logan Chiendd7cf5b2012-03-01 12:55:19 +080030#include <llvm/LinkAllPasses.h>
31#include <llvm/LinkAllVMCore.h>
Logan Chien4c17dff2012-03-02 20:15:46 +080032#include <llvm/Support/CommandLine.h>
Logan Chien013b6f22012-03-02 17:20:33 +080033#include <llvm/Support/ManagedStatic.h>
Logan Chien8b977d32012-02-21 19:14:55 +080034#include <llvm/Support/TargetSelect.h>
35#include <llvm/Support/Threading.h>
36
Logan Chien013b6f22012-03-02 17:20:33 +080037namespace llvm {
38 extern bool TimePassesIsEnabled;
39}
40
Logan Chien4c17dff2012-03-02 20:15:46 +080041extern llvm::cl::opt<bool> EnableARMLongCalls;
42// NOTE: Although EnableARMLongCalls is defined in llvm/lib/Target/ARM/
43// ARMISelLowering.cpp, however, it is not in the llvm namespace.
44
Logan Chien8b977d32012-02-21 19:14:55 +080045
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080046namespace {
Logan Chien8b977d32012-02-21 19:14:55 +080047
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080048pthread_once_t llvm_initialized = PTHREAD_ONCE_INIT;
49
50void InitializeLLVM() {
Logan Chien013b6f22012-03-02 17:20:33 +080051 // NOTE: Uncomment following line to show the time consumption of LLVM passes
52 //llvm::TimePassesIsEnabled = true;
53
Logan Chien8b977d32012-02-21 19:14:55 +080054 // Initialize LLVM target, MC subsystem, asm printer, and asm parser
55 llvm::InitializeAllTargets();
56 llvm::InitializeAllTargetMCs();
57 llvm::InitializeAllAsmPrinters();
58 llvm::InitializeAllAsmParsers();
59 // TODO: Maybe we don't have to initialize "all" targets.
60
Logan Chien4c17dff2012-03-02 20:15:46 +080061 // Enable -arm-long-calls
62 EnableARMLongCalls = true;
63
Logan Chiendd7cf5b2012-03-01 12:55:19 +080064 // Initialize LLVM optimization passes
65 llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
66
67 llvm::initializeCore(registry);
68 llvm::initializeScalarOpts(registry);
69 llvm::initializeIPO(registry);
70 llvm::initializeAnalysis(registry);
71 llvm::initializeIPA(registry);
72 llvm::initializeTransformUtils(registry);
73 llvm::initializeInstCombine(registry);
74 llvm::initializeInstrumentation(registry);
75 llvm::initializeTarget(registry);
76
Logan Chien8b977d32012-02-21 19:14:55 +080077 // Initialize LLVM internal data structure for multithreading
78 llvm::llvm_start_multithreaded();
79}
80
Logan Chienf1306552012-03-16 11:17:53 +080081// The Guard to Shutdown LLVM
Logan Chienaeb53032012-03-18 02:29:38 +080082// llvm::llvm_shutdown_obj llvm_guard;
83// TODO: We are commenting out this line because this will cause SEGV from
84// time to time.
85// Two reasons: (1) the order of the destruction of static objects, or
86// (2) dlopen/dlclose side-effect on static objects.
Shih-wei Liaofc34adb2012-03-07 08:51:44 -080087
88} // anonymous namespace
89
90
91namespace art {
92namespace compiler_llvm {
Shih-wei Liaod1fec812012-02-13 09:51:10 -080093
94
Logan Chiene75a8cc2012-02-24 12:26:43 +080095llvm::Module* makeLLVMModuleContents(llvm::Module* module);
Logan Chien42e0e152012-01-13 15:42:36 +080096
97
Shih-wei Liaod1fec812012-02-13 09:51:10 -080098CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -080099 : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
Logan Chien7f767612012-03-01 18:54:49 +0800100 insn_set_(insn_set), curr_cunit_(NULL) {
Shih-wei Liaofc34adb2012-03-07 08:51:44 -0800101
102
103 // Initialize LLVM libraries
104 pthread_once(&llvm_initialized, InitializeLLVM);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800105}
106
107
108CompilerLLVM::~CompilerLLVM() {
Logan Chien7f767612012-03-01 18:54:49 +0800109 STLDeleteElements(&cunits_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800110}
111
112
Logan Chience119062012-03-02 11:57:34 +0800113void CompilerLLVM::EnsureCompilationUnit() {
Logan Chience119062012-03-02 11:57:34 +0800114 compiler_lock_.AssertHeld();
Logan Chien7f767612012-03-01 18:54:49 +0800115
116 if (curr_cunit_ != NULL) {
117 return;
Logan Chien8b977d32012-02-21 19:14:55 +0800118 }
Logan Chien7f767612012-03-01 18:54:49 +0800119
120 // Allocate compilation unit
121 size_t cunit_idx = cunits_.size();
122
Logan Chien6546ec52012-03-17 20:08:29 +0800123 curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx);
Logan Chien7f767612012-03-01 18:54:49 +0800124
125 // Setup output filename
126 curr_cunit_->SetElfFileName(
127 StringPrintf("%s-%zu", elf_filename_.c_str(), cunit_idx));
128
129 if (IsBitcodeFileNameAvailable()) {
130 curr_cunit_->SetBitcodeFileName(
131 StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
132 }
133
134 // Register compilation unit
135 cunits_.push_back(curr_cunit_);
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800136}
137
138
Logan Chien7f767612012-03-01 18:54:49 +0800139void CompilerLLVM::MaterializeRemainder() {
Logan Chien8b977d32012-02-21 19:14:55 +0800140 MutexLock GUARD(compiler_lock_);
Logan Chien7f767612012-03-01 18:54:49 +0800141 if (curr_cunit_ != NULL) {
Logan Chience119062012-03-02 11:57:34 +0800142 Materialize();
Logan Chien7f767612012-03-01 18:54:49 +0800143 }
144}
Logan Chien8b977d32012-02-21 19:14:55 +0800145
Logan Chien8b977d32012-02-21 19:14:55 +0800146
Logan Chien7f767612012-03-01 18:54:49 +0800147void CompilerLLVM::MaterializeIfThresholdReached() {
148 MutexLock GUARD(compiler_lock_);
149 if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
Logan Chience119062012-03-02 11:57:34 +0800150 Materialize();
Logan Chien7f767612012-03-01 18:54:49 +0800151 }
152}
153
154
Logan Chience119062012-03-02 11:57:34 +0800155void CompilerLLVM::Materialize() {
156 compiler_lock_.AssertHeld();
157
Logan Chien7f767612012-03-01 18:54:49 +0800158 DCHECK(curr_cunit_ != NULL);
159 DCHECK(!curr_cunit_->IsMaterialized());
160
161 // Write bitcode to file when filename is set
162 if (IsBitcodeFileNameAvailable()) {
163 curr_cunit_->WriteBitcodeToFile();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800164 }
165
Logan Chien8b977d32012-02-21 19:14:55 +0800166 // Materialize the llvm::Module into ELF object file
Logan Chien7f767612012-03-01 18:54:49 +0800167 curr_cunit_->Materialize();
Logan Chien8b977d32012-02-21 19:14:55 +0800168
169 // Delete the compilation unit
Logan Chien7f767612012-03-01 18:54:49 +0800170 curr_cunit_ = NULL;
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800171}
172
173
Logan Chien7f767612012-03-01 18:54:49 +0800174CompiledMethod* CompilerLLVM::
175CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800176 MutexLock GUARD(compiler_lock_);
177
Logan Chience119062012-03-02 11:57:34 +0800178 EnsureCompilationUnit();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800179
Logan Chien8b977d32012-02-21 19:14:55 +0800180 UniquePtr<MethodCompiler> method_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800181 new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));
Logan Chien8b977d32012-02-21 19:14:55 +0800182
Logan Chien7f767612012-03-01 18:54:49 +0800183 return method_compiler->Compile();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800184}
Logan Chien83426162011-12-09 09:29:50 +0800185
186
Logan Chien7f767612012-03-01 18:54:49 +0800187CompiledMethod* CompilerLLVM::
188CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
Logan Chien88894ee2012-02-13 16:42:22 +0800189 MutexLock GUARD(compiler_lock_);
190
Logan Chience119062012-03-02 11:57:34 +0800191 EnsureCompilationUnit();
Logan Chien88894ee2012-02-13 16:42:22 +0800192
Logan Chien8b977d32012-02-21 19:14:55 +0800193 UniquePtr<JniCompiler> jni_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800194 new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));
Logan Chien8b977d32012-02-21 19:14:55 +0800195
Logan Chien7f767612012-03-01 18:54:49 +0800196 return jni_compiler->Compile();
Logan Chien88894ee2012-02-13 16:42:22 +0800197}
198
199
Logan Chienf04364f2012-02-10 12:01:39 +0800200CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
201 char const *shorty) {
Logan Chienf04364f2012-02-10 12:01:39 +0800202 MutexLock GUARD(compiler_lock_);
203
Logan Chience119062012-03-02 11:57:34 +0800204 EnsureCompilationUnit();
Logan Chienf04364f2012-02-10 12:01:39 +0800205
Logan Chien8b977d32012-02-21 19:14:55 +0800206 UniquePtr<UpcallCompiler> upcall_compiler(
Logan Chien7f767612012-03-01 18:54:49 +0800207 new UpcallCompiler(curr_cunit_, *compiler_));
Logan Chien8b977d32012-02-21 19:14:55 +0800208
Logan Chien7f767612012-03-01 18:54:49 +0800209 return upcall_compiler->CreateStub(is_static, shorty);
Logan Chienf04364f2012-02-10 12:01:39 +0800210}
211
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700212CompilerLLVM* EnsureCompilerLLVM(art::Compiler& compiler) {
213 if (compiler.GetCompilerContext() == NULL) {
214 compiler.SetCompilerContext(new CompilerLLVM(&compiler, compiler.GetInstructionSet()));
215 }
216 CompilerLLVM* compiler_llvm = reinterpret_cast<CompilerLLVM*>(compiler.GetCompilerContext());
217 compiler_llvm->SetElfFileName(compiler.GetElfFileName());
218 compiler_llvm->SetBitcodeFileName(compiler.GetBitcodeFileName());
219 return compiler_llvm;
220}
Logan Chienf04364f2012-02-10 12:01:39 +0800221
Logan Chien83426162011-12-09 09:29:50 +0800222} // namespace compiler_llvm
223} // namespace art
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800224
Elliott Hughes3fa1b7e2012-03-13 17:06:22 -0700225extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800226 const art::DexFile::CodeItem* code_item,
227 uint32_t access_flags, uint32_t method_idx,
228 const art::ClassLoader* class_loader,
229 const art::DexFile& dex_file)
230{
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800231 art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
232 art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
233
234 art::OatCompilationUnit oat_compilation_unit(
235 class_loader, class_linker, dex_file, *dex_cache, code_item,
236 method_idx, access_flags);
237
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700238 return art::compiler_llvm::EnsureCompilerLLVM(compiler)->CompileDexMethod(&oat_compilation_unit);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800239}
240
241extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
242 uint32_t access_flags, uint32_t method_idx,
243 const art::ClassLoader* class_loader,
244 const art::DexFile& dex_file) {
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800245 art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
246 art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
247
248 art::OatCompilationUnit oat_compilation_unit(
249 class_loader, class_linker, dex_file, *dex_cache, NULL,
250 method_idx, access_flags);
251
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700252 art::compiler_llvm::CompilerLLVM* compiler_llvm = art::compiler_llvm::EnsureCompilerLLVM(compiler);
253 art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
254 compiler_llvm->MaterializeIfThresholdReached();
Elliott Hughes13b835a2012-03-13 19:45:22 -0700255 return result;
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800256}
257
258extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static,
259 const char* shorty, uint32_t shorty_len) {
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700260 return art::compiler_llvm::EnsureCompilerLLVM(compiler)->CreateInvokeStub(is_static, shorty);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800261}
262
263extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700264 art::compiler_llvm::EnsureCompilerLLVM(compiler)->MaterializeRemainder();
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800265}
266
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800267// Note: Using this function carefully!!! This is temporary solution, we will remove it.
268extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700269 return new art::MutexLock(art::compiler_llvm::EnsureCompilerLLVM(compiler)->compiler_lock_);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800270}
271
272extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
Elliott Hughes6f4976c2012-03-13 21:19:01 -0700273 delete art::compiler_llvm::EnsureCompilerLLVM(compiler);
Shih-wei Liaoc4c98812012-03-10 21:55:51 -0800274}