Analysis: infer when a refcount is required and add colors in DebugVisitor
[scilab.git] / scilab / modules / ast / includes / analysis / data / LoopBlock.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #ifndef __LOOPBLOCK_HXX__
14 #define __LOOPBLOCK_HXX__
15
16 #include <unordered_map>
17
18 #include "Block.hxx"
19 #include "tools.hxx"
20
21 namespace analysis
22 {
23
24 class LoopAnalyzer;
25
26 class LoopBlockHead : public Block
27 {
28     /*
29       A loop block naturally contains phi nodes:
30       a = 0;
31       b = 1;
32       for i=1:N
33       a = a + b // the values of a and b depends from where we come
34       // a = phi(before loop, end loop) + phi(before loop, end loop)
35       b = b + int8(1) // b = phi(before loop, end loop) + int8(1)
36       end
37       So we can suppose three cases:
38       i) we don't enter in the loop => easy: we just ignore the loop
39       ii) the loop has only one iteration => easy: the loop block is equivalent to a normal block
40       iii) the loop has more than one iteration => types and refcounts need to be computed again
41       according to the inferred types and refcounts at the end of the loop.
42       The best case (except empty loops) is when info are the same before and after one iteration.
43       In the previous example, after one iteration a is typed double and b is int8 but after a second iteration
44       a & b are int8.
45
46       The problem is that in the most of the cases loops should have a lot of iterations so we can suppose with a
47       good probability that inferred types after the loop should be ones guessed after two iterations.
48     */
49
50 public:
51
52     LoopBlockHead(const unsigned int id, Block * parent, ast::Exp * exp) : Block(id, parent, exp) { }
53
54     inline Block * getFirstBlock()
55     {
56         return blocks.front();
57     }
58
59     inline Block * getSecondBlock()
60     {
61         return blocks.back();
62     }
63
64     Block * addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp) override;
65     void finalize() override;
66 };
67
68 class LoopBlock : public Block
69 {
70
71     friend class LoopBlockHead;
72
73     const bool first;
74     std::unordered_map<ast::Exp *, symbol::Symbol> clonedSym;
75
76 public:
77     LoopBlock(const unsigned int id, Block * parent, ast::Exp * exp, const bool _first) : Block(id, parent, exp), first(_first) { }
78
79     inline LoopBlockHead * getParent()
80     {
81         return static_cast<LoopBlockHead *>(parent);
82     }
83
84     bool requiresAnotherTrip() override;
85     Block * getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global) override;
86     Info & getInfo(const symbol::Symbol & sym) override;
87     void clone(const symbol::Symbol & sym, ast::Exp * exp) override;
88     void finalize() override;
89 };
90
91 } // namespace analysis
92
93 #endif // __LOOPBLOCK_HXX__