60 #include <boost/range/adaptors.hpp> 61 #include <unordered_set> 67 if(node->get_kind() == ssa_name_K || node->get_kind() == parm_decl_K)
72 else if(GetPointer<const cst_node>(node))
78 return std::deque<bit_lattice>();
83 std::deque<tree_nodeConstRef> working_list, return_list;
86 const auto stmt_kind = stmt->get_kind();
87 if(!working_list_idx.count(stmt->index) && (stmt_kind == gimple_assign_K || stmt_kind == gimple_phi_K ||
88 stmt_kind == gimple_return_K || stmt_kind == gimple_asm_K))
90 working_list.push_back(stmt);
91 working_list_idx.insert(stmt->index);
95 const auto stmt = working_list.front();
96 working_list.pop_front();
97 working_list_idx.erase(stmt->index);
102 for(
const auto&
phi : bb->CGetPhiList())
105 const auto gp = GetPointerS<const gimple_phi>(phi_node);
106 if(!gp->virtual_flag)
114 for(
const auto& stmt : bb->CGetStmtList())
117 if(stmt_node->get_kind() == gimple_assign_K)
119 const auto ga = GetPointerS<const gimple_assign>(stmt_node);
122 push_back(stmt_node);
125 else if(stmt_node->get_kind() == gimple_return_K)
127 return_list.push_back(stmt_node);
132 const auto is_root_function =
AppM->CGetCallGraphManager()->GetRootFunctions().count(
function_id);
133 while(!working_list.empty())
135 const auto stmt_node = pop_front();
136 const auto stmt_kind = stmt_node->get_kind();
138 if(stmt_kind == gimple_assign_K)
140 const auto ga = GetPointerS<const gimple_assign>(stmt_node);
142 const auto ssa = GetPointer<const ssa_name>(
GET_CONST_NODE(ga->op0));
152 bool hasRequiredValues =
true;
153 std::vector<std::tuple<unsigned int, unsigned int>> vars_read;
156 for(
const auto& var_pair : vars_read)
158 const auto use_node_id = std::get<0>(var_pair);
163 const auto use_node =
TM->CGetTreeNode(use_node_id);
168 const auto ssa_use = GetPointer<const ssa_name>(use_node);
170 if(ssa_use && !
current.count(use_node_id))
172 const auto def_stmt = ssa_use->CGetDefStmt();
176 "Function parameter bitvalue must be defined before");
184 "---Input " + ssa_use->ToString() +
" definition has not been analyzed yet");
188 hasRequiredValues =
false;
193 if(hasRequiredValues)
196 current.insert(std::make_pair(output_nid,
best.at(output_nid)));
201 for(
const auto& next_node : ssa->CGetUseStmts())
210 "---Inputs not fully analyzed by the forward Bit Value Analysis. Operation " +
211 GET_NODE(ga->op0)->ToString() +
" postponed");
212 push_back(stmt_node);
216 else if(stmt_kind == gimple_phi_K)
218 const auto gp = GetPointerS<const gimple_phi>(stmt_node);
222 const auto ssa = GetPointerS<const ssa_name>(
GET_CONST_NODE(gp->res));
234 bool atLeastOne =
false;
235 bool allInputs =
true;
239 for(
const auto& def_edge : gp->CGetDefEdgesList())
242 if(def_id == output_nid)
245 "---Skipping " +
STR(def_edge.first) +
" coming from BB" +
STR(def_edge.second) +
246 " because of ssa cycle");
252 const auto def_ssa = GetPointer<const ssa_name>(def_node);
255 const auto def_stmt = def_ssa->CGetDefStmt();
259 "Function parameter bitvalue must be defined before");
267 "---Skipping " +
STR(def_node) +
268 " no current has been yet computed for this ssa var");
279 current.insert(std::make_pair(def_id,
best.at(def_id)));
296 const auto ins =
current.insert(std::make_pair(output_nid, res));
297 auto current_updated = ins.second;
306 for(
const auto& next_node : ssa->CGetUseStmts())
308 push_back(
GET_NODE(next_node.first));
314 push_back(stmt_node);
317 else if(stmt_kind == gimple_return_K)
319 if(!is_root_function)
321 const auto gr = GetPointerS<const gimple_return>(stmt_node);
322 THROW_ASSERT(gr->op,
"Empty return should not be a use of any ssa");
329 output_current = output_current.size() ?
inf(res, output_current,
function_id) : res;
334 else if(stmt_kind == gimple_asm_K)
336 const auto ga = GetPointerS<const gimple_asm>(stmt_node);
340 THROW_ASSERT(tl->valu,
"only the first output and so only single output gimple_asm are supported");
341 const auto ssa = GetPointer<const ssa_name>(
GET_CONST_NODE(tl->valu));
367 std::deque<bit_lattice> res;
368 const auto& lhs = ga->
op0;
369 const auto& rhs = ga->
op1;
383 const auto ae = GetPointerS<const addr_expr>(
GET_CONST_NODE(rhs));
384 const auto address_size =
AppM->get_address_bitsize();
385 const auto is_pretty_print_used =
388 const auto lt0 =
lsb_to_zero(ae, is_pretty_print_used);
390 "---address_size: " +
STR(address_size) +
" lt0: " +
STR(lt0));
391 if(lt0 && address_size > lt0)
406 case truth_not_expr_K:
407 case view_convert_expr_K:
426 if(rhs_kind == abs_expr_K)
429 const auto sign_bit = op_bitstring.front();
440 for(
const auto bit : boost::adaptors::reverse(op_bitstring))
443 res.push_front(borrow_and_bit_pair.back());
444 borrow = borrow_and_bit_pair.front();
446 if(res.size() < op_size)
455 std::deque<bit_lattice> negated_bitstring;
457 for(
const auto& bit : boost::adaptors::reverse(op_bitstring))
460 negated_bitstring.push_front(borrow_and_bit_pair.back());
461 borrow = borrow_and_bit_pair.front();
463 if(negated_bitstring.size() < op_size)
465 negated_bitstring.push_front(
468 res =
inf(op_bitstring, negated_bitstring, lhs);
477 THROW_ASSERT(lhs_signed && op_signed,
"lhs and rhs of an abs_expr must be signed");
479 else if(rhs_kind == bit_not_expr_K)
481 if(op_bitstring.size() == 1 && op_bitstring.at(0) ==
bit_lattice::X &&
486 if(op_bitstring.size() < lhs_size)
491 auto op_it = op_bitstring.rbegin();
492 for(
unsigned bit_index = 0; bit_index < lhs_size && op_it != op_bitstring.rend(); ++op_it, ++bit_index)
497 else if(rhs_kind == convert_expr_K || rhs_kind == nop_expr_K || rhs_kind == view_convert_expr_K)
501 if((lhs_signed != op_signed && !do_not_extend) && res.size() < lhs_size)
505 while(res.size() > lhs_size)
510 else if(rhs_kind == negate_expr_K)
513 if(!lhs_signed && lhs_size > op_bitstring.size())
517 auto op_it = op_bitstring.rbegin();
518 for(
unsigned bit_index = 0; bit_index < lhs_size && op_it != op_bitstring.rend(); ++op_it, ++bit_index)
523 if(lhs_signed && res.size() < lhs_size)
528 else if(rhs_kind == truth_not_expr_K)
532 for(
auto current_bit : op_bitstring)
557 case exact_div_expr_K:
570 case pointer_plus_expr_K:
573 case trunc_div_expr_K:
574 case trunc_mod_expr_K:
575 case truth_and_expr_K:
576 case truth_andif_expr_K:
577 case truth_or_expr_K:
578 case truth_orif_expr_K:
579 case truth_xor_expr_K:
580 case widen_mult_expr_K:
581 case extract_bit_expr_K:
618 if(rhs_kind == bit_and_expr_K)
620 if(lhs_size > op0_bitstring.size())
624 if(lhs_size > op1_bitstring.size())
629 auto op0_it = op0_bitstring.rbegin();
630 auto op1_it = op1_bitstring.rbegin();
631 for(
auto bit_index = 0u;
632 bit_index < lhs_size && op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
633 ++op0_it, ++op1_it, ++bit_index)
638 else if(rhs_kind == bit_ior_expr_K)
640 if(op0_bitstring.size() == 1 && op0_bitstring.at(0) ==
bit_lattice::X &&
645 if(op1_bitstring.size() == 1 && op1_bitstring.at(0) ==
bit_lattice::X &&
650 if(lhs_size > op1_bitstring.size())
654 if(lhs_size > op0_bitstring.size())
659 auto op0_it = op0_bitstring.rbegin();
660 auto op1_it = op1_bitstring.rbegin();
661 for(
auto bit_index = 0u;
662 bit_index < lhs_size && op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
663 ++op0_it, ++op1_it, ++bit_index)
668 else if(rhs_kind == bit_xor_expr_K)
670 if(op0_bitstring.size() == 1 && op0_bitstring.at(0) ==
bit_lattice::X &&
675 if(op1_bitstring.size() == 1 && op1_bitstring.at(0) ==
bit_lattice::X &&
681 if(lhs_size > op1_bitstring.size())
685 if(lhs_size > op0_bitstring.size())
690 auto op0_it = op0_bitstring.rbegin();
691 auto op1_it = op1_bitstring.rbegin();
692 for(
auto bit_index = 0u;
693 bit_index < lhs_size && op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
694 ++op0_it, ++op1_it, ++bit_index)
699 else if(rhs_kind == eq_expr_K)
701 if(op0_bitstring.size() > op1_bitstring.size())
705 if(op1_bitstring.size() > op0_bitstring.size())
710 auto op0_bitstring_it = op0_bitstring.begin();
711 auto op1_bitstring_it = op1_bitstring.begin();
712 auto computed_result =
false;
713 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
714 ++op0_bitstring_it, ++op1_bitstring_it)
720 computed_result =
true;
728 computed_result =
true;
739 else if(rhs_kind == exact_div_expr_K || rhs_kind == trunc_div_expr_K)
749 while(res.size() > lhs_size)
754 else if(rhs_kind == ge_expr_K)
756 if(op0_bitstring.size() > op1_bitstring.size())
760 if(op1_bitstring.size() > op0_bitstring.size())
765 const auto is_signed_var = op0_signed || op1_signed;
766 auto op0_bitstring_it = op0_bitstring.begin();
767 auto op1_bitstring_it = op1_bitstring.begin();
768 auto computed_result =
false;
769 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
770 ++op0_bitstring_it, ++op1_bitstring_it)
776 computed_result =
true;
781 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
791 computed_result =
true;
796 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
806 computed_result =
true;
817 else if(rhs_kind == gt_expr_K)
819 if(op0_bitstring.size() > op1_bitstring.size())
823 if(op1_bitstring.size() > op0_bitstring.size())
828 const auto is_signed_var = op0_signed || op1_signed;
829 auto op0_bitstring_it = op0_bitstring.begin();
830 auto op1_bitstring_it = op1_bitstring.begin();
831 auto computed_result =
false;
832 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
833 ++op0_bitstring_it, ++op1_bitstring_it)
839 computed_result =
true;
844 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
854 computed_result =
true;
859 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
869 computed_result =
true;
880 else if(rhs_kind == le_expr_K)
882 if(op0_bitstring.size() > op1_bitstring.size())
886 if(op1_bitstring.size() > op0_bitstring.size())
891 const auto is_signed_var = op0_signed || op1_signed;
892 auto op0_bitstring_it = op0_bitstring.begin();
893 auto op1_bitstring_it = op1_bitstring.begin();
894 auto computed_result =
false;
895 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
896 ++op0_bitstring_it, ++op1_bitstring_it)
902 computed_result =
true;
907 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
917 computed_result =
true;
922 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
932 computed_result =
true;
943 else if(rhs_kind == lrotate_expr_K)
953 if(lhs_size > op0_bitstring.size())
962 res.push_back(cur_bit);
970 else if(rhs_kind == lshift_expr_K)
974 const auto bsize_elev2 = 1ULL << op1_bitstring.size();
975 if(lhs_size < bsize_elev2 || lhs_size < bsize_elev2 + op0_bitstring.size())
981 res =
create_u_bitstring(static_cast<unsigned int>(op0_bitstring.size() + bsize_elev2));
994 if(lhs_size <= static_cast<size_t>(cst_val))
1000 res = op0_bitstring;
1001 while(res.size() > op0_bitsize)
1008 if(res.size() > lhs_size)
1020 else if(rhs_kind == lt_expr_K)
1022 if(op0_bitstring.size() > op1_bitstring.size())
1026 if(op1_bitstring.size() > op0_bitstring.size())
1031 const auto is_signed_var = op0_signed || op1_signed;
1032 auto op0_bitstring_it = op0_bitstring.begin();
1033 auto op1_bitstring_it = op1_bitstring.begin();
1034 auto computed_result =
false;
1035 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
1036 ++op0_bitstring_it, ++op1_bitstring_it)
1042 computed_result =
true;
1047 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
1057 computed_result =
true;
1062 if(op0_bitstring_it == op0_bitstring.begin() && is_signed_var)
1072 computed_result =
true;
1076 if(!computed_result)
1083 else if(rhs_kind == max_expr_K || rhs_kind == min_expr_K)
1085 if(op0_bitstring.size() > op1_bitstring.size())
1089 if(op1_bitstring.size() > op0_bitstring.size())
1095 res =
inf(op0_bitstring, op1_bitstring,
operation->op0);
1097 else if(rhs_kind == minus_expr_K)
1099 const auto arg_size_max =
std::max(op0_bitstring.size(), op1_bitstring.size());
1100 if(arg_size_max > op1_bitstring.size())
1104 if(arg_size_max > op0_bitstring.size())
1109 auto op0_it = op0_bitstring.rbegin();
1110 auto op1_it = op1_bitstring.rbegin();
1112 for(
auto bit_index = 0u;
1113 bit_index < lhs_size && op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
1114 ++op0_it, ++op1_it, ++bit_index)
1116 res.push_front(
minus_expr_map.at(*op0_it).at(*op1_it).at(borrow).back());
1117 borrow =
minus_expr_map.at(*op0_it).at(*op1_it).at(borrow).front();
1119 if(lhs_signed && res.size() < lhs_size)
1121 res.push_front(
minus_expr_map.at(op0_bitstring.front()).at(op1_bitstring.front()).at(borrow).back());
1123 else if(!lhs_signed)
1125 while(res.size() < lhs_size)
1127 res.push_front(borrow);
1131 else if(rhs_kind == mult_expr_K || rhs_kind == widen_mult_expr_K)
1188 const auto lenght_op0 = op0_bitstring.size();
1189 const auto lenght_op1 = op1_bitstring.size();
1190 const auto res_bitsize =
std::min(lenght_op0 + lenght_op1, static_cast<size_t>(lhs_size));
1191 if(res_bitsize > op0_bitstring.size())
1195 if(res_bitsize > op1_bitstring.size())
1199 while(op0_bitstring.size() > res_bitsize)
1201 op0_bitstring.pop_front();
1203 while(op1_bitstring.size() > res_bitsize)
1205 op1_bitstring.pop_front();
1208 while(res.size() < res_bitsize)
1212 auto op1_it = op1_bitstring.crbegin();
1213 for(
auto pos = 0u; op1_it != op1_bitstring.crend() && pos < res_bitsize; ++op1_it, ++pos)
1215 std::deque<bit_lattice> temp_op1;
1216 while(temp_op1.size() < pos)
1220 auto op0_it = op0_bitstring.crbegin();
1221 for(
size_t idx = 0; (idx + pos) < res_bitsize; ++idx, ++op0_it)
1226 std::deque<bit_lattice> temp_res;
1227 auto temp_op1_it = temp_op1.crbegin();
1228 const auto temp_op1_end = temp_op1.crend();
1229 auto res_it = res.crbegin();
1230 const auto res_end = res.crend();
1231 for(
auto bit_index = 0u; bit_index < res_bitsize && temp_op1_it != temp_op1_end && res_it != res_end;
1232 temp_op1_it++, res_it++, bit_index++)
1234 temp_res.push_front(
plus_expr_map.at(*temp_op1_it).at(*res_it).at(carry1).back());
1235 carry1 =
plus_expr_map.at(*temp_op1_it).at(*res_it).at(carry1).front();
1240 else if(rhs_kind == ne_expr_K)
1242 if(op0_bitstring.size() > op1_bitstring.size())
1246 if(op1_bitstring.size() > op0_bitstring.size())
1251 auto op0_bitstring_it = op0_bitstring.begin();
1252 auto op1_bitstring_it = op1_bitstring.begin();
1253 auto computed_result =
false;
1254 for(; op0_bitstring_it != op0_bitstring.end() && op1_bitstring_it != op1_bitstring.end();
1255 ++op0_bitstring_it, ++op1_bitstring_it)
1261 computed_result =
true;
1269 computed_result =
true;
1273 if(!computed_result)
1280 else if(rhs_kind == plus_expr_K || rhs_kind == pointer_plus_expr_K)
1282 if(op0_bitstring.size() > op1_bitstring.size())
1286 if(op1_bitstring.size() > op0_bitstring.size())
1291 auto op0_it = op0_bitstring.rbegin();
1292 auto op1_it = op1_bitstring.rbegin();
1294 for(
auto bit_index = 0u;
1295 bit_index < lhs_size && op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
1296 ++op0_it, ++op1_it, ++bit_index)
1300 res.push_front(
plus_expr_map.at(*op0_it).at(*op1_it).at(carry1).back());
1301 carry1 =
plus_expr_map.at(*op0_it).at(*op1_it).at(carry1).front();
1304 if(lhs_signed && res.size() < lhs_size)
1306 res.push_front(
plus_expr_map.at(op0_bitstring.front()).at(op1_bitstring.front()).at(carry1).back());
1308 else if(!lhs_signed)
1310 while(res.size() < lhs_size)
1317 else if(rhs_kind == rrotate_expr_K)
1327 if(lhs_size > op0_bitstring.size())
1331 res = op0_bitstring;
1334 const auto cur_bit = res.back();
1336 res.push_front(cur_bit);
1344 else if(rhs_kind == rshift_expr_K)
1356 "---forward_transfer, negative right shift is undefined behavior");
1361 if(op0_bitstring.size() <=
static_cast<size_t>(cst_val))
1365 res.push_front(op0_bitstring.front());
1374 const auto new_lenght = op0_bitstring.size() -
static_cast<size_t>(cst_val);
1375 auto op0_it = op0_bitstring.begin();
1376 while(res.size() < new_lenght)
1378 res.push_back(*op0_it);
1388 else if(rhs_kind == trunc_mod_expr_K)
1393 1 + static_cast<unsigned int>(
std::min(op0_bitstring.size(), op1_bitstring.size())));
1400 while(res.size() > lhs_size)
1405 else if(rhs_kind == truth_and_expr_K || rhs_kind == truth_andif_expr_K || rhs_kind == truth_or_expr_K ||
1406 rhs_kind == truth_orif_expr_K || rhs_kind == truth_xor_expr_K)
1408 if(op0_bitstring.size() > op1_bitstring.size())
1412 if(op1_bitstring.size() > op0_bitstring.size())
1418 for(
const auto& current_bit : op0_bitstring)
1431 for(
const auto& current_bit : op1_bitstring)
1443 if(rhs_kind == truth_and_expr_K || rhs_kind == truth_andif_expr_K)
1447 else if(rhs_kind == truth_or_expr_K || rhs_kind == truth_orif_expr_K)
1451 else if(rhs_kind == truth_xor_expr_K)
1460 else if(rhs_kind == extract_bit_expr_K)
1466 if(op0_bitstring.size() <=
static_cast<size_t>(cst_val))
1470 res.push_front(op0_bitstring.front());
1479 const auto new_lenght = op0_bitstring.size() -
static_cast<size_t>(cst_val);
1480 auto op0_it = op0_bitstring.begin();
1481 while(res.size() < new_lenght)
1483 res.push_back(*op0_it);
1486 while(res.size() > 1)
1499 case bit_ior_concat_expr_K:
1501 case ternary_plus_expr_K:
1502 case ternary_pm_expr_K:
1503 case ternary_mp_expr_K:
1504 case ternary_mm_expr_K:
1557 if(rhs_kind == bit_ior_concat_expr_K)
1561 if(op0_bitstring.size() > op1_bitstring.size())
1565 if(op1_bitstring.size() > op0_bitstring.size())
1570 auto op0_it = op0_bitstring.rbegin();
1571 auto op1_it = op1_bitstring.rbegin();
1572 for(
integer_cst_t index = 0; op0_it != op0_bitstring.rend() && op1_it != op1_bitstring.rend();
1573 ++op0_it, ++op1_it, ++
index)
1577 res.push_front(*op1_it);
1581 res.push_front(*op0_it);
1585 else if(rhs_kind == cond_expr_K)
1588 for(
const auto& current_bit : op0_bitstring)
1604 res = op2_bitstring;
1609 res = op1_bitstring;
1623 const auto inf_size =
std::max(op1_bitstring.size(), op2_bitstring.size());
1624 if(op1_bitstring.size() < inf_size)
1628 if(op2_bitstring.size() < inf_size)
1632 res =
inf(op1_bitstring, op2_bitstring, lhs);
1635 else if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_pm_expr_K || rhs_kind == ternary_mp_expr_K ||
1636 rhs_kind == ternary_mm_expr_K)
1638 const auto arg_size_max =
std::max({op0_bitstring.size(), op1_bitstring.size(), op2_bitstring.size()});
1639 if(op0_bitstring.size() < arg_size_max)
1643 if(op1_bitstring.size() < arg_size_max)
1647 if(op2_bitstring.size() < arg_size_max)
1652 auto op0_it = op0_bitstring.crbegin();
1653 auto op1_it = op1_bitstring.crbegin();
1654 const auto op0_end = op0_bitstring.crend();
1655 const auto op1_end = op1_bitstring.crend();
1657 std::deque<bit_lattice> res_int;
1658 for(
auto bit_index = 0u; bit_index < lhs_size && op0_it != op0_end && op1_it != op1_end;
1659 op0_it++, op1_it++, bit_index++)
1661 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_pm_expr_K)
1663 res_int.push_front(
plus_expr_map.at(*op0_it).at(*op1_it).at(carry1).back());
1664 carry1 =
plus_expr_map.at(*op0_it).at(*op1_it).at(carry1).front();
1668 res_int.push_front(
minus_expr_map.at(*op0_it).at(*op1_it).at(carry1).back());
1669 carry1 =
minus_expr_map.at(*op0_it).at(*op1_it).at(carry1).front();
1673 if(lhs_signed && res_int.size() < lhs_size)
1675 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_pm_expr_K)
1678 plus_expr_map.at(op0_bitstring.front()).at(op1_bitstring.front()).at(carry1).back());
1683 minus_expr_map.at(op0_bitstring.front()).at(op1_bitstring.front()).at(carry1).back());
1686 else if(!lhs_signed)
1688 while(res_int.size() < lhs_size)
1690 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_pm_expr_K)
1704 if(res_int.size() > op2_bitstring.size())
1709 auto op2_it = op2_bitstring.crbegin();
1710 auto res_int_it = res_int.crbegin();
1711 const auto op2_end = op2_bitstring.crend();
1712 const auto res_int_end = res_int.crend();
1714 for(
auto bit_index = 0u; bit_index < lhs_size && op2_it != op2_end && res_int_it != res_int_end;
1715 op2_it++, res_int_it++, bit_index++)
1717 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_mp_expr_K)
1719 res.push_front(
plus_expr_map.at(*res_int_it).at(*op2_it).at(carry1).back());
1720 carry1 =
plus_expr_map.at(*res_int_it).at(*op2_it).at(carry1).front();
1724 res.push_front(
minus_expr_map.at(*res_int_it).at(*op2_it).at(carry1).back());
1725 carry1 =
minus_expr_map.at(*res_int_it).at(*op2_it).at(carry1).front();
1729 if(lhs_signed && res.size() < lhs_size)
1731 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_mp_expr_K)
1733 res.push_front(
plus_expr_map.at(res_int.front()).at(op2_bitstring.front()).at(carry1).back());
1737 res.push_front(
minus_expr_map.at(res_int.front()).at(op2_bitstring.front()).at(carry1).back());
1740 else if(!lhs_signed)
1742 while(res.size() < lhs_size)
1744 if(rhs_kind == ternary_plus_expr_K || rhs_kind == ternary_mp_expr_K)
1757 else if(rhs_kind == fshl_expr_K)
1767 static_cast<unsigned int>(lhs_size));
1769 if(lhs_size > op0_bitstring.size())
1773 if(lhs_size > op1_bitstring.size())
1777 res.insert(res.end(), op0_bitstring.begin() +
offset, op0_bitstring.end());
1778 res.insert(res.end(), op1_bitstring.begin(), op1_bitstring.begin() +
offset);
1786 else if(rhs_kind == fshr_expr_K)
1796 static_cast<unsigned int>(lhs_size));
1798 if(lhs_size > op0_bitstring.size())
1802 if(lhs_size > op1_bitstring.size())
1806 res.insert(res.end(), op0_bitstring.begin() +
offset, op0_bitstring.end());
1807 res.insert(res.end(), op1_bitstring.begin(), op1_bitstring.begin() +
offset);
1823 case fix_ceil_expr_K:
1824 case fix_floor_expr_K:
1825 case fix_round_expr_K:
1826 case fix_trunc_expr_K:
1827 case imagpart_expr_K:
1828 case realpart_expr_K:
1829 case alignof_expr_K:
1833 case ordered_expr_K:
1834 case sat_minus_expr_K:
1835 case sat_plus_expr_K:
1841 case unordered_expr_K:
1842 case extractvalue_expr_K:
1843 case extractelement_expr_K:
1845 case bit_field_ref_K:
1846 case component_ref_K:
1847 case insertvalue_expr_K:
1848 case insertelement_expr_K:
1855 case aggr_init_expr_K:
1861 const auto called_id = call_it->second;
1862 const auto tn =
TM->CGetTreeNode(called_id);
1863 THROW_ASSERT(tn->get_kind() == function_decl_K,
"node " +
STR(called_id) +
" is not a function_decl");
1864 const auto* fd = GetPointerS<const function_decl>(tn);
1865 if(fd->bit_values.empty())
1886 case cleanup_point_expr_K:
1890 case indirect_ref_K:
1891 case misaligned_indirect_ref_K:
1893 case non_lvalue_expr_K:
1894 case reference_expr_K:
1895 case reinterpret_cast_expr_K:
1897 case static_cast_expr_K:
1902 case reduc_max_expr_K:
1903 case reduc_min_expr_K:
1904 case reduc_plus_expr_K:
1905 case vec_unpack_hi_expr_K:
1906 case vec_unpack_lo_expr_K:
1907 case vec_unpack_float_hi_expr_K:
1908 case vec_unpack_float_lo_expr_K:
1912 case ceil_div_expr_K:
1913 case ceil_mod_expr_K:
1914 case complex_expr_K:
1915 case compound_expr_K:
1916 case eh_filter_expr_K:
1918 case floor_div_expr_K:
1919 case floor_mod_expr_K:
1920 case goto_subroutine_K:
1924 case mult_highpart_expr_K:
1925 case postdecrement_expr_K:
1926 case postincrement_expr_K:
1927 case predecrement_expr_K:
1928 case preincrement_expr_K:
1932 case round_div_expr_K:
1933 case round_mod_expr_K:
1935 case try_catch_expr_K:
1937 case widen_sum_expr_K:
1938 case with_size_expr_K:
1939 case vec_lshift_expr_K:
1940 case vec_rshift_expr_K:
1941 case widen_mult_hi_expr_K:
1942 case widen_mult_lo_expr_K:
1943 case vec_pack_trunc_expr_K:
1944 case vec_pack_sat_expr_K:
1945 case vec_pack_fix_trunc_expr_K:
1946 case vec_extracteven_expr_K:
1947 case vec_extractodd_expr_K:
1948 case vec_interleavehigh_expr_K:
1949 case vec_interleavelow_expr_K:
1952 case with_cleanup_expr_K:
1953 case obj_type_ref_K:
1955 case vec_cond_expr_K:
1956 case vec_perm_expr_K:
1957 case dot_prod_expr_K:
1959 case array_range_ref_K:
1974 case case_label_expr_K:
1977 case identifier_node_K:
1978 case statement_list_K:
1980 case target_mem_ref_K:
1981 case target_mem_ref461_K:
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#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.
static const std::map< bit_lattice, std::map< bit_lattice, std::map< bit_lattice, std::deque< bit_lattice > > > > plus_expr_map
Map storing the implementation of the forward_transfer's plus_expr.
File containing functions and utilities to support the printing of debug messagges.
std::string ToString() const
Print this node as string in gimple format.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
std::deque< bit_lattice > create_x_bitstring(size_t lenght)
Create a bitstring containing bits initialized at <X>
tree_nodeRef op1
The second operand of the binary expression.
Definition of the class representing a generic C application.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
Full implementation of Bit Value analysis as described in BitValue Inference: Detecting and Exploitin...
tree_nodeRef op0
The first operand of the binary expression.
bool IsHandledByBitvalue(const tree_nodeConstRef &tn) const
Returns true if the type identified by type_id is handled by bitvalue analysis.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Data structure describing a basic block at tree level.
static void get_required_values(std::vector< std::tuple< unsigned int, unsigned int >> &required, const tree_nodeRef &tn)
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
static const std::map< bit_lattice, std::map< bit_lattice, std::map< bit_lattice, std::deque< bit_lattice > > > > minus_expr_map
Map storing the implementation of the forward_transfer's minus_expr.
void forward()
Applies the forward algorithm, as described in the paper, analyzing each assignment statement followi...
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
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
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.
This class specifies the characteristic of a particular operation working on a given functional unit...
This struct specifies the gimple_assign node (GCC 4.3 tree node).
std::deque< bit_lattice > create_u_bitstring(size_t lenght)
Creates a bitstring containing bits initialized at <U>
unsigned int lsb_to_zero(const addr_expr *ae, bool safe) const
CustomMap< unsigned int, std::deque< bit_lattice > > current
Map of the current bit-values of each variable.
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_and_expr_map
Map storing the implementation of the forward_transfer's bit_and_expr_map.
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...
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_ior_expr_map
Map storing the implementation of the forward_transfer's bit_ior_expr_map.
std::deque< bit_lattice > get_current(const tree_nodeConstRef &tn) const
Given an operand, returns its current bitvalue.
unsigned offset[NUM_VERTICES+1]
#define GET_CONST_NODE(t)
static unsigned long long Size(const tree_nodeConstRef &t)
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
const tree_managerConstRef TM
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
This file collects some utility functions.
std::deque< bit_lattice > string_to_bitstring(const std::string &s)
inverse of bitstring_to_string
CustomUnorderedMapUnstable< unsigned int, unsigned int > direct_call_id_to_called_id
Maps the id of a gimple statement to the id of the function called in that statement.
const unsigned int function_id
The index of the function to be analyzed.
std::deque< bit_lattice > forward_transfer(const gimple_assign *ga) const
Takes a gimple assignment, analyzes the operation performed from the rhs and its input bitstring...
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
std::vector< blocRef > bb_topological
Topologically ordered basic blocks.
Class specification of the basic_block structure.
CustomMap< unsigned int, std::deque< bit_lattice > > best
Map of the best bit-values of each variable.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
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.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
bool IsSignedIntegerType(const tree_nodeConstRef &tn) const
static const std::map< bit_lattice, std::map< bit_lattice, bit_lattice > > bit_xor_expr_map
Map storing the implementation of the forward_transfer's bit_xor_expr_map.
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...