Predator  [unstable] git snapshot
clutil.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Kamil Dudka <kdudka@redhat.com>
3  *
4  * This file is part of predator.
5  *
6  * predator is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * any later version.
10  *
11  * predator is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with predator. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef H_GUARD_CLUTIL_H
21 #define H_GUARD_CLUTIL_H
22 
23 /**
24  * @file clutil.hh
25  * some generic utilities working on top of code_listener/CodeStorage
26  */
27 
28 #include "code_listener.h"
29 
30 #include <cassert>
31 #include <set>
32 #include <stack>
33 #include <string>
34 #include <vector>
35 
36 namespace CodeStorage {
37  struct Storage;
38 }
39 
40 /// compare given two pieces of static type-info semantically
41 bool operator==(const struct cl_type &cltA, const struct cl_type &cltB);
42 
43 /// compare given two pieces of static type-info semantically
44 inline bool operator!=(const struct cl_type &cltA, const struct cl_type &cltB)
45 {
46  return !(cltA == cltB);
47 }
48 
49 /// return type of the @b target object that the pointer type can point to
50 const struct cl_type* targetTypeOfPtr(const struct cl_type *clt);
51 
52 /// return type of the @b target object that the array type can point to
53 const struct cl_type* targetTypeOfArray(const struct cl_type *clt);
54 
55 inline bool isComposite(const struct cl_type *clt, bool includingArray = true)
56 {
57  if (!clt)
58  return false;
59 
60  switch (clt->code) {
61  case CL_TYPE_ARRAY:
62  return includingArray;
63 
64  case CL_TYPE_STRUCT:
65  case CL_TYPE_UNION:
66  return true;
67 
68  default:
69  return false;
70  }
71 }
72 
73 inline bool isDataPtr(const struct cl_type *clt)
74 {
75  if (!clt || clt->code != CL_TYPE_PTR)
76  return false;
77 
78  clt = targetTypeOfPtr(clt);
79  return (CL_TYPE_FNC != clt->code);
80 }
81 
82 inline bool isCodePtr(const struct cl_type *clt)
83 {
84  if (!clt || clt->code != CL_TYPE_PTR)
85  return false;
86 
87  clt = targetTypeOfPtr(clt);
88  return (CL_TYPE_FNC == clt->code);
89 }
90 
91 /// return true if the given operand is a local variable
92 inline bool isLcVar(const cl_operand &op)
93 {
94  if (CL_OPERAND_VAR != op.code)
95  // not a variable
96  return false;
97 
98  const enum cl_scope_e code = op.scope;
99  switch (code) {
100  case CL_SCOPE_GLOBAL:
101  case CL_SCOPE_STATIC:
102  // global variable
103  return false;
104 
105  default:
106  return true;
107  }
108 }
109 
110 /**
111  * return true if there is any CL_ACCESSOR_REF in the given chain of accessors
112  * @note CL_ACCESSOR_REF accessors can't be chained with each other, as it makes
113  * semantically no sense
114  */
115 bool seekRefAccessor(const struct cl_accessor *ac);
116 
117 /// return integral value from the integral constant given as operand
118 int intCstFromOperand(const struct cl_operand *op);
119 
120 /// return unique ID of the variable/register given as operand
121 int varIdFromOperand(const struct cl_operand *op, const char **pName = 0);
122 
123 /// get name of an @b external function given as CL_OPERAND_CST, true on success
124 bool fncNameFromCst(const char **pName, const struct cl_operand *op);
125 
126 /// get uid of a function from the given operand if available, true on success
127 bool fncUidFromOperand(int *pUid, const struct cl_operand *op);
128 
129 typedef std::vector<int /* nth */> TFieldIdxChain;
130 
131 int offsetByIdxChain(const struct cl_type *, const TFieldIdxChain &);
132 
133 // TODO: do not define the helper type at gl scope
134 struct CltStackItem {
135  const struct cl_type *clt;
137 };
138 
139 // take the given visitor through a composite type (or whatever you pass in)
140 template <class TVisitor>
141 bool /* complete */ traverseTypeIc(const struct cl_type *clt, TVisitor &visitor,
142  bool digOnlyComposite = false)
143 {
144  assert(clt);
145 
146  // we use std::set to avoid an infinite loop
147  std::set<int /* uid */> done;
148  done.insert(clt->uid);
149 
150  // initialize DFS
151  typedef CltStackItem TItem;
152  TItem si;
153  si.clt = clt;
154  si.ic.push_back(0);
155 
156  // DFS loop
157  std::stack<TItem> todo;
158  todo.push(si);
159  while (!todo.empty()) {
160  TItem &si = todo.top();
161  assert(!si.ic.empty());
162 
163  typename TFieldIdxChain::reference nth = si.ic.back();
164  if (nth == si.clt->item_cnt) {
165  // done at this level
166  if (isComposite(si.clt))
167  done.erase(si.clt->uid);
168 
169  todo.pop();
170  continue;
171  }
172 
173  if (digOnlyComposite && !isComposite(si.clt)) {
174  // caller is interested only in composite types, skip this
175  ++nth;
176  continue;
177  }
178 
179  const struct cl_type_item *item = si.clt->items + nth;
180  const TFieldIdxChain &icConst = si.ic;
181  if (!/* continue */visitor(icConst, item))
182  return false;
183 
184  if (!item->type->item_cnt) {
185  // non-composite type item
186  ++nth;
187  continue;
188  }
189 
190  const int uid = item->type->uid;
191  if (done.end() == done.find(uid)) {
192  done.insert(uid);
193 
194  // nest into sub-type
195  TItem next;
196  next.clt = item->type;
197  next.ic = si.ic;
198  next.ic.push_back(0);
199  todo.push(next);
200  }
201 
202  // move to the next at this level
203  ++nth;
204  }
205 
206  // the traversal is done, without any interruption by visitor
207  return true;
208 }
209 
210 std::string varToString(
211  const CodeStorage::Storage &stor,
212  const int uid,
213  const struct cl_loc **pLoc = 0);
214 
215 #endif /* H_GUARD_CLUTIL_H */