OmniSciDB  b24e664e58
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CgenState.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 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 "IRCodegenUtils.h"
20 #include "InValuesBitmap.h"
21 #include "InputMetadata.h"
22 #include "LLVMGlobalContext.h"
23 
24 #include "../Analyzer/Analyzer.h"
25 
26 #include <llvm/IR/Constants.h>
27 #include <llvm/IR/IRBuilder.h>
28 #include <llvm/Transforms/Utils/ValueMapper.h>
29 
30 struct CgenState {
31  public:
32  CgenState(const std::vector<InputTableInfo>& query_infos,
33  const bool contains_left_deep_outer_join)
34  : module_(nullptr)
38  , contains_left_deep_outer_join_(contains_left_deep_outer_join)
39  , outer_join_match_found_per_level_(std::max(query_infos.size(), size_t(1)) - 1)
40  , query_infos_(query_infos)
44 
45  size_t getOrAddLiteral(const Analyzer::Constant* constant,
46  const EncodingType enc_type,
47  const int dict_id,
48  const int device_id) {
49  const auto& ti = constant->get_type_info();
50  const auto type = ti.is_decimal() ? decimal_to_int_type(ti) : ti.get_type();
51  switch (type) {
52  case kBOOLEAN:
53  return getOrAddLiteral(constant->get_is_null()
54  ? int8_t(inline_int_null_val(ti))
55  : int8_t(constant->get_constval().boolval ? 1 : 0),
56  device_id);
57  case kTINYINT:
58  return getOrAddLiteral(constant->get_is_null()
59  ? int8_t(inline_int_null_val(ti))
60  : constant->get_constval().tinyintval,
61  device_id);
62  case kSMALLINT:
63  return getOrAddLiteral(constant->get_is_null()
64  ? int16_t(inline_int_null_val(ti))
65  : constant->get_constval().smallintval,
66  device_id);
67  case kINT:
68  return getOrAddLiteral(constant->get_is_null() ? int32_t(inline_int_null_val(ti))
69  : constant->get_constval().intval,
70  device_id);
71  case kBIGINT:
72  return getOrAddLiteral(constant->get_is_null()
73  ? int64_t(inline_int_null_val(ti))
74  : constant->get_constval().bigintval,
75  device_id);
76  case kFLOAT:
77  return getOrAddLiteral(constant->get_is_null()
78  ? float(inline_fp_null_val(ti))
79  : constant->get_constval().floatval,
80  device_id);
81  case kDOUBLE:
82  return getOrAddLiteral(constant->get_is_null()
83  ? inline_fp_null_val(ti)
84  : constant->get_constval().doubleval,
85  device_id);
86  case kCHAR:
87  case kTEXT:
88  case kVARCHAR:
89  if (enc_type == kENCODING_DICT) {
90  if (constant->get_is_null()) {
91  return getOrAddLiteral(int32_t(inline_int_null_val(ti)), device_id);
92  }
93  return getOrAddLiteral(
94  std::make_pair(*constant->get_constval().stringval, dict_id), device_id);
95  }
96  CHECK_EQ(kENCODING_NONE, enc_type);
97  if (constant->get_is_null()) {
98  throw std::runtime_error(
99  "CHAR / VARCHAR NULL literal not supported in this context"); // TODO(alex):
100  // support
101  // null
102  }
103  return getOrAddLiteral(*constant->get_constval().stringval, device_id);
104  case kTIME:
105  case kTIMESTAMP:
106  case kDATE:
107  case kINTERVAL_DAY_TIME:
109  // TODO(alex): support null
110  return getOrAddLiteral(constant->get_constval().bigintval, device_id);
111  case kARRAY: {
112  if (enc_type == kENCODING_NONE) {
113  if (ti.get_subtype() == kDOUBLE) {
114  std::vector<double> double_array_literal;
115  for (const auto& value : constant->get_value_list()) {
116  const auto c = dynamic_cast<const Analyzer::Constant*>(value.get());
117  CHECK(c);
118  double d = c->get_constval().doubleval;
119  double_array_literal.push_back(d);
120  }
121  return getOrAddLiteral(double_array_literal, device_id);
122  }
123  if (ti.get_subtype() == kINT) {
124  std::vector<int32_t> int32_array_literal;
125  for (const auto& value : constant->get_value_list()) {
126  const auto c = dynamic_cast<const Analyzer::Constant*>(value.get());
127  CHECK(c);
128  int32_t i = c->get_constval().intval;
129  int32_array_literal.push_back(i);
130  }
131  return getOrAddLiteral(int32_array_literal, device_id);
132  }
133  if (ti.get_subtype() == kTINYINT) {
134  std::vector<int8_t> int8_array_literal;
135  for (const auto& value : constant->get_value_list()) {
136  const auto c = dynamic_cast<const Analyzer::Constant*>(value.get());
137  CHECK(c);
138  int8_t i = c->get_constval().tinyintval;
139  int8_array_literal.push_back(i);
140  }
141  if (ti.get_comp_param() == 64) {
142  return getOrAddLiteral(std::make_pair(int8_array_literal, 64), device_id);
143  }
144  return getOrAddLiteral(int8_array_literal, device_id);
145  }
146  throw std::runtime_error("Unsupported literal array");
147  }
148  if (enc_type == kENCODING_GEOINT) {
149  if (ti.get_subtype() == kTINYINT) {
150  std::vector<int8_t> int8_array_literal;
151  for (const auto& value : constant->get_value_list()) {
152  const auto c = dynamic_cast<const Analyzer::Constant*>(value.get());
153  CHECK(c);
154  int8_t i = c->get_constval().tinyintval;
155  int8_array_literal.push_back(i);
156  }
157  if (ti.get_comp_param() == 32) {
158  return getOrAddLiteral(std::make_pair(int8_array_literal, 32), device_id);
159  }
160  return getOrAddLiteral(int8_array_literal, device_id);
161  }
162  }
163  throw std::runtime_error("Encoded literal arrays are not supported");
164  }
165  default:
166  abort();
167  }
168  }
169 
170  using LiteralValue = boost::variant<int8_t,
171  int16_t,
172  int32_t,
173  int64_t,
174  float,
175  double,
176  std::pair<std::string, int>,
177  std::string,
178  std::vector<double>,
179  std::vector<int32_t>,
180  std::vector<int8_t>,
181  std::pair<std::vector<int8_t>, int>>;
182  using LiteralValues = std::vector<LiteralValue>;
183 
184  const std::unordered_map<int, LiteralValues>& getLiterals() const { return literals_; }
185 
186  llvm::Value* addStringConstant(const std::string& str) {
187  llvm::Value* str_lv = ir_builder_.CreateGlobalString(
188  str, "str_const_" + std::to_string(std::hash<std::string>()(str)));
189  auto i8_ptr = llvm::PointerType::get(get_int_type(8, context_), 0);
190  str_constants_.push_back(str_lv);
191  str_lv = ir_builder_.CreateBitCast(str_lv, i8_ptr);
192  return str_lv;
193  }
194 
196  std::unique_ptr<InValuesBitmap>& in_values_bitmap) {
197  if (in_values_bitmap->isEmpty()) {
198  return in_values_bitmap.get();
199  }
200  in_values_bitmaps_.emplace_back(std::move(in_values_bitmap));
201  return in_values_bitmaps_.back().get();
202  }
203  // look up a runtime function based on the name, return type and type of
204  // the arguments and call it; x64 only, don't call from GPU codegen
205  llvm::Value* emitExternalCall(
206  const std::string& fname,
207  llvm::Type* ret_type,
208  const std::vector<llvm::Value*> args,
209  const std::vector<llvm::Attribute::AttrKind>& fnattrs = {}) {
210  std::vector<llvm::Type*> arg_types;
211  for (const auto arg : args) {
212  arg_types.push_back(arg->getType());
213  }
214  auto func_ty = llvm::FunctionType::get(ret_type, arg_types, false);
215  llvm::AttributeList attrs;
216  if (!fnattrs.empty()) {
217  std::vector<std::pair<unsigned, llvm::Attribute>> indexedAttrs;
218  indexedAttrs.reserve(fnattrs.size());
219  for (auto attr : fnattrs)
220  indexedAttrs.emplace_back(llvm::AttributeList::FunctionIndex,
221  llvm::Attribute::get(context_, attr));
222  attrs = llvm::AttributeList::get(context_,
223  {&indexedAttrs.front(), indexedAttrs.size()});
224  }
225  auto func_p = module_->getOrInsertFunction(fname, func_ty, attrs);
226  CHECK(func_p);
227  llvm::Value* result = ir_builder_.CreateCall(func_p, args);
228  // check the assumed type
229  CHECK_EQ(result->getType(), ret_type);
230  return result;
231  }
232 
233  llvm::Value* emitCall(const std::string& fname, const std::vector<llvm::Value*>& args);
234 
235  size_t getLiteralBufferUsage(const int device_id) { return literal_bytes_[device_id]; }
236 
237  llvm::Value* castToTypeIn(llvm::Value* val, const size_t bit_width);
238 
239  std::pair<llvm::ConstantInt*, llvm::ConstantInt*> inlineIntMaxMin(
240  const size_t byte_width,
241  const bool is_signed);
242 
243  llvm::ConstantInt* inlineIntNull(const SQLTypeInfo&);
244 
245  llvm::ConstantFP* inlineFpNull(const SQLTypeInfo&);
246 
247  template <class T>
248  llvm::ConstantInt* llInt(const T v) const {
250  }
251 
252  llvm::ConstantFP* llFp(const float v) const {
253  return static_cast<llvm::ConstantFP*>(
254  llvm::ConstantFP::get(llvm::Type::getFloatTy(context_), v));
255  }
256 
257  llvm::ConstantFP* llFp(const double v) const {
258  return static_cast<llvm::ConstantFP*>(
259  llvm::ConstantFP::get(llvm::Type::getDoubleTy(context_), v));
260  }
261 
262  llvm::ConstantInt* llBool(const bool v) const { return ::ll_bool(v, context_); }
263 
264  llvm::Module* module_;
265  llvm::Function* row_func_;
266  std::vector<llvm::Function*> helper_functions_;
267  llvm::LLVMContext& context_;
268  llvm::ValueToValueMapTy vmap_; // used for cloning the runtime module
269  llvm::IRBuilder<> ir_builder_;
270  std::unordered_map<int, std::vector<llvm::Value*>> fetch_cache_;
273  llvm::Value* lv;
274  };
275  std::vector<FunctionOperValue> ext_call_cache_;
276  std::vector<llvm::Value*> group_by_expr_cache_;
277  std::vector<llvm::Value*> str_constants_;
278  std::vector<llvm::Value*> frag_offsets_;
280  std::vector<llvm::Value*> outer_join_match_found_per_level_;
281  std::unordered_map<int, llvm::Value*> scan_idx_to_hash_pos_;
282  std::vector<std::unique_ptr<const InValuesBitmap>> in_values_bitmaps_;
283  const std::vector<InputTableInfo>& query_infos_;
285 
286  llvm::Function* query_func_;
287  llvm::IRBuilder<> query_func_entry_ir_builder_;
288  std::unordered_map<int, std::vector<llvm::Value*>> query_func_literal_loads_;
289 
293  };
294  std::unordered_map<llvm::Value*, HoistedLiteralLoadLocator> row_func_hoisted_literals_;
295 
296  static size_t literalBytes(const CgenState::LiteralValue& lit) {
297  switch (lit.which()) {
298  case 0:
299  return 1; // int8_t
300  case 1:
301  return 2; // int16_t
302  case 2:
303  return 4; // int32_t
304  case 3:
305  return 8; // int64_t
306  case 4:
307  return 4; // float
308  case 5:
309  return 8; // double
310  case 6:
311  return 4; // std::pair<std::string, int>
312  case 7:
313  return 4; // std::string
314  case 8:
315  return 4; // std::vector<double>
316  case 9:
317  return 4; // std::vector<int32_t>
318  case 10:
319  return 4; // std::vector<int8_t>
320  case 11:
321  return 4; // std::pair<std::vector<int8_t>, int>
322  default:
323  abort();
324  }
325  }
326 
327  static size_t addAligned(const size_t off_in, const size_t alignment) {
328  size_t off = off_in;
329  if (off % alignment != 0) {
330  off += (alignment - off % alignment);
331  }
332  return off + alignment;
333  }
334 
335  private:
336  template <class T>
337  size_t getOrAddLiteral(const T& val, const int device_id) {
338  const LiteralValue var_val(val);
339  size_t literal_found_off{0};
340  auto& literals = literals_[device_id];
341  for (const auto& literal : literals) {
342  const auto lit_bytes = literalBytes(literal);
343  literal_found_off = addAligned(literal_found_off, lit_bytes);
344  if (literal == var_val) {
345  return literal_found_off - lit_bytes;
346  }
347  }
348  literals.emplace_back(val);
349  const auto lit_bytes = literalBytes(var_val);
350  literal_bytes_[device_id] = addAligned(literal_bytes_[device_id], lit_bytes);
351  return literal_bytes_[device_id] - lit_bytes;
352  }
353 
354  std::unordered_map<int, LiteralValues> literals_;
355  std::unordered_map<int, size_t> literal_bytes_;
356 };
std::vector< llvm::Function * > helper_functions_
Definition: CgenState.h:266
int8_t tinyintval
Definition: sqltypes.h:126
const std::list< std::shared_ptr< Analyzer::Expr > > & get_value_list() const
Definition: Analyzer.h:331
#define CHECK_EQ(x, y)
Definition: Logger.h:198
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:103
std::vector< llvm::Value * > outer_join_match_found_per_level_
Definition: CgenState.h:280
Definition: sqltypes.h:52
EncodingType
Definition: encodetypes.h:22
const std::vector< InputTableInfo > & query_infos_
Definition: CgenState.h:283
const Analyzer::FunctionOper * foper
Definition: CgenState.h:272
llvm::Value * addStringConstant(const std::string &str)
Definition: CgenState.h:186
bool boolval
Definition: sqltypes.h:125
llvm::Function * query_func_
Definition: CgenState.h:286
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
std::unordered_map< llvm::Value *, HoistedLiteralLoadLocator > row_func_hoisted_literals_
Definition: CgenState.h:294
llvm::IRBuilder ir_builder_
Definition: CgenState.h:269
bool get_is_null() const
Definition: Analyzer.h:328
std::vector< llvm::Value * > str_constants_
Definition: CgenState.h:277
llvm::ConstantInt * llBool(const bool v) const
Definition: CgenState.h:262
std::unordered_map< int, std::vector< llvm::Value * > > query_func_literal_loads_
Definition: CgenState.h:288
const bool contains_left_deep_outer_join_
Definition: CgenState.h:279
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
const std::unordered_map< int, LiteralValues > & getLiterals() const
Definition: CgenState.h:184
double inline_fp_null_val(const SQL_TYPE_INFO &ti)
int32_t intval
Definition: sqltypes.h:128
size_t getOrAddLiteral(const T &val, const int device_id)
Definition: CgenState.h:337
llvm::ConstantFP * llFp(const double v) const
Definition: CgenState.h:257
std::string to_string(char const *&&v)
static size_t literalBytes(const CgenState::LiteralValue &lit)
Definition: CgenState.h:296
std::vector< FunctionOperValue > ext_call_cache_
Definition: CgenState.h:275
llvm::Function * row_func_
Definition: CgenState.h:265
float floatval
Definition: sqltypes.h:130
std::vector< llvm::Value * > group_by_expr_cache_
Definition: CgenState.h:276
boost::variant< int8_t, int16_t, int32_t, int64_t, float, double, std::pair< std::string, int >, std::string, std::vector< double >, std::vector< int32_t >, std::vector< int8_t >, std::pair< std::vector< int8_t >, int >> LiteralValue
Definition: CgenState.h:181
llvm::Module * module_
Definition: CgenState.h:264
llvm::LLVMContext & context_
Definition: CgenState.h:267
size_t getOrAddLiteral(const Analyzer::Constant *constant, const EncodingType enc_type, const int dict_id, const int device_id)
Definition: CgenState.h:45
CHECK(cgen_state)
CgenState(const std::vector< InputTableInfo > &query_infos, const bool contains_left_deep_outer_join)
Definition: CgenState.h:32
std::unordered_map< int, std::vector< llvm::Value * > > fetch_cache_
Definition: CgenState.h:270
static size_t addAligned(const size_t off_in, const size_t alignment)
Definition: CgenState.h:327
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:24
int64_t bigintval
Definition: sqltypes.h:129
std::vector< LiteralValue > LiteralValues
Definition: CgenState.h:182
const InValuesBitmap * addInValuesBitmap(std::unique_ptr< InValuesBitmap > &in_values_bitmap)
Definition: CgenState.h:195
const int32_t groups_buffer_size return nullptr
std::unordered_map< int, size_t > literal_bytes_
Definition: CgenState.h:355
int16_t smallintval
Definition: sqltypes.h:127
std::unordered_map< int, llvm::Value * > scan_idx_to_hash_pos_
Definition: CgenState.h:281
bool needs_error_check_
Definition: CgenState.h:284
llvm::ConstantFP * llFp(const float v) const
Definition: CgenState.h:252
llvm::IRBuilder query_func_entry_ir_builder_
Definition: CgenState.h:287
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:134
std::string * stringval
Definition: sqltypes.h:134
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:268
std::vector< std::unique_ptr< const InValuesBitmap > > in_values_bitmaps_
Definition: CgenState.h:282
Definition: sqltypes.h:55
Definition: sqltypes.h:56
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value * > args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={})
Definition: CgenState.h:205
std::unordered_map< int, LiteralValues > literals_
Definition: CgenState.h:354
std::vector< llvm::Value * > frag_offsets_
Definition: CgenState.h:278
size_t getLiteralBufferUsage(const int device_id)
Definition: CgenState.h:235
Datum get_constval() const
Definition: Analyzer.h:329
Definition: sqltypes.h:44
llvm::LLVMContext & getGlobalLLVMContext()
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:248
bool g_enable_watchdog false
Definition: Execute.cpp:71
llvm::ValueToValueMapTy vmap_
Definition: CgenState.h:268
const int8_t * literals
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
llvm::ConstantInt * ll_bool(const bool v, llvm::LLVMContext &context)
Definition: sqltypes.h:48
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:74
double doubleval
Definition: sqltypes.h:131
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62