Halide
Util.h
Go to the documentation of this file.
1 // Always use assert, even if llvm-config defines NDEBUG
2 #ifdef NDEBUG
3 #undef NDEBUG
4 #include <assert.h>
5 #define NDEBUG
6 #else
7 #include <assert.h>
8 #endif
9 
10 #ifndef HALIDE_UTIL_H
11 #define HALIDE_UTIL_H
12 
13 /** \file
14  * Various utility functions used internally Halide. */
15 
16 #include <cstdint>
17 #include <cstring>
18 #include <limits>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "runtime/HalideRuntime.h"
24 
25 #ifdef Halide_STATIC_DEFINE
26 #define HALIDE_EXPORT
27 #else
28 #if defined(_MSC_VER)
29 // Halide_EXPORTS is quietly defined by CMake when building a shared library
30 #ifdef Halide_EXPORTS
31 #define HALIDE_EXPORT __declspec(dllexport)
32 #else
33 #define HALIDE_EXPORT __declspec(dllimport)
34 #endif
35 #else
36 #define HALIDE_EXPORT __attribute__((visibility("default")))
37 #endif
38 #endif
39 
40 // If we're in user code, we don't want certain functions to be inlined.
41 #if defined(COMPILING_HALIDE) || defined(BUILDING_PYTHON)
42 #define HALIDE_NO_USER_CODE_INLINE
43 #else
44 #define HALIDE_NO_USER_CODE_INLINE HALIDE_NEVER_INLINE
45 #endif
46 
47 // On windows, Halide needs a larger stack than the default MSVC provides
48 #ifdef _MSC_VER
49 #pragma comment(linker, "/STACK:8388608,1048576")
50 #endif
51 
52 namespace Halide {
53 
54 /** Load a plugin in the form of a dynamic library (e.g. for custom autoschedulers).
55  * If the string doesn't contain any . characters, the proper prefix and/or suffix
56  * for the platform will be added:
57  *
58  * foo -> libfoo.so (Linux/OSX/etc -- note that .dylib is not supported)
59  * foo -> foo.dll (Windows)
60  *
61  * otherwise, it is assumed to be an appropriate pathname.
62  *
63  * Any error in loading will assert-fail. */
64 void load_plugin(const std::string &lib_name);
65 
66 namespace Internal {
67 
68 /** Some numeric conversions are UB if the value won't fit in the result;
69  * safe_numeric_cast<>() is meant as a drop-in replacement for a C/C++ cast
70  * that adds well-defined behavior for the UB cases, attempting to mimic
71  * common implementation behavior as much as possible.
72  */
73 template<typename DST, typename SRC,
74  typename std::enable_if<std::is_floating_point<SRC>::value>::type * = nullptr>
75 DST safe_numeric_cast(SRC s) {
76  if (std::is_integral<DST>::value) {
77  // Treat float -> int as a saturating cast; this is handled
78  // in different ways by different compilers, so an arbitrary but safe
79  // choice like this is reasonable.
80  if (s < (SRC)std::numeric_limits<DST>::min()) {
82  }
83  if (s > (SRC)std::numeric_limits<DST>::max()) {
85  }
86  }
87  return (DST)s;
88 }
89 
90 template<typename DST, typename SRC,
91  typename std::enable_if<std::is_integral<SRC>::value>::type * = nullptr>
92 DST safe_numeric_cast(SRC s) {
93  if (std::is_integral<DST>::value) {
94  // any-int -> signed-int is technically UB if value won't fit;
95  // in practice, common compilers implement such conversions as done below
96  // (as verified by exhaustive testing on Clang for x86-64). We could
97  // probably continue to rely on that behavior, but making it explicit
98  // avoids possible wrather of UBSan and similar debug helpers.
99  // (Yes, using sizeof for this comparison is a little odd for the uint->int
100  // case, but the intent is to match existing common behavior, which this does.)
101  if (std::is_integral<SRC>::value && std::is_signed<DST>::value && sizeof(DST) < sizeof(SRC)) {
102  using UnsignedSrc = typename std::make_unsigned<SRC>::type;
103  return (DST)(s & (UnsignedSrc)(-1));
104  }
105  }
106  return (DST)s;
107 }
108 
109 /** An aggressive form of reinterpret cast used for correct type-punning. */
110 template<typename DstType, typename SrcType>
111 DstType reinterpret_bits(const SrcType &src) {
112  static_assert(sizeof(SrcType) == sizeof(DstType), "Types must be same size");
113  DstType dst;
114  memcpy(&dst, &src, sizeof(SrcType));
115  return dst;
116 }
117 
118 /** Make a unique name for an object based on the name of the stack
119  * variable passed in. If introspection isn't working or there are no
120  * debug symbols, just uses unique_name with the given prefix. */
121 std::string make_entity_name(void *stack_ptr, const std::string &type, char prefix);
122 
123 /** Get value of an environment variable. Returns its value
124  * is defined in the environment. If the var is not defined, an empty string
125  * is returned.
126  */
127 std::string get_env_variable(char const *env_var_name);
128 
129 /** Get the name of the currently running executable. Platform-specific.
130  * If program name cannot be retrieved, function returns an empty string. */
131 std::string running_program_name();
132 
133 /** Generate a unique name starting with the given prefix. It's unique
134  * relative to all other strings returned by unique_name in this
135  * process.
136  *
137  * The single-character version always appends a numeric suffix to the
138  * character.
139  *
140  * The string version will either return the input as-is (with high
141  * probability on the first time it is called with that input), or
142  * replace any existing '$' characters with underscores, then add a
143  * '$' sign and a numeric suffix to it.
144  *
145  * Note that unique_name('f') therefore differs from
146  * unique_name("f"). The former returns something like f123, and the
147  * latter returns either f or f$123.
148  */
149 // @{
150 std::string unique_name(char prefix);
151 std::string unique_name(const std::string &prefix);
152 // @}
153 
154 /** Test if the first string starts with the second string */
155 bool starts_with(const std::string &str, const std::string &prefix);
156 
157 /** Test if the first string ends with the second string */
158 bool ends_with(const std::string &str, const std::string &suffix);
159 
160 /** Replace all matches of the second string in the first string with the last string */
161 std::string replace_all(const std::string &str, const std::string &find, const std::string &replace);
162 
163 /** Split the source string using 'delim' as the divider. */
164 std::vector<std::string> split_string(const std::string &source, const std::string &delim);
165 
166 /** Perform a left fold of a vector. Returns a default-constructed
167  * vector element if the vector is empty. Similar to std::accumulate
168  * but with a less clunky syntax. */
169 template<typename T, typename Fn>
170 T fold_left(const std::vector<T> &vec, Fn f) {
171  T result;
172  if (vec.empty()) {
173  return result;
174  }
175  result = vec[0];
176  for (size_t i = 1; i < vec.size(); i++) {
177  result = f(result, vec[i]);
178  }
179  return result;
180 }
181 
182 /** Returns a right fold of a vector. Returns a default-constructed
183  * vector element if the vector is empty. */
184 template<typename T, typename Fn>
185 T fold_right(const std::vector<T> &vec, Fn f) {
186  T result;
187  if (vec.empty()) {
188  return result;
189  }
190  result = vec.back();
191  for (size_t i = vec.size() - 1; i > 0; i--) {
192  result = f(vec[i - 1], result);
193  }
194  return result;
195 }
196 
197 template<typename... T>
198 struct meta_and : std::true_type {};
199 
200 template<typename T1, typename... Args>
201 struct meta_and<T1, Args...> : std::integral_constant<bool, T1::value && meta_and<Args...>::value> {};
202 
203 template<typename... T>
204 struct meta_or : std::false_type {};
205 
206 template<typename T1, typename... Args>
207 struct meta_or<T1, Args...> : std::integral_constant<bool, T1::value || meta_or<Args...>::value> {};
208 
209 template<typename To, typename... Args>
210 struct all_are_convertible : meta_and<std::is_convertible<Args, To>...> {};
211 
212 /** Returns base name and fills in namespaces, outermost one first in vector. */
213 std::string extract_namespaces(const std::string &name, std::vector<std::string> &namespaces);
214 
215 struct FileStat {
217  uint32_t mod_time; // Unix epoch time
221 };
222 
223 /** Create a unique file with a name of the form prefixXXXXXsuffix in an arbitrary
224  * (but writable) directory; this is typically /tmp, but the specific
225  * location is not guaranteed. (Note that the exact form of the file name
226  * may vary; in particular, the suffix may be ignored on Windows.)
227  * The file is created (but not opened), thus this can be called from
228  * different threads (or processes, e.g. when building with parallel make)
229  * without risking collision. Note that if this file is used as a temporary
230  * file, the caller is responsibly for deleting it. Neither the prefix nor suffix
231  * may contain a directory separator.
232  */
233 std::string file_make_temp(const std::string &prefix, const std::string &suffix);
234 
235 /** Create a unique directory in an arbitrary (but writable) directory; this is
236  * typically somewhere inside /tmp, but the specific location is not guaranteed.
237  * The directory will be empty (i.e., this will never return /tmp itself,
238  * but rather a new directory inside /tmp). The caller is responsible for removing the
239  * directory after use.
240  */
241 std::string dir_make_temp();
242 
243 /** Wrapper for access(). Quietly ignores errors. */
244 bool file_exists(const std::string &name);
245 
246 /** assert-fail if the file doesn't exist. useful primarily for testing purposes. */
247 void assert_file_exists(const std::string &name);
248 
249 /** assert-fail if the file DOES exist. useful primarily for testing purposes. */
250 void assert_no_file_exists(const std::string &name);
251 
252 /** Wrapper for unlink(). Asserts upon error. */
253 void file_unlink(const std::string &name);
254 
255 /** Wrapper for unlink(). Quietly ignores errors. */
256 void file_unlink(const std::string &name);
257 
258 /** Ensure that no file with this path exists. If such a file
259  * exists and cannot be removed, assert-fail. */
260 void ensure_no_file_exists(const std::string &name);
261 
262 /** Wrapper for rmdir(). Asserts upon error. */
263 void dir_rmdir(const std::string &name);
264 
265 /** Wrapper for stat(). Asserts upon error. */
266 FileStat file_stat(const std::string &name);
267 
268 /** Read the entire contents of a file into a vector<char>. The file
269  * is read in binary mode. Errors trigger an assertion failure. */
270 std::vector<char> read_entire_file(const std::string &pathname);
271 
272 /** Create or replace the contents of a file with a given pointer-and-length
273  * of memory. If the file doesn't exist, it is created; if it does exist, it
274  * is completely overwritten. Any error triggers an assertion failure. */
275 void write_entire_file(const std::string &pathname, const void *source, size_t source_len);
276 
277 inline void write_entire_file(const std::string &pathname, const std::vector<char> &source) {
278  write_entire_file(pathname, source.data(), source.size());
279 }
280 
281 /** A simple utility class that creates a temporary file in its ctor and
282  * deletes that file in its dtor; this is useful for temporary files that you
283  * want to ensure are deleted when exiting a certain scope. Since this is essentially
284  * just an RAII wrapper around file_make_temp() and file_unlink(), it has the same
285  * failure modes (i.e.: assertion upon error).
286  */
287 class TemporaryFile final {
288 public:
289  TemporaryFile(const std::string &prefix, const std::string &suffix)
290  : temp_path(file_make_temp(prefix, suffix)), do_unlink(true) {
291  }
292  const std::string &pathname() const {
293  return temp_path;
294  }
296  if (do_unlink) {
297  file_unlink(temp_path);
298  }
299  }
300  // You can call this if you want to defeat the automatic deletion;
301  // this is rarely what you want to do (since it defeats the purpose
302  // of this class), but can be quite handy for debugging purposes.
303  void detach() {
304  do_unlink = false;
305  }
306 
307 private:
308  const std::string temp_path;
309  bool do_unlink;
310  TemporaryFile(const TemporaryFile &) = delete;
311  void operator=(const TemporaryFile &) = delete;
312 };
313 
314 /** Routines to test if math would overflow for signed integers with
315  * the given number of bits. */
316 // @{
317 bool add_would_overflow(int bits, int64_t a, int64_t b);
318 bool sub_would_overflow(int bits, int64_t a, int64_t b);
319 bool mul_would_overflow(int bits, int64_t a, int64_t b);
320 // @}
321 
322 /** Helper class for saving/restoring variable values on the stack, to allow
323  * for early-exit that preserves correctness */
324 template<typename T>
325 struct ScopedValue {
326  T &var;
328  /** Preserve the old value, restored at dtor time */
330  : var(var), old_value(var) {
331  }
332  /** Preserve the old value, then set the var to a new value. */
333  ScopedValue(T &var, T new_value)
334  : var(var), old_value(var) {
335  var = new_value;
336  }
338  var = old_value;
339  }
340  operator T() const {
341  return old_value;
342  }
343  // allow move but not copy
344  ScopedValue(const ScopedValue &that) = delete;
345  ScopedValue(ScopedValue &&that) noexcept = default;
346 };
347 
348 // Wrappers for some C++14-isms that are useful and trivially implementable
349 // in C++11; these are defined in the Halide::Internal namespace. If we
350 // are compiling under C++14 or later, we just use the standard implementations
351 // rather than our own.
352 #if __cplusplus >= 201402L
353 
354 // C++14: Use the standard implementations
355 using std::index_sequence;
356 using std::integer_sequence;
359 
360 #else
361 
362 // C++11: std::integer_sequence (etc) is standard in C++14 but not C++11, but
363 // is easily written in C++11. This is a simple version that could
364 // probably be improved.
365 
366 template<typename T, T... Ints>
368  static constexpr size_t size() {
369  return sizeof...(Ints);
370  }
371 };
372 
373 template<typename T>
375 
376 template<typename T, T... Ints>
378  using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
379 };
380 
381 template<typename T, T I, T N>
383  using type = typename next_integer_sequence<
385 };
386 
387 template<typename T, T N>
390 };
391 
392 template<typename T, T N>
394 
395 template<size_t... Ints>
397 
398 template<size_t N>
400 
401 #endif
402 
403 // Helpers for timing blocks of code. Put 'TIC;' at the start and
404 // 'TOC;' at the end. Timing is reported at the toc via
405 // debug(0). The calls can be nested and will pretty-print
406 // appropriately. Took this idea from matlab via Jon Barron.
407 //
408 // Note that this uses global state internally, and is not thread-safe
409 // at all. Only use it for single-threaded debugging sessions.
410 
411 void halide_tic_impl(const char *file, int line);
412 void halide_toc_impl(const char *file, int line);
413 #define HALIDE_TIC Halide::Internal::halide_tic_impl(__FILE__, __LINE__)
414 #define HALIDE_TOC Halide::Internal::halide_toc_impl(__FILE__, __LINE__)
415 #ifdef COMPILING_HALIDE
416 #define TIC HALIDE_TIC
417 #define TOC HALIDE_TOC
418 #endif
419 
420 // statically cast a value from one type to another: this is really just
421 // some syntactic sugar around static_cast<>() to avoid compiler warnings
422 // regarding 'bool' in some compliation configurations.
423 template<typename TO>
424 struct StaticCast {
425  template<typename FROM, typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * = nullptr>
426  inline constexpr static TO2 value(const FROM &from) {
427  return static_cast<TO2>(from);
428  }
429 
430  template<typename FROM, typename TO2 = TO, typename std::enable_if<std::is_same<TO2, bool>::value>::type * = nullptr>
431  inline constexpr static TO2 value(const FROM &from) {
432  return from != 0;
433  }
434 };
435 
436 // Like std::is_convertible, but with additional tests for arithmetic types:
437 // ensure that the value will roundtrip losslessly (e.g., no integer truncation
438 // or dropping of fractional parts).
439 template<typename TO>
441  template<typename FROM, typename TO2 = TO, typename std::enable_if<!std::is_convertible<FROM, TO>::value>::type * = nullptr>
442  inline constexpr static bool value(const FROM &from) {
443  return false;
444  }
445 
446  template<typename FROM, typename TO2 = TO, typename std::enable_if<std::is_convertible<FROM, TO>::value && std::is_arithmetic<TO>::value && std::is_arithmetic<FROM>::value && !std::is_same<TO, FROM>::value>::type * = nullptr>
447  inline constexpr static bool value(const FROM &from) {
448  return StaticCast<FROM>::value(StaticCast<TO>::value(from)) == from;
449  }
450 
451  template<typename FROM, typename TO2 = TO, typename std::enable_if<std::is_convertible<FROM, TO>::value && !(std::is_arithmetic<TO>::value && std::is_arithmetic<FROM>::value && !std::is_same<TO, FROM>::value)>::type * = nullptr>
452  inline constexpr static bool value(const FROM &from) {
453  return true;
454  }
455 };
456 
457 /** Emit a version of a string that is a valid identifier in C (. is replaced with _) */
458 std::string c_print_name(const std::string &name);
459 
460 /** Return the LLVM_VERSION against which this libHalide is compiled. This is provided
461  * only for internal tests which need to verify behavior; please don't use this outside
462  * of Halide tests. */
463 int get_llvm_version();
464 
465 } // namespace Internal
466 } // namespace Halide
467 
468 #endif
Halide::Internal::TemporaryFile::pathname
const std::string & pathname() const
Definition: Util.h:292
Halide::Internal::all_are_convertible
Definition: Util.h:210
Halide::Internal::c_print_name
std::string c_print_name(const std::string &name)
Emit a version of a string that is a valid identifier in C (.
Halide::Internal::running_program_name
std::string running_program_name()
Get the name of the currently running executable.
Halide::Internal::sub_would_overflow
bool sub_would_overflow(int bits, int64_t a, int64_t b)
Halide::Internal::halide_tic_impl
void halide_tic_impl(const char *file, int line)
Halide::Internal::FileStat
Definition: Util.h:215
Halide::Internal::make_integer_sequence_helper::type
typename next_integer_sequence< typename make_integer_sequence_helper< T, I+1, N >::type >::type type
Definition: Util.h:384
Halide::Internal::next_integer_sequence
Definition: Util.h:374
Halide::Internal::replace_all
std::string replace_all(const std::string &str, const std::string &find, const std::string &replace)
Replace all matches of the second string in the first string with the last string.
Halide::min
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:577
Halide::Internal::split_string
std::vector< std::string > split_string(const std::string &source, const std::string &delim)
Split the source string using 'delim' as the divider.
Halide::Internal::make_entity_name
std::string make_entity_name(void *stack_ptr, const std::string &type, char prefix)
Make a unique name for an object based on the name of the stack variable passed in.
Halide::Internal::get_env_variable
std::string get_env_variable(char const *env_var_name)
Get value of an environment variable.
Definition: halide_test_dirs.h:26
Halide::Internal::meta_and
Definition: Util.h:198
Halide::Internal::extract_namespaces
std::string extract_namespaces(const std::string &name, std::vector< std::string > &namespaces)
Returns base name and fills in namespaces, outermost one first in vector.
Halide::Internal::ScopedValue
Helper class for saving/restoring variable values on the stack, to allow for early-exit that preserve...
Definition: Util.h:325
Halide::Internal::ScopedValue::~ScopedValue
~ScopedValue()
Definition: Util.h:337
Halide::Internal::dir_rmdir
void dir_rmdir(const std::string &name)
Wrapper for rmdir().
Halide::Internal::StaticCast
Definition: Util.h:424
Halide::Internal::read_entire_file
std::vector< char > read_entire_file(const std::string &pathname)
Read the entire contents of a file into a vector<char>.
Halide::Internal::file_make_temp
std::string file_make_temp(const std::string &prefix, const std::string &suffix)
Create a unique file with a name of the form prefixXXXXXsuffix in an arbitrary (but writable) directo...
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition: runtime_internal.h:19
Halide::Internal::add_would_overflow
bool add_would_overflow(int bits, int64_t a, int64_t b)
Routines to test if math would overflow for signed integers with the given number of bits.
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AddAtomicMutex.h:21
Halide::Internal::StaticCast::value
constexpr static TO2 value(const FROM &from)
Definition: Util.h:426
Halide::Internal::ensure_no_file_exists
void ensure_no_file_exists(const std::string &name)
Ensure that no file with this path exists.
Halide::Internal::ScopedValue::ScopedValue
ScopedValue(T &var, T new_value)
Preserve the old value, then set the var to a new value.
Definition: Util.h:333
Halide::Internal::FileStat::gid
uint32_t gid
Definition: Util.h:219
Halide::Internal::make_index_sequence
make_integer_sequence< size_t, N > make_index_sequence
Definition: Util.h:399
Halide::Internal::write_entire_file
void write_entire_file(const std::string &pathname, const void *source, size_t source_len)
Create or replace the contents of a file with a given pointer-and-length of memory.
Halide::Internal::file_stat
FileStat file_stat(const std::string &name)
Wrapper for stat().
size_t
__SIZE_TYPE__ size_t
Definition: runtime_internal.h:27
Halide::Internal::fold_right
T fold_right(const std::vector< T > &vec, Fn f)
Returns a right fold of a vector.
Definition: Util.h:185
Halide::Internal::file_unlink
void file_unlink(const std::string &name)
Wrapper for unlink().
Halide::Internal::index_sequence
integer_sequence< size_t, Ints... > index_sequence
Definition: Util.h:396
Halide::Internal::assert_no_file_exists
void assert_no_file_exists(const std::string &name)
assert-fail if the file DOES exist.
Halide::Internal::TemporaryFile::detach
void detach()
Definition: Util.h:303
Halide::Internal::safe_numeric_cast
DST safe_numeric_cast(SRC s)
Some numeric conversions are UB if the value won't fit in the result; safe_numeric_cast<>() is meant ...
Definition: Util.h:75
Halide::Internal::dir_make_temp
std::string dir_make_temp()
Create a unique directory in an arbitrary (but writable) directory; this is typically somewhere insid...
Halide::Internal::starts_with
bool starts_with(const std::string &str, const std::string &prefix)
Test if the first string starts with the second string.
Halide::Internal::FileStat::mode
uint32_t mode
Definition: Util.h:220
int64_t
signed __INT64_TYPE__ int64_t
Definition: runtime_internal.h:18
Halide::Internal::FileStat::file_size
uint64_t file_size
Definition: Util.h:216
Halide::Internal::FileStat::uid
uint32_t uid
Definition: Util.h:218
Halide::Internal::ScopedValue::ScopedValue
ScopedValue(T &var)
Preserve the old value, restored at dtor time.
Definition: Util.h:329
Halide::Internal::integer_sequence
Definition: Util.h:367
Halide::Internal::TemporaryFile::~TemporaryFile
~TemporaryFile()
Definition: Util.h:295
Halide::Internal::halide_toc_impl
void halide_toc_impl(const char *file, int line)
Halide::Internal::fold_left
T fold_left(const std::vector< T > &vec, Fn f)
Perform a left fold of a vector.
Definition: Util.h:170
Halide::Internal::reinterpret_bits
DstType reinterpret_bits(const SrcType &src)
An aggressive form of reinterpret cast used for correct type-punning.
Definition: Util.h:111
dst
char * dst
Definition: printer.h:32
HalideRuntime.h
memcpy
void * memcpy(void *s1, const void *s2, size_t n)
Halide::Internal::TemporaryFile
A simple utility class that creates a temporary file in its ctor and deletes that file in its dtor; t...
Definition: Util.h:287
Halide::Internal::ScopedValue::old_value
T old_value
Definition: Util.h:327
Halide::Internal::make_integer_sequence
typename make_integer_sequence_helper< T, 0, N >::type make_integer_sequence
Definition: Util.h:393
Halide::Internal::ends_with
bool ends_with(const std::string &str, const std::string &suffix)
Test if the first string ends with the second string.
Halide::Internal::IsRoundtrippable
Definition: Util.h:440
Halide::Internal::FileStat::mod_time
uint32_t mod_time
Definition: Util.h:217
Halide::load_plugin
void load_plugin(const std::string &lib_name)
Load a plugin in the form of a dynamic library (e.g.
Halide::Internal::make_integer_sequence_helper
Definition: Util.h:382
Halide::Internal::mul_would_overflow
bool mul_would_overflow(int bits, int64_t a, int64_t b)
Halide::Internal::meta_or
Definition: Util.h:204
Halide::Internal::unique_name
std::string unique_name(char prefix)
Generate a unique name starting with the given prefix.
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:21
Halide::Internal::integer_sequence::size
static constexpr size_t size()
Definition: Util.h:368
Halide::max
Expr max(const FuncRef &a, const FuncRef &b)
Definition: Func.h:580
Halide::Internal::file_exists
bool file_exists(const std::string &name)
Wrapper for access().
Halide::Internal::ScopedValue::var
T & var
Definition: Util.h:326
Halide::Internal::TemporaryFile::TemporaryFile
TemporaryFile(const std::string &prefix, const std::string &suffix)
Definition: Util.h:289
Halide::Internal::get_llvm_version
int get_llvm_version()
Return the LLVM_VERSION against which this libHalide is compiled.
Halide::Internal::IsRoundtrippable::value
constexpr static bool value(const FROM &from)
Definition: Util.h:442
Halide::Internal::assert_file_exists
void assert_file_exists(const std::string &name)
assert-fail if the file doesn't exist.