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 <string.h> 11#include <isl_ctx_private.h> 12#include <isl_id_private.h> 13 14#undef BASE 15#define BASE id 16 17#include <isl_list_templ.c> 18 19/* A special, static isl_id to use as domains (and ranges) 20 * of sets and parameters domains. 21 * The user should never get a hold on this isl_id. 22 */ 23isl_id isl_id_none = { 24 .ref = -1, 25 .ctx = NULL, 26 .name = "#none", 27 .user = NULL 28}; 29 30isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id) 31{ 32 return id ? id->ctx : NULL; 33} 34 35void *isl_id_get_user(__isl_keep isl_id *id) 36{ 37 return id ? id->user : NULL; 38} 39 40const char *isl_id_get_name(__isl_keep isl_id *id) 41{ 42 return id ? id->name : NULL; 43} 44 45static __isl_give isl_id *id_alloc(isl_ctx *ctx, const char *name, void *user) 46{ 47 const char *copy = name ? strdup(name) : NULL; 48 isl_id *id; 49 50 if (name && !copy) 51 return NULL; 52 id = isl_calloc_type(ctx, struct isl_id); 53 if (!id) 54 goto error; 55 56 id->ctx = ctx; 57 isl_ctx_ref(id->ctx); 58 id->ref = 1; 59 id->name = copy; 60 id->user = user; 61 62 id->hash = isl_hash_init(); 63 if (name) 64 id->hash = isl_hash_string(id->hash, name); 65 else 66 id->hash = isl_hash_builtin(id->hash, user); 67 68 return id; 69error: 70 free((char *)copy); 71 return NULL; 72} 73 74struct isl_name_and_user { 75 const char *name; 76 void *user; 77}; 78 79static int isl_id_has_name_and_user(const void *entry, const void *val) 80{ 81 isl_id *id = (isl_id *)entry; 82 struct isl_name_and_user *nu = (struct isl_name_and_user *) val; 83 84 if (id->user != nu->user) 85 return 0; 86 if (!id->name && !nu->name) 87 return 1; 88 89 return !strcmp(id->name, nu->name); 90} 91 92__isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user) 93{ 94 struct isl_hash_table_entry *entry; 95 uint32_t id_hash; 96 struct isl_name_and_user nu = { name, user }; 97 98 id_hash = isl_hash_init(); 99 if (name) 100 id_hash = isl_hash_string(id_hash, name); 101 else 102 id_hash = isl_hash_builtin(id_hash, user); 103 entry = isl_hash_table_find(ctx, &ctx->id_table, id_hash, 104 isl_id_has_name_and_user, &nu, 1); 105 if (!entry) 106 return NULL; 107 if (entry->data) 108 return isl_id_copy(entry->data); 109 entry->data = id_alloc(ctx, name, user); 110 if (!entry->data) 111 ctx->id_table.n--; 112 return entry->data; 113} 114 115/* If the id has a negative refcount, then it is a static isl_id 116 * which should not be changed. 117 */ 118__isl_give isl_id *isl_id_copy(isl_id *id) 119{ 120 if (!id) 121 return NULL; 122 123 if (id->ref < 0) 124 return id; 125 126 id->ref++; 127 return id; 128} 129 130static int isl_id_eq(const void *entry, const void *name) 131{ 132 return entry == name; 133} 134 135uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id) 136{ 137 if (id) 138 isl_hash_hash(hash, id->hash); 139 140 return hash; 141} 142 143/* Replace the free_user callback by "free_user". 144 */ 145__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id, 146 __isl_give void (*free_user)(void *user)) 147{ 148 if (!id) 149 return NULL; 150 151 id->free_user = free_user; 152 153 return id; 154} 155 156/* If the id has a negative refcount, then it is a static isl_id 157 * and should not be freed. 158 */ 159void *isl_id_free(__isl_take isl_id *id) 160{ 161 struct isl_hash_table_entry *entry; 162 163 if (!id) 164 return NULL; 165 166 if (id->ref < 0) 167 return NULL; 168 169 if (--id->ref > 0) 170 return NULL; 171 172 entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash, 173 isl_id_eq, id, 0); 174 if (!entry) 175 isl_die(id->ctx, isl_error_unknown, 176 "unable to find id", (void)0); 177 else 178 isl_hash_table_remove(id->ctx, &id->ctx->id_table, entry); 179 180 if (id->free_user) 181 id->free_user(id->user); 182 183 free((char *)id->name); 184 isl_ctx_deref(id->ctx); 185 free(id); 186 187 return NULL; 188} 189 190__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p, 191 __isl_keep isl_id *id) 192{ 193 if (!id) 194 goto error; 195 196 if (id->name) 197 p = isl_printer_print_str(p, id->name); 198 if (id->user) { 199 char buffer[50]; 200 snprintf(buffer, sizeof(buffer), "@%p", id->user); 201 p = isl_printer_print_str(p, buffer); 202 } 203 return p; 204error: 205 isl_printer_free(p); 206 return NULL; 207} 208