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 |
||
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 |
||
687 | { |
||
688 | void *clone = lookup(obj); |
||
689 | if (!clone) |
||
690 | clone = obj->clone(*this); |
||
691 | return reinterpret_cast |
||
692 | } |
||
693 | |||
694 | template |
||
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 |
||
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 |
||
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 |
||
747 | |||
748 | private: |
||
749 | std::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 |
||
767 | std::map |
||
768 | |||
769 | public: |
||
770 | bimap() : l(back), r(forth) { } |
||
771 | bimap(const bimap |
||
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 |
||
781 | const std::map |
||
782 | typedef typename std::map |
||
783 | const std::map |
||
784 | }; |
||
785 | |||
786 | } // namespace nv50_ir |
||
787 | |||
788 | #endif // __NV50_IR_UTIL_H__><>>><>><>>=>><>><>=>=>=>><>>><>><>=>=>=>><>>>><>><>=>=>=>><>>=>>>>>>=><=>=> |