Commit | Line | Data |
---|---|---|
e2803273 TT |
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 | ||
75f9892d TT |
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 | ||
d5ab122c TT |
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); | |
0c8effa3 TT |
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); | |
b5cc3923 TT |
54 | extern struct value *eval_op_var_entry_value (struct type *expect_type, |
55 | struct expression *exp, | |
56 | enum noside noside, symbol *sym); | |
17679395 TT |
57 | extern struct value *eval_op_func_static_var (struct type *expect_type, |
58 | struct expression *exp, | |
59 | enum noside noside, | |
60 | value *func, const char *var); | |
55bdbff8 TT |
61 | extern struct value *eval_op_register (struct type *expect_type, |
62 | struct expression *exp, | |
63 | enum noside noside, const char *name); | |
b50db09f TT |
64 | extern struct value *eval_op_string (struct type *expect_type, |
65 | struct expression *exp, | |
66 | enum noside noside, int len, | |
67 | const char *string); | |
1594e0bb TT |
68 | extern struct value *eval_op_ternop (struct type *expect_type, |
69 | struct expression *exp, | |
70 | enum noside noside, | |
71 | struct value *array, struct value *low, | |
72 | struct value *upper); | |
808b22cf TT |
73 | extern struct value *eval_op_structop_struct (struct type *expect_type, |
74 | struct expression *exp, | |
75 | enum noside noside, | |
76 | struct value *arg1, | |
77 | const char *string); | |
ab0609be TT |
78 | extern struct value *eval_op_structop_ptr (struct type *expect_type, |
79 | struct expression *exp, | |
80 | enum noside noside, | |
81 | struct value *arg1, | |
82 | const char *string); | |
07f724a8 TT |
83 | extern struct value *eval_op_member (struct type *expect_type, |
84 | struct expression *exp, | |
85 | enum noside noside, | |
86 | struct value *arg1, struct value *arg2); | |
e51e26a0 TT |
87 | extern struct value *eval_op_concat (struct type *expect_type, |
88 | struct expression *exp, | |
89 | enum noside noside, | |
90 | struct value *arg1, struct value *arg2); | |
a94323b6 TT |
91 | extern struct value *eval_op_add (struct type *expect_type, |
92 | struct expression *exp, | |
93 | enum noside noside, | |
94 | struct value *arg1, struct value *arg2); | |
5133d78b TT |
95 | extern struct value *eval_op_sub (struct type *expect_type, |
96 | struct expression *exp, | |
97 | enum noside noside, | |
98 | struct value *arg1, struct value *arg2); | |
373907ff TT |
99 | extern struct value *eval_op_binary (struct type *expect_type, |
100 | struct expression *exp, | |
101 | enum noside noside, enum exp_opcode op, | |
102 | struct value *arg1, struct value *arg2); | |
224d6424 TT |
103 | extern struct value *eval_op_subscript (struct type *expect_type, |
104 | struct expression *exp, | |
105 | enum noside noside, enum exp_opcode op, | |
106 | struct value *arg1, | |
107 | struct value *arg2); | |
46916f2b TT |
108 | extern struct value *eval_op_equal (struct type *expect_type, |
109 | struct expression *exp, | |
110 | enum noside noside, enum exp_opcode op, | |
111 | struct value *arg1, | |
112 | struct value *arg2); | |
113 | extern struct value *eval_op_notequal (struct type *expect_type, | |
114 | struct expression *exp, | |
115 | enum noside noside, enum exp_opcode op, | |
116 | struct value *arg1, | |
117 | struct value *arg2); | |
118 | extern struct value *eval_op_less (struct type *expect_type, | |
119 | struct expression *exp, | |
120 | enum noside noside, enum exp_opcode op, | |
121 | struct value *arg1, | |
122 | struct value *arg2); | |
123 | extern struct value *eval_op_gtr (struct type *expect_type, | |
124 | struct expression *exp, | |
125 | enum noside noside, enum exp_opcode op, | |
126 | struct value *arg1, | |
127 | struct value *arg2); | |
128 | extern struct value *eval_op_geq (struct type *expect_type, | |
129 | struct expression *exp, | |
130 | enum noside noside, enum exp_opcode op, | |
131 | struct value *arg1, | |
132 | struct value *arg2); | |
133 | extern struct value *eval_op_leq (struct type *expect_type, | |
134 | struct expression *exp, | |
135 | enum noside noside, enum exp_opcode op, | |
136 | struct value *arg1, | |
137 | struct value *arg2); | |
d5ab122c | 138 | |
e2803273 TT |
139 | namespace expr |
140 | { | |
141 | ||
142 | /* The check_objfile overloads are used to check whether a particular | |
143 | component of some operation references an objfile. The passed-in | |
144 | objfile will never be a debug objfile. */ | |
145 | ||
146 | /* See if EXP_OBJFILE matches OBJFILE. */ | |
147 | static inline bool | |
148 | check_objfile (struct objfile *exp_objfile, struct objfile *objfile) | |
149 | { | |
150 | if (exp_objfile->separate_debug_objfile_backlink) | |
151 | exp_objfile = exp_objfile->separate_debug_objfile_backlink; | |
152 | return exp_objfile == objfile; | |
153 | } | |
154 | ||
155 | static inline bool | |
156 | check_objfile (struct type *type, struct objfile *objfile) | |
157 | { | |
158 | struct objfile *ty_objfile = type->objfile_owner (); | |
159 | if (ty_objfile != nullptr) | |
160 | return check_objfile (ty_objfile, objfile); | |
161 | return false; | |
162 | } | |
163 | ||
164 | static inline bool | |
165 | check_objfile (struct symbol *sym, struct objfile *objfile) | |
166 | { | |
167 | return check_objfile (symbol_objfile (sym), objfile); | |
168 | } | |
169 | ||
170 | static inline bool | |
171 | check_objfile (const struct block *block, struct objfile *objfile) | |
172 | { | |
173 | return check_objfile (block_objfile (block), objfile); | |
174 | } | |
175 | ||
176 | static inline bool | |
177 | check_objfile (minimal_symbol *minsym, struct objfile *objfile) | |
178 | { | |
179 | /* This may seem strange but minsyms are only used with an objfile | |
180 | as well. */ | |
181 | return false; | |
182 | } | |
183 | ||
184 | static inline bool | |
185 | check_objfile (internalvar *ivar, struct objfile *objfile) | |
186 | { | |
187 | return false; | |
188 | } | |
189 | ||
190 | static inline bool | |
191 | check_objfile (const std::string &str, struct objfile *objfile) | |
192 | { | |
193 | return false; | |
194 | } | |
195 | ||
196 | static inline bool | |
197 | check_objfile (const operation_up &op, struct objfile *objfile) | |
198 | { | |
199 | return op->uses_objfile (objfile); | |
200 | } | |
201 | ||
202 | static inline bool | |
203 | check_objfile (enum exp_opcode val, struct objfile *objfile) | |
204 | { | |
205 | return false; | |
206 | } | |
207 | ||
208 | static inline bool | |
209 | check_objfile (ULONGEST val, struct objfile *objfile) | |
210 | { | |
211 | return false; | |
212 | } | |
213 | ||
214 | template<typename T> | |
215 | static inline bool | |
216 | check_objfile (enum_flags<T> val, struct objfile *objfile) | |
217 | { | |
218 | return false; | |
219 | } | |
220 | ||
221 | template<typename T> | |
222 | static inline bool | |
223 | check_objfile (const std::vector<T> &collection, struct objfile *objfile) | |
224 | { | |
225 | for (const auto &item : collection) | |
226 | { | |
227 | if (check_objfile (item, objfile)) | |
228 | return true; | |
229 | } | |
230 | return false; | |
231 | } | |
232 | ||
233 | template<typename S, typename T> | |
234 | static inline bool | |
235 | check_objfile (const std::pair<S, T> &item, struct objfile *objfile) | |
236 | { | |
237 | return (check_objfile (item.first, objfile) | |
238 | || check_objfile (item.second, objfile)); | |
239 | } | |
240 | ||
de401988 TT |
241 | static inline void |
242 | dump_for_expression (struct ui_file *stream, int depth, | |
243 | const operation_up &op) | |
244 | { | |
245 | op->dump (stream, depth); | |
246 | } | |
247 | ||
248 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
249 | enum exp_opcode op); | |
250 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
251 | const std::string &str); | |
252 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
253 | struct type *type); | |
254 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
255 | CORE_ADDR addr); | |
256 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
257 | internalvar *ivar); | |
258 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
259 | symbol *sym); | |
260 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
261 | minimal_symbol *msym); | |
262 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
263 | const block *bl); | |
264 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
265 | type_instance_flags flags); | |
266 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
267 | enum c_string_type_values flags); | |
268 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
269 | enum range_flag flags); | |
270 | extern void dump_for_expression (struct ui_file *stream, int depth, | |
271 | objfile *objf); | |
272 | ||
273 | template<typename T> | |
274 | void | |
275 | dump_for_expression (struct ui_file *stream, int depth, | |
276 | const std::vector<T> &vals) | |
277 | { | |
278 | fprintf_filtered (stream, _("%*sVector:\n"), depth, ""); | |
279 | for (auto &item : vals) | |
280 | dump_for_expression (stream, depth + 1, item); | |
281 | } | |
282 | ||
283 | template<typename X, typename Y> | |
284 | void | |
285 | dump_for_expression (struct ui_file *stream, int depth, | |
286 | const std::pair<X, Y> &vals) | |
287 | { | |
288 | dump_for_expression (stream, depth, vals.first); | |
289 | dump_for_expression (stream, depth, vals.second); | |
290 | } | |
291 | ||
e2803273 TT |
292 | /* Base class for most concrete operations. This class holds data, |
293 | specified via template parameters, and supplies generic | |
294 | implementations of the 'dump' and 'uses_objfile' methods. */ | |
295 | template<typename... Arg> | |
296 | class tuple_holding_operation : public operation | |
297 | { | |
298 | public: | |
299 | ||
300 | explicit tuple_holding_operation (Arg... args) | |
301 | : m_storage (std::forward<Arg> (args)...) | |
302 | { | |
303 | } | |
304 | ||
305 | DISABLE_COPY_AND_ASSIGN (tuple_holding_operation); | |
306 | ||
307 | bool uses_objfile (struct objfile *objfile) const override | |
308 | { | |
309 | return do_check_objfile<0, Arg...> (objfile, m_storage); | |
310 | } | |
311 | ||
312 | void dump (struct ui_file *stream, int depth) const override | |
313 | { | |
de401988 TT |
314 | dump_for_expression (stream, depth, opcode ()); |
315 | do_dump<0, Arg...> (stream, depth + 1, m_storage); | |
e2803273 TT |
316 | } |
317 | ||
318 | protected: | |
319 | ||
320 | /* Storage for the data. */ | |
321 | std::tuple<Arg...> m_storage; | |
322 | ||
323 | private: | |
324 | ||
325 | /* do_dump does the work of dumping the data. */ | |
326 | template<int I, typename... T> | |
327 | typename std::enable_if<I == sizeof... (T), void>::type | |
328 | do_dump (struct ui_file *stream, int depth, const std::tuple<T...> &value) | |
329 | const | |
330 | { | |
331 | } | |
332 | ||
333 | template<int I, typename... T> | |
334 | typename std::enable_if<I < sizeof... (T), void>::type | |
335 | do_dump (struct ui_file *stream, int depth, const std::tuple<T...> &value) | |
336 | const | |
337 | { | |
de401988 | 338 | dump_for_expression (stream, depth, std::get<I> (value)); |
e2803273 TT |
339 | do_dump<I + 1, T...> (stream, depth, value); |
340 | } | |
341 | ||
342 | /* do_check_objfile does the work of checking whether this object | |
343 | refers to OBJFILE. */ | |
344 | template<int I, typename... T> | |
345 | typename std::enable_if<I == sizeof... (T), bool>::type | |
346 | do_check_objfile (struct objfile *objfile, const std::tuple<T...> &value) | |
347 | const | |
348 | { | |
349 | return false; | |
350 | } | |
351 | ||
352 | template<int I, typename... T> | |
353 | typename std::enable_if<I < sizeof... (T), bool>::type | |
354 | do_check_objfile (struct objfile *objfile, const std::tuple<T...> &value) | |
355 | const | |
356 | { | |
357 | if (check_objfile (std::get<I> (value), objfile)) | |
358 | return true; | |
359 | return do_check_objfile<I + 1, T...> (objfile, value); | |
360 | } | |
361 | }; | |
362 | ||
363 | /* The check_constant overloads are used to decide whether a given | |
364 | concrete operation is a constant. This is done by checking the | |
365 | operands. */ | |
366 | ||
367 | static inline bool | |
368 | check_constant (const operation_up &item) | |
369 | { | |
370 | return item->constant_p (); | |
371 | } | |
372 | ||
373 | static inline bool | |
374 | check_constant (struct minimal_symbol *msym) | |
375 | { | |
376 | return false; | |
377 | } | |
378 | ||
379 | static inline bool | |
380 | check_constant (struct type *type) | |
381 | { | |
382 | return true; | |
383 | } | |
384 | ||
385 | static inline bool | |
386 | check_constant (const struct block *block) | |
387 | { | |
388 | return true; | |
389 | } | |
390 | ||
391 | static inline bool | |
392 | check_constant (const std::string &str) | |
393 | { | |
394 | return true; | |
395 | } | |
396 | ||
397 | static inline bool | |
398 | check_constant (struct objfile *objfile) | |
399 | { | |
400 | return true; | |
401 | } | |
402 | ||
403 | static inline bool | |
404 | check_constant (ULONGEST cst) | |
405 | { | |
406 | return true; | |
407 | } | |
408 | ||
409 | static inline bool | |
410 | check_constant (struct symbol *sym) | |
411 | { | |
412 | enum address_class sc = SYMBOL_CLASS (sym); | |
413 | return (sc == LOC_BLOCK | |
414 | || sc == LOC_CONST | |
415 | || sc == LOC_CONST_BYTES | |
416 | || sc == LOC_LABEL); | |
417 | } | |
418 | ||
419 | template<typename T> | |
420 | static inline bool | |
421 | check_constant (const std::vector<T> &collection) | |
422 | { | |
423 | for (const auto &item : collection) | |
424 | if (!check_constant (item)) | |
425 | return false; | |
426 | return true; | |
427 | } | |
428 | ||
429 | template<typename S, typename T> | |
430 | static inline bool | |
431 | check_constant (const std::pair<S, T> &item) | |
432 | { | |
433 | return check_constant (item.first) && check_constant (item.second); | |
434 | } | |
435 | ||
436 | /* Base class for concrete operations. This class supplies an | |
437 | implementation of 'constant_p' that works by checking the | |
438 | operands. */ | |
439 | template<typename... Arg> | |
440 | class maybe_constant_operation | |
441 | : public tuple_holding_operation<Arg...> | |
442 | { | |
443 | public: | |
444 | ||
445 | using tuple_holding_operation<Arg...>::tuple_holding_operation; | |
446 | ||
447 | bool constant_p () const override | |
448 | { | |
449 | return do_check_constant<0, Arg...> (this->m_storage); | |
450 | } | |
451 | ||
452 | private: | |
453 | ||
454 | template<int I, typename... T> | |
455 | typename std::enable_if<I == sizeof... (T), bool>::type | |
456 | do_check_constant (const std::tuple<T...> &value) const | |
457 | { | |
458 | return true; | |
459 | } | |
460 | ||
461 | template<int I, typename... T> | |
462 | typename std::enable_if<I < sizeof... (T), bool>::type | |
463 | do_check_constant (const std::tuple<T...> &value) const | |
464 | { | |
465 | if (!check_constant (std::get<I> (value))) | |
466 | return false; | |
467 | return do_check_constant<I + 1, T...> (value); | |
468 | } | |
469 | }; | |
470 | ||
cae26a0c TT |
471 | /* A floating-point constant. The constant is encoded in the target |
472 | format. */ | |
473 | ||
474 | typedef std::array<gdb_byte, 16> float_data; | |
475 | ||
476 | /* An operation that holds a floating-point constant of a given | |
477 | type. | |
478 | ||
479 | This does not need the facilities provided by | |
480 | tuple_holding_operation, so it does not use it. */ | |
481 | class float_const_operation | |
482 | : public operation | |
483 | { | |
484 | public: | |
485 | ||
486 | float_const_operation (struct type *type, float_data data) | |
487 | : m_type (type), | |
488 | m_data (data) | |
489 | { | |
490 | } | |
491 | ||
492 | value *evaluate (struct type *expect_type, | |
493 | struct expression *exp, | |
494 | enum noside noside) override | |
495 | { | |
496 | return value_from_contents (m_type, m_data.data ()); | |
497 | } | |
498 | ||
499 | enum exp_opcode opcode () const override | |
500 | { return OP_FLOAT; } | |
501 | ||
502 | bool constant_p () const override | |
503 | { return true; } | |
504 | ||
505 | void dump (struct ui_file *stream, int depth) const override; | |
506 | ||
507 | private: | |
508 | ||
509 | struct type *m_type; | |
510 | float_data m_data; | |
511 | }; | |
512 | ||
d5ab122c TT |
513 | class scope_operation |
514 | : public maybe_constant_operation<struct type *, std::string> | |
515 | { | |
516 | public: | |
517 | ||
518 | using maybe_constant_operation::maybe_constant_operation; | |
519 | ||
520 | value *evaluate (struct type *expect_type, | |
521 | struct expression *exp, | |
522 | enum noside noside) override | |
523 | { | |
524 | return eval_op_scope (expect_type, exp, noside, | |
525 | std::get<0> (m_storage), | |
526 | std::get<1> (m_storage).c_str ()); | |
527 | } | |
528 | ||
529 | value *evaluate_for_address (struct expression *exp, | |
530 | enum noside noside) override; | |
531 | ||
532 | enum exp_opcode opcode () const override | |
533 | { return OP_SCOPE; } | |
534 | ||
535 | protected: | |
536 | ||
537 | void do_generate_ax (struct expression *exp, | |
538 | struct agent_expr *ax, | |
539 | struct axs_value *value, | |
540 | struct type *cast_type) | |
541 | override; | |
542 | }; | |
543 | ||
d336c29e TT |
544 | class long_const_operation |
545 | : public tuple_holding_operation<struct type *, LONGEST> | |
546 | { | |
547 | public: | |
548 | ||
549 | using tuple_holding_operation::tuple_holding_operation; | |
550 | ||
551 | value *evaluate (struct type *expect_type, | |
552 | struct expression *exp, | |
553 | enum noside noside) override | |
554 | { | |
555 | return value_from_longest (std::get<0> (m_storage), | |
556 | std::get<1> (m_storage)); | |
557 | } | |
558 | ||
559 | enum exp_opcode opcode () const override | |
560 | { return OP_LONG; } | |
561 | ||
562 | bool constant_p () const override | |
563 | { return true; } | |
564 | ||
565 | protected: | |
566 | ||
567 | void do_generate_ax (struct expression *exp, | |
568 | struct agent_expr *ax, | |
569 | struct axs_value *value, | |
570 | struct type *cast_type) | |
571 | override; | |
572 | }; | |
573 | ||
0c8effa3 TT |
574 | class var_msym_value_operation |
575 | : public maybe_constant_operation<minimal_symbol *, struct objfile *> | |
576 | { | |
577 | public: | |
578 | ||
579 | using maybe_constant_operation::maybe_constant_operation; | |
580 | ||
581 | value *evaluate (struct type *expect_type, | |
582 | struct expression *exp, | |
583 | enum noside noside) override | |
584 | { | |
585 | return eval_op_var_msym_value (expect_type, exp, noside, m_outermost, | |
586 | std::get<0> (m_storage), | |
587 | std::get<1> (m_storage)); | |
588 | } | |
589 | ||
590 | value *evaluate_for_sizeof (struct expression *exp, enum noside noside) | |
591 | override; | |
592 | ||
593 | value *evaluate_for_address (struct expression *exp, enum noside noside) | |
594 | override; | |
595 | ||
596 | value *evaluate_for_cast (struct type *expect_type, | |
597 | struct expression *exp, | |
598 | enum noside noside) override; | |
599 | ||
600 | enum exp_opcode opcode () const override | |
601 | { return OP_VAR_MSYM_VALUE; } | |
602 | ||
603 | void set_outermost () override | |
604 | { | |
605 | m_outermost = true; | |
606 | } | |
607 | ||
608 | protected: | |
609 | ||
610 | /* True if this is the outermost operation in the expression. */ | |
611 | bool m_outermost = false; | |
612 | ||
613 | void do_generate_ax (struct expression *exp, | |
614 | struct agent_expr *ax, | |
615 | struct axs_value *value, | |
616 | struct type *cast_type) | |
617 | override; | |
618 | }; | |
619 | ||
b5cc3923 TT |
620 | class var_entry_value_operation |
621 | : public tuple_holding_operation<symbol *> | |
622 | { | |
623 | public: | |
624 | ||
625 | using tuple_holding_operation::tuple_holding_operation; | |
626 | ||
627 | value *evaluate (struct type *expect_type, | |
628 | struct expression *exp, | |
629 | enum noside noside) override | |
630 | { | |
631 | return eval_op_var_entry_value (expect_type, exp, noside, | |
632 | std::get<0> (m_storage)); | |
633 | } | |
634 | ||
635 | enum exp_opcode opcode () const override | |
636 | { return OP_VAR_ENTRY_VALUE; } | |
637 | }; | |
638 | ||
17679395 TT |
639 | class func_static_var_operation |
640 | : public maybe_constant_operation<operation_up, std::string> | |
641 | { | |
642 | public: | |
643 | ||
644 | using maybe_constant_operation::maybe_constant_operation; | |
645 | ||
646 | value *evaluate (struct type *expect_type, | |
647 | struct expression *exp, | |
648 | enum noside noside) override | |
649 | { | |
650 | value *func = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
651 | return eval_op_func_static_var (expect_type, exp, noside, func, | |
652 | std::get<1> (m_storage).c_str ()); | |
653 | } | |
654 | ||
655 | enum exp_opcode opcode () const override | |
656 | { return OP_FUNC_STATIC_VAR; } | |
657 | }; | |
658 | ||
247d935b TT |
659 | class last_operation |
660 | : public tuple_holding_operation<int> | |
661 | { | |
662 | public: | |
663 | ||
664 | using tuple_holding_operation::tuple_holding_operation; | |
665 | ||
666 | value *evaluate (struct type *expect_type, | |
667 | struct expression *exp, | |
668 | enum noside noside) override | |
669 | { | |
670 | return access_value_history (std::get<0> (m_storage)); | |
671 | } | |
672 | ||
673 | enum exp_opcode opcode () const override | |
674 | { return OP_LAST; } | |
675 | }; | |
676 | ||
55bdbff8 TT |
677 | class register_operation |
678 | : public tuple_holding_operation<std::string> | |
679 | { | |
680 | public: | |
681 | ||
682 | using tuple_holding_operation::tuple_holding_operation; | |
683 | ||
684 | value *evaluate (struct type *expect_type, | |
685 | struct expression *exp, | |
686 | enum noside noside) override | |
687 | { | |
688 | return eval_op_register (expect_type, exp, noside, | |
689 | std::get<0> (m_storage).c_str ()); | |
690 | } | |
691 | ||
692 | enum exp_opcode opcode () const override | |
693 | { return OP_REGISTER; } | |
694 | ||
695 | protected: | |
696 | ||
697 | void do_generate_ax (struct expression *exp, | |
698 | struct agent_expr *ax, | |
699 | struct axs_value *value, | |
700 | struct type *cast_type) | |
701 | override; | |
702 | }; | |
703 | ||
e6985c5e TT |
704 | class bool_operation |
705 | : public tuple_holding_operation<bool> | |
706 | { | |
707 | public: | |
708 | ||
709 | using tuple_holding_operation::tuple_holding_operation; | |
710 | ||
711 | value *evaluate (struct type *expect_type, | |
712 | struct expression *exp, | |
713 | enum noside noside) override | |
714 | { | |
715 | struct type *type = language_bool_type (exp->language_defn, exp->gdbarch); | |
716 | return value_from_longest (type, std::get<0> (m_storage)); | |
717 | } | |
718 | ||
719 | enum exp_opcode opcode () const override | |
720 | { return OP_BOOL; } | |
721 | ||
722 | bool constant_p () const override | |
723 | { return true; } | |
724 | }; | |
725 | ||
e6e01e16 TT |
726 | class internalvar_operation |
727 | : public tuple_holding_operation<internalvar *> | |
728 | { | |
729 | public: | |
730 | ||
731 | using tuple_holding_operation::tuple_holding_operation; | |
732 | ||
733 | value *evaluate (struct type *expect_type, | |
734 | struct expression *exp, | |
735 | enum noside noside) override | |
736 | { | |
737 | return value_of_internalvar (exp->gdbarch, | |
738 | std::get<0> (m_storage)); | |
739 | } | |
740 | ||
741 | internalvar *get_internalvar () const | |
742 | { | |
743 | return std::get<0> (m_storage); | |
744 | } | |
745 | ||
746 | enum exp_opcode opcode () const override | |
747 | { return OP_INTERNALVAR; } | |
748 | ||
749 | protected: | |
750 | ||
751 | void do_generate_ax (struct expression *exp, | |
752 | struct agent_expr *ax, | |
753 | struct axs_value *value, | |
754 | struct type *cast_type) | |
755 | override; | |
756 | }; | |
757 | ||
b50db09f TT |
758 | class string_operation |
759 | : public tuple_holding_operation<std::string> | |
760 | { | |
761 | public: | |
762 | ||
763 | using tuple_holding_operation::tuple_holding_operation; | |
764 | ||
765 | value *evaluate (struct type *expect_type, | |
766 | struct expression *exp, | |
767 | enum noside noside) override | |
768 | { | |
769 | const std::string &str = std::get<0> (m_storage); | |
770 | return eval_op_string (expect_type, exp, noside, | |
771 | str.size (), str.c_str ()); | |
772 | } | |
773 | ||
774 | enum exp_opcode opcode () const override | |
775 | { return OP_STRING; } | |
776 | }; | |
777 | ||
1594e0bb TT |
778 | class ternop_slice_operation |
779 | : public maybe_constant_operation<operation_up, operation_up, operation_up> | |
780 | { | |
781 | public: | |
782 | ||
783 | using maybe_constant_operation::maybe_constant_operation; | |
784 | ||
785 | value *evaluate (struct type *expect_type, | |
786 | struct expression *exp, | |
787 | enum noside noside) override | |
788 | { | |
789 | struct value *array | |
790 | = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
791 | struct value *low | |
792 | = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
793 | struct value *upper | |
794 | = std::get<2> (m_storage)->evaluate (nullptr, exp, noside); | |
795 | return eval_op_ternop (expect_type, exp, noside, array, low, upper); | |
796 | } | |
797 | ||
798 | enum exp_opcode opcode () const override | |
799 | { return TERNOP_SLICE; } | |
800 | }; | |
801 | ||
9186293f TT |
802 | class ternop_cond_operation |
803 | : public maybe_constant_operation<operation_up, operation_up, operation_up> | |
804 | { | |
805 | public: | |
806 | ||
807 | using maybe_constant_operation::maybe_constant_operation; | |
808 | ||
809 | value *evaluate (struct type *expect_type, | |
810 | struct expression *exp, | |
811 | enum noside noside) override | |
812 | { | |
813 | struct value *val | |
814 | = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
815 | ||
816 | if (value_logical_not (val)) | |
817 | return std::get<2> (m_storage)->evaluate (nullptr, exp, noside); | |
818 | return std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
819 | } | |
820 | ||
821 | enum exp_opcode opcode () const override | |
822 | { return TERNOP_COND; } | |
823 | ||
824 | protected: | |
825 | ||
826 | void do_generate_ax (struct expression *exp, | |
827 | struct agent_expr *ax, | |
828 | struct axs_value *value, | |
829 | struct type *cast_type) | |
830 | override; | |
831 | }; | |
832 | ||
8cfd3e95 TT |
833 | class complex_operation |
834 | : public maybe_constant_operation<operation_up, operation_up, struct type *> | |
835 | { | |
836 | public: | |
837 | ||
838 | using maybe_constant_operation::maybe_constant_operation; | |
839 | ||
840 | value *evaluate (struct type *expect_type, | |
841 | struct expression *exp, | |
842 | enum noside noside) override | |
843 | { | |
844 | value *real = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
845 | value *imag = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
846 | return value_literal_complex (real, imag, | |
847 | std::get<2> (m_storage)); | |
848 | } | |
849 | ||
850 | enum exp_opcode opcode () const override | |
851 | { return OP_COMPLEX; } | |
852 | }; | |
853 | ||
808b22cf TT |
854 | class structop_base_operation |
855 | : public tuple_holding_operation<operation_up, std::string> | |
856 | { | |
857 | public: | |
858 | ||
859 | /* Used for completion. Return the field name. */ | |
860 | const std::string &get_string () const | |
861 | { | |
862 | return std::get<1> (m_storage); | |
863 | } | |
864 | ||
865 | /* Used for completion. Evaluate the LHS for type. */ | |
866 | value *evaluate_lhs (struct expression *exp) | |
867 | { | |
868 | return std::get<0> (m_storage)->evaluate (nullptr, exp, | |
869 | EVAL_AVOID_SIDE_EFFECTS); | |
870 | } | |
871 | ||
872 | protected: | |
873 | ||
874 | using tuple_holding_operation::tuple_holding_operation; | |
875 | }; | |
876 | ||
877 | class structop_operation | |
878 | : public structop_base_operation | |
879 | { | |
880 | public: | |
881 | ||
882 | using structop_base_operation::structop_base_operation; | |
883 | ||
884 | value *evaluate (struct type *expect_type, | |
885 | struct expression *exp, | |
886 | enum noside noside) override | |
887 | { | |
888 | value *val =std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
889 | return eval_op_structop_struct (expect_type, exp, noside, val, | |
890 | std::get<1> (m_storage).c_str ()); | |
891 | } | |
892 | ||
893 | enum exp_opcode opcode () const override | |
894 | { return STRUCTOP_STRUCT; } | |
895 | ||
896 | protected: | |
897 | ||
898 | void do_generate_ax (struct expression *exp, | |
899 | struct agent_expr *ax, | |
900 | struct axs_value *value, | |
901 | struct type *cast_type) | |
902 | override | |
903 | { | |
904 | gen_expr_structop (exp, STRUCTOP_STRUCT, | |
905 | std::get<0> (this->m_storage).get (), | |
906 | std::get<1> (this->m_storage).c_str (), | |
907 | ax, value); | |
908 | } | |
909 | }; | |
910 | ||
ab0609be TT |
911 | class structop_ptr_operation |
912 | : public structop_base_operation | |
913 | { | |
914 | public: | |
915 | ||
916 | using structop_base_operation::structop_base_operation; | |
917 | ||
918 | value *evaluate (struct type *expect_type, | |
919 | struct expression *exp, | |
920 | enum noside noside) override | |
921 | { | |
922 | value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
923 | return eval_op_structop_ptr (expect_type, exp, noside, val, | |
924 | std::get<1> (m_storage).c_str ()); | |
925 | } | |
926 | ||
927 | enum exp_opcode opcode () const override | |
928 | { return STRUCTOP_PTR; } | |
929 | ||
930 | protected: | |
931 | ||
932 | void do_generate_ax (struct expression *exp, | |
933 | struct agent_expr *ax, | |
934 | struct axs_value *value, | |
935 | struct type *cast_type) | |
936 | override | |
937 | { | |
938 | gen_expr_structop (exp, STRUCTOP_PTR, | |
939 | std::get<0> (this->m_storage).get (), | |
940 | std::get<1> (this->m_storage).c_str (), | |
941 | ax, value); | |
942 | } | |
943 | }; | |
944 | ||
07f724a8 TT |
945 | class structop_member_operation |
946 | : public tuple_holding_operation<operation_up, operation_up> | |
947 | { | |
948 | public: | |
949 | ||
950 | using tuple_holding_operation::tuple_holding_operation; | |
951 | ||
952 | value *evaluate (struct type *expect_type, | |
953 | struct expression *exp, | |
954 | enum noside noside) override | |
955 | { | |
956 | value *lhs | |
957 | = std::get<0> (m_storage)->evaluate_for_address (exp, noside); | |
958 | value *rhs | |
959 | = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
960 | return eval_op_member (expect_type, exp, noside, lhs, rhs); | |
961 | } | |
962 | ||
963 | enum exp_opcode opcode () const override | |
964 | { return STRUCTOP_MEMBER; } | |
965 | }; | |
966 | ||
967 | class structop_mptr_operation | |
968 | : public tuple_holding_operation<operation_up, operation_up> | |
969 | { | |
970 | public: | |
971 | ||
972 | using tuple_holding_operation::tuple_holding_operation; | |
973 | ||
974 | value *evaluate (struct type *expect_type, | |
975 | struct expression *exp, | |
976 | enum noside noside) override | |
977 | { | |
978 | value *lhs | |
979 | = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
980 | value *rhs | |
981 | = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
982 | return eval_op_member (expect_type, exp, noside, lhs, rhs); | |
983 | } | |
984 | ||
985 | enum exp_opcode opcode () const override | |
986 | { return STRUCTOP_MPTR; } | |
987 | }; | |
988 | ||
e51e26a0 TT |
989 | class concat_operation |
990 | : public maybe_constant_operation<operation_up, operation_up> | |
991 | { | |
992 | public: | |
993 | ||
994 | using maybe_constant_operation::maybe_constant_operation; | |
995 | ||
996 | value *evaluate (struct type *expect_type, | |
997 | struct expression *exp, | |
998 | enum noside noside) override | |
999 | { | |
1000 | value *lhs | |
1001 | = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside); | |
1002 | value *rhs | |
1003 | = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside); | |
1004 | return eval_op_concat (expect_type, exp, noside, lhs, rhs); | |
1005 | } | |
1006 | ||
1007 | enum exp_opcode opcode () const override | |
1008 | { return BINOP_CONCAT; } | |
1009 | }; | |
1010 | ||
a94323b6 TT |
1011 | class add_operation |
1012 | : public maybe_constant_operation<operation_up, operation_up> | |
1013 | { | |
1014 | public: | |
1015 | ||
1016 | using maybe_constant_operation::maybe_constant_operation; | |
1017 | ||
1018 | value *evaluate (struct type *expect_type, | |
1019 | struct expression *exp, | |
1020 | enum noside noside) override | |
1021 | { | |
1022 | value *lhs | |
1023 | = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside); | |
1024 | value *rhs | |
1025 | = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside); | |
1026 | return eval_op_add (expect_type, exp, noside, lhs, rhs); | |
1027 | } | |
1028 | ||
1029 | enum exp_opcode opcode () const override | |
1030 | { return BINOP_ADD; } | |
1031 | ||
1032 | protected: | |
1033 | ||
1034 | void do_generate_ax (struct expression *exp, | |
1035 | struct agent_expr *ax, | |
1036 | struct axs_value *value, | |
1037 | struct type *cast_type) | |
1038 | override | |
1039 | { | |
1040 | gen_expr_binop (exp, BINOP_ADD, | |
1041 | std::get<0> (this->m_storage).get (), | |
1042 | std::get<1> (this->m_storage).get (), | |
1043 | ax, value); | |
1044 | } | |
1045 | }; | |
1046 | ||
5133d78b TT |
1047 | class sub_operation |
1048 | : public maybe_constant_operation<operation_up, operation_up> | |
1049 | { | |
1050 | public: | |
1051 | ||
1052 | using maybe_constant_operation::maybe_constant_operation; | |
1053 | ||
1054 | value *evaluate (struct type *expect_type, | |
1055 | struct expression *exp, | |
1056 | enum noside noside) override | |
1057 | { | |
1058 | value *lhs | |
1059 | = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside); | |
1060 | value *rhs | |
1061 | = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside); | |
1062 | return eval_op_sub (expect_type, exp, noside, lhs, rhs); | |
1063 | } | |
1064 | ||
1065 | enum exp_opcode opcode () const override | |
1066 | { return BINOP_SUB; } | |
1067 | ||
1068 | protected: | |
1069 | ||
1070 | void do_generate_ax (struct expression *exp, | |
1071 | struct agent_expr *ax, | |
1072 | struct axs_value *value, | |
1073 | struct type *cast_type) | |
1074 | override | |
1075 | { | |
1076 | gen_expr_binop (exp, BINOP_SUB, | |
1077 | std::get<0> (this->m_storage).get (), | |
1078 | std::get<1> (this->m_storage).get (), | |
1079 | ax, value); | |
1080 | } | |
1081 | }; | |
1082 | ||
373907ff TT |
1083 | typedef struct value *binary_ftype (struct type *expect_type, |
1084 | struct expression *exp, | |
1085 | enum noside noside, enum exp_opcode op, | |
1086 | struct value *arg1, struct value *arg2); | |
1087 | ||
1088 | template<enum exp_opcode OP, binary_ftype FUNC> | |
1089 | class binop_operation | |
1090 | : public maybe_constant_operation<operation_up, operation_up> | |
1091 | { | |
1092 | public: | |
1093 | ||
1094 | using maybe_constant_operation::maybe_constant_operation; | |
1095 | ||
1096 | value *evaluate (struct type *expect_type, | |
1097 | struct expression *exp, | |
1098 | enum noside noside) override | |
1099 | { | |
1100 | value *lhs | |
1101 | = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | |
1102 | value *rhs | |
1103 | = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | |
1104 | return FUNC (expect_type, exp, noside, OP, lhs, rhs); | |
1105 | } | |
1106 | ||
1107 | enum exp_opcode opcode () const override | |
1108 | { return OP; } | |
1109 | }; | |
1110 | ||
1111 | template<enum exp_opcode OP, binary_ftype FUNC> | |
1112 | class usual_ax_binop_operation | |
1113 | : public binop_operation<OP, FUNC> | |
1114 | { | |
1115 | public: | |
1116 | ||
1117 | using binop_operation<OP, FUNC>::binop_operation; | |
1118 | ||
1119 | protected: | |
1120 | ||
1121 | void do_generate_ax (struct expression *exp, | |
1122 | struct agent_expr *ax, | |
1123 | struct axs_value *value, | |
1124 | struct type *cast_type) | |
1125 | override | |
1126 | { | |
1127 | gen_expr_binop (exp, OP, | |
1128 | std::get<0> (this->m_storage).get (), | |
1129 | std::get<1> (this->m_storage).get (), | |
1130 | ax, value); | |
1131 | } | |
1132 | }; | |
1133 | ||
1134 | using exp_operation = binop_operation<BINOP_EXP, eval_op_binary>; | |
1135 | using intdiv_operation = binop_operation<BINOP_INTDIV, eval_op_binary>; | |
1136 | using mod_operation = binop_operation<BINOP_MOD, eval_op_binary>; | |
1137 | ||
1138 | using mul_operation = usual_ax_binop_operation<BINOP_MUL, eval_op_binary>; | |
1139 | using div_operation = usual_ax_binop_operation<BINOP_DIV, eval_op_binary>; | |
1140 | using rem_operation = usual_ax_binop_operation<BINOP_REM, eval_op_binary>; | |
1141 | using lsh_operation = usual_ax_binop_operation<BINOP_LSH, eval_op_binary>; | |
1142 | using rsh_operation = usual_ax_binop_operation<BINOP_RSH, eval_op_binary>; | |
1143 | using bitwise_and_operation | |
1144 | = usual_ax_binop_operation<BINOP_BITWISE_AND, eval_op_binary>; | |
1145 | using bitwise_ior_operation | |
1146 | = usual_ax_binop_operation<BINOP_BITWISE_IOR, eval_op_binary>; | |
1147 | using bitwise_xor_operation | |
1148 | = usual_ax_binop_operation<BINOP_BITWISE_XOR, eval_op_binary>; | |
1149 | ||
224d6424 TT |
1150 | class subscript_operation |
1151 | : public usual_ax_binop_operation<BINOP_SUBSCRIPT, eval_op_subscript> | |
1152 | { | |
1153 | public: | |
1154 | using usual_ax_binop_operation<BINOP_SUBSCRIPT, | |
1155 | eval_op_subscript>::usual_ax_binop_operation; | |
1156 | ||
1157 | value *evaluate_for_sizeof (struct expression *exp, | |
1158 | enum noside noside) override; | |
1159 | }; | |
1160 | ||
46916f2b TT |
1161 | /* Implementation of comparison operations. */ |
1162 | template<enum exp_opcode OP, binary_ftype FUNC> | |
1163 | class comparison_operation | |
1164 | : public usual_ax_binop_operation<OP, FUNC> | |
1165 | { | |
1166 | public: | |
1167 | ||
1168 | using usual_ax_binop_operation<OP, FUNC>::usual_ax_binop_operation; | |
1169 | ||
1170 | value *evaluate (struct type *expect_type, | |
1171 | struct expression *exp, | |
1172 | enum noside noside) override | |
1173 | { | |
1174 | value *lhs | |
1175 | = std::get<0> (this->m_storage)->evaluate (nullptr, exp, noside); | |
1176 | value *rhs | |
1177 | = std::get<1> (this->m_storage)->evaluate (value_type (lhs), exp, | |
1178 | noside); | |
1179 | return FUNC (expect_type, exp, noside, OP, lhs, rhs); | |
1180 | } | |
1181 | }; | |
1182 | ||
1183 | using equal_operation = comparison_operation<BINOP_EQUAL, eval_op_equal>; | |
1184 | using notequal_operation | |
1185 | = comparison_operation<BINOP_NOTEQUAL, eval_op_notequal>; | |
1186 | using less_operation = comparison_operation<BINOP_LESS, eval_op_less>; | |
1187 | using gtr_operation = comparison_operation<BINOP_GTR, eval_op_gtr>; | |
1188 | using geq_operation = comparison_operation<BINOP_GEQ, eval_op_geq>; | |
1189 | using leq_operation = comparison_operation<BINOP_LEQ, eval_op_leq>; | |
1190 | ||
e2803273 TT |
1191 | } /* namespace expr */ |
1192 | ||
1193 | #endif /* EXPOP_H */ |