1/*
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.h"
18#include "compilers.h"
19#include "driver/compiler_driver.h"
20#include "mirror/art_method-inl.h"
21
22#ifdef ART_USE_PORTABLE_COMPILER
23#include "dex/portable/mir_to_gbc.h"
24#include "elf_writer_mclinker.h"
25#endif
26
27namespace art {
28
29#ifdef ART_SEA_IR_MODE
30extern "C" art::CompiledMethod* SeaIrCompileMethod(const art::DexFile::CodeItem* code_item,
31                                                   uint32_t access_flags,
32                                                   art::InvokeType invoke_type,
33                                                   uint16_t class_def_idx,
34                                                   uint32_t method_idx,
35                                                   jobject class_loader,
36                                                   const art::DexFile& dex_file);
37#endif
38
39
40CompiledMethod* Compiler::TryCompileWithSeaIR(const art::DexFile::CodeItem* code_item,
41                                              uint32_t access_flags,
42                                              art::InvokeType invoke_type,
43                                              uint16_t class_def_idx,
44                                              uint32_t method_idx,
45                                              jobject class_loader,
46                                              const art::DexFile& dex_file) {
47#ifdef ART_SEA_IR_MODE
48    bool use_sea = (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
49    if (use_sea) {
50      LOG(INFO) << "Using SEA IR to compile..." << std::endl;
51      return SeaIrCompileMethod(code_item,
52                                access_flags,
53                                invoke_type,
54                                class_def_idx,
55                                method_idx,
56                                class_loader,
57                                dex_file);
58  }
59#endif
60  return nullptr;
61}
62
63
64#ifdef ART_USE_PORTABLE_COMPILER
65
66extern "C" void ArtInitCompilerContext(art::CompilerDriver* driver);
67
68extern "C" void ArtUnInitCompilerContext(art::CompilerDriver* driver);
69
70extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver* driver,
71                                                 const art::DexFile::CodeItem* code_item,
72                                                 uint32_t access_flags,
73                                                 art::InvokeType invoke_type,
74                                                 uint16_t class_def_idx,
75                                                 uint32_t method_idx,
76                                                 jobject class_loader,
77                                                 const art::DexFile& dex_file);
78
79extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver* driver,
80                                                        uint32_t access_flags, uint32_t method_idx,
81                                                        const art::DexFile& dex_file);
82
83extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver* driver,
84                                               std::string const& filename);
85
86
87class LLVMCompiler FINAL : public Compiler {
88 public:
89  explicit LLVMCompiler(CompilerDriver* driver) : Compiler(driver, 1000) {}
90
91  void Init() const OVERRIDE {
92    ArtInitCompilerContext(GetCompilerDriver());
93  }
94
95  void UnInit() const OVERRIDE {
96    ArtUnInitCompilerContext(GetCompilerDriver());
97  }
98
99  CompiledMethod* Compile(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 OVERRIDE {
106    CompiledMethod* method = TryCompileWithSeaIR(code_item,
107                                                 access_flags,
108                                                 invoke_type,
109                                                 class_def_idx,
110                                                 method_idx,
111                                                 class_loader,
112                                                 dex_file);
113    if (method != nullptr) {
114      return method;
115    }
116
117    return ArtCompileMethod(GetCompilerDriver(),
118                            code_item,
119                            access_flags,
120                            invoke_type,
121                            class_def_idx,
122                            method_idx,
123                            class_loader,
124                            dex_file);
125  }
126
127  CompiledMethod* JniCompile(uint32_t access_flags,
128                             uint32_t method_idx,
129                             const DexFile& dex_file) const OVERRIDE {
130    return ArtLLVMJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
131  }
132
133  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const {
134    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode());
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      OVERRIDE
143      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
144    return art::ElfWriterMclinker::Create(
145        file, oat_writer, dex_files, android_root, is_host, driver);
146  }
147
148  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const {
149    return PortableCodeGenerator(
150        cu, cu->mir_graph.get(), &cu->arena,
151        reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit));
152  }
153
154  void InitCompilationUnit(CompilationUnit& cu) const {
155      // Fused long branches not currently useful in bitcode.
156    cu.disable_opt |=
157        (1 << kBranchFusing) |
158        (1 << kSuppressExceptionEdges);
159  }
160
161  bool IsPortable() const OVERRIDE {
162    return true;
163  }
164
165  void SetBitcodeFileName(const CompilerDriver& driver, const std::string& filename) {
166    typedef void (*SetBitcodeFileNameFn)(const CompilerDriver&, const std::string&);
167
168    SetBitcodeFileNameFn set_bitcode_file_name =
169      reinterpret_cast<SetBitcodeFileNameFn>(compilerLLVMSetBitcodeFileName);
170
171    set_bitcode_file_name(driver, filename);
172  }
173
174 private:
175  DISALLOW_COPY_AND_ASSIGN(LLVMCompiler);
176};
177#endif
178
179Compiler* Compiler::Create(CompilerDriver* driver, Compiler::Kind kind) {
180  switch (kind) {
181    case kQuick:
182      return new QuickCompiler(driver);
183      break;
184    case kOptimizing:
185      return new OptimizingCompiler(driver);
186      break;
187    case kPortable:
188#ifdef ART_USE_PORTABLE_COMPILER
189      return new LLVMCompiler(driver);
190#else
191      LOG(FATAL) << "Portable compiler not compiled";
192#endif
193      break;
194    default:
195      LOG(FATAL) << "UNREACHABLE";
196  }
197  return nullptr;
198}
199
200}  // namespace art
201