bearch: Disallow passing Projs to get_irn_ops().
[libfirm] / ir / ir / valueset.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @author    Michael Beck
9  * @brief     A value set, containing expression for values.
10  */
11 #include "config.h"
12
13 #include "valueset.h"
14 #include "irnode_t.h"
15 #include "iropt_t.h"
16 #include "hashptr.h"
17
18 static ir_valueset_entry_t null_valueset_entry;
19
20 #undef DO_REHASH
21 #define HashSet                   ir_valueset_t
22 #define HashSetIterator           ir_valueset_iterator_t
23 #define ValueType                 ir_valueset_entry_t
24 #define NullValue                 null_valueset_entry
25 #define KeyType                   ir_node*
26 #define ConstKeyType              const ir_node*
27 #define GetKey(entry)             (entry).value
28 #define InitData(self,entry,key)  do { (entry).value = (key); (entry).list.next = NULL; (entry).list.prev = NULL; } while (0)
29 #define Hash(self,key)            ir_node_hash(key)
30 #define KeysEqual(self,key1,key2) (key1) == (key2)
31 #define SetRangeEmpty(ptr,size)   memset(ptr, 0, (size) * sizeof((ptr)[0]))
32 #define EntrySetEmpty(entry)      (entry).value = NULL
33 #define EntrySetDeleted(entry)    do { (entry).data.value = (ir_node*) -1; list_del(&(entry).data.list); } while (0)
34 #define EntryIsEmpty(entry)       ((entry).data.value == NULL)
35 #define EntryIsDeleted(entry)     ((entry).data.value == (ir_node*)-1)
36
37 #define hashset_init            ir_valueset_init
38 #define hashset_init_size       ir_valueset_init_size
39 #define hashset_destroy         ir_valueset_destroy
40 ir_valueset_entry_t *ir_valueset_insert_(ir_valueset_t *self, ir_node *value);
41 #define hashset_insert          ir_valueset_insert_
42 #define hashset_remove          ir_valueset_remove
43 ir_valueset_entry_t *ir_valueset_find_(const ir_valueset_t *self,
44                                        const ir_node *value);
45 #define hashset_find            ir_valueset_find_
46 #define hashset_size            ir_valueset_size
47
48 #define ADDITIONAL_INIT         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
49 #define ADDITIONAL_TERM         INIT_LIST_HEAD(&self->elem_list); INIT_LIST_HEAD(&self->all_iters);
50
51 #define HAVE_OWN_RESIZE
52
53 #include "hashset.c.inl"
54
55 /**
56  * Resize the hashset
57  * @internal
58  */
59 static void resize(HashSet *self, size_t new_size)
60 {
61         HashSetEntry *old_entries = self->entries;
62         HashSetEntry *new_entries;
63         list_head    list = self->elem_list;
64         int          res = 1;
65
66         /* allocate a new array with double size */
67         new_entries = Alloc(new_size);
68         SetRangeEmpty(new_entries, new_size);
69
70         /* use the new array */
71         self->entries      = new_entries;
72         self->num_buckets  = new_size;
73         self->num_elements = 0;
74         self->num_deleted  = 0;
75 #ifndef NDEBUG
76         self->entries_version++;
77 #endif
78         reset_thresholds(self);
79
80         assert(!list_empty(&self->elem_list));
81         list.next->prev = &list;
82         list.prev->next = &list;
83
84         /* reinsert all elements */
85         INIT_LIST_HEAD(&self->elem_list);
86         list_for_each_entry(ValueType, entry, &list, list) {
87                 res &= ir_valueset_insert(self, entry->value, entry->expr);
88         }
89         /* all re-inserted data must be new, if not, we found a node twice ... */
90         assert(res == 1);
91
92         /* now we can free the old array */
93         Free(old_entries);
94 }
95
96 int ir_valueset_insert(ir_valueset_t *valueset, ir_node *value, ir_node *expr)
97 {
98         ir_valueset_entry_t *entry = ir_valueset_insert_(valueset, value);
99
100         if (entry->list.next != NULL) {
101                 /* this value is already inserted, do nothing */
102                 return 0;
103         }
104
105         /* new element added */
106         entry->expr = expr;
107         list_add_tail(&entry->list, &valueset->elem_list);
108         return 1;
109 }
110
111 int ir_valueset_replace(ir_valueset_t *valueset, ir_node *value, ir_node *expr)
112 {
113         int res = 0;
114         ir_valueset_entry_t *entry = ir_valueset_insert_(valueset, value);
115
116         if (entry->expr != expr) {
117                 entry->expr = expr;
118                 res = 1;
119         }
120         if (entry->list.next == NULL) {
121                 /* we have added a new element */
122                 list_add_tail(&entry->list, &valueset->elem_list);
123                 return 1;
124         }
125         return res;
126 }
127
128 void *ir_valueset_lookup(const ir_valueset_t *valueset, const ir_node *value)
129 {
130         ir_valueset_entry_t *entry = ir_valueset_find_(valueset, value);
131         if (entry != NULL)
132                 return entry->expr;
133         return NULL;
134 }
135
136 void ir_valueset_iterator_init(ir_valueset_iterator_t *iterator,
137                                const ir_valueset_t *valueset)
138 {
139         iterator->iter     = valueset->elem_list.next;
140         iterator->valueset = valueset;
141 }
142
143 ir_node *ir_valueset_iterator_next(ir_valueset_iterator_t *iterator, ir_node **expr)
144 {
145         ir_valueset_entry_t *entry;
146
147         if (iterator->iter == &iterator->valueset->elem_list) {
148                 *expr = NULL;
149                 return NULL;
150         }
151
152         entry = list_entry(iterator->iter, ir_valueset_entry_t, list);
153         iterator->iter = iterator->iter->next;
154
155         *expr = entry->expr;
156         return entry->value;
157 }
158
159 void ir_valueset_remove_iterator(ir_valueset_t *valueset, ir_valueset_iterator_t *iterator)
160 {
161         ir_valueset_entry_t *rem = list_entry(iterator->iter->prev, ir_valueset_entry_t, list);
162
163         ir_valueset_remove(valueset, rem->value);
164 }