OmniSciDB  91042dcc5b
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConstantIR.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 MapD Technologies, 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 #include "CodeGenerator.h"
18 #include "Execute.h"
19 
20 std::vector<llvm::Value*> CodeGenerator::codegen(const Analyzer::Constant* constant,
21  const EncodingType enc_type,
22  const int dict_id,
23  const CompilationOptions& co) {
25  if (co.hoist_literals) {
26  if (const auto geo_constant = dynamic_cast<const Analyzer::GeoConstant*>(constant)) {
27  return codegenGeoConstant(geo_constant, co);
28  } else {
29  std::vector<const Analyzer::Constant*> constants(
30  executor()->deviceCount(co.device_type), constant);
31  return codegenHoistedConstants(constants, enc_type, dict_id);
32  }
33  }
34  const auto& type_info = constant->get_type_info();
35  const auto type =
36  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
37  switch (type) {
38  case kBOOLEAN:
39  return {llvm::ConstantInt::get(get_int_type(8, cgen_state_->context_),
40  constant->get_constval().boolval)};
41  case kTINYINT:
42  case kSMALLINT:
43  case kINT:
44  case kBIGINT:
45  case kTIME:
46  case kTIMESTAMP:
47  case kDATE:
48  case kINTERVAL_DAY_TIME:
50  return {CodeGenerator::codegenIntConst(constant, cgen_state_)};
51  case kFLOAT:
52  return {llvm::ConstantFP::get(llvm::Type::getFloatTy(cgen_state_->context_),
53  constant->get_constval().floatval)};
54  case kDOUBLE:
55  return {llvm::ConstantFP::get(llvm::Type::getDoubleTy(cgen_state_->context_),
56  constant->get_constval().doubleval)};
57  case kVARCHAR:
58  case kCHAR:
59  case kTEXT: {
60  CHECK(constant->get_constval().stringval || constant->get_is_null());
61  if (constant->get_is_null()) {
62  if (enc_type == kENCODING_DICT) {
63  return {
64  cgen_state_->llInt(static_cast<int32_t>(inline_int_null_val(type_info)))};
65  }
66  return {cgen_state_->llInt(int64_t(0)),
67  llvm::Constant::getNullValue(
68  llvm::PointerType::get(get_int_type(8, cgen_state_->context_), 0)),
69  cgen_state_->llInt(int32_t(0))};
70  }
71  const auto& str_const = *constant->get_constval().stringval;
72  if (enc_type == kENCODING_DICT) {
73  return {
75  ->getStringDictionaryProxy(
76  dict_id, executor()->getRowSetMemoryOwner(), true)
77  ->getIdOfString(str_const))};
78  }
79  return {cgen_state_->llInt(int64_t(0)),
80  cgen_state_->addStringConstant(str_const),
81  cgen_state_->llInt(static_cast<int32_t>(str_const.size()))};
82  }
83  default:
84  CHECK(false);
85  }
86  abort();
87 }
88 
89 llvm::ConstantInt* CodeGenerator::codegenIntConst(const Analyzer::Constant* constant,
90  CgenState* cgen_state) {
91  const auto& type_info = constant->get_type_info();
92  if (constant->get_is_null()) {
93  return cgen_state->inlineIntNull(type_info);
94  }
95  const auto type =
96  type_info.is_decimal() ? decimal_to_int_type(type_info) : type_info.get_type();
97  switch (type) {
98  case kTINYINT:
99  return cgen_state->llInt(constant->get_constval().tinyintval);
100  case kSMALLINT:
101  return cgen_state->llInt(constant->get_constval().smallintval);
102  case kINT:
103  return cgen_state->llInt(constant->get_constval().intval);
104  case kBIGINT:
105  return cgen_state->llInt(constant->get_constval().bigintval);
106  case kTIME:
107  case kTIMESTAMP:
108  case kDATE:
109  case kINTERVAL_DAY_TIME:
111  return cgen_state->llInt(constant->get_constval().bigintval);
112  default:
113  UNREACHABLE();
114  }
115  UNREACHABLE();
116  return nullptr;
117 }
118 
120  const SQLTypeInfo& type_info,
121  const EncodingType enc_type,
122  const int dict_id,
123  const int16_t lit_off) {
125  std::string literal_name = "literal_" + std::to_string(lit_off);
126  auto lit_buff_query_func_lv = get_arg_by_name(cgen_state_->query_func_, "literals");
127  const auto lit_buf_start = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
128  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
129  lit_buff_query_func_lv,
130  cgen_state_->llInt(lit_off));
131  CHECK(!type_info.is_geometry());
132  if (type_info.is_string() && enc_type != kENCODING_DICT) {
134  CHECK_EQ(size_t(4),
136  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
137  lit_buf_start,
138  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
139  // packed offset + length, 16 bits each
140  auto off_and_len = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
141  off_and_len_ptr->getType()->getPointerElementType(), off_and_len_ptr);
142  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
144  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
145  cgen_state_->llInt(int32_t(16)));
146  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
147  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
148 
149  auto var_start = cgen_state_->llInt(int64_t(0));
150  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
151  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
152  lit_buff_query_func_lv,
153  off_lv);
154  auto var_length = len_lv;
155 
156  var_start->setName(literal_name + "_start");
157  var_start_address->setName(literal_name + "_start_address");
158  var_length->setName(literal_name + "_length");
159 
160  return {var_start, var_start_address, var_length};
161  } else if (type_info.is_array() &&
162  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
163  if (enc_type == kENCODING_NONE) {
165  } else if (enc_type == kENCODING_GEOINT) {
167  CHECK_EQ(kTINYINT, type_info.get_subtype());
168  }
169 
170  auto off_and_len_ptr = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(
171  lit_buf_start,
172  llvm::PointerType::get(get_int_type(32, cgen_state_->context_), 0));
173  // packed offset + length, 16 bits each
174  auto off_and_len = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
175  off_and_len_ptr->getType()->getPointerElementType(), off_and_len_ptr);
176  auto off_lv = cgen_state_->query_func_entry_ir_builder_.CreateLShr(
178  off_and_len, cgen_state_->llInt(int32_t(0xffff0000))),
179  cgen_state_->llInt(int32_t(16)));
180  auto len_lv = cgen_state_->query_func_entry_ir_builder_.CreateAnd(
181  off_and_len, cgen_state_->llInt(int32_t(0x0000ffff)));
182 
183  auto var_start_address = cgen_state_->query_func_entry_ir_builder_.CreateGEP(
184  lit_buff_query_func_lv->getType()->getScalarType()->getPointerElementType(),
185  lit_buff_query_func_lv,
186  off_lv);
187  auto var_length = len_lv;
188 
189  var_start_address->setName(literal_name + "_start_address");
190  var_length->setName(literal_name + "_length");
191 
192  return {var_start_address, var_length};
193  }
194 
195  llvm::Type* val_ptr_type{nullptr};
196  const auto val_bits = get_bit_width(type_info);
197  CHECK_EQ(size_t(0), val_bits % 8);
198  if (type_info.is_integer() || type_info.is_decimal() || type_info.is_time() ||
199  type_info.is_timeinterval() || type_info.is_string() || type_info.is_boolean()) {
200  val_ptr_type = llvm::PointerType::get(
201  llvm::IntegerType::get(cgen_state_->context_, val_bits), 0);
202  } else {
203  CHECK(type_info.get_type() == kFLOAT || type_info.get_type() == kDOUBLE);
204  val_ptr_type = (type_info.get_type() == kFLOAT)
205  ? llvm::Type::getFloatPtrTy(cgen_state_->context_)
206  : llvm::Type::getDoublePtrTy(cgen_state_->context_);
207  }
208  auto* bit_cast = cgen_state_->query_func_entry_ir_builder_.CreateBitCast(lit_buf_start,
209  val_ptr_type);
210  auto lit_lv = cgen_state_->query_func_entry_ir_builder_.CreateLoad(
211  bit_cast->getType()->getPointerElementType(), bit_cast);
212  lit_lv->setName(literal_name);
213  return {lit_lv};
214 }
215 
217  const SQLTypeInfo& type_info,
218  const EncodingType enc_type,
219  const int16_t lit_off,
220  const std::vector<llvm::Value*>& literal_loads) {
222  std::string literal_name = "literal_" + std::to_string(lit_off);
223  CHECK(!type_info.is_geometry());
224 
225  if (type_info.is_string() && enc_type != kENCODING_DICT) {
226  CHECK_EQ(literal_loads.size(), 3u);
227 
228  llvm::Value* var_start = literal_loads[0];
229  llvm::Value* var_start_address = literal_loads[1];
230  llvm::Value* var_length = literal_loads[2];
231 
232  llvm::PointerType* placeholder0_type =
233  llvm::PointerType::get(var_start->getType(), 0);
234  auto* int_to_ptr0 =
235  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type);
236  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
237  int_to_ptr0->getType()->getPointerElementType(),
238  int_to_ptr0,
239  "__placeholder__" + literal_name + "_start");
240  llvm::PointerType* placeholder1_type =
241  llvm::PointerType::get(var_start_address->getType(), 0);
242  auto* int_to_ptr1 =
243  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type);
244  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
245  int_to_ptr1->getType()->getPointerElementType(),
246  int_to_ptr1,
247  "__placeholder__" + literal_name + "_start_address");
248  llvm::PointerType* placeholder2_type =
249  llvm::PointerType::get(var_length->getType(), 0);
250  auto* int_to_ptr2 =
251  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder2_type);
252  auto placeholder2 = cgen_state_->ir_builder_.CreateLoad(
253  int_to_ptr2->getType()->getPointerElementType(),
254  int_to_ptr2,
255  "__placeholder__" + literal_name + "_length");
256 
257  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
258  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
259  cgen_state_->row_func_hoisted_literals_[placeholder2] = {lit_off, 2};
260 
261  return {placeholder0, placeholder1, placeholder2};
262  }
263 
264  if (type_info.is_array() &&
265  (enc_type == kENCODING_NONE || enc_type == kENCODING_GEOINT)) {
266  CHECK_EQ(literal_loads.size(), 2u);
267 
268  llvm::Value* var_start_address = literal_loads[0];
269  llvm::Value* var_length = literal_loads[1];
270 
271  llvm::PointerType* placeholder0_type =
272  llvm::PointerType::get(var_start_address->getType(), 0);
273  auto* int_to_ptr0 =
274  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder0_type);
275  auto placeholder0 = cgen_state_->ir_builder_.CreateLoad(
276  int_to_ptr0->getType()->getPointerElementType(),
277  int_to_ptr0,
278  "__placeholder__" + literal_name + "_start_address");
279  llvm::PointerType* placeholder1_type =
280  llvm::PointerType::get(var_length->getType(), 0);
281  auto* int_to_ptr1 =
282  cgen_state_->ir_builder_.CreateIntToPtr(cgen_state_->llInt(0), placeholder1_type);
283  auto placeholder1 = cgen_state_->ir_builder_.CreateLoad(
284  int_to_ptr1->getType()->getPointerElementType(),
285  int_to_ptr1,
286  "__placeholder__" + literal_name + "_length");
287 
288  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
289  cgen_state_->row_func_hoisted_literals_[placeholder1] = {lit_off, 1};
290 
291  return {placeholder0, placeholder1};
292  }
293 
294  CHECK_EQ(literal_loads.size(), 1u);
295  llvm::Value* to_return_lv = literal_loads[0];
296 
297  auto* int_to_ptr = cgen_state_->ir_builder_.CreateIntToPtr(
298  cgen_state_->llInt(0), llvm::PointerType::get(to_return_lv->getType(), 0));
299  auto placeholder0 =
300  cgen_state_->ir_builder_.CreateLoad(int_to_ptr->getType()->getPointerElementType(),
301  int_to_ptr,
302  "__placeholder__" + literal_name);
303 
304  cgen_state_->row_func_hoisted_literals_[placeholder0] = {lit_off, 0};
305 
306  return {placeholder0};
307 }
308 
309 std::vector<llvm::Value*> CodeGenerator::codegenHoistedConstants(
310  const std::vector<const Analyzer::Constant*>& constants,
311  const EncodingType enc_type,
312  const int dict_id) {
314  CHECK(!constants.empty());
315  const auto& type_info = constants.front()->get_type_info();
316  checked_int16_t checked_lit_off{0};
317  int16_t lit_off{-1};
318  try {
319  for (size_t device_id = 0; device_id < constants.size(); ++device_id) {
320  const auto constant = constants[device_id];
321  const auto& crt_type_info = constant->get_type_info();
322  CHECK(type_info == crt_type_info);
323  checked_lit_off =
324  cgen_state_->getOrAddLiteral(constant, enc_type, dict_id, device_id);
325  if (device_id) {
326  CHECK_EQ(lit_off, checked_lit_off);
327  } else {
328  lit_off = (int16_t)checked_lit_off;
329  }
330  }
331  } catch (const std::range_error& e) {
332  // detect literal buffer overflow when trying to
333  // assign literal buf offset which is not in a valid range
334  // to checked_type variable
335  throw TooManyLiterals();
336  }
337  std::vector<llvm::Value*> hoisted_literal_loads;
338  auto entry = cgen_state_->query_func_literal_loads_.find(lit_off);
339 
340  if (entry == cgen_state_->query_func_literal_loads_.end()) {
341  hoisted_literal_loads =
342  codegenHoistedConstantsLoads(type_info, enc_type, dict_id, lit_off);
343  cgen_state_->query_func_literal_loads_[lit_off] = hoisted_literal_loads;
344  } else {
345  hoisted_literal_loads = entry->second;
346  }
347 
348  std::vector<llvm::Value*> literal_placeholders = codegenHoistedConstantsPlaceholders(
349  type_info, enc_type, lit_off, hoisted_literal_loads);
350  return literal_placeholders;
351 }
int8_t tinyintval
Definition: sqltypes.h:212
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:219
Definition: sqltypes.h:49
CgenState * cgen_state_
llvm::Value * addStringConstant(const std::string &str)
Definition: CgenState.h:186
llvm::Function * query_func_
Definition: CgenState.h:375
std::unordered_map< llvm::Value *, HoistedLiteralLoadLocator > row_func_hoisted_literals_
Definition: CgenState.h:383
llvm::IRBuilder ir_builder_
Definition: CgenState.h:354
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 15, 15, boost::multiprecision::signed_magnitude, boost::multiprecision::checked, void >> checked_int16_t
int8_t boolval
Definition: sqltypes.h:211
bool get_is_null() const
Definition: Analyzer.h:333
#define UNREACHABLE()
Definition: Logger.h:255
std::unordered_map< int, std::vector< llvm::Value * > > query_func_literal_loads_
Definition: CgenState.h:377
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
int32_t intval
Definition: sqltypes.h:214
bool is_time() const
Definition: sqltypes.h:525
std::string to_string(char const *&&v)
static size_t literalBytes(const CgenState::LiteralValue &lit)
Definition: CgenState.h:385
float floatval
Definition: sqltypes.h:216
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
EncodingType
Definition: sqltypes.h:233
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:352
size_t getOrAddLiteral(const Analyzer::Constant *constant, const EncodingType enc_type, const int dict_id, const int device_id)
Definition: CgenState.h:45
llvm::Value * get_arg_by_name(llvm::Function *func, const std::string &name)
Definition: Execute.h:163
std::vector< llvm::Value * > codegenHoistedConstants(const std::vector< const Analyzer::Constant * > &constants, const EncodingType enc_type, const int dict_id)
Definition: ConstantIR.cpp:309
bool is_integer() const
Definition: sqltypes.h:521
std::vector< llvm::Value * > codegenHoistedConstantsLoads(const SQLTypeInfo &type_info, const EncodingType enc_type, const int dict_id, const int16_t lit_off)
Definition: ConstantIR.cpp:119
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:64
int64_t bigintval
Definition: sqltypes.h:215
std::vector< llvm::Value * > codegenHoistedConstantsPlaceholders(const SQLTypeInfo &type_info, const EncodingType enc_type, const int16_t lit_off, const std::vector< llvm::Value * > &literal_loads)
Definition: ConstantIR.cpp:216
bool is_timeinterval() const
Definition: sqltypes.h:530
int16_t smallintval
Definition: sqltypes.h:213
bool is_boolean() const
Definition: sqltypes.h:526
llvm::IRBuilder query_func_entry_ir_builder_
Definition: CgenState.h:376
#define AUTOMATIC_IR_METADATA(CGENSTATE)
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
std::string * stringval
Definition: sqltypes.h:220
SQLTypes decimal_to_int_type(const SQLTypeInfo &ti)
Definition: Datum.cpp:493
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqltypes.h:52
Definition: sqltypes.h:53
static llvm::ConstantInt * codegenIntConst(const Analyzer::Constant *constant, CgenState *cgen_state)
Definition: ConstantIR.cpp:89
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:337
Datum get_constval() const
Definition: Analyzer.h:334
Definition: sqltypes.h:41
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:289
#define CHECK(condition)
Definition: Logger.h:211
bool is_geometry() const
Definition: sqltypes.h:531
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
std::vector< llvm::Value * > codegenGeoConstant(const Analyzer::GeoConstant *, const CompilationOptions &)
Definition: GeoIR.cpp:110
Definition: sqltypes.h:45
bool is_string() const
Definition: sqltypes.h:519
bool is_decimal() const
Definition: sqltypes.h:522
bool is_array() const
Definition: sqltypes.h:527
double doubleval
Definition: sqltypes.h:217
Executor * executor() const