1/// These are automatically generated C++ bindings for isl.
2///
3/// isl is a library for computing with integer sets and maps described by
4/// Presburger formulas. On top of this, isl provides various tools for
5/// polyhedral compilation, ranging from dependence analysis over scheduling
6/// to AST generation.
7
8#ifndef ISL_CPP
9#define ISL_CPP
10
11#include <isl/ctx.h>
12#include <isl/options.h>
13
14#include <functional>
15#include <memory>
16#include <ostream>
17#include <stdexcept>
18#include <string>
19#include <type_traits>
20
21#if __cplusplus >= 201703L
22#include <any>
23#include <optional>
24#endif
25
26/* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
27 * gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
28 * Older versions of gcc (e.g., 4.9) only define __EXCEPTIONS.
29 * If exceptions are not available, any error condition will result
30 * in an abort.
31 */
32#ifndef ISL_USE_EXCEPTIONS
33#if defined(__cpp_exceptions) || defined(_CPPUNWIND) || defined(__EXCEPTIONS)
34#define ISL_USE_EXCEPTIONS	1
35#else
36#define ISL_USE_EXCEPTIONS	0
37#endif
38#endif
39
40namespace isl {
41
42class ctx {
43	isl_ctx *ptr;
44public:
45	/* implicit */ ctx(isl_ctx *ctx) : ptr(ctx) {}
46	isl_ctx *release() {
47		auto tmp = ptr;
48		ptr = nullptr;
49		return tmp;
50	}
51	isl_ctx *get() {
52		return ptr;
53	}
54#if __cplusplus >= 201703L
55	static void free_user(void *user) {
56		std::any *p = static_cast<std::any *>(user);
57		delete p;
58	}
59#endif
60};
61
62/* Macros hiding try/catch.
63 * If exceptions are not available, then no exceptions will be thrown and
64 * there is nothing to catch.
65 */
66#if ISL_USE_EXCEPTIONS
67#define ISL_CPP_TRY		try
68#define ISL_CPP_CATCH_ALL	catch (...)
69#else
70#define ISL_CPP_TRY		if (1)
71#define ISL_CPP_CATCH_ALL	if (0)
72#endif
73
74#if ISL_USE_EXCEPTIONS
75
76/* Class capturing isl errors.
77 *
78 * The what() return value is stored in a reference counted string
79 * to ensure that the copy constructor and the assignment operator
80 * do not throw any exceptions.
81 */
82class exception : public std::exception {
83	std::shared_ptr<std::string> what_str;
84
85protected:
86	inline exception(const char *what_arg, const char *msg,
87		const char *file, int line);
88public:
89	exception() {}
90	exception(const char *what_arg) {
91		what_str = std::make_shared<std::string>(what_arg);
92	}
93	static inline void throw_error(enum isl_error error, const char *msg,
94		const char *file, int line);
95	virtual const char *what() const noexcept {
96		return what_str->c_str();
97	}
98
99	/* Default behavior on error conditions that occur inside isl calls
100	 * performed from inside the bindings.
101	 * In the case exceptions are available, isl should continue
102	 * without printing a warning since the warning message
103	 * will be included in the exception thrown from inside the bindings.
104	 */
105	static constexpr auto on_error = ISL_ON_ERROR_CONTINUE;
106	/* Wrapper for throwing an exception with the given message.
107	 */
108	static void throw_invalid(const char *msg, const char *file, int line) {
109		throw_error(isl_error_invalid, msg, file, line);
110	}
111	static inline void throw_last_error(ctx ctx);
112};
113
114/* Create an exception of a type described by "what_arg", with
115 * error message "msg" in line "line" of file "file".
116 *
117 * Create a string holding the what() return value that
118 * corresponds to what isl would have printed.
119 * If no error message or no error file was set, then use "what_arg" instead.
120 */
121exception::exception(const char *what_arg, const char *msg, const char *file,
122	int line)
123{
124	if (!msg || !file)
125		what_str = std::make_shared<std::string>(what_arg);
126	else
127		what_str = std::make_shared<std::string>(std::string(file) +
128				    ":" + std::to_string(line) + ": " + msg);
129}
130
131class exception_abort : public exception {
132	friend exception;
133	exception_abort(const char *msg, const char *file, int line) :
134		exception("execution aborted", msg, file, line) {}
135};
136
137class exception_alloc : public exception {
138	friend exception;
139	exception_alloc(const char *msg, const char *file, int line) :
140		exception("memory allocation failure", msg, file, line) {}
141};
142
143class exception_unknown : public exception {
144	friend exception;
145	exception_unknown(const char *msg, const char *file, int line) :
146		exception("unknown failure", msg, file, line) {}
147};
148
149class exception_internal : public exception {
150	friend exception;
151	exception_internal(const char *msg, const char *file, int line) :
152		exception("internal error", msg, file, line) {}
153};
154
155class exception_invalid : public exception {
156	friend exception;
157	exception_invalid(const char *msg, const char *file, int line) :
158		exception("invalid argument", msg, file, line) {}
159};
160
161class exception_quota : public exception {
162	friend exception;
163	exception_quota(const char *msg, const char *file, int line) :
164		exception("quota exceeded", msg, file, line) {}
165};
166
167class exception_unsupported : public exception {
168	friend exception;
169	exception_unsupported(const char *msg, const char *file, int line) :
170		exception("unsupported operation", msg, file, line) {}
171};
172
173/* Throw an exception of the class that corresponds to "error", with
174 * error message "msg" in line "line" of file "file".
175 *
176 * isl_error_none is treated as an invalid error type.
177 */
178void exception::throw_error(enum isl_error error, const char *msg,
179	const char *file, int line)
180{
181	switch (error) {
182	case isl_error_none:
183		break;
184	case isl_error_abort: throw exception_abort(msg, file, line);
185	case isl_error_alloc: throw exception_alloc(msg, file, line);
186	case isl_error_unknown: throw exception_unknown(msg, file, line);
187	case isl_error_internal: throw exception_internal(msg, file, line);
188	case isl_error_invalid: throw exception_invalid(msg, file, line);
189	case isl_error_quota: throw exception_quota(msg, file, line);
190	case isl_error_unsupported:
191				throw exception_unsupported(msg, file, line);
192	}
193
194	throw exception_invalid("invalid error type", file, line);
195}
196
197/* Throw an exception corresponding to the last error on "ctx" and
198 * reset the error.
199 *
200 * If "ctx" is NULL or if it is not in an error state at the start,
201 * then an invalid argument exception is thrown.
202 */
203void exception::throw_last_error(ctx ctx)
204{
205	enum isl_error error;
206	const char *msg, *file;
207	int line;
208
209	error = isl_ctx_last_error(ctx.get());
210	msg = isl_ctx_last_error_msg(ctx.get());
211	file = isl_ctx_last_error_file(ctx.get());
212	line = isl_ctx_last_error_line(ctx.get());
213	isl_ctx_reset_error(ctx.get());
214
215	throw_error(error, msg, file, line);
216}
217
218#else
219
220#include <stdio.h>
221#include <stdlib.h>
222
223class exception {
224public:
225	/* Default behavior on error conditions that occur inside isl calls
226	 * performed from inside the bindings.
227	 * In the case exceptions are not available, isl should abort.
228	 */
229	static constexpr auto on_error = ISL_ON_ERROR_ABORT;
230	/* Wrapper for throwing an exception with the given message.
231	 * In the case exceptions are not available, print an error and abort.
232	 */
233	static void throw_invalid(const char *msg, const char *file, int line) {
234		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
235		abort();
236	}
237	/* Throw an exception corresponding to the last
238	 * error on "ctx".
239	 * isl should already abort when an error condition occurs,
240	 * so this function should never be called.
241	 */
242	static void throw_last_error(ctx ctx) {
243		abort();
244	}
245};
246
247#endif
248
249/* Helper class for setting the on_error and resetting the option
250 * to the original value when leaving the scope.
251 */
252class options_scoped_set_on_error {
253	isl_ctx *ctx;
254	int saved_on_error;
255public:
256	options_scoped_set_on_error(class ctx ctx, int on_error) {
257		this->ctx = ctx.get();
258		saved_on_error = isl_options_get_on_error(this->ctx);
259		isl_options_set_on_error(this->ctx, on_error);
260	}
261	~options_scoped_set_on_error() {
262		isl_options_set_on_error(ctx, saved_on_error);
263	}
264};
265
266} // namespace isl
267
268