1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 
16 #include "ConstantValue.hxx"
17 #include "alltypes.hxx"
18 #include "tools.hxx"
19 
20 namespace analysis
21 {
22 
ConstantValue(types::InternalType * _val)23 ConstantValue::ConstantValue(types::InternalType * _val) : val(_val), kind(ITVAL)
24 {
25     _val->IncreaseRef();
26 }
27 
ConstantValue(const ConstantValue & cv)28 ConstantValue::ConstantValue(const ConstantValue & cv) : val(cv.val), kind(cv.kind)
29 {
30     if (kind == ITVAL)
31     {
32         val.pIT->IncreaseRef();
33     }
34 }
35 
~ConstantValue()36 ConstantValue::~ConstantValue()
37 {
38     if (kind == ITVAL)
39     {
40         val.pIT->DecreaseRef();
41         val.pIT->killMe();
42     }
43 }
44 
operator =(const ConstantValue & R)45 ConstantValue & ConstantValue::operator=(const ConstantValue & R)
46 {
47     if (kind == ITVAL)
48     {
49         val.pIT->DecreaseRef();
50         val.pIT->killMe();
51     }
52     val = R.val;
53     kind = R.kind;
54     if (kind == ITVAL)
55     {
56         val.pIT->IncreaseRef();
57     }
58 
59     return *this;
60 }
61 
operator =(types::InternalType * const pIT)62 ConstantValue & ConstantValue::operator=(types::InternalType * const pIT)
63 {
64     if (kind == ITVAL)
65     {
66         val.pIT->DecreaseRef();
67         val.pIT->killMe();
68     }
69     val = pIT;
70     kind = ITVAL;
71     pIT->IncreaseRef();
72 
73     return *this;
74 }
75 
operator =(GVN::Value * const _val)76 ConstantValue & ConstantValue::operator=(GVN::Value * const _val)
77 {
78     if (kind == ITVAL)
79     {
80         val.pIT->DecreaseRef();
81         val.pIT->killMe();
82     }
83     val = _val;
84     kind = GVNVAL;
85 
86     return *this;
87 }
88 
operator =(ConstantValue && R)89 ConstantValue & ConstantValue::operator=(ConstantValue && R)
90 {
91     if (kind == ITVAL)
92     {
93         val.pIT->DecreaseRef();
94         val.pIT->killMe();
95     }
96     val = R.val;
97     kind = R.kind;
98     R.kind = UNKNOWN;
99 
100     return *this;
101 }
102 
getIT() const103 types::InternalType * ConstantValue::getIT() const
104 {
105     if (kind == ITVAL)
106     {
107         return val.pIT;
108     }
109 
110     return nullptr;
111 }
112 
getGVNValue() const113 GVN::Value * ConstantValue::getGVNValue() const
114 {
115     if (kind == GVNVAL)
116     {
117         return val.gvnVal;
118     }
119 
120     return nullptr;
121 }
122 
merge(const ConstantValue & cv)123 void ConstantValue::merge(const ConstantValue & cv)
124 {
125     if (kind != UNKNOWN && cv.kind != UNKNOWN)
126     {
127         if (kind == cv.kind)
128         {
129             switch (kind)
130             {
131                 case GVNVAL:
132                     if (val.gvnVal != cv.val.gvnVal)
133                     {
134                         kind = UNKNOWN;
135                     }
136                     break;
137                 case ITVAL:
138                     if (val.pIT != cv.val.pIT && *val.pIT != *cv.val.pIT)
139                     {
140                         val.pIT->DecreaseRef();
141                         val.pIT->killMe();
142                         kind = UNKNOWN;
143                     }
144                     break;
145                 default:
146                     break;
147             }
148         }
149         else if (kind == GVNVAL)
150         {
151             // cv.kind == ITVAL
152             double x;
153             if (cv.getDblValue(x) && val.gvnVal->poly->isConstant(x))
154             {
155                 kind = ITVAL;
156                 val.pIT = cv.val.pIT;
157                 val.pIT->IncreaseRef();
158             }
159             else
160             {
161                 kind = UNKNOWN;
162             }
163         }
164         else
165         {
166             // kind == ITVAL
167             double x;
168             if (!getDblValue(x) || !cv.val.gvnVal->poly->isConstant(x))
169             {
170                 val.pIT->DecreaseRef();
171                 val.pIT->killMe();
172                 kind = UNKNOWN;
173             }
174         }
175     }
176     else
177     {
178         if (kind == ITVAL)
179         {
180             val.pIT->DecreaseRef();
181             val.pIT->killMe();
182         }
183         kind = UNKNOWN;
184     }
185 }
186 
getGVNValue(GVN & gvn,GVN::Value * & _val) const187 bool ConstantValue::getGVNValue(GVN & gvn, GVN::Value *& _val) const
188 {
189     if (kind == GVNVAL)
190     {
191         _val = val.gvnVal;
192         return true;
193     }
194     else if (kind == ITVAL)
195     {
196         if (val.pIT->isDouble() && static_cast<types::Double *>(val.pIT)->getSize() == 1)
197         {
198             types::Double * pDbl = static_cast<types::Double *>(val.pIT);
199             if (!pDbl->isComplex() || pDbl->getImg(0) == 0)
200             {
201                 const double x = pDbl->get()[0];
202                 int64_t i;
203                 if (tools::asInteger(x, i))
204                 {
205                     _val = gvn.getValue(i);
206                     return true;
207                 }
208             }
209         }
210     }
211 
212     return false;
213 }
214 
getDblValue(double & _val) const215 bool ConstantValue::getDblValue(double & _val) const
216 {
217     if (kind == ITVAL)
218     {
219         if (val.pIT->isDouble() && static_cast<types::Double *>(val.pIT)->getSize() == 1)
220         {
221             types::Double * pDbl = static_cast<types::Double *>(val.pIT);
222             if (!pDbl->isComplex() || pDbl->getImg(0) == 0)
223             {
224                 _val = pDbl->get()[0];
225                 return true;
226             }
227         }
228     }
229     else if (kind == GVNVAL)
230     {
231         if (GVN::Value * gvnValue = val.gvnVal)
232         {
233             if (gvnValue->poly->isConstant())
234             {
235                 _val = (double)gvnValue->poly->constant;
236                 return true;
237             }
238         }
239     }
240     return false;
241 }
242 
getBoolValue(bool & _val) const243 bool ConstantValue::getBoolValue(bool & _val) const
244 {
245     if (kind == ITVAL)
246     {
247         if (val.pIT->isBool() && static_cast<types::Bool *>(val.pIT)->getSize() == 1)
248         {
249             _val = (bool)static_cast<types::Bool *>(val.pIT)->get(0);
250         }
251         else
252         {
253             _val = val.pIT->isTrue();
254         }
255         return true;
256     }
257     else if (kind == GVNVAL)
258     {
259         if (GVN::Value * gvnValue = val.gvnVal)
260         {
261             if (gvnValue->poly->isConstant())
262             {
263                 _val = gvnValue->poly->constant != 0;
264                 return true;
265             }
266         }
267     }
268     return false;
269 }
270 
getCplxValue(std::complex<double> & _val) const271 bool ConstantValue::getCplxValue(std::complex<double> & _val) const
272 {
273     if (kind == ITVAL)
274     {
275         if (val.pIT->isDouble() && static_cast<types::Double *>(val.pIT)->getSize() == 1)
276         {
277             types::Double * pDbl = static_cast<types::Double *>(val.pIT);
278             if (pDbl->isComplex())
279             {
280                 _val.real(pDbl->get(0));
281                 _val.imag(pDbl->getImg(0));
282             }
283             else
284             {
285                 _val.real(pDbl->get(0));
286                 _val.imag(0);
287             }
288             return true;
289         }
290     }
291     else if (kind == GVNVAL)
292     {
293         if (GVN::Value * gvnValue = val.gvnVal)
294         {
295             if (gvnValue->poly->isConstant())
296             {
297                 _val.real((double)gvnValue->poly->constant);
298                 _val.imag(0.);
299                 return true;
300             }
301         }
302     }
303     return false;
304 }
305 
getStrValue(std::wstring & _val) const306 bool ConstantValue::getStrValue(std::wstring & _val) const
307 {
308     if (kind == ITVAL)
309     {
310         if (val.pIT->isString() && static_cast<types::String *>(val.pIT)->getSize() == 1)
311         {
312             _val = std::wstring(static_cast<types::String *>(val.pIT)->get(0));
313             return true;
314         }
315     }
316 
317     return false;
318 }
319 
320 
operator <<(std::wostream & out,const ConstantValue & cv)321 std::wostream & operator<<(std::wostream & out, const ConstantValue & cv)
322 {
323     switch (cv.kind)
324     {
325         case ConstantValue::GVNVAL:
326             out << *cv.val.gvnVal;
327             break;
328         case ConstantValue::ITVAL:
329         {
330             if (cv.val.pIT->isDouble() && static_cast<types::Double *>(cv.val.pIT)->getSize() == 1)
331             {
332                 out << static_cast<types::Double *>(cv.val.pIT)->get(0, 0);
333             }
334             else
335             {
336                 out << L"\"" << cv.val.pIT->getTypeStr() << L"\"";
337             }
338             break;
339         }
340         default:
341             break;
342     }
343 
344     return out;
345 }
346 }
347