OmniSciDB  ca0c39ec8f
 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 && ti.get_type() == kTIME) {
114  operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
115  }
116  if ((operand_ti.get_type() == kTIMESTAMP || operand_ti.get_type() == kDATE) &&
117  ti.get_type() == kTIMESTAMP) {
118  const auto operand_dimen =
119  (operand_ti.is_timestamp()) ? operand_ti.get_dimension() : 0;
120  if (operand_dimen != ti.get_dimension()) {
122  operand_lv, operand_ti, ti, !ti.get_notnull());
123  }
124  }
125  if (ti.is_integer() || ti.is_decimal() || ti.is_time()) {
126  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
127  } else {
128  return codegenCastToFp(operand_lv, operand_ti, ti);
129  }
130  } else {
131  return codegenCastFromFp(operand_lv, operand_ti, ti);
132  }
133  CHECK(false);
134  return nullptr;
135 }
136 
137 llvm::Value* CodeGenerator::codegenCastTimestampToTime(llvm::Value* ts_lv,
138  const int dimen,
139  const bool nullable) {
140  std::vector<llvm::Value*> datetrunc_args{ts_lv};
141  std::string hptodate_fname;
142  if (dimen > 0) {
143  hptodate_fname = "ExtractTimeFromHPTimestamp";
144  datetrunc_args.push_back(
146  } else {
147  hptodate_fname = "ExtractTimeFromLPTimestamp";
148  }
149  if (nullable) {
150  datetrunc_args.push_back(cgen_state_->inlineIntNull(SQLTypeInfo(kBIGINT, false)));
151  hptodate_fname += "Nullable";
152  }
154  hptodate_fname, get_int_type(64, cgen_state_->context_), datetrunc_args);
155 }
156 
157 llvm::Value* CodeGenerator::codegenCastTimestampToDate(llvm::Value* ts_lv,
158  const int dimen,
159  const bool nullable) {
161  CHECK(ts_lv->getType()->isIntegerTy(64));
162  if (dimen > 0) {
163  if (nullable) {
165  "DateTruncateHighPrecisionToDateNullable",
167  {{ts_lv,
170  }
171  return cgen_state_->emitExternalCall(
172  "DateTruncateHighPrecisionToDate",
173  get_int_type(64, cgen_state_->context_),
174  {{ts_lv,
175  cgen_state_->llInt(DateTimeUtils::get_timestamp_precision_scale(dimen))}});
176  }
177  std::unique_ptr<CodeGenerator::NullCheckCodegen> nullcheck_codegen;
178  if (nullable) {
179  nullcheck_codegen =
180  std::make_unique<NullCheckCodegen>(cgen_state_,
181  executor(),
182  ts_lv,
183  SQLTypeInfo(kTIMESTAMP, dimen, 0, !nullable),
184  "cast_timestamp_nullcheck");
185  }
186  auto ret = cgen_state_->emitExternalCall(
187  "datetrunc_day", get_int_type(64, cgen_state_->context_), {ts_lv});
188  if (nullcheck_codegen) {
189  ret = nullcheck_codegen->finalize(ll_int(NULL_BIGINT, cgen_state_->context_), ret);
190  }
191  return ret;
192 }
193 
194 llvm::Value* CodeGenerator::codegenCastBetweenTimestamps(llvm::Value* ts_lv,
195  const SQLTypeInfo& operand_ti,
196  const SQLTypeInfo& target_ti,
197  const bool nullable) {
199  const auto operand_dimen = operand_ti.get_dimension();
200  const auto target_dimen = target_ti.get_dimension();
201  if (operand_dimen == target_dimen) {
202  return ts_lv;
203  }
204  CHECK(ts_lv->getType()->isIntegerTy(64));
205  const auto scale =
206  DateTimeUtils::get_timestamp_precision_scale(abs(operand_dimen - target_dimen));
207  if (operand_dimen < target_dimen) {
208  codegenCastBetweenIntTypesOverflowChecks(ts_lv, operand_ti, target_ti, scale);
209  return nullable
210  ? cgen_state_->emitCall("mul_int64_t_nullable_lhs",
211  {ts_lv,
212  cgen_state_->llInt(static_cast<int64_t>(scale)),
213  cgen_state_->inlineIntNull(operand_ti)})
214  : cgen_state_->ir_builder_.CreateMul(
215  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
216  }
217  return nullable
218  ? cgen_state_->emitCall("floor_div_nullable_lhs",
219  {ts_lv,
220  cgen_state_->llInt(static_cast<int64_t>(scale)),
221  cgen_state_->inlineIntNull(operand_ti)})
222  : cgen_state_->ir_builder_.CreateSDiv(
223  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
224 }
225 
226 llvm::Value* CodeGenerator::codegenCastFromString(llvm::Value* operand_lv,
227  const SQLTypeInfo& operand_ti,
228  const SQLTypeInfo& ti,
229  const bool operand_is_const,
230  const CompilationOptions& co) {
232  if (!ti.is_string()) {
233  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
234  ti.get_type_name() + " not supported");
235  }
236  if (operand_ti.get_compression() == kENCODING_NONE &&
238  return operand_lv;
239  }
240  if (ti.get_compression() == kENCODING_DICT &&
241  operand_ti.get_compression() == kENCODING_DICT) {
242  if (ti.get_comp_param() == operand_ti.get_comp_param()) {
243  return operand_lv;
244  }
245  if (operand_ti.get_comp_param() == DictRef::literalsDictId) {
246  // Anything being casted from a literal dictionary is not materialized at this point
247  // Should already have been kicked to CPU if it was originally a GPU query
248 
250  const int64_t source_string_proxy_handle =
251  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
252  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
253 
254  const int64_t dest_string_proxy_handle =
255  reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
256  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
257 
258  auto source_string_proxy_handle_lv = cgen_state_->llInt(source_string_proxy_handle);
259  auto dest_string_proxy_handle_lv = cgen_state_->llInt(dest_string_proxy_handle);
260 
261  std::vector<llvm::Value*> string_cast_lvs{
262  operand_lv, source_string_proxy_handle_lv, dest_string_proxy_handle_lv};
263  if (ti.is_dict_intersection()) {
265  "intersect_translate_string_id_to_other_dict",
267  string_cast_lvs);
268  } else {
269  return cgen_state_->emitExternalCall("union_translate_string_id_to_other_dict",
271  string_cast_lvs);
272  }
273  }
274 
275  const std::vector<StringOps_Namespace::StringOpInfo> string_op_infos;
276  auto string_dictionary_translation_mgr =
277  std::make_unique<StringDictionaryTranslationMgr>(
278  operand_ti.get_comp_param(),
279  ti.get_comp_param(),
281  ti,
282  string_op_infos,
285  executor()->deviceCount(co.device_type),
286  executor(),
287  &executor()->getCatalog()->getDataMgr(),
288  false /* delay_translation */);
289 
290  return cgen_state_
291  ->moveStringDictionaryTranslationMgr(std::move(string_dictionary_translation_mgr))
292  ->codegen(operand_lv, operand_ti, true /* add_nullcheck */, co);
293  }
294  // dictionary encode non-constant
295  if (operand_ti.get_compression() != kENCODING_DICT && !operand_is_const) {
296  if (g_cluster) {
297  throw std::runtime_error(
298  "Cast from none-encoded string to dictionary-encoded not supported for "
299  "distributed queries");
300  }
301  CHECK_EQ(kENCODING_NONE, operand_ti.get_compression());
303  CHECK(operand_lv->getType()->isIntegerTy(64));
305  throw QueryMustRunOnCpu();
306  }
308  "string_compress",
310  {operand_lv,
311  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
312  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
313  }
314  CHECK(operand_lv->getType()->isIntegerTy(32));
315  if (ti.get_compression() == kENCODING_NONE) {
316  if (g_cluster) {
317  throw std::runtime_error(
318  "Cast from dictionary-encoded string to none-encoded not "
319  "currently supported for distributed queries.");
320  }
321  // Removed watchdog check here in exchange for row cardinality based check in
322  // RelAlgExecutor
323  CHECK_EQ(kENCODING_DICT, operand_ti.get_compression());
325  throw QueryMustRunOnCpu();
326  }
327  const int64_t string_dictionary_ptr =
328  operand_ti.get_comp_param() == 0
329  ? reinterpret_cast<int64_t>(
330  executor()->getRowSetMemoryOwner()->getLiteralStringDictProxy())
331  : reinterpret_cast<int64_t>(executor()->getStringDictionaryProxy(
332  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true));
334  "string_decompress",
336  {operand_lv, cgen_state_->llInt(string_dictionary_ptr)});
337  }
338  CHECK(operand_is_const);
339  CHECK_EQ(kENCODING_DICT, ti.get_compression());
340  return operand_lv;
341 }
342 
343 llvm::Value* CodeGenerator::codegenCastBetweenIntTypes(llvm::Value* operand_lv,
344  const SQLTypeInfo& operand_ti,
345  const SQLTypeInfo& ti,
346  bool upscale) {
348  if (ti.is_decimal() &&
349  (!operand_ti.is_decimal() || operand_ti.get_scale() <= ti.get_scale())) {
350  if (upscale) {
351  if (operand_ti.get_scale() < ti.get_scale()) { // scale only if needed
352  auto scale = exp_to_scale(ti.get_scale() - operand_ti.get_scale());
353  const auto scale_lv =
354  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
355  operand_lv = cgen_state_->ir_builder_.CreateSExt(
356  operand_lv, get_int_type(64, cgen_state_->context_));
357 
358  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, scale);
359 
360  if (operand_ti.get_notnull()) {
361  operand_lv = cgen_state_->ir_builder_.CreateMul(operand_lv, scale_lv);
362  } else {
363  operand_lv = cgen_state_->emitCall(
364  "scale_decimal_up",
365  {operand_lv,
366  scale_lv,
367  cgen_state_->llInt(inline_int_null_val(operand_ti)),
369  }
370  }
371  }
372  } else if (operand_ti.is_decimal()) {
373  // rounded scale down
374  auto scale = (int64_t)exp_to_scale(operand_ti.get_scale() - ti.get_scale());
375  const auto scale_lv =
376  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
377 
378  const auto operand_width =
379  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
380 
381  std::string method_name = "scale_decimal_down_nullable";
382  if (operand_ti.get_notnull()) {
383  method_name = "scale_decimal_down_not_nullable";
384  }
385 
386  CHECK(operand_width == 64);
387  operand_lv = cgen_state_->emitCall(
388  method_name,
389  {operand_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(operand_ti))});
390  }
391  if (ti.is_integer() && operand_ti.is_integer() &&
392  operand_ti.get_logical_size() > ti.get_logical_size()) {
393  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, 1);
394  }
395 
396  const auto operand_width =
397  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
398  const auto target_width = get_bit_width(ti);
399  if (target_width == operand_width) {
400  return operand_lv;
401  }
402  if (operand_ti.get_notnull()) {
403  return cgen_state_->ir_builder_.CreateCast(
404  target_width > operand_width ? llvm::Instruction::CastOps::SExt
405  : llvm::Instruction::CastOps::Trunc,
406  operand_lv,
407  get_int_type(target_width, cgen_state_->context_));
408  }
409  return cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
410  numeric_type_name(ti) + "_nullable",
411  {operand_lv,
412  cgen_state_->inlineIntNull(operand_ti),
413  cgen_state_->inlineIntNull(ti)});
414 }
415 
417  llvm::Value* operand_lv,
418  const SQLTypeInfo& operand_ti,
419  const SQLTypeInfo& ti,
420  const int64_t scale) {
422  llvm::Value* chosen_max{nullptr};
423  llvm::Value* chosen_min{nullptr};
424  std::tie(chosen_max, chosen_min) =
426 
428  auto cast_ok = llvm::BasicBlock::Create(
430  auto cast_fail = llvm::BasicBlock::Create(
432  auto operand_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() / scale;
433  auto operand_min = static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue() / scale;
434  const auto ti_llvm_type =
436  llvm::Value* operand_max_lv = llvm::ConstantInt::get(ti_llvm_type, operand_max);
437  llvm::Value* operand_min_lv = llvm::ConstantInt::get(ti_llvm_type, operand_min);
438  const bool is_narrowing = operand_ti.get_logical_size() > ti.get_logical_size();
439  if (is_narrowing) {
440  const auto operand_ti_llvm_type =
442  operand_max_lv =
443  cgen_state_->ir_builder_.CreateSExt(operand_max_lv, operand_ti_llvm_type);
444  operand_min_lv =
445  cgen_state_->ir_builder_.CreateSExt(operand_min_lv, operand_ti_llvm_type);
446  }
447  llvm::Value* over{nullptr};
448  llvm::Value* under{nullptr};
449  if (operand_ti.get_notnull()) {
450  over = cgen_state_->ir_builder_.CreateICmpSGT(operand_lv, operand_max_lv);
451  under = cgen_state_->ir_builder_.CreateICmpSLE(operand_lv, operand_min_lv);
452  } else {
453  const auto type_name =
454  is_narrowing ? numeric_type_name(operand_ti) : numeric_type_name(ti);
455  const auto null_operand_val = cgen_state_->llInt(inline_int_null_val(operand_ti));
456  const auto null_bool_val = cgen_state_->inlineIntNull(SQLTypeInfo(kBOOLEAN, false));
457  over = toBool(cgen_state_->emitCall(
458  "gt_" + type_name + "_nullable_lhs",
459  {operand_lv, operand_max_lv, null_operand_val, null_bool_val}));
460  under = toBool(cgen_state_->emitCall(
461  "le_" + type_name + "_nullable_lhs",
462  {operand_lv, operand_min_lv, null_operand_val, null_bool_val}));
463  }
464  const auto detected = cgen_state_->ir_builder_.CreateOr(over, under, "overflow");
465  cgen_state_->ir_builder_.CreateCondBr(detected, cast_fail, cast_ok);
466 
467  cgen_state_->ir_builder_.SetInsertPoint(cast_fail);
468  cgen_state_->ir_builder_.CreateRet(
469  cgen_state_->llInt(Executor::ERR_OVERFLOW_OR_UNDERFLOW));
470 
471  cgen_state_->ir_builder_.SetInsertPoint(cast_ok);
472 }
473 
474 llvm::Value* CodeGenerator::codegenCastToFp(llvm::Value* operand_lv,
475  const SQLTypeInfo& operand_ti,
476  const SQLTypeInfo& ti) {
478  if (!ti.is_fp()) {
479  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
480  ti.get_type_name() + " not supported");
481  }
482  llvm::Value* result_lv;
483  if (operand_ti.get_notnull()) {
484  auto const fp_type = ti.get_type() == kFLOAT
485  ? llvm::Type::getFloatTy(cgen_state_->context_)
486  : llvm::Type::getDoubleTy(cgen_state_->context_);
487  result_lv = cgen_state_->ir_builder_.CreateSIToFP(operand_lv, fp_type);
488  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
489  double const multiplier = shared::power10inv(scale);
490  result_lv = cgen_state_->ir_builder_.CreateFMul(
491  result_lv, llvm::ConstantFP::get(result_lv->getType(), multiplier));
492  }
493  } else {
494  if (auto const scale = static_cast<unsigned>(operand_ti.get_scale())) {
495  double const multiplier = shared::power10inv(scale);
496  auto const fp_type = ti.get_type() == kFLOAT
497  ? llvm::Type::getFloatTy(cgen_state_->context_)
498  : llvm::Type::getDoubleTy(cgen_state_->context_);
499  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
500  numeric_type_name(ti) + "_scaled_nullable",
501  {operand_lv,
502  cgen_state_->inlineIntNull(operand_ti),
504  llvm::ConstantFP::get(fp_type, multiplier)});
505  } else {
506  result_lv = cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
507  numeric_type_name(ti) + "_nullable",
508  {operand_lv,
509  cgen_state_->inlineIntNull(operand_ti),
510  cgen_state_->inlineFpNull(ti)});
511  }
512  }
513  CHECK(result_lv);
514  return result_lv;
515 }
516 
517 llvm::Value* CodeGenerator::codegenCastFromFp(llvm::Value* operand_lv,
518  const SQLTypeInfo& operand_ti,
519  const SQLTypeInfo& ti) {
521  if (!operand_ti.is_fp() || !ti.is_number() || ti.is_decimal()) {
522  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
523  ti.get_type_name() + " not supported");
524  }
525  if (operand_ti.get_type() == ti.get_type()) {
526  // Should not have been called when both dimensions are same.
527  return operand_lv;
528  }
529  CHECK(operand_lv->getType()->isFloatTy() || operand_lv->getType()->isDoubleTy());
530  if (operand_ti.get_notnull()) {
531  if (ti.get_type() == kDOUBLE) {
532  return cgen_state_->ir_builder_.CreateFPExt(
533  operand_lv, llvm::Type::getDoubleTy(cgen_state_->context_));
534  } else if (ti.get_type() == kFLOAT) {
535  return cgen_state_->ir_builder_.CreateFPTrunc(
536  operand_lv, llvm::Type::getFloatTy(cgen_state_->context_));
537  } else if (ti.is_integer()) {
538  // Round by adding/subtracting 0.5 before fptosi.
539  auto* fp_type = operand_lv->getType()->isFloatTy()
540  ? llvm::Type::getFloatTy(cgen_state_->context_)
541  : llvm::Type::getDoubleTy(cgen_state_->context_);
542  auto* zero = llvm::ConstantFP::get(fp_type, 0.0);
543  auto* mhalf = llvm::ConstantFP::get(fp_type, -0.5);
544  auto* phalf = llvm::ConstantFP::get(fp_type, 0.5);
545  auto* is_negative = cgen_state_->ir_builder_.CreateFCmpOLT(operand_lv, zero);
546  auto* offset = cgen_state_->ir_builder_.CreateSelect(is_negative, mhalf, phalf);
547  operand_lv = cgen_state_->ir_builder_.CreateFAdd(operand_lv, offset);
548  return cgen_state_->ir_builder_.CreateFPToSI(
549  operand_lv, get_int_type(get_bit_width(ti), cgen_state_->context_));
550  } else {
551  CHECK(false);
552  }
553  } else {
554  const auto from_tname = numeric_type_name(operand_ti);
555  const auto to_tname = numeric_type_name(ti);
556  if (ti.is_fp()) {
557  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
558  {operand_lv,
559  cgen_state_->inlineFpNull(operand_ti),
560  cgen_state_->inlineFpNull(ti)});
561  } else if (ti.is_integer()) {
562  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
563  {operand_lv,
564  cgen_state_->inlineFpNull(operand_ti),
565  cgen_state_->inlineIntNull(ti)});
566  } else {
567  CHECK(false);
568  }
569  }
570  CHECK(false);
571  return nullptr;
572 }
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:380
#define CHECK_EQ(x, y)
Definition: Logger.h:230
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:152
llvm::Value * codegenCastFromFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:517
HOST DEVICE int get_size() const
Definition: sqltypes.h:389
Definition: sqltypes.h:64
bool is_timestamp() const
Definition: sqltypes.h:995
CgenState * cgen_state_
#define NULL_BIGINT
bool is_fp() const
Definition: sqltypes.h:579
HOST DEVICE int get_scale() const
Definition: sqltypes.h:384
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:441
llvm::Value * codegenCastToFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:474
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:379
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool is_number() const
Definition: sqltypes.h:580
bool is_time() const
Definition: sqltypes.h:581
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:439
llvm::Function * current_func_
Definition: CgenState.h:433
int get_logical_size() const
Definition: sqltypes.h:399
bool is_integer() const
Definition: sqltypes.h:577
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:64
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1386
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:343
bool is_dict_intersection() const
Definition: sqltypes.h:644
bool needs_error_check_
Definition: CgenState.h:461
bool is_boolean() const
Definition: sqltypes.h:582
llvm::Value * codegenCastTimestampToDate(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:157
#define AUTOMATIC_IR_METADATA(CGENSTATE)
double power10inv(unsigned const x)
Definition: misc.h:276
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:82
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:219
ExecutorDeviceType device_type
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:30
Definition: sqltypes.h:68
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:387
const Expr * get_operand() const
Definition: Analyzer.h:379
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:416
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:381
std::string get_type_name() const
Definition: sqltypes.h:503
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:343
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:388
llvm::Value * codegenCastBetweenTimestamps(llvm::Value *ts_lv, const SQLTypeInfo &operand_dimen, const SQLTypeInfo &target_dimen, const bool nullable)
Definition: CastIR.cpp:194
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:306
#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 * codegenCastTimestampToTime(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:137
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:226
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:575
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:386
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:578
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:123
SQLOps get_optype() const
Definition: Analyzer.h:378
bool is_array() const
Definition: sqltypes.h:583
static constexpr int32_t literalsDictId
Definition: DictRef.h:15
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:106
Executor * executor() const