souffle  2.0.2-371-g6315b36
MiscUtil.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file MiscUtil.h
12  *
13  * @brief Datalog project utilities
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "tinyformat.h"
20 #include <cassert>
21 #include <chrono>
22 #include <cstdlib>
23 #include <iostream>
24 #include <memory>
25 #include <utility>
26 
27 #ifdef _WIN32
28 #include <fcntl.h>
29 #include <io.h>
30 #include <stdlib.h>
31 #include <windows.h>
32 
33 /**
34  * Windows headers define these and they interfere with the standard library
35  * functions.
36  */
37 #undef min
38 #undef max
39 
40 /**
41  * On windows, the following gcc builtins are missing.
42  *
43  * In the case of popcountll, __popcnt64 is the windows equivalent.
44  *
45  * For ctz and ctzll, BitScanForward and BitScanForward64 are the respective
46  * windows equivalents. However ctz is used in a constexpr context, and we can't
47  * use BitScanForward, so we implement it ourselves.
48  */
49 #define __builtin_popcountll __popcnt64
50 
51 #if defined(_MSC_VER)
52 constexpr unsigned long __builtin_ctz(unsigned long value) {
53  unsigned long trailing_zeroes = 0;
54  while ((value = value >> 1) ^ 1) {
55  ++trailing_zeroes;
56  }
57  return trailing_zeroes;
58 }
59 
60 inline unsigned long __builtin_ctzll(unsigned long long value) {
61  unsigned long trailing_zero = 0;
62 
63  if (_BitScanForward64(&trailing_zero, value)) {
64  return trailing_zero;
65  } else {
66  return 64;
67  }
68 }
69 #endif // _MSC_VER
70 #endif // _WIN32
71 
72 // -------------------------------------------------------------------------------
73 // Timing Utils
74 // -------------------------------------------------------------------------------
75 
76 namespace souffle {
77 
78 // a type def for a time point
80 using std::chrono::microseconds;
81 
82 // a shortcut for taking the current time
83 inline time_point now() {
85 }
86 
87 // a shortcut for obtaining the time difference in milliseconds
88 inline long duration_in_us(const time_point& start, const time_point& end) {
89  return static_cast<long>(std::chrono::duration_cast<std::chrono::microseconds>(end - start).count());
90 }
91 
92 // a shortcut for obtaining the time difference in nanoseconds
93 inline long duration_in_ns(const time_point& start, const time_point& end) {
94  return static_cast<long>(std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count());
95 }
96 
97 // -------------------------------------------------------------------------------
98 // Cloning Utilities
99 // -------------------------------------------------------------------------------
100 
101 template <typename A>
102 std::unique_ptr<A> clone(const A* node) {
103  return node ? std::unique_ptr<A>(node->clone()) : nullptr;
104 }
105 
106 template <typename A>
107 std::unique_ptr<A> clone(const std::unique_ptr<A>& node) {
108  return node ? std::unique_ptr<A>(node->clone()) : nullptr;
109 }
110 
111 template <typename A, typename B>
112 auto clone(const std::pair<A, B>& p) {
113  return std::make_pair(clone(p.first), clone(p.second));
114 }
115 
116 // -------------------------------------------------------------------------------
117 // Comparison Utilities
118 // -------------------------------------------------------------------------------
119 /**
120  * Compares two values referenced by a pointer where the case where both
121  * pointers are null is also considered equivalent.
122  */
123 template <typename T>
124 bool equal_ptr(const T* a, const T* b) {
125  if (a == nullptr && b == nullptr) {
126  return true;
127  }
128  if (a != nullptr && b != nullptr) {
129  return *a == *b;
130  }
131  return false;
132 }
133 
134 /**
135  * Compares two values referenced by a pointer where the case where both
136  * pointers are null is also considered equivalent.
137  */
138 template <typename T>
139 bool equal_ptr(const std::unique_ptr<T>& a, const std::unique_ptr<T>& b) {
140  return equal_ptr(a.get(), b.get());
141 }
142 
143 template <typename A, typename B>
144 using copy_const_t = std::conditional_t<std::is_const_v<A>, const B, B>;
145 
146 /**
147  * Helpers for `dynamic_cast`ing without having to specify redundant type qualifiers.
148  * e.g. `as<AstLiteral>(p)` instead of `dynamic_cast<const AstLiteral*>(p.get())`.
149  */
150 template <typename B, typename A>
151 auto as(A* x) {
152  static_assert(std::is_base_of_v<A, B>,
153  "`as<B, A>` does not allow cross-type dyn casts. "
154  "(i.e. `as<B, A>` where `B <: A` is not true.) "
155  "Such a cast is likely a mistake or typo.");
156  return dynamic_cast<copy_const_t<A, B>*>(x);
157 }
158 
159 template <typename B, typename A>
160 std::enable_if_t<std::is_base_of_v<A, B>, copy_const_t<A, B>*> as(A& x) {
161  return as<B>(&x);
162 }
163 
164 template <typename B, typename A>
165 B* as(const std::unique_ptr<A>& x) {
166  return as<B>(x.get());
167 }
168 
169 /**
170  * Checks if the object of type Source can be casted to type Destination.
171  */
172 template <typename B, typename A>
173 bool isA(A* x) {
174  return dynamic_cast<copy_const_t<A, B>*>(x) != nullptr;
175 }
176 
177 template <typename B, typename A>
178 std::enable_if_t<std::is_base_of_v<A, B>, bool> isA(A& x) {
179  return isA<B>(&x);
180 }
181 
182 template <typename B, typename A>
183 bool isA(const std::unique_ptr<A>& x) {
184  return isA<B>(x.get());
185 }
186 
187 // -------------------------------------------------------------------------------
188 // Error Utilities
189 // -------------------------------------------------------------------------------
190 
191 template <typename... Args>
192 [[noreturn]] void fatal(const char* format, const Args&... args) {
193  tfm::format(std::cerr, format, args...);
194  std::cerr << "\n";
195  assert(false && "fatal error; see std err");
196  abort();
197 }
198 
199 // HACK: Workaround to suppress spurious reachability warnings.
200 #define UNREACHABLE_BAD_CASE_ANALYSIS fatal("unhandled switch branch");
201 } // namespace souffle
tinyformat::format
void format(std::ostream &out, const char *fmt)
Definition: tinyformat.h:1089
souffle::isA
bool isA(A *x)
Checks if the object of type Source can be casted to type Destination.
Definition: MiscUtil.h:179
souffle::duration_in_us
long duration_in_us(const time_point &start, const time_point &end)
Definition: MiscUtil.h:94
tinyformat.h
souffle::now
time_point now()
Definition: MiscUtil.h:89
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::copy_const_t
std::conditional_t< std::is_const_v< A >, const B, B > copy_const_t
Definition: MiscUtil.h:150
souffle::as
auto as(A *x)
Helpers for dynamic_casting without having to specify redundant type qualifiers.
Definition: MiscUtil.h:157
souffle::duration_in_ns
long duration_in_ns(const time_point &start, const time_point &end)
Definition: MiscUtil.h:99
IO.h
souffle::equal_ptr
bool equal_ptr(const T *a, const T *b)
Compares two values referenced by a pointer where the case where both pointers are null is also consi...
Definition: MiscUtil.h:130
souffle::time_point
std::chrono::high_resolution_clock::time_point time_point
Definition: MiscUtil.h:85
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle
Definition: AggregateOp.h:25
p
a horizontalBars(j=m=void 0===a.axisX.type?new c.AutoScaleAxis(c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})):a.axisX.type.call(c, c.Axis.units.x, b.normalized.series, o, c.extend({}, a.axisX,{highLow:d, referenceValue:0})), l=n=void 0===a.axisY.type?new c.StepAxis(c.Axis.units.y, b.normalized.series, o,{ticks:k}):a.axisY.type.call(c, c.Axis.units.y, b.normalized.series, o, a.axisY)) var p
Definition: htmlJsChartistMin.h:15