only construct Rotl if backend supports it
[libfirm] / ir / ir / irlinkednodeset.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 nodeset.
24  * @version   $Id$
25  */
26 #include "config.h"
27
28 #include "irlinkednodeset.h"
29 #include "irnode_t.h"
30 #include "hashptr.h"
31
32 static ir_lnk_nodeset_entry_t null_nodeset_entry;
33
34 #define DO_REHASH
35 #define HashSet                   ir_lnk_nodeset_t
36 #define HashSetIterator           ir_lnk_nodeset_iterator_t
37 #define ValueType                 ir_lnk_nodeset_entry_t
38 #define NullValue                 null_nodeset_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 #define Hash(self,key)            ((unsigned)((key)->node_nr))
44 #define KeysEqual(self,key1,key2) (key1) == (key2)
45 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof((ptr)[0]))
46 #define EntrySetEmpty(value)      (value).node = NULL
47 #define EntrySetDeleted(value)    do { (value).node = (ir_node*) -1; list_del(&(value).list); } while (0)
48 #define EntryIsEmpty(value)       ((value).node == NULL)
49 #define EntryIsDeleted(value)     ((value).node == (ir_node*)-1)
50
51 #define hashset_init            ir_lnk_nodeset_init
52 #define hashset_init_size       ir_lnk_nodeset_init_size
53 #define hashset_destroy         ir_lnk_nodeset_destroy
54 ir_lnk_nodeset_entry_t *ir_lnk_nodeset_insert_(ir_lnk_nodeset_t *nodeset, ir_node *node);
55 #define hashset_insert          ir_lnk_nodeset_insert_
56 #define hashset_remove          ir_lnk_nodeset_remove
57 ir_lnk_nodeset_entry_t *ir_lnk_nodeset_find_(const ir_lnk_nodeset_t *nodeset, const ir_node *node);
58 #define hashset_find            ir_lnk_nodeset_find_
59 #define hashset_size            ir_lnk_nodeset_size
60
61 #define ADDITIONAL_INIT         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
62 #define ADDITIONAL_TERM         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
63
64 #define NO_ITERATOR
65 #define HAVE_OWN_RESIZE
66
67 #include "hashset.c"
68
69 /**
70  * Resize the hashset
71  * @internal
72  */
73 static void resize(HashSet *self, size_t new_size)
74 {
75         HashSetEntry *old_entries = self->entries;
76         HashSetEntry *new_entries;
77         list_head    list = self->elem_list;
78         HashSetEntry *entry;
79         int          res = 1;
80
81         /* allocate a new array with double size */
82         new_entries = Alloc(new_size);
83         SetRangeEmpty(new_entries, new_size);
84
85         /* use the new array */
86         self->entries      = new_entries;
87         self->num_buckets  = new_size;
88         self->num_elements = 0;
89         self->num_deleted  = 0;
90 #ifndef NDEBUG
91         self->entries_version++;
92 #endif
93         reset_thresholds(self);
94
95         assert(!list_empty(&self->elem_list));
96         list.next->prev = &list;
97         list.prev->next = &list;
98
99         /* reinsert all elements */
100         INIT_LIST_HEAD(&self->elem_list);
101         list_for_each_entry(ValueType, entry, &list, list) {
102                 res &= ir_lnk_nodeset_insert(self, EntryGetValue(*entry).node);
103         }
104         /* all re-inserted data must be new, if not, we found a node twice ... */
105         assert(res == 1);
106
107         /* now we can free the old array */
108         Free(old_entries);
109 }
110
111
112 /* Inserts a node into a linked nodeset. */
113 int ir_lnk_nodeset_insert(ir_lnk_nodeset_t *nodeset, ir_node *node)
114 {
115         ir_lnk_nodeset_entry_t *entry = ir_lnk_nodeset_insert_(nodeset, node);
116
117         if (entry->list.next == NULL) {
118                 /* we have added a new element */
119                 list_add_tail(&entry->list, &nodeset->elem_list);
120                 return 1;
121         }
122         return 0;
123 }
124
125 int ir_lnk_nodeset_contains(const ir_lnk_nodeset_t *nodeset, const ir_node *node)
126 {
127         return ir_lnk_nodeset_find_(nodeset, node) != NULL;
128 }
129
130 /**
131  * Initializes a nodeset iterator. Sets the iterator before the first element in
132  * the linked nodeset.
133  *
134  * @param iterator   Pointer to already allocated iterator memory
135  * @param nodeset       Pointer to the nodeset
136  */
137 void ir_lnk_nodeset_iterator_init(ir_lnk_nodeset_iterator_t *iterator,
138                                   const ir_lnk_nodeset_t *nodeset)
139 {
140         iterator->iter    = nodeset->elem_list.next;
141         iterator->nodeset = nodeset;
142 }
143
144 /**
145  * Advances the iterator and returns the current element or NULL if all elements
146  * in the linked nodeset have been processed.
147  * @attention It is not allowed to use ir_lnk_nodeset_insert or ir_lnk_nodeset_remove while
148  *            iterating over a nodeset.
149  *
150  * @param iterator  Pointer to the nodeset iterator.
151  * @returns         Next element in the nodeset or NULL
152  */
153 ir_node *ir_lnk_nodeset_iterator_next(ir_lnk_nodeset_iterator_t *iterator)
154 {
155         ir_node *res;
156         if (iterator->iter == &iterator->nodeset->elem_list)
157                 return NULL;
158
159         res = list_entry(iterator->iter, ir_lnk_nodeset_entry_t, list)->node;
160         iterator->iter = iterator->iter->next;
161
162         return res;
163 }
164
165 /**
166  * Removes the element the iterator currently points to.
167  *
168  * @param nodeset   Pointer to the linked nodeset
169  * @param iterator  Pointer to the nodeset iterator.
170  */
171 void ir_lnk_nodeset_remove_iterator(ir_lnk_nodeset_t *nodeset,
172                                     ir_lnk_nodeset_iterator_t *iterator)
173 {
174         ir_lnk_nodeset_entry_t *rem = list_entry(iterator->iter->prev, ir_lnk_nodeset_entry_t, list);
175
176         ir_lnk_nodeset_remove(nodeset, rem->node);
177 }