diff options
Diffstat (limited to 'compiler/compiler_backend.cc')
| -rw-r--r-- | compiler/compiler_backend.cc | 293 | 
1 files changed, 293 insertions, 0 deletions
| diff --git a/compiler/compiler_backend.cc b/compiler/compiler_backend.cc new file mode 100644 index 0000000000..b8f21a9bf5 --- /dev/null +++ b/compiler/compiler_backend.cc @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compiler_backend.h" +#include "elf_writer_quick.h" +#include "dex/quick/mir_to_lir.h" +#include "dex/mir_graph.h" +#include "driver/compiler_driver.h" +#include "mirror/art_method-inl.h" + +#ifdef ART_USE_PORTABLE_COMPILER +#include "dex/portable/mir_to_gbc.h" +#include "elf_writer_mclinker.h" +#endif + +namespace art { + +#ifdef ART_SEA_IR_MODE +extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler, +                                                   const art::DexFile::CodeItem* code_item, +                                                   uint32_t access_flags, +                                                   art::InvokeType invoke_type, +                                                   uint16_t class_def_idx, +                                                   uint32_t method_idx, +                                                   jobject class_loader, +                                                   const art::DexFile& dex_file); +#endif + +extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver); +extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver); +extern "C" art::CompiledMethod* ArtQuickCompileMethod(art::CompilerDriver& compiler, +                                                      const art::DexFile::CodeItem* code_item, +                                                      uint32_t access_flags, +                                                      art::InvokeType invoke_type, +                                                      uint16_t class_def_idx, +                                                      uint32_t method_idx, +                                                      jobject class_loader, +                                                      const art::DexFile& dex_file); + +extern "C" art::CompiledMethod* ArtQuickJniCompileMethod(art::CompilerDriver& compiler, +                                                         uint32_t access_flags, uint32_t method_idx, +                                                         const art::DexFile& dex_file); + + +static CompiledMethod* TryCompileWithSeaIR(art::CompilerDriver& compiler, +                                           const art::DexFile::CodeItem* code_item, +                                           uint32_t access_flags, +                                           art::InvokeType invoke_type, +                                           uint16_t class_def_idx, +                                           uint32_t method_idx, +                                           jobject class_loader, +                                           const art::DexFile& dex_file) { +#ifdef ART_SEA_IR_MODE +    bool use_sea = Runtime::Current()->IsSeaIRMode(); +    use_sea = use_sea && +        (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci")); +    if (use_sea) { +      LOG(INFO) << "Using SEA IR to compile..." << std::endl; +      return SeaIrCompileMethod(compiler, +                                code_item, +                                access_flags, +                                invoke_type, +                                class_def_idx, +                                method_idx, +                                class_loader, +                                dex_file); +  } +#endif +  return nullptr; +} + + +class QuickBackend : public CompilerBackend { + public: +  QuickBackend() : CompilerBackend(100) {} + +  void Init(CompilerDriver& driver) const { +    ArtInitQuickCompilerContext(driver); +  } + +  void UnInit(CompilerDriver& driver) const { +    ArtUnInitQuickCompilerContext(driver); +  } + +  CompiledMethod* Compile(CompilerDriver& compiler, +                          const DexFile::CodeItem* code_item, +                          uint32_t access_flags, +                          InvokeType invoke_type, +                          uint16_t class_def_idx, +                          uint32_t method_idx, +                          jobject class_loader, +                          const DexFile& dex_file) const { +    CompiledMethod* method = TryCompileWithSeaIR(compiler, +                                                 code_item, +                                                 access_flags, +                                                 invoke_type, +                                                 class_def_idx, +                                                 method_idx, +                                                 class_loader, +                                                 dex_file); +    if (method != nullptr) return method; + +    return ArtQuickCompileMethod(compiler, +                                 code_item, +                                 access_flags, +                                 invoke_type, +                                 class_def_idx, +                                 method_idx, +                                 class_loader, +                                 dex_file); +  } + +  CompiledMethod* JniCompile(CompilerDriver& driver, +                             uint32_t access_flags, +                             uint32_t method_idx, +                             const DexFile& dex_file) const { +    return ArtQuickJniCompileMethod(driver, access_flags, method_idx, dex_file); +  } + +  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const { +    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCode()); +  } + +  bool WriteElf(art::File* file, +                OatWriter& oat_writer, +                const std::vector<const art::DexFile*>& dex_files, +                const std::string& android_root, +                bool is_host, const CompilerDriver& driver) const +    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +    return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, driver); +  } + +  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const { +    Mir2Lir* mir_to_lir = nullptr; +    switch (cu->instruction_set) { +      case kThumb2: +        mir_to_lir = ArmCodeGenerator(cu, cu->mir_graph.get(), &cu->arena); +        break; +      case kMips: +        mir_to_lir = MipsCodeGenerator(cu, cu->mir_graph.get(), &cu->arena); +        break; +      case kX86: +        mir_to_lir = X86CodeGenerator(cu, cu->mir_graph.get(), &cu->arena); +        break; +      default: +        LOG(FATAL) << "Unexpected instruction set: " << cu->instruction_set; +    } + +    /* The number of compiler temporaries depends on backend so set it up now if possible */ +    if (mir_to_lir) { +      size_t max_temps = mir_to_lir->GetMaxPossibleCompilerTemps(); +      bool set_max = cu->mir_graph->SetMaxAvailableNonSpecialCompilerTemps(max_temps); +      CHECK(set_max); +    } +    return mir_to_lir;; +  } + +  void InitCompilationUnit(CompilationUnit& cu) const {} + + private: +  DISALLOW_COPY_AND_ASSIGN(QuickBackend); +}; + +#ifdef ART_USE_PORTABLE_COMPILER + +extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver); +extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver); +extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver, +                                                 const art::DexFile::CodeItem* code_item, +                                                 uint32_t access_flags, +                                                 art::InvokeType invoke_type, +                                                 uint16_t class_def_idx, +                                                 uint32_t method_idx, +                                                 jobject class_loader, +                                                 const art::DexFile& dex_file); +extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver, +                                                        uint32_t access_flags, uint32_t method_idx, +                                                        const art::DexFile& dex_file); + + +class LLVMBackend : public CompilerBackend { + public: +  LLVMBackend() : CompilerBackend(1000) {} + +  void Init(CompilerDriver& driver) const { +    ArtInitCompilerContext(driver); +  } + +  void UnInit(CompilerDriver& driver) const { +    ArtUnInitCompilerContext(driver); +  } + +  CompiledMethod* Compile(CompilerDriver& compiler, +                          const DexFile::CodeItem* code_item, +                          uint32_t access_flags, +                          InvokeType invoke_type, +                          uint16_t class_def_idx, +                          uint32_t method_idx, +                          jobject class_loader, +                          const DexFile& dex_file) const { +    CompiledMethod* method = TryCompileWithSeaIR(compiler, +                                                 code_item, +                                                 access_flags, +                                                 invoke_type, +                                                 class_def_idx, +                                                 method_idx, +                                                 class_loader, +                                                 dex_file); +    if (method != nullptr) return method; + +    return ArtCompileMethod(compiler, +                            code_item, +                            access_flags, +                            invoke_type, +                            class_def_idx, +                            method_idx, +                            class_loader, +                            dex_file); +  } + +  CompiledMethod* JniCompile(CompilerDriver& driver, +                             uint32_t access_flags, +                             uint32_t method_idx, +                             const DexFile& dex_file) const { +    return ArtLLVMJniCompileMethod(driver, access_flags, method_idx, dex_file); +  } + +  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const { +    return reinterpret_cast<uintptr_t>(method->GetEntryPointFromPortableCompiledCode()); +  } + +  bool WriteElf(art::File* file, +                OatWriter& oat_writer, +                const std::vector<const art::DexFile*>& dex_files, +                const std::string& android_root, +                bool is_host, const CompilerDriver& driver) const +    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +    return art::ElfWriterMclinker::Create( +        file, oat_writer, dex_files, android_root, is_host, driver); +  } + +  Backend* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit) const { +    return PortableCodeGenerator( +        cu, cu->mir_graph.get(), &cu->arena, +        reinterpret_cast<art::llvm::LlvmCompilationUnit*>(compilation_unit)); +  } + +  void InitCompilationUnit(CompilationUnit& cu) const { +      // Fused long branches not currently useful in bitcode. +    cu.disable_opt |= +        (1 << kBranchFusing) | +        (1 << kSuppressExceptionEdges); +  } + +  bool isPortable() const { return true; } + + private: +  DISALLOW_COPY_AND_ASSIGN(LLVMBackend); +}; +#endif + +CompilerBackend* CompilerBackend::Create(CompilerBackend::Kind kind) { +  switch (kind) { +    case kQuick: +      return new QuickBackend(); +      break; +    case kPortable: +#ifdef ART_USE_PORTABLE_COMPILER +      return new LLVMBackend(); +#else +      LOG(FATAL) << "Portable compiler not compiled"; +#endif +      break; +    default: +      LOG(FATAL) << "UNREACHABLE"; +  } +  return nullptr; +} + +}  // namespace art |