isl_ctx.c 8.7 KB

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