]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/expop.h
Introduce var_entry_value_operation
[thirdparty/binutils-gdb.git] / gdb / expop.h
1 /* Definitions for expressions in GDB
2
3 Copyright (C) 2020 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #ifndef EXPOP_H
21 #define EXPOP_H
22
23 #include "block.h"
24 #include "c-lang.h"
25 #include "cp-abi.h"
26 #include "expression.h"
27 #include "objfiles.h"
28 #include "gdbsupport/traits.h"
29 #include "gdbsupport/enum-flags.h"
30
31 struct agent_expr;
32 struct axs_value;
33
34 extern void gen_expr_binop (struct expression *exp,
35 enum exp_opcode op,
36 expr::operation *lhs, expr::operation *rhs,
37 struct agent_expr *ax, struct axs_value *value);
38 extern void gen_expr_structop (struct expression *exp,
39 enum exp_opcode op,
40 expr::operation *lhs,
41 const char *name,
42 struct agent_expr *ax, struct axs_value *value);
43
44 extern struct value *eval_op_scope (struct type *expect_type,
45 struct expression *exp,
46 enum noside noside,
47 struct type *type, const char *string);
48 extern struct value *eval_op_var_msym_value (struct type *expect_type,
49 struct expression *exp,
50 enum noside noside,
51 bool outermost_p,
52 minimal_symbol *msymbol,
53 struct objfile *objfile);
54 extern struct value *eval_op_var_entry_value (struct type *expect_type,
55 struct expression *exp,
56 enum noside noside, symbol *sym);
57
58 namespace expr
59 {
60
61 /* The check_objfile overloads are used to check whether a particular
62 component of some operation references an objfile. The passed-in
63 objfile will never be a debug objfile. */
64
65 /* See if EXP_OBJFILE matches OBJFILE. */
66 static inline bool
67 check_objfile (struct objfile *exp_objfile, struct objfile *objfile)
68 {
69 if (exp_objfile->separate_debug_objfile_backlink)
70 exp_objfile = exp_objfile->separate_debug_objfile_backlink;
71 return exp_objfile == objfile;
72 }
73
74 static inline bool
75 check_objfile (struct type *type, struct objfile *objfile)
76 {
77 struct objfile *ty_objfile = type->objfile_owner ();
78 if (ty_objfile != nullptr)
79 return check_objfile (ty_objfile, objfile);
80 return false;
81 }
82
83 static inline bool
84 check_objfile (struct symbol *sym, struct objfile *objfile)
85 {
86 return check_objfile (symbol_objfile (sym), objfile);
87 }
88
89 static inline bool
90 check_objfile (const struct block *block, struct objfile *objfile)
91 {
92 return check_objfile (block_objfile (block), objfile);
93 }
94
95 static inline bool
96 check_objfile (minimal_symbol *minsym, struct objfile *objfile)
97 {
98 /* This may seem strange but minsyms are only used with an objfile
99 as well. */
100 return false;
101 }
102
103 static inline bool
104 check_objfile (internalvar *ivar, struct objfile *objfile)
105 {
106 return false;
107 }
108
109 static inline bool
110 check_objfile (const std::string &str, struct objfile *objfile)
111 {
112 return false;
113 }
114
115 static inline bool
116 check_objfile (const operation_up &op, struct objfile *objfile)
117 {
118 return op->uses_objfile (objfile);
119 }
120
121 static inline bool
122 check_objfile (enum exp_opcode val, struct objfile *objfile)
123 {
124 return false;
125 }
126
127 static inline bool
128 check_objfile (ULONGEST val, struct objfile *objfile)
129 {
130 return false;
131 }
132
133 template<typename T>
134 static inline bool
135 check_objfile (enum_flags<T> val, struct objfile *objfile)
136 {
137 return false;
138 }
139
140 template<typename T>
141 static inline bool
142 check_objfile (const std::vector<T> &collection, struct objfile *objfile)
143 {
144 for (const auto &item : collection)
145 {
146 if (check_objfile (item, objfile))
147 return true;
148 }
149 return false;
150 }
151
152 template<typename S, typename T>
153 static inline bool
154 check_objfile (const std::pair<S, T> &item, struct objfile *objfile)
155 {
156 return (check_objfile (item.first, objfile)
157 || check_objfile (item.second, objfile));
158 }
159
160 static inline void
161 dump_for_expression (struct ui_file *stream, int depth,
162 const operation_up &op)
163 {
164 op->dump (stream, depth);
165 }
166
167 extern void dump_for_expression (struct ui_file *stream, int depth,
168 enum exp_opcode op);
169 extern void dump_for_expression (struct ui_file *stream, int depth,
170 const std::string &str);
171 extern void dump_for_expression (struct ui_file *stream, int depth,
172 struct type *type);
173 extern void dump_for_expression (struct ui_file *stream, int depth,
174 CORE_ADDR addr);
175 extern void dump_for_expression (struct ui_file *stream, int depth,
176 internalvar *ivar);
177 extern void dump_for_expression (struct ui_file *stream, int depth,
178 symbol *sym);
179 extern void dump_for_expression (struct ui_file *stream, int depth,
180 minimal_symbol *msym);
181 extern void dump_for_expression (struct ui_file *stream, int depth,
182 const block *bl);
183 extern void dump_for_expression (struct ui_file *stream, int depth,
184 type_instance_flags flags);
185 extern void dump_for_expression (struct ui_file *stream, int depth,
186 enum c_string_type_values flags);
187 extern void dump_for_expression (struct ui_file *stream, int depth,
188 enum range_flag flags);
189 extern void dump_for_expression (struct ui_file *stream, int depth,
190 objfile *objf);
191
192 template<typename T>
193 void
194 dump_for_expression (struct ui_file *stream, int depth,
195 const std::vector<T> &vals)
196 {
197 fprintf_filtered (stream, _("%*sVector:\n"), depth, "");
198 for (auto &item : vals)
199 dump_for_expression (stream, depth + 1, item);
200 }
201
202 template<typename X, typename Y>
203 void
204 dump_for_expression (struct ui_file *stream, int depth,
205 const std::pair<X, Y> &vals)
206 {
207 dump_for_expression (stream, depth, vals.first);
208 dump_for_expression (stream, depth, vals.second);
209 }
210
211 /* Base class for most concrete operations. This class holds data,
212 specified via template parameters, and supplies generic
213 implementations of the 'dump' and 'uses_objfile' methods. */
214 template<typename... Arg>
215 class tuple_holding_operation : public operation
216 {
217 public:
218
219 explicit tuple_holding_operation (Arg... args)
220 : m_storage (std::forward<Arg> (args)...)
221 {
222 }
223
224 DISABLE_COPY_AND_ASSIGN (tuple_holding_operation);
225
226 bool uses_objfile (struct objfile *objfile) const override
227 {
228 return do_check_objfile<0, Arg...> (objfile, m_storage);
229 }
230
231 void dump (struct ui_file *stream, int depth) const override
232 {
233 dump_for_expression (stream, depth, opcode ());
234 do_dump<0, Arg...> (stream, depth + 1, m_storage);
235 }
236
237 protected:
238
239 /* Storage for the data. */
240 std::tuple<Arg...> m_storage;
241
242 private:
243
244 /* do_dump does the work of dumping the data. */
245 template<int I, typename... T>
246 typename std::enable_if<I == sizeof... (T), void>::type
247 do_dump (struct ui_file *stream, int depth, const std::tuple<T...> &value)
248 const
249 {
250 }
251
252 template<int I, typename... T>
253 typename std::enable_if<I < sizeof... (T), void>::type
254 do_dump (struct ui_file *stream, int depth, const std::tuple<T...> &value)
255 const
256 {
257 dump_for_expression (stream, depth, std::get<I> (value));
258 do_dump<I + 1, T...> (stream, depth, value);
259 }
260
261 /* do_check_objfile does the work of checking whether this object
262 refers to OBJFILE. */
263 template<int I, typename... T>
264 typename std::enable_if<I == sizeof... (T), bool>::type
265 do_check_objfile (struct objfile *objfile, const std::tuple<T...> &value)
266 const
267 {
268 return false;
269 }
270
271 template<int I, typename... T>
272 typename std::enable_if<I < sizeof... (T), bool>::type
273 do_check_objfile (struct objfile *objfile, const std::tuple<T...> &value)
274 const
275 {
276 if (check_objfile (std::get<I> (value), objfile))
277 return true;
278 return do_check_objfile<I + 1, T...> (objfile, value);
279 }
280 };
281
282 /* The check_constant overloads are used to decide whether a given
283 concrete operation is a constant. This is done by checking the
284 operands. */
285
286 static inline bool
287 check_constant (const operation_up &item)
288 {
289 return item->constant_p ();
290 }
291
292 static inline bool
293 check_constant (struct minimal_symbol *msym)
294 {
295 return false;
296 }
297
298 static inline bool
299 check_constant (struct type *type)
300 {
301 return true;
302 }
303
304 static inline bool
305 check_constant (const struct block *block)
306 {
307 return true;
308 }
309
310 static inline bool
311 check_constant (const std::string &str)
312 {
313 return true;
314 }
315
316 static inline bool
317 check_constant (struct objfile *objfile)
318 {
319 return true;
320 }
321
322 static inline bool
323 check_constant (ULONGEST cst)
324 {
325 return true;
326 }
327
328 static inline bool
329 check_constant (struct symbol *sym)
330 {
331 enum address_class sc = SYMBOL_CLASS (sym);
332 return (sc == LOC_BLOCK
333 || sc == LOC_CONST
334 || sc == LOC_CONST_BYTES
335 || sc == LOC_LABEL);
336 }
337
338 template<typename T>
339 static inline bool
340 check_constant (const std::vector<T> &collection)
341 {
342 for (const auto &item : collection)
343 if (!check_constant (item))
344 return false;
345 return true;
346 }
347
348 template<typename S, typename T>
349 static inline bool
350 check_constant (const std::pair<S, T> &item)
351 {
352 return check_constant (item.first) && check_constant (item.second);
353 }
354
355 /* Base class for concrete operations. This class supplies an
356 implementation of 'constant_p' that works by checking the
357 operands. */
358 template<typename... Arg>
359 class maybe_constant_operation
360 : public tuple_holding_operation<Arg...>
361 {
362 public:
363
364 using tuple_holding_operation<Arg...>::tuple_holding_operation;
365
366 bool constant_p () const override
367 {
368 return do_check_constant<0, Arg...> (this->m_storage);
369 }
370
371 private:
372
373 template<int I, typename... T>
374 typename std::enable_if<I == sizeof... (T), bool>::type
375 do_check_constant (const std::tuple<T...> &value) const
376 {
377 return true;
378 }
379
380 template<int I, typename... T>
381 typename std::enable_if<I < sizeof... (T), bool>::type
382 do_check_constant (const std::tuple<T...> &value) const
383 {
384 if (!check_constant (std::get<I> (value)))
385 return false;
386 return do_check_constant<I + 1, T...> (value);
387 }
388 };
389
390 /* A floating-point constant. The constant is encoded in the target
391 format. */
392
393 typedef std::array<gdb_byte, 16> float_data;
394
395 /* An operation that holds a floating-point constant of a given
396 type.
397
398 This does not need the facilities provided by
399 tuple_holding_operation, so it does not use it. */
400 class float_const_operation
401 : public operation
402 {
403 public:
404
405 float_const_operation (struct type *type, float_data data)
406 : m_type (type),
407 m_data (data)
408 {
409 }
410
411 value *evaluate (struct type *expect_type,
412 struct expression *exp,
413 enum noside noside) override
414 {
415 return value_from_contents (m_type, m_data.data ());
416 }
417
418 enum exp_opcode opcode () const override
419 { return OP_FLOAT; }
420
421 bool constant_p () const override
422 { return true; }
423
424 void dump (struct ui_file *stream, int depth) const override;
425
426 private:
427
428 struct type *m_type;
429 float_data m_data;
430 };
431
432 class scope_operation
433 : public maybe_constant_operation<struct type *, std::string>
434 {
435 public:
436
437 using maybe_constant_operation::maybe_constant_operation;
438
439 value *evaluate (struct type *expect_type,
440 struct expression *exp,
441 enum noside noside) override
442 {
443 return eval_op_scope (expect_type, exp, noside,
444 std::get<0> (m_storage),
445 std::get<1> (m_storage).c_str ());
446 }
447
448 value *evaluate_for_address (struct expression *exp,
449 enum noside noside) override;
450
451 enum exp_opcode opcode () const override
452 { return OP_SCOPE; }
453
454 protected:
455
456 void do_generate_ax (struct expression *exp,
457 struct agent_expr *ax,
458 struct axs_value *value,
459 struct type *cast_type)
460 override;
461 };
462
463 class long_const_operation
464 : public tuple_holding_operation<struct type *, LONGEST>
465 {
466 public:
467
468 using tuple_holding_operation::tuple_holding_operation;
469
470 value *evaluate (struct type *expect_type,
471 struct expression *exp,
472 enum noside noside) override
473 {
474 return value_from_longest (std::get<0> (m_storage),
475 std::get<1> (m_storage));
476 }
477
478 enum exp_opcode opcode () const override
479 { return OP_LONG; }
480
481 bool constant_p () const override
482 { return true; }
483
484 protected:
485
486 void do_generate_ax (struct expression *exp,
487 struct agent_expr *ax,
488 struct axs_value *value,
489 struct type *cast_type)
490 override;
491 };
492
493 class var_msym_value_operation
494 : public maybe_constant_operation<minimal_symbol *, struct objfile *>
495 {
496 public:
497
498 using maybe_constant_operation::maybe_constant_operation;
499
500 value *evaluate (struct type *expect_type,
501 struct expression *exp,
502 enum noside noside) override
503 {
504 return eval_op_var_msym_value (expect_type, exp, noside, m_outermost,
505 std::get<0> (m_storage),
506 std::get<1> (m_storage));
507 }
508
509 value *evaluate_for_sizeof (struct expression *exp, enum noside noside)
510 override;
511
512 value *evaluate_for_address (struct expression *exp, enum noside noside)
513 override;
514
515 value *evaluate_for_cast (struct type *expect_type,
516 struct expression *exp,
517 enum noside noside) override;
518
519 enum exp_opcode opcode () const override
520 { return OP_VAR_MSYM_VALUE; }
521
522 void set_outermost () override
523 {
524 m_outermost = true;
525 }
526
527 protected:
528
529 /* True if this is the outermost operation in the expression. */
530 bool m_outermost = false;
531
532 void do_generate_ax (struct expression *exp,
533 struct agent_expr *ax,
534 struct axs_value *value,
535 struct type *cast_type)
536 override;
537 };
538
539 class var_entry_value_operation
540 : public tuple_holding_operation<symbol *>
541 {
542 public:
543
544 using tuple_holding_operation::tuple_holding_operation;
545
546 value *evaluate (struct type *expect_type,
547 struct expression *exp,
548 enum noside noside) override
549 {
550 return eval_op_var_entry_value (expect_type, exp, noside,
551 std::get<0> (m_storage));
552 }
553
554 enum exp_opcode opcode () const override
555 { return OP_VAR_ENTRY_VALUE; }
556 };
557
558 } /* namespace expr */
559
560 #endif /* EXPOP_H */