OmniSciDB  a987f07e93
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AutomaticIRMetadataGuard.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
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 #pragma once
18 
19 #include <cctype>
20 #include <cstdint>
21 #include <string>
22 #include <unordered_set>
23 #include <vector>
24 
25 #include "CgenState.h"
26 
27 #ifndef NDEBUG
28 
30 
32  public:
34  const std::string& ppfile,
35  const size_t ppline,
36  const std::string& ppfunc)
37  : cgen_state_(cgen_state)
38  , ppfile_(ppfile)
39  , ppline_(ppline)
40  , ppfunc_(ppfunc)
41  , our_instructions_(nullptr)
42  , done_(false) {
43  std::lock_guard<std::mutex> lock(instructions_mutex_);
46  if (enabled_) {
51  }
52  }
53 
55 
56  void done() noexcept {
57  if (enabled_ && !done_) {
58  std::lock_guard<std::mutex> lock(instructions_mutex_);
60  if (this_is_root_) {
63  }
64  done_ = true;
65  }
66  }
67 
69  // iterate over all LLVM instructions in the module
70  for (auto func_it = cgen_state_->module_->begin();
71  func_it != cgen_state_->module_->end();
72  ++func_it) {
73  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
74  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
75  // remember all the instructions that already existed
76  // before this guard object was constructed
77  CHECK_EQ(preexisting_instructions_.count(&*instr_it), 0U);
78  preexisting_instructions_.insert(&*instr_it);
79  }
80  }
81  }
82  }
83 
84  void rememberOurInstructions() noexcept {
85  // iterate over all LLVM instructions in the module
86  for (auto func_it = cgen_state_->module_->begin();
87  func_it != cgen_state_->module_->end();
88  ++func_it) {
89  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
90  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
91  // remember any new instructions as ours, skipping
92  // instructions already remembered as preexisting
93  llvm::Instruction* i = &*instr_it;
94  if (!preexisting_instructions_.count(i)) {
95  std::string qefile = makeQueryEngineFilename();
96  std::string footnote =
97  ppfunc_ + " after " + qefile + " line #" + std::to_string(ppline_);
98  auto it = our_instructions_->find(i);
99  if (it == our_instructions_->end()) {
100  std::string bfile = replacePunctuation(makeBaseFilename());
101  our_instructions_->emplace(i, InstructionInfo{bfile, footnote});
102  } else {
103  it->second.detailed_footnote_ =
104  footnote + ", " + it->second.detailed_footnote_;
105  }
106  }
107  }
108  }
109  }
110  }
111 
112  void markInstructions() noexcept {
113  // iterate over all LLVM instructions in the module
114  for (auto func_it = cgen_state_->module_->begin();
115  func_it != cgen_state_->module_->end();
116  ++func_it) {
117  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
118  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
119  auto our_it = our_instructions_->find(&*instr_it);
120  if (our_it == our_instructions_->end()) {
121  continue;
122  }
123  unsigned kind_id =
124  cgen_state_->context_.getMDKindID(our_it->second.main_filename_);
125  auto value = llvm::MDNode::get(
127  llvm::MDString::get(
129  detailed_footnote_prefix_ + our_it->second.detailed_footnote_));
130  our_it->first->setMetadata(kind_id, value);
131  }
132  }
133  }
134  }
135 
136  private:
137  std::string makeBaseFilename() {
138  std::vector<std::string> fnames = split(ppfile_, "/");
139  if (!fnames.empty()) {
140  return fnames.back();
141  }
142  return ppfile_;
143  }
144 
145  std::string makeQueryEngineFilename() {
146  std::vector<std::string> fnames = split(ppfile_, "/");
147  bool copying{false};
148  std::string f;
149  for (auto n : fnames) {
150  if (copying && !n.empty()) {
151  if (!f.empty()) {
152  f += "/";
153  }
154  f += n;
155  }
156  if (n == "QueryEngine") {
157  copying = true;
158  }
159  }
160  if (f.empty() && fnames.size() > 0) {
161  f = fnames.back();
162  } else if (f.empty()) {
163  f = ppfile_;
164  }
165  return f;
166  }
167 
168  std::string replacePunctuation(std::string text) {
169  static const std::unordered_set<std::string::value_type> allowed_punct{'_', '.'};
170  for (auto& ch : text) {
171  if (std::ispunct(ch) && !allowed_punct.count(ch)) {
172  ch = '_';
173  }
174  }
175  return text;
176  }
177 
178  private:
180  std::string main_filename_;
181  std::string detailed_footnote_;
182  };
183  using OurInstructions = std::unordered_map<llvm::Instruction*, InstructionInfo>;
184 
186 
187  const std::string ppfile_;
188  const size_t ppline_;
189  const std::string ppfunc_;
190 
191  std::unordered_set<llvm::Instruction*> preexisting_instructions_;
193 
194  bool done_;
196  bool enabled_;
197 
198  inline static std::unordered_map<CgenState*, OurInstructions> instructions_;
199 
200  inline static const std::string detailed_footnote_prefix_{"HEAVY.AI Debugging Info: "};
201 
202  inline static std::mutex instructions_mutex_;
203 };
204 
205 #define AUTOMATIC_IR_METADATA(CGENSTATE) \
206  AutomaticIRMetadataGuard automatic_ir_metadata_guard( \
207  CGENSTATE, __FILE__, __LINE__, __func__)
208 
209 #define AUTOMATIC_IR_METADATA_DONE() automatic_ir_metadata_guard.done()
210 
211 #else // NDEBUG
212 
213 #define AUTOMATIC_IR_METADATA(CGENSTATE)
214 #define AUTOMATIC_IR_METADATA_DONE()
215 
216 #endif // NDEBUG
#define CHECK_EQ(x, y)
Definition: Logger.h:297
void rememberPreexistingInstructions() noexcept
constexpr double f
Definition: Utm.h:31
std::string to_string(char const *&&v)
std::vector< std::string > split(std::string_view str, std::string_view delim, std::optional< size_t > maxsplit)
split apart a string into a vector of substrings
AutomaticIRMetadataGuard(CgenState *cgen_state, const std::string &ppfile, const size_t ppline, const std::string &ppfunc)
llvm::Module * module_
Definition: CgenState.h:364
llvm::LLVMContext & context_
Definition: CgenState.h:373
static std::unordered_map< CgenState *, OurInstructions > instructions_
std::unordered_map< llvm::Instruction *, InstructionInfo > OurInstructions
std::unordered_set< llvm::Instruction * > preexisting_instructions_
bool g_enable_automatic_ir_metadata
Definition: Execute.cpp:162
bool g_enable_watchdog false
Definition: Execute.cpp:79
#define CHECK(condition)
Definition: Logger.h:289
constexpr double n
Definition: Utm.h:38
std::string replacePunctuation(std::string text)
static const std::string detailed_footnote_prefix_