Analysis: infer when a refcount is required and add colors in DebugVisitor 40/17240/2
Calixte DENIZET [Wed, 23 Sep 2015 14:53:00 +0000 (16:53 +0200)]
Change-Id: Ia34946b02bc3758ff35a7f523789b459c8cad2f3

16 files changed:
scilab/modules/ast/includes/analysis/Decorator.hxx
scilab/modules/ast/includes/analysis/Result.hxx
scilab/modules/ast/includes/analysis/data/ArgIOInfo.hxx [new file with mode: 0644]
scilab/modules/ast/includes/analysis/data/Block.hxx
scilab/modules/ast/includes/analysis/data/Data.hxx
scilab/modules/ast/includes/analysis/data/FunctionBlock.hxx
scilab/modules/ast/includes/analysis/data/Info.hxx
scilab/modules/ast/includes/analysis/data/LocalInfo.hxx [new file with mode: 0644]
scilab/modules/ast/includes/ast/debugvisitor.hxx
scilab/modules/ast/includes/exps/exp.hxx
scilab/modules/ast/src/cpp/analysis/Block.cpp
scilab/modules/ast/src/cpp/analysis/Data.cpp
scilab/modules/ast/src/cpp/analysis/FunctionBlock.cpp
scilab/modules/ast/src/cpp/analysis/Info.cpp
scilab/modules/ast/src/cpp/analysis/XBlock.cpp
scilab/modules/ast/src/cpp/ast/debugvisitor.cpp

index f28f3ad..021d5a2 100644 (file)
@@ -25,12 +25,10 @@ struct Decorator
 {
     Result res;
     OptionalDecoration opt;
-    bool cloneData;
     bool deleteData;
-    bool hasRefCount;
     bool safe;
 
-    Decorator() : res(), opt(), cloneData(false), deleteData(false), hasRefCount(false), safe(false) { }
+    Decorator() : res(), opt(), deleteData(false), safe(false) { }
 
     ~Decorator()
     {
@@ -123,10 +121,14 @@ struct Decorator
         {
             out << L", " << deco.opt;
         }
-        out << L", Cl:" << (deco.cloneData ? L"T" : L"F")
-            << L", Del:" << (deco.deleteData ? L"T" : L"F")
-            << L", RefC:" << (deco.hasRefCount ? L"T" : L"F")
-            << L", Safe:" << (deco.safe ? L"T" : L"F");
+        if (deco.deleteData)
+        {
+            out << L", Del: T";
+        }
+        if (deco.safe)
+        {
+            out << L", Safe: T";
+        }
 
         return out;
     }
index 1c73fad..f283d84 100644 (file)
@@ -77,14 +77,14 @@ public:
     }
 
     inline bool isTemp() const
-       {
-           return tempId != -1;
-       }
+    {
+        return tempId != -1;
+    }
 
     inline bool hasGVNValue() const
-       {
-           return constant.getGVNValue() != nullptr;
-       }
+    {
+        return constant.getGVNValue() != nullptr;
+    }
 
     inline ConstantValue & getConstant()
     {
@@ -125,19 +125,19 @@ public:
     }
 
     inline bool isAnInt() const
-       {
-           return hasGVNValue() || getRange().isValid();
-       }
+    {
+        return hasGVNValue() || getRange().isValid();
+    }
 
     inline SymbolicDimension & getMaxIndex()
-       {
-           return maxIndex;
-       }
-    
+    {
+        return maxIndex;
+    }
+
     inline const SymbolicDimension & getMaxIndex() const
-       {
-           return maxIndex;
-       }
+    {
+        return maxIndex;
+    }
 
     inline SymbolicDimension & setMaxIndex(SymbolicDimension & _maxIndex)
     {
@@ -150,13 +150,24 @@ public:
         maxIndex = _maxIndex;
         return maxIndex;
     }
-    
+
     friend std::wostream & operator<<(std::wostream & out, const Result & res)
     {
-        out << L"Result {" << res.type
-           << L", temp id:" << res.tempId
-           << L", constant:" << res.constant
-           << L", isAnInt:" << (res.isAnInt() ? L"T" : L"F") << L"}";
+        out << L"Result {" << res.type;
+        if (res.tempId != -1)
+        {
+            out << L", temp id:" << res.tempId;
+        }
+        if (res.constant.isKnown())
+        {
+            out << L", constant:" << res.constant;
+        }
+        if (res.isAnInt())
+        {
+            out << L", isAnInt: T";
+        }
+        out << L'}';
+
         return out;
     }
 };
diff --git a/scilab/modules/ast/includes/analysis/data/ArgIOInfo.hxx b/scilab/modules/ast/includes/analysis/data/ArgIOInfo.hxx
new file mode 100644 (file)
index 0000000..9bc3527
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __ARGIO_INFO_HXX__
+#define __ARGIO_INFO_HXX__
+
+#include "TypeLocal.hxx"
+
+namespace analysis
+{
+
+struct ArgIOInfo
+{
+    const symbol::Symbol sym;
+    bool refcount;
+    TypeLocal tl;
+
+    ArgIOInfo(const symbol::Symbol & _sym, const bool _refcount, const TypeLocal & _tl) : sym(_sym), refcount(_refcount), tl(_tl) { }
+
+};
+
+} // namespace analysis
+
+#endif // __ARGIO_INFO_HXX__
index c157f7d..53f4243 100644 (file)
@@ -130,8 +130,14 @@ public:
     virtual void addGlobal(const symbol::Symbol & sym);
     virtual GVN & getGVN();
     virtual void clone(const symbol::Symbol & sym, ast::Exp * exp);
+    virtual void needRefCount(const tools::SymbolSet & set);
 
     friend std::wostream & operator<<(std::wostream & out, const Block & block);
+
+private:
+
+    void needRefCount(const tools::SymbolSet & set1, const tools::SymbolSet & set2);
+
 };
 
 } // namespace analysis
index 1951b66..63bfcb2 100644 (file)
 #define __DATA_HXX__
 
 #include <iostream>
-#include <set>
 
-#include "tools.hxx"
 #include "symbol.hxx"
+#include "tools.hxx"
 
 namespace analysis
 {
@@ -37,6 +36,7 @@ struct Data
     bool hasOneOwner() const;
     bool isDeletable() const;
     bool same(Data * data);
+    void setValidity(const bool v);
     friend std::wostream & operator<<(std::wostream & out, const Data & data);
 };
 
index a932761..6326f4c 100644 (file)
@@ -23,6 +23,8 @@
 #include "Block.hxx"
 #include "MacroDef.hxx"
 #include "TypeLocal.hxx"
+#include "LocalInfo.hxx"
+#include "ArgIOInfo.hxx"
 #include "TemporaryManager.hxx"
 #include "TITypeSignatureTuple.hxx"
 #include "gvn/ConstraintManager.hxx"
@@ -40,9 +42,9 @@ class FunctionBlock : public Block
     std::vector<symbol::Symbol> in;
     std::vector<symbol::Symbol> out;
     tools::SymbolOrdSet globals;
-    std::vector<std::pair<symbol::Symbol, TypeLocal>> types_in;
-    std::vector<std::pair<symbol::Symbol, TypeLocal>> types_out;
-    tools::SymbolMap<std::set<TypeLocal>> locals;
+    std::vector<ArgIOInfo> types_in;
+    std::vector<ArgIOInfo> types_out;
+    tools::SymbolMap<LocalInfo> locals;
     std::vector<GVN::Value *> inValues;
     unsigned int lhs;
     unsigned int rhs;
@@ -82,17 +84,17 @@ public:
         return rhs;
     }
 
-    inline const std::vector<std::pair<symbol::Symbol, TypeLocal>> & getTypesIn() const
+    inline const std::vector<ArgIOInfo> & getTypesIn() const
     {
         return types_in;
     }
 
-    inline const std::vector<std::pair<symbol::Symbol, TypeLocal>> & getTypesOut() const
+    inline const std::vector<ArgIOInfo> & getTypesOut() const
     {
         return types_out;
     }
 
-    inline const tools::SymbolMap<std::set<TypeLocal>> & getTypesLocals() const
+    inline const tools::SymbolMap<LocalInfo> & getTypesLocals() const
     {
         return locals;
     }
@@ -149,6 +151,7 @@ public:
     void addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt) override;
     int getTmpId(const TIType & type, const bool isAnInt) override;
     void releaseTmp(const int id, ast::Exp * exp) override;
+    void needRefCount(const tools::SymbolSet & set) override;
 
     bool addIn(const TITypeSignatureTuple & tuple, const std::vector<GVN::Value *> & values);
     void setGlobals(const tools::SymbolOrdSet & v);
index f986394..0844034 100644 (file)
 
 namespace ast
 {
-    class Exp;
+class Exp;
 }
 
 namespace analysis
 {
 
-    struct Info
+struct Info
+{
+    enum Local
     {
-        enum Local
-        {
-            INFO_TRUE, INFO_FALSE, INFO_UNKNOWN
-        };
+        INFO_TRUE, INFO_FALSE, INFO_UNKNOWN
+    };
 
-        bool R;
-        bool W;
-        bool O;
-        bool isint;
-        Local local;
-        bool cleared;
-        bool exists;
-        TIType type;
-        Data * data;
-        ast::Exp * exp;
-        ConstantValue constant;
-        SymbolicRange range;
-        SymbolicDimension maxIndex;
+    bool R;
+    bool W;
+    bool O;
+    bool isint;
+    Local local;
+    bool cleared;
+    bool exists;
+    TIType type;
+    Data * data;
+    ast::Exp * exp;
+    ConstantValue constant;
+    SymbolicRange range;
+    SymbolicDimension maxIndex;
 
-        Info(Data * _data = nullptr) : R(false), W(false), O(false), isint(false), local(Local::INFO_TRUE), cleared(false), exists(true), data(_data), exp(nullptr) { }
-        Info(const Info & i) : R(i.R), W(i.W), O(i.O), isint(i.isint), local(i.local), cleared(i.cleared), exists(i.exists), constant(i.constant), range(i.range), maxIndex(i.maxIndex), type(i.type), data(i.data ? new Data(*i.data) : nullptr), exp(i.exp) { }
+    Info(Data * _data = nullptr) : R(false), W(false), O(false), isint(false), local(Local::INFO_TRUE), cleared(false), exists(true), data(_data), exp(nullptr) { }
+    Info(const Info & i) : R(i.R), W(i.W), O(i.O), isint(i.isint), local(i.local), cleared(i.cleared), exists(i.exists), constant(i.constant), range(i.range), maxIndex(i.maxIndex), type(i.type), data(i.data ? new Data(*i.data) : nullptr), exp(i.exp) { }
 
-        void merge(Info & info);
-        void addData(const bool known, const symbol::Symbol & sym);
-        void addData(Data * _data, const symbol::Symbol & sym);
-        SymbolicRange & getRange();
-        const SymbolicRange & getRange() const;
-        SymbolicDimension & getMaxIndex();
-        const SymbolicDimension & getMaxIndex() const;
-        SymbolicRange & setRange(SymbolicRange & _range);
-        ConstantValue & getConstant();
-        const ConstantValue & getConstant() const;
-        ConstantValue & setConstant(ConstantValue & val);
-        bool isknown() const;
-        static const symbol::Symbol & getRightSym(ast::Exp * exp);
-        const TIType & getType() const;
-        friend std::wostream & operator<<(std::wostream & out, const Info & info);
-    };
+    void merge(const Info & info, bool & isSameData);
+    void addData(const bool known, const symbol::Symbol & sym);
+    void addData(Data * _data, const symbol::Symbol & sym);
+    SymbolicRange & getRange();
+    const SymbolicRange & getRange() const;
+    SymbolicDimension & getMaxIndex();
+    const SymbolicDimension & getMaxIndex() const;
+    SymbolicRange & setRange(SymbolicRange & _range);
+    ConstantValue & getConstant();
+    const ConstantValue & getConstant() const;
+    ConstantValue & setConstant(ConstantValue & val);
+    bool isknown() const;
+    static const symbol::Symbol & getRightSym(ast::Exp * exp);
+    const TIType & getType() const;
+    friend std::wostream & operator<<(std::wostream & out, const Info & info);
+};
 
 } // namespace analysis
 
diff --git a/scilab/modules/ast/includes/analysis/data/LocalInfo.hxx b/scilab/modules/ast/includes/analysis/data/LocalInfo.hxx
new file mode 100644 (file)
index 0000000..08c3ada
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __LOCAL_INFO_HXX__
+#define __LOCAL_INFO_HXX__
+
+#include <set>
+
+#include "TypeLocal.hxx"
+
+namespace analysis
+{
+
+struct LocalInfo
+{
+    bool refcount;
+    std::set<TypeLocal> set;
+
+    LocalInfo() : refcount(false), set() { }
+
+};
+
+} // namespace analysis
+
+#endif // __LOCAL_INFO_HXX__
index 2f4be5f..ddd8443 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2008-2008 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -27,7 +28,14 @@ namespace ast
 class EXTERN_AST DebugVisitor : public GenVisitor<const_kind>
 {
 public:
-    DebugVisitor(std::wostream & my_ostr = std::wcerr, const bool _printDecoration = false) : ostr(&my_ostr), printDecoration(_printDecoration) { }
+    DebugVisitor(std::wostream & my_ostr = std::wcerr, const bool _printDecoration = false, const bool _colored = false) : ostr(&my_ostr),
+        printDecoration(_printDecoration),
+#ifdef _MSC_VER
+        colored(false)
+#else
+        colored(_colored)
+#endif
+    { }
 
     /** \name Visit Matrix Expressions nodes.
      ** \{ */
@@ -91,8 +99,8 @@ public :
     /** \name Visit Declaration nodes.
      ** \{ */
     /** \brief Visit Var declarations. */
-    virtual void visit (const VarDec  &e);
-    virtual void visit (const FunctionDec  &e);
+    virtual void visit (const VarDec &e);
+    virtual void visit (const FunctionDec &e);
     /** \} */
 
     /** \name Visit Type dedicated Expressions related node.
@@ -148,13 +156,27 @@ protected:
 
     std::wostream * ostr;
     const bool printDecoration;
+    const bool colored;
 
 private:
 
     void START_NODE(const ast::Ast & e);
     void END_NODE(void);
-    void print(const std::wstring& str);
-    void print(const std::wstring& str, const Exp & e);
+    void print(const std::wstring & pre, const Location & loc, const std::wstring & post, const std::wstring & deco);
+    void print(const std::wstring & str);
+    void print(const std::wstring & str, const Exp & e);
+    void print(const Exp & e);
+    void print(const Location & loc);
+
+    static const std::wstring NORMAL;
+    static const std::wstring BOLD;
+    static const std::wstring RED;
+    static const std::wstring GREEN;
+    static const std::wstring YELLOW;
+    static const std::wstring BLUE;
+    static const std::wstring MAGENTA;
+    static const std::wstring CYAN;
+    static const std::wstring WHITE;
 };
 }
 #endif // !AST_DEBUGVISITOR_HXX
index cabf1d4..7b685f6 100644 (file)
@@ -250,7 +250,7 @@ public:
         FUNCTIONDEC,
         LISTEXP,
         OPTIMIZEDEXP,
-       MEMFILLEXP,
+        MEMFILLEXP,
         DAXPYEXP,
         STRINGSELECTEXP,
         TABLEINTSELECTEXP,
@@ -258,6 +258,101 @@ public:
         SMALLINTSELECTEXP,
     };
 
+    const std::wstring getTypeString() const
+    {
+        switch (getType())
+        {
+            case SIMPLEVAR:
+                return L"SimpleVar";
+            case DOLLARVAR:
+                return L"DollarVar";
+            case COLONVAR:
+                return L"ColonVar";
+            case ARRAYLISTVAR:
+                return L"ArrayListVar";
+            case DOUBLEEXP:
+                return L"DoubleExp";
+            case BOOLEXP:
+                return L"BoolExp";
+            case STRINGEXP:
+                return L"StringExp";
+            case COMMENTEXP:
+                return L"CommentExp";
+            case CONSTEXP:
+                return L"ConstExp";
+            case NILEXP:
+                return L"NilExp";
+            case CALLEXP:
+                return L"CallExp";
+            case CELLCALLEXP:
+                return L"CellCallExp";
+            case OPEXP:
+                return L"OpExp";
+            case LOGICALOPEXP:
+                return L"LogicalOpExp";
+            case ASSIGNEXP:
+                return L"AssignExp";
+            case IFEXP:
+                return L"IfExp";
+            case WHILEEXP:
+                return L"WhileExp";
+            case FOREXP:
+                return L"ForExp";
+            case BREAKEXP:
+                return L"BreakExp";
+            case CONTINUEEXP:
+                return L"ContinueExp";
+            case TRYCATCHEXP:
+                return L"TryCatchExp";
+            case SELECTEXP:
+                return L"SelectExp";
+            case CASEEXP:
+                return L"CaseExp";
+            case RETURNEXP:
+                return L"ReturnExp";
+            case FIELDEXP:
+                return L"FieldExp";
+            case NOTEXP:
+                return L"NotExp";
+            case TRANSPOSEEXP:
+                return L"TransposeExp";
+            case MATRIXEXP:
+                return L"MatrixExp";
+            case MATRIXLINEEXP:
+                return L"MatrixLineExp";
+            case CELLEXP:
+                return L"CellExp";
+            case SEQEXP:
+                return L"SeqExp";
+            case ARRAYLISTEXP:
+                return L"ArrayListExp";
+            case ASSIGNLISTEXP:
+                return L"AssignListExp";
+            case VARDEC:
+                return L"VarDec";
+            case FUNCTIONDEC:
+                return L"FunctionDec";
+            case LISTEXP:
+                return L"ListExp";
+            case OPTIMIZEDEXP:
+                return L"OptimizedExp";
+            case MEMFILLEXP:
+                return L"MemfillExp";
+            case DAXPYEXP:
+                return L"DAXPYExp";
+            case STRINGSELECTEXP:
+                return L"StringSelectExp";
+            case TABLEINTSELECTEXP:
+                return L"TableIntSelectExp";
+            case MAPINTSELECTEXP:
+                return L"MapIntSelectExp";
+            case SMALLINTSELECTEXP:
+                return L"SmallIntSelectExp";
+            default:
+                return L"????Exp";
+        }
+    }
+
     virtual ExpType getType() const = 0;
 
     template <class T>
index a40f509..b59b061 100644 (file)
@@ -54,7 +54,7 @@ Info & Block::setDefaultData(const symbol::Symbol & sym)
 
 void Block::clone(Info & info, const symbol::Symbol & sym, ast::Exp * exp)
 {
-    if (!info.data->hasOneOwner())
+    if (info.data->valid && !info.data->hasOneOwner())
     {
         // data is shared between several symbols => we need to clone it
         info.data->rem(sym);
@@ -203,10 +203,7 @@ Info & Block::addWrite(const symbol::Symbol & sym, const TIType & Rtype, ast::Ex
         info.exists = true;
     }
 
-    if (!info.type.isscalar())
-    {
-        clone(info, sym, exp);
-    }
+    clone(info, sym, exp);
     info.W = true;
 
     return info;
@@ -444,31 +441,73 @@ bool Block::requiresAnotherTrip()
     return false;
 }
 
+void Block::needRefCount(const tools::SymbolSet & set)
+{
+    if (parent)
+    {
+        parent->needRefCount(set);
+    }
+}
+
+void Block::needRefCount(const tools::SymbolSet & set1, const tools::SymbolSet & set2)
+{
+    tools::SymbolSet res;
+    for (const auto & sym : set1)
+    {
+        res.emplace(sym);
+    }
+    for (const auto & sym : set2)
+    {
+        res.emplace(sym);
+    }
+    needRefCount(res);
+}
+
 void Block::merge(tools::SymbolMap<Info> & M, tools::SymbolMap<Info> & N)
 {
     // TODO: when we merge double and double* we should mark the sym to convert the double into a double*
     // and in the LLVM side, make a phi node to set the correct value !
     for (auto & p : M)
     {
+        bool isSameData;
         tools::SymbolMap<Info>::iterator i = N.find(p.first);
         if (i != N.end())
         {
             // sym is common to the two maps
-            p.second.merge(i->second);
+            p.second.merge(i->second, isSameData);
+            if (!isSameData)
+            {
+                // the variable requires a reference counter
+                needRefCount(p.second.data->sharedSyms, i->second.data->sharedSyms);
+            }
+
             N.erase(i);
         }
         else
         {
             // sym is in M and not in N
-            Info & i = getInfo(p.first);
-            p.second.merge(i);
+            const Info & i = getInfo(p.first);
+            p.second.merge(i, isSameData);
+            if (!isSameData)
+            {
+                // the variable requires a reference counter
+                needRefCount(p.second.data->sharedSyms, i.data->sharedSyms);
+            }
         }
     }
 
     // We erased common syms in N, so the remainder is the syms which are in N and not in M
     for (auto & p : N)
     {
-        Block::addSym(M, p.first, p.second).merge(getInfo(p.first));
+        bool isSameData;
+        Info & i1 = Block::addSym(M, p.first, p.second);
+        Info & i2 = getInfo(p.first);
+        i1.merge(i2, isSameData);
+        if (!isSameData)
+        {
+            // the variable requires a reference counter
+            needRefCount(i1.data->sharedSyms, i2.data->sharedSyms);
+        }
     }
 }
 
index 92b883d..f809c2b 100644 (file)
 namespace analysis
 {
 
-    Data::Data(const bool _known, const symbol::Symbol & sym) : known(_known), valid(true)
-    {
-        sharedSyms.emplace(sym);
-    }
+Data::Data(const bool _known, const symbol::Symbol & sym) : known(_known), valid(true), sharedSyms()
+{
+    sharedSyms.emplace(sym);
+}
 
-    void Data::clear()
-    {
-        sharedSyms.clear();
-    }
+void Data::clear()
+{
+    valid = true;
+    sharedSyms.clear();
+}
 
-    void Data::add(const symbol::Symbol & sym)
+void Data::add(const symbol::Symbol & sym)
+{
+    if (valid)
     {
-        if (valid)
-        {
-            sharedSyms.emplace(sym);
-        }
+        sharedSyms.emplace(sym);
     }
+}
 
-    void Data::rem(const symbol::Symbol & sym)
+void Data::rem(const symbol::Symbol & sym)
+{
+    if (valid)
     {
-        if (valid)
-        {
-            sharedSyms.erase(sym);
-        }
+        sharedSyms.erase(sym);
     }
+}
 
-    bool Data::hasOneOwner() const
-    {
-        return valid && known && (sharedSyms.size() == 1);
-    }
+bool Data::hasOneOwner() const
+{
+    return valid && known && (sharedSyms.size() == 1);
+}
 
-    bool Data::isDeletable() const
-    {
-        return valid && known && sharedSyms.empty();
-    }
+bool Data::isDeletable() const
+{
+    return valid && known && sharedSyms.empty();
+}
+
+bool Data::same(Data * data)
+{
+    return (valid && data->valid) && (data == this || (known == data->known && sharedSyms == data->sharedSyms));
+}
 
-    bool Data::same(Data * data)
+void Data::setValidity(const bool v)
+{
+    if (valid && !v)
     {
-        return (valid && data->valid) && (data == this || (known == data->known && sharedSyms == data->sharedSyms));
+        valid = false;
+        sharedSyms.clear();
     }
+}
 
-    std::wostream & operator<<(std::wostream & out, const Data & data)
-    {
-        out << L"known:" << (data.known ? L"T" : L"F")
-            << L", valid:" << (data.valid ? L"T" : L"F")
-            << L", ";
+std::wostream & operator<<(std::wostream & out, const Data & data)
+{
+    out << L"known:" << (data.known ? L"T" : L"F")
+        << L", valid:" << (data.valid ? L"T" : L"F")
+        << L", ";
 
-        tools::printSet(data.sharedSyms, out);
+    tools::printSet(data.sharedSyms, out);
 
-        return out;
-    }
+    return out;
+}
 
 } // namespace analysis
index 9f74e8e..ab1bb3a 100644 (file)
@@ -137,23 +137,24 @@ void FunctionBlock::finalize()
             const TIType & type = it->second.type;
             if (type.isscalar())
             {
-                types_out.emplace_back(out[i], TypeLocal(type.type, 1, 1, false));
+                types_out.emplace_back(out[i], false, TypeLocal(type.type, 1, 1, false));
             }
             else
             {
-                types_out.emplace_back(out[i], TypeLocal(type.type, -1, -1, false));
+                types_out.emplace_back(out[i], false, TypeLocal(type.type, -1, -1, false));
             }
         }
         else
         {
-            types_out.emplace_back(out[i], TypeLocal(TIType::UNKNOWN, -1, -1, false));
+            types_out.emplace_back(out[i], false, TypeLocal(TIType::UNKNOWN, -1, -1, false));
         }
 
         auto jt = locals.find(out[i]);
         if (jt != locals.end())
         {
-            jt->second.erase(types_out.back().second);
-            if (jt->second.empty())
+            types_out.back().refcount = jt->second.refcount;
+            jt->second.set.erase(types_out.back().tl);
+            if (jt->second.set.empty())
             {
                 locals.erase(jt);
             }
@@ -166,10 +167,10 @@ void FunctionBlock::addLocal(const symbol::Symbol & sym, const TIType & type, co
     auto i = locals.find(sym);
     if (i == locals.end())
     {
-        i = locals.emplace(sym, std::set<TypeLocal>()).first;
+        i = locals.emplace(sym, LocalInfo()).first;
     }
 
-    i->second.emplace(TypeLocal::get(type, isAnInt));
+    i->second.set.emplace(TypeLocal::get(type, isAnInt));
 }
 
 int FunctionBlock::getTmpId(const TIType & type, const bool isAnInt)
@@ -191,6 +192,18 @@ void FunctionBlock::releaseTmp(const int id, ast::Exp * exp)
     }
 }
 
+void FunctionBlock::needRefCount(const tools::SymbolSet & set)
+{
+    for (const auto & sym : set)
+    {
+        auto i = locals.find(sym);
+        if (i != locals.end())
+        {
+            i->second.refcount = true;
+        }
+    }
+}
+
 void FunctionBlock::setInOut(MacroDef * macrodef, const unsigned int rhs, const std::vector<TIType> & _in)
 {
     in = macrodef->getIn();
@@ -200,11 +213,11 @@ void FunctionBlock::setInOut(MacroDef * macrodef, const unsigned int rhs, const
     {
         if (_in[i].isscalar())
         {
-            types_in.emplace_back(in[i], TypeLocal(_in[i].type, 1, 1, false));
+            types_in.emplace_back(in[i], true, TypeLocal(_in[i].type, 1, 1, false));
         }
         else
         {
-            types_in.emplace_back(in[i], TypeLocal(_in[i].type, -1, -1, false));
+            types_in.emplace_back(in[i], true, TypeLocal(_in[i].type, -1, -1, false));
         }
     }
 }
@@ -238,16 +251,21 @@ std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
         << L" -LHS: " << fblock.lhs << L'\n'
         << L" -RHS: " << fblock.rhs << L'\n'
         << L" -in:" << L'\n';
-    for (const auto & p : fblock.types_in)
+    for (const auto & i : fblock.types_in)
     {
-        out << L"   -" << p.first << L" -> " << p.second << L'\n';
+        out << L"   -" << i.sym << L" -> " << i.tl << L'\n';
     }
 
     out << L'\n'
         << L" -out:" << L'\n';
-    for (const auto & p : fblock.types_out)
+    for (const auto & i : fblock.types_out)
     {
-        out << L"   -" << p.first << L" -> " << p.second << L'\n';
+        out << L"   -" << i.sym;
+        if (i.refcount)
+        {
+            out << L" (refcount)";
+        }
+        out << L" -> " << i.tl << L'\n';
     }
     out << L'\n';
     if (fblock.locals.empty())
@@ -259,8 +277,13 @@ std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
         out << L" -locals:" << L'\n';
         for (const auto & p : fblock.locals)
         {
-            out << L"   -" << p.first << L" -> ";
-            tools::printSet(p.second, out);
+            out << L"   -" << p.first;
+            if (p.second.refcount)
+            {
+                out << L" (refcount)";
+            }
+            out << L" -> ";
+            tools::printSet(p.second.set, out);
             out << L'\n';
         }
     }
@@ -283,7 +306,7 @@ std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
     //ast::PrintVisitor pv(out, true, false);
     //fblock.exp->accept(pv);
 
-    ast::DebugVisitor dv(out, true);
+    ast::DebugVisitor dv(out, true, true);
     fblock.exp->accept(dv);
 
     return out;
index c732ccb..1ccc2b8 100644 (file)
 namespace analysis
 {
 
-    void Info::merge(Info & info)
+void Info::merge(const Info & info, bool & isSameData)
+{
+    R = R || info.R;
+    W = W || info.W;
+    O = O || info.O;
+    isint = isint && info.isint;
+    if (local != info.local)
     {
-        R = R || info.R;
-        W = W || info.W;
-        O = O || info.O;
-        isint = isint && info.isint;
-        if (local != info.local)
-        {
-            local = Local::INFO_UNKNOWN;
-        }
-        cleared = cleared && info.cleared;
-        exists = exists || info.exists;
-        constant.merge(info.constant);
-        maxIndex.mergeAsMax(info.maxIndex);
-        type.merge(info.type);
-        data->valid = data->same(info.data);
-        // No need to merge range since this info is just used in for loop
+        local = Local::INFO_UNKNOWN;
     }
+    cleared = cleared && info.cleared;
+    exists = exists || info.exists;
+    constant.merge(info.constant);
+    maxIndex.mergeAsMax(info.maxIndex);
+    type.merge(info.type);
+    isSameData = data->same(info.data);
+    data->setValidity(isSameData);
+    // No need to merge range since this info is just used in for loop
+}
+
+void Info::addData(const bool known, const symbol::Symbol & sym)
+{
+    data = new Data(known, sym);
+}
 
-    void Info::addData(const bool known, const symbol::Symbol & sym)
-    {
-        data = new Data(known, sym);
-    }
+void Info::addData(Data * _data, const symbol::Symbol & sym)
+{
+    data = _data;
+    data->add(sym);
+}
 
-    void Info::addData(Data * _data, const symbol::Symbol & sym)
-    {
-        data = _data;
-        data->add(sym);
-    }
+SymbolicRange & Info::getRange()
+{
+    return range;
+}
 
-    SymbolicRange & Info::getRange()
-    {
-        return range;
-    }
+const SymbolicRange & Info::getRange() const
+{
+    return range;
+}
 
-    const SymbolicRange & Info::getRange() const
-    {
-        return range;
-    }
+SymbolicDimension & Info::getMaxIndex()
+{
+    return maxIndex;
+}
 
-    SymbolicDimension & Info::getMaxIndex()
-    {
-        return maxIndex;
-    }
+const SymbolicDimension & Info::getMaxIndex() const
+{
+    return maxIndex;
+}
 
-    const SymbolicDimension & Info::getMaxIndex() const
-    {
-        return maxIndex;
-    }
+SymbolicRange & Info::setRange(SymbolicRange & _range)
+{
+    range = _range;
+    return range;
+}
 
-    SymbolicRange & Info::setRange(SymbolicRange & _range)
-    {
-        range = _range;
-        return range;
-    }
+ConstantValue & Info::getConstant()
+{
+    return constant;
+}
 
-    ConstantValue & Info::getConstant()
-    {
-        return constant;
-    }
+const ConstantValue & Info::getConstant() const
+{
+    return constant;
+}
 
-    const ConstantValue & Info::getConstant() const
-    {
-        return constant;
-    }
+ConstantValue & Info::setConstant(ConstantValue & val)
+{
+    constant = val;
+    return constant;
+}
 
-    ConstantValue & Info::setConstant(ConstantValue & val)
-    {
-        constant = val;
-        return constant;
-    }
+bool Info::isknown() const
+{
+    return local == Local::INFO_TRUE;
+}
 
-    bool Info::isknown() const
-    {
-        return local == Local::INFO_TRUE;
-    }
+const symbol::Symbol & Info::getRightSym(ast::Exp * exp)
+{
+    return static_cast<const ast::SimpleVar &>(static_cast<const ast::AssignExp *>(exp)->getRightExp()).getSymbol();
+}
 
-    const symbol::Symbol & Info::getRightSym(ast::Exp * exp)
-    {
-        return static_cast<const ast::SimpleVar &>(static_cast<const ast::AssignExp *>(exp)->getRightExp()).getSymbol();
-    }
+const TIType & Info::getType() const
+{
+    return type;
+}
 
-    const TIType & Info::getType() const
+std::wostream & operator<<(std::wostream & out, const Info & info)
+{
+    out << L"Type: " << info.type << L" - RWO:"
+        << (info.R ? L"T" : L"F")
+        << (info.W ? L"T" : L"F")
+        << (info.O ? L"T" : L"F")
+        << L" - int:" << (info.isint ? L"T" : L"F")
+        << L" - local:" << (info.local == Info::Local::INFO_TRUE ? L"T" : (info.local == Info::Local::INFO_FALSE ? L"F" : L"U"))
+        << L" - cleared:" << (info.cleared ? L"T" : L"F")
+        << L" - exists:" << (info.exists ? L"T" : L"F")
+        << L" - constant:" << info.constant;
+
+    out << L" - data:";
+    if (info.data)
     {
-        return type;
+        out << *info.data;
     }
-
-    std::wostream & operator<<(std::wostream & out, const Info & info)
+    else
     {
-        out << L"Type: " << info.type << L" - RWO:"
-            << (info.R ? L"T" : L"F")
-            << (info.W ? L"T" : L"F")
-            << (info.O ? L"T" : L"F")
-            << L" - int:" << (info.isint ? L"T" : L"F")
-            << L" - local:" << (info.local == Info::Local::INFO_TRUE ? L"T" : (info.local == Info::Local::INFO_FALSE ? L"F" : L"U"))
-            << L" - cleared:" << (info.cleared ? L"T" : L"F")
-            << L" - exists:" << (info.exists ? L"T" : L"F")
-            << L" - constant:" << info.constant;
-
-        out << L" - data:";
-        if (info.data)
-        {
-            out << *info.data;
-        }
-        else
-        {
-            out << L"null";
-        }
-
-        return out;
+        out << L"null";
     }
 
+    return out;
+}
+
 } // namespace analysis
index c755370..b6a0912 100644 (file)
@@ -21,10 +21,10 @@ Block * XBlockHead::addBlock(const unsigned int id, BlockKind kind, ast::Exp * e
 {
     if (kind == MACRO)
     {
-       Block * b = new FunctionBlock(id, this, exp);
-       testBlocks.push_back(b);
+        Block * b = new FunctionBlock(id, this, exp);
+        testBlocks.push_back(b);
 
-       return b;
+        return b;
     }
 
     Block * b = new XBlock(id, this, exp);
@@ -40,22 +40,23 @@ void XBlockHead::finalize()
     std::vector<Block *>::iterator end = blocks.end();
     for (first = blocks.begin(); first != end; ++first)
     {
-       if (!(*first)->getReturn())
-       {
-           break;
-       }
+        if (!(*first)->getReturn())
+        {
+            break;
+        }
     }
 
     if (first != end)
     {
-       for (std::vector<Block *>::iterator i = std::next(first); i != end; ++i)
-       {
-           if (!(*i)->getReturn())
-           {
-               merge((*first)->getMap(), (*i)->getMap());
-           }
-       }
-       pullup((*first)->getMap());
+        tools::SymbolMap<Info> & map = (*first)->getMap();
+        for (std::vector<Block *>::iterator i = std::next(first); i != end; ++i)
+        {
+            if (!(*i)->getReturn())
+            {
+                merge(map, (*i)->getMap());
+            }
+        }
+        pullup((*first)->getMap());
     }
 }
 }
index 92fea2e..90b08bf 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2008-2008 - DIGITEO - Bruno JOFRET
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -17,7 +18,29 @@ namespace ast
 {
 static int level = -1;
 
-void DebugVisitor::START_NODE(const ast::Ast& e)
+#ifndef _MSC_VER
+const std::wstring DebugVisitor::NORMAL = L"\033[0m";
+const std::wstring DebugVisitor::BOLD = L"\033[1m";
+const std::wstring DebugVisitor::RED = L"\033[31m";
+const std::wstring DebugVisitor::GREEN = L"\033[32m";
+const std::wstring DebugVisitor::YELLOW = L"\033[33m";
+const std::wstring DebugVisitor::BLUE = L"\033[34m";
+const std::wstring DebugVisitor::MAGENTA = L"\033[35m";
+const std::wstring DebugVisitor::CYAN = L"\033[36m";
+const std::wstring DebugVisitor::WHITE = L"\033[37m";
+#else
+const std::wstring DebugVisitor::NORMAL = L"";
+const std::wstring DebugVisitor::BOLD = L"";
+const std::wstring DebugVisitor::RED = L"";
+const std::wstring DebugVisitor::GREEN = L"";
+const std::wstring DebugVisitor::YELLOW = L"";
+const std::wstring DebugVisitor::BLUE = L"";
+const std::wstring DebugVisitor::MAGENTA = L"";
+const std::wstring DebugVisitor::CYAN = L"";
+const std::wstring DebugVisitor::WHITE = L"";
+#endif
+
+void DebugVisitor::START_NODE(const ast::Ast & e)
 {
     *ostr << L"(" << e.getNodeNumber() << L") ";
     ++level;
@@ -28,7 +51,7 @@ void DebugVisitor::END_NODE(void)
     --level;
 }
 
-void DebugVisitor::print(const std::wstring& str)
+void DebugVisitor::print(const std::wstring & str)
 {
     for (int i = 0 ; i < level; ++i)
     {
@@ -41,7 +64,21 @@ void DebugVisitor::print(const std::wstring& str)
     *ostr << str << std::endl;
 }
 
-void DebugVisitor::print(const std::wstring& str, const Exp &e)
+void DebugVisitor::print(const Location & loc)
+{
+    if (colored)
+    {
+        *ostr << L"@(" << YELLOW << loc.first_line << L"." << BOLD << loc.first_column << NORMAL << L" -> "
+              << YELLOW << loc.last_line << L"." << BOLD << loc.last_column << NORMAL << L")";
+    }
+    else
+    {
+        *ostr << L"@(" << loc.first_line << L"." << loc.first_column << L" -> "
+              << loc.last_line << L"." << loc.last_column << L")";
+    }
+}
+
+void DebugVisitor::print(const std::wstring & pre, const Location & loc, const std::wstring & post, const std::wstring & deco)
 {
     for (int i = 0 ; i < level; ++i)
     {
@@ -51,23 +88,54 @@ void DebugVisitor::print(const std::wstring& str, const Exp &e)
     {
         *ostr << L"|_./ ";
     }
-    *ostr << str;
 
-    Location loc = e.getLocation();
-    *ostr << L" @(" << loc.first_line << L"." << loc.first_column << L" -> ";
-    *ostr << loc.last_line << L"." << loc.last_column << L")";
-    if (printDecoration)
+    *ostr << pre << L' ';
+    print(loc);
+
+    if (!post.empty())
+    {
+        *ostr << L" : " << post;
+    }
+    if (!deco.empty())
     {
-        *ostr << L" Deco(" << e.getDecorator() << L")";
+        *ostr << L' ' << deco;
     }
     *ostr << std::endl;
 }
 
+void DebugVisitor::print(const std::wstring & str, const Exp & e)
+{
+    std::wstring expType;
+    if (colored)
+    {
+        expType = BOLD + e.getTypeString() + NORMAL;
+    }
+    else
+    {
+        expType = e.getTypeString();
+    }
 
-void DebugVisitor::visit (const MatrixExp &e)
+    if (printDecoration)
+    {
+        std::wostringstream wos;
+        wos << L"Deco(" << e.getDecorator() << L")";
+        print(expType, e.getLocation(), str, wos.str());
+    }
+    else
+    {
+        print(expType, e.getLocation(), str, L"");
+    }
+}
+
+void DebugVisitor::print(const Exp & e)
+{
+    print(L"", e);
+}
+
+void DebugVisitor::visit(const MatrixExp & e)
 {
     START_NODE(e);
-    print(L"Exec MatrixExp", e);
+    print(e);
     exps_t lines = e.getLines();
     for (exps_t::const_iterator it = lines.begin(), itEnd = lines.end(); it != itEnd ; ++it)
     {
@@ -76,10 +144,10 @@ void DebugVisitor::visit (const MatrixExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const MatrixLineExp &e)
+void DebugVisitor::visit(const MatrixLineExp & e)
 {
     START_NODE(e);
-    print(L"Exec MatrixLineExp", e);
+    print(e);
     exps_t columns = e.getColumns();
     for (exps_t::const_iterator it = columns.begin(), itEnd = columns.end(); it != itEnd ; ++it)
     {
@@ -88,10 +156,10 @@ void DebugVisitor::visit (const MatrixLineExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const CellExp &e)
+void DebugVisitor::visit(const CellExp & e)
 {
     START_NODE(e);
-    print(L"Exec CellExp", e);
+    print(e);
     exps_t lines = e.getLines();
     for (exps_t::const_iterator it = lines.begin(), itEnd = lines.end(); it != itEnd ; ++it)
     {
@@ -100,7 +168,7 @@ void DebugVisitor::visit (const CellExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const StringExp &e)
+void DebugVisitor::visit(const StringExp & e)
 {
     START_NODE(e);
     std::wostringstream stream;
@@ -112,18 +180,32 @@ void DebugVisitor::visit (const StringExp &e)
     {
         stream << e.getValue();
     }
-    print(L"Exec StringExp : " + stream.str(), e);
+    if (colored)
+    {
+        print(RED + stream.str() + NORMAL, e);
+    }
+    else
+    {
+        print(stream.str(), e);
+    }
     END_NODE();
 }
 
-void DebugVisitor::visit (const CommentExp &e)
+void DebugVisitor::visit(const CommentExp & e)
 {
     START_NODE(e);
-    print(L"Exec CommentExp : " + e.getComment(), e);
+    if (colored)
+    {
+        print(GREEN + e.getComment() + NORMAL, e);
+    }
+    else
+    {
+        print(e.getComment(), e);
+    }
     END_NODE();
 }
 
-void DebugVisitor::visit (const DoubleExp  &e)
+void DebugVisitor::visit(const DoubleExp & e)
 {
     START_NODE(e);
     std::wostringstream stream;
@@ -146,11 +228,18 @@ void DebugVisitor::visit (const DoubleExp  &e)
     {
         stream << e.getValue();
     }
-    print(L"Exec DoubleExp : " + stream.str(), e);
+    if (colored)
+    {
+        print(RED + stream.str() + NORMAL, e);
+    }
+    else
+    {
+        print(stream.str(), e);
+    }
     END_NODE();
 }
 
-void DebugVisitor::visit (const BoolExp  &e)
+void DebugVisitor::visit(const BoolExp & e)
 {
     START_NODE(e);
     std::wostringstream stream;
@@ -162,56 +251,76 @@ void DebugVisitor::visit (const BoolExp  &e)
     {
         stream << e.getValue();
     }
-    print(L"Exec BoolExp : " + stream.str(), e);
+    if (colored)
+    {
+        print(RED + stream.str() + NORMAL, e);
+    }
+    else
+    {
+        print(stream.str(), e);
+    }
     END_NODE();
 }
 
-void DebugVisitor::visit (const NilExp &e)
+void DebugVisitor::visit(const NilExp & e)
 {
     START_NODE(e);
-    print(L"Exec NilExp", e);
+    print(e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const SimpleVar &e)
+void DebugVisitor::visit(const SimpleVar & e)
 {
-    std::wstring ty;
-    analysis::TIType type = e.getDecorator().getResult().getType();
-    if (type.type != analysis::TIType::UNKNOWN)
+    START_NODE(e);
+    std::wstring str;
+    if (colored)
     {
-        if (type.isscalar())
-        {
-            ty = L" (" + analysis::TIType::toString(type.type) + L")";
-        }
-        else
+        str = RED + e.getSymbol().getName() + NORMAL;
+    }
+    else
+    {
+        str = e.getSymbol().getName();
+    }
+    if (printDecoration)
+    {
+        std::wstring ty;
+        analysis::TIType type = e.getDecorator().getResult().getType();
+        if (type.type != analysis::TIType::UNKNOWN)
         {
-            ty = L" (" + analysis::TIType::toString(type.type) + L"*)";
+            if (type.isscalar())
+            {
+                ty = L" (" + analysis::TIType::toString(type.type) + L")";
+            }
+            else
+            {
+                ty = L" (" + analysis::TIType::toString(type.type) + L"*)";
+            }
         }
+        str += ty;
     }
+    print(str, e);
 
-    START_NODE(e);
-    print(L"Exec SimpleVar : " + e.getSymbol().getName() + ty, e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const ColonVar &e)
+void DebugVisitor::visit(const ColonVar & e)
 {
     START_NODE(e);
-    print(L"Exec ColonVar", e);
+    print(e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const DollarVar &e)
+void DebugVisitor::visit(const DollarVar & e)
 {
     START_NODE(e);
-    print(L"Exec DollarVar", e);
+    print(e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const ArrayListVar &e)
+void DebugVisitor::visit(const ArrayListVar & e)
 {
     START_NODE(e);
-    print(L"Exec ArrayListVar", e);
+    print(e);
     exps_t vars = e.getVars();
     for (exps_t::const_iterator it = vars.begin (), itEnd = vars.end(); it != itEnd; ++it)
     {
@@ -220,46 +329,46 @@ void DebugVisitor::visit (const ArrayListVar &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const FieldExp &e)
+void DebugVisitor::visit(const FieldExp & e)
 {
     START_NODE(e);
-    print(L"Exec FieldExp", e);
+    print(e);
     e.getHead()->accept(*this);
     e.getTail()->accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit(const OpExp &e)
+void DebugVisitor::visit(const OpExp & e)
 {
     START_NODE(e);
-    print(L"Exec OpExp", e);
+    print(e);
     e.getLeft().accept(*this);
     e.getRight().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit(const LogicalOpExp &e)
+void DebugVisitor::visit(const LogicalOpExp & e)
 {
     START_NODE(e);
-    print(L"Exec LogicalOpExp", e);
+    print(e);
     e.getLeft().accept(*this);
     e.getRight().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const AssignExp  &e)
+void DebugVisitor::visit(const AssignExp & e)
 {
     START_NODE(e);
-    print(L"Exec AssignExp", e);
+    print(e);
     e.getLeftExp().accept(*this);
     e.getRightExp().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit(const CellCallExp &e)
+void DebugVisitor::visit(const CellCallExp & e)
 {
     START_NODE(e);
-    print(L"Exec CellCallExp", e);
+    print(e);
     e.getName().accept(*this);
 
     exps_t args = e.getArgs();
@@ -271,12 +380,10 @@ void DebugVisitor::visit(const CellCallExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit(const CallExp &e)
+void DebugVisitor::visit(const CallExp & e)
 {
-    std::wstring str;
-
     START_NODE(e);
-    print(L"Exec CallExp" + str, e);
+    print(e);
     e.getName().accept(*this);
 
     exps_t args = e.getArgs();
@@ -288,12 +395,12 @@ void DebugVisitor::visit(const CallExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const IfExp  &e)
+void DebugVisitor::visit(const IfExp & e)
 {
     START_NODE(e);
-    print(L"Exec IfExp", e);
-    e.getTest ().accept(*this);
-    e.getThen ().accept(*this);
+    print(e);
+    e.getTest().accept(*this);
+    e.getThen().accept(*this);
     if (e.hasElse())
     {
         e.getElse ().accept(*this);
@@ -301,51 +408,51 @@ void DebugVisitor::visit (const IfExp  &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const TryCatchExp  &e)
+void DebugVisitor::visit(const TryCatchExp & e)
 {
     START_NODE(e);
-    print(L"Exec TryCatchExp", e);
-    e.getTry ().accept(*this);
-    e.getCatch ().accept(*this);
+    print(e);
+    e.getTry().accept(*this);
+    e.getCatch().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const WhileExp  &e)
+void DebugVisitor::visit(const WhileExp & e)
 {
     START_NODE(e);
-    print(L"Exec WhileExp", e);
+    print(e);
     e.getTest().accept(*this);
     e.getBody().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const ForExp  &e)
+void DebugVisitor::visit(const ForExp & e)
 {
     START_NODE(e);
-    print(L"Exec ForExp", e);
+    print(e);
     e.getVardec().accept(*this);
     e.getBody().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const ContinueExp &e)
+void DebugVisitor::visit(const ContinueExp & e)
 {
     START_NODE(e);
-    print(L"Exec ContinueExp", e);
+    print(e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const BreakExp &e)
+void DebugVisitor::visit(const BreakExp & e)
 {
     START_NODE(e);
-    print(L"Exec BreakExp", e);
+    print(e);
     END_NODE();
 }
 
-void DebugVisitor::visit (const ReturnExp &e)
+void DebugVisitor::visit(const ReturnExp & e)
 {
     START_NODE(e);
-    print(L"Exec ReturnExp", e);
+    print(e);
     if (!e.isGlobal())
     {
         e.getExp().accept(*this);
@@ -353,10 +460,10 @@ void DebugVisitor::visit (const ReturnExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const SelectExp &e)
+void DebugVisitor::visit(const SelectExp & e)
 {
     START_NODE(e);
-    print(L"Exec SelectExp", e);
+    print(e);
     e.getSelect()->accept(*this);
 
     exps_t cases = e.getCases();
@@ -372,19 +479,19 @@ void DebugVisitor::visit (const SelectExp &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const CaseExp &e)
+void DebugVisitor::visit(const CaseExp & e)
 {
     START_NODE(e);
-    print(L"Exec CaseExp", e);
+    print(e);
     e.getTest()->accept(*this);
     e.getBody()->accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const SeqExp  &e)
+void DebugVisitor::visit(const SeqExp & e)
 {
     START_NODE(e);
-    print(L"Exec SeqExp", e);
+    print(e);
     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
     {
         (*it)->accept(*this);
@@ -392,10 +499,10 @@ void DebugVisitor::visit (const SeqExp  &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const ArrayListExp  &e)
+void DebugVisitor::visit(const ArrayListExp & e)
 {
     START_NODE(e);
-    print(L"Exec ArrayListExp", e);
+    print(e);
     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
     {
         (*it)->accept(*this);
@@ -403,10 +510,10 @@ void DebugVisitor::visit (const ArrayListExp  &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const AssignListExp  &e)
+void DebugVisitor::visit(const AssignListExp & e)
 {
     START_NODE(e);
-    print(L"Exec AssignListExp", e);
+    print(e);
     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
     {
         (*it)->accept(*this);
@@ -414,37 +521,49 @@ void DebugVisitor::visit (const AssignListExp  &e)
     END_NODE();
 }
 
-void DebugVisitor::visit (const NotExp &e)
+void DebugVisitor::visit(const NotExp & e)
 {
     START_NODE(e);
-    print(L"Exec NotExp", e);
+    print(e);
     e.getExp().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const TransposeExp &e)
+void DebugVisitor::visit(const TransposeExp & e)
 {
     START_NODE(e);
-    print(L"Exec TransposeExp", e);
+    print(e);
     e.getExp().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const VarDec  &e)
+void DebugVisitor::visit(const VarDec & e)
 {
+    std::wstring sym, name;
+    if (colored)
+    {
+        sym = BOLD + L"Symbol" + NORMAL;
+        name = RED + e.getSymbol().getName() + NORMAL;
+    }
+    else
+    {
+        sym = L"Symbol";
+        name = e.getSymbol().getName();
+    }
+
     START_NODE(e);
-    print(L"Exec VarDec", e);
+    print(e);
     START_NODE(e);
-    print(L"Exec Symbol : " + e.getSymbol().getName(), e);
+    print(sym, e.getLocation(), name, L"");
     END_NODE();
     e.getInit().accept(*this);
     END_NODE();
 }
 
-void DebugVisitor::visit (const FunctionDec  &e)
+void DebugVisitor::visit(const FunctionDec & e)
 {
     START_NODE(e);
-    print(L"Exec FunctionDec", e);
+    print(e);
     // FIXME
 
     // First ask if there are some return values.
@@ -465,7 +584,7 @@ void DebugVisitor::visit (const FunctionDec  &e)
 void DebugVisitor::visit(const ListExp &e)
 {
     START_NODE(e);
-    print(L"Exec ListExp", e);
+    print(e);
     e.getStart().accept(*this);
     e.getStep().accept(*this);
     e.getEnd().accept(*this);
@@ -480,7 +599,7 @@ void DebugVisitor::visit(const OptimizedExp &e)
 void DebugVisitor::visit(const MemfillExp &e)
 {
     START_NODE(e);
-    print(L"Exec MemfillExp", e);
+    print(e);
     e.getValue().accept(*this);
 
     exps_t args = e.getArgs();
@@ -495,7 +614,7 @@ void DebugVisitor::visit(const MemfillExp &e)
 void DebugVisitor::visit(const DAXPYExp &e)
 {
     START_NODE(e);
-    print(L"Exec DAXPYExp", e);
+    print(e);
     e.getA().accept(*this);
     e.getX().accept(*this);
     e.getY().accept(*this);