blob: 0afa665eb79ab399d62853d1e679fa39f05a4629 [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
Mark Mendellae9fd932014-02-10 16:14:35 -080086// Hack for CFI CIE initialization
87extern std::vector<uint8_t>* X86CFIInitialization();
88
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +000089class QuickBackend : public CompilerBackend {
90 public:
91 QuickBackend() : CompilerBackend(100) {}
92
93 void Init(CompilerDriver& driver) const {
94 ArtInitQuickCompilerContext(driver);
95 }
96
97 void UnInit(CompilerDriver& driver) const {
98 ArtUnInitQuickCompilerContext(driver);
99 }
100
101 CompiledMethod* Compile(CompilerDriver& compiler,
102 const DexFile::CodeItem* code_item,
103 uint32_t access_flags,
104 InvokeType invoke_type,
105 uint16_t class_def_idx,
106 uint32_t method_idx,
107 jobject class_loader,
108 const DexFile& dex_file) const {
109 CompiledMethod* method = TryCompileWithSeaIR(compiler,
110 code_item,
111 access_flags,
112 invoke_type,
113 class_def_idx,
114 method_idx,
115 class_loader,
116 dex_file);
117 if (method != nullptr) return method;
118
119 return ArtQuickCompileMethod(compiler,
120 code_item,
121 access_flags,
122 invoke_type,
123 class_def_idx,
124 method_idx,
125 class_loader,
126 dex_file);
127 }
128
129 CompiledMethod* JniCompile(CompilerDriver& driver,
130 uint32_t access_flags,
131 uint32_t method_idx,
132 const DexFile& dex_file) const {
133 return ArtQuickJniCompileMethod(driver, access_flags, method_idx, dex_file);
134 }
135
136 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
137 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode());
138 }
139
140 bool WriteElf(art::File* file,
Ian Rogers3d504072014-03-01 09:16:49 -0800141 OatWriter* oat_writer,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000142 const std::vector<const art::DexFile*>& dex_files,
143 const std::string& android_root,
144 bool is_host, const CompilerDriver& driver) const
Ian Rogers3d504072014-03-01 09:16:49 -0800145 OVERRIDE
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000146 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
147 return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, driver);
148 }
149
150 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
151 Mir2Lir* mir_to_lir = nullptr;
152 switch (cu->instruction_set) {
153 case kThumb2:
154 mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
155 break;
156 case kMips:
157 mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
158 break;
159 case kX86:
160 mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena);
161 break;
162 default:
163 LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set;
164 }
165
166 /* The number of compiler temporaries depends on backend so set it up now if possible */
167 if (mir_to_lir) {
168 size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps();
169 bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps);
170 CHECK(set_max);
171 }
Mark Mendellae9fd932014-02-10 16:14:35 -0800172 return mir_to_lir;
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000173 }
174
175 void InitCompilationUnit(CompilationUnit& cu) const {}
176
Mark Mendellae9fd932014-02-10 16:14:35 -0800177 /*
178 * @brief Generate and return Dwarf CFI initialization, if supported by the
179 * backend.
180 * @param driver CompilerDriver for this compile.
181 * @returns nullptr if not supported by backend or a vector of bytes for CFI DWARF
182 * information.
183 * @note This is used for backtrace information in generated code.
184 */
185 std::vector<uint8_t>* GetCallFrameInformationInitialization(const CompilerDriver& driver) const
186 OVERRIDE {
187 if (driver.GetInstructionSet() == kX86) {
188 return X86CFIInitialization();
189 }
190 return nullptr;
191 }
192
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000193 private:
194 DISALLOW_COPY_AND_ASSIGN(QuickBackend);
195};
196
197#ifdef ART_USE_PORTABLE_COMPILER
198
199extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000200
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000201extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000202
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000203extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
204 const art::DexFile::CodeItem* code_item,
205 uint32_t access_flags,
206 art::InvokeType invoke_type,
207 uint16_t class_def_idx,
208 uint32_t method_idx,
209 jobject class_loader,
210 const art::DexFile& dex_file);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000211
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000212extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
213 uint32_t access_flags, uint32_t method_idx,
214 const art::DexFile& dex_file);
215
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000216extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
217 std::string const& filename);
218
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000219
220class LLVMBackend : public CompilerBackend {
221 public:
222 LLVMBackend() : CompilerBackend(1000) {}
223
224 void Init(CompilerDriver& driver) const {
225 ArtInitCompilerContext(driver);
226 }
227
228 void UnInit(CompilerDriver& driver) const {
229 ArtUnInitCompilerContext(driver);
230 }
231
232 CompiledMethod* Compile(CompilerDriver& compiler,
233 const DexFile::CodeItem* code_item,
234 uint32_t access_flags,
235 InvokeType invoke_type,
236 uint16_t class_def_idx,
237 uint32_t method_idx,
238 jobject class_loader,
239 const DexFile& dex_file) const {
240 CompiledMethod* method = TryCompileWithSeaIR(compiler,
241 code_item,
242 access_flags,
243 invoke_type,
244 class_def_idx,
245 method_idx,
246 class_loader,
247 dex_file);
248 if (method != nullptr) return method;
249
250 return ArtCompileMethod(compiler,
251 code_item,
252 access_flags,
253 invoke_type,
254 class_def_idx,
255 method_idx,
256 class_loader,
257 dex_file);
258 }
259
260 CompiledMethod* JniCompile(CompilerDriver& driver,
261 uint32_t access_flags,
262 uint32_t method_idx,
263 const DexFile& dex_file) const {
264 return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file);
265 }
266
267 uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
268 return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
269 }
270
271 bool WriteElf(art::File* file,
Ian Rogers3d504072014-03-01 09:16:49 -0800272 OatWriter* oat_writer,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000273 const std::vector<const art::DexFile*>& dex_files,
274 const std::string& android_root,
275 bool is_host, const CompilerDriver& driver) const
Ian Rogers3d504072014-03-01 09:16:49 -0800276 OVERRIDE
277 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000278 return art::ElfWriterMclinker::Create(
279 file, oat_writer, dex_files, android_root, is_host, driver);
280 }
281
282 Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
283 return PortableCodeGenerator(
284 cu, cu->mir_graph.get(), &cu->arena,
285 reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
286 }
287
288 void InitCompilationUnit(CompilationUnit& cu) const {
289 // Fused long branches not currently useful in bitcode.
290 cu.disable_opt |=
291 (1 << kBranchFusing) |
292 (1 << kSuppressExceptionEdges);
293 }
294
Ian Rogers3d504072014-03-01 09:16:49 -0800295 bool IsPortable() const OVERRIDE {
296 return true;
297 }
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000298
Ian Rogers3d504072014-03-01 09:16:49 -0800299 void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
300 typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000301
302 SetBitcodeFileNameFn set_bitcode_file_name =
303 reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
304
Ian Rogers3d504072014-03-01 09:16:49 -0800305 set_bitcode_file_name(driver, filename);
Nicolas Geoffrayf3e2cc42014-02-18 18:37:26 +0000306 }
307
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000308 private:
309 DISALLOW_COPY_AND_ASSIGN(LLVMBackend);
310};
311#endif
312
313CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) {
314 switch (kind) {
315 case kQuick:
316 return new QuickBackend();
317 break;
318 case kPortable:
319#ifdef ART_USE_PORTABLE_COMPILER
320 return new LLVMBackend();
321#else
322 LOG(FATAL) << "Portable compiler not compiled";
323#endif
324 break;
325 default:
326 LOG(FATAL) << "UNREACHABLE";
327 }
328 return nullptr;
329}
330
331} // namespace art