- removed Psi nodes, Mux nodes are used again ...
[libfirm] / ir / ir / irlinkednodemap.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @author    Michael Beck
23  * @brief     A linked nodemap.
24  * @version   $Id$
25  */
26 #include "config.h"
27
28 #include "irlinkednodemap.h"
29 #include "irnode_t.h"
30 #include "hashptr.h"
31
32 static ir_lnk_nodemap_entry_t null_nodemap_entry;
33
34 #define DO_REHASH
35 #define HashSet                   ir_lnk_nodemap_t
36 #define HashSetIterator           ir_lnk_nodemap_iterator_t
37 #define ValueType                 ir_lnk_nodemap_entry_t
38 #define NullValue                 null_nodemap_entry
39 #define KeyType                   ir_node*
40 #define ConstKeyType              const ir_node*
41 #define GetKey(value)             (value).node
42 #define InitData(self,value,key)  do { (value).node = (key); (value).list.next = NULL; (value).list.prev = NULL; } while(0)
43 #ifdef DEBUG_libfirm
44 #define Hash(self,key)            ((unsigned)((key)->node_nr))
45 #else
46 #define Hash(self,key)            HASH_PTR(key)
47 #endif
48 #define KeysEqual(self,key1,key2) (key1) == (key2)
49 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof((ptr)[0]))
50 #define EntrySetEmpty(value)      (value).node = NULL
51 #define EntrySetDeleted(value)    do { (value).node = (ir_node*) -1; list_del(&(value).list); } while(0)
52 #define EntryIsEmpty(value)       ((value).node == NULL)
53 #define EntryIsDeleted(value)     ((value).node == (ir_node*)-1)
54
55 #define hashset_init            ir_lnk_nodemap_init
56 #define hashset_init_size       ir_lnk_nodemap_init_size
57 #define hashset_destroy         ir_lnk_nodemap_destroy
58 #define hashset_insert          _ir_lnk_nodemap_insert
59 #define hashset_remove          ir_lnk_nodemap_remove
60 #define hashset_find            _ir_lnk_nodemap_find
61 #define hashset_size            ir_lnk_nodemap_size
62
63 #define ADDITIONAL_INIT         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
64 #define ADDITIONAL_TERM         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
65
66 #define NO_ITERATOR
67 #define HAVE_OWN_RESIZE
68
69 #include "hashset.c"
70
71 /**
72  * Resize the hashset
73  * @internal
74  */
75 static
76 void resize(HashSet *self, size_t new_size)
77 {
78         HashSetEntry *old_entries = self->entries;
79         HashSetEntry *new_entries;
80         list_head    list = self->elem_list;
81         HashSetEntry *entry;
82         int          res = 1;
83
84         /* allocate a new array with double size */
85         new_entries = Alloc(new_size);
86         SetRangeEmpty(new_entries, new_size);
87
88         /* use the new array */
89         self->entries      = new_entries;
90         self->num_buckets  = new_size;
91         self->num_elements = 0;
92         self->num_deleted  = 0;
93 #ifndef NDEBUG
94         self->entries_version++;
95 #endif
96         reset_thresholds(self);
97
98         assert(!list_empty(&self->elem_list));
99         list.next->prev = &list;
100         list.prev->next = &list;
101
102         /* reinsert all elements */
103         INIT_LIST_HEAD(&self->elem_list);
104         list_for_each_entry(ValueType, entry, &list, list) {
105                 res &= ir_lnk_nodemap_put(self, EntryGetValue(*entry).node, EntryGetValue(*entry).data);
106         }
107         /* all re-inserted data must be new, if not, we found a node twice ... */
108         assert(res == 1);
109
110         /* now we can free the old array */
111         Free(old_entries);
112 }
113
114
115 int ir_lnk_nodemap_put(ir_lnk_nodemap_t *nodemap, ir_node *node, void *data)
116 {
117         ir_lnk_nodemap_entry_t *entry = _ir_lnk_nodemap_insert(nodemap, node);
118
119         entry->data = data;
120         if (entry->list.next == NULL) {
121                 /* we have added a new element */
122                 list_add_tail(&entry->list, &nodemap->elem_list);
123                 return 1;
124         }
125         return 0;
126 }
127
128 void *ir_lnk_nodemap_get(const ir_lnk_nodemap_t *nodemap, const ir_node *node)
129 {
130         ir_lnk_nodemap_entry_t *entry = _ir_lnk_nodemap_find(nodemap, node);
131         return entry->data;
132 }
133
134 /**
135  * Initializes a nodemap iterator. Sets the iterator before the first element in
136  * the linked nodemap.
137  *
138  * @param iterator   Pointer to already allocated iterator memory
139  * @param nodemap       Pointer to the nodemap
140  */
141 void ir_lnk_nodemap_iterator_init(ir_lnk_nodemap_iterator_t *iterator,
142                                   const ir_lnk_nodemap_t *nodemap) {
143         iterator->iter    = nodemap->elem_list.next;
144         iterator->nodemap = nodemap;
145 }
146
147 /**
148  * Advances the iterator and returns the current element or NULL if all elements
149  * in the linked nodemap have been processed.
150  * @attention It is not allowed to use ir_lnk_nodemap_insert or ir_lnk_nodemap_remove while
151  *            iterating over a nodemap.
152  *
153  * @param iterator  Pointer to the nodemap iterator.
154  * @returns         Next element in the nodemap or NULL
155  */
156 ir_node *ir_lnk_nodemap_iterator_next(ir_lnk_nodemap_iterator_t *iterator) {
157         ir_node *res;
158         if (iterator->iter == &iterator->nodemap->elem_list)
159                 return NULL;
160
161         res = list_entry(iterator->iter, ir_lnk_nodemap_entry_t, list)->node;
162         iterator->iter = iterator->iter->next;
163
164         return res;
165 }
166
167 /**
168  * Removes the element the iterator currently points to.
169  *
170  * @param nodemap   Pointer to the linked nodemap
171  * @param iterator  Pointer to the nodemap iterator.
172  */
173 void ir_lnk_nodemap_remove_iterator(ir_lnk_nodemap_t *nodemap,
174                                     ir_lnk_nodemap_iterator_t *iterator) {
175         ir_lnk_nodemap_entry_t *rem = list_entry(iterator->iter->prev, ir_lnk_nodemap_entry_t, list);
176
177         ir_lnk_nodemap_remove(nodemap, rem->node);
178 }