summaryrefslogtreecommitdiff
path: root/gcc/expr-accessor.c
blob: 6169f6d6b522057cbf4438c0162db1cd57f61b15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple-expr.h"
#include "predict.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "cgraph.h"
#include "diagnostic.h"
#include "fold-const.h"
#include "gimple-fold.h"
#include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h"
#include "tree-pretty-print.h"
#include "tree-inline.h"
#include "ipa-fnsummary.h"
#include "ipa-utils.h"
#include "tree-ssa-ccp.h"
#include "stringpool.h"
#include "attribs.h"
#include "tree-ssa-alias.h"
#include "tree-ssanames.h"
#include "gimple.h"
#include "cfg.h" // needed for gimple-iterator.h
#include "gimple-iterator.h"
#include "gimple-ssa.h"
#include <stdbool.h>


#include "types-inlines.h"
#include "type-stringifier.hpp"
#include "expr-accessor.hpp"
#include "expr-walker.hpp"
#include "type-accessor.hpp"

void
ExprAccessor::add_all_fields_in_struct(const_tree t)
{
  // Inefficient
  TypeAccessor typeAccessor(record_field_map);
  typeAccessor.walk(t);
}

void
ExprAccessor::_walk_pre(const_tree e)
{
  const_tree t = TREE_TYPE(e);
  add_all_fields_in_struct(t);
}

void
ExprAccessor::update(const_tree e, unsigned access)
{
  _access = access;
  walk(e);
}

void
ExprAccessor::_walk_COMPONENT_REF_pre(const_tree e)
{
  assert_is_type(e, COMPONENT_REF);
  const_tree op0 = TREE_OPERAND(e, 0);
  gcc_assert(op0);
  const_tree op0_t = TREE_TYPE(op0);
  gcc_assert(op0_t);
  // op0_t can either be a RECORD_TYPE or a UNION_TYPE
  const enum tree_code code = TREE_CODE(op0_t);
  const bool is_record = RECORD_TYPE == code;
  const bool is_union = UNION_TYPE == code;
  const bool valid = is_record != is_union;
  gcc_assert(valid);
 
  const_tree op1 = TREE_OPERAND(e, 1);
  assert_is_type(op1, FIELD_DECL);
  const bool record_already_in_map = record_field_map.find(op0_t) != record_field_map.end();
  field_access_map_t field_map; 
  field_map = record_already_in_map ? record_field_map[op0_t] : field_map;
  const bool field_already_in_map = field_map.find(op1) != field_map.end();
  unsigned prev_access = field_already_in_map ? field_map[op1] : Empty;

  prev_access |= _access;
  field_map[op1] = prev_access;
  add_all_fields_in_struct(op0_t);
  record_field_map[op0_t] = field_map;
}

void
ExprAccessor::print_accesses()
{
  for (auto i = record_field_map.cbegin(), e = record_field_map.cend(); i != e; ++i)
  {
    const_tree record = i->first;
    field_access_map_t field_map = i->second;
    for (auto j = field_map.cbegin(), f = field_map.cend(); j != f; ++j)
    {
      const_tree field = j->first;
      const std::string name_r = TypeStringifier::get_type_identifier(record);
      const std::string name_f = TypeStringifier::get_field_identifier(field);
      unsigned access = j->second;
      log("%s.%s = 0x%04x\n", name_r.c_str(), name_f.c_str(), access);
    }
  }
}