OmniSciDB  cde582ebc3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CastIR.cpp
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 #include "CodeGenerator.h"
18 #include "Execute.h"
20 
21 llvm::Value* CodeGenerator::codegenCast(const Analyzer::UOper* uoper,
22  const CompilationOptions& co) {
24  CHECK_EQ(uoper->get_optype(), kCAST);
25  const auto& ti = uoper->get_type_info();
26  const auto operand = uoper->get_operand();
27  const auto operand_as_const = dynamic_cast<const Analyzer::Constant*>(operand);
28  // For dictionary encoded constants, the cast holds the dictionary id
29  // information as the compression parameter; handle this case separately.
30  llvm::Value* operand_lv{nullptr};
31  if (operand_as_const) {
32  const auto operand_lvs =
33  codegen(operand_as_const, ti.get_compression(), ti.get_comp_param(), co);
34  if (operand_lvs.size() == 3) {
35  operand_lv = cgen_state_->emitCall("string_pack", {operand_lvs[1], operand_lvs[2]});
36  } else {
37  operand_lv = operand_lvs.front();
38  }
39  } else {
40  operand_lv = codegen(operand, true, co).front();
41  }
42 
43  // If the operand is a TextEncodingNone struct ({i8*, i64, i8})
44  // unpack it into an int64_t using "string_pack" so that codegenCast
45  // can properly cast it to a TextEncodingDict
46  if (operand_lv->getType()->isPointerTy() &&
47  operand_lv->getType()->getPointerElementType()->isStructTy()) {
48  auto _struct = cgen_state_->ir_builder_.CreateLoad(
49  operand_lv->getType()->getPointerElementType(), operand_lv);
50  auto ptr = cgen_state_->ir_builder_.CreateExtractValue(_struct, {0});
51  auto len = cgen_state_->ir_builder_.CreateTrunc(
52  cgen_state_->ir_builder_.CreateExtractValue(_struct, {1}),
54  operand_lv = cgen_state_->emitCall("string_pack", {ptr, len});
55  }
56  const auto& operand_ti = operand->get_type_info();
57  return codegenCast(operand_lv, operand_ti, ti, operand_as_const, co);
58 }
59 
60 namespace {
61 
62 bool byte_array_cast(const SQLTypeInfo& operand_ti, const SQLTypeInfo& ti) {
63  return (operand_ti.is_array() && ti.is_array() && ti.get_subtype() == kTINYINT &&
64  operand_ti.get_size() > 0 && operand_ti.get_size() == ti.get_size());
65 }
66 
67 } // namespace
68 
69 llvm::Value* CodeGenerator::codegenCast(llvm::Value* operand_lv,
70  const SQLTypeInfo& operand_ti,
71  const SQLTypeInfo& ti,
72  const bool operand_is_const,
73  const CompilationOptions& co) {
75  if (byte_array_cast(operand_ti, ti)) {
76  auto* byte_array_type = get_int_array_type(8, ti.get_size(), cgen_state_->context_);
77  return cgen_state_->ir_builder_.CreatePointerCast(operand_lv,
78  byte_array_type->getPointerTo());
79  }
80  if (operand_lv->getType()->isIntegerTy()) {
81  if (operand_ti.is_string()) {
82  return codegenCastFromString(operand_lv, operand_ti, ti, operand_is_const, co);
83  }
84  CHECK(operand_ti.is_integer() || operand_ti.is_decimal() || operand_ti.is_time() ||
85  operand_ti.is_boolean());
86  if (operand_ti.is_boolean()) {
87  // cast boolean to int8
88  CHECK(operand_lv->getType()->isIntegerTy(1) ||
89  operand_lv->getType()->isIntegerTy(8));
90  if (operand_lv->getType()->isIntegerTy(1)) {
91  operand_lv = cgen_state_->castToTypeIn(operand_lv, 8);
92  }
93  if (ti.is_boolean()) {
94  return operand_lv;
95  }
96  }
97  if (operand_ti.is_integer() && operand_lv->getType()->isIntegerTy(8) &&
98  ti.is_boolean()) {
99  // cast int8 to boolean
100  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
101  }
102  if (operand_ti.get_type() == kTIMESTAMP && ti.get_type() == kDATE) {
103  // Maybe we should instead generate DatetruncExpr directly from RelAlgTranslator
104  // for this pattern. However, DatetruncExpr is supposed to return a timestamp,
105  // whereas this cast returns a date. The underlying type for both is still the same,
106  // but it still doesn't look like a good idea to misuse DatetruncExpr.
107  // Date will have default precision of day, but TIMESTAMP dimension would
108  // matter but while converting date through seconds
110  operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
111  }
112  if ((operand_ti.get_type() == kTIMESTAMP || operand_ti.get_type() == kDATE) &&
113  ti.get_type() == kTIMESTAMP) {
114  const auto operand_dimen =
115  (operand_ti.is_timestamp()) ? operand_ti.get_dimension() : 0;
116  if (operand_dimen != ti.get_dimension()) {
118  operand_lv, operand_ti, ti, !ti.get_notnull());
119  }
120  }
121  if (ti.is_integer() || ti.is_decimal() || ti.is_time()) {
122  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
123  } else {
124  return codegenCastToFp(operand_lv, operand_ti, ti);
125  }
126  } else {
127  return codegenCastFromFp(operand_lv, operand_ti, ti);
128  }
129  CHECK(false);
130  return nullptr;
131 }
132 
133 llvm::Value* CodeGenerator::codegenCastTimestampToDate(llvm::Value* ts_lv,
134  const int dimen,
135  const bool nullable) {
137  CHECK(ts_lv->getType()->isIntegerTy(64));
138  if (dimen > 0) {
139  if (nullable) {
141  "DateTruncateHighPrecisionToDateNullable",
143  {{ts_lv,
146  }
147  return cgen_state_->emitExternalCall(
148  "DateTruncateHighPrecisionToDate",
149  get_int_type(64, cgen_state_->context_),
150  {{ts_lv,
151  cgen_state_->llInt(DateTimeUtils::get_timestamp_precision_scale(dimen))}});
152  }
153  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
154  if (nullable) {
155  nullcheck_codegen =
156  std::make_unique<NullCheckCodegen>(cgen_state_,
157  executor(),
158  ts_lv,
159  SQLTypeInfo(kTIMESTAMP, dimen, 0, !nullable),
160  "cast_timestamp_nullcheck");
161  }
162  auto ret = cgen_state_->emitExternalCall(
163  "datetrunc_day", get_int_type(64, cgen_state_->context_), {ts_lv});
164  if (nullcheck_codegen) {
165  ret = nullcheck_codegen->finalize(ll_int(NULL_BIGINT, cgen_state_->context_), ret);
166  }
167  return ret;
168 }
169 
170 llvm::Value* CodeGenerator::codegenCastBetweenTimestamps(llvm::Value* ts_lv,
171  const SQLTypeInfo& operand_ti,
172  const SQLTypeInfo& target_ti,
173  const bool nullable) {
175  const auto operand_dimen = operand_ti.get_dimension();
176  const auto target_dimen = target_ti.get_dimension();
177  if (operand_dimen == target_dimen) {
178  return ts_lv;
179  }
180  CHECK(ts_lv->getType()->isIntegerTy(64));
181  const auto scale =
182  DateTimeUtils::get_timestamp_precision_scale(abs(operand_dimen - target_dimen));
183  if (operand_dimen < target_dimen) {
184  codegenCastBetweenIntTypesOverflowChecks(ts_lv, operand_ti, target_ti, scale);
185  return nullable
186  ? cgen_state_->emitCall("mul_int64_t_nullable_lhs",
187  {ts_lv,
188  cgen_state_->llInt(static_cast<int64_t>(scale)),
189  cgen_state_->inlineIntNull(operand_ti)})
190  : cgen_state_->ir_builder_.CreateMul(
191  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
192  }
193  return nullable
194  ? cgen_state_->emitCall("floor_div_nullable_lhs",
195  {ts_lv,
196  cgen_state_->llInt(static_cast<int64_t>(scale)),
197  cgen_state_->inlineIntNull(operand_ti)})
198  : cgen_state_->ir_builder_.CreateSDiv(
199  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
200 }
201 
202 llvm::Value* CodeGenerator::codegenCastFromString(llvm::Value* operand_lv,
203  const SQLTypeInfo& operand_ti,
204  const SQLTypeInfo& ti,
205  const bool operand_is_const,
206  const CompilationOptions& co) {
208  if (!ti.is_string()) {
209  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
210  ti.get_type_name() + " not supported");
211  }
212  if (operand_ti.get_compression() == kENCODING_NONE &&
214  return operand_lv;
215  }
216  if (ti.get_compression() == kENCODING_DICT &&
217  operand_ti.get_compression() == kENCODING_DICT) {
218  if (ti.get_comp_param() == operand_ti.get_comp_param()) {
219  return operand_lv;
220  }
221  if (operand_ti.get_comp_param() == DictRef::literalsDictId) {
222  // Anything being casted from a literal dictionary is not materialized at this point
223  // Should already have been kicked to CPU if it was originally a GPU query
224 
226  const int64_t source_string_proxy_handle =
227  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
228  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
229 
230  const int64_t dest_string_proxy_handle =
231  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
232  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
233 
234  auto source_string_proxy_handle_lv = cgen_state_->llInt(source_string_proxy_handle);
235  auto dest_string_proxy_handle_lv = cgen_state_->llInt(dest_string_proxy_handle);
236 
237  std::vector<llvm::Value*> string_cast_lvs{
238  operand_lv, source_string_proxy_handle_lv, dest_string_proxy_handle_lv};
239  if (ti.is_dict_intersection()) {
241  "intersect_translate_string_id_to_other_dict",
243  string_cast_lvs);
244  } else {
245  return cgen_state_->emitExternalCall("union_translate_string_id_to_other_dict",
247  string_cast_lvs);
248  }
249  }
250 
251  const std::vector<StringOps_Namespace::StringOpInfo> string_op_infos;
252  auto string_dictionary_translation_mgr =
253  std::make_unique<StringDictionaryTranslationMgr>(
254  operand_ti.get_comp_param(),
255  ti.get_comp_param(),
257  string_op_infos,
260  executor()->deviceCount(co.device_type),
261  executor(),
262  &executor()->getCatalog()->getDataMgr(),
263  false /* delay_translation */);
264 
265  return cgen_state_
266  ->moveStringDictionaryTranslationMgr(std::move(string_dictionary_translation_mgr))
267  ->codegen(operand_lv, operand_ti, true /* add_nullcheck */, co);
268  }
269  // dictionary encode non-constant
270  if (operand_ti.get_compression() != kENCODING_DICT && !operand_is_const) {
271  if (g_cluster) {
272  throw std::runtime_error(
273  "Cast from none-encoded string to dictionary-encoded not supported for "
274  "distributed queries");
275  }
276  CHECK_EQ(kENCODING_NONE, operand_ti.get_compression());
278  CHECK(operand_lv->getType()->isIntegerTy(64));
280  throw QueryMustRunOnCpu();
281  }
283  "string_compress",
285  {operand_lv,
286  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
287  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
288  }
289  CHECK(operand_lv->getType()->isIntegerTy(32));
290  if (ti.get_compression() == kENCODING_NONE) {
291  if (g_cluster) {
292  throw std::runtime_error(
293  "Cast from dictionary-encoded string to none-encoded not "
294  "currently supported for distributed queries.");
295  }
296  // Removed watchdog check here in exchange for row cardinality based check in
297  // RelAlgExecutor
298  CHECK_EQ(kENCODING_DICT, operand_ti.get_compression());
300  throw QueryMustRunOnCpu();
301  }
302  const int64_t string_dictionary_ptr =
303  operand_ti.get_comp_param() == 0
304  ? reinterpret_cast<int64_t>(
305  executor()->getRowSetMemoryOwner()->getLiteralStringDictProxy())
306  : reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
307  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
309  "string_decompress",
311  {operand_lv, cgen_state_->llInt(string_dictionary_ptr)});
312  }
313  CHECK(operand_is_const);
314  CHECK_EQ(kENCODING_DICT, ti.get_compression());
315  return operand_lv;
316 }
317 
318 llvm::Value* CodeGenerator::codegenCastBetweenIntTypes(llvm::Value* operand_lv,
319  const SQLTypeInfo& operand_ti,
320  const SQLTypeInfo& ti,
321  bool upscale) {
323  if (ti.is_decimal() &&
324  (!operand_ti.is_decimal() || operand_ti.get_scale() <= ti.get_scale())) {
325  if (upscale) {
326  if (operand_ti.get_scale() < ti.get_scale()) { // scale only if needed
327  auto scale = exp_to_scale(ti.get_scale() - operand_ti.get_scale());
328  const auto scale_lv =
329  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
330  operand_lv = cgen_state_->ir_builder_.CreateSExt(
331  operand_lv, get_int_type(64, cgen_state_->context_));
332 
333  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, scale);
334 
335  if (operand_ti.get_notnull()) {
336  operand_lv = cgen_state_->ir_builder_.CreateMul(operand_lv, scale_lv);
337  } else {
338  operand_lv = cgen_state_->emitCall(
339  "scale_decimal_up",
340  {operand_lv,
341  scale_lv,
342  cgen_state_->llInt(inline_int_null_val(operand_ti)),
344  }
345  }
346  }
347  } else if (operand_ti.is_decimal()) {
348  // rounded scale down
349  auto scale = (int64_t)exp_to_scale(operand_ti.get_scale() - ti.get_scale());
350  const auto scale_lv =
351  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
352 
353  const auto operand_width =
354  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
355 
356  std::string method_name = "scale_decimal_down_nullable";
357  if (operand_ti.get_notnull()) {
358  method_name = "scale_decimal_down_not_nullable";
359  }
360 
361  CHECK(operand_width == 64);
362  operand_lv = cgen_state_->emitCall(
363  method_name,
364  {operand_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(operand_ti))});
365  }
366  if (ti.is_integer() && operand_ti.is_integer() &&
367  operand_ti.get_logical_size() > ti.get_logical_size()) {
368  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, 1);
369  }
370 
371  const auto operand_width =
372  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
373  const auto target_width = get_bit_width(ti);
374  if (target_width == operand_width) {
375  return operand_lv;
376  }
377  if (operand_ti.get_notnull()) {
378  return cgen_state_->ir_builder_.CreateCast(
379  target_width > operand_width ? llvm::Instruction::CastOps::SExt
380  : llvm::Instruction::CastOps::Trunc,
381  operand_lv,
382  get_int_type(target_width, cgen_state_->context_));
383  }
384  return cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
385  numeric_type_name(ti) + "_nullable",
386  {operand_lv,
387  cgen_state_->inlineIntNull(operand_ti),
388  cgen_state_->inlineIntNull(ti)});
389 }
390 
392  llvm::Value* operand_lv,
393  const SQLTypeInfo& operand_ti,
394  const SQLTypeInfo& ti,
395  const int64_t scale) {
397  llvm::Value* chosen_max{nullptr};
398  llvm::Value* chosen_min{nullptr};
399  std::tie(chosen_max, chosen_min) =
401 
403  auto cast_ok = llvm::BasicBlock::Create(
405  auto cast_fail = llvm::BasicBlock::Create(
407  auto operand_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() / scale;
408  auto operand_min = static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue() / scale;
409  const auto ti_llvm_type =
411  llvm::Value* operand_max_lv = llvm::ConstantInt::get(ti_llvm_type, operand_max);
412  llvm::Value* operand_min_lv = llvm::ConstantInt::get(ti_llvm_type, operand_min);
413  const bool is_narrowing = operand_ti.get_logical_size() > ti.get_logical_size();
414  if (is_narrowing) {
415  const auto operand_ti_llvm_type =
417  operand_max_lv =
418  cgen_state_->ir_builder_.CreateSExt(operand_max_lv, operand_ti_llvm_type);
419  operand_min_lv =
420  cgen_state_->ir_builder_.CreateSExt(operand_min_lv, operand_ti_llvm_type);
421  }
422  llvm::Value* over{nullptr};
423  llvm::Value* under{nullptr};
424  if (operand_ti.get_notnull()) {
425  over = cgen_state_->ir_builder_.CreateICmpSGT(operand_lv, operand_max_lv);
426  under = cgen_state_->ir_builder_.CreateICmpSLE(operand_lv, operand_min_lv);
427  } else {
428  const auto type_name =
429  is_narrowing ? numeric_type_name(operand_ti) : numeric_type_name(ti);
430  const auto null_operand_val = cgen_state_->llInt(inline_int_null_val(operand_ti));
431  const auto null_bool_val = cgen_state_->inlineIntNull(SQLTypeInfo(kBOOLEAN, false));
432  over = toBool(cgen_state_->emitCall(
433  "gt_" + type_name + "_nullable_lhs",
434  {operand_lv, operand_max_lv, null_operand_val, null_bool_val}));
435  under = toBool(cgen_state_->emitCall(
436  "le_" + type_name + "_nullable_lhs",
437  {operand_lv, operand_min_lv, null_operand_val, null_bool_val}));
438  }
439  const auto detected = cgen_state_->ir_builder_.CreateOr(over, under, "overflow");
440  cgen_state_->ir_builder_.CreateCondBr(detected, cast_fail, cast_ok);
441 
442  cgen_state_->ir_builder_.SetInsertPoint(cast_fail);
443  cgen_state_->ir_builder_.CreateRet(
444  cgen_state_->llInt(Executor::ERR_OVERFLOW_OR_UNDERFLOW));
445 
446  cgen_state_->ir_builder_.SetInsertPoint(cast_ok);
447 }
448 
449 llvm::Value* CodeGenerator::codegenCastToFp(llvm::Value* operand_lv,
450  const SQLTypeInfo& operand_ti,
451  const SQLTypeInfo& ti) {
453  if (!ti.is_fp()) {
454  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
455  ti.get_type_name() + " not supported");
456  }
457  llvm::Value* result_lv;
458  if (operand_ti.get_notnull()) {
459  auto const fp_type = ti.get_type() == kFLOAT
460  ? llvm::Type::getFloatTy(cgen_state_->context_)
461  : llvm::Type::getDoubleTy(cgen_state_->context_);
462  result_lv = cgen_state_->ir_builder_.CreateSIToFP(operand_lv, fp_type);
463  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
464  double const multiplier = shared::power10inv(scale);
465  result_lv = cgen_state_->ir_builder_.CreateFMul(
466  result_lv, llvm::ConstantFP::get(result_lv->getType(), multiplier));
467  }
468  } else {
469  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
470  double const multiplier = shared::power10inv(scale);
471  auto const fp_type = ti.get_type() == kFLOAT
472  ? llvm::Type::getFloatTy(cgen_state_->context_)
473  : llvm::Type::getDoubleTy(cgen_state_->context_);
474  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
475  numeric_type_name(ti) + "_scaled_nullable",
476  {operand_lv,
477  cgen_state_->inlineIntNull(operand_ti),
479  llvm::ConstantFP::get(fp_type, multiplier)});
480  } else {
481  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
482  numeric_type_name(ti) + "_nullable",
483  {operand_lv,
484  cgen_state_->inlineIntNull(operand_ti),
485  cgen_state_->inlineFpNull(ti)});
486  }
487  }
488  CHECK(result_lv);
489  return result_lv;
490 }
491 
492 llvm::Value* CodeGenerator::codegenCastFromFp(llvm::Value* operand_lv,
493  const SQLTypeInfo& operand_ti,
494  const SQLTypeInfo& ti) {
496  if (!operand_ti.is_fp() || !ti.is_number() || ti.is_decimal()) {
497  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
498  ti.get_type_name() + " not supported");
499  }
500  if (operand_ti.get_type() == ti.get_type()) {
501  // Should not have been called when both dimensions are same.
502  return operand_lv;
503  }
504  CHECK(operand_lv->getType()->isFloatTy() || operand_lv->getType()->isDoubleTy());
505  if (operand_ti.get_notnull()) {
506  if (ti.get_type() == kDOUBLE) {
507  return cgen_state_->ir_builder_.CreateFPExt(
508  operand_lv, llvm::Type::getDoubleTy(cgen_state_->context_));
509  } else if (ti.get_type() == kFLOAT) {
510  return cgen_state_->ir_builder_.CreateFPTrunc(
511  operand_lv, llvm::Type::getFloatTy(cgen_state_->context_));
512  } else if (ti.is_integer()) {
513  // Round by adding/subtracting 0.5 before fptosi.
514  auto* fp_type = operand_lv->getType()->isFloatTy()
515  ? llvm::Type::getFloatTy(cgen_state_->context_)
516  : llvm::Type::getDoubleTy(cgen_state_->context_);
517  auto* zero = llvm::ConstantFP::get(fp_type, 0.0);
518  auto* mhalf = llvm::ConstantFP::get(fp_type, -0.5);
519  auto* phalf = llvm::ConstantFP::get(fp_type, 0.5);
520  auto* is_negative = cgen_state_->ir_builder_.CreateFCmpOLT(operand_lv, zero);
521  auto* offset = cgen_state_->ir_builder_.CreateSelect(is_negative, mhalf, phalf);
522  operand_lv = cgen_state_->ir_builder_.CreateFAdd(operand_lv, offset);
523  return cgen_state_->ir_builder_.CreateFPToSI(
524  operand_lv, get_int_type(get_bit_width(ti), cgen_state_->context_));
525  } else {
526  CHECK(false);
527  }
528  } else {
529  const auto from_tname = numeric_type_name(operand_ti);
530  const auto to_tname = numeric_type_name(ti);
531  if (ti.is_fp()) {
532  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
533  {operand_lv,
534  cgen_state_->inlineFpNull(operand_ti),
535  cgen_state_->inlineFpNull(ti)});
536  } else if (ti.is_integer()) {
537  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
538  {operand_lv,
539  cgen_state_->inlineFpNull(operand_ti),
540  cgen_state_->inlineIntNull(ti)});
541  } else {
542  CHECK(false);
543  }
544  }
545  CHECK(false);
546  return nullptr;
547 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:330
#define CHECK_EQ(x, y)
Definition: Logger.h:230
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:148
llvm::Value * codegenCastFromFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:492
HOST DEVICE int get_size() const
Definition: sqltypes.h:339
bool is_timestamp() const
Definition: sqltypes.h:895
CgenState * cgen_state_
#define NULL_BIGINT
bool is_fp() const
Definition: sqltypes.h:514
HOST DEVICE int get_scale() const
Definition: sqltypes.h:334
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value * > args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={}, const bool has_struct_return=false)
Definition: CgenState.h:217
llvm::ConstantInt * ll_int(const T v, llvm::LLVMContext &context)
llvm::IRBuilder ir_builder_
Definition: CgenState.h:361
llvm::Value * codegenCastToFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:449
Definition: sqldefs.h:48
bool byte_array_cast(const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:62
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool is_number() const
Definition: sqltypes.h:515
bool is_time() const
Definition: sqltypes.h:516
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:359
llvm::Function * current_func_
Definition: CgenState.h:353
int get_logical_size() const
Definition: sqltypes.h:349
bool is_integer() const
Definition: sqltypes.h:512
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:64
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1344
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:318
bool is_dict_intersection() const
Definition: sqltypes.h:565
bool needs_error_check_
Definition: CgenState.h:381
bool is_boolean() const
Definition: sqltypes.h:517
llvm::Value * codegenCastTimestampToDate(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:133
#define AUTOMATIC_IR_METADATA(CGENSTATE)
double power10inv(unsigned const x)
Definition: misc.h:276
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:81
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:215
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqltypes.h:53
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:337
const Expr * get_operand() const
Definition: Analyzer.h:378
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:391
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:331
std::string get_type_name() const
Definition: sqltypes.h:443
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:343
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:338
llvm::Value * codegenCastBetweenTimestamps(llvm::Value *ts_lv, const SQLTypeInfo &operand_dimen, const SQLTypeInfo &target_dimen, const bool nullable)
Definition: CastIR.cpp:170
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:296
#define CHECK(condition)
Definition: Logger.h:222
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:51
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool g_cluster
llvm::Value * codegenCastFromString(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const bool operand_is_const, const CompilationOptions &co)
Definition: CastIR.cpp:202
const StringDictionaryTranslationMgr * moveStringDictionaryTranslationMgr(std::unique_ptr< const StringDictionaryTranslationMgr > &&str_dict_translation_mgr)
Definition: CgenState.h:196
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:21
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:209
bool is_string() const
Definition: sqltypes.h:510
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:336
llvm::Value * codegen(llvm::Value *str_id_input, const SQLTypeInfo &input_ti, const bool add_nullcheck, const CompilationOptions &co) const
constexpr auto type_name() noexcept
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
bool is_decimal() const
Definition: sqltypes.h:513
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:119
SQLOps get_optype() const
Definition: Analyzer.h:377
bool is_array() const
Definition: sqltypes.h:518
static constexpr int32_t literalsDictId
Definition: DictRef.h:15
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:102
Executor * executor() const