Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 <new>
  27. #include <assert.h>
  28. #include <stdio.h>
  29. #include <memory>
  30. #include <map>
  31.  
  32. #ifndef NDEBUG
  33. # include <typeinfo>
  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<Iterator> 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<typename C>
  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<typename T> T *get(T *obj)
  687.    {
  688.       void *clone = lookup(obj);
  689.       if (!clone)
  690.          clone = obj->clone(*this);
  691.       return reinterpret_cast<T *>(clone);
  692.    }
  693.  
  694.    template<typename T> 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<typename C>
  712. class ShallowClonePolicy : public ClonePolicy<C>
  713. {
  714. public:
  715.    ShallowClonePolicy(C *c) : ClonePolicy<C>(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<typename C, typename T>
  729. inline T *cloneShallow(C *c, T *obj)
  730. {
  731.    ShallowClonePolicy<C> 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<typename C>
  743. class DeepClonePolicy : public ClonePolicy<C>
  744. {
  745. public:
  746.    DeepClonePolicy(C *c) : ClonePolicy<C>(c) {}
  747.  
  748. private:
  749.    std::map<const void *, void *> 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<typename S, typename T>
  764. struct bimap
  765. {
  766.    std::map<S, T> forth;
  767.    std::map<T, S> back;
  768.  
  769. public:
  770.    bimap() : l(back), r(forth) { }
  771.    bimap(const bimap<S, T> &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<T, S>::const_iterator l_iterator;
  781.    const std::map<T, S> &l;
  782.    typedef typename std::map<S, T>::const_iterator r_iterator;
  783.    const std::map<S, T> &r;
  784. };
  785.  
  786. } // namespace nv50_ir
  787.  
  788. #endif // __NV50_IR_UTIL_H__
  789.