Introduce option 'on_error'
authorTobias Grosser <tobias@grosser.es>
Sat, 3 Dec 2011 15:52:35 +0000 (16:52 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Sat, 3 Dec 2011 19:23:42 +0000 (20:23 +0100)
The option on_error defines the behaviour of isl in case of an error.
By default, the option is set to 'warn'. This is the current behaviour
and means isl prints a warning and continues the execution of the
program. We also introduce two new modes: 'continue' and 'abort'.
'continue' does not print any warning, but continues execution and 'abort'
abort the program from within isl.  'abort' is useful for debuggers as
they automatically break at the place of the error condition.

Signed-off-by: Tobias Grosser <tobias@grosser.es>
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/ctx.h
include/isl/options.h
isl_ctx.c
isl_options.c
isl_options_private.h

index 1b4c475..a1f7fb5 100644 (file)
@@ -479,6 +479,49 @@ a C<NULL> value for an C<__isl_take> argument.
 
 =back
 
+=head2 Error Handling
+
+C<isl> supports different ways to react in case a runtime error is triggered.
+Runtime errors arise, e.g., if a function such as C<isl_map_intersect> is called
+with two maps that have incompatible spaces. There are three possible ways
+to react on error: to warn, to continue or to abort.
+
+The default behavior is to warn. In this mode, C<isl> prints a warning, stores
+the last error in the corresponding C<isl_ctx> and the function in which the
+error was triggered returns C<NULL>. An error does not corrupt internal state,
+such that isl can continue to be used. C<isl> also provides functions to
+read the last error and to reset the memory that stores the last error. The
+last error is only stored for information purposes. Its presence does not
+change the behavior of C<isl>. Hence, resetting an error is not required to
+continue to use isl, but only to observe new errors.
+
+       #include <isl/ctx.h>
+       enum isl_error isl_ctx_last_error(isl_ctx *ctx);
+       void isl_ctx_reset_error(isl_ctx *ctx);
+
+Another option is to continue on error. This is similar to warn on error mode,
+except that C<isl> does not print any warning. This allows a program to
+implement its own error reporting.
+
+The last option is to directly abort the execution of the program from within
+the isl library. This makes it obviously impossible to recover from an error,
+but it allows to directly spot the error location. By aborting on error,
+debuggers break at the location the error occurred and can provide a stack
+trace. Other tools that automatically provide stack traces on abort or that do
+not want to continue execution after an error was triggered may also prefer to
+abort on error.
+
+The on error behavior of isl can be specified by calling
+C<isl_options_set_on_error> or by setting the command line option
+C<--isl-on-error>. Valid arguments for the function call are
+C<ISL_ON_ERROR_WARN>, C<ISL_ON_ERROR_CONTINUE> and C<ISL_ON_ERROR_ABORT>. The
+choices for the command line option are C<warn>, C<continue> and C<abort>.
+It is also possible to query the current error mode.
+
+       #include <isl/options.h>
+       int isl_options_set_on_error(isl_ctx *ctx, int val);
+       int isl_options_get_on_error(isl_ctx *ctx);
+
 =head2 Identifiers
 
 Identifiers are used to identify both individual dimensions
index 43e0fc6..814833b 100644 (file)
@@ -120,10 +120,13 @@ typedef struct isl_ctx isl_ctx;
 
 #define isl_die(ctx,errno,msg,code)                                    \
        do {                                                            \
-               isl_ctx_set_error(ctx, errno);                          \
-               fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg);        \
+               isl_handle_error(ctx, errno, msg, __FILE__, __LINE__);  \
                code;                                                   \
        } while (0)
+
+void isl_handle_error(isl_ctx *ctx, int errno, const char *msg,
+       const char *file, int line);
+
 #define isl_assert4(ctx,test,code,errno)                               \
        do {                                                            \
                if (test)                                               \
index 41616ad..1c14b19 100644 (file)
@@ -26,6 +26,12 @@ ISL_ARG_DECL(isl_options, struct isl_options, isl_options_args)
 int isl_options_set_bound(isl_ctx *ctx, int val);
 int isl_options_get_bound(isl_ctx *ctx);
 
+#define                        ISL_ON_ERROR_WARN       0
+#define                        ISL_ON_ERROR_CONTINUE   1
+#define                        ISL_ON_ERROR_ABORT      2
+int isl_options_set_on_error(isl_ctx *ctx, int val);
+int isl_options_get_on_error(isl_ctx *ctx);
+
 int isl_options_set_gbr_only_first(isl_ctx *ctx, int val);
 int isl_options_get_gbr_only_first(isl_ctx *ctx);
 
index b5d5fcf..6f99950 100644 (file)
--- a/isl_ctx.c
+++ b/isl_ctx.c
 #include <isl/vec.h>
 #include <isl/options.h>
 
+void isl_handle_error(isl_ctx *ctx, int errno, const char *msg,
+       const char *file, int line)
+{
+       isl_ctx_set_error(ctx, errno);
+
+       switch (isl_options_get_on_error(ctx)) {
+       case ISL_ON_ERROR_WARN:
+               fprintf(stderr, "%s:%d: %s\n", file, line, msg);
+               return;
+       case ISL_ON_ERROR_CONTINUE:
+               return;
+       case ISL_ON_ERROR_ABORT:
+               fprintf(stderr, "%s:%d: %s\n", file, line, msg);
+               abort();
+               return;
+       }
+}
+
 static struct isl_options *find_nested_options(struct isl_args *args,
        void *opt, struct isl_args *wanted)
 {
index 9ea5829..6301772 100644 (file)
@@ -64,6 +64,13 @@ static struct isl_arg_choice bound[] = {
        {0}
 };
 
+static struct isl_arg_choice on_error[] = {
+       {"warn",        ISL_ON_ERROR_WARN},
+       {"continue",    ISL_ON_ERROR_CONTINUE},
+       {"abort",       ISL_ON_ERROR_ABORT},
+       {0}
+};
+
 static struct isl_arg_flags bernstein_recurse[] = {
        {"none",        ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS, 0},
        {"factors",     ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS,
@@ -106,6 +113,8 @@ ISL_ARG_BOOL(struct isl_options, gbr_only_first, 0, "gbr-only-first", 0,
        "only perform basis reduction in first direction")
 ISL_ARG_CHOICE(struct isl_options, bound, 0, "bound", bound,
        ISL_BOUND_BERNSTEIN, "algorithm to use for computing bounds")
+ISL_ARG_CHOICE(struct isl_options, on_error, 0, "on-error", on_error,
+       ISL_ON_ERROR_WARN, "how to react if an error is detected")
 ISL_ARG_FLAGS(struct isl_options, bernstein_recurse, 0,
        "bernstein-recurse", bernstein_recurse, ISL_BERNSTEIN_FACTORS, NULL)
 ISL_ARG_BOOL(struct isl_options, bernstein_triangulate, 0,
@@ -137,6 +146,11 @@ ISL_ARG_CTX_DEF(isl_options, struct isl_options, isl_options_args)
 ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args, bound)
 ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args, bound)
 
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+       on_error)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+       on_error)
+
 ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
        gbr_only_first)
 ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
index 0c9137c..f49077c 100644 (file)
@@ -31,6 +31,7 @@ struct isl_options {
        unsigned                closure;
 
        int                     bound;
+       unsigned                on_error;
 
        #define                 ISL_BERNSTEIN_FACTORS   1
        #define                 ISL_BERNSTEIN_INTERVALS 2