OmniSciDB  0bd2ec9cf4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CastIR.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 llvm::Value* CodeGenerator::codegenCast(const Analyzer::UOper* uoper,
21  const CompilationOptions& co) {
22  CHECK_EQ(uoper->get_optype(), kCAST);
23  const auto& ti = uoper->get_type_info();
24  const auto operand = uoper->get_operand();
25  const auto operand_as_const = dynamic_cast<const Analyzer::Constant*>(operand);
26  // For dictionary encoded constants, the cast holds the dictionary id
27  // information as the compression parameter; handle this case separately.
28  llvm::Value* operand_lv{nullptr};
29  if (operand_as_const) {
30  const auto operand_lvs =
31  codegen(operand_as_const, ti.get_compression(), ti.get_comp_param(), co);
32  if (operand_lvs.size() == 3) {
33  operand_lv = cgen_state_->emitCall("string_pack", {operand_lvs[1], operand_lvs[2]});
34  } else {
35  operand_lv = operand_lvs.front();
36  }
37  } else {
38  operand_lv = codegen(operand, true, co).front();
39  }
40  const auto& operand_ti = operand->get_type_info();
41  return codegenCast(operand_lv, operand_ti, ti, operand_as_const, co);
42 }
43 
44 namespace {
45 
46 bool byte_array_cast(const SQLTypeInfo& operand_ti, const SQLTypeInfo& ti) {
47  return (operand_ti.is_array() && ti.is_array() && ti.get_subtype() == kTINYINT &&
48  operand_ti.get_size() > 0 && operand_ti.get_size() == ti.get_size());
49 }
50 
51 } // namespace
52 
53 llvm::Value* CodeGenerator::codegenCast(llvm::Value* operand_lv,
54  const SQLTypeInfo& operand_ti,
55  const SQLTypeInfo& ti,
56  const bool operand_is_const,
57  const CompilationOptions& co) {
58  if (byte_array_cast(operand_ti, ti)) {
59  auto* byte_array_type = get_int_array_type(8, ti.get_size(), cgen_state_->context_);
60  return cgen_state_->ir_builder_.CreatePointerCast(operand_lv,
61  byte_array_type->getPointerTo());
62  }
63  if (operand_lv->getType()->isIntegerTy()) {
64  if (operand_ti.is_string()) {
65  return codegenCastFromString(operand_lv, operand_ti, ti, operand_is_const, co);
66  }
67  CHECK(operand_ti.is_integer() || operand_ti.is_decimal() || operand_ti.is_time() ||
68  operand_ti.is_boolean());
69  if (operand_ti.is_boolean()) {
70  CHECK(operand_lv->getType()->isIntegerTy(1) ||
71  operand_lv->getType()->isIntegerTy(8));
72  if (operand_lv->getType()->isIntegerTy(1)) {
73  operand_lv = cgen_state_->castToTypeIn(operand_lv, 8);
74  }
75  }
76  if (operand_ti.get_type() == kTIMESTAMP && ti.get_type() == kDATE) {
77  // Maybe we should instead generate DatetruncExpr directly from RelAlgTranslator
78  // for this pattern. However, DatetruncExpr is supposed to return a timestamp,
79  // whereas this cast returns a date. The underlying type for both is still the same,
80  // but it still doesn't look like a good idea to misuse DatetruncExpr.
81  // Date will have default precision of day, but TIMESTAMP dimension would
82  // matter but while converting date through seconds
84  operand_lv, operand_ti.get_dimension(), !ti.get_notnull());
85  }
86  if ((operand_ti.get_type() == kTIMESTAMP || operand_ti.get_type() == kDATE) &&
87  ti.get_type() == kTIMESTAMP) {
88  const auto operand_dimen =
89  (operand_ti.is_timestamp()) ? operand_ti.get_dimension() : 0;
90  if (operand_dimen != ti.get_dimension()) {
92  operand_lv, operand_ti, ti, !ti.get_notnull());
93  }
94  }
95  if (ti.is_integer() || ti.is_decimal() || ti.is_time()) {
96  return codegenCastBetweenIntTypes(operand_lv, operand_ti, ti);
97  } else {
98  return codegenCastToFp(operand_lv, operand_ti, ti);
99  }
100  } else {
101  return codegenCastFromFp(operand_lv, operand_ti, ti);
102  }
103  CHECK(false);
104  return nullptr;
105 }
106 
107 llvm::Value* CodeGenerator::codegenCastTimestampToDate(llvm::Value* ts_lv,
108  const int dimen,
109  const bool nullable) {
110  CHECK(ts_lv->getType()->isIntegerTy(64));
111  std::vector<llvm::Value*> datetrunc_args{ts_lv};
112  if (dimen > 0) {
113  static const std::string hptodate_fname = "DateTruncateHighPrecisionToDate";
114  static const std::string hptodate_null_fname =
115  "DateTruncateHighPrecisionToDateNullable";
116  datetrunc_args.push_back(
118  if (nullable) {
119  datetrunc_args.push_back(cgen_state_->inlineIntNull(SQLTypeInfo(kBIGINT, false)));
120  }
121  return cgen_state_->emitExternalCall(nullable ? hptodate_null_fname : hptodate_fname,
123  datetrunc_args);
124  }
125  std::string datetrunc_fname{"DateTruncate"};
126  datetrunc_args.insert(datetrunc_args.begin(),
127  cgen_state_->llInt(static_cast<int32_t>(dtDAY)));
128  if (nullable) {
129  datetrunc_args.push_back(cgen_state_->inlineIntNull(SQLTypeInfo(kBIGINT, false)));
130  datetrunc_fname += "Nullable";
131  }
133  datetrunc_fname, get_int_type(64, cgen_state_->context_), datetrunc_args);
134 }
135 
136 llvm::Value* CodeGenerator::codegenCastBetweenTimestamps(llvm::Value* ts_lv,
137  const SQLTypeInfo& operand_ti,
138  const SQLTypeInfo& target_ti,
139  const bool nullable) {
140  const auto operand_dimen = operand_ti.get_dimension();
141  const auto target_dimen = target_ti.get_dimension();
142  if (operand_dimen == target_dimen) {
143  return ts_lv;
144  }
145  CHECK(ts_lv->getType()->isIntegerTy(64));
146  const auto scale =
147  DateTimeUtils::get_timestamp_precision_scale(abs(operand_dimen - target_dimen));
148  if (operand_dimen < target_dimen) {
149  return nullable
150  ? cgen_state_->emitCall("mul_int64_t_nullable_lhs",
151  {ts_lv,
152  cgen_state_->llInt(static_cast<int64_t>(scale)),
153  cgen_state_->inlineIntNull(operand_ti)})
154  : cgen_state_->ir_builder_.CreateMul(
155  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
156  }
157  return nullable
158  ? cgen_state_->emitCall("div_int64_t_nullable_lhs",
159  {ts_lv,
160  cgen_state_->llInt(static_cast<int64_t>(scale)),
161  cgen_state_->inlineIntNull(operand_ti)})
162  : cgen_state_->ir_builder_.CreateSDiv(
163  ts_lv, cgen_state_->llInt(static_cast<int64_t>(scale)));
164 }
165 
166 llvm::Value* CodeGenerator::codegenCastFromString(llvm::Value* operand_lv,
167  const SQLTypeInfo& operand_ti,
168  const SQLTypeInfo& ti,
169  const bool operand_is_const,
170  const CompilationOptions& co) {
171  if (!ti.is_string()) {
172  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
173  ti.get_type_name() + " not supported");
174  }
175  if (operand_ti.get_compression() == kENCODING_NONE &&
177  return operand_lv;
178  }
179  // dictionary encode non-constant
180  if (operand_ti.get_compression() != kENCODING_DICT && !operand_is_const) {
181  if (g_cluster) {
182  throw std::runtime_error(
183  "Cast from none-encoded string to dictionary-encoded not supported for "
184  "distributed queries");
185  }
186  if (g_enable_watchdog) {
187  throw WatchdogException(
188  "Cast from none-encoded string to dictionary-encoded would be slow");
189  }
190  CHECK_EQ(kENCODING_NONE, operand_ti.get_compression());
192  CHECK(operand_lv->getType()->isIntegerTy(64));
194  throw QueryMustRunOnCpu();
195  }
197  "string_compress",
199  {operand_lv,
200  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
201  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
202  }
203  CHECK(operand_lv->getType()->isIntegerTy(32));
204  if (ti.get_compression() == kENCODING_NONE) {
205  if (g_cluster) {
206  throw std::runtime_error(
207  "Cast from dictionary-encoded string to none-encoded not supported for "
208  "distributed queries");
209  }
210  if (g_enable_watchdog) {
211  throw WatchdogException(
212  "Cast from dictionary-encoded string to none-encoded would be slow");
213  }
214  CHECK_EQ(kENCODING_DICT, operand_ti.get_compression());
216  throw QueryMustRunOnCpu();
217  }
219  "string_decompress",
221  {operand_lv,
222  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
223  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
224  }
225  CHECK(operand_is_const);
227  return operand_lv;
228 }
229 
230 llvm::Value* CodeGenerator::codegenCastBetweenIntTypes(llvm::Value* operand_lv,
231  const SQLTypeInfo& operand_ti,
232  const SQLTypeInfo& ti,
233  bool upscale) {
234  if (ti.is_decimal() &&
235  (!operand_ti.is_decimal() || operand_ti.get_scale() <= ti.get_scale())) {
236  if (upscale) {
237  if (operand_ti.get_scale() < ti.get_scale()) { // scale only if needed
238  auto scale = exp_to_scale(ti.get_scale() - operand_ti.get_scale());
239  const auto scale_lv =
240  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
241  operand_lv = cgen_state_->ir_builder_.CreateSExt(
242  operand_lv, get_int_type(64, cgen_state_->context_));
243 
244  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, scale);
245 
246  if (operand_ti.get_notnull()) {
247  operand_lv = cgen_state_->ir_builder_.CreateMul(operand_lv, scale_lv);
248  } else {
249  operand_lv = cgen_state_->emitCall(
250  "scale_decimal_up",
251  {operand_lv,
252  scale_lv,
253  cgen_state_->llInt(inline_int_null_val(operand_ti)),
255  }
256  }
257  }
258  } else if (operand_ti.is_decimal()) {
259  // rounded scale down
260  auto scale = (int64_t)exp_to_scale(operand_ti.get_scale() - ti.get_scale());
261  const auto scale_lv =
262  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
263 
264  const auto operand_width =
265  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
266 
267  std::string method_name = "scale_decimal_down_nullable";
268  if (operand_ti.get_notnull()) {
269  method_name = "scale_decimal_down_not_nullable";
270  }
271 
272  CHECK(operand_width == 64);
273  operand_lv = cgen_state_->emitCall(
274  method_name,
275  {operand_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(operand_ti))});
276  }
277  if (ti.is_integer() && operand_ti.is_integer() &&
278  operand_ti.get_logical_size() > ti.get_logical_size()) {
279  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, 1);
280  }
281 
282  const auto operand_width =
283  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
284  const auto target_width = get_bit_width(ti);
285  if (target_width == operand_width) {
286  return operand_lv;
287  }
288  if (operand_ti.get_notnull()) {
289  return cgen_state_->ir_builder_.CreateCast(
290  target_width > operand_width ? llvm::Instruction::CastOps::SExt
291  : llvm::Instruction::CastOps::Trunc,
292  operand_lv,
293  get_int_type(target_width, cgen_state_->context_));
294  }
295  return cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
296  numeric_type_name(ti) + "_nullable",
297  {operand_lv,
298  cgen_state_->inlineIntNull(operand_ti),
299  cgen_state_->inlineIntNull(ti)});
300 }
301 
303  llvm::Value* operand_lv,
304  const SQLTypeInfo& operand_ti,
305  const SQLTypeInfo& ti,
306  const int64_t scale) {
307  llvm::Value* chosen_max{nullptr};
308  llvm::Value* chosen_min{nullptr};
309  std::tie(chosen_max, chosen_min) =
311 
313  auto cast_ok =
314  llvm::BasicBlock::Create(cgen_state_->context_, "cast_ok", cgen_state_->row_func_);
315  auto cast_fail = llvm::BasicBlock::Create(
316  cgen_state_->context_, "cast_fail", cgen_state_->row_func_);
317  auto operand_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() / scale;
318  auto operand_min = static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue() / scale;
319  const auto ti_llvm_type =
321  llvm::Value* operand_max_lv = llvm::ConstantInt::get(ti_llvm_type, operand_max);
322  llvm::Value* operand_min_lv = llvm::ConstantInt::get(ti_llvm_type, operand_min);
323  const bool is_narrowing = operand_ti.get_logical_size() > ti.get_logical_size();
324  if (is_narrowing) {
325  const auto operand_ti_llvm_type =
327  operand_max_lv =
328  cgen_state_->ir_builder_.CreateSExt(operand_max_lv, operand_ti_llvm_type);
329  operand_min_lv =
330  cgen_state_->ir_builder_.CreateSExt(operand_min_lv, operand_ti_llvm_type);
331  }
332  llvm::Value* over{nullptr};
333  llvm::Value* under{nullptr};
334  if (operand_ti.get_notnull()) {
335  over = cgen_state_->ir_builder_.CreateICmpSGT(operand_lv, operand_max_lv);
336  under = cgen_state_->ir_builder_.CreateICmpSLE(operand_lv, operand_min_lv);
337  } else {
338  const auto type_name =
339  is_narrowing ? numeric_type_name(operand_ti) : numeric_type_name(ti);
340  const auto null_operand_val = cgen_state_->llInt(inline_int_null_val(operand_ti));
341  const auto null_bool_val = cgen_state_->inlineIntNull(SQLTypeInfo(kBOOLEAN, false));
342  over = toBool(cgen_state_->emitCall(
343  "gt_" + type_name + "_nullable_lhs",
344  {operand_lv, operand_max_lv, null_operand_val, null_bool_val}));
345  under = toBool(cgen_state_->emitCall(
346  "le_" + type_name + "_nullable_lhs",
347  {operand_lv, operand_min_lv, null_operand_val, null_bool_val}));
348  }
349  const auto detected = cgen_state_->ir_builder_.CreateOr(over, under, "overflow");
350  cgen_state_->ir_builder_.CreateCondBr(detected, cast_fail, cast_ok);
351 
352  cgen_state_->ir_builder_.SetInsertPoint(cast_fail);
353  cgen_state_->ir_builder_.CreateRet(
354  cgen_state_->llInt(Executor::ERR_OVERFLOW_OR_UNDERFLOW));
355 
356  cgen_state_->ir_builder_.SetInsertPoint(cast_ok);
357 }
358 
359 llvm::Value* CodeGenerator::codegenCastToFp(llvm::Value* operand_lv,
360  const SQLTypeInfo& operand_ti,
361  const SQLTypeInfo& ti) {
362  if (!ti.is_fp()) {
363  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
364  ti.get_type_name() + " not supported");
365  }
366  const auto to_tname = numeric_type_name(ti);
367  llvm::Value* result_lv{nullptr};
368  if (operand_ti.get_notnull()) {
369  result_lv = cgen_state_->ir_builder_.CreateSIToFP(
370  operand_lv,
371  ti.get_type() == kFLOAT ? llvm::Type::getFloatTy(cgen_state_->context_)
372  : llvm::Type::getDoubleTy(cgen_state_->context_));
373  } else {
374  result_lv = cgen_state_->emitCall(
375  "cast_" + numeric_type_name(operand_ti) + "_to_" + to_tname + "_nullable",
376  {operand_lv,
377  cgen_state_->inlineIntNull(operand_ti),
378  cgen_state_->inlineFpNull(ti)});
379  }
380  CHECK(result_lv);
381  if (operand_ti.get_scale()) {
382  result_lv = cgen_state_->ir_builder_.CreateFDiv(
383  result_lv,
384  llvm::ConstantFP::get(result_lv->getType(),
385  exp_to_scale(operand_ti.get_scale())));
386  }
387  return result_lv;
388 }
389 
390 llvm::Value* CodeGenerator::codegenCastFromFp(llvm::Value* operand_lv,
391  const SQLTypeInfo& operand_ti,
392  const SQLTypeInfo& ti) {
393  if (!operand_ti.is_fp() || !ti.is_number() || ti.is_decimal()) {
394  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
395  ti.get_type_name() + " not supported");
396  }
397  if (operand_ti.get_type() == ti.get_type()) {
398  // Should not have been called when both dimensions are same.
399  return operand_lv;
400  }
401  CHECK(operand_lv->getType()->isFloatTy() || operand_lv->getType()->isDoubleTy());
402  if (operand_ti.get_notnull()) {
403  if (ti.get_type() == kDOUBLE) {
404  return cgen_state_->ir_builder_.CreateFPExt(
405  operand_lv, llvm::Type::getDoubleTy(cgen_state_->context_));
406  } else if (ti.get_type() == kFLOAT) {
407  return cgen_state_->ir_builder_.CreateFPTrunc(
408  operand_lv, llvm::Type::getFloatTy(cgen_state_->context_));
409  } else if (ti.is_integer()) {
410  return cgen_state_->ir_builder_.CreateFPToSI(
411  operand_lv, get_int_type(get_bit_width(ti), cgen_state_->context_));
412  } else {
413  CHECK(false);
414  }
415  } else {
416  const auto from_tname = numeric_type_name(operand_ti);
417  const auto to_tname = numeric_type_name(ti);
418  if (ti.is_fp()) {
419  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
420  {operand_lv,
421  cgen_state_->inlineFpNull(operand_ti),
422  cgen_state_->inlineFpNull(ti)});
423  } else if (ti.is_integer()) {
424  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
425  {operand_lv,
426  cgen_state_->inlineFpNull(operand_ti),
427  cgen_state_->inlineIntNull(ti)});
428  } else {
429  CHECK(false);
430  }
431  }
432  CHECK(false);
433  return nullptr;
434 }
bool is_fp() const
Definition: sqltypes.h:481
bool is_boolean() const
Definition: sqltypes.h:484
#define CHECK_EQ(x, y)
Definition: Logger.h:201
llvm::Value * castToTypeIn(llvm::Value *val, const size_t bit_width)
Definition: CgenState.cpp:103
llvm::Value * codegenCastFromFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:390
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:334
HOST DEVICE int get_comp_param() const
Definition: sqltypes.h:335
bool g_cluster
CgenState * cgen_state_
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:205
llvm::IRBuilder ir_builder_
Definition: CgenState.h:318
HOST DEVICE int get_scale() const
Definition: sqltypes.h:331
llvm::Value * codegenCastToFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:359
HOST DEVICE int get_size() const
Definition: sqltypes.h:336
Definition: sqldefs.h:49
bool byte_array_cast(const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:46
llvm::Type * get_int_type(const int width, llvm::LLVMContext &context)
bool g_enable_watchdog
bool is_number() const
Definition: sqltypes.h:482
llvm::Function * row_func_
Definition: CgenState.h:314
std::string get_type_name() const
Definition: sqltypes.h:429
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:316
CHECK(cgen_state)
bool is_array() const
Definition: sqltypes.h:485
bool is_time() const
Definition: sqltypes.h:483
int get_logical_size() const
Definition: sqltypes.h:337
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:326
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:24
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:977
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:230
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:333
bool needs_error_check_
Definition: CgenState.h:333
llvm::Value * codegenCastTimestampToDate(llvm::Value *ts_lv, const int dimen, const bool nullable)
Definition: CastIR.cpp:107
SQLTypeInfoCore< ArrayContextTypeSizer, ExecutorTypePackaging, DateTimeFacilities > SQLTypeInfo
Definition: sqltypes.h:852
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:78
ExecutorDeviceType device_type_
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value * > &args)
Definition: CgenState.cpp:134
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
Definition: sqltypes.h:56
const Expr * get_operand() const
Definition: Analyzer.h:365
bool is_integer() const
Definition: sqltypes.h:479
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:302
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:328
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:333
llvm::Value * codegenCastBetweenTimestamps(llvm::Value *ts_lv, const SQLTypeInfo &operand_dimen, const SQLTypeInfo &target_dimen, const bool nullable)
Definition: CastIR.cpp:136
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:295
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:327
bool is_string() const
Definition: sqltypes.h:477
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)
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:166
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:20
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:159
bool is_decimal() const
Definition: sqltypes.h:480
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:74
SQLOps get_optype() const
Definition: Analyzer.h:364
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62
Executor * executor() const