blob: eaa39f83c11d2c02dfb6c12e1fbebd4f89df8075 [file] [log] [blame]
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +00001/*
2 * Copyright (C) 2014 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_backend.h"
18#include "elf_writer_quick.h"
19#include "dex/quick/mir_to_lir.h"
20#include "dex/mir_graph.h"
21#include "driver/compiler_driver.h"
22#include "mirror/art_method-inl.h"
23
24#ifdef ART_USE_PORTABLE_COMPILER
25#include "dex/portable/mir_to_gbc.h"
26#include "elf_writer_mclinker.h"
27#endif
28
29namespace art {
30
31#ifdef ART_SEA_IR_MODE
32extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler,
33 const art::DexFile::CodeItem* code_item,
34 uint32_t access_flags,
35 art::InvokeType invoke_type,
36 uint16_t class_def_idx,
37 uint32_t method_idx,
38 jobject class_loader,
39 const art::DexFile& dex_file);
40#endif
41
42extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver);
43extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver);
44extern "C" art::CompiledMethod* ArtQuickCompileMethod(art::CompilerDriver& compiler,
45 const art::DexFile::CodeItem* code_item,
46 uint32_t access_flags,
47 art::InvokeType invoke_type,
48 uint16_t class_def_idx,
49 uint32_t method_idx,
50 jobject class_loader,
51 const art::DexFile& dex_file);
52
53extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver& compiler,
54 uint32_t access_flags, uint32_t method_idx,
55 const art::DexFile& dex_file);
56
57
58static CompiledMethod* TryCompileWithSeaIR(art::CompilerDriver& compiler,
59 const art::DexFile::CodeItem* code_item,
60 uint32_t access_flags,
61 art::InvokeType invoke_type,
62 uint16_t class_def_idx,
63 uint32_t method_idx,
64 jobject class_loader,
65 const art::DexFile& dex_file) {
66#ifdef ART_SEA_IR_MODE
67 bool use_sea = Runtime::Current()->IsSeaIRMode();
68 use_sea = use_sea &&
69 (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
70 if (use_sea) {
71 LOG(INFO) << "Using SEA IR to compile..." << std::endl;
72 return SeaIrCompileMethod(compiler,
73 code_item,
74 access_flags,
75 invoke_type,
76 class_def_idx,
77 method_idx,
78 class_loader,
79 dex_file);
80 }
81#endif
82 return nullptr;
83}
84
85
86class QuickBackend : public CompilerBackend {
87 public:
88 QuickBackend() : CompilerBackend(100) {}
89
90 void Init(CompilerDriver& driver) const {
91 ArtInitQuickCompilerContext(driver);
92 }
93
94 void UnInit(CompilerDriver& driver) const {
95 ArtUnInitQuickCompilerContext(driver);
96 }
97
98 CompiledMethod* Compile(CompilerDriver& compiler,
99 const DexFile::CodeItem* code_item,
100 uint32_t access_flags,
101 InvokeType invoke_type,
102 uint16_t class_def_idx,
103 uint32_t method_idx,
104 jobject class_loader,
105 const DexFile& dex_file) const {
106 CompiledMethod* method = TryCompileWithSeaIR(compiler,
107 code_item,
108 access_flags,
109 invoke_type,
110 class_def_idx,
111 method_idx,
112 class_loader,
113 dex_file);
114 if (method != nullptr) return method;
115
116 return ArtQuickCompileMethod(compiler,
117 code_item,
118 access_flags,
119 invoke_type,
120 class_def_idx,
121 method_idx,
122 class_loader,
123 dex_file);
124 }
125
126 CompiledMethod* JniCompile(CompilerDriver& driver,
127 uint32_t access_flags,
128 uint32_t method_idx,
129 const DexFile& dex_file) const {
130 return ArtQuickJniCompileMethod(driver, access_flags, method_idx, dex_file);
131 }
132
133 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
134 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
135 }
136
137 bool WriteElf(art::File* file,
138 OatWriter& oat_writer,
139 const std::vector<const art::DexFile*>& dex_files,
140 const std::string& android_root,
141 bool is_host, const CompilerDriver& driver) const
142 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
143 return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, driver);
144 }
145
146 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
147 Mir2Lir* mir_to_lir = nullptr;
148 switch (cu->instruction_set) {
149 case kThumb2:
150 mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
151 break;
152 case kMips:
153 mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
154 break;
155 case kX86:
156 mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
157 break;
158 default:
159 LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
160 }
161
162 /* The number of compiler temporaries depends on backend so set it up now if possible */
163 if (mir_to_lir) {
164 size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
165 bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
166 CHECK(set_max);
167 }
168 return mir_to_lir;;
169 }
170
171 void InitCompilationUnit(CompilationUnit& cu) const {}
172
173 private:
174 DISALLOW_COPY_AND_ASSIGN(QuickBackend);
175};
176
177#ifdef ART_USE_PORTABLE_COMPILER
178
179extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000180
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000181extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000182
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000183extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
184 const art::DexFile::CodeItem* code_item,
185 uint32_t access_flags,
186 art::InvokeType invoke_type,
187 uint16_t class_def_idx,
188 uint32_t method_idx,
189 jobject class_loader,
190 const art::DexFile& dex_file);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000191
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000192extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
193 uint32_t access_flags, uint32_t method_idx,
194 const art::DexFile& dex_file);
195
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000196extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
197 std::string const& filename);
198
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000199
200class LLVMBackend : public CompilerBackend {
201 public:
202 LLVMBackend() : CompilerBackend(1000) {}
203
204 void Init(CompilerDriver& driver) const {
205 ArtInitCompilerContext(driver);
206 }
207
208 void UnInit(CompilerDriver& driver) const {
209 ArtUnInitCompilerContext(driver);
210 }
211
212 CompiledMethod* Compile(CompilerDriver& compiler,
213 const DexFile::CodeItem* code_item,
214 uint32_t access_flags,
215 InvokeType invoke_type,
216 uint16_t class_def_idx,
217 uint32_t method_idx,
218 jobject class_loader,
219 const DexFile& dex_file) const {
220 CompiledMethod* method = TryCompileWithSeaIR(compiler,
221 code_item,
222 access_flags,
223 invoke_type,
224 class_def_idx,
225 method_idx,
226 class_loader,
227 dex_file);
228 if (method != nullptr) return method;
229
230 return ArtCompileMethod(compiler,
231 code_item,
232 access_flags,
233 invoke_type,
234 class_def_idx,
235 method_idx,
236 class_loader,
237 dex_file);
238 }
239
240 CompiledMethod* JniCompile(CompilerDriver& driver,
241 uint32_t access_flags,
242 uint32_t method_idx,
243 const DexFile& dex_file) const {
244 return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file);
245 }
246
247 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
248 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
249 }
250
251 bool WriteElf(art::File* file,
252 OatWriter& oat_writer,
253 const std::vector<const art::DexFile*>& dex_files,
254 const std::string& android_root,
255 bool is_host, const CompilerDriver& driver) const
256 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
257 return art::ElfWriterMclinker::Create(
258 file, oat_writer, dex_files, android_root, is_host, driver);
259 }
260
261 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
262 return PortableCodeGenerator(
263 cu, cu->mir_graph.get(), &cu->arena,
264 reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
265 }
266
267 void InitCompilationUnit(CompilationUnit& cu) const {
268 // Fused long branches not currently useful in bitcode.
269 cu.disable_opt |=
270 (1 << kBranchFusing) |
271 (1 << kSuppressExceptionEdges);
272 }
273
274 bool isPortable() const { return true; }
275
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000276 void SetBitcodeFileName(std::string const& filename) {
277 typedef void (*SetBitcodeFileNameFn)(CompilerDriver&, std::string const&);
278
279 SetBitcodeFileNameFn set_bitcode_file_name =
280 reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
281
282 set_bitcode_file_name(*this, filename);
283 }
284
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000285 private:
286 DISALLOW_COPY_AND_ASSIGN(LLVMBackend);
287};
288#endif
289
290CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) {
291 switch (kind) {
292 case kQuick:
293 return new QuickBackend();
294 break;
295 case kPortable:
296#ifdef ART_USE_PORTABLE_COMPILER
297 return new LLVMBackend();
298#else
299 LOG(FATAL) << "Portable compiler not compiled";
300#endif
301 break;
302 default:
303 LOG(FATAL) << "UNREACHABLE";
304 }
305 return nullptr;
306}
307
308} // namespace art