blob: f37ee376340d86fe84303958dd0895f61d74ab7a [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,
Ian Rogers3d504072014-03-01 09:16:49 -0800138 OatWriter* oat_writer,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000139 const std::vector<const art::DexFile*>& dex_files,
140 const std::string& android_root,
141 bool is_host, const CompilerDriver& driver) const
Ian Rogers3d504072014-03-01 09:16:49 -0800142 OVERRIDE
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000143 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
144 return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, driver);
145 }
146
147 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
148 Mir2Lir* mir_to_lir = nullptr;
149 switch (cu->instruction_set) {
150 case kThumb2:
151 mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
152 break;
153 case kMips:
154 mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
155 break;
156 case kX86:
157 mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
158 break;
159 default:
160 LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
161 }
162
163 /* The number of compiler temporaries depends on backend so set it up now if possible */
164 if (mir_to_lir) {
165 size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
166 bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
167 CHECK(set_max);
168 }
169 return mir_to_lir;;
170 }
171
172 void InitCompilationUnit(CompilationUnit& cu) const {}
173
174 private:
175 DISALLOW_COPY_AND_ASSIGN(QuickBackend);
176};
177
178#ifdef ART_USE_PORTABLE_COMPILER
179
180extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000181
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000182extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000183
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000184extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
185 const art::DexFile::CodeItem* code_item,
186 uint32_t access_flags,
187 art::InvokeType invoke_type,
188 uint16_t class_def_idx,
189 uint32_t method_idx,
190 jobject class_loader,
191 const art::DexFile& dex_file);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000192
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000193extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
194 uint32_t access_flags, uint32_t method_idx,
195 const art::DexFile& dex_file);
196
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000197extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
198 std::string const& filename);
199
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000200
201class LLVMBackend : public CompilerBackend {
202 public:
203 LLVMBackend() : CompilerBackend(1000) {}
204
205 void Init(CompilerDriver& driver) const {
206 ArtInitCompilerContext(driver);
207 }
208
209 void UnInit(CompilerDriver& driver) const {
210 ArtUnInitCompilerContext(driver);
211 }
212
213 CompiledMethod* Compile(CompilerDriver& compiler,
214 const DexFile::CodeItem* code_item,
215 uint32_t access_flags,
216 InvokeType invoke_type,
217 uint16_t class_def_idx,
218 uint32_t method_idx,
219 jobject class_loader,
220 const DexFile& dex_file) const {
221 CompiledMethod* method = TryCompileWithSeaIR(compiler,
222 code_item,
223 access_flags,
224 invoke_type,
225 class_def_idx,
226 method_idx,
227 class_loader,
228 dex_file);
229 if (method != nullptr) return method;
230
231 return ArtCompileMethod(compiler,
232 code_item,
233 access_flags,
234 invoke_type,
235 class_def_idx,
236 method_idx,
237 class_loader,
238 dex_file);
239 }
240
241 CompiledMethod* JniCompile(CompilerDriver& driver,
242 uint32_t access_flags,
243 uint32_t method_idx,
244 const DexFile& dex_file) const {
245 return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file);
246 }
247
248 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
249 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
250 }
251
252 bool WriteElf(art::File* file,
Ian Rogers3d504072014-03-01 09:16:49 -0800253 OatWriter* oat_writer,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000254 const std::vector<const art::DexFile*>& dex_files,
255 const std::string& android_root,
256 bool is_host, const CompilerDriver& driver) const
Ian Rogers3d504072014-03-01 09:16:49 -0800257 OVERRIDE
258 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000259 return art::ElfWriterMclinker::Create(
260 file, oat_writer, dex_files, android_root, is_host, driver);
261 }
262
263 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
264 return PortableCodeGenerator(
265 cu, cu->mir_graph.get(), &cu->arena,
266 reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
267 }
268
269 void InitCompilationUnit(CompilationUnit& cu) const {
270 // Fused long branches not currently useful in bitcode.
271 cu.disable_opt |=
272 (1 << kBranchFusing) |
273 (1 << kSuppressExceptionEdges);
274 }
275
Ian Rogers3d504072014-03-01 09:16:49 -0800276 bool IsPortable() const OVERRIDE {
277 return true;
278 }
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000279
Ian Rogers3d504072014-03-01 09:16:49 -0800280 void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
281 typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000282
283 SetBitcodeFileNameFn set_bitcode_file_name =
284 reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
285
Ian Rogers3d504072014-03-01 09:16:49 -0800286 set_bitcode_file_name(driver, filename);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000287 }
288
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000289 private:
290 DISALLOW_COPY_AND_ASSIGN(LLVMBackend);
291};
292#endif
293
294CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) {
295 switch (kind) {
296 case kQuick:
297 return new QuickBackend();
298 break;
299 case kPortable:
300#ifdef ART_USE_PORTABLE_COMPILER
301 return new LLVMBackend();
302#else
303 LOG(FATAL) << "Portable compiler not compiled";
304#endif
305 break;
306 default:
307 LOG(FATAL) << "UNREACHABLE";
308 }
309 return nullptr;
310}
311
312} // namespace art