14e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler/*
24e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * Copyright (C) 2014 The Android Open Source Project
34e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler *
44e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * Licensed under the Apache License, Version 2.0 (the "License");
54e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * you may not use this file except in compliance with the License.
64e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * You may obtain a copy of the License at
74e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler *
84e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler *      http://www.apache.org/licenses/LICENSE-2.0
94e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler *
104e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * Unless required by applicable law or agreed to in writing, software
114e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * distributed under the License is distributed on an "AS IS" BASIS,
124e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * See the License for the specific language governing permissions and
144e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * limitations under the License.
154e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler */
164e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
174e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler#ifndef ART_COMPILER_DEX_PASS_DRIVER_H_
184e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler#define ART_COMPILER_DEX_PASS_DRIVER_H_
194e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
2075ba13f244098f42584637b8fd3f6d74d2fc291aVladimir Marko#include <vector>
214e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler#include "pass.h"
224e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler#include "safe_map.h"
234e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
244e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler// Forward Declarations.
254e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylerclass Pass;
264f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scottclass PassDriver;
274e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylernamespace art {
284f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott/**
294f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott * @brief Helper function to create a single instance of a given Pass and can be shared across
304f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott * the threads.
314f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott */
324f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scotttemplate <typename PassType>
334f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scottconst Pass* GetPassInstance() {
344f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static const PassType pass;
354f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  return &pass;
364f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott}
374f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
384f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott// Empty holder for the constructor.
394f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scottclass PassDriverDataHolder {
404f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott};
414e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
424e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler/**
434e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler * @class PassDriver
444f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott * @brief PassDriver is the wrapper around all Pass instances in order to execute them
454e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler */
464f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scotttemplate <typename PassDriverType>
474e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beylerclass PassDriver {
484e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler public:
494f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  explicit PassDriver() {
504f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    InitializePasses();
514f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
524e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
534f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  virtual ~PassDriver() {
544f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
554e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
564e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /**
574e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   * @brief Insert a Pass: can warn if multiple passes have the same name.
584e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   */
594f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  void InsertPass(const Pass* new_pass) {
604f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    DCHECK(new_pass != nullptr);
614f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    DCHECK(new_pass->GetName() != nullptr && new_pass->GetName()[0] != 0);
624f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
634f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    // It is an error to override an existing pass.
644f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    DCHECK(GetPass(new_pass->GetName()) == nullptr)
654f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott        << "Pass name " << new_pass->GetName() << " already used.";
664f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
674f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    // Now add to the list.
684f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    pass_list_.push_back(new_pass);
694f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
704e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
714e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /**
724e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   * @brief Run a pass using the name as key.
734e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   * @return whether the pass was applied.
744e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   */
754f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  virtual bool RunPass(const char* pass_name) {
764f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    // Paranoid: c_unit cannot be nullptr and we need a pass name.
774f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    DCHECK(pass_name != nullptr && pass_name[0] != 0);
784f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
794f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    const Pass* cur_pass = GetPass(pass_name);
804f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
814f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    if (cur_pass != nullptr) {
824f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      return RunPass(cur_pass);
834f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    }
844f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
854f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    // Return false, we did not find the pass.
864f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    return false;
874f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
884e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
894e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /**
904f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Runs all the passes with the pass_list_.
914e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   */
924f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  void Launch() {
934f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    for (const Pass* cur_pass : pass_list_) {
944f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      RunPass(cur_pass);
954f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    }
964f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
974e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
984f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /**
994f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Searches for a particular pass.
1004f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @param the name of the pass to be searched for.
1014f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   */
1024f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  const Pass* GetPass(const char* name) const {
1034f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    for (const Pass* cur_pass : pass_list_) {
1044f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      if (strcmp(name, cur_pass->GetName()) == 0) {
1054f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott        return cur_pass;
1064f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      }
1074f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    }
1084f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    return nullptr;
1094f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1104e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1114f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static void CreateDefaultPassList(const std::string& disable_passes) {
1124f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    // Insert each pass from g_passes into g_default_pass_list.
1134f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    PassDriverType::g_default_pass_list.clear();
1144f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    PassDriverType::g_default_pass_list.reserve(PassDriver<PassDriverType>::g_passes_size);
1154f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    for (uint16_t i = 0; i < PassDriver<PassDriverType>::g_passes_size; ++i) {
1164f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      const Pass* pass = PassDriver<PassDriverType>::g_passes[i];
1174f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      // Check if we should disable this pass.
1184f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      if (disable_passes.find(pass->GetName()) != std::string::npos) {
1194f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott        LOG(INFO) << "Skipping " << pass->GetName();
1204f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      } else {
1214f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott        PassDriver<PassDriverType>::g_default_pass_list.push_back(pass);
1224f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      }
1234f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    }
1244f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1254e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1264e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /**
1274f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Run a pass using the Pass itself.
1284f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @param time_split do we want a time split request(default: false)?
1294f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @return whether the pass was applied.
1304e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   */
1314f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  virtual bool RunPass(const Pass* pass, bool time_split = false) = 0;
1324e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1334e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /**
1344f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Print the pass names of all the passes available.
1354e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler   */
1364f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static void PrintPassNames() {
1374f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    LOG(INFO) << "Loop Passes are:";
1384e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1394f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    for (const Pass* cur_pass : PassDriver<PassDriverType>::g_default_pass_list) {
1404f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott      LOG(INFO) << "\t-" << cur_pass->GetName();
1414f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    }
1424f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1434e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1444f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /**
1454f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Gets the list of passes currently schedule to execute.
1464f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @return pass_list_
1474f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   */
1484f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  std::vector<const Pass*>& GetPasses() {
1494f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    return pass_list_;
1504f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1514e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1528bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  static void SetPrintAllPasses() {
1538bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler    default_print_passes_ = true;
1548bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  }
1558bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
156a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko  static void SetDumpPassList(const std::string& list) {
157a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko    dump_pass_list_ = list;
1588bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  }
1598bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
160a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko  static void SetPrintPassList(const std::string& list) {
161a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko    print_pass_list_ = list;
1624e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  }
1634e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1644f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  void SetDefaultPasses() {
1654f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    pass_list_ = PassDriver<PassDriverType>::g_default_pass_list;
1664f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1674f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
1688bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler protected:
1698bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  virtual void InitializePasses() {
1708bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler    SetDefaultPasses();
1718bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  }
1728bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
1734f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /**
1744f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Apply a patch: perform start/work/end functions.
1754f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   */
1764f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  virtual void ApplyPass(PassDataHolder* data, const Pass* pass) {
1774f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    pass->Start(data);
1784f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    DispatchPass(pass);
1794f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    pass->End(data);
1804f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1814f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /**
1824f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * @brief Dispatch a patch.
1834f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   * Gives the ability to add logic when running the patch.
1844f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott   */
1854f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  virtual void DispatchPass(const Pass* pass) {
1864f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott    UNUSED(pass);
1874f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  }
1884e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1894e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler  /** @brief List of passes: provides the order to execute the passes. */
19075ba13f244098f42584637b8fd3f6d74d2fc291aVladimir Marko  std::vector<const Pass*> pass_list_;
1914e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1924f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /** @brief The number of passes within g_passes.  */
1934f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static const uint16_t g_passes_size;
1944f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott
1954f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /** @brief The number of passes within g_passes.  */
1964f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static const Pass* const g_passes[];
1974e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
1984f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  /** @brief The default pass list is used to initialize pass_list_. */
1994f59668b3d51f63601ebe59dbd2b7e8a7c5bd093James C Scott  static std::vector<const Pass*> g_default_pass_list;
2008bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
2018bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  /** @brief Do we, by default, want to be printing the log messages? */
2028bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  static bool default_print_passes_;
2038bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
2048bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  /** @brief What are the passes we want to be printing the log messages? */
205a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko  static std::string print_pass_list_;
2068bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler
2078bceccec7eddff8cd872aa20505b4a3a6be60a16Jean Christophe Beyler  /** @brief What are the passes we want to be dumping the CFG? */
208a9f1ce6fbe8a9247d0d8e20727f590b091e816daVladimir Marko  static std::string dump_pass_list_;
2094e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler};
2104e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler
2114e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler}  // namespace art
2124e97c539408f47145526f0062c1c06df99146a73Jean Christophe Beyler#endif  // ART_COMPILER_DEX_PASS_DRIVER_H_
213