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