summaryrefslogtreecommitdiffstats
path: root/compiler/dex/pass_driver.h
blob: 8a3eae1486b3a168a30dff5a461cf4bc85a76604 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * 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.
 */

#ifndef ART_COMPILER_DEX_PASS_DRIVER_H_
#define ART_COMPILER_DEX_PASS_DRIVER_H_

#include <vector>
#include "pass.h"
#include "safe_map.h"

// Forward Declarations.
class Pass;
class PassDriver;
namespace art {
/**
 * @brief Helper function to create a single instance of a given Pass and can be shared across
 * the threads.
 */
template <typename PassType>
const Pass* GetPassInstance() {
  static const PassType pass;
  return &pass;
}

// Empty holder for the constructor.
class PassDriverDataHolder {
};

/**
 * @class PassDriver
 * @brief PassDriver is the wrapper around all Pass instances in order to execute them
 */
template <typename PassDriverType>
class PassDriver {
 public:
  explicit PassDriver() {
    InitializePasses();
  }

  virtual ~PassDriver() {
  }

  /**
   * @brief Insert a Pass: can warn if multiple passes have the same name.
   */
  void InsertPass(const Pass* new_pass) {
    DCHECK(new_pass != nullptr);
    DCHECK(new_pass->GetName() != nullptr && new_pass->GetName()[0] != 0);

    // It is an error to override an existing pass.
    DCHECK(GetPass(new_pass->GetName()) == nullptr)
        << "Pass name " << new_pass->GetName() << " already used.";

    // Now add to the list.
    pass_list_.push_back(new_pass);
  }

  /**
   * @brief Run a pass using the name as key.
   * @return whether the pass was applied.
   */
  virtual bool RunPass(const char* pass_name) {
    // Paranoid: c_unit cannot be nullptr and we need a pass name.
    DCHECK(pass_name != nullptr && pass_name[0] != 0);

    const Pass* cur_pass = GetPass(pass_name);

    if (cur_pass != nullptr) {
      return RunPass(cur_pass);
    }

    // Return false, we did not find the pass.
    return false;
  }

  /**
   * @brief Runs all the passes with the pass_list_.
   */
  void Launch() {
    for (const Pass* cur_pass : pass_list_) {
      RunPass(cur_pass);
    }
  }

  /**
   * @brief Searches for a particular pass.
   * @param the name of the pass to be searched for.
   */
  const Pass* GetPass(const char* name) const {
    for (const Pass* cur_pass : pass_list_) {
      if (strcmp(name, cur_pass->GetName()) == 0) {
        return cur_pass;
      }
    }
    return nullptr;
  }

  static void CreateDefaultPassList(const std::string& disable_passes) {
    // Insert each pass from g_passes into g_default_pass_list.
    PassDriverType::g_default_pass_list.clear();
    PassDriverType::g_default_pass_list.reserve(PassDriver<PassDriverType>::g_passes_size);
    for (uint16_t i = 0; i < PassDriver<PassDriverType>::g_passes_size; ++i) {
      const Pass* pass = PassDriver<PassDriverType>::g_passes[i];
      // Check if we should disable this pass.
      if (disable_passes.find(pass->GetName()) != std::string::npos) {
        LOG(INFO) << "Skipping " << pass->GetName();
      } else {
        PassDriver<PassDriverType>::g_default_pass_list.push_back(pass);
      }
    }
  }

  /**
   * @brief Run a pass using the Pass itself.
   * @param time_split do we want a time split request(default: false)?
   * @return whether the pass was applied.
   */
  virtual bool RunPass(const Pass* pass, bool time_split = false) = 0;

  /**
   * @brief Print the pass names of all the passes available.
   */
  static void PrintPassNames() {
    LOG(INFO) << "Loop Passes are:";

    for (const Pass* cur_pass : PassDriver<PassDriverType>::g_default_pass_list) {
      LOG(INFO) << "\t-" << cur_pass->GetName();
    }
  }

  /**
   * @brief Gets the list of passes currently schedule to execute.
   * @return pass_list_
   */
  std::vector<const Pass*>& GetPasses() {
    return pass_list_;
  }

  static void SetPrintAllPasses() {
    default_print_passes_ = true;
  }

  static void SetDumpPassList(const std::string& list) {
    dump_pass_list_ = list;
  }

  static void SetPrintPassList(const std::string& list) {
    print_pass_list_ = list;
  }

  /**
   * @brief Used to set a string that contains the overridden pass options.
   * @details An overridden pass option means that the pass uses this option
   * instead of using its default option.
   * @param s The string passed by user with overridden options. The string is in format
   * Pass1Name:Pass1Option:Pass1Setting,Pass2Name:Pass2Option::Pass2Setting
   */
  static void SetOverriddenPassOptions(const std::string& s) {
    overridden_pass_options_list_ = s;
  }

  void SetDefaultPasses() {
    pass_list_ = PassDriver<PassDriverType>::g_default_pass_list;
  }

 protected:
  virtual void InitializePasses() {
    SetDefaultPasses();
  }

  /**
   * @brief Apply a patch: perform start/work/end functions.
   */
  virtual void ApplyPass(PassDataHolder* data, const Pass* pass) {
    pass->Start(data);
    DispatchPass(pass);
    pass->End(data);
  }
  /**
   * @brief Dispatch a patch.
   * Gives the ability to add logic when running the patch.
   */
  virtual void DispatchPass(const Pass* pass) {
    UNUSED(pass);
  }

  /** @brief List of passes: provides the order to execute the passes. */
  std::vector<const Pass*> pass_list_;

  /** @brief The number of passes within g_passes.  */
  static const uint16_t g_passes_size;

  /** @brief The number of passes within g_passes.  */
  static const Pass* const g_passes[];

  /** @brief The default pass list is used to initialize pass_list_. */
  static std::vector<const Pass*> g_default_pass_list;

  /** @brief Do we, by default, want to be printing the log messages? */
  static bool default_print_passes_;

  /** @brief What are the passes we want to be printing the log messages? */
  static std::string print_pass_list_;

  /** @brief What are the passes we want to be dumping the CFG? */
  static std::string dump_pass_list_;

  /** @brief String of all options that should be overridden for selected passes */
  static std::string overridden_pass_options_list_;
};

}  // namespace art
#endif  // ART_COMPILER_DEX_PASS_DRIVER_H_