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