Ignore:
Timestamp:
Dec 19, 2016, 2:39:35 PM (3 years ago)
Author:
nmedfort
Message:

Multi-threading support for PabloAST / PabloCompiler?. Requires unique LLVM Context / Module for each thread.

Location:
icGREP/icgrep-devel/icgrep/pablo
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/pablo/arithmetic.h

    r5227 r5230  
    3535    virtual ~Operator() { }
    3636protected:
    37     Operator(const ClassTypeId typeId, Type * const type, PabloAST * const expr1, PabloAST * const expr2)
    38     : PabloAST(typeId, type, nullptr)
     37    Operator(const ClassTypeId typeId, Type * const type, PabloAST * const expr1, PabloAST * const expr2, Allocator & allocator)
     38    : PabloAST(typeId, type, nullptr, allocator)
    3939    , mLH(expr1)
    4040    , mRH(expr2) {
     
    5555    } \
    5656protected: \
    57     Name(Type * const type, PabloAST * const expr1, PabloAST * const expr2) \
    58     : Operator(ClassTypeId::Name, type, expr1, expr2) { \
     57    Name(Type * const type, PabloAST * const expr1, PabloAST * const expr2, Allocator & allocator) \
     58    : Operator(ClassTypeId::Name, type, expr1, expr2, allocator) { \
    5959    } \
    6060};
  • icGREP/icgrep-devel/icgrep/pablo/boolean.h

    r5217 r5230  
    1717    virtual ~And() { }
    1818protected:
    19     And(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name)
    20     : Variadic(ClassTypeId::And, type, {expr1, expr2}, name)
     19    And(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name, Allocator & allocator)
     20    : Variadic(ClassTypeId::And, type, {expr1, expr2}, name, allocator)
    2121    {
    2222
    2323    }
    24     And(Type * const type, const unsigned reserved, const String * name)
    25     : Variadic(ClassTypeId::And, type, reserved, name)
     24    And(Type * const type, const unsigned reserved, const String * name, Allocator & allocator)
     25    : Variadic(ClassTypeId::And, type, reserved, name, allocator)
    2626    {
    2727
    2828    }
    2929    template<typename iterator>
    30     And(Type * const type, iterator begin, iterator end, const String * name)
    31     : Variadic(ClassTypeId::And, type, begin, end, name) {
     30    And(Type * const type, iterator begin, iterator end, const String * name, Allocator & allocator)
     31    : Variadic(ClassTypeId::And, type, begin, end, name, allocator) {
    3232
    3333    }
     
    4545    virtual ~Or() { }
    4646protected:
    47     Or(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name)
    48     : Variadic(ClassTypeId::Or, type, {expr1, expr2}, name)
     47    Or(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name, Allocator & allocator)
     48    : Variadic(ClassTypeId::Or, type, {expr1, expr2}, name, allocator)
    4949    {
    5050
    5151    }
    52     Or(Type * const type, const unsigned reserved, const String * name)
    53     : Variadic(ClassTypeId::Or, type, reserved, name)
     52    Or(Type * const type, const unsigned reserved, const String * name, Allocator & allocator)
     53    : Variadic(ClassTypeId::Or, type, reserved, name, allocator)
    5454    {
    5555
    5656    }
    5757    template<typename iterator>
    58     Or(Type * const type, iterator begin, iterator end, const String * name)
    59     : Variadic(ClassTypeId::Or, type, begin, end, name) {
     58    Or(Type * const type, iterator begin, iterator end, const String * name, Allocator & allocator)
     59    : Variadic(ClassTypeId::Or, type, begin, end, name, allocator) {
    6060
    6161    }
     
    7272    }
    7373protected:
    74     Xor(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name)
    75     : Variadic(ClassTypeId::Xor, type, {expr1, expr2}, name)
     74    Xor(Type * const type, PabloAST * expr1, PabloAST * expr2, const String * name, Allocator & allocator)
     75    : Variadic(ClassTypeId::Xor, type, {expr1, expr2}, name, allocator)
    7676    {
    7777
    7878    }
    79     Xor(Type * const type, const unsigned reserved, const String * name)
    80     : Variadic(ClassTypeId::Xor, type, reserved, name)
     79    Xor(Type * const type, const unsigned reserved, const String * name, Allocator & allocator)
     80    : Variadic(ClassTypeId::Xor, type, reserved, name, allocator)
    8181    {
    8282
    8383    }
    8484    template<typename iterator>
    85     Xor(Type * const type, iterator begin, iterator end, const String * name)
    86     : Variadic(ClassTypeId::Xor, type, begin, end, name) {
     85    Xor(Type * const type, iterator begin, iterator end, const String * name, Allocator & allocator)
     86    : Variadic(ClassTypeId::Xor, type, begin, end, name, allocator) {
    8787
    8888    }
     
    104104    }
    105105protected:
    106     Not(PabloAST * expr, const String * name)
    107     : Statement(ClassTypeId::Not, expr->getType(), {expr}, name)
     106    Not(PabloAST * expr, const String * name, Allocator & allocator)
     107    : Statement(ClassTypeId::Not, expr->getType(), {expr}, name, allocator)
    108108    {
    109109
     
    132132    }
    133133protected:
    134     Sel(PabloAST * condExpr, PabloAST * trueExpr, PabloAST * falseExpr, const String * name)
    135     : Statement(ClassTypeId::Sel, trueExpr->getType(), {condExpr, trueExpr, falseExpr}, name) {
     134    Sel(PabloAST * condExpr, PabloAST * trueExpr, PabloAST * falseExpr, const String * name, Allocator & allocator)
     135    : Statement(ClassTypeId::Sel, trueExpr->getType(), {condExpr, trueExpr, falseExpr}, name, allocator) {
    136136
    137137    }
  • icGREP/icgrep-devel/icgrep/pablo/branch.cpp

    r5227 r5230  
    55namespace pablo {
    66
    7 Branch::Branch(const ClassTypeId typeId, PabloAST * condition, PabloBlock * body)
    8 : Statement(typeId, nullptr, {condition}, nullptr)
     7Branch::Branch(const ClassTypeId typeId, PabloAST * condition, PabloBlock * body, Allocator &allocator)
     8: Statement(typeId, nullptr, {condition}, nullptr, allocator)
    99, mBody(body) {
    1010
  • icGREP/icgrep-devel/icgrep/pablo/branch.h

    r5227 r5230  
    4242    EscapedVars getEscaped() const;
    4343protected:
    44     Branch(const ClassTypeId typeId, PabloAST * condition, PabloBlock * body);
     44    Branch(const ClassTypeId typeId, PabloAST * condition, PabloBlock * body, Allocator & allocator);
    4545protected:
    4646    PabloBlock *            mBody;
     
    5656    }
    5757protected:
    58     If(PabloAST * condition, PabloBlock * body)
    59     : Branch(ClassTypeId::If, condition, body) {
     58    If(PabloAST * condition, PabloBlock * body, Allocator & allocator)
     59    : Branch(ClassTypeId::If, condition, body, allocator) {
    6060
    6161    }
     
    7171    }
    7272protected:
    73     While(PabloAST * condition, PabloBlock * body)
    74     : Branch(ClassTypeId::While, condition, body) {
     73    While(PabloAST * condition, PabloBlock * body, Allocator & allocator)
     74    : Branch(ClassTypeId::While, condition, body, allocator) {
    7575
    7676    }
  • icGREP/icgrep-devel/icgrep/pablo/builder.hpp

    r5229 r5230  
    5454
    5555    inline static PabloBuilder Create(PabloBuilder & builder) noexcept {
    56         return PabloBuilder(PabloBlock::Create(builder.getPabloBlock()), builder);
     56        return PabloBuilder(PabloBlock::Create(builder.getPabloBlock()->getParent()), builder);
    5757    }
    5858
  • icGREP/icgrep-devel/icgrep/pablo/codegenstate.cpp

    r5229 r5230  
    3636Call * PabloBlock::createCall(PabloAST * prototype, const std::vector<PabloAST *> &) {
    3737    assert (prototype);
    38     return insertAtInsertionPoint(new Call(prototype));
     38    return insertAtInsertionPoint(new (mAllocator) Call(prototype, mAllocator));
    3939}
    4040
    4141Count * PabloBlock::createCount(PabloAST * expr) {
    4242    Type * type = getParent()->getBuilder()->getSizeTy();
    43     return insertAtInsertionPoint(new Count(expr, makeName("count"), type));
     43    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName("count"), type, mAllocator));
    4444}
    4545
    4646Count * PabloBlock::createCount(PabloAST * const expr, const std::string & prefix)  {
    4747    Type * type = getParent()->getBuilder()->getSizeTy();
    48     return insertAtInsertionPoint(new Count(expr, makeName(prefix), type));
     48    return insertAtInsertionPoint(new (mAllocator) Count(expr, makeName(prefix), type, mAllocator));
    4949}
    5050
     
    5454        name = makeName("not");
    5555    }
    56     return insertAtInsertionPoint(new Not(expr, name));
     56    return insertAtInsertionPoint(new (mAllocator) Not(expr, name, mAllocator));
    5757}
    5858
     
    7272        name = makeName("inFile");
    7373    }
    74     return insertAtInsertionPoint(new InFile(expr, name));
     74    return insertAtInsertionPoint(new (mAllocator) InFile(expr, name, mAllocator));
    7575}
    7676
     
    8080        name = makeName("atEOF");
    8181    }
    82     return insertAtInsertionPoint(new AtEOF(expr, name));
     82    return insertAtInsertionPoint(new (mAllocator) AtEOF(expr, name, mAllocator));
    8383}
    8484   
     
    9090        name = makeName("advance");
    9191    }
    92     return insertAtInsertionPoint(new Advance(expr, shiftAmount, name));
     92    return insertAtInsertionPoint(new (mAllocator) Advance(expr, shiftAmount, name, mAllocator));
    9393}
    9494
     
    9797        name = makeName("lookahead");
    9898    }
    99     return insertAtInsertionPoint(new Lookahead(expr, shiftAmount, name));
     99    return insertAtInsertionPoint(new (mAllocator) Lookahead(expr, shiftAmount, name, mAllocator));
    100100}
    101101
     
    112112    }
    113113    Type * type = array->getType();
    114     if (LLVM_LIKELY(isa<StreamType>(type))) {
    115         type = cast<StreamType>(type)->getStreamElementType();
    116     } else if (LLVM_LIKELY(isa<ArrayType>(type))) {
     114    if (LLVM_LIKELY(isa<ArrayType>(type))) {
    117115        type = cast<ArrayType>(type)->getArrayElementType();
    118116    } else {
     
    124122        throw std::runtime_error(out.str());
    125123    }
    126     return insertAtInsertionPoint(new Extract(array, index, name, type));
     124    return insertAtInsertionPoint(new (mAllocator) Extract(array, index, name, type, mAllocator));
    127125}
    128126
     
    132130        name = makeName("and");
    133131    }
    134     return insertAtInsertionPoint(new And(expr1->getType(), expr1, expr2, name));
     132    return insertAtInsertionPoint(new (mAllocator) And(expr1->getType(), expr1, expr2, name, mAllocator));
    135133}
    136134
     
    139137        name = makeName("and");
    140138    }
    141     return insertAtInsertionPoint(new And(type, reserved, name));
     139    return insertAtInsertionPoint(new (mAllocator) And(type, reserved, name, mAllocator));
    142140}
    143141
     
    147145        name = makeName("or");
    148146    }
    149     return insertAtInsertionPoint(new Or(expr1->getType(), expr1, expr2, name));
     147    return insertAtInsertionPoint(new (mAllocator) Or(expr1->getType(), expr1, expr2, name, mAllocator));
    150148}
    151149
     
    154152        name = makeName("or");
    155153    }
    156     return insertAtInsertionPoint(new Or(type, reserved, name));
     154    return insertAtInsertionPoint(new (mAllocator) Or(type, reserved, name, mAllocator));
    157155}
    158156
     
    162160        name = makeName("xor");
    163161    }
    164     return insertAtInsertionPoint(new Xor(expr1->getType(), expr1, expr2, name));
     162    return insertAtInsertionPoint(new (mAllocator) Xor(expr1->getType(), expr1, expr2, name, mAllocator));
    165163}
    166164
     
    169167        name = makeName("xor");
    170168    }
    171     return insertAtInsertionPoint(new Xor(type, reserved, name));
     169    return insertAtInsertionPoint(new (mAllocator) Xor(type, reserved, name, mAllocator));
    172170}
    173171
    174172Add * PabloBlock::createAdd(PabloAST * expr1, PabloAST * expr2) {
    175173    CHECK_SAME_TYPE(expr1, expr2);
    176     return new Add(expr1->getType(), expr1, expr2);
     174    return new (mAllocator) Add(expr1->getType(), expr1, expr2, mAllocator);
    177175}
    178176
    179177Subtract * PabloBlock::createSubtract(PabloAST * expr1, PabloAST * expr2) {
    180178    CHECK_SAME_TYPE(expr1, expr2);
    181     return new Subtract(expr1->getType(), expr1, expr2);
     179    return new (mAllocator) Subtract(expr1->getType(), expr1, expr2, mAllocator);
    182180}
    183181
    184182LessThan * PabloBlock::createLessThan(PabloAST * expr1, PabloAST * expr2) {
    185183    CHECK_SAME_TYPE(expr1, expr2);
    186     return new LessThan(getParent()->getBuilder()->getInt1Ty(), expr1, expr2);
     184    return new (mAllocator) LessThan(getParent()->getBuilder()->getInt1Ty(), expr1, expr2, mAllocator);
    187185}
    188186
     
    241239    }
    242240
    243     return insertAtInsertionPoint(new Assign(var, value));
     241    return insertAtInsertionPoint(new (mAllocator) Assign(var, value, mAllocator));
    244242}
    245243
     
    249247        name = makeName("matchstar");
    250248    }
    251     return insertAtInsertionPoint(new MatchStar(marker, charclass, name));
     249    return insertAtInsertionPoint(new (mAllocator) MatchStar(marker, charclass, name, mAllocator));
    252250}
    253251
     
    257255        name = makeName("scanthru");
    258256    }
    259     return insertAtInsertionPoint(new ScanThru(from, thru, name));
     257    return insertAtInsertionPoint(new (mAllocator) ScanThru(from, thru, name, mAllocator));
    260258}
    261259
    262260If * PabloBlock::createIf(PabloAST * condition, PabloBlock * body) {
    263261    assert (condition);
    264     If * const node = insertAtInsertionPoint(new If(condition, body));
     262    If * const node = insertAtInsertionPoint(new (mAllocator) If(condition, body, mAllocator));
    265263    body->setBranch(node);
    266264    return node;
     
    269267While * PabloBlock::createWhile(PabloAST * condition, PabloBlock * body) {
    270268    assert (condition);
    271     While * const node = insertAtInsertionPoint(new While(condition, body));
     269    While * const node = insertAtInsertionPoint(new (mAllocator) While(condition, body, mAllocator));
    272270    body->setBranch(node);
    273271    return node;
     
    281279        name = makeName("sel");
    282280    }
    283     return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, name));
     281    return insertAtInsertionPoint(new (mAllocator) Sel(condition, trueExpr, falseExpr, name, mAllocator));
    284282}
    285283
     
    313311        stmt = stmt->eraseFromParent(recursively);
    314312    }
    315     mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(this));
    316 }
    317 
    318 }
     313}
     314
     315}
  • icGREP/icgrep-devel/icgrep/pablo/codegenstate.h

    r5229 r5230  
    6262
    6363    inline static PabloBlock * Create(PabloKernel * const parent) noexcept {
    64         return new PabloBlock(parent);
    65     }
    66 
    67     inline static PabloBlock * Create(PabloBlock * const predecessor) noexcept {
    68         return new PabloBlock(predecessor->mParent);
     64        Allocator & allocator = parent->mAllocator;
     65        return new (allocator) PabloBlock(parent, allocator);
    6966    }
    7067
     
    313310protected:
    314311
    315     explicit PabloBlock(PabloKernel * const parent) noexcept
    316     : PabloAST(PabloAST::ClassTypeId::Block, nullptr, nullptr)
     312    explicit PabloBlock(PabloKernel * const parent, Allocator & allocator) noexcept
     313    : PabloAST(PabloAST::ClassTypeId::Block, nullptr, nullptr, allocator)
    317314    , mParent(parent)
    318315    , mBranch(nullptr)
    319     , mScopeIndex(0) {
     316    , mScopeIndex(0)
     317    , mAllocator(allocator) {
    320318
    321319    }
     
    337335    Branch *                    mBranch;
    338336    unsigned                    mScopeIndex;
     337    Allocator &                 mAllocator;
    339338};
    340339
  • icGREP/icgrep-devel/icgrep/pablo/expression_map.hpp

    r5202 r5230  
    9898    friend struct ExpressionTable;
    9999
    100     using Allocator = LLVMAllocator;
     100    using Allocator = SlabAllocator<const PabloAST *>;
    101101
    102102    struct Key {
     
    105105        : mType(type)
    106106        , mArgs(1 + args.size())
    107         , mArg(allocator.Allocate<const PabloAST *>(mArgs)) {
     107        , mArg(allocator.allocate(mArgs)) {
    108108            unsigned i = 1;
    109109            mArg[0] = arg1;
     
    116116        : mType(type)
    117117        , mArgs(stmt->getNumOperands())
    118         , mArg(allocator.Allocate<const PabloAST *>(mArgs)) {
     118        , mArg(allocator.allocate(mArgs)) {
    119119            unsigned i = 0;
    120120            for (PabloAST * arg : *stmt) {
     
    170170        PabloAST * const f = find(key);
    171171        if (f) {
    172             mAllocator.Deallocate<const PabloAST *>(key.mArg);
     172            mAllocator.deallocate(key.mArg);
    173173            return f;
    174174        }
     
    182182        PabloAST * const entry = find(key);
    183183        if (entry) {
    184             mAllocator.Deallocate<const PabloAST *>(key.mArg);
     184            mAllocator.deallocate(key.mArg);
    185185            return std::make_pair(entry, false);
    186186        }
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/pablo_automultiplexing.cpp

    r5217 r5230  
    11#include "pablo_automultiplexing.hpp"
    22#include <pablo/builder.hpp>
    3 #include <pablo/prototype.h>
    43#include <pablo/printer_pablos.h>
    54#include <boost/container/flat_set.hpp>
  • icGREP/icgrep-devel/icgrep/pablo/pabloAST.cpp

    r5227 r5230  
    1616
    1717namespace pablo {
    18 
    19 PabloAST::Allocator PabloAST::mAllocator;
    20 PabloAST::VectorAllocator PabloAST::mVectorAllocator;
    2118
    2219using TypeId = PabloAST::ClassTypeId;
     
    280277    }
    281278
    282     mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(this));
    283279    return next;
    284280}
     
    307303    if (LLVM_UNLIKELY(mOperands == mCapacity)) {
    308304        mCapacity = std::max<unsigned>(mCapacity * 2, 2);
    309         PabloAST ** expandedOperandSpace = reinterpret_cast<PabloAST**>(mAllocator.allocate(mCapacity * sizeof(PabloAST *)));
     305        PabloAST ** expandedOperandSpace = mAllocator.allocate(mCapacity);
    310306        for (unsigned i = 0; i != mOperands; ++i) {
    311307            expandedOperandSpace[i] = mOperand[i];
    312308        }
    313         mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(mOperand));
     309        mAllocator.deallocate(mOperand);
    314310        mOperand = expandedOperandSpace;
    315311    }
  • icGREP/icgrep-devel/icgrep/pablo/pabloAST.h

    r5227 r5230  
    3838public:
    3939
    40     using Allocator = SlabAllocator<u_int8_t>;
    41     using VectorAllocator = SlabAllocator<PabloAST *>;
    42     using Users = std::vector<PabloAST *, VectorAllocator>;
     40    using Allocator = SlabAllocator<PabloAST *>;
     41    using Users = std::vector<PabloAST *, Allocator>;
    4342    using user_iterator = Users::iterator;
    4443    using const_user_iterator = Users::const_iterator;
     
    149148    }
    150149
    151     void * operator new (std::size_t size) noexcept {
    152         return mAllocator.allocate(size);
    153     }
    154 
    155     void operator delete (void * ptr) {
    156         mAllocator.deallocate(static_cast<Allocator::value_type *>(ptr));
    157     }
     150    void * operator new (std::size_t size, Allocator & allocator) noexcept {
     151        return allocator.allocate<uint8_t>(size);
     152    }
     153
     154//    void operator delete (void * ptr) {
     155//        mAllocator.deallocate(static_cast<Allocator::value_type *>(ptr));
     156//    }
    158157
    159158    void print(raw_ostream & O) const;
    160159
    161160protected:
    162     inline PabloAST(const ClassTypeId id, Type * const type, const String * name)
     161    inline PabloAST(const ClassTypeId id, Type * const type, const String * name, Allocator & allocator)
    163162    : mClassTypeId(id)
    164163    , mType(type)
    165164    , mName(name)
    166     , mUsers(mVectorAllocator)
    167     {
     165    , mUsers(allocator) {
    168166
    169167    }
     
    172170    virtual ~PabloAST() {
    173171        mUsers.clear();
    174     }   
    175     static Allocator        mAllocator;
    176     static VectorAllocator  mVectorAllocator;
     172    }       
    177173private:
    178174    const ClassTypeId       mClassTypeId;
     
    239235    virtual ~Statement() {}
    240236protected:
    241     explicit Statement(const ClassTypeId id, Type * const type, std::initializer_list<PabloAST *> operands, const String * const name)
    242     : PabloAST(id, type, name)
     237    explicit Statement(const ClassTypeId id, Type * const type, std::initializer_list<PabloAST *> operands, const String * const name, Allocator & allocator)
     238    : PabloAST(id, type, name, allocator)
    243239    , mNext(nullptr)
    244240    , mPrev(nullptr)
    245241    , mParent(nullptr)
    246242    , mOperands(operands.size())
    247     , mOperand(reinterpret_cast<PabloAST**>(mAllocator.allocate(mOperands * sizeof(PabloAST *)))) {
     243    , mOperand(allocator.allocate(mOperands)) {
    248244        unsigned i = 0;
    249245        for (PabloAST * const value : operands) {
     
    254250        }
    255251    }
    256     explicit Statement(const ClassTypeId id, Type * const type, const unsigned reserved, const String * const name)
    257     : PabloAST(id, type, name)
     252    explicit Statement(const ClassTypeId id, Type * const type, const unsigned reserved, const String * const name, Allocator & allocator)
     253    : PabloAST(id, type, name, allocator)
    258254    , mNext(nullptr)
    259255    , mPrev(nullptr)
    260256    , mParent(nullptr)
    261257    , mOperands(0)
    262     , mOperand(reinterpret_cast<PabloAST**>(mAllocator.allocate(reserved * sizeof(PabloAST *)))) {
     258    , mOperand(allocator.allocate(mOperands)) {
    263259        std::memset(mOperand, 0, reserved * sizeof(PabloAST *));
    264260    }
    265261    template<typename iterator>
    266     explicit Statement(const ClassTypeId id, Type * const type, iterator begin, iterator end, const String * const name)
    267     : PabloAST(id, type, name)
     262    explicit Statement(const ClassTypeId id, Type * const type, iterator begin, iterator end, const String * const name, Allocator & allocator)
     263    : PabloAST(id, type, name, allocator)
    268264    , mNext(nullptr)
    269265    , mPrev(nullptr)
    270266    , mParent(nullptr)
    271267    , mOperands(std::distance(begin, end))
    272     , mOperand(reinterpret_cast<PabloAST**>(mAllocator.allocate(mOperands * sizeof(PabloAST *)))) {
     268    , mOperand(allocator.allocate(mOperands)) {
    273269        unsigned i = 0;
    274270        for (auto value = begin; value != end; ++value, ++i) {
     
    348344
    349345protected:
    350     explicit Variadic(const ClassTypeId id, Type * const type, std::initializer_list<PabloAST *> operands, const String * const name)
    351     : Statement(id, type, operands, name)
    352     , mCapacity(operands.size()) {
    353 
    354     }
    355     explicit Variadic(const ClassTypeId id, Type * const type, const unsigned reserved, const String * name)
    356     : Statement(id, type, reserved, name)
    357     , mCapacity(reserved) {
     346    explicit Variadic(const ClassTypeId id, Type * const type, std::initializer_list<PabloAST *> operands, const String * const name, Allocator & allocator)
     347    : Statement(id, type, operands, name, allocator)
     348    , mCapacity(operands.size())
     349    , mAllocator(allocator) {
     350
     351    }
     352    explicit Variadic(const ClassTypeId id, Type * const type, const unsigned reserved, const String * name, Allocator & allocator)
     353    : Statement(id, type, reserved, name, allocator)
     354    , mCapacity(reserved)
     355    , mAllocator(allocator) {
    358356
    359357    }
    360358    template<typename iterator>
    361     explicit Variadic(const ClassTypeId id, Type * const type, iterator begin, iterator end, const String * name)
    362     : Statement(id, type, begin, end, name)
    363     , mCapacity(std::distance(begin, end)) {
     359    explicit Variadic(const ClassTypeId id, Type * const type, iterator begin, iterator end, const String * name, Allocator & allocator)
     360    : Statement(id, type, begin, end, name, allocator)
     361    , mCapacity(std::distance(begin, end))
     362    , mAllocator(allocator) {
    364363
    365364    }
    366365private:
    367366    unsigned        mCapacity;
     367    Allocator &     mAllocator;
    368368};
    369369
  • icGREP/icgrep-devel/icgrep/pablo/pablo_kernel.cpp

    r5229 r5230  
    77#include <pablo/codegenstate.h>
    88#include <pablo/pablo_compiler.h>
    9 #include <llvm/Support/Debug.h>
     9// #include <llvm/Support/Debug.h>
    1010#include <pablo/pe_var.h>
    1111#include <llvm/IR/Verifier.h>
    1212#include <IDISA/idisa_builder.h>
    13 #include <pablo/prototype.h>
    14 #include <stack>
    1513
    1614using namespace pablo;
     
    2018
    2119Var * PabloKernel::addInput(const std::string name, Type * const type) {
    22     Var * param = new Var(mSymbolTable->make(name), type, true);
     20    Var * param = new (mAllocator) Var(mSymbolTable->make(name, iBuilder), type, mAllocator, true);
    2321    mInputs.push_back(param);
    2422    if (isa<ArrayType>(type) || isa<StreamType>(type)) {
     
    3230
    3331Var * PabloKernel::addOutput(const std::string name, Type * const type) {
    34     Var * result = new Var(mSymbolTable->make(name), type, false);
     32    Var * result = new (mAllocator) Var(mSymbolTable->make(name, iBuilder), type, mAllocator, false);
    3533    mOutputs.push_back(result);
    3634    if (isa<ArrayType>(type) || isa<StreamType>(type)) {
     
    4442
    4543Var * PabloKernel::makeVariable(PabloAST * name, Type * const type) {
    46     Var * const var = new Var(name, type);
     44    Var * const var = new (mAllocator) Var(name, type, mAllocator);
    4745    mVariables.push_back(var);
    4846    return var;
     
    5856        }
    5957    }
    60     Zeroes * value = new Zeroes(type);
     58    Zeroes * value = new (mAllocator) Zeroes(type, mAllocator);
    6159    mConstants.push_back(value);
    6260    return value;
     
    7270        }
    7371    }
    74     Ones * value = new Ones(type);
     72    Ones * value = new (mAllocator) Ones(type, mAllocator);
    7573    mConstants.push_back(value);
    7674    return value;
     
    131129: KernelBuilder(builder, kernelName, {}, {}, {}, {}, {Binding{builder->getBitBlockType(), "EOFbit"}, Binding{builder->getBitBlockType(), "EOFmask"}})
    132130, mPabloCompiler(new PabloCompiler(this))
    133 , mSymbolTable(new SymbolGenerator())
     131, mSymbolTable(new SymbolGenerator(mAllocator))
    134132, mEntryBlock(PabloBlock::Create(this))
    135133{
  • icGREP/icgrep-devel/icgrep/pablo/pablo_kernel.h

    r5217 r5230  
    99#include <kernels/kernel.h>
    1010#include <pablo/symbol_generator.h>
     11#include <util/slab_allocator.h>
    1112
    1213namespace IDISA {
     
    3334
    3435public:
     36
     37    using Allocator = PabloAST::Allocator;
    3538
    3639    PabloKernel(IDISA::IDISA_Builder * builder, const std::string & kernelName);
     
    115118
    116119    inline String * getName(const std::string & name) const {
    117         return mSymbolTable->get(name);
     120        return mSymbolTable->get(name, iBuilder);
    118121    }
    119122
    120123    inline String * makeName(const std::string & prefix) const {
    121         return mSymbolTable->make(prefix);
     124        return mSymbolTable->make(prefix, iBuilder);
    122125    }
    123126
     
    128131private:
    129132
     133    Allocator                       mAllocator;
    130134    PabloCompiler * const           mPabloCompiler;
    131135    SymbolGenerator *               mSymbolTable;
    132136    PabloBlock *                    mEntryBlock;
     137
    133138    std::vector<Var *>              mInputs;
    134139    std::vector<Var *>              mOutputs;
  • icGREP/icgrep-devel/icgrep/pablo/pablo_toolchain.cpp

    r5227 r5230  
    2020#include <pablo/optimizers/schedulingprepass.h>
    2121#endif
    22 #include <pablo/prototype.h>
    2322#include <pablo/analysis/pabloverifier.hpp>
    2423#include <pablo/printer_pablos.h>
    2524#include <llvm/Support/CommandLine.h>
    2625#include <llvm/Support/FileSystem.h>
     26#include <llvm/Support/raw_ostream.h>
    2727#ifdef PRINT_TIMING_INFORMATION
    2828#include <hrtime.h>
     
    176176    if (DebugOptions.isSet(PrintCompiledREcode)) {
    177177        //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
    178         llvm::raw_os_ostream cerr(std::cerr);
    179         cerr << "Initial Pablo AST:\n";
    180         PabloPrinter::print(kernel, cerr);
     178        errs() << "Initial Pablo AST:\n";
     179        PabloPrinter::print(kernel, errs());
    181180    }
    182181   
     
    243242    if (DebugOptions.isSet(PrintUnloweredCode)) {
    244243        //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
    245         llvm::raw_os_ostream cerr(std::cerr);
    246         cerr << "Unlowered Pablo AST:\n";
    247         PabloPrinter::print(kernel, cerr);
     244        errs() << "Unlowered Pablo AST:\n";
     245        PabloPrinter::print(kernel, errs());
    248246    }
    249247    #ifdef PRINT_TIMING_INFORMATION
     
    267265        if (PabloOutputFilename.empty()) {
    268266            //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
    269             llvm::raw_os_ostream cerr(std::cerr);
    270             cerr << "Final Pablo AST:\n";
    271             PabloPrinter::print(kernel, cerr);
     267            errs() << "Final Pablo AST:\n";
     268            PabloPrinter::print(kernel, errs());
    272269        } else {
    273270            std::error_code error;
     
    277274    }
    278275#ifdef PRINT_TIMING_INFORMATION
    279     std::cerr << "PABLO OPTIMIZATION TIME: " << (optimization_end - optimization_start) << std::endl;
    280     std::cerr << "  SIMPLIFICATION TIME: " << (simplification_end - simplification_start) << std::endl;
    281     std::cerr << "  COALESCING TIME: " << (coalescing_end - coalescing_start) << std::endl;
    282     std::cerr << "  SINKING TIME: " << (sinking_end - sinking_start) << std::endl;
    283     std::cerr << "  PRE-DISTRIBUTION TIME: " << (pre_distribution_end - pre_distribution_start) << std::endl;
    284     std::cerr << "  MULTIPLEXING TIME: " << (multiplexing_end - multiplexing_start) << std::endl;
    285     std::cerr << "  LOWERING TIME: " << (lowering_end - lowering_start) << std::endl;
    286     std::cerr << "  FLATTENIF TIME: " << (flattenif_end - flattenif_start) << std::endl;
    287     std::cerr << "  POST-DISTRIBUTION TIME: " << (post_distribution_end - post_distribution_start) << std::endl;
    288     std::cerr << "  SCHEDULING TIME: " << (scheduling_end - scheduling_start) << std::endl;
    289     std::cerr << "PABLO STATEMENTS: " << COUNT_STATEMENTS(function) << std::endl;
    290     std::cerr << "PABLO ADVANCES: " << COUNT_ADVANCES(function) << std::endl;
    291     std::cerr << "PRE-LOWERING VARIADIC DISTRIBUTION: ";
     276    errs() << "PABLO OPTIMIZATION TIME: " << (optimization_end - optimization_start) << "\n";
     277    errs() << "  SIMPLIFICATION TIME: " << (simplification_end - simplification_start) << "\n";
     278    errs() << "  COALESCING TIME: " << (coalescing_end - coalescing_start) << "\n";
     279    errs() << "  SINKING TIME: " << (sinking_end - sinking_start) << "\n";
     280    errs() << "  PRE-DISTRIBUTION TIME: " << (pre_distribution_end - pre_distribution_start) << "\n";
     281    errs() << "  MULTIPLEXING TIME: " << (multiplexing_end - multiplexing_start) << "\n";
     282    errs() << "  LOWERING TIME: " << (lowering_end - lowering_start) << "\n";
     283    errs() << "  FLATTENIF TIME: " << (flattenif_end - flattenif_start) << "\n";
     284    errs() << "  POST-DISTRIBUTION TIME: " << (post_distribution_end - post_distribution_start) << "\n";
     285    errs() << "  SCHEDULING TIME: " << (scheduling_end - scheduling_start) << "\n";
     286    errs() << "PABLO STATEMENTS: " << COUNT_STATEMENTS(function) << "\n";
     287    errs() << "PABLO ADVANCES: " << COUNT_ADVANCES(function) << "\n";
     288    errs() << "PRE-LOWERING VARIADIC DISTRIBUTION: ";
    292289    bool join = false;
    293290    for (auto dist : distribution) {
    294291        if (join) {
    295             std::cerr << ';';
    296         }
    297         std::cerr << dist.first << '|' << dist.second;
     292            errs() << ';';
     293        }
     294        errs() << dist.first << '|' << dist.second;
    298295        join = true;
    299296    }
    300     std::cerr << std::endl;
    301 #endif
    302 }
    303 
    304 }
     297    errs() << "\n";
     298#endif
     299}
     300
     301}
  • icGREP/icgrep-devel/icgrep/pablo/pe_advance.h

    r5227 r5230  
    3232    }
    3333protected:
    34     Advance(PabloAST * expr, PabloAST * shiftAmount, const String * name)
    35     : Statement(ClassTypeId::Advance, expr->getType(), {expr, shiftAmount}, name)
    36     {
     34    Advance(PabloAST * expr, PabloAST * shiftAmount, const String * name, Allocator & allocator)
     35    : Statement(ClassTypeId::Advance, expr->getType(), {expr, shiftAmount}, name, allocator) {
    3736        assert(isa<Integer>(shiftAmount));
    3837    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_call.h

    r5217 r5230  
    2424        return getPrototype()->getName();
    2525    }
    26     inline void setLocalCarryIndex(const unsigned idx) {
    27         mLocalCarryIndex = idx;
    28     }
    29     inline unsigned getLocalCarryIndex() const {
    30         return mLocalCarryIndex;
    31     }
    3226protected:
    33     Call(PabloAST * prototype)
    34     : Statement(ClassTypeId::Call, nullptr, {prototype}, prototype->getName())
    35     , mLocalCarryIndex(0) {
     27    Call(PabloAST * prototype, Allocator & allocator)
     28    : Statement(ClassTypeId::Call, nullptr, {prototype}, prototype->getName(), allocator) {
    3629
    3730    }
    38 private:
    39     unsigned mLocalCarryIndex;
    4031};
    4132}
  • icGREP/icgrep-devel/icgrep/pablo/pe_constant.h

    r5202 r5230  
    2424    }
    2525protected:
    26     Constant(Type * type, const PabloAST * const value) : Constant(ClassTypeId::Ones, type), mValue(value) { }
     26    Constant(Type * type, const PabloAST * const value, Allocator & allocator)
     27    : PabloAST(ClassTypeId::Ones, type, allocators)
     28    , mValue(value) {
     29    }
    2730private:
    2831
  • icGREP/icgrep-devel/icgrep/pablo/pe_count.h

    r5217 r5230  
    2727    }
    2828protected:
    29     explicit Count(PabloAST * expr, const String * counter, Type * type)
    30     : Statement(ClassTypeId::Count, type, {expr}, counter) {
     29    explicit Count(PabloAST * expr, const String * name, Type * type, Allocator & allocator)
     30    : Statement(ClassTypeId::Count, type, {expr}, name, allocator) {
    3131
    3232    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_infile.h

    r5202 r5230  
    2727    }
    2828protected:
    29     InFile(PabloAST * expr, const String * name)
    30     : Statement(ClassTypeId::InFile, expr->getType(), {expr}, name) {
     29    InFile(PabloAST * expr, const String * name, Allocator & allocator)
     30    : Statement(ClassTypeId::InFile, expr->getType(), {expr}, name, allocator) {
    3131
    3232    }
     
    4848    }
    4949protected:
    50     AtEOF(PabloAST * expr, const String * name)
    51     : Statement(ClassTypeId::AtEOF, expr->getType(), {expr}, name) {
     50    AtEOF(PabloAST * expr, const String * name, Allocator & allocator)
     51    : Statement(ClassTypeId::AtEOF, expr->getType(), {expr}, name, allocator) {
    5252
    5353    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_integer.h

    r5227 r5230  
    2424    }
    2525protected:
    26     Integer(const IntTy value, Type * type) noexcept
    27     : PabloAST(ClassTypeId::Integer, type, nullptr)
     26    Integer(const IntTy value, Type * type, Allocator & allocator) noexcept
     27    : PabloAST(ClassTypeId::Integer, type, nullptr, allocator)
    2828    , mValue(value)
    2929    {
  • icGREP/icgrep-devel/icgrep/pablo/pe_lookahead.h

    r5227 r5230  
    3232    }
    3333protected:
    34     Lookahead(PabloAST * expr, PabloAST * shiftAmount, const String * name)
    35     : Statement(ClassTypeId::Lookahead, expr->getType(), {expr, shiftAmount}, name)
    36     {
     34    Lookahead(PabloAST * expr, PabloAST * shiftAmount, const String * name, Allocator & allocator)
     35    : Statement(ClassTypeId::Lookahead, expr->getType(), {expr, shiftAmount}, name, allocator) {
    3736        assert(isa<Integer>(shiftAmount));
    3837    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_matchstar.h

    r5227 r5230  
    2929    virtual ~MatchStar() {}
    3030protected:
    31     MatchStar(PabloAST * marker,  PabloAST * cc, const String * name)
    32     : Statement(ClassTypeId::MatchStar, marker->getType(), {marker, cc}, name) {
    33 
     31    MatchStar(PabloAST * marker,  PabloAST * cc, const String * name, Allocator & allocator)
     32    : Statement(ClassTypeId::MatchStar, marker->getType(), {marker, cc}, name, allocator) {
    3433    }
    3534};
  • icGREP/icgrep-devel/icgrep/pablo/pe_ones.h

    r5217 r5230  
    3131    }
    3232protected:
    33     Ones(Type * const type) : PabloAST(ClassTypeId::Ones, type, nullptr) { }
     33    Ones(Type * const type, Allocator & allocator)
     34    : PabloAST(ClassTypeId::Ones, type, nullptr, allocator) {
     35    }
    3436};
    3537
  • icGREP/icgrep-devel/icgrep/pablo/pe_scanthru.h

    r5227 r5230  
    3030    }
    3131protected:
    32     ScanThru(PabloAST * from, PabloAST * thru, const String * name)
    33     : Statement(ClassTypeId::ScanThru, from->getType(), {from, thru}, name) {
     32    ScanThru(PabloAST * from, PabloAST * thru, const String * name, Allocator & allocator)
     33    : Statement(ClassTypeId::ScanThru, from->getType(), {from, thru}, name, allocator) {
    3434
    3535    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_setithbit.h

    r5217 r5230  
    2727    virtual ~SetIthBit() {}
    2828protected:
    29     explicit SetIthBit(PabloAST * var, PabloAST * position, PabloAST * value, const PabloAST * name)
    30     : Statement(ClassTypeId::SetIthBit, {var, cast<Integer>(position), cast<Integer>(value)}, cast<String>(name)) {
     29    explicit SetIthBit(PabloAST * var, PabloAST * position, PabloAST * value, const PabloAST * name, Allocator & allocator)
     30    : Statement(ClassTypeId::SetIthBit, {var, cast<Integer>(position), cast<Integer>(value)}, cast<String>(name), allocator) {
    3131
    3232    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_string.h

    r5202 r5230  
    3939    }
    4040protected:
    41     String(const std::string & value) noexcept
    42     : PabloAST(ClassTypeId::String, llvm::Type::getInt8PtrTy(llvm::getGlobalContext()), this)
    43     , mValue(duplicate(value))
    44     {
     41    String(Type * type, const std::string & value, Allocator & allocator) noexcept
     42    : PabloAST(ClassTypeId::String, type, this, allocator)
     43    , mValue(duplicate(value, allocator)) {
    4544
    4645    }
    47     inline const char * duplicate(const std::string & value) {
    48         char * string = reinterpret_cast<char*>(mAllocator.allocate(value.length() + 1));
     46
     47    inline const char * duplicate(const std::string & value, Allocator & allocator) {
     48        char * string = reinterpret_cast<char*>(allocator.allocate<char*>(value.length() + 1));
    4949        std::memcpy(string, value.c_str(), value.length());
    5050        string[value.length()] = '\0';
  • icGREP/icgrep-devel/icgrep/pablo/pe_var.h

    r5227 r5230  
    3535    }
    3636protected:
    37     Var(const PabloAST * name, Type * const type, const bool readOnly = false)
    38     : PabloAST(ClassTypeId::Var, type, cast<String>(name))
     37    Var(const PabloAST * name, Type * const type, Allocator & allocator, const bool readOnly = false)
     38    : PabloAST(ClassTypeId::Var, type, cast<String>(name), allocator)
    3939    , mReadOnly(readOnly) {
    4040
     
    6262    }
    6363protected:
    64     Extract(PabloAST * array, PabloAST * const index, const String * const name, Type * type)
    65     : Statement(ClassTypeId::Extract, type, {array, index}, name) {
     64    Extract(PabloAST * array, PabloAST * const index, const String * const name, Type * type, Allocator & allocator)
     65    : Statement(ClassTypeId::Extract, type, {array, index}, name, allocator) {
    6666
    6767    }
  • icGREP/icgrep-devel/icgrep/pablo/pe_zeroes.h

    r5217 r5230  
    3333    }
    3434protected:
    35     Zeroes(Type * const type) : PabloAST(ClassTypeId::Zeroes, type, nullptr) { }
     35    Zeroes(Type * const type, Allocator & allocator)
     36    : PabloAST(ClassTypeId::Zeroes, type, nullptr, allocator) {
     37    }
    3638};
    3739
  • icGREP/icgrep-devel/icgrep/pablo/prototype.cpp

    r5217 r5230  
    55namespace pablo {
    66
    7 Prototype::Prototype(const PabloAST::ClassTypeId type, std::string && name, const unsigned numOfParameters, const unsigned numOfResults)
    8 : PabloAST(type, nullptr, nullptr)
     7Prototype::Prototype(const PabloAST::ClassTypeId type, std::string && name, const unsigned numOfParameters, const unsigned numOfResults, Allocator &allocator)
     8: PabloAST(type, nullptr, nullptr, allocator)
    99, mName(GlobalSymbolGenerator.get(name))
    1010, mNumOfParameters(numOfParameters)
  • icGREP/icgrep-devel/icgrep/pablo/prototype.h

    r5217 r5230  
    2424    }
    2525
    26     static Prototype * Create(std::string name, const unsigned numOfParameters, const unsigned numOfResults, void * functionPtr = nullptr);
     26//    static Prototype * Create(std::string name, const unsigned numOfParameters, const unsigned numOfResults, void * functionPtr = nullptr);
    2727
    2828    const String * getName() const {
     
    3939
    4040protected:
    41     Prototype(const PabloAST::ClassTypeId type, std::string && name, const unsigned numOfParameters, const unsigned numOfResults);
     41    Prototype(const PabloAST::ClassTypeId type, std::string && name, const unsigned numOfParameters, const unsigned numOfResults, Allocator & allocator);
    4242protected:
    4343    const String * const    mName;
     
    4646};
    4747
    48 inline Prototype * Prototype::Create(std::string name, const unsigned numOfParameters, const unsigned numOfResults, void *) {
    49     return new Prototype(PabloAST::ClassTypeId::Prototype, std::move(name), numOfParameters, numOfResults);
    50 }
     48//inline Prototype * Prototype::Create(std::string name, const unsigned numOfParameters, const unsigned numOfResults, void *) {
     49//    return new Prototype(PabloAST::ClassTypeId::Prototype, std::move(name), numOfParameters, numOfResults);
     50//}
    5151
    5252}
  • icGREP/icgrep-devel/icgrep/pablo/ps_assign.h

    r5202 r5230  
    3333    }
    3434protected:
    35     explicit Assign(PabloAST * variable, PabloAST * expr)
    36     : Statement(ClassTypeId::Assign, nullptr, {variable, expr}, nullptr) {
     35    explicit Assign(PabloAST * variable, PabloAST * expr, Allocator & allocator)
     36    : Statement(ClassTypeId::Assign, nullptr, {variable, expr}, nullptr, allocator) {
    3737
    3838    }
  • icGREP/icgrep-devel/icgrep/pablo/symbol_generator.cpp

    r5217 r5230  
    1212namespace pablo {
    1313
    14 String * SymbolGenerator::get(const std::string name) {
     14String * SymbolGenerator::get(const std::string name, IDISA::IDISA_Builder * builder) {
    1515    if (LLVM_UNLIKELY(name.length() == 0)) {
    1616        throw std::runtime_error("symbol name cannot be 0-length");
     
    1919    String * result = nullptr;
    2020    if (f == mStringMap.end()) {
    21         result = new String(name);
     21        result = new (mAllocator) String(builder->getInt8PtrTy(), name, mAllocator);
    2222        assert (result);
    2323        mStringMap.insert(std::make_pair(std::move(name), result));
     
    3333    Integer * result;
    3434    if (f == mIntegerMap.end()) {
    35         result = new Integer(value, builder->getSizeTy());
     35        result = new (mAllocator) Integer(value, builder->getSizeTy(), mAllocator);
    3636        assert (result->value() == value);
    3737        mIntegerMap.insert(std::make_pair(value, result));
     
    4242}
    4343
    44 String * SymbolGenerator::make(const std::string prefix) {
     44String * SymbolGenerator::make(const std::string prefix, IDISA::IDISA_Builder * builder) {
    4545    auto f = mPrefixMap.find(prefix);
    4646    if (f == mPrefixMap.end()) {
    4747        mPrefixMap.insert(std::make_pair(prefix, 1));
    48         return get(prefix);
     48        return get(prefix, builder);
    4949    } else {
    5050        const unsigned count = f->second++;
    51         return get(prefix + '_' + std::to_string(count));
     51        return get(prefix + '_' + std::to_string(count), builder);
    5252    }
    5353}
  • icGREP/icgrep-devel/icgrep/pablo/symbol_generator.h

    r5217 r5230  
    2424    friend class PabloBlock;
    2525    using Twine = llvm::Twine;
     26    using Allocator = PabloAST::Allocator;
    2627public:
    2728    typedef int64_t integer_t;
    28     String * get(const std::string name);
    29     String * make(const std::string prefix);
     29    String * get(const std::string name, IDISA::IDISA_Builder * builder);
     30    String * make(const std::string prefix, IDISA::IDISA_Builder *builder);
    3031    Integer * getInteger(const integer_t value, IDISA::IDISA_Builder * builder);
    31     SymbolGenerator() = default;
     32    SymbolGenerator(Allocator & allocator) : mAllocator(allocator) {}
    3233    ~SymbolGenerator() = default;
    3334private:
     35    Allocator &                                 mAllocator;
    3436    std::unordered_map<std::string, integer_t>  mPrefixMap;
    3537    std::unordered_map<std::string, String *>   mStringMap;
Note: See TracChangeset for help on using the changeset viewer.