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