Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright 2008-2009 Katholieke Universiteit Leuven
      3  *
      4  * Use of this software is governed by the MIT license
      5  *
      6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
      7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      8  */
      9 
     10 #include <isl_ctx_private.h>
     11 #include <isl/vec.h>
     12 #include <isl_options_private.h>
     13 
     14 #define __isl_calloc(type,size)		((type *)calloc(1, size))
     15 #define __isl_calloc_type(type)		__isl_calloc(type,sizeof(type))
     16 
     17 /* Construct an isl_stat indicating whether "obj" is non-NULL.
     18  *
     19  * That is, return isl_stat_ok if "obj" is non_NULL and
     20  * isl_stat_error otherwise.
     21  */
     22 isl_stat isl_stat_non_null(void *obj)
     23 {
     24 	if (obj != NULL)
     25 		return isl_stat_ok;
     26 	return isl_stat_error;
     27 }
     28 
     29 /* Return the negation of "b", where the negation of isl_bool_error
     30  * is isl_bool_error again.
     31  */
     32 isl_bool isl_bool_not(isl_bool b)
     33 {
     34 	if (b < 0)
     35 		return isl_bool_error;
     36 	if (b == isl_bool_false)
     37 		return isl_bool_true;
     38 	return isl_bool_false;
     39 }
     40 
     41 /* Create an isl_bool from an integer.
     42  *
     43  * Return isl_bool_false if b is zero, otherwise return isl_bool_true.
     44  * This function never returns isl_bool_error.
     45  */
     46 isl_bool isl_bool_ok(int b)
     47 {
     48 	if (b)
     49 		return isl_bool_true;
     50 	return isl_bool_false;
     51 }
     52 
     53 /* Check that the result of an allocation ("p") is not NULL and
     54  * complain if it is.
     55  * The only exception is when allocation size ("size") is equal to zero.
     56  */
     57 static void *check_non_null(isl_ctx *ctx, void *p, size_t size)
     58 {
     59 	if (p || size == 0)
     60 		return p;
     61 	isl_die(ctx, isl_error_alloc, "allocation failure", return NULL);
     62 }
     63 
     64 /* Prepare for performing the next "operation" in the context.
     65  * Return 0 if we are allowed to perform this operation and
     66  * return -1 if we should abort the computation.
     67  *
     68  * In particular, we should stop if the user has explicitly aborted
     69  * the computation or if the maximal number of operations has been exceeded.
     70  */
     71 int isl_ctx_next_operation(isl_ctx *ctx)
     72 {
     73 	if (!ctx)
     74 		return -1;
     75 	if (ctx->abort) {
     76 		isl_ctx_set_error(ctx, isl_error_abort);
     77 		return -1;
     78 	}
     79 	if (ctx->max_operations && ctx->operations >= ctx->max_operations)
     80 		isl_die(ctx, isl_error_quota,
     81 			"maximal number of operations exceeded", return -1);
     82 	ctx->operations++;
     83 	return 0;
     84 }
     85 
     86 /* Call malloc and complain if it fails.
     87  * If ctx is NULL, then return NULL.
     88  */
     89 void *isl_malloc_or_die(isl_ctx *ctx, size_t size)
     90 {
     91 	if (isl_ctx_next_operation(ctx) < 0)
     92 		return NULL;
     93 	return ctx ? check_non_null(ctx, malloc(size), size) : NULL;
     94 }
     95 
     96 /* Call calloc and complain if it fails.
     97  * If ctx is NULL, then return NULL.
     98  */
     99 void *isl_calloc_or_die(isl_ctx *ctx, size_t nmemb, size_t size)
    100 {
    101 	if (isl_ctx_next_operation(ctx) < 0)
    102 		return NULL;
    103 	return ctx ? check_non_null(ctx, calloc(nmemb, size), nmemb) : NULL;
    104 }
    105 
    106 /* Call realloc and complain if it fails.
    107  * If ctx is NULL, then return NULL.
    108  */
    109 void *isl_realloc_or_die(isl_ctx *ctx, void *ptr, size_t size)
    110 {
    111 	if (isl_ctx_next_operation(ctx) < 0)
    112 		return NULL;
    113 	return ctx ? check_non_null(ctx, realloc(ptr, size), size) : NULL;
    114 }
    115 
    116 /* Keep track of all information about the current error ("error", "msg",
    117  * "file", "line") in "ctx".
    118  */
    119 void isl_ctx_set_full_error(isl_ctx *ctx, enum isl_error error, const char *msg,
    120 	const char *file, int line)
    121 {
    122 	if (!ctx)
    123 		return;
    124 	ctx->error = error;
    125 	ctx->error_msg = msg;
    126 	ctx->error_file = file;
    127 	ctx->error_line = line;
    128 }
    129 
    130 void isl_handle_error(isl_ctx *ctx, enum isl_error error, const char *msg,
    131 	const char *file, int line)
    132 {
    133 	if (!ctx)
    134 		return;
    135 
    136 	isl_ctx_set_full_error(ctx, error, msg, file, line);
    137 
    138 	switch (ctx->opt->on_error) {
    139 	case ISL_ON_ERROR_WARN:
    140 		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
    141 		return;
    142 	case ISL_ON_ERROR_CONTINUE:
    143 		return;
    144 	case ISL_ON_ERROR_ABORT:
    145 		fprintf(stderr, "%s:%d: %s\n", file, line, msg);
    146 		abort();
    147 		return;
    148 	}
    149 }
    150 
    151 static struct isl_options *find_nested_options(struct isl_args *args,
    152 	void *opt, struct isl_args *wanted)
    153 {
    154 	int i;
    155 	struct isl_options *options;
    156 
    157 	if (args == wanted)
    158 		return opt;
    159 
    160 	for (i = 0; args->args[i].type != isl_arg_end; ++i) {
    161 		struct isl_arg *arg = &args->args[i];
    162 		void *child;
    163 
    164 		if (arg->type != isl_arg_child)
    165 			continue;
    166 
    167 		if (arg->offset == ISL_ARG_OFFSET_NONE)
    168 			child = opt;
    169 		else
    170 			child = *(void **)(((char *)opt) + arg->offset);
    171 
    172 		options = find_nested_options(arg->u.child.child,
    173 						child, wanted);
    174 		if (options)
    175 			return options;
    176 	}
    177 
    178 	return NULL;
    179 }
    180 
    181 static struct isl_options *find_nested_isl_options(struct isl_args *args,
    182 	void *opt)
    183 {
    184 	return find_nested_options(args, opt, &isl_options_args);
    185 }
    186 
    187 void *isl_ctx_peek_options(isl_ctx *ctx, struct isl_args *args)
    188 {
    189 	if (!ctx)
    190 		return NULL;
    191 	if (args == &isl_options_args)
    192 		return ctx->opt;
    193 	return find_nested_options(ctx->user_args, ctx->user_opt, args);
    194 }
    195 
    196 isl_ctx *isl_ctx_alloc_with_options(struct isl_args *args, void *user_opt)
    197 {
    198 	struct isl_ctx *ctx = NULL;
    199 	struct isl_options *opt = NULL;
    200 	int opt_allocated = 0;
    201 
    202 	if (!user_opt)
    203 		return NULL;
    204 
    205 	opt = find_nested_isl_options(args, user_opt);
    206 	if (!opt) {
    207 		opt = isl_options_new_with_defaults();
    208 		if (!opt)
    209 			goto error;
    210 		opt_allocated = 1;
    211 	}
    212 
    213 	ctx = __isl_calloc_type(struct isl_ctx);
    214 	if (!ctx)
    215 		goto error;
    216 
    217 	if (isl_hash_table_init(ctx, &ctx->id_table, 0))
    218 		goto error;
    219 
    220 	ctx->stats = isl_calloc_type(ctx, struct isl_stats);
    221 	if (!ctx->stats)
    222 		goto error;
    223 
    224 	ctx->user_args = args;
    225 	ctx->user_opt = user_opt;
    226 	ctx->opt_allocated = opt_allocated;
    227 	ctx->opt = opt;
    228 	ctx->ref = 0;
    229 
    230 	isl_int_init(ctx->zero);
    231 	isl_int_set_si(ctx->zero, 0);
    232 
    233 	isl_int_init(ctx->one);
    234 	isl_int_set_si(ctx->one, 1);
    235 
    236 	isl_int_init(ctx->two);
    237 	isl_int_set_si(ctx->two, 2);
    238 
    239 	isl_int_init(ctx->negone);
    240 	isl_int_set_si(ctx->negone, -1);
    241 
    242 	isl_int_init(ctx->normalize_gcd);
    243 
    244 	ctx->n_cached = 0;
    245 	ctx->n_miss = 0;
    246 
    247 	isl_ctx_reset_error(ctx);
    248 
    249 	ctx->operations = 0;
    250 	isl_ctx_set_max_operations(ctx, ctx->opt->max_operations);
    251 
    252 	return ctx;
    253 error:
    254 	isl_args_free(args, user_opt);
    255 	if (opt_allocated)
    256 		isl_options_free(opt);
    257 	free(ctx);
    258 	return NULL;
    259 }
    260 
    261 struct isl_ctx *isl_ctx_alloc()
    262 {
    263 	struct isl_options *opt;
    264 
    265 	opt = isl_options_new_with_defaults();
    266 
    267 	return isl_ctx_alloc_with_options(&isl_options_args, opt);
    268 }
    269 
    270 void isl_ctx_ref(struct isl_ctx *ctx)
    271 {
    272 	ctx->ref++;
    273 }
    274 
    275 void isl_ctx_deref(struct isl_ctx *ctx)
    276 {
    277 	isl_assert(ctx, ctx->ref > 0, return);
    278 	ctx->ref--;
    279 }
    280 
    281 /* Print statistics on usage.
    282  */
    283 static void print_stats(isl_ctx *ctx)
    284 {
    285 	fprintf(stderr, "operations: %lu\n", ctx->operations);
    286 }
    287 
    288 void isl_ctx_free(struct isl_ctx *ctx)
    289 {
    290 	if (!ctx)
    291 		return;
    292 	if (ctx->ref != 0)
    293 		isl_die(ctx, isl_error_invalid,
    294 			"isl_ctx not freed as some objects still reference it",
    295 			return);
    296 
    297 	if (ctx->opt->print_stats)
    298 		print_stats(ctx);
    299 
    300 	isl_hash_table_clear(&ctx->id_table);
    301 	isl_blk_clear_cache(ctx);
    302 	isl_int_clear(ctx->zero);
    303 	isl_int_clear(ctx->one);
    304 	isl_int_clear(ctx->two);
    305 	isl_int_clear(ctx->negone);
    306 	isl_int_clear(ctx->normalize_gcd);
    307 	isl_args_free(ctx->user_args, ctx->user_opt);
    308 	if (ctx->opt_allocated)
    309 		isl_options_free(ctx->opt);
    310 	free(ctx->stats);
    311 	free(ctx);
    312 }
    313 
    314 struct isl_options *isl_ctx_options(isl_ctx *ctx)
    315 {
    316 	if (!ctx)
    317 		return NULL;
    318 	return ctx->opt;
    319 }
    320 
    321 enum isl_error isl_ctx_last_error(isl_ctx *ctx)
    322 {
    323 	return ctx ? ctx->error : isl_error_invalid;
    324 }
    325 
    326 /* Return the error message of the last error in "ctx".
    327  */
    328 const char *isl_ctx_last_error_msg(isl_ctx *ctx)
    329 {
    330 	return ctx ? ctx->error_msg : NULL;
    331 }
    332 
    333 /* Return the file name where the last error in "ctx" occurred.
    334  */
    335 const char *isl_ctx_last_error_file(isl_ctx *ctx)
    336 {
    337 	return ctx ? ctx->error_file : NULL;
    338 }
    339 
    340 /* Return the line number where the last error in "ctx" occurred.
    341  */
    342 int isl_ctx_last_error_line(isl_ctx *ctx)
    343 {
    344 	return ctx ? ctx->error_line : -1;
    345 }
    346 
    347 void isl_ctx_reset_error(isl_ctx *ctx)
    348 {
    349 	if (!ctx)
    350 		return;
    351 	ctx->error = isl_error_none;
    352 	ctx->error_msg = NULL;
    353 	ctx->error_file = NULL;
    354 	ctx->error_line = -1;
    355 }
    356 
    357 void isl_ctx_set_error(isl_ctx *ctx, enum isl_error error)
    358 {
    359 	isl_ctx_set_full_error(ctx, error, NULL, NULL, -1);
    360 }
    361 
    362 void isl_ctx_abort(isl_ctx *ctx)
    363 {
    364 	if (ctx)
    365 		ctx->abort = 1;
    366 }
    367 
    368 void isl_ctx_resume(isl_ctx *ctx)
    369 {
    370 	if (ctx)
    371 		ctx->abort = 0;
    372 }
    373 
    374 int isl_ctx_aborted(isl_ctx *ctx)
    375 {
    376 	return ctx ? ctx->abort : -1;
    377 }
    378 
    379 int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags)
    380 {
    381 	if (!ctx)
    382 		return -1;
    383 	return isl_args_parse(ctx->user_args, argc, argv, ctx->user_opt, flags);
    384 }
    385 
    386 /* Set the maximal number of iterations of "ctx" to "max_operations".
    387  */
    388 void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations)
    389 {
    390 	if (!ctx)
    391 		return;
    392 	ctx->max_operations = max_operations;
    393 }
    394 
    395 /* Return the maximal number of iterations of "ctx".
    396  */
    397 unsigned long isl_ctx_get_max_operations(isl_ctx *ctx)
    398 {
    399 	return ctx ? ctx->max_operations : 0;
    400 }
    401 
    402 /* Reset the number of operations performed by "ctx".
    403  */
    404 void isl_ctx_reset_operations(isl_ctx *ctx)
    405 {
    406 	if (!ctx)
    407 		return;
    408 	ctx->operations = 0;
    409 }
    410