309 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 *4 * Use of this software is governed by the MIT license5 *6 * Written by Sven Verdoolaege, K.U.Leuven, Departement7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium8 */9 10#include <string.h>11#include <isl_ctx_private.h>12#include <isl_id_private.h>13 14#undef EL_BASE15#define EL_BASE id16 17#include <isl_list_templ.c>18#include <isl_list_read_templ.c>19 20/* A special, static isl_id to use as domains (and ranges)21 * of sets and parameters domains.22 * The user should never get a hold on this isl_id.23 */24isl_id isl_id_none = {25 .ref = -1,26 .ctx = NULL,27 .name = "#none",28 .user = NULL29};30 31isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id)32{33 return id ? id->ctx : NULL;34}35 36void *isl_id_get_user(__isl_keep isl_id *id)37{38 return id ? id->user : NULL;39}40 41const char *isl_id_get_name(__isl_keep isl_id *id)42{43 return id ? id->name : NULL;44}45 46static __isl_give isl_id *id_alloc(isl_ctx *ctx, const char *name, void *user)47{48 const char *copy = name ? strdup(name) : NULL;49 isl_id *id;50 51 if (name && !copy)52 return NULL;53 id = isl_calloc_type(ctx, struct isl_id);54 if (!id)55 goto error;56 57 id->ctx = ctx;58 isl_ctx_ref(id->ctx);59 id->ref = 1;60 id->name = copy;61 id->user = user;62 63 id->hash = isl_hash_init();64 if (name)65 id->hash = isl_hash_string(id->hash, name);66 else67 id->hash = isl_hash_builtin(id->hash, user);68 69 return id;70error:71 free((char *)copy);72 return NULL;73}74 75uint32_t isl_id_get_hash(__isl_keep isl_id *id)76{77 return id ? id->hash : 0;78}79 80struct isl_name_and_user {81 const char *name;82 void *user;83};84 85static isl_bool isl_id_has_name_and_user(const void *entry, const void *val)86{87 isl_id *id = (isl_id *)entry;88 struct isl_name_and_user *nu = (struct isl_name_and_user *) val;89 90 if (id->user != nu->user)91 return isl_bool_false;92 if (id->name == nu->name)93 return isl_bool_true;94 if (!id->name || !nu->name)95 return isl_bool_false;96 97 return isl_bool_ok(!strcmp(id->name, nu->name));98}99 100__isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user)101{102 struct isl_hash_table_entry *entry;103 uint32_t id_hash;104 struct isl_name_and_user nu = { name, user };105 106 if (!ctx)107 return NULL;108 109 id_hash = isl_hash_init();110 if (name)111 id_hash = isl_hash_string(id_hash, name);112 else113 id_hash = isl_hash_builtin(id_hash, user);114 entry = isl_hash_table_find(ctx, &ctx->id_table, id_hash,115 isl_id_has_name_and_user, &nu, 1);116 if (!entry)117 return NULL;118 if (entry->data)119 return isl_id_copy(entry->data);120 entry->data = id_alloc(ctx, name, user);121 if (!entry->data)122 ctx->id_table.n--;123 return entry->data;124}125 126/* If the id has a negative refcount, then it is a static isl_id127 * which should not be changed.128 */129__isl_give isl_id *isl_id_copy(isl_id *id)130{131 if (!id)132 return NULL;133 134 if (id->ref < 0)135 return id;136 137 id->ref++;138 return id;139}140 141/* Compare two isl_ids.142 *143 * The order is fairly arbitrary. We do keep the comparison of144 * the user pointers as a last resort since these pointer values145 * may not be stable across different systems or even different runs.146 */147int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2)148{149 if (id1 == id2)150 return 0;151 if (!id1)152 return -1;153 if (!id2)154 return 1;155 if (!id1->name != !id2->name)156 return !id1->name - !id2->name;157 if (id1->name) {158 int cmp = strcmp(id1->name, id2->name);159 if (cmp != 0)160 return cmp;161 }162 if (id1->user < id2->user)163 return -1;164 else165 return 1;166}167 168static isl_bool isl_id_eq(const void *entry, const void *name)169{170 return isl_bool_ok(entry == name);171}172 173uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id)174{175 if (id)176 isl_hash_hash(hash, id->hash);177 178 return hash;179}180 181/* Replace the free_user callback by "free_user".182 */183__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,184 void (*free_user)(void *user))185{186 if (!id)187 return NULL;188 189 id->free_user = free_user;190 191 return id;192}193 194/* Retrieve the callback set by isl_id_set_free_user,195 * or NULL if no such callback was set.196 */197void (*isl_id_get_free_user(__isl_keep isl_id *id))(void *user)198{199 if (!id)200 return NULL;201 return id->free_user;202}203 204/* If the id has a negative refcount, then it is a static isl_id205 * and should not be freed.206 */207__isl_null isl_id *isl_id_free(__isl_take isl_id *id)208{209 struct isl_hash_table_entry *entry;210 211 if (!id)212 return NULL;213 214 if (id->ref < 0)215 return NULL;216 217 if (--id->ref > 0)218 return NULL;219 220 entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash,221 isl_id_eq, id, 0);222 if (!entry)223 return NULL;224 if (entry == isl_hash_table_entry_none)225 isl_die(id->ctx, isl_error_unknown,226 "unable to find id", (void)0);227 else228 isl_hash_table_remove(id->ctx, &id->ctx->id_table, entry);229 230 if (id->free_user)231 id->free_user(id->user);232 233 free((char *)id->name);234 isl_ctx_deref(id->ctx);235 free(id);236 237 return NULL;238}239 240__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,241 __isl_keep isl_id *id)242{243 if (!id)244 goto error;245 246 if (id->name)247 p = isl_printer_print_str(p, id->name);248 if (id->user) {249 char buffer[50];250 snprintf(buffer, sizeof(buffer), "@%p", id->user);251 p = isl_printer_print_str(p, buffer);252 }253 return p;254error:255 isl_printer_free(p);256 return NULL;257}258 259/* Read an isl_id from "s" based on its name.260 */261__isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s)262{263 struct isl_token *tok;264 char *str;265 isl_ctx *ctx;266 isl_id *id;267 268 if (!s)269 return NULL;270 tok = isl_stream_next_token(s);271 if (!tok) {272 isl_stream_error(s, NULL, "unexpected EOF");273 return NULL;274 }275 ctx = isl_stream_get_ctx(s);276 str = isl_token_get_str(ctx, tok);277 isl_token_free(tok);278 if (!str)279 return NULL;280 id = isl_id_alloc(ctx, str, NULL);281 free(str);282 283 return id;284}285 286#undef TYPE_BASE287#define TYPE_BASE id288#include "isl_read_from_str_templ.c"289 290/* Is "id1" (obviously) equal to "id2"?291 *292 * isl_id objects can be compared by pointer value, but293 * isl_multi_*_plain_is_equal needs an isl_*_plain_is_equal.294 */295static isl_bool isl_id_plain_is_equal(__isl_keep isl_id *id1,296 __isl_keep isl_id *id2)297{298 if (!id1 || !id2)299 return isl_bool_error;300 return id1 == id2;301}302 303#undef BASE304#define BASE id305 306#include <isl_multi_no_domain_templ.c>307#include <isl_multi_no_explicit_domain.c>308#include <isl_multi_templ.c>309