blob: b8f21a9bf52a46b6b90e67a7c0b972c4a50eb223 [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);
180extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
181extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
182 const art::DexFile::CodeItem* code_item,
183 uint32_t access_flags,
184 art::InvokeType invoke_type,
185 uint16_t class_def_idx,
186 uint32_t method_idx,
187 jobject class_loader,
188 const art::DexFile& dex_file);
189extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
190 uint32_t access_flags, uint32_t method_idx,
191 const art::DexFile& dex_file);
192
193
194class LLVMBackend : public CompilerBackend {
195 public:
196 LLVMBackend() : CompilerBackend(1000) {}
197
198 void Init(CompilerDriver& driver) const {
199 ArtInitCompilerContext(driver);
200 }
201
202 void UnInit(CompilerDriver& driver) const {
203 ArtUnInitCompilerContext(driver);
204 }
205
206 CompiledMethod* Compile(CompilerDriver& compiler,
207 const DexFile::CodeItem* code_item,
208 uint32_t access_flags,
209 InvokeType invoke_type,
210 uint16_t class_def_idx,
211 uint32_t method_idx,
212 jobject class_loader,
213 const DexFile& dex_file) const {
214 CompiledMethod* method = TryCompileWithSeaIR(compiler,
215 code_item,
216 access_flags,
217 invoke_type,
218 class_def_idx,
219 method_idx,
220 class_loader,
221 dex_file);
222 if (method != nullptr) return method;
223
224 return ArtCompileMethod(compiler,
225 code_item,
226 access_flags,
227 invoke_type,
228 class_def_idx,
229 method_idx,
230 class_loader,
231 dex_file);
232 }
233
234 CompiledMethod* JniCompile(CompilerDriver& driver,
235 uint32_t access_flags,
236 uint32_t method_idx,
237 const DexFile& dex_file) const {
238 return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file);
239 }
240
241 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
242 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
243 }
244
245 bool WriteElf(art::File* file,
246 OatWriter& oat_writer,
247 const std::vector<const art::DexFile*>& dex_files,
248 const std::string& android_root,
249 bool is_host, const CompilerDriver& driver) const
250 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
251 return art::ElfWriterMclinker::Create(
252 file, oat_writer, dex_files, android_root, is_host, driver);
253 }
254
255 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
256 return PortableCodeGenerator(
257 cu, cu->mir_graph.get(), &cu->arena,
258 reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
259 }
260
261 void InitCompilationUnit(CompilationUnit& cu) const {
262 // Fused long branches not currently useful in bitcode.
263 cu.disable_opt |=
264 (1 << kBranchFusing) |
265 (1 << kSuppressExceptionEdges);
266 }
267
268 bool isPortable() const { return true; }
269
270 private:
271 DISALLOW_COPY_AND_ASSIGN(LLVMBackend);
272};
273#endif
274
275CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) {
276 switch (kind) {
277 case kQuick:
278 return new QuickBackend();
279 break;
280 case kPortable:
281#ifdef ART_USE_PORTABLE_COMPILER
282 return new LLVMBackend();
283#else
284 LOG(FATAL) << "Portable compiler not compiled";
285#endif
286 break;
287 default:
288 LOG(FATAL) << "UNREACHABLE";
289 }
290 return nullptr;
291}
292
293} // namespace art