OmniSciDB  c07336695a
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_dimen, ti.get_dimension(), !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 int operand_dimen,
138  const int target_dimen,
139  const bool nullable) {
140  if (operand_dimen == target_dimen) {
141  return ts_lv;
142  }
143  CHECK(ts_lv->getType()->isIntegerTy(64));
144  static const std::string sup_fname{"DateTruncateAlterPrecisionScaleUp"};
145  static const std::string sdn_fname{"DateTruncateAlterPrecisionScaleDown"};
146  static const std::string sup_null_fname{"DateTruncateAlterPrecisionScaleUpNullable"};
147  static const std::string sdn_null_fname{"DateTruncateAlterPrecisionScaleDownNullable"};
148  std::vector<llvm::Value*> f_args{ts_lv,
149  cgen_state_->llInt(static_cast<int64_t>(
151  abs(operand_dimen - target_dimen))))};
152  if (nullable) {
153  f_args.push_back(cgen_state_->inlineIntNull(SQLTypeInfo(kBIGINT, false)));
154  }
155  return operand_dimen < target_dimen
156  ? cgen_state_->emitExternalCall(nullable ? sup_null_fname : sup_fname,
158  f_args)
159  : cgen_state_->emitExternalCall(nullable ? sdn_null_fname : sdn_fname,
161  f_args);
162 }
163 
164 llvm::Value* CodeGenerator::codegenCastFromString(llvm::Value* operand_lv,
165  const SQLTypeInfo& operand_ti,
166  const SQLTypeInfo& ti,
167  const bool operand_is_const,
168  const CompilationOptions& co) {
169  if (!ti.is_string()) {
170  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
171  ti.get_type_name() + " not supported");
172  }
173  if (operand_ti.get_compression() == kENCODING_NONE &&
175  return operand_lv;
176  }
177  // dictionary encode non-constant
178  if (operand_ti.get_compression() != kENCODING_DICT && !operand_is_const) {
179  if (g_cluster) {
180  throw std::runtime_error(
181  "Cast from none-encoded string to dictionary-encoded not supported for "
182  "distributed queries");
183  }
184  if (g_enable_watchdog) {
185  throw WatchdogException(
186  "Cast from none-encoded string to dictionary-encoded would be slow");
187  }
188  CHECK_EQ(kENCODING_NONE, operand_ti.get_compression());
190  CHECK(operand_lv->getType()->isIntegerTy(64));
192  throw QueryMustRunOnCpu();
193  }
195  "string_compress",
197  {operand_lv,
198  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
199  ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
200  }
201  CHECK(operand_lv->getType()->isIntegerTy(32));
202  if (ti.get_compression() == kENCODING_NONE) {
203  if (g_cluster) {
204  throw std::runtime_error(
205  "Cast from dictionary-encoded string to none-encoded not supported for "
206  "distributed queries");
207  }
208  if (g_enable_watchdog) {
209  throw WatchdogException(
210  "Cast from dictionary-encoded string to none-encoded would be slow");
211  }
212  CHECK_EQ(kENCODING_DICT, operand_ti.get_compression());
214  throw QueryMustRunOnCpu();
215  }
217  "string_decompress",
219  {operand_lv,
220  cgen_state_->llInt(int64_t(executor()->getStringDictionaryProxy(
221  operand_ti.get_comp_param(), executor()->getRowSetMemoryOwner(), true)))});
222  }
223  CHECK(operand_is_const);
225  return operand_lv;
226 }
227 
228 llvm::Value* CodeGenerator::codegenCastBetweenIntTypes(llvm::Value* operand_lv,
229  const SQLTypeInfo& operand_ti,
230  const SQLTypeInfo& ti,
231  bool upscale) {
232  if (ti.is_decimal() &&
233  (!operand_ti.is_decimal() || operand_ti.get_scale() <= ti.get_scale())) {
234  if (upscale) {
235  if (operand_ti.get_scale() < ti.get_scale()) { // scale only if needed
236  auto scale = exp_to_scale(ti.get_scale() - operand_ti.get_scale());
237  const auto scale_lv =
238  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
239  operand_lv = cgen_state_->ir_builder_.CreateSExt(
240  operand_lv, get_int_type(64, cgen_state_->context_));
241 
242  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, scale);
243 
244  if (operand_ti.get_notnull()) {
245  operand_lv = cgen_state_->ir_builder_.CreateMul(operand_lv, scale_lv);
246  } else {
247  operand_lv = cgen_state_->emitCall(
248  "scale_decimal_up",
249  {operand_lv,
250  scale_lv,
251  cgen_state_->llInt(inline_int_null_val(operand_ti)),
253  }
254  }
255  }
256  } else if (operand_ti.is_decimal()) {
257  // rounded scale down
258  auto scale = (int64_t)exp_to_scale(operand_ti.get_scale() - ti.get_scale());
259  const auto scale_lv =
260  llvm::ConstantInt::get(get_int_type(64, cgen_state_->context_), scale);
261 
262  const auto operand_width =
263  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
264 
265  std::string method_name = "scale_decimal_down_nullable";
266  if (operand_ti.get_notnull()) {
267  method_name = "scale_decimal_down_not_nullable";
268  }
269 
270  CHECK(operand_width == 64);
271  operand_lv = cgen_state_->emitCall(
272  method_name,
273  {operand_lv, scale_lv, cgen_state_->llInt(inline_int_null_val(operand_ti))});
274  }
275  if (ti.is_integer() && operand_ti.is_integer() &&
276  operand_ti.get_logical_size() > ti.get_logical_size()) {
277  codegenCastBetweenIntTypesOverflowChecks(operand_lv, operand_ti, ti, 1);
278  }
279 
280  const auto operand_width =
281  static_cast<llvm::IntegerType*>(operand_lv->getType())->getBitWidth();
282  const auto target_width = get_bit_width(ti);
283  if (target_width == operand_width) {
284  return operand_lv;
285  }
286  if (operand_ti.get_notnull()) {
287  return cgen_state_->ir_builder_.CreateCast(
288  target_width > operand_width ? llvm::Instruction::CastOps::SExt
289  : llvm::Instruction::CastOps::Trunc,
290  operand_lv,
291  get_int_type(target_width, cgen_state_->context_));
292  }
293  return cgen_state_->emitCall("cast_" + numeric_type_name(operand_ti) + "_to_" +
294  numeric_type_name(ti) + "_nullable",
295  {operand_lv,
296  cgen_state_->inlineIntNull(operand_ti),
297  cgen_state_->inlineIntNull(ti)});
298 }
299 
301  llvm::Value* operand_lv,
302  const SQLTypeInfo& operand_ti,
303  const SQLTypeInfo& ti,
304  const int64_t scale) {
305  llvm::Value* chosen_max{nullptr};
306  llvm::Value* chosen_min{nullptr};
307  std::tie(chosen_max, chosen_min) =
309 
311  auto cast_ok =
312  llvm::BasicBlock::Create(cgen_state_->context_, "cast_ok", cgen_state_->row_func_);
313  auto cast_fail = llvm::BasicBlock::Create(
314  cgen_state_->context_, "cast_fail", cgen_state_->row_func_);
315  auto operand_max = static_cast<llvm::ConstantInt*>(chosen_max)->getSExtValue() / scale;
316  auto operand_min = static_cast<llvm::ConstantInt*>(chosen_min)->getSExtValue() / scale;
317  const auto ti_llvm_type =
319  llvm::Value* operand_max_lv = llvm::ConstantInt::get(ti_llvm_type, operand_max);
320  llvm::Value* operand_min_lv = llvm::ConstantInt::get(ti_llvm_type, operand_min);
321  const bool is_narrowing = operand_ti.get_logical_size() > ti.get_logical_size();
322  if (is_narrowing) {
323  const auto operand_ti_llvm_type =
325  operand_max_lv =
326  cgen_state_->ir_builder_.CreateSExt(operand_max_lv, operand_ti_llvm_type);
327  operand_min_lv =
328  cgen_state_->ir_builder_.CreateSExt(operand_min_lv, operand_ti_llvm_type);
329  }
330  llvm::Value* over{nullptr};
331  llvm::Value* under{nullptr};
332  if (operand_ti.get_notnull()) {
333  over = cgen_state_->ir_builder_.CreateICmpSGT(operand_lv, operand_max_lv);
334  under = cgen_state_->ir_builder_.CreateICmpSLE(operand_lv, operand_min_lv);
335  } else {
336  const auto type_name =
337  is_narrowing ? numeric_type_name(operand_ti) : numeric_type_name(ti);
338  const auto null_operand_val = cgen_state_->llInt(inline_int_null_val(operand_ti));
339  const auto null_bool_val = cgen_state_->inlineIntNull(SQLTypeInfo(kBOOLEAN, false));
340  over = toBool(cgen_state_->emitCall(
341  "gt_" + type_name + "_nullable_lhs",
342  {operand_lv, operand_max_lv, null_operand_val, null_bool_val}));
343  under = toBool(cgen_state_->emitCall(
344  "le_" + type_name + "_nullable_lhs",
345  {operand_lv, operand_min_lv, null_operand_val, null_bool_val}));
346  }
347  const auto detected = cgen_state_->ir_builder_.CreateOr(over, under, "overflow");
348  cgen_state_->ir_builder_.CreateCondBr(detected, cast_fail, cast_ok);
349 
350  cgen_state_->ir_builder_.SetInsertPoint(cast_fail);
351  cgen_state_->ir_builder_.CreateRet(
353 
354  cgen_state_->ir_builder_.SetInsertPoint(cast_ok);
355 }
356 
357 llvm::Value* CodeGenerator::codegenCastToFp(llvm::Value* operand_lv,
358  const SQLTypeInfo& operand_ti,
359  const SQLTypeInfo& ti) {
360  if (!ti.is_fp()) {
361  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
362  ti.get_type_name() + " not supported");
363  }
364  const auto to_tname = numeric_type_name(ti);
365  llvm::Value* result_lv{nullptr};
366  if (operand_ti.get_notnull()) {
367  result_lv = cgen_state_->ir_builder_.CreateSIToFP(
368  operand_lv,
369  ti.get_type() == kFLOAT ? llvm::Type::getFloatTy(cgen_state_->context_)
370  : llvm::Type::getDoubleTy(cgen_state_->context_));
371  } else {
372  result_lv = cgen_state_->emitCall(
373  "cast_" + numeric_type_name(operand_ti) + "_to_" + to_tname + "_nullable",
374  {operand_lv,
375  cgen_state_->inlineIntNull(operand_ti),
376  cgen_state_->inlineFpNull(ti)});
377  }
378  CHECK(result_lv);
379  if (operand_ti.get_scale()) {
380  result_lv = cgen_state_->ir_builder_.CreateFDiv(
381  result_lv,
382  llvm::ConstantFP::get(result_lv->getType(),
383  exp_to_scale(operand_ti.get_scale())));
384  }
385  return result_lv;
386 }
387 
388 llvm::Value* CodeGenerator::codegenCastFromFp(llvm::Value* operand_lv,
389  const SQLTypeInfo& operand_ti,
390  const SQLTypeInfo& ti) {
391  if (!operand_ti.is_fp() || !ti.is_number() || ti.is_decimal()) {
392  throw std::runtime_error("Cast from " + operand_ti.get_type_name() + " to " +
393  ti.get_type_name() + " not supported");
394  }
395  if (operand_ti.get_type() == ti.get_type()) {
396  // Should not have been called when both dimensions are same.
397  return operand_lv;
398  }
399  CHECK(operand_lv->getType()->isFloatTy() || operand_lv->getType()->isDoubleTy());
400  if (operand_ti.get_notnull()) {
401  if (ti.get_type() == kDOUBLE) {
402  return cgen_state_->ir_builder_.CreateFPExt(
403  operand_lv, llvm::Type::getDoubleTy(cgen_state_->context_));
404  } else if (ti.get_type() == kFLOAT) {
405  return cgen_state_->ir_builder_.CreateFPTrunc(
406  operand_lv, llvm::Type::getFloatTy(cgen_state_->context_));
407  } else if (ti.is_integer()) {
408  return cgen_state_->ir_builder_.CreateFPToSI(
409  operand_lv, get_int_type(get_bit_width(ti), cgen_state_->context_));
410  } else {
411  CHECK(false);
412  }
413  } else {
414  const auto from_tname = numeric_type_name(operand_ti);
415  const auto to_tname = numeric_type_name(ti);
416  if (ti.is_fp()) {
417  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
418  {operand_lv,
419  cgen_state_->inlineFpNull(operand_ti),
420  cgen_state_->inlineFpNull(ti)});
421  } else if (ti.is_integer()) {
422  return cgen_state_->emitCall("cast_" + from_tname + "_to_" + to_tname + "_nullable",
423  {operand_lv,
424  cgen_state_->inlineFpNull(operand_ti),
425  cgen_state_->inlineIntNull(ti)});
426  } else {
427  CHECK(false);
428  }
429  }
430  CHECK(false);
431  return nullptr;
432 }
#define CHECK_EQ(x, y)
Definition: Logger.h:195
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:388
bool is_time() const
Definition: sqltypes.h:452
HOST DEVICE int get_size() const
Definition: sqltypes.h:329
HOST DEVICE int get_dimension() const
Definition: sqltypes.h:321
bool is_fp() const
Definition: sqltypes.h:450
CgenState * cgen_state_
HOST DEVICE bool get_notnull() const
Definition: sqltypes.h:326
llvm::IRBuilder ir_builder_
Definition: CgenState.h:268
HOST DEVICE int get_scale() const
Definition: sqltypes.h:324
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:319
llvm::Value * codegenCastToFp(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti)
Definition: CastIR.cpp:357
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)
HOST DEVICE EncodingType get_compression() const
Definition: sqltypes.h:327
llvm::Function * row_func_
Definition: CgenState.h:264
std::string get_type_name() const
Definition: sqltypes.h:422
bool is_array() const
Definition: sqltypes.h:454
bool is_integer() const
Definition: sqltypes.h:448
size_t get_bit_width(const SQLTypeInfo &ti)
llvm::LLVMContext & context_
Definition: CgenState.h:266
bool is_decimal() const
Definition: sqltypes.h:449
HOST DEVICE SQLTypes get_subtype() const
Definition: sqltypes.h:320
llvm::ConstantInt * inlineIntNull(const SQLTypeInfo &)
Definition: CgenState.cpp:24
llvm::Value * emitExternalCall(const std::string &fname, llvm::Type *ret_type, const std::vector< llvm::Value *> args, const std::vector< llvm::Attribute::AttrKind > &fnattrs={})
Definition: CgenState.h:203
static const int32_t ERR_OVERFLOW_OR_UNDERFLOW
Definition: Execute.h:1010
llvm::Value * codegenCastBetweenIntTypes(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, bool upscale=true)
Definition: CastIR.cpp:228
bool needs_error_check_
Definition: CgenState.h:283
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:819
ExecutorDeviceType device_type_
bool is_boolean() const
Definition: sqltypes.h:453
std::vector< llvm::Value * > codegen(const Analyzer::Expr *, const bool fetch_columns, const CompilationOptions &)
Definition: IRCodegen.cpp:25
Definition: sqltypes.h:55
llvm::Value * emitCall(const std::string &fname, const std::vector< llvm::Value *> &args)
Definition: CgenState.cpp:134
void codegenCastBetweenIntTypesOverflowChecks(llvm::Value *operand_lv, const SQLTypeInfo &operand_ti, const SQLTypeInfo &ti, const int64_t scale)
Definition: CastIR.cpp:300
llvm::Value * toBool(llvm::Value *)
Definition: LogicalIR.cpp:333
int get_logical_size() const
Definition: sqltypes.h:330
bool is_number() const
Definition: sqltypes.h:451
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:77
#define CHECK(condition)
Definition: Logger.h:187
constexpr int64_t get_timestamp_precision_scale(const int32_t dimen)
Definition: DateTimeUtils.h:48
uint64_t exp_to_scale(const unsigned exp)
int64_t inline_int_null_val(const SQL_TYPE_INFO &ti)
bool g_cluster
bool g_enable_watchdog
Definition: Execute.cpp:69
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:164
llvm::Value * codegenCast(const Analyzer::UOper *, const CompilationOptions &)
Definition: CastIR.cpp:20
std::string numeric_type_name(const SQLTypeInfo &ti)
Definition: Execute.h:157
llvm::ArrayType * get_int_array_type(int const width, int count, llvm::LLVMContext &context)
bool is_string() const
Definition: sqltypes.h:446
std::pair< llvm::ConstantInt *, llvm::ConstantInt * > inlineIntMaxMin(const size_t byte_width, const bool is_signed)
Definition: CgenState.cpp:74
llvm::ConstantInt * llInt(const T v) const
Definition: CgenState.h:247
SQLOps get_optype() const
Definition: Analyzer.h:363
llvm::Value * codegenCastBetweenTimestamps(llvm::Value *ts_lv, const int operand_dimen, const int target_dimen, const bool nullable)
Definition: CastIR.cpp:136
llvm::ConstantFP * inlineFpNull(const SQLTypeInfo &)
Definition: CgenState.cpp:62
const Expr * get_operand() const
Definition: Analyzer.h:364