1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef __NV50_IR_UTIL_H__
24bf215546Sopenharmony_ci#define __NV50_IR_UTIL_H__
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include <new>
27bf215546Sopenharmony_ci#include <assert.h>
28bf215546Sopenharmony_ci#include <stdio.h>
29bf215546Sopenharmony_ci#include <memory>
30bf215546Sopenharmony_ci#include <map>
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#ifndef NDEBUG
33bf215546Sopenharmony_ci# include <typeinfo>
34bf215546Sopenharmony_ci#endif
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "util/u_inlines.h"
37bf215546Sopenharmony_ci#include "util/u_memory.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#define ERROR(args...) _debug_printf("ERROR: " args)
40bf215546Sopenharmony_ci#define WARN(args...) _debug_printf("WARNING: " args)
41bf215546Sopenharmony_ci#define INFO(args...) _debug_printf(args)
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#define INFO_DBG(m, f, args...)          \
44bf215546Sopenharmony_ci   do {                                  \
45bf215546Sopenharmony_ci      if (m & NV50_IR_DEBUG_##f)         \
46bf215546Sopenharmony_ci         _debug_printf(args);             \
47bf215546Sopenharmony_ci   } while(0)
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#define FATAL(args...)          \
50bf215546Sopenharmony_ci   do {                         \
51bf215546Sopenharmony_ci      fprintf(stderr, args);    \
52bf215546Sopenharmony_ci      abort();                  \
53bf215546Sopenharmony_ci   } while(0)
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci#define NV50_IR_FUNC_ALLOC_OBJ_DEF(obj, f, args...)               \
57bf215546Sopenharmony_ci   new ((f)->getProgram()->mem_##obj.allocate()) obj(f, args)
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci#define new_Instruction(f, args...)                      \
60bf215546Sopenharmony_ci   NV50_IR_FUNC_ALLOC_OBJ_DEF(Instruction, f, args)
61bf215546Sopenharmony_ci#define new_CmpInstruction(f, args...)                   \
62bf215546Sopenharmony_ci   NV50_IR_FUNC_ALLOC_OBJ_DEF(CmpInstruction, f, args)
63bf215546Sopenharmony_ci#define new_TexInstruction(f, args...)                   \
64bf215546Sopenharmony_ci   NV50_IR_FUNC_ALLOC_OBJ_DEF(TexInstruction, f, args)
65bf215546Sopenharmony_ci#define new_FlowInstruction(f, args...)                  \
66bf215546Sopenharmony_ci   NV50_IR_FUNC_ALLOC_OBJ_DEF(FlowInstruction, f, args)
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci#define new_LValue(f, args...)                  \
69bf215546Sopenharmony_ci   NV50_IR_FUNC_ALLOC_OBJ_DEF(LValue, f, args)
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci#define NV50_IR_PROG_ALLOC_OBJ_DEF(obj, p, args...)   \
73bf215546Sopenharmony_ci   new ((p)->mem_##obj.allocate()) obj(p, args)
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci#define new_Symbol(p, args...)                           \
76bf215546Sopenharmony_ci   NV50_IR_PROG_ALLOC_OBJ_DEF(Symbol, p, args)
77bf215546Sopenharmony_ci#define new_ImmediateValue(p, args...)                   \
78bf215546Sopenharmony_ci   NV50_IR_PROG_ALLOC_OBJ_DEF(ImmediateValue, p, args)
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci#define delete_Instruction(p, insn) (p)->releaseInstruction(insn)
82bf215546Sopenharmony_ci#define delete_Value(p, val) (p)->releaseValue(val)
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_cinamespace nv50_ir {
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ciclass Iterator
88bf215546Sopenharmony_ci{
89bf215546Sopenharmony_cipublic:
90bf215546Sopenharmony_ci   virtual ~Iterator() { };
91bf215546Sopenharmony_ci   virtual void next() = 0;
92bf215546Sopenharmony_ci   virtual void *get() const = 0;
93bf215546Sopenharmony_ci   virtual bool end() const = 0; // if true, get will return 0
94bf215546Sopenharmony_ci   virtual void reset() { assert(0); } // only for graph iterators
95bf215546Sopenharmony_ci};
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_citypedef std::unique_ptr<Iterator> IteratorRef;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ciclass ManipIterator : public Iterator
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_cipublic:
102bf215546Sopenharmony_ci   virtual bool insert(void *) = 0; // insert after current position
103bf215546Sopenharmony_ci   virtual void erase() = 0;
104bf215546Sopenharmony_ci};
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci// WARNING: do not use a->prev/next for __item or __list
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci#define DLLIST_DEL(__item)                      \
109bf215546Sopenharmony_ci   do {                                         \
110bf215546Sopenharmony_ci      (__item)->prev->next = (__item)->next;    \
111bf215546Sopenharmony_ci      (__item)->next->prev = (__item)->prev;    \
112bf215546Sopenharmony_ci      (__item)->next = (__item);                \
113bf215546Sopenharmony_ci      (__item)->prev = (__item);                \
114bf215546Sopenharmony_ci   } while(0)
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci#define DLLIST_ADDTAIL(__list, __item)          \
117bf215546Sopenharmony_ci   do {                                         \
118bf215546Sopenharmony_ci      (__item)->next = (__list);                \
119bf215546Sopenharmony_ci      (__item)->prev = (__list)->prev;          \
120bf215546Sopenharmony_ci      (__list)->prev->next = (__item);          \
121bf215546Sopenharmony_ci      (__list)->prev = (__item);                \
122bf215546Sopenharmony_ci   } while(0)
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci#define DLLIST_ADDHEAD(__list, __item)          \
125bf215546Sopenharmony_ci   do {                                         \
126bf215546Sopenharmony_ci      (__item)->prev = (__list);                \
127bf215546Sopenharmony_ci      (__item)->next = (__list)->next;          \
128bf215546Sopenharmony_ci      (__list)->next->prev = (__item);          \
129bf215546Sopenharmony_ci      (__list)->next = (__item);                \
130bf215546Sopenharmony_ci   } while(0)
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci#define DLLIST_MERGE(__listA, __listB, ty)      \
133bf215546Sopenharmony_ci   do {                                         \
134bf215546Sopenharmony_ci      ty prevB = (__listB)->prev;               \
135bf215546Sopenharmony_ci      (__listA)->prev->next = (__listB);        \
136bf215546Sopenharmony_ci      (__listB)->prev->next = (__listA);        \
137bf215546Sopenharmony_ci      (__listB)->prev = (__listA)->prev;        \
138bf215546Sopenharmony_ci      (__listA)->prev = prevB;                  \
139bf215546Sopenharmony_ci   } while(0)
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci#define DLLIST_EMPTY(__list) ((__list)->next == (__list))
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci#define DLLIST_FOR_EACH(list, it) \
144bf215546Sopenharmony_ci   for (DLList::Iterator it = (list)->iterator(); !(it).end(); (it).next())
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ciclass DLList
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_cipublic:
149bf215546Sopenharmony_ci   class Item
150bf215546Sopenharmony_ci   {
151bf215546Sopenharmony_ci   public:
152bf215546Sopenharmony_ci      Item(void *priv) : next(this), prev(this), data(priv) { }
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   public:
155bf215546Sopenharmony_ci      Item *next;
156bf215546Sopenharmony_ci      Item *prev;
157bf215546Sopenharmony_ci      void *data;
158bf215546Sopenharmony_ci   };
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   DLList() : head(0) { }
161bf215546Sopenharmony_ci   ~DLList() { clear(); }
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   inline void insertHead(void *data)
164bf215546Sopenharmony_ci   {
165bf215546Sopenharmony_ci      Item *item = new Item(data);
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci      assert(data);
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci      item->prev = &head;
170bf215546Sopenharmony_ci      item->next = head.next;
171bf215546Sopenharmony_ci      head.next->prev = item;
172bf215546Sopenharmony_ci      head.next = item;
173bf215546Sopenharmony_ci   }
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   inline void insertTail(void *data)
176bf215546Sopenharmony_ci   {
177bf215546Sopenharmony_ci      Item *item = new Item(data);
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci      assert(data);
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci      DLLIST_ADDTAIL(&head, item);
182bf215546Sopenharmony_ci   }
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   inline void insert(void *data) { insertTail(data); }
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   void clear();
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   class Iterator : public ManipIterator
189bf215546Sopenharmony_ci   {
190bf215546Sopenharmony_ci   public:
191bf215546Sopenharmony_ci      Iterator(Item *head, bool r) : rev(r), pos(r ? head->prev : head->next),
192bf215546Sopenharmony_ci                                     term(head) { }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci      virtual void next() { if (!end()) pos = rev ? pos->prev : pos->next; }
195bf215546Sopenharmony_ci      virtual void *get() const { return pos->data; }
196bf215546Sopenharmony_ci      virtual bool end() const { return pos == term; }
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci      // caution: if you're at end-2 and erase it, then do next, you're at end
199bf215546Sopenharmony_ci      virtual void erase();
200bf215546Sopenharmony_ci      virtual bool insert(void *data);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci      // move item to another list, no consistency with its iterators though
203bf215546Sopenharmony_ci      void moveToList(DLList&);
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   private:
206bf215546Sopenharmony_ci      const bool rev;
207bf215546Sopenharmony_ci      Item *pos;
208bf215546Sopenharmony_ci      Item *term;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci      friend class DLList;
211bf215546Sopenharmony_ci   };
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   inline void erase(Iterator& pos)
214bf215546Sopenharmony_ci   {
215bf215546Sopenharmony_ci      pos.erase();
216bf215546Sopenharmony_ci   }
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   Iterator iterator()
219bf215546Sopenharmony_ci   {
220bf215546Sopenharmony_ci      return Iterator(&head, false);
221bf215546Sopenharmony_ci   }
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   Iterator revIterator()
224bf215546Sopenharmony_ci   {
225bf215546Sopenharmony_ci      return Iterator(&head, true);
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ciprivate:
229bf215546Sopenharmony_ci   Item head;
230bf215546Sopenharmony_ci};
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ciclass Stack
233bf215546Sopenharmony_ci{
234bf215546Sopenharmony_cipublic:
235bf215546Sopenharmony_ci   class Item {
236bf215546Sopenharmony_ci   public:
237bf215546Sopenharmony_ci      union {
238bf215546Sopenharmony_ci         void *p;
239bf215546Sopenharmony_ci         int i;
240bf215546Sopenharmony_ci         unsigned int u;
241bf215546Sopenharmony_ci         float f;
242bf215546Sopenharmony_ci         double d;
243bf215546Sopenharmony_ci      } u;
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci      Item() { memset(&u, 0, sizeof(u)); }
246bf215546Sopenharmony_ci   };
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   Stack() : size(0), limit(0), array(0) { }
249bf215546Sopenharmony_ci   ~Stack() { if (array) FREE(array); }
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   inline void push(int i)          { Item data; data.u.i = i; push(data); }
252bf215546Sopenharmony_ci   inline void push(unsigned int u) { Item data; data.u.u = u; push(data); }
253bf215546Sopenharmony_ci   inline void push(void *p)        { Item data; data.u.p = p; push(data); }
254bf215546Sopenharmony_ci   inline void push(float f)        { Item data; data.u.f = f; push(data); }
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   inline void push(Item data)
257bf215546Sopenharmony_ci   {
258bf215546Sopenharmony_ci      if (size == limit)
259bf215546Sopenharmony_ci         resize();
260bf215546Sopenharmony_ci      array[size++] = data;
261bf215546Sopenharmony_ci   }
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   inline Item pop()
264bf215546Sopenharmony_ci   {
265bf215546Sopenharmony_ci      if (!size) {
266bf215546Sopenharmony_ci         Item data;
267bf215546Sopenharmony_ci         assert(0);
268bf215546Sopenharmony_ci         return data;
269bf215546Sopenharmony_ci      }
270bf215546Sopenharmony_ci      return array[--size];
271bf215546Sopenharmony_ci   }
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   inline unsigned int getSize() { return size; }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   inline Item& peek() { assert(size); return array[size - 1]; }
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   void clear(bool releaseStorage = false)
278bf215546Sopenharmony_ci   {
279bf215546Sopenharmony_ci      if (releaseStorage && array)
280bf215546Sopenharmony_ci         FREE(array);
281bf215546Sopenharmony_ci      size = limit = 0;
282bf215546Sopenharmony_ci   }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   void moveTo(Stack&); // move all items to target (not like push(pop()))
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ciprivate:
287bf215546Sopenharmony_ci   void resize()
288bf215546Sopenharmony_ci   {
289bf215546Sopenharmony_ci         unsigned int sizeOld, sizeNew;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci         sizeOld = limit * sizeof(Item);
292bf215546Sopenharmony_ci         limit = MAX2(4, limit + limit);
293bf215546Sopenharmony_ci         sizeNew = limit * sizeof(Item);
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci         array = (Item *)REALLOC(array, sizeOld, sizeNew);
296bf215546Sopenharmony_ci   }
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   unsigned int size;
299bf215546Sopenharmony_ci   unsigned int limit;
300bf215546Sopenharmony_ci   Item *array;
301bf215546Sopenharmony_ci};
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ciclass DynArray
304bf215546Sopenharmony_ci{
305bf215546Sopenharmony_cipublic:
306bf215546Sopenharmony_ci   class Item
307bf215546Sopenharmony_ci   {
308bf215546Sopenharmony_ci   public:
309bf215546Sopenharmony_ci      union {
310bf215546Sopenharmony_ci         uint32_t u32;
311bf215546Sopenharmony_ci         void *p;
312bf215546Sopenharmony_ci      };
313bf215546Sopenharmony_ci   };
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   DynArray() : data(NULL), size(0) { }
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   ~DynArray() { if (data) FREE(data); }
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   inline Item& operator[](unsigned int i)
320bf215546Sopenharmony_ci   {
321bf215546Sopenharmony_ci      if (i >= size)
322bf215546Sopenharmony_ci         resize(i);
323bf215546Sopenharmony_ci      return data[i];
324bf215546Sopenharmony_ci   }
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   inline const Item operator[](unsigned int i) const
327bf215546Sopenharmony_ci   {
328bf215546Sopenharmony_ci      return data[i];
329bf215546Sopenharmony_ci   }
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   void resize(unsigned int index)
332bf215546Sopenharmony_ci   {
333bf215546Sopenharmony_ci      const unsigned int oldSize = size * sizeof(Item);
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci      if (!size)
336bf215546Sopenharmony_ci         size = 8;
337bf215546Sopenharmony_ci      while (size <= index)
338bf215546Sopenharmony_ci         size <<= 1;
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci      data = (Item *)REALLOC(data, oldSize, size * sizeof(Item));
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   void clear()
344bf215546Sopenharmony_ci   {
345bf215546Sopenharmony_ci      FREE(data);
346bf215546Sopenharmony_ci      data = NULL;
347bf215546Sopenharmony_ci      size = 0;
348bf215546Sopenharmony_ci   }
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ciprivate:
351bf215546Sopenharmony_ci   Item *data;
352bf215546Sopenharmony_ci   unsigned int size;
353bf215546Sopenharmony_ci};
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ciclass ArrayList
356bf215546Sopenharmony_ci{
357bf215546Sopenharmony_cipublic:
358bf215546Sopenharmony_ci   ArrayList() : size(0) { }
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   void insert(void *item, int& id)
361bf215546Sopenharmony_ci   {
362bf215546Sopenharmony_ci      id = ids.getSize() ? ids.pop().u.i : size++;
363bf215546Sopenharmony_ci      data[id].p = item;
364bf215546Sopenharmony_ci   }
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   void remove(int& id)
367bf215546Sopenharmony_ci   {
368bf215546Sopenharmony_ci      const unsigned int uid = id;
369bf215546Sopenharmony_ci      assert(uid < size && data[id].p);
370bf215546Sopenharmony_ci      ids.push(uid);
371bf215546Sopenharmony_ci      data[uid].p = NULL;
372bf215546Sopenharmony_ci      id = -1;
373bf215546Sopenharmony_ci   }
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   inline int getSize() const { return size; }
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci   inline void *get(unsigned int id) { assert(id < size); return data[id].p; }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   class Iterator : public nv50_ir::Iterator
380bf215546Sopenharmony_ci   {
381bf215546Sopenharmony_ci   public:
382bf215546Sopenharmony_ci      Iterator(const ArrayList *array) : pos(0), data(array->data)
383bf215546Sopenharmony_ci      {
384bf215546Sopenharmony_ci         size = array->getSize();
385bf215546Sopenharmony_ci         if (size)
386bf215546Sopenharmony_ci            nextValid();
387bf215546Sopenharmony_ci      }
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci      void nextValid() { while ((pos < size) && !data[pos].p) ++pos; }
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci      void next() { if (pos < size) { ++pos; nextValid(); } }
392bf215546Sopenharmony_ci      void *get() const { assert(pos < size); return data[pos].p; }
393bf215546Sopenharmony_ci      bool end() const { return pos >= size; }
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   private:
396bf215546Sopenharmony_ci      unsigned int pos;
397bf215546Sopenharmony_ci      unsigned int size;
398bf215546Sopenharmony_ci      const DynArray& data;
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci      friend class ArrayList;
401bf215546Sopenharmony_ci   };
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci   Iterator iterator() const { return Iterator(this); }
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   void clear()
406bf215546Sopenharmony_ci   {
407bf215546Sopenharmony_ci      data.clear();
408bf215546Sopenharmony_ci      ids.clear(true);
409bf215546Sopenharmony_ci      size = 0;
410bf215546Sopenharmony_ci   }
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ciprivate:
413bf215546Sopenharmony_ci   DynArray data;
414bf215546Sopenharmony_ci   Stack ids;
415bf215546Sopenharmony_ci   unsigned int size;
416bf215546Sopenharmony_ci};
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ciclass Interval
419bf215546Sopenharmony_ci{
420bf215546Sopenharmony_cipublic:
421bf215546Sopenharmony_ci   Interval() : head(0), tail(0) { }
422bf215546Sopenharmony_ci   Interval(const Interval&);
423bf215546Sopenharmony_ci   ~Interval();
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci   bool extend(int, int);
426bf215546Sopenharmony_ci   void insert(const Interval&);
427bf215546Sopenharmony_ci   void unify(Interval&); // clears source interval
428bf215546Sopenharmony_ci   void clear();
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   inline int begin() const { return head ? head->bgn : -1; }
431bf215546Sopenharmony_ci   inline int end() const { checkTail(); return tail ? tail->end : -1; }
432bf215546Sopenharmony_ci   inline bool isEmpty() const { return !head; }
433bf215546Sopenharmony_ci   bool overlaps(const Interval&) const;
434bf215546Sopenharmony_ci   bool contains(int pos) const;
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   inline int extent() const { return end() - begin(); }
437bf215546Sopenharmony_ci   int length() const;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci   void print() const;
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   inline void checkTail() const;
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ciprivate:
444bf215546Sopenharmony_ci   class Range
445bf215546Sopenharmony_ci   {
446bf215546Sopenharmony_ci   public:
447bf215546Sopenharmony_ci      Range(int a, int b) : next(0), bgn(a), end(b) { }
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      Range *next;
450bf215546Sopenharmony_ci      int bgn;
451bf215546Sopenharmony_ci      int end;
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci      void coalesce(Range **ptail)
454bf215546Sopenharmony_ci      {
455bf215546Sopenharmony_ci         Range *rnn;
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci         while (next && end >= next->bgn) {
458bf215546Sopenharmony_ci            assert(bgn <= next->bgn);
459bf215546Sopenharmony_ci            rnn = next->next;
460bf215546Sopenharmony_ci            end = MAX2(end, next->end);
461bf215546Sopenharmony_ci            delete next;
462bf215546Sopenharmony_ci            next = rnn;
463bf215546Sopenharmony_ci         }
464bf215546Sopenharmony_ci         if (!next)
465bf215546Sopenharmony_ci            *ptail = this;
466bf215546Sopenharmony_ci      }
467bf215546Sopenharmony_ci   };
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci   Range *head;
470bf215546Sopenharmony_ci   Range *tail;
471bf215546Sopenharmony_ci};
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ciclass BitSet
474bf215546Sopenharmony_ci{
475bf215546Sopenharmony_cipublic:
476bf215546Sopenharmony_ci   BitSet() : marker(false), data(0), size(0) { }
477bf215546Sopenharmony_ci   BitSet(unsigned int nBits, bool zero) : marker(false), data(0), size(0)
478bf215546Sopenharmony_ci   {
479bf215546Sopenharmony_ci      allocate(nBits, zero);
480bf215546Sopenharmony_ci   }
481bf215546Sopenharmony_ci   ~BitSet()
482bf215546Sopenharmony_ci   {
483bf215546Sopenharmony_ci      if (data)
484bf215546Sopenharmony_ci         FREE(data);
485bf215546Sopenharmony_ci   }
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   // allocate will keep old data iff size is unchanged
488bf215546Sopenharmony_ci   bool allocate(unsigned int nBits, bool zero);
489bf215546Sopenharmony_ci   bool resize(unsigned int nBits); // keep old data, zero additional bits
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   inline unsigned int getSize() const { return size; }
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   void fill(uint32_t val);
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci   void setOr(BitSet *, BitSet *); // second BitSet may be NULL
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci   inline void set(unsigned int i)
498bf215546Sopenharmony_ci   {
499bf215546Sopenharmony_ci      assert(i < size);
500bf215546Sopenharmony_ci      data[i / 32] |= 1 << (i % 32);
501bf215546Sopenharmony_ci   }
502bf215546Sopenharmony_ci   // NOTE: range may not cross 32 bit boundary (implies n <= 32)
503bf215546Sopenharmony_ci   inline void setRange(unsigned int i, unsigned int n)
504bf215546Sopenharmony_ci   {
505bf215546Sopenharmony_ci      assert((i + n) <= size && (((i % 32) + n) <= 32));
506bf215546Sopenharmony_ci      data[i / 32] |= ((1 << n) - 1) << (i % 32);
507bf215546Sopenharmony_ci   }
508bf215546Sopenharmony_ci   inline void setMask(unsigned int i, uint32_t m)
509bf215546Sopenharmony_ci   {
510bf215546Sopenharmony_ci      assert(i < size);
511bf215546Sopenharmony_ci      data[i / 32] |= m;
512bf215546Sopenharmony_ci   }
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci   inline void clr(unsigned int i)
515bf215546Sopenharmony_ci   {
516bf215546Sopenharmony_ci      assert(i < size);
517bf215546Sopenharmony_ci      data[i / 32] &= ~(1 << (i % 32));
518bf215546Sopenharmony_ci   }
519bf215546Sopenharmony_ci   // NOTE: range may not cross 32 bit boundary (implies n <= 32)
520bf215546Sopenharmony_ci   inline void clrRange(unsigned int i, unsigned int n)
521bf215546Sopenharmony_ci   {
522bf215546Sopenharmony_ci      assert((i + n) <= size && (((i % 32) + n) <= 32));
523bf215546Sopenharmony_ci      data[i / 32] &= ~(((1 << n) - 1) << (i % 32));
524bf215546Sopenharmony_ci   }
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   inline bool test(unsigned int i) const
527bf215546Sopenharmony_ci   {
528bf215546Sopenharmony_ci      assert(i < size);
529bf215546Sopenharmony_ci      return data[i / 32] & (1 << (i % 32));
530bf215546Sopenharmony_ci   }
531bf215546Sopenharmony_ci   // NOTE: range may not cross 32 bit boundary (implies n <= 32)
532bf215546Sopenharmony_ci   inline bool testRange(unsigned int i, unsigned int n) const
533bf215546Sopenharmony_ci   {
534bf215546Sopenharmony_ci      assert((i + n) <= size && (((i % 32) + n) <= 32));
535bf215546Sopenharmony_ci      return data[i / 32] & (((1 << n) - 1) << (i % 32));
536bf215546Sopenharmony_ci   }
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   // Find a range of count (<= 32) clear bits aligned to roundup_pow2(count).
539bf215546Sopenharmony_ci   int findFreeRange(unsigned int count, unsigned int max) const;
540bf215546Sopenharmony_ci   inline int findFreeRange(unsigned int count) const {
541bf215546Sopenharmony_ci      return findFreeRange(count, size);
542bf215546Sopenharmony_ci   }
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci   BitSet& operator|=(const BitSet&);
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci   BitSet& operator=(const BitSet& set)
547bf215546Sopenharmony_ci   {
548bf215546Sopenharmony_ci      assert(data && set.data);
549bf215546Sopenharmony_ci      assert(size == set.size);
550bf215546Sopenharmony_ci      memcpy(data, set.data, (set.size + 7) / 8);
551bf215546Sopenharmony_ci      return *this;
552bf215546Sopenharmony_ci   }
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   void andNot(const BitSet&);
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   // bits = (bits | setMask) & ~clrMask
557bf215546Sopenharmony_ci   inline void periodicMask32(uint32_t setMask, uint32_t clrMask)
558bf215546Sopenharmony_ci   {
559bf215546Sopenharmony_ci      for (unsigned int i = 0; i < (size + 31) / 32; ++i)
560bf215546Sopenharmony_ci         data[i] = (data[i] | setMask) & ~clrMask;
561bf215546Sopenharmony_ci   }
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci   unsigned int popCount() const;
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci   void print() const;
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_cipublic:
568bf215546Sopenharmony_ci   bool marker; // for user
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ciprivate:
571bf215546Sopenharmony_ci   uint32_t *data;
572bf215546Sopenharmony_ci   unsigned int size;
573bf215546Sopenharmony_ci};
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_civoid Interval::checkTail() const
576bf215546Sopenharmony_ci{
577bf215546Sopenharmony_ci#if NV50_DEBUG & NV50_DEBUG_PROG_RA
578bf215546Sopenharmony_ci   Range *r = head;
579bf215546Sopenharmony_ci   while (r->next)
580bf215546Sopenharmony_ci      r = r->next;
581bf215546Sopenharmony_ci   assert(tail == r);
582bf215546Sopenharmony_ci#endif
583bf215546Sopenharmony_ci}
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ciclass MemoryPool
586bf215546Sopenharmony_ci{
587bf215546Sopenharmony_ciprivate:
588bf215546Sopenharmony_ci   inline bool enlargeAllocationsArray(const unsigned int id, unsigned int nr)
589bf215546Sopenharmony_ci   {
590bf215546Sopenharmony_ci      const unsigned int size = sizeof(uint8_t *) * id;
591bf215546Sopenharmony_ci      const unsigned int incr = sizeof(uint8_t *) * nr;
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci      uint8_t **alloc = (uint8_t **)REALLOC(allocArray, size, size + incr);
594bf215546Sopenharmony_ci      if (!alloc)
595bf215546Sopenharmony_ci         return false;
596bf215546Sopenharmony_ci      allocArray = alloc;
597bf215546Sopenharmony_ci      return true;
598bf215546Sopenharmony_ci   }
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   inline bool enlargeCapacity()
601bf215546Sopenharmony_ci   {
602bf215546Sopenharmony_ci      const unsigned int id = count >> objStepLog2;
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci      uint8_t *const mem = (uint8_t *)MALLOC(objSize << objStepLog2);
605bf215546Sopenharmony_ci      if (!mem)
606bf215546Sopenharmony_ci         return false;
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci      if (!(id % 32)) {
609bf215546Sopenharmony_ci         if (!enlargeAllocationsArray(id, 32)) {
610bf215546Sopenharmony_ci            FREE(mem);
611bf215546Sopenharmony_ci            return false;
612bf215546Sopenharmony_ci         }
613bf215546Sopenharmony_ci      }
614bf215546Sopenharmony_ci      allocArray[id] = mem;
615bf215546Sopenharmony_ci      return true;
616bf215546Sopenharmony_ci   }
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_cipublic:
619bf215546Sopenharmony_ci   MemoryPool(unsigned int size, unsigned int incr) : objSize(size),
620bf215546Sopenharmony_ci                                                      objStepLog2(incr)
621bf215546Sopenharmony_ci   {
622bf215546Sopenharmony_ci      allocArray = NULL;
623bf215546Sopenharmony_ci      released = NULL;
624bf215546Sopenharmony_ci      count = 0;
625bf215546Sopenharmony_ci   }
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   ~MemoryPool()
628bf215546Sopenharmony_ci   {
629bf215546Sopenharmony_ci      unsigned int allocCount = (count + (1 << objStepLog2) - 1) >> objStepLog2;
630bf215546Sopenharmony_ci      for (unsigned int i = 0; i < allocCount && allocArray[i]; ++i)
631bf215546Sopenharmony_ci         FREE(allocArray[i]);
632bf215546Sopenharmony_ci      if (allocArray)
633bf215546Sopenharmony_ci         FREE(allocArray);
634bf215546Sopenharmony_ci   }
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ci   void *allocate()
637bf215546Sopenharmony_ci   {
638bf215546Sopenharmony_ci      void *ret;
639bf215546Sopenharmony_ci      const unsigned int mask = (1 << objStepLog2) - 1;
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci      if (released) {
642bf215546Sopenharmony_ci         ret = released;
643bf215546Sopenharmony_ci         released = *(void **)released;
644bf215546Sopenharmony_ci         return ret;
645bf215546Sopenharmony_ci      }
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci      if (!(count & mask))
648bf215546Sopenharmony_ci         if (!enlargeCapacity())
649bf215546Sopenharmony_ci            return NULL;
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci      ret = allocArray[count >> objStepLog2] + (count & mask) * objSize;
652bf215546Sopenharmony_ci      ++count;
653bf215546Sopenharmony_ci      return ret;
654bf215546Sopenharmony_ci   }
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   void release(void *ptr)
657bf215546Sopenharmony_ci   {
658bf215546Sopenharmony_ci      *(void **)ptr = released;
659bf215546Sopenharmony_ci      released = ptr;
660bf215546Sopenharmony_ci   }
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ciprivate:
663bf215546Sopenharmony_ci   uint8_t **allocArray; // array (list) of MALLOC allocations
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   void *released; // list of released objects
666bf215546Sopenharmony_ci
667bf215546Sopenharmony_ci   unsigned int count; // highest allocated object
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci   const unsigned int objSize;
670bf215546Sopenharmony_ci   const unsigned int objStepLog2;
671bf215546Sopenharmony_ci};
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci/**
674bf215546Sopenharmony_ci *  Composite object cloning policy.
675bf215546Sopenharmony_ci *
676bf215546Sopenharmony_ci *  Encapsulates how sub-objects are to be handled (if at all) when a
677bf215546Sopenharmony_ci *  composite object is being cloned.
678bf215546Sopenharmony_ci */
679bf215546Sopenharmony_citemplate<typename C>
680bf215546Sopenharmony_ciclass ClonePolicy
681bf215546Sopenharmony_ci{
682bf215546Sopenharmony_ciprotected:
683bf215546Sopenharmony_ci   C *c;
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_cipublic:
686bf215546Sopenharmony_ci   ClonePolicy(C *c) : c(c) {}
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   C *context() { return c; }
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci   template<typename T> T *get(T *obj)
691bf215546Sopenharmony_ci   {
692bf215546Sopenharmony_ci      void *clone = lookup(obj);
693bf215546Sopenharmony_ci      if (!clone)
694bf215546Sopenharmony_ci         clone = obj->clone(*this);
695bf215546Sopenharmony_ci      return reinterpret_cast<T *>(clone);
696bf215546Sopenharmony_ci   }
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci   template<typename T> void set(const T *obj, T *clone)
699bf215546Sopenharmony_ci   {
700bf215546Sopenharmony_ci      insert(obj, clone);
701bf215546Sopenharmony_ci   }
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ciprotected:
704bf215546Sopenharmony_ci   virtual void *lookup(void *obj) = 0;
705bf215546Sopenharmony_ci   virtual void insert(const void *obj, void *clone) = 0;
706bf215546Sopenharmony_ci};
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_ci/**
709bf215546Sopenharmony_ci *  Shallow non-recursive cloning policy.
710bf215546Sopenharmony_ci *
711bf215546Sopenharmony_ci *  Objects cloned with the "shallow" policy don't clone their
712bf215546Sopenharmony_ci *  children recursively, instead, the new copy shares its children
713bf215546Sopenharmony_ci *  with the original object.
714bf215546Sopenharmony_ci */
715bf215546Sopenharmony_citemplate<typename C>
716bf215546Sopenharmony_ciclass ShallowClonePolicy : public ClonePolicy<C>
717bf215546Sopenharmony_ci{
718bf215546Sopenharmony_cipublic:
719bf215546Sopenharmony_ci   ShallowClonePolicy(C *c) : ClonePolicy<C>(c) {}
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ciprotected:
722bf215546Sopenharmony_ci   virtual void *lookup(void *obj)
723bf215546Sopenharmony_ci   {
724bf215546Sopenharmony_ci      return obj;
725bf215546Sopenharmony_ci   }
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci   virtual void insert(const void *obj, void *clone)
728bf215546Sopenharmony_ci   {
729bf215546Sopenharmony_ci   }
730bf215546Sopenharmony_ci};
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_citemplate<typename C, typename T>
733bf215546Sopenharmony_ciinline T *cloneShallow(C *c, T *obj)
734bf215546Sopenharmony_ci{
735bf215546Sopenharmony_ci   ShallowClonePolicy<C> pol(c);
736bf215546Sopenharmony_ci   return obj->clone(pol);
737bf215546Sopenharmony_ci}
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci/**
740bf215546Sopenharmony_ci *  Recursive cloning policy.
741bf215546Sopenharmony_ci *
742bf215546Sopenharmony_ci *  Objects cloned with the "deep" policy clone their children
743bf215546Sopenharmony_ci *  recursively, keeping track of what has already been cloned to
744bf215546Sopenharmony_ci *  avoid making several new copies of the same object.
745bf215546Sopenharmony_ci */
746bf215546Sopenharmony_citemplate<typename C>
747bf215546Sopenharmony_ciclass DeepClonePolicy : public ClonePolicy<C>
748bf215546Sopenharmony_ci{
749bf215546Sopenharmony_cipublic:
750bf215546Sopenharmony_ci   DeepClonePolicy(C *c) : ClonePolicy<C>(c) {}
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ciprivate:
753bf215546Sopenharmony_ci   std::map<const void *, void *> map;
754bf215546Sopenharmony_ci
755bf215546Sopenharmony_ciprotected:
756bf215546Sopenharmony_ci   virtual void *lookup(void *obj)
757bf215546Sopenharmony_ci   {
758bf215546Sopenharmony_ci      return map[obj];
759bf215546Sopenharmony_ci   }
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci   virtual void insert(const void *obj, void *clone)
762bf215546Sopenharmony_ci   {
763bf215546Sopenharmony_ci      map[obj] = clone;
764bf215546Sopenharmony_ci   }
765bf215546Sopenharmony_ci};
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_citemplate<typename S, typename T>
768bf215546Sopenharmony_cistruct bimap
769bf215546Sopenharmony_ci{
770bf215546Sopenharmony_ci   std::map<S, T> forth;
771bf215546Sopenharmony_ci   std::map<T, S> back;
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_cipublic:
774bf215546Sopenharmony_ci   bimap() : l(back), r(forth) { }
775bf215546Sopenharmony_ci   bimap(const bimap<S, T> &m)
776bf215546Sopenharmony_ci      : forth(m.forth), back(m.back), l(back), r(forth) { }
777bf215546Sopenharmony_ci
778bf215546Sopenharmony_ci   void insert(const S &s, const T &t)
779bf215546Sopenharmony_ci   {
780bf215546Sopenharmony_ci      forth.insert(std::make_pair(s, t));
781bf215546Sopenharmony_ci      back.insert(std::make_pair(t, s));
782bf215546Sopenharmony_ci   }
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   typedef typename std::map<T, S>::const_iterator l_iterator;
785bf215546Sopenharmony_ci   const std::map<T, S> &l;
786bf215546Sopenharmony_ci   typedef typename std::map<S, T>::const_iterator r_iterator;
787bf215546Sopenharmony_ci   const std::map<S, T> &r;
788bf215546Sopenharmony_ci};
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_ci} // namespace nv50_ir
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_ci#endif // __NV50_IR_UTIL_H__
793