PandA-2024.02
bit_lattice.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
41 #include "bit_lattice.hpp"
43 
45 #include "Parameter.hpp"
46 
48 #include <string>
49 
51 #include <algorithm>
52 #include <vector>
53 
55 #include "tree_helper.hpp"
56 #include "tree_manager.hpp"
57 #include "tree_node.hpp"
58 #include "tree_reindex.hpp"
59 
61 #include "dbgPrintHelper.hpp"
62 #include "string_manipulation.hpp"
63 #include "utility.hpp"
64 
66  : TM(_TM), bl_debug_level(_bl_debug_level)
67 {
68 }
69 
71 
73 {
74  return signed_var.count(tn->index) || tree_helper::IsSignedIntegerType(tn);
75 }
76 
78 {
79  if(a == b)
80  {
81  return a;
82  }
83  else if(a == bit_lattice::X || b == bit_lattice::X)
84  {
85  return bit_lattice::X;
86  }
87  else if(a == bit_lattice::U)
88  {
89  return b;
90  }
91  else if(b == bit_lattice::U)
92  {
93  return a;
94  }
95  else
96  {
97  return bit_lattice::X;
98  }
99 }
100 
101 std::deque<bit_lattice> BitLatticeManipulator::sup(const std::deque<bit_lattice>& _a, const std::deque<bit_lattice>& _b,
102  const size_t out_type_size, const bool out_is_signed,
103  const bool out_is_bool)
104 {
105  THROW_ASSERT(!_a.empty() && !_b.empty(), "a = " + std::string(_a.empty() ? "empty" : bitstring_to_string(_a)) +
106  ", b = " + (_b.empty() ? "empty" : bitstring_to_string(_b)));
107  THROW_ASSERT(out_type_size, "Size can not be zero");
108  THROW_ASSERT(!out_is_bool || (out_type_size == 1), "boolean with type size != 1");
109  std::deque<bit_lattice> res;
110  if(out_is_bool)
111  {
112  res.push_back(bit_sup(_a.back(), _b.back()));
113  return res;
114  }
115 
116  std::deque<bit_lattice> longer = (_a.size() >= _b.size()) ? _a : _b;
117  std::deque<bit_lattice> shorter = (_a.size() >= _b.size()) ? _b : _a;
118  while(longer.size() > out_type_size)
119  {
120  longer.pop_front();
121  }
122  while(shorter.size() > out_type_size)
123  {
124  shorter.pop_front();
125  }
126  if(longer.size() < out_type_size)
127  {
128  longer = sign_extend_bitstring(longer, out_is_signed, out_type_size);
129  }
130  if(shorter.size() < out_type_size)
131  {
132  shorter = sign_extend_bitstring(shorter, out_is_signed, out_type_size);
133  }
134  // // BEWARE: zero is stored as single bit, but it has to be considered as a full string
135  // // of zeros to propagate values correctly
136  // if(shorter.size() == 1 && shorter.front() == bit_lattice::ZERO)
137  // {
138  // auto l_bw = longer.size();
139  // for(;l_bw > 1; --l_bw)
140  // shorter.push_front(bit_lattice::ZERO);
141  // }
142  // if(!out_is_signed && longer.size() > shorter.size() && longer.front() == bit_lattice::ZERO)
143  // {
144  // shorter = sign_extend_bitstring(shorter, out_is_signed, longer.size());
145  // }
146  // else
147  // {
148  // while(longer.size() > shorter.size())
149  // {
150  // if(out_is_signed)
151  // {
152  // shorter = sign_extend_bitstring(shorter, out_is_signed, longer.size());
153  // }
154  // else
155  // {
156  // longer.pop_front();
157  // }
158  // }
159  // }
160 
161  auto a_it = longer.crbegin();
162  auto b_it = shorter.crbegin();
163  const auto a_end = longer.crend();
164  const auto b_end = shorter.crend();
165  for(; a_it != a_end && b_it != b_end; a_it++, b_it++)
166  {
167  res.push_front(bit_sup(*a_it, *b_it));
168  }
169 
170  if(res.empty())
171  {
172  res.push_front(bit_lattice::X);
173  }
174  sign_reduce_bitstring(res, out_is_signed);
175  size_t final_size;
176  const bool a_sign_is_x = _a.front() == bit_lattice::X;
177  const bool b_sign_is_x = _b.front() == bit_lattice::X;
178  auto sign_bit = res.front();
179  if(out_is_signed)
180  {
181  final_size =
182  std::min(out_type_size,
183  ((a_sign_is_x == b_sign_is_x ||
184  ((_a.front() == bit_lattice::ZERO || _a.front() == bit_lattice::ONE) && _a.size() < _b.size()) ||
185  ((_b.front() == bit_lattice::ZERO || _b.front() == bit_lattice::ONE) && _a.size() > _b.size())) ?
186  (std::min(_a.size(), _b.size())) :
187  (a_sign_is_x ? _a.size() : _b.size())));
188  THROW_ASSERT(final_size, "final size of sup cannot be 0");
189  }
190  else
191  {
192  final_size = std::min(out_type_size, (a_sign_is_x == b_sign_is_x) ?
193  std::min(_a.size(), _b.size()) :
194  (a_sign_is_x ? (_a.size() < _b.size() ? _a.size() : 1 + _b.size()) :
195  (_a.size() < _b.size() ? 1 + _a.size() : _b.size())));
196  sign_bit = (a_sign_is_x == b_sign_is_x) ? sign_bit :
197  (a_sign_is_x ? (_a.size() < _b.size() ? sign_bit : bit_lattice::ZERO) :
198  (_a.size() < _b.size() ? bit_lattice::ZERO : sign_bit));
199  THROW_ASSERT(final_size, "final size of sup cannot be 0");
200  }
201  while(res.size() > final_size)
202  {
203  res.pop_front();
204  }
205  if(sign_bit != bit_lattice::X && res.front() == bit_lattice::X)
206  {
207  res.pop_front();
208  res.push_front(sign_bit);
209  }
210  if(!out_is_signed)
211  {
212  sign_reduce_bitstring(res, out_is_signed);
213  }
214 
215  return res;
216 }
217 
218 std::deque<bit_lattice> BitLatticeManipulator::sup(const std::deque<bit_lattice>& a, const std::deque<bit_lattice>& b,
219  const unsigned int output_uid) const
220 {
221  return sup(a, b, TM->CGetTreeNode(output_uid));
222 }
223 
224 std::deque<bit_lattice> BitLatticeManipulator::sup(const std::deque<bit_lattice>& a, const std::deque<bit_lattice>& b,
225  const tree_nodeConstRef& out_node) const
226 {
227  THROW_ASSERT(!a.empty() && !b.empty(), "a.size() = " + STR(a.size()) + " b.size() = " + STR(b.size()));
228 
229  // extend the shorter of the two bitstrings
230  // compute the underlying type size
231  const auto kind =
232  out_node->get_kind() == tree_reindex_K ? GET_CONST_NODE(out_node)->get_kind() : out_node->get_kind();
233  const auto node_type = tree_helper::CGetType(out_node);
234  size_t out_type_size = 0;
235  if(kind == ssa_name_K || kind == parm_decl_K || kind == integer_cst_K)
236  {
237  out_type_size = static_cast<size_t>(Size(node_type));
238  }
239  else if(kind == function_decl_K)
240  {
241  THROW_ASSERT(GET_CONST_NODE(node_type)->get_kind() == function_type_K ||
242  GET_CONST_NODE(node_type)->get_kind() == method_type_K,
243  "node " + STR(out_node) + " is " + node_type->get_kind_text());
244  const auto ft = GetPointerS<const function_type>(GET_CONST_NODE(node_type));
245  out_type_size = static_cast<size_t>(Size(ft->retn));
246  }
247  else
248  {
249  THROW_UNREACHABLE("unexpected sup for output_uid " + STR(out_node) + " of kind " + tree_node::GetString(kind));
250  }
251  THROW_ASSERT(out_type_size, "");
252  const auto out_is_bool = tree_helper::IsBooleanType(node_type);
253  THROW_ASSERT(!out_is_bool || (out_type_size == 1), "boolean with type size != 1");
254  const auto out_is_signed = IsSignedIntegerType(out_node);
255  return sup(a, b, out_type_size, out_is_signed, out_is_bool);
256 }
257 
259 {
260  if(a == b)
261  {
262  return a;
263  }
264  else if(a == bit_lattice::U || b == bit_lattice::U)
265  {
266  return bit_lattice::U;
267  }
268  else if(a == bit_lattice::X)
269  {
270  return b;
271  }
272  else if(b == bit_lattice::X)
273  {
274  return a;
275  }
276  else
277  {
278  return bit_lattice::U;
279  }
280 }
281 
282 std::deque<bit_lattice> BitLatticeManipulator::inf(const std::deque<bit_lattice>& a, const std::deque<bit_lattice>& b,
283  const size_t out_type_size, const bool out_is_signed,
284  const bool out_is_bool)
285 {
286  THROW_ASSERT(!(a.empty() && b.empty()), "a.size() = " + STR(a.size()) + " b.size() = " + STR(b.size()));
287  THROW_ASSERT(out_type_size, "");
288  THROW_ASSERT(!out_is_bool || (out_type_size == 1), "boolean with type size != 1");
289  std::deque<bit_lattice> res;
290  if(out_is_bool)
291  {
292  res.push_back(bit_inf(a.back(), b.back()));
293  return res;
294  }
295 
296  std::deque<bit_lattice> a_copy = a;
297  std::deque<bit_lattice> b_copy = b;
298  sign_reduce_bitstring(a_copy, out_is_signed);
299  sign_reduce_bitstring(b_copy, out_is_signed);
300 
301  // a_tmp is the longer bistring
302  std::deque<bit_lattice> a_tmp = (a_copy.size() >= b_copy.size()) ? a_copy : b_copy;
303  std::deque<bit_lattice> b_tmp = (a_copy.size() >= b_copy.size()) ? b_copy : a_copy;
304 
305  if(a_tmp.size() > b_tmp.size())
306  {
307  b_tmp = sign_extend_bitstring(b_tmp, out_is_signed, a_tmp.size());
308  }
309 
310  auto a_it = a_tmp.crbegin();
311  auto b_it = b_tmp.crbegin();
312  const auto a_end = a_tmp.crend();
313  const auto b_end = b_tmp.crend();
314  for(; a_it != a_end && b_it != b_end; a_it++, b_it++)
315  {
316  res.push_front(bit_inf(*a_it, *b_it));
317  }
318 
319  if(res.empty())
320  {
321  res.push_front(bit_lattice::X);
322  }
323 
324  sign_reduce_bitstring(res, out_is_signed);
325 
326  while(res.size() > out_type_size)
327  {
328  res.pop_front();
329  }
330  return res;
331 }
332 
333 std::deque<bit_lattice> BitLatticeManipulator::inf(const std::deque<bit_lattice>& a, const std::deque<bit_lattice>& b,
334  const unsigned int output_uid) const
335 {
336  return inf(a, b, TM->CGetTreeNode(output_uid));
337 }
338 
339 std::deque<bit_lattice> BitLatticeManipulator::inf(const std::deque<bit_lattice>& a, const std::deque<bit_lattice>& b,
340  const tree_nodeConstRef& out_node) const
341 {
342  THROW_ASSERT(!(a.empty() && b.empty()), "a.size() = " + STR(a.size()) + " b.size() = " + STR(b.size()));
343 
344  const auto kind =
345  out_node->get_kind() == tree_reindex_K ? GET_CONST_NODE(out_node)->get_kind() : out_node->get_kind();
346  const auto node_type = tree_helper::CGetType(out_node);
347  size_t out_type_size = 0;
348  if(kind == ssa_name_K || kind == parm_decl_K || kind == integer_cst_K)
349  {
350  out_type_size = static_cast<size_t>(Size(node_type));
351  }
352  else if(kind == function_decl_K)
353  {
354  THROW_ASSERT(GET_CONST_NODE(node_type)->get_kind() == function_type_K ||
355  GET_CONST_NODE(node_type)->get_kind() == method_type_K,
356  "node " + STR(out_node) + " is " + node_type->get_kind_text());
357  const auto ft = GetPointerS<const function_type>(GET_CONST_NODE(node_type));
358  out_type_size = static_cast<size_t>(Size(ft->retn));
359  }
360  else
361  {
362  THROW_UNREACHABLE("unexpected sup for " + STR(out_node) + " of kind " + tree_node::GetString(kind));
363  }
364  THROW_ASSERT(out_type_size, "");
365  const auto out_is_bool = tree_helper::IsBooleanType(node_type);
366  THROW_ASSERT(!out_is_bool || (out_type_size == 1), "boolean with type size != 1");
367  const auto out_is_signed = IsSignedIntegerType(out_node);
368  return inf(a, b, out_type_size, out_is_signed, out_is_bool);
369 }
370 
372 void BitLatticeManipulator::sign_reduce_bitstring(std::deque<bit_lattice>& bitstring, bool bitstring_is_signed)
373 {
374  THROW_ASSERT(!bitstring.empty(), "");
375  while(bitstring.size() > 1)
376  {
377  if(bitstring_is_signed)
378  {
379  if(bitstring.at(0) != bit_lattice::U && bitstring.at(0) == bitstring.at(1))
380  {
381  bitstring.pop_front();
382  }
383  else
384  {
385  break;
386  }
387  }
388  else
389  {
390  if((bitstring.at(0) == bit_lattice::X && bitstring.at(1) == bit_lattice::X) ||
391  (bitstring.at(0) == bit_lattice::ZERO && bitstring.at(1) != bit_lattice::X))
392  {
393  bitstring.pop_front();
394  }
395  else if(bitstring.at(0) == bit_lattice::ZERO && bitstring.at(1) == bit_lattice::X)
396  {
397  bitstring.pop_front();
398  bitstring.pop_front();
399  bitstring.push_front(bit_lattice::ZERO);
400  }
401  else
402  {
403  break;
404  }
405  }
406  }
407 }
408 
409 std::deque<bit_lattice> BitLatticeManipulator::sign_extend_bitstring(const std::deque<bit_lattice>& bitstring,
410  bool bitstring_is_signed, size_t final_size)
411 {
412  THROW_ASSERT(final_size, "cannot sign extend a bitstring to final_size 0");
413  THROW_ASSERT(final_size > bitstring.size(), "useless sign extension");
414  std::deque<bit_lattice> res = bitstring;
415  if(res.empty())
416  {
417  res.push_front(bit_lattice::X);
418  }
419  const auto sign_bit = (bitstring_is_signed || res.front() == bit_lattice::X) ? res.front() : bit_lattice::ZERO;
420  while(res.size() < final_size)
421  {
422  res.push_front(sign_bit);
423  }
424  return res;
425 }
426 
427 std::deque<bit_lattice> BitLatticeManipulator::constructor_bitstring(const tree_nodeRef& ctor_tn,
428  unsigned int ssa_node_id) const
429 {
430  const bool ssa_is_signed = tree_helper::is_int(TM, ssa_node_id);
431  THROW_ASSERT(ctor_tn->get_kind() == constructor_K, "ctor_tn is not constructor node");
432  auto* c = GetPointerS<const constructor>(ctor_tn);
433  std::vector<unsigned long long> array_dims;
434  unsigned long long elements_bitsize;
435  tree_helper::get_array_dim_and_bitsize(TM, GET_INDEX_CONST_NODE(c->type), array_dims, elements_bitsize);
436  unsigned int initialized_elements = 0;
437  std::deque<bit_lattice> current_inf;
438  current_inf.push_back(bit_lattice::X);
439  std::deque<bit_lattice> cur_bitstring;
440  for(const auto& i : c->list_of_idx_valu)
441  {
442  const auto el = GET_CONST_NODE(i.second);
443  THROW_ASSERT(el, "unexpected condition");
444 
445  if(el->get_kind() == integer_cst_K)
446  {
447  cur_bitstring =
448  create_bitstring_from_constant(tree_helper::GetConstValue(i.second), elements_bitsize, ssa_is_signed);
449  }
450  else if(el->get_kind() == real_cst_K)
451  {
452  THROW_ASSERT(elements_bitsize == 64 || elements_bitsize == 32,
453  "Unhandled real type size (" + STR(elements_bitsize) + ")");
454  const auto real_const = GetPointerS<const real_cst>(el);
455  if(real_const->valx.front() == '-' && real_const->valr.front() != real_const->valx.front())
456  {
457  cur_bitstring = string_to_bitstring(convert_fp_to_string("-" + real_const->valr, elements_bitsize));
458  }
459  else
460  {
461  cur_bitstring = string_to_bitstring(convert_fp_to_string(real_const->valr, elements_bitsize));
462  }
463  sign_reduce_bitstring(cur_bitstring, ssa_is_signed);
464  }
465  else if(el->get_kind() == constructor_K &&
466  GetPointer<const array_type>(GET_CONST_NODE(GetPointerS<const constructor>(el)->type)))
467  {
468  THROW_ASSERT(array_dims.size() > 1 || GET_NODE(c->type)->get_kind() == record_type_K,
469  "invalid nested constructors:" + ctor_tn->ToString() + " " + STR(array_dims.size()));
470  cur_bitstring = constructor_bitstring(el, ssa_node_id);
471  }
472  else
473  {
474  cur_bitstring = create_u_bitstring(elements_bitsize);
475  }
476 
477  current_inf = inf(current_inf, cur_bitstring, ssa_node_id);
478  initialized_elements++;
479  }
480  if(initialized_elements < array_dims.front())
481  {
482  current_inf = inf(current_inf, create_bitstring_from_constant(0, elements_bitsize, ssa_is_signed), ssa_node_id);
483  }
484  return current_inf;
485 }
486 
487 std::deque<bit_lattice> BitLatticeManipulator::string_cst_bitstring(const tree_nodeRef& strcst_tn,
488  unsigned int ssa_node_id) const
489 {
490  THROW_ASSERT(strcst_tn->get_kind() == string_cst_K, "strcst_tn is not a string_cst node");
491  auto* sc = GetPointerS<string_cst>(strcst_tn);
492  const std::string str = sc->strg;
493  const bool node_is_signed = tree_helper::is_int(TM, ssa_node_id);
494  auto current_inf = create_bitstring_from_constant(0, 8, node_is_signed);
495  for(const auto c : str)
496  {
497  auto current_el = create_bitstring_from_constant(static_cast<long long int>(c), 8, node_is_signed);
498  current_inf = inf(current_inf, current_el, ssa_node_id);
499  }
500  return current_inf;
501 }
502 
504 {
505  const auto type = tree_helper::CGetType(tn);
508 }
509 
511 {
512  auto updated = false;
513  for(auto& b : best)
514  {
515  const auto c = current.find(b.first);
516  if(c != current.end())
517  {
518  const auto cur_lattice = c->second;
519  const auto best_lattice = b.second;
520  const auto sup_lattice = sup(cur_lattice, best_lattice, b.first);
521  if(best_lattice != sup_lattice)
522  {
523  b.second = sup_lattice;
524  updated = true;
525 #ifndef NDEBUG
526  const auto tn = TM->CGetTreeNode(b.first);
527 #endif
529  "Changes in " +
530  STR(tn->get_kind() == function_decl_K ?
531  (tree_helper::GetMangledFunctionName(GetPointerS<const function_decl>(tn)) +
532  " return value") :
533  STR(tn)) +
534  " Cur is " + bitstring_to_string(cur_lattice) + " Best is " +
535  bitstring_to_string(best_lattice) + " Sup is " + bitstring_to_string(sup_lattice));
536  }
537  }
538  }
539  return updated;
540 }
541 
542 bool BitLatticeManipulator::update_current(std::deque<bit_lattice>& res, const tree_nodeConstRef& tn)
543 {
544  if(!res.empty())
545  {
546  const auto out_is_signed = IsSignedIntegerType(tn);
547  sign_reduce_bitstring(res, out_is_signed);
548  if(out_is_signed && res.front() == bit_lattice::X)
549  {
550  res.front() = bit_lattice::ZERO;
551  }
552 
553  THROW_ASSERT(best.count(tn->index), "");
554  const auto sup_lattice = bitstring_constant(res) ? res : sup(res, best.at(tn->index), tn);
555  auto& cur_lattice = current[tn->index];
556  if(cur_lattice != sup_lattice)
557  {
558  cur_lattice = sup_lattice;
559  return true;
560  }
561  }
562  return false;
563 }
564 
566 {
567  current.clear();
568  best.clear();
569  signed_var.clear();
570 }
571 
572 std::deque<bit_lattice> create_u_bitstring(size_t lenght)
573 {
574  return std::deque<bit_lattice>(lenght, bit_lattice::U);
575 }
576 
577 std::deque<bit_lattice> create_x_bitstring(size_t lenght)
578 {
579  return std::deque<bit_lattice>(lenght, bit_lattice::X);
580 }
581 
582 std::deque<bit_lattice> create_bitstring_from_constant(integer_cst_t value, unsigned long long len, bool signed_value)
583 {
584  std::deque<bit_lattice> res;
585  if(value == 0)
586  {
587  res.push_front(bit_lattice::ZERO);
588  return res;
589  }
590  unsigned bit;
591  for(bit = 0; bit < len && value != 0; bit++, value >>= 1)
592  {
593  res.push_front((value & 1) ? bit_lattice::ONE : bit_lattice::ZERO);
594  }
595  if(bit < len && signed_value)
596  {
597  res.push_front(bit_lattice::ZERO);
598  }
599  return res;
600 }
601 
602 std::string bitstring_to_string(const std::deque<bit_lattice>& bitstring)
603 {
604  std::string res;
605  for(const auto bit : bitstring)
606  {
607  switch(bit)
608  {
609  case(bit_lattice::U):
610  res.push_back('U');
611  break;
612  case(bit_lattice::X):
613  res.push_back('X');
614  break;
615  case(bit_lattice::ZERO):
616  res.push_back('0');
617  break;
618  case(bit_lattice::ONE):
619  res.push_back('1');
620  break;
621  default:
622  THROW_ERROR("unexpected value in bit_lattice");
623  break;
624  }
625  }
626  return res;
627 }
628 
629 std::deque<bit_lattice> string_to_bitstring(const std::string& s)
630 {
631  std::deque<bit_lattice> res;
632  for(const auto bit : s)
633  {
634  switch(bit)
635  {
636  case('U'):
637  res.push_back(bit_lattice::U);
638  break;
639  case('X'):
640  res.push_back(bit_lattice::X);
641  break;
642  case('0'):
643  res.push_back(bit_lattice::ZERO);
644  break;
645  case('1'):
646  res.push_back(bit_lattice::ONE);
647  break;
648  default:
649  THROW_ERROR(std::string("unexpected char in bitvalue string: ") + bit);
650  break;
651  }
652  }
653  return res;
654 }
655 
656 bool bitstring_constant(const std::deque<bit_lattice>& a)
657 {
658  bool res = true;
659  for(const auto i : a)
660  {
661  if(i == bit_lattice::U || i == bit_lattice::X)
662  {
663  res = false;
664  break;
665  }
666  }
667  return res;
668 }
669 
670 unsigned long long BitLatticeManipulator::size(const tree_managerConstRef tm, unsigned int index)
671 {
672  return BitLatticeManipulator::Size(tm->CGetTreeNode(index));
673 }
674 
675 unsigned long long BitLatticeManipulator::Size(const tree_nodeConstRef& t)
676 {
677  switch(t->get_kind())
678  {
679  case tree_reindex_K:
680  {
681  return Size(GET_CONST_NODE(t));
682  }
683  case CASE_DECL_NODES:
684  {
685  THROW_ASSERT(GetPointerS<const decl_node>(t)->type, "expected a var decl type");
686  if(t->get_kind() == function_decl_K)
687  {
688  return 32u;
689  }
690  return Size(GET_NODE(GetPointerS<const decl_node>(t)->type));
691  }
692  case ssa_name_K:
693  {
694  const auto sa = GetPointerS<const ssa_name>(t);
695  THROW_ASSERT(sa->type, "Expected an ssa_name type");
696  return Size(GET_CONST_NODE(sa->type));
697  }
698  case array_type_K:
699  {
700  const auto at = GetPointerS<const array_type>(t);
701  if(at->size)
702  {
703  if(tree_helper::IsConstant(at->size))
704  {
705  const auto val = tree_helper::GetConstValue(at->size);
706  THROW_ASSERT(val >= 0, "");
707  return static_cast<unsigned long long>(val);
708  }
709  return 32u;
710  }
711  break;
712  }
713  case boolean_type_K:
714  {
715  return 1u;
716  }
717  case CharType_K:
718  case complex_type_K:
719  case enumeral_type_K:
720  case function_type_K:
721  case method_type_K:
722  case nullptr_type_K:
723  case pointer_type_K:
724  case real_type_K:
725  case record_type_K:
726  case reference_type_K:
727  case type_pack_expansion_K:
728  case type_argument_pack_K:
729  case union_type_K:
730  case vector_type_K:
731  {
732  const auto tn = GetPointer<const type_node>(t);
733  THROW_ASSERT(tn->size, "");
734  const auto val = tree_helper::GetConstValue(tn->size);
735  THROW_ASSERT(val >= 0, "");
736  return static_cast<unsigned long long>(val);
737  }
738  case integer_type_K:
739  {
740  const auto it = GetPointer<const integer_type>(t);
741  if(it->prec != it->algn && it->prec % it->algn)
742  {
743  return it->prec;
744  }
745  THROW_ASSERT(it->size, "");
746  const auto val = tree_helper::GetConstValue(it->size);
747  THROW_ASSERT(val >= 0, "");
748  return static_cast<unsigned long long>(val);
749  }
750  case void_type_K:
751  {
752  return 32u;
753  }
754  case call_expr_K:
755  case aggr_init_expr_K:
756  {
757  const auto ce = GetPointerS<const call_expr>(t);
758  return Size(GET_NODE(ce->type));
759  }
763  {
764  const auto te = GetPointerS<const expr_node>(t);
765  return Size(GET_NODE(te->type));
766  }
767  case lut_expr_K:
768  {
769  return 1u;
770  }
771  case array_ref_K:
772  {
773  const auto ar = GetPointerS<const array_ref>(t);
774  return Size(GET_NODE(ar->type));
775  }
776  case CASE_CST_NODES:
777  {
778  const auto sc = GetPointerS<const cst_node>(t);
779  return Size(GET_NODE(sc->type));
780  }
781  case constructor_K:
782  {
783  const auto c = GetPointerS<const constructor>(t);
784  return Size(GET_NODE(c->type));
785  }
786  case target_mem_ref461_K:
787  {
788  const auto tmr = GetPointerS<const target_mem_ref461>(t);
789  return Size(GET_NODE(tmr->type));
790  }
791  case gimple_call_K:
792  {
793  return 32u;
794  }
795  case array_range_ref_K:
796  case binfo_K:
797  case block_K:
798  case case_label_expr_K:
799  case identifier_node_K:
800  case lang_type_K:
801  case offset_type_K:
802  case qual_union_type_K:
803  case set_type_K:
804  case statement_list_K:
805  case target_expr_K:
806  case target_mem_ref_K:
807  case template_type_parm_K:
808  case tree_list_K:
809  case tree_vec_K:
810  case typename_type_K:
811  case CASE_CPP_NODES:
812  case last_tree_K:
813  case none_K:
814  case placeholder_expr_K:
815  case gimple_asm_K:
816  case gimple_assign_K:
817  case gimple_bind_K:
818  case gimple_cond_K:
819  case gimple_for_K:
820  case gimple_goto_K:
821  case gimple_label_K:
822  case gimple_multi_way_if_K:
823  case gimple_nop_K:
824  case gimple_phi_K:
825  case gimple_pragma_K:
826  case gimple_predict_K:
827  case gimple_resx_K:
828  case gimple_return_K:
829  case gimple_switch_K:
830  case gimple_while_K:
831  case CASE_PRAGMA_NODES:
832  case error_mark_K:
833  default:
834  {
835  THROW_UNREACHABLE(std::string("Unexpected type pattern ") + t->get_kind_text());
836  }
837  }
838  THROW_ERROR("unexpected pattern");
839  return 0u;
840 }
841 
842 bool BitLatticeManipulator::isBetter(const std::string& a_string, const std::string& b_string)
843 {
844  auto av = string_to_bitstring(a_string);
845  auto bv = string_to_bitstring(b_string);
846  auto a_it = av.crbegin();
847  auto b_it = bv.crbegin();
848  const auto a_end = av.crend();
849  const auto b_end = bv.crend();
850  for(; a_it != a_end && b_it != b_end; a_it++, b_it++)
851  {
852  if((*b_it == bit_lattice::U && *a_it != bit_lattice::U) || (*b_it != bit_lattice::X && *a_it == bit_lattice::X))
853  {
854  return true;
855  }
856  }
857  return a_string.size() < b_string.size();
858 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
std::deque< bit_lattice > string_cst_bitstring(const tree_nodeRef &strcst_tn, unsigned int ssa_node_id) const
auxiliary function used to build the bitstring lattice for read-only string_cst
std::string convert_fp_to_string(std::string num, unsigned long long precision)
convert a real number stored in a string into a string of bits with a given precision ...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsComplexType(const tree_nodeConstRef &type)
Return if treenode is a complex.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
std::deque< bit_lattice > create_bitstring_from_constant(integer_cst_t value, unsigned long long len, bool signed_value)
Creates a bitstring from a constant input.
File containing functions and utilities to support the printing of debug messagges.
static bool is_int(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of integer type.
std::string ToString() const
Print this node as string in gimple format.
static bool IsConstant(const tree_nodeConstRef &node)
Return if a tree node is a constant object.
#define CASE_BINARY_EXPRESSION
This macro collects all case labels for binary_expr objects.
Definition: tree_node.hpp:463
std::deque< bit_lattice > create_x_bitstring(size_t lenght)
Create a bitstring containing bits initialized at <X>
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
Definition: tree_node.hpp:672
static bool isBetter(const std::string &a_string, const std::string &b_string)
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
Definition: tree_node.cpp:120
bool bitstring_constant(const std::deque< bit_lattice > &a)
Checks if a bitstring is constant.
bool IsHandledByBitvalue(const tree_nodeConstRef &tn) const
Returns true if the type identified by type_id is handled by bitvalue analysis.
#define min(x, y)
static bit_lattice bit_inf(const bit_lattice a, const bit_lattice b)
static std::string GetMangledFunctionName(const function_decl *fd)
Return the mangled function name.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
static void sign_reduce_bitstring(std::deque< bit_lattice > &bitstring, bool bitstring_is_signed)
Reduce the size of a bitstring erasing all but one most significant zeros in unsigned bitstring and a...
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
CustomSet< unsigned int > signed_var
Set storing the signed ssa.
Definition: bit_lattice.hpp:90
std::string bitstring_to_string(const std::deque< bit_lattice > &bitstring)
Translates a bitstring ( expressed as an std::deque of bit_lattice ) into a string of characters...
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
std::deque< bit_lattice > inf(const std::deque< bit_lattice > &a, const std::deque< bit_lattice > &b, const unsigned int output_uid) const
Computes the inf between two bitstrings.
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
const int bl_debug_level
The debug level of methods of this class - it cannot be named debug_level because of ambiguity of Fro...
Definition: bit_lattice.hpp:94
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
std::deque< bit_lattice > create_u_bitstring(size_t lenght)
Creates a bitstring containing bits initialized at <U>
static bit_lattice bit_sup(const bit_lattice a, const bit_lattice b)
Definition: bit_lattice.cpp:77
CustomMap< unsigned int, std::deque< bit_lattice > > current
Map of the current bit-values of each variable.
Definition: bit_lattice.hpp:78
bool update_current(std::deque< bit_lattice > &res, const tree_nodeConstRef &tn)
Given a bitstring res, and the id of a tree node ouput_uid, this functions checks if it is necessary ...
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
#define index(x, y)
Definition: Keccak.c:74
kind
static unsigned long long size(const tree_managerConstRef tm, unsigned int index)
BitLatticeManipulator(const tree_managerConstRef TM, const int debug_level)
Constructor.
Definition: bit_lattice.cpp:65
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
static unsigned long long Size(const tree_nodeConstRef &t)
Classes specification of the tree_node data structures.
bit_lattice
Definition: bit_lattice.hpp:60
This file collects some utility functions and macros.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
const tree_managerConstRef TM
Definition: bit_lattice.hpp:71
This file collects some utility functions.
bool mix()
Mixes the content of current and best using the sup operation, storing the result in the best map...
std::deque< bit_lattice > string_to_bitstring(const std::string &s)
inverse of bitstring_to_string
Definition: APInt.hpp:53
std::deque< bit_lattice > sup(const std::deque< bit_lattice > &a, const std::deque< bit_lattice > &b, const unsigned int output_uid) const
Computes the sup between two bitstrings.
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
Definition: tree_node.hpp:689
int el
Definition: adpcm.c:105
Class specification of the tree_reindex support class.
CustomMap< unsigned int, std::deque< bit_lattice > > best
Map of the best bit-values of each variable.
Definition: bit_lattice.hpp:85
std::deque< bit_lattice > constructor_bitstring(const tree_nodeRef &ctor_tn, unsigned int ssa_node_id) const
auxiliary function used to build the bitstring lattice for read-only arrays
void clear()
Clean up the internal data structures.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
char str[25]
Definition: fixedptc.c:8
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
static std::deque< bit_lattice > sign_extend_bitstring(const std::deque< bit_lattice > &bitstring, bool bitstring_is_signed, size_t final_size)
Extends a bitstring.
this class is used to manage the command-line or XML options.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
bool IsSignedIntegerType(const tree_nodeConstRef &tn) const
Definition: bit_lattice.cpp:72
~BitLatticeManipulator()
Destructor.
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
Class specification of the manager of the tree structures extracted from the raw file.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
static void get_array_dim_and_bitsize(const tree_managerConstRef &TM, const unsigned int index, std::vector< unsigned long long > &dims, unsigned long long &elts_bitsize)
Return the dimension of the array.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:51 for PandA-2024.02 by doxygen 1.8.13