OmniSciDB  8fa3bf436f
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AutomaticIRMetadataGuard.h
Go to the documentation of this file.
1 /*
2  * Copyright 2020 OmniSci, 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)
45  if (enabled_) {
50  }
51  }
52 
54 
55  void done() noexcept {
56  if (enabled_ && !done_) {
58  if (this_is_root_) {
61  }
62  done_ = true;
63  }
64  }
65 
67  // iterate over all LLVM instructions in the module
68  for (auto func_it = cgen_state_->module_->begin();
69  func_it != cgen_state_->module_->end();
70  ++func_it) {
71  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
72  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
73  // remember all the instructions that already existed
74  // before this guard object was constructed
75  CHECK_EQ(preexisting_instructions_.count(&*instr_it), 0U);
76  preexisting_instructions_.insert(&*instr_it);
77  }
78  }
79  }
80  }
81 
82  void rememberOurInstructions() noexcept {
83  // iterate over all LLVM instructions in the module
84  for (auto func_it = cgen_state_->module_->begin();
85  func_it != cgen_state_->module_->end();
86  ++func_it) {
87  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
88  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
89  // remember any new instructions as ours, skipping
90  // instructions already remembered as preexisting
91  llvm::Instruction* i = &*instr_it;
92  if (!preexisting_instructions_.count(i)) {
93  std::string qefile = makeQueryEngineFilename();
94  std::string footnote =
95  ppfunc_ + " near " + qefile + " line #" + std::to_string(ppline_);
96  auto it = our_instructions_->find(i);
97  if (it == our_instructions_->end()) {
98  std::string bfile = replacePunctuation(makeBaseFilename());
99  our_instructions_->emplace(i, InstructionInfo{bfile, footnote});
100  } else {
101  it->second.detailed_footnote_ =
102  footnote + ", " + it->second.detailed_footnote_;
103  }
104  }
105  }
106  }
107  }
108  }
109 
110  void markInstructions() noexcept {
111  // iterate over all LLVM instructions in the module
112  for (auto func_it = cgen_state_->module_->begin();
113  func_it != cgen_state_->module_->end();
114  ++func_it) {
115  for (auto bb_it = func_it->begin(); bb_it != func_it->end(); ++bb_it) {
116  for (auto instr_it = bb_it->begin(); instr_it != bb_it->end(); ++instr_it) {
117  auto our_it = our_instructions_->find(&*instr_it);
118  if (our_it == our_instructions_->end()) {
119  continue;
120  }
121  unsigned kind_id =
122  cgen_state_->context_.getMDKindID(our_it->second.main_filename_);
123  auto value = llvm::MDNode::get(
125  llvm::MDString::get(
127  detailed_footnote_prefix_ + our_it->second.detailed_footnote_));
128  our_it->first->setMetadata(kind_id, value);
129  }
130  }
131  }
132  }
133 
134  private:
135  std::string makeBaseFilename() {
136  std::vector<std::string> fnames = split(ppfile_, "/");
137  if (!fnames.empty()) {
138  return fnames.back();
139  }
140  return ppfile_;
141  }
142 
143  std::string makeQueryEngineFilename() {
144  std::vector<std::string> fnames = split(ppfile_, "/");
145  bool copying{false};
146  std::string f;
147  for (auto n : fnames) {
148  if (copying && !n.empty()) {
149  if (!f.empty()) {
150  f += "/";
151  }
152  f += n;
153  }
154  if (n == "QueryEngine") {
155  copying = true;
156  }
157  }
158  if (f.empty() && fnames.size() > 0) {
159  f = fnames.back();
160  } else if (f.empty()) {
161  f = ppfile_;
162  }
163  return f;
164  }
165 
166  std::string replacePunctuation(std::string text) {
167  static const std::unordered_set<std::string::value_type> allowed_punct{'_', '.'};
168  for (auto& ch : text) {
169  if (std::ispunct(ch) && !allowed_punct.count(ch)) {
170  ch = '_';
171  }
172  }
173  return text;
174  }
175 
176  private:
178  std::string main_filename_;
179  std::string detailed_footnote_;
180  };
181  using OurInstructions = std::unordered_map<llvm::Instruction*, InstructionInfo>;
182 
184 
185  const std::string ppfile_;
186  const size_t ppline_;
187  const std::string ppfunc_;
188 
189  std::unordered_set<llvm::Instruction*> preexisting_instructions_;
191 
192  bool done_;
194  bool enabled_;
195 
196  inline static std::unordered_map<CgenState*, OurInstructions> instructions_;
197 
198  inline static const std::string detailed_footnote_prefix_{"Omnisci Debugging Info: "};
199 };
200 
201 #define AUTOMATIC_IR_METADATA(CGENSTATE) \
202  AutomaticIRMetadataGuard automatic_ir_metadata_guard( \
203  CGENSTATE, __FILE__, __LINE__, __func__)
204 
205 #define AUTOMATIC_IR_METADATA_DONE() automatic_ir_metadata_guard.done()
206 
207 #else // NDEBUG
208 
209 #define AUTOMATIC_IR_METADATA(CGENSTATE)
210 #define AUTOMATIC_IR_METADATA_DONE()
211 
212 #endif // NDEBUG
#define CHECK_EQ(x, y)
Definition: Logger.h:211
void rememberPreexistingInstructions() noexcept
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:318
llvm::LLVMContext & context_
Definition: CgenState.h:327
int count
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:136
bool g_enable_watchdog false
Definition: Execute.cpp:76
#define CHECK(condition)
Definition: Logger.h:203
char * f
std::string replacePunctuation(std::string text)
static const std::string detailed_footnote_prefix_