Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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