]> sourceware.org Git - systemtap.git/blame - staptree.cxx
Refactor parser for target_symbol->components
[systemtap.git] / staptree.cxx
CommitLineData
56099f08 1// parse tree functions
482fe2af 2// Copyright (C) 2005-2009 Red Hat Inc.
69c68955
FCE
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
2f1a1aea 8
2b066ec1 9#include "config.h"
2f1a1aea
FCE
10#include "staptree.h"
11#include "parse.h"
72dbc915
FCE
12#include "util.h"
13
2f1a1aea 14#include <iostream>
56099f08 15#include <typeinfo>
d02548c0 16#include <sstream>
56099f08 17#include <cassert>
b2199bb3 18#include <cstring>
c3a3c0c9 19#include <vector>
66e00001 20#include <algorithm>
edc22ba9 21#include <cstring>
2f1a1aea 22
2b066ec1
FCE
23using namespace std;
24
2f1a1aea 25
c1d5f3f6 26
56099f08
FCE
27expression::expression ():
28 type (pe_unknown), tok (0)
29{
dff50e09 30}
56099f08
FCE
31
32
33expression::~expression ()
34{
35}
36
37
38statement::statement ():
39 tok (0)
40{
dff50e09 41}
56099f08
FCE
42
43
44statement::~statement ()
45{
46}
47
48
49symbol::symbol ():
50 referent (0)
51{
52}
53
54
55arrayindex::arrayindex ():
d02548c0 56 base (0)
56099f08
FCE
57{
58}
59
60
61functioncall::functioncall ():
62 referent (0)
63{
64}
65
66
67symboldecl::symboldecl ():
68 tok (0),
69 type (pe_unknown)
70{
dff50e09 71}
56099f08
FCE
72
73
74symboldecl::~symboldecl ()
75{
76}
77
a229fcd7
GH
78probe_point::probe_point (std::vector<component*> const & comps,
79 const token * t):
cbbe8080 80 components(comps), tok(t), optional (false), sufficient (false),
80342244 81 condition (0)
a229fcd7
GH
82{
83}
56099f08 84
1939ea32
FCE
85// NB: shallow-copy of compoonents & condition!
86probe_point::probe_point (const probe_point& pp):
87 components(pp.components), tok(pp.tok), optional (pp.optional), sufficient (pp.sufficient),
88 condition (pp.condition)
89{
90}
91
92
9c0c0e46 93probe_point::probe_point ():
80342244 94 tok (0), optional (false), sufficient (false), condition (0)
82919855
FCE
95{
96}
97
98
c1d5f3f6 99unsigned probe::last_probeidx = 0;
82919855 100probe::probe ():
5d23847d 101 body (0), tok (0)
9c0c0e46 102{
c1d5f3f6 103 this->name = string ("probe_") + lex_cast<string>(last_probeidx ++);
9c0c0e46
FCE
104}
105
106
107probe_point::component::component ():
108 arg (0)
109{
110}
111
112
dff50e09
FCE
113probe_point::component::component (std::string const & f, literal * a):
114 functor(f), arg(a)
a229fcd7
GH
115{
116}
117
118
2b066ec1 119vardecl::vardecl ():
ef474d24 120 arity (-1), maxsize(0), init(NULL)
56099f08
FCE
121{
122}
123
124
2b066ec1
FCE
125void
126vardecl::set_arity (int a)
56099f08 127{
d98d459c
GH
128 if (a < 0)
129 return;
8846477c 130
ef474d24 131 if ((arity != a && arity >= 0) || (a == 0 && maxsize > 0))
8846477c
FCE
132 throw semantic_error ("inconsistent arity", tok);
133
134 if (arity != a)
135 {
136 arity = a;
137 index_types.resize (arity);
138 for (int i=0; i<arity; i++)
139 index_types[i] = pe_unknown;
140 }
56099f08
FCE
141}
142
dff50e09 143bool
313b2f74
GH
144vardecl::compatible_arity (int a)
145{
ef474d24
JS
146 if (a == 0 && maxsize > 0)
147 return false;
d98d459c 148 if (arity == -1 || a == -1)
313b2f74
GH
149 return true;
150 return arity == a;
151}
152
56099f08
FCE
153
154functiondecl::functiondecl ():
155 body (0)
156{
157}
158
159
3a20432b 160literal_number::literal_number (int64_t v)
56099f08
FCE
161{
162 value = v;
163 type = pe_long;
164}
165
2f1a1aea 166
56099f08
FCE
167literal_string::literal_string (const string& v)
168{
169 value = v;
170 type = pe_string;
171}
172
173
174ostream&
175operator << (ostream& o, const exp_type& e)
176{
177 switch (e)
178 {
179 case pe_unknown: o << "unknown"; break;
180 case pe_long: o << "long"; break;
181 case pe_string: o << "string"; break;
182 case pe_stats: o << "stats"; break;
183 default: o << "???"; break;
184 }
185 return o;
186}
187
188
189// ------------------------------------------------------------------------
190// parse tree printing
191
cc9ee605 192ostream& operator << (ostream& o, const expression& k)
56099f08
FCE
193{
194 k.print (o);
195 return o;
196}
197
198
cc9ee605 199void literal_string::print (ostream& o) const
56099f08 200{
cc9ee605
FCE
201 o << '"';
202 for (unsigned i=0; i<value.size(); i++)
203 if (value[i] == '"') // or other escapeworthy characters?
204 o << '\\' << '"';
205 else
206 o << value[i];
207 o << '"';
56099f08
FCE
208}
209
f3c26ea5 210
cc9ee605 211void literal_number::print (ostream& o) const
56099f08
FCE
212{
213 o << value;
214}
215
216
cc9ee605 217void binary_expression::print (ostream& o) const
56099f08 218{
dff50e09
FCE
219 o << "(" << *left << ") "
220 << op
a9c62ac9 221 << " (" << *right << ")";
56099f08 222}
2f1a1aea
FCE
223
224
cc9ee605 225void unary_expression::print (ostream& o) const
2f1a1aea 226{
dff50e09 227 o << op << '(' << *operand << ")";
56099f08
FCE
228}
229
cc9ee605 230void array_in::print (ostream& o) const
69c68955
FCE
231{
232 o << "[";
233 for (unsigned i=0; i<operand->indexes.size(); i++)
234 {
235 if (i > 0) o << ", ";
236 operand->indexes[i]->print (o);
237 }
a9c62ac9
FCE
238 o << "] in ";
239 operand->base->print_indexable (o);
69c68955 240}
56099f08 241
cc9ee605 242void post_crement::print (ostream& o) const
56099f08 243{
dff50e09 244 o << '(' << *operand << ")" << op;
56099f08
FCE
245}
246
247
cc9ee605 248void ternary_expression::print (ostream& o) const
56099f08 249{
ae56fddd
FCE
250 o << "(" << *cond << ")?("
251 << *truevalue << "):("
dff50e09 252 << *falsevalue << ")";
56099f08
FCE
253}
254
255
cc9ee605 256void symbol::print (ostream& o) const
56099f08
FCE
257{
258 o << name;
259}
260
261
8eb285ac 262void target_symbol::print (ostream& o) const
d7f3e0c5 263{
03c75a4a
JS
264 if (addressof)
265 o << "&";
d7f3e0c5
GH
266 o << base_name;
267 for (unsigned i = 0; i < components.size(); ++i)
268 {
269 switch (components[i].first)
270 {
271 case comp_literal_array_index:
272 o << '[' << components[i].second << ']';
273 break;
246b383e 274 case comp_struct_member:
d7f3e0c5
GH
275 o << "->" << components[i].second;
276 break;
d7f3e0c5
GH
277 }
278 }
279}
280
281
8eb285ac 282void cast_op::print (ostream& o) const
9b5af295 283{
03c75a4a
JS
284 if (addressof)
285 o << "&";
9b5af295
JS
286 o << base_name << '(' << *operand;
287 o << ", " << lex_cast_qstring (type);
288 if (module.length() > 0)
289 o << ", " << lex_cast_qstring (module);
290 o << ')';
291 for (unsigned i = 0; i < components.size(); ++i)
292 {
293 switch (components[i].first)
294 {
295 case comp_literal_array_index:
296 o << '[' << components[i].second << ']';
297 break;
298 case comp_struct_member:
299 o << "->" << components[i].second;
300 break;
301 }
302 }
303}
304
305
cc9ee605 306void vardecl::print (ostream& o) const
56099f08
FCE
307{
308 o << name;
ef474d24
JS
309 if (maxsize > 0)
310 o << "[" << maxsize << "]";
bed7c0af 311 if (arity > 0 || index_types.size() > 0)
56099f08 312 o << "[...]";
9ba8c134
JS
313 if (init)
314 {
315 o << " = ";
316 init->print(o);
317 }
56099f08
FCE
318}
319
2f1a1aea 320
cc9ee605 321void vardecl::printsig (ostream& o) const
56099f08 322{
ef474d24
JS
323 o << name;
324 if (maxsize > 0)
325 o << "[" << maxsize << "]";
326 o << ":" << type;
56099f08 327 if (index_types.size() > 0)
2f1a1aea 328 {
56099f08
FCE
329 o << " [";
330 for (unsigned i=0; i<index_types.size(); i++)
331 o << (i>0 ? ", " : "") << index_types[i];
332 o << "]";
333 }
334}
335
336
cc9ee605 337void functiondecl::print (ostream& o) const
56099f08
FCE
338{
339 o << "function " << name << " (";
340 for (unsigned i=0; i<formal_args.size(); i++)
341 o << (i>0 ? ", " : "") << *formal_args[i];
342 o << ")" << endl;
343 body->print(o);
344}
345
346
cc9ee605 347void functiondecl::printsig (ostream& o) const
56099f08
FCE
348{
349 o << name << ":" << type << " (";
350 for (unsigned i=0; i<formal_args.size(); i++)
351 o << (i>0 ? ", " : "")
352 << *formal_args[i]
353 << ":"
354 << formal_args[i]->type;
355 o << ")";
356}
357
358
cc9ee605 359void arrayindex::print (ostream& o) const
56099f08 360{
a9c62ac9
FCE
361 base->print_indexable (o);
362 o << "[";
56099f08
FCE
363 for (unsigned i=0; i<indexes.size(); i++)
364 o << (i>0 ? ", " : "") << *indexes[i];
365 o << "]";
366}
367
368
cc9ee605 369void functioncall::print (ostream& o) const
56099f08
FCE
370{
371 o << function << "(";
372 for (unsigned i=0; i<args.size(); i++)
373 o << (i>0 ? ", " : "") << *args[i];
374 o << ")";
dff50e09 375}
56099f08
FCE
376
377
3cb17058
JS
378bool
379print_format::parse_print(const std::string &name,
32784362 380 bool &stream, bool &format, bool &delim, bool &newline, bool &_char)
3cb17058
JS
381{
382 const char *n = name.c_str();
383
384 stream = true;
32784362
MH
385 format = delim = newline = _char = false;
386
387 if (strcmp(n, "print_char") == 0)
388 {
389 _char = true;
390 return true;
391 }
3cb17058
JS
392
393 if (*n == 's')
394 {
395 stream = false;
396 ++n;
397 }
398
399 if (0 != strncmp(n, "print", 5))
400 return false;
401 n += 5;
402
403 if (*n == 'f')
404 {
405 format = true;
406 ++n;
407 }
408 else
409 {
410 if (*n == 'd')
411 {
412 delim = true;
413 ++n;
414 }
415
416 if (*n == 'l' && *(n+1) == 'n')
417 {
418 newline = true;
419 n += 2;
420 }
421 }
422
423 return (*n == '\0');
424}
425
426
dff50e09 427string
d02548c0
GH
428print_format::components_to_string(vector<format_component> const & components)
429{
430 ostringstream oss;
431
432 for (vector<format_component>::const_iterator i = components.begin();
433 i != components.end(); ++i)
434 {
435
436 assert (i->type != conv_unspecified);
437
438 if (i->type == conv_literal)
439 {
440 assert(!i->literal_string.empty());
441 for (string::const_iterator j = i->literal_string.begin();
442 j != i->literal_string.end(); ++j)
443 {
c4bb5be2 444 // See also: c_unparser::visit_literal_string and lex_cast_qstring
d02548c0
GH
445 if (*j == '%')
446 oss << '%';
c4bb5be2
FCE
447 else if(*j == '"')
448 oss << '\\';
d02548c0
GH
449 oss << *j;
450 }
451 }
452 else
453 {
454 oss << '%';
455
456 if (i->flags & static_cast<unsigned long>(fmt_flag_zeropad))
457 oss << '0';
458
459 if (i->flags & static_cast<unsigned long>(fmt_flag_plus))
460 oss << '+';
461
462 if (i->flags & static_cast<unsigned long>(fmt_flag_space))
463 oss << ' ';
464
465 if (i->flags & static_cast<unsigned long>(fmt_flag_left))
466 oss << '-';
467
468 if (i->flags & static_cast<unsigned long>(fmt_flag_special))
469 oss << '#';
470
34201621
DB
471 if (i->widthtype == width_dynamic)
472 oss << '*';
473 else if (i->widthtype != width_unspecified && i->width > 0)
d02548c0
GH
474 oss << i->width;
475
34201621
DB
476 if (i->prectype == prec_dynamic)
477 oss << ".*";
478 else if (i->prectype != prec_unspecified && i->precision > 0)
d02548c0
GH
479 oss << '.' << i->precision;
480
dff50e09 481 switch (i->type)
dc0b623a
MH
482 {
483 case conv_binary:
484 oss << "b";
485 break;
486
fecccf83
EB
487 case conv_char:
488 oss << "llc";
489 break;
490
d02548c0
GH
491 case conv_signed_decimal:
492 oss << "lld";
493 break;
494
495 case conv_unsigned_decimal:
496 oss << "llu";
497 break;
498
499 case conv_unsigned_octal:
500 oss << "llo";
501 break;
502
58cf0567
MH
503 case conv_unsigned_ptr:
504 oss << "p";
505 break;
506
d02548c0
GH
507 case conv_unsigned_uppercase_hex:
508 oss << "llX";
509 break;
510
511 case conv_unsigned_lowercase_hex:
512 oss << "llx";
513 break;
514
515 case conv_string:
516 oss << 's';
517 break;
dff50e09 518
34201621
DB
519 case conv_memory:
520 oss << 'm';
521 break;
dff50e09 522
30c94a80
EB
523 case conv_memory_hex:
524 oss << 'M';
525 break;
526
d02548c0
GH
527 default:
528 break;
529 }
530 }
531 }
532 return oss.str ();
533}
dff50e09
FCE
534
535vector<print_format::format_component>
d02548c0
GH
536print_format::string_to_components(string const & str)
537{
538 format_component curr;
539 vector<format_component> res;
540
d02548c0
GH
541 curr.clear();
542
543 string::const_iterator i = str.begin();
dff50e09 544
d02548c0
GH
545 while (i != str.end())
546 {
07c17d67 547 if (*i != '%')
d02548c0 548 {
07c17d67
GH
549 assert (curr.type == conv_unspecified || curr.type == conv_literal);
550 curr.type = conv_literal;
dc0b623a 551 curr.literal_string += *i;
d02548c0 552 ++i;
07c17d67
GH
553 continue;
554 }
555 else if (i+1 == str.end() || *(i+1) == '%')
556 {
557 assert(*i == '%');
558 // *i == '%' and *(i+1) == '%'; append only one '%' to the literal string
559 assert (curr.type == conv_unspecified || curr.type == conv_literal);
560 curr.type = conv_literal;
561 curr.literal_string += '%';
2a99f48f 562 i += 2;
07c17d67
GH
563 continue;
564 }
dff50e09 565 else
07c17d67
GH
566 {
567 assert(*i == '%');
568 if (curr.type != conv_unspecified)
d02548c0 569 {
07c17d67
GH
570 // Flush any component we were previously accumulating
571 assert (curr.type == conv_literal);
572 res.push_back(curr);
573 curr.clear();
574 }
575 }
576 ++i;
dff50e09 577
07c17d67
GH
578 if (i == str.end())
579 break;
d02548c0 580
dff50e09 581 // Now we are definitely parsing a conversion.
d898100a 582 // Begin by parsing flags (which are optional).
d02548c0 583
07c17d67
GH
584 switch (*i)
585 {
586 case '0':
587 curr.flags |= static_cast<unsigned long>(fmt_flag_zeropad);
588 ++i;
d02548c0 589 break;
dff50e09 590
07c17d67
GH
591 case '+':
592 curr.flags |= static_cast<unsigned long>(fmt_flag_plus);
593 ++i;
d02548c0 594 break;
dff50e09 595
07c17d67
GH
596 case '-':
597 curr.flags |= static_cast<unsigned long>(fmt_flag_left);
598 ++i;
d02548c0 599 break;
dff50e09 600
07c17d67
GH
601 case ' ':
602 curr.flags |= static_cast<unsigned long>(fmt_flag_space);
603 ++i;
604 break;
dff50e09 605
07c17d67
GH
606 case '#':
607 curr.flags |= static_cast<unsigned long>(fmt_flag_special);
608 ++i;
609 break;
dc0b623a 610
07c17d67
GH
611 default:
612 break;
613 }
d02548c0 614
34201621
DB
615 if (i == str.end())
616 break;
617
07c17d67 618 // Parse optional width
34201621 619 if (*i == '*')
07c17d67 620 {
34201621 621 curr.widthtype = width_dynamic;
07c17d67
GH
622 ++i;
623 }
34201621
DB
624 else if (isdigit(*i))
625 {
626 curr.widthtype = width_static;
627 curr.width = 0;
628 do
629 {
630 curr.width *= 10;
631 curr.width += (*i - '0');
632 ++i;
633 }
634 while (i != str.end() && isdigit(*i));
635 }
d02548c0 636
07c17d67
GH
637 if (i == str.end())
638 break;
d02548c0 639
07c17d67
GH
640 // Parse optional precision
641 if (*i == '.')
642 {
643 ++i;
644 if (i == str.end())
645 break;
34201621 646 if (*i == '*')
07c17d67 647 {
34201621 648 curr.prectype = prec_dynamic;
d02548c0 649 ++i;
07c17d67 650 }
34201621
DB
651 else if (isdigit(*i))
652 {
653 curr.prectype = prec_static;
654 curr.precision = 0;
655 do
656 {
657 curr.precision *= 10;
658 curr.precision += (*i - '0');
659 ++i;
660 }
661 while (i != str.end() && isdigit(*i));
662 }
07c17d67 663 }
d02548c0 664
07c17d67
GH
665 if (i == str.end())
666 break;
d02548c0 667
fecccf83 668 // Parse the actual conversion specifier (bcsmdioupxXn)
07c17d67
GH
669 switch (*i)
670 {
671 // Valid conversion types
dc0b623a
MH
672 case 'b':
673 curr.type = conv_binary;
674 break;
dff50e09 675
fecccf83
EB
676 case 'c':
677 curr.type = conv_char;
678 break;
679
07c17d67
GH
680 case 's':
681 curr.type = conv_string;
682 break;
dff50e09 683
34201621
DB
684 case 'm':
685 curr.type = conv_memory;
686 break;
dff50e09 687
30c94a80
EB
688 case 'M':
689 curr.type = conv_memory_hex;
690 break;
691
07c17d67
GH
692 case 'd':
693 case 'i':
694 curr.type = conv_signed_decimal;
695 break;
dff50e09 696
07c17d67
GH
697 case 'o':
698 curr.type = conv_unsigned_octal;
699 break;
dff50e09 700
07c17d67
GH
701 case 'u':
702 curr.type = conv_unsigned_decimal;
703 break;
dff50e09 704
58cf0567
MH
705 case 'p':
706 curr.type = conv_unsigned_ptr;
707 break;
708
07c17d67
GH
709 case 'X':
710 curr.type = conv_unsigned_uppercase_hex;
711 break;
dff50e09 712
07c17d67
GH
713 case 'x':
714 curr.type = conv_unsigned_lowercase_hex;
715 break;
dc0b623a 716
07c17d67 717 default:
d02548c0
GH
718 break;
719 }
dff50e09 720
07c17d67 721 if (curr.type == conv_unspecified)
a9c62ac9 722 throw parse_error("invalid or missing conversion specifier");
dff50e09 723
07c17d67 724 ++i;
dc0b623a 725 res.push_back(curr);
dff50e09 726 curr.clear();
d02548c0
GH
727 }
728
07c17d67
GH
729 // If there's a remaining partly-composed conversion, fail.
730 if (!curr.is_empty())
731 {
732 if (curr.type == conv_literal)
dff50e09 733 res.push_back(curr);
07c17d67 734 else
a9c62ac9 735 throw parse_error("trailing incomplete print format conversion");
07c17d67 736 }
d02548c0
GH
737
738 return res;
739}
740
741
742void print_format::print (ostream& o) const
743{
3cb17058 744 o << tok->content << "(";
d02548c0 745 if (print_with_format)
3cb17058
JS
746 o << lex_cast_qstring (raw_components);
747 if (print_with_delim)
748 o << lex_cast_qstring (delimiter.literal_string);
a9c62ac9
FCE
749 if (hist)
750 hist->print(o);
d02548c0
GH
751 for (vector<expression*>::const_iterator i = args.begin();
752 i != args.end(); ++i)
753 {
3cb17058 754 if (i != args.begin() || print_with_format || print_with_delim)
d02548c0
GH
755 o << ", ";
756 (*i)->print(o);
757 }
758 o << ")";
759}
760
761void stat_op::print (ostream& o) const
762{
763 o << '@';
764 switch (ctype)
765 {
766 case sc_average:
767 o << "avg(";
768 break;
769
770 case sc_count:
771 o << "count(";
772 break;
773
774 case sc_sum:
775 o << "sum(";
776 break;
777
778 case sc_min:
779 o << "min(";
780 break;
dff50e09 781
d02548c0
GH
782 case sc_max:
783 o << "max(";
784 break;
785 }
786 stat->print(o);
787 o << ")";
788}
789
dff50e09 790void
d02548c0
GH
791hist_op::print (ostream& o) const
792{
793 o << '@';
794 switch (htype)
795 {
796 case hist_linear:
797 assert(params.size() == 3);
798 o << "hist_linear(";
799 stat->print(o);
800 for (size_t i = 0; i < params.size(); ++i)
801 {
802 o << ", " << params[i];
803 }
804 o << ")";
805 break;
806
807 case hist_log:
e38723d2 808 assert(params.size() == 0);
d02548c0
GH
809 o << "hist_log(";
810 stat->print(o);
d02548c0
GH
811 o << ")";
812 break;
813 }
814}
815
cc9ee605 816ostream& operator << (ostream& o, const statement& k)
56099f08
FCE
817{
818 k.print (o);
819 return o;
820}
821
822
cc9ee605 823void embeddedcode::print (ostream &o) const
54dfabe9
FCE
824{
825 o << "%{";
826 o << code;
827 o << "%}";
828}
829
cc9ee605 830void block::print (ostream& o) const
56099f08
FCE
831{
832 o << "{" << endl;
833 for (unsigned i=0; i<statements.size(); i++)
69c68955 834 o << *statements [i] << endl;
bb2e3076 835 o << "}";
56099f08
FCE
836}
837
ba6f838d
FCE
838block::block (statement* car, statement* cdr)
839{
840 statements.push_back(car);
841 statements.push_back(cdr);
842 this->tok = car->tok;
843}
844
845
56099f08 846
cc9ee605 847void for_loop::print (ostream& o) const
56099f08 848{
f3c26ea5 849 o << "for (";
cbfbbf69 850 if (init) init->print (o);
f3c26ea5
FCE
851 o << "; ";
852 cond->print (o);
853 o << "; ";
cbfbbf69 854 if (incr) incr->print (o);
bb2e3076 855 o << ") ";
f3c26ea5 856 block->print (o);
56099f08
FCE
857}
858
859
cc9ee605 860void foreach_loop::print (ostream& o) const
69c68955
FCE
861{
862 o << "foreach ([";
863 for (unsigned i=0; i<indexes.size(); i++)
864 {
865 if (i > 0) o << ", ";
866 indexes[i]->print (o);
93484556
FCE
867 if (sort_direction != 0 && sort_column == i+1)
868 o << (sort_direction > 0 ? "+" : "-");
69c68955 869 }
a9c62ac9
FCE
870 o << "] in ";
871 base->print_indexable (o);
93484556
FCE
872 if (sort_direction != 0 && sort_column == 0)
873 o << (sort_direction > 0 ? "+" : "-");
27f21e8c
DS
874 if (limit)
875 {
876 o << " limit ";
877 limit->print (o);
878 }
93484556 879 o << ") ";
69c68955
FCE
880 block->print (o);
881}
882
883
cc9ee605 884void null_statement::print (ostream& o) const
56099f08 885{
dff50e09 886 o << ";";
56099f08
FCE
887}
888
889
cc9ee605 890void expr_statement::print (ostream& o) const
56099f08
FCE
891{
892 o << *value;
893}
894
895
cc9ee605 896void return_statement::print (ostream& o) const
56099f08
FCE
897{
898 o << "return " << *value;
899}
900
901
cc9ee605 902void delete_statement::print (ostream& o) const
56099f08
FCE
903{
904 o << "delete " << *value;
905}
906
cc9ee605 907void next_statement::print (ostream& o) const
f3c26ea5
FCE
908{
909 o << "next";
910}
911
cc9ee605 912void break_statement::print (ostream& o) const
f3c26ea5
FCE
913{
914 o << "break";
915}
916
cc9ee605 917void continue_statement::print (ostream& o) const
f3c26ea5
FCE
918{
919 o << "continue";
920}
56099f08 921
cc9ee605 922void if_statement::print (ostream& o) const
56099f08 923{
bb2e3076 924 o << "if (" << *condition << ") "
56099f08
FCE
925 << *thenblock << endl;
926 if (elseblock)
927 o << "else " << *elseblock << endl;
928}
929
930
cc9ee605 931void stapfile::print (ostream& o) const
56099f08
FCE
932{
933 o << "# file " << name << endl;
934
54dfabe9
FCE
935 for (unsigned i=0; i<embeds.size(); i++)
936 embeds[i]->print (o);
937
bed7c0af
FCE
938 for (unsigned i=0; i<globals.size(); i++)
939 {
940 o << "global ";
941 globals[i]->print (o);
942 o << endl;
943 }
944
20c6c071
GH
945 for (unsigned i=0; i<aliases.size(); i++)
946 {
947 aliases[i]->print (o);
948 o << endl;
949 }
950
bed7c0af 951 for (unsigned i=0; i<probes.size(); i++)
56099f08
FCE
952 {
953 probes[i]->print (o);
954 o << endl;
955 }
956
957 for (unsigned j = 0; j < functions.size(); j++)
958 {
959 functions[j]->print (o);
960 o << endl;
961 }
962}
963
964
cc9ee605 965void probe::print (ostream& o) const
56099f08
FCE
966{
967 o << "probe ";
40a1cb62
FCE
968 printsig (o);
969 o << *body;
970}
971
972
cc9ee605 973void probe::printsig (ostream& o) const
40a1cb62 974{
77b2151e
DB
975 const probe_alias *alias = get_alias ();
976 if (alias)
977 {
978 alias->printsig (o);
979 return;
980 }
dff50e09 981
9c0c0e46 982 for (unsigned i=0; i<locations.size(); i++)
56099f08 983 {
65aeaea0 984 if (i > 0) o << ",";
9c0c0e46 985 locations[i]->print (o);
56099f08 986 }
56099f08
FCE
987}
988
989
c3a3c0c9 990void
2c5a19c6 991probe::collect_derivation_chain (std::vector<probe*> &probes_list)
c3a3c0c9 992{
2c5a19c6 993 probes_list.push_back(this);
c3a3c0c9
WC
994}
995
996
cc9ee605 997void probe_point::print (ostream& o) const
56099f08 998{
9c0c0e46
FCE
999 for (unsigned i=0; i<components.size(); i++)
1000 {
1001 if (i>0) o << ".";
1002 probe_point::component* c = components[i];
1003 o << c->functor;
1004 if (c->arg)
1005 o << "(" << *c->arg << ")";
1006 }
d898100a
FCE
1007 if (sufficient)
1008 o << "!";
1009 else if (optional) // sufficient implies optional
6e3347a9 1010 o << "?";
cbbe8080
MH
1011 if (condition)
1012 o<< " if (" << *condition << ")";
c3a3c0c9
WC
1013}
1014
1015string probe_point::str ()
1016{
1017 ostringstream o;
1018 for (unsigned i=0; i<components.size(); i++)
1019 {
1020 if (i>0) o << ".";
1021 probe_point::component* c = components[i];
1022 o << c->functor;
1023 if (c->arg)
1024 o << "(" << *c->arg << ")";
1025 }
d898100a
FCE
1026 if (sufficient)
1027 o << "!";
1028 else if (optional) // sufficient implies optional
c3a3c0c9 1029 o << "?";
cbbe8080
MH
1030 if (condition)
1031 o<< " if (" << *condition << ")";
c3a3c0c9 1032 return o.str();
56099f08
FCE
1033}
1034
cc9ee605 1035
20c6c071
GH
1036probe_alias::probe_alias(std::vector<probe_point*> const & aliases):
1037 probe (), alias_names (aliases)
1038{
1039}
1040
cc9ee605 1041void probe_alias::printsig (ostream& o) const
20c6c071
GH
1042{
1043 for (unsigned i=0; i<alias_names.size(); i++)
1044 {
1045 o << (i>0 ? " = " : "");
1046 alias_names[i]->print (o);
1047 }
5227f1ea 1048 o << " = ";
20c6c071
GH
1049 for (unsigned i=0; i<locations.size(); i++)
1050 {
d898100a 1051 if (i > 0) o << ", ";
20c6c071
GH
1052 locations[i]->print (o);
1053 }
1054}
1055
56099f08 1056
cc9ee605 1057ostream& operator << (ostream& o, const probe_point& k)
82919855
FCE
1058{
1059 k.print (o);
1060 return o;
1061}
1062
1063
cc9ee605 1064ostream& operator << (ostream& o, const symboldecl& k)
56099f08
FCE
1065{
1066 k.print (o);
1067 return o;
1068}
1069
1070
82919855
FCE
1071
1072// ------------------------------------------------------------------------
1073// visitors
1074
1075
1076void
1077block::visit (visitor* u)
1078{
1079 u->visit_block (this);
1080}
1081
54dfabe9
FCE
1082
1083void
1084embeddedcode::visit (visitor* u)
1085{
1086 u->visit_embeddedcode (this);
1087}
1088
1089
82919855
FCE
1090void
1091for_loop::visit (visitor* u)
1092{
1093 u->visit_for_loop (this);
1094}
1095
69c68955
FCE
1096void
1097foreach_loop::visit (visitor* u)
1098{
1099 u->visit_foreach_loop (this);
1100}
1101
82919855
FCE
1102void
1103null_statement::visit (visitor* u)
1104{
1105 u->visit_null_statement (this);
1106}
1107
1108void
1109expr_statement::visit (visitor* u)
1110{
1111 u->visit_expr_statement (this);
1112}
1113
1114void
1115return_statement::visit (visitor* u)
1116{
1117 u->visit_return_statement (this);
1118}
1119
1120void
1121delete_statement::visit (visitor* u)
1122{
d7f3e0c5 1123 u->push_active_lvalue (this->value);
82919855 1124 u->visit_delete_statement (this);
d7f3e0c5 1125 u->pop_active_lvalue ();
82919855
FCE
1126}
1127
1128void
1129if_statement::visit (visitor* u)
1130{
1131 u->visit_if_statement (this);
1132}
1133
f3c26ea5
FCE
1134void
1135next_statement::visit (visitor* u)
1136{
1137 u->visit_next_statement (this);
1138}
1139
1140void
1141break_statement::visit (visitor* u)
1142{
1143 u->visit_break_statement (this);
1144}
1145
1146void
1147continue_statement::visit (visitor* u)
1148{
1149 u->visit_continue_statement (this);
1150}
1151
82919855
FCE
1152void
1153literal_string::visit(visitor* u)
1154{
1155 u->visit_literal_string (this);
1156}
1157
1158void
1159literal_number::visit(visitor* u)
1160{
1161 u->visit_literal_number (this);
1162}
1163
1164void
1165binary_expression::visit (visitor* u)
1166{
1167 u->visit_binary_expression (this);
1168}
1169
1170void
1171unary_expression::visit (visitor* u)
1172{
1173 u->visit_unary_expression (this);
1174}
1175
1176void
1177pre_crement::visit (visitor* u)
1178{
d7f3e0c5 1179 u->push_active_lvalue (this->operand);
82919855 1180 u->visit_pre_crement (this);
d7f3e0c5 1181 u->pop_active_lvalue ();
82919855
FCE
1182}
1183
1184void
1185post_crement::visit (visitor* u)
1186{
d7f3e0c5 1187 u->push_active_lvalue (this->operand);
82919855 1188 u->visit_post_crement (this);
d7f3e0c5 1189 u->pop_active_lvalue ();
82919855
FCE
1190}
1191
1192void
1193logical_or_expr::visit (visitor* u)
1194{
1195 u->visit_logical_or_expr (this);
1196}
1197
1198void
1199logical_and_expr::visit (visitor* u)
1200{
1201 u->visit_logical_and_expr (this);
1202}
1203
1204void
1205array_in::visit (visitor* u)
1206{
1207 u->visit_array_in (this);
1208}
1209
1210void
1211comparison::visit (visitor* u)
1212{
1213 u->visit_comparison (this);
1214}
1215
1216void
1217concatenation::visit (visitor* u)
1218{
1219 u->visit_concatenation (this);
1220}
1221
82919855
FCE
1222void
1223ternary_expression::visit (visitor* u)
1224{
1225 u->visit_ternary_expression (this);
1226}
1227
1228void
1229assignment::visit (visitor* u)
1230{
d7f3e0c5 1231 u->push_active_lvalue (this->left);
82919855 1232 u->visit_assignment (this);
d7f3e0c5 1233 u->pop_active_lvalue ();
82919855
FCE
1234}
1235
1236void
1237symbol::visit (visitor* u)
1238{
1239 u->visit_symbol (this);
1240}
1241
dff50e09 1242void
d7f3e0c5
GH
1243target_symbol::visit (visitor* u)
1244{
1245 u->visit_target_symbol(this);
1246}
1247
9b5af295
JS
1248void
1249cast_op::visit (visitor* u)
1250{
1251 u->visit_cast_op(this);
1252}
1253
82919855
FCE
1254void
1255arrayindex::visit (visitor* u)
1256{
1257 u->visit_arrayindex (this);
1258}
1259
1260void
1261functioncall::visit (visitor* u)
1262{
1263 u->visit_functioncall (this);
1264}
1265
d02548c0
GH
1266void
1267print_format::visit (visitor *u)
1268{
1269 u->visit_print_format (this);
1270}
1271
1272void
1273stat_op::visit (visitor *u)
1274{
1275 u->visit_stat_op (this);
1276}
1277
1278void
1279hist_op::visit (visitor *u)
1280{
1281 u->visit_hist_op (this);
1282}
1283
dff50e09 1284void
d02548c0
GH
1285indexable::print_indexable (std::ostream& o) const
1286{
1287 const symbol *sym;
1288 const hist_op *hist;
1289 classify_const_indexable(this, sym, hist);
1290 if (sym)
1291 sym->print (o);
1292 else
1293 {
1294 assert (hist);
1295 hist->print (o);
dff50e09 1296 }
d02548c0
GH
1297}
1298
dff50e09 1299void
d02548c0
GH
1300indexable::visit_indexable (visitor* u)
1301{
1302 symbol *sym;
1303 hist_op *hist;
1304 classify_indexable(this, sym, hist);
1305 if (sym)
1306 sym->visit (u);
1307 else
1308 {
1309 assert (hist);
1310 hist->visit (u);
1311 }
1312}
1313
1314
dff50e09 1315bool
d02548c0
GH
1316indexable::is_symbol(symbol *& sym_out)
1317{
1318 sym_out = NULL;
1319 return false;
1320}
1321
dff50e09 1322bool
d02548c0
GH
1323indexable::is_hist_op(hist_op *& hist_out)
1324{
1325 hist_out = NULL;
1326 return false;
1327}
1328
dff50e09 1329bool
d02548c0
GH
1330indexable::is_const_symbol(const symbol *& sym_out) const
1331{
1332 sym_out = NULL;
1333 return false;
1334}
1335
dff50e09 1336bool
d02548c0
GH
1337indexable::is_const_hist_op(const hist_op *& hist_out) const
1338{
1339 hist_out = NULL;
1340 return false;
1341}
1342
dff50e09 1343bool
d02548c0
GH
1344symbol::is_symbol(symbol *& sym_out)
1345{
1346 sym_out = this;
1347 return true;
1348}
1349
dff50e09 1350bool
d02548c0
GH
1351symbol::is_const_symbol(const symbol *& sym_out) const
1352{
1353 sym_out = this;
1354 return true;
1355}
1356
1357const token *
1358symbol::get_tok() const
1359{
1360 return tok;
1361}
1362
dff50e09 1363bool
d02548c0
GH
1364hist_op::is_hist_op(hist_op *& hist_out)
1365{
1366 hist_out = this;
1367 return true;
1368}
1369
dff50e09 1370bool
d02548c0
GH
1371hist_op::is_const_hist_op(const hist_op *& hist_out) const
1372{
1373 hist_out = this;
1374 return true;
1375}
1376
1377const token *
1378hist_op::get_tok() const
1379{
1380 return tok;
1381}
1382
1383void
1384classify_indexable(indexable* ix,
1385 symbol *& array_out,
dff50e09 1386 hist_op *& hist_out)
d02548c0
GH
1387{
1388 array_out = NULL;
1389 hist_out = NULL;
1390 if (!(ix->is_symbol (array_out) || ix->is_hist_op (hist_out)))
1391 throw semantic_error("Expecting symbol or histogram operator", ix->get_tok());
1392 if (ix && !(hist_out || array_out))
1393 throw semantic_error("Failed to classify indexable", ix->get_tok());
1394}
1395
1396void
1397classify_const_indexable(const indexable* ix,
1398 const symbol *& array_out,
dff50e09 1399 const hist_op *& hist_out)
d02548c0
GH
1400{
1401 array_out = NULL;
1402 hist_out = NULL;
1403 if (!(ix->is_const_symbol(array_out) || ix->is_const_hist_op(hist_out)))
1404 throw semantic_error("Expecting symbol or histogram operator", ix->get_tok());
1405}
1406
d7f3e0c5
GH
1407// ------------------------------------------------------------------------
1408
dff50e09 1409bool
d7f3e0c5
GH
1410visitor::is_active_lvalue(expression *e)
1411{
1412 for (unsigned i = 0; i < active_lvalues.size(); ++i)
1413 {
1414 if (active_lvalues[i] == e)
1415 return true;
1416 }
1417 return false;
1418}
1419
dff50e09 1420void
d7f3e0c5
GH
1421visitor::push_active_lvalue(expression *e)
1422{
1423 active_lvalues.push_back(e);
1424}
1425
dff50e09 1426void
d7f3e0c5
GH
1427visitor::pop_active_lvalue()
1428{
1429 assert(!active_lvalues.empty());
1430 active_lvalues.pop_back();
1431}
1432
1433
82919855
FCE
1434
1435// ------------------------------------------------------------------------
1436
1437void
54dfabe9 1438traversing_visitor::visit_block (block* s)
82919855
FCE
1439{
1440 for (unsigned i=0; i<s->statements.size(); i++)
1441 s->statements[i]->visit (this);
1442}
1443
1444void
78f6bba6 1445traversing_visitor::visit_embeddedcode (embeddedcode*)
54dfabe9
FCE
1446{
1447}
1448
1449void
78f6bba6 1450traversing_visitor::visit_null_statement (null_statement*)
82919855
FCE
1451{
1452}
1453
1454void
54dfabe9 1455traversing_visitor::visit_expr_statement (expr_statement* s)
82919855
FCE
1456{
1457 s->value->visit (this);
1458}
1459
1460void
1461traversing_visitor::visit_if_statement (if_statement* s)
1462{
1463 s->condition->visit (this);
1464 s->thenblock->visit (this);
2b066ec1
FCE
1465 if (s->elseblock)
1466 s->elseblock->visit (this);
82919855
FCE
1467}
1468
1469void
1470traversing_visitor::visit_for_loop (for_loop* s)
1471{
cbfbbf69 1472 if (s->init) s->init->visit (this);
82919855 1473 s->cond->visit (this);
cbfbbf69 1474 if (s->incr) s->incr->visit (this);
82919855
FCE
1475 s->block->visit (this);
1476}
1477
69c68955
FCE
1478void
1479traversing_visitor::visit_foreach_loop (foreach_loop* s)
1480{
dff50e09 1481 symbol *array = NULL;
71572ba8
GH
1482 hist_op *hist = NULL;
1483 classify_indexable (s->base, array, hist);
1484 if (array)
1485 array->visit(this);
1486 else
1487 hist->visit(this);
1488
69c68955
FCE
1489 for (unsigned i=0; i<s->indexes.size(); i++)
1490 s->indexes[i]->visit (this);
27f21e8c
DS
1491
1492 if (s->limit)
1493 s->limit->visit (this);
1494
69c68955
FCE
1495 s->block->visit (this);
1496}
1497
82919855
FCE
1498void
1499traversing_visitor::visit_return_statement (return_statement* s)
1500{
1501 s->value->visit (this);
1502}
1503
1504void
1505traversing_visitor::visit_delete_statement (delete_statement* s)
1506{
1507 s->value->visit (this);
1508}
1509
f3c26ea5 1510void
78f6bba6 1511traversing_visitor::visit_next_statement (next_statement*)
f3c26ea5
FCE
1512{
1513}
1514
1515void
78f6bba6 1516traversing_visitor::visit_break_statement (break_statement*)
f3c26ea5
FCE
1517{
1518}
1519
1520void
78f6bba6 1521traversing_visitor::visit_continue_statement (continue_statement*)
f3c26ea5
FCE
1522{
1523}
1524
82919855 1525void
78f6bba6 1526traversing_visitor::visit_literal_string (literal_string*)
82919855
FCE
1527{
1528}
1529
1530void
78f6bba6 1531traversing_visitor::visit_literal_number (literal_number*)
82919855
FCE
1532{
1533}
1534
1535void
1536traversing_visitor::visit_binary_expression (binary_expression* e)
1537{
1538 e->left->visit (this);
1539 e->right->visit (this);
1540}
1541
1542void
1543traversing_visitor::visit_unary_expression (unary_expression* e)
1544{
1545 e->operand->visit (this);
1546}
1547
1548void
1549traversing_visitor::visit_pre_crement (pre_crement* e)
1550{
1551 e->operand->visit (this);
1552}
1553
1554void
1555traversing_visitor::visit_post_crement (post_crement* e)
1556{
1557 e->operand->visit (this);
1558}
1559
1560
1561void
1562traversing_visitor::visit_logical_or_expr (logical_or_expr* e)
1563{
1564 e->left->visit (this);
1565 e->right->visit (this);
1566}
1567
1568void
1569traversing_visitor::visit_logical_and_expr (logical_and_expr* e)
1570{
1571 e->left->visit (this);
1572 e->right->visit (this);
1573}
1574
1575void
1576traversing_visitor::visit_array_in (array_in* e)
1577{
ce10591c 1578 e->operand->visit (this);
82919855
FCE
1579}
1580
1581void
1582traversing_visitor::visit_comparison (comparison* e)
1583{
1584 e->left->visit (this);
1585 e->right->visit (this);
1586}
1587
1588void
1589traversing_visitor::visit_concatenation (concatenation* e)
1590{
1591 e->left->visit (this);
1592 e->right->visit (this);
1593}
1594
82919855
FCE
1595void
1596traversing_visitor::visit_ternary_expression (ternary_expression* e)
1597{
1598 e->cond->visit (this);
1599 e->truevalue->visit (this);
1600 e->falsevalue->visit (this);
1601}
1602
1603void
1604traversing_visitor::visit_assignment (assignment* e)
1605{
1606 e->left->visit (this);
1607 e->right->visit (this);
1608}
1609
1610void
78f6bba6 1611traversing_visitor::visit_symbol (symbol*)
82919855
FCE
1612{
1613}
1614
d7f3e0c5 1615void
78f6bba6 1616traversing_visitor::visit_target_symbol (target_symbol*)
d7f3e0c5
GH
1617{
1618}
1619
9b5af295
JS
1620void
1621traversing_visitor::visit_cast_op (cast_op* e)
1622{
1623 e->operand->visit (this);
1624}
1625
82919855
FCE
1626void
1627traversing_visitor::visit_arrayindex (arrayindex* e)
1628{
cbfbbf69
FCE
1629 for (unsigned i=0; i<e->indexes.size(); i++)
1630 e->indexes[i]->visit (this);
1631
1bbeef03
GH
1632 symbol *array = NULL;
1633 hist_op *hist = NULL;
1634 classify_indexable(e->base, array, hist);
1635 if (array)
1636 return array->visit(this);
1637 else
1638 return hist->visit(this);
82919855
FCE
1639}
1640
1641void
1642traversing_visitor::visit_functioncall (functioncall* e)
1643{
1644 for (unsigned i=0; i<e->args.size(); i++)
1645 e->args[i]->visit (this);
1646}
1647
d02548c0
GH
1648void
1649traversing_visitor::visit_print_format (print_format* e)
1650{
1651 for (unsigned i=0; i<e->args.size(); i++)
1652 e->args[i]->visit (this);
a4636912
GH
1653 if (e->hist)
1654 e->hist->visit(this);
d02548c0
GH
1655}
1656
1657void
1658traversing_visitor::visit_stat_op (stat_op* e)
1659{
1660 e->stat->visit (this);
1661}
1662
1663void
1664traversing_visitor::visit_hist_op (hist_op* e)
1665{
1666 e->stat->visit (this);
1667}
1668
82919855 1669
cbfbbf69 1670void
dff50e09 1671functioncall_traversing_visitor::visit_functioncall (functioncall* e)
cbfbbf69
FCE
1672{
1673 traversing_visitor::visit_functioncall (e);
1674
1675 // prevent infinite recursion
1676 if (traversed.find (e->referent) == traversed.end ())
1677 {
1678 traversed.insert (e->referent);
1679 // recurse
3066c15c
FCE
1680 functiondecl* last_current_function = current_function;
1681 current_function = e->referent;
cbfbbf69 1682 e->referent->body->visit (this);
3066c15c 1683 current_function = last_current_function;
cbfbbf69
FCE
1684 }
1685}
1686
1687
1688void
1689varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s)
1690{
1b07c728
FCE
1691 // We want to elide embedded-C functions when possible. For
1692 // example, each $target variable access is expanded to an
1693 // embedded-C function call. Yet, for safety reasons, we should
1694 // presume that embedded-C functions have intentional side-effects.
1695 //
1696 // To tell these two types of functions apart, we apply a
1697 // Kludge(tm): we look for a magic string within the function body.
1698 // $target variables as rvalues will have this; lvalues won't.
1699 // Also, explicit side-effect-free tapset functions will have this.
dff50e09 1700
3066c15c 1701 assert (current_function); // only they get embedded code
1b07c728 1702 if (s->code.find ("/* pure */") != string::npos)
3066c15c
FCE
1703 return;
1704
cbfbbf69
FCE
1705 embedded_seen = true;
1706}
1707
b0be9bdb
FCE
1708void
1709varuse_collecting_visitor::visit_target_symbol (target_symbol *e)
1710{
1711 // Still-unresolved target symbol assignments get treated as
1712 // generating side-effects like embedded-C, to prevent premature
1713 // elision and later error message suppression (PR5516). rvalue use
1714 // of unresolved target symbols is OTOH not considered a side-effect.
1715
1716 if (is_active_lvalue (e))
1717 embedded_seen = true;
1718}
cbfbbf69 1719
9b5af295
JS
1720void
1721varuse_collecting_visitor::visit_cast_op (cast_op *e)
1722{
1723 // As with target_symbols, unresolved cast assignments need to preserved
1724 // for later error handling.
1725 if (is_active_lvalue (e))
1726 embedded_seen = true;
1727
1728 functioncall_traversing_visitor::visit_cast_op (e);
1729}
1730
cbfbbf69
FCE
1731void
1732varuse_collecting_visitor::visit_print_format (print_format* e)
1733{
1734 // NB: Instead of being top-level statements, "print" and "printf"
1735 // are implemented as statement-expressions containing a
1736 // print_format. They have side-effects, but not via the
dff50e09 1737 // embedded-code detection method above.
1b07c728
FCE
1738 //
1739 // But sprint and sprintf don't have side-effects.
1740
1741 if (e->print_to_stream)
1742 embedded_seen = true; // a proxy for "has unknown side-effects"
1743
cbfbbf69
FCE
1744 functioncall_traversing_visitor::visit_print_format (e);
1745}
1746
1747
1748void
1749varuse_collecting_visitor::visit_assignment (assignment *e)
1750{
1751 if (e->op == "=" || e->op == "<<<") // pure writes
1752 {
3066c15c 1753 expression* last_lvalue = current_lvalue;
cbfbbf69
FCE
1754 current_lvalue = e->left; // leave a mark for ::visit_symbol
1755 functioncall_traversing_visitor::visit_assignment (e);
1756 current_lvalue = last_lvalue;
1757 }
1758 else // read-modify-writes
1759 {
1760 expression* last_lrvalue = current_lrvalue;
1761 current_lrvalue = e->left; // leave a mark for ::visit_symbol
1762 functioncall_traversing_visitor::visit_assignment (e);
1763 current_lrvalue = last_lrvalue;
1764 }
1765}
1766
1767void
1768varuse_collecting_visitor::visit_symbol (symbol *e)
1769{
1770 if (e->referent == 0)
1771 throw semantic_error ("symbol without referent", e->tok);
1772
d0c4107b
FCE
1773 // We could handle initialized globals by marking them as "written".
1774 // However, this current visitor may be called for a function or
1775 // probe body, from the point of view of which this global is
1776 // already initialized, so not written.
1777 /*
27d24ae2
FCE
1778 if (e->referent->init)
1779 written.insert (e->referent);
d0c4107b 1780 */
27d24ae2 1781
cbfbbf69
FCE
1782 if (current_lvalue == e || current_lrvalue == e)
1783 {
1784 written.insert (e->referent);
1785 // clog << "write ";
1786 }
1787 if (current_lvalue != e || current_lrvalue == e)
1788 {
1789 read.insert (e->referent);
1790 // clog << "read ";
1791 }
1792 // clog << *e->tok << endl;
1793}
1794
1795// NB: stat_op need not be overridden, since it will get to
1796// visit_symbol and only as a possible rvalue.
1797
d20fd9e9 1798
cbfbbf69
FCE
1799void
1800varuse_collecting_visitor::visit_arrayindex (arrayindex *e)
1801{
1802 // Hooking this callback is necessary because of the hacky
1803 // statistics representation. For the expression "i[4] = 5", the
1804 // incoming lvalue will point to this arrayindex. However, the
1805 // symbol corresponding to the "i[4]" is multiply inherited with
1806 // arrayindex. If the symbol base part of this object is not at
1807 // offset 0, then static_cast<symbol*>(e) may result in a different
1808 // address, and not match lvalue by number when we recurse that way.
1809 // So we explicitly override the incoming lvalue/lrvalue values to
1810 // point at the embedded objects' actual base addresses.
1811
1812 expression* last_lrvalue = current_lrvalue;
1813 expression* last_lvalue = current_lvalue;
1814
1815 symbol *array = NULL;
1816 hist_op *hist = NULL;
1817 classify_indexable(e->base, array, hist);
1818
1819 if (array)
1820 {
1821 if (current_lrvalue == e) current_lrvalue = array;
1822 if (current_lvalue == e) current_lvalue = array;
1823 functioncall_traversing_visitor::visit_arrayindex (e);
1824 }
1825 else // if (hist)
1826 {
1827 if (current_lrvalue == e) current_lrvalue = hist->stat;
1828 if (current_lvalue == e) current_lvalue = hist->stat;
1829 functioncall_traversing_visitor::visit_arrayindex (e);
1830 }
1831
1832 current_lrvalue = last_lrvalue;
1833 current_lvalue = last_lvalue;
1834}
1835
1836
1837void
1838varuse_collecting_visitor::visit_pre_crement (pre_crement *e)
1839{
1840 expression* last_lrvalue = current_lrvalue;
1841 current_lrvalue = e->operand; // leave a mark for ::visit_symbol
1842 functioncall_traversing_visitor::visit_pre_crement (e);
1843 current_lrvalue = last_lrvalue;
1844}
1845
1846void
1847varuse_collecting_visitor::visit_post_crement (post_crement *e)
1848{
1849 expression* last_lrvalue = current_lrvalue;
1850 current_lrvalue = e->operand; // leave a mark for ::visit_symbol
1851 functioncall_traversing_visitor::visit_post_crement (e);
1852 current_lrvalue = last_lrvalue;
1853}
1854
3066c15c
FCE
1855void
1856varuse_collecting_visitor::visit_foreach_loop (foreach_loop* s)
1857{
27d24ae2
FCE
1858 // NB: we duplicate so don't bother call
1859 // functioncall_traversing_visitor::visit_foreach_loop (s);
1860
dff50e09 1861 symbol *array = NULL;
27d24ae2
FCE
1862 hist_op *hist = NULL;
1863 classify_indexable (s->base, array, hist);
1864 if (array)
1865 array->visit(this);
1866 else
1867 hist->visit(this);
1868
3066c15c 1869 // If the collection is sorted, imply a "write" access to the
27d24ae2 1870 // array in addition to the "read" one already noted above.
3066c15c
FCE
1871 if (s->sort_direction)
1872 {
dff50e09 1873 symbol *array = NULL;
3066c15c
FCE
1874 hist_op *hist = NULL;
1875 classify_indexable (s->base, array, hist);
1876 if (array) this->written.insert (array->referent);
1877 // XXX: Can hist_op iterations be sorted?
1878 }
27d24ae2
FCE
1879
1880 // NB: don't forget to visit the index expressions, which are lvalues.
1881 for (unsigned i=0; i<s->indexes.size(); i++)
1882 {
1883 expression* last_lvalue = current_lvalue;
1884 current_lvalue = s->indexes[i]; // leave a mark for ::visit_symbol
1885 s->indexes[i]->visit (this);
1886 current_lvalue = last_lvalue;
1887 }
1888
1889 if (s->limit)
1890 s->limit->visit (this);
1891
1892 s->block->visit (this);
3066c15c 1893}
cbfbbf69
FCE
1894
1895
3066c15c
FCE
1896void
1897varuse_collecting_visitor::visit_delete_statement (delete_statement* s)
1898{
1899 // Ideally, this would be treated like an assignment: a plain write
1900 // to the underlying value ("lvalue"). XXX: However, the
1901 // optimization pass is not smart enough to remove an unneeded
1902 // "delete" yet, so we pose more like a *crement ("lrvalue"). This
1903 // should protect the underlying value from optimizional mischief.
1904 expression* last_lrvalue = current_lrvalue;
1905 current_lrvalue = s->value; // leave a mark for ::visit_symbol
1906 functioncall_traversing_visitor::visit_delete_statement (s);
1907 current_lrvalue = last_lrvalue;
1908}
cbfbbf69 1909
cf9ff341
FCE
1910bool
1911varuse_collecting_visitor::side_effect_free ()
1912{
1913 return (written.empty() && !embedded_seen);
1914}
1915
1916
1917bool
1918varuse_collecting_visitor::side_effect_free_wrt (const set<vardecl*>& vars)
1919{
1920 // A looser notion of side-effect-freeness with respect to a given
1921 // list of variables.
1922
1923 // That's useful because the written list may consist of local
1924 // variables of called functions. But visible side-effects only
1925 // occur if the client's locals, or any globals are written-to.
1926
1927 set<vardecl*> intersection;
1928 insert_iterator<set<vardecl*> > int_it (intersection, intersection.begin());
1929 set_intersection (written.begin(), written.end(),
1930 vars.begin(), vars.end(),
1931 int_it);
1932
1933 return (intersection.empty() && !embedded_seen);
1934}
1935
1936
1937
cbfbbf69 1938
82919855
FCE
1939// ------------------------------------------------------------------------
1940
1941
1942throwing_visitor::throwing_visitor (const std::string& m): msg (m) {}
1943throwing_visitor::throwing_visitor (): msg ("invalid element") {}
1944
1945
1946void
1947throwing_visitor::throwone (const token* t)
1948{
1949 throw semantic_error (msg, t);
1950}
1951
1952void
54dfabe9
FCE
1953throwing_visitor::visit_block (block* s)
1954{
1955 throwone (s->tok);
1956}
1957
1958void
1959throwing_visitor::visit_embeddedcode (embeddedcode* s)
82919855
FCE
1960{
1961 throwone (s->tok);
1962}
1963
1964void
54dfabe9 1965throwing_visitor::visit_null_statement (null_statement* s)
82919855
FCE
1966{
1967 throwone (s->tok);
1968}
1969
1970void
54dfabe9 1971throwing_visitor::visit_expr_statement (expr_statement* s)
82919855
FCE
1972{
1973 throwone (s->tok);
1974}
1975
1976void
1977throwing_visitor::visit_if_statement (if_statement* s)
1978{
1979 throwone (s->tok);
1980}
1981
1982void
1983throwing_visitor::visit_for_loop (for_loop* s)
1984{
1985 throwone (s->tok);
1986}
1987
69c68955
FCE
1988void
1989throwing_visitor::visit_foreach_loop (foreach_loop* s)
1990{
1991 throwone (s->tok);
1992}
1993
82919855
FCE
1994void
1995throwing_visitor::visit_return_statement (return_statement* s)
1996{
1997 throwone (s->tok);
1998}
1999
2000void
2001throwing_visitor::visit_delete_statement (delete_statement* s)
2002{
2003 throwone (s->tok);
2004}
2005
f3c26ea5
FCE
2006void
2007throwing_visitor::visit_next_statement (next_statement* s)
2008{
2009 throwone (s->tok);
2010}
2011
2012void
2013throwing_visitor::visit_break_statement (break_statement* s)
2014{
2015 throwone (s->tok);
2016}
2017
2018void
2019throwing_visitor::visit_continue_statement (continue_statement* s)
2020{
2021 throwone (s->tok);
2022}
2023
82919855
FCE
2024void
2025throwing_visitor::visit_literal_string (literal_string* e)
2026{
2027 throwone (e->tok);
2028}
2029
2030void
2031throwing_visitor::visit_literal_number (literal_number* e)
2032{
2033 throwone (e->tok);
2034}
2035
2036void
2037throwing_visitor::visit_binary_expression (binary_expression* e)
2038{
2039 throwone (e->tok);
2040}
2041
2042void
2043throwing_visitor::visit_unary_expression (unary_expression* e)
2044{
2045 throwone (e->tok);
2046}
2047
2048void
2049throwing_visitor::visit_pre_crement (pre_crement* e)
2050{
2051 throwone (e->tok);
2052}
2053
2054void
2055throwing_visitor::visit_post_crement (post_crement* e)
2056{
2057 throwone (e->tok);
0054a7ea
FCE
2058}
2059
2060
82919855
FCE
2061void
2062throwing_visitor::visit_logical_or_expr (logical_or_expr* e)
2063{
2064 throwone (e->tok);
2065}
2066
2067void
2068throwing_visitor::visit_logical_and_expr (logical_and_expr* e)
2069{
2070 throwone (e->tok);
2071}
2072
2073void
2074throwing_visitor::visit_array_in (array_in* e)
2075{
2076 throwone (e->tok);
2077}
2078
2079void
2080throwing_visitor::visit_comparison (comparison* e)
2081{
2082 throwone (e->tok);
2083}
2084
2085void
2086throwing_visitor::visit_concatenation (concatenation* e)
2087{
2088 throwone (e->tok);
2089}
2090
82919855
FCE
2091void
2092throwing_visitor::visit_ternary_expression (ternary_expression* e)
2093{
2094 throwone (e->tok);
2095}
2096
2097void
2098throwing_visitor::visit_assignment (assignment* e)
2099{
2100 throwone (e->tok);
2101}
2102
2103void
2104throwing_visitor::visit_symbol (symbol* e)
2105{
2106 throwone (e->tok);
2107}
2108
d7f3e0c5
GH
2109void
2110throwing_visitor::visit_target_symbol (target_symbol* e)
2111{
2112 throwone (e->tok);
2113}
2114
9b5af295
JS
2115void
2116throwing_visitor::visit_cast_op (cast_op* e)
2117{
2118 throwone (e->tok);
2119}
2120
82919855
FCE
2121void
2122throwing_visitor::visit_arrayindex (arrayindex* e)
2123{
2124 throwone (e->tok);
2125}
2126
2127void
2128throwing_visitor::visit_functioncall (functioncall* e)
2129{
2130 throwone (e->tok);
2131}
85365d1b 2132
d02548c0
GH
2133void
2134throwing_visitor::visit_print_format (print_format* e)
2135{
2136 throwone (e->tok);
2137}
2138
2139void
2140throwing_visitor::visit_stat_op (stat_op* e)
2141{
2142 throwone (e->tok);
2143}
2144
2145void
2146throwing_visitor::visit_hist_op (hist_op* e)
2147{
2148 throwone (e->tok);
2149}
2150
85365d1b
GH
2151
2152// ------------------------------------------------------------------------
2153
85365d1b
GH
2154
2155void
4b6455e8 2156update_visitor::visit_block (block* s)
85365d1b 2157{
85365d1b 2158 for (unsigned i = 0; i < s->statements.size(); ++i)
4b6455e8
JS
2159 s->statements[i] = require (s->statements[i]);
2160 provide (s);
2161}
2162
2163void
2164update_visitor::visit_embeddedcode (embeddedcode* s)
2165{
2166 provide (s);
2167}
2168
2169void
2170update_visitor::visit_null_statement (null_statement* s)
2171{
2172 provide (s);
2173}
2174
2175void
2176update_visitor::visit_expr_statement (expr_statement* s)
2177{
2178 s->value = require (s->value);
2179 provide (s);
2180}
2181
2182void
2183update_visitor::visit_if_statement (if_statement* s)
2184{
2185 s->condition = require (s->condition);
2186 s->thenblock = require (s->thenblock);
2187 s->elseblock = require (s->elseblock);
2188 provide (s);
2189}
2190
2191void
2192update_visitor::visit_for_loop (for_loop* s)
2193{
2194 s->init = require (s->init);
2195 s->cond = require (s->cond);
2196 s->incr = require (s->incr);
2197 s->block = require (s->block);
2198 provide (s);
2199}
2200
2201void
2202update_visitor::visit_foreach_loop (foreach_loop* s)
2203{
2204 for (unsigned i = 0; i < s->indexes.size(); ++i)
2205 s->indexes[i] = require (s->indexes[i]);
2206 s->base = require (s->base);
2207 s->limit = require (s->limit);
2208 s->block = require (s->block);
2209 provide (s);
2210}
2211
2212void
2213update_visitor::visit_return_statement (return_statement* s)
2214{
2215 s->value = require (s->value);
2216 provide (s);
2217}
2218
2219void
2220update_visitor::visit_delete_statement (delete_statement* s)
2221{
2222 s->value = require (s->value);
2223 provide (s);
2224}
2225
2226void
2227update_visitor::visit_next_statement (next_statement* s)
2228{
2229 provide (s);
2230}
2231
2232void
2233update_visitor::visit_break_statement (break_statement* s)
2234{
2235 provide (s);
2236}
2237
2238void
2239update_visitor::visit_continue_statement (continue_statement* s)
2240{
2241 provide (s);
2242}
2243
2244void
2245update_visitor::visit_literal_string (literal_string* e)
2246{
2247 provide (e);
2248}
2249
2250void
2251update_visitor::visit_literal_number (literal_number* e)
2252{
2253 provide (e);
2254}
2255
2256void
2257update_visitor::visit_binary_expression (binary_expression* e)
2258{
2259 e->left = require (e->left);
2260 e->right = require (e->right);
2261 provide (e);
2262}
2263
2264void
2265update_visitor::visit_unary_expression (unary_expression* e)
2266{
2267 e->operand = require (e->operand);
2268 provide (e);
2269}
2270
2271void
2272update_visitor::visit_pre_crement (pre_crement* e)
2273{
2274 e->operand = require (e->operand);
2275 provide (e);
2276}
2277
2278void
2279update_visitor::visit_post_crement (post_crement* e)
2280{
2281 e->operand = require (e->operand);
2282 provide (e);
2283}
2284
2285
2286void
2287update_visitor::visit_logical_or_expr (logical_or_expr* e)
2288{
2289 e->left = require (e->left);
2290 e->right = require (e->right);
2291 provide (e);
2292}
2293
2294void
2295update_visitor::visit_logical_and_expr (logical_and_expr* e)
2296{
2297 e->left = require (e->left);
2298 e->right = require (e->right);
2299 provide (e);
2300}
2301
2302void
2303update_visitor::visit_array_in (array_in* e)
2304{
2305 e->operand = require (e->operand);
2306 provide (e);
2307}
2308
2309void
2310update_visitor::visit_comparison (comparison* e)
2311{
2312 e->left = require (e->left);
2313 e->right = require (e->right);
2314 provide (e);
2315}
2316
2317void
2318update_visitor::visit_concatenation (concatenation* e)
2319{
2320 e->left = require (e->left);
2321 e->right = require (e->right);
2322 provide (e);
2323}
2324
2325void
2326update_visitor::visit_ternary_expression (ternary_expression* e)
2327{
2328 e->cond = require (e->cond);
2329 e->truevalue = require (e->truevalue);
2330 e->falsevalue = require (e->falsevalue);
2331 provide (e);
2332}
2333
2334void
2335update_visitor::visit_assignment (assignment* e)
2336{
2337 e->left = require (e->left);
2338 e->right = require (e->right);
2339 provide (e);
2340}
2341
2342void
2343update_visitor::visit_symbol (symbol* e)
2344{
2345 provide (e);
2346}
2347
2348void
2349update_visitor::visit_target_symbol (target_symbol* e)
2350{
2351 provide (e);
2352}
2353
9b5af295
JS
2354void
2355update_visitor::visit_cast_op (cast_op* e)
2356{
2357 e->operand = require (e->operand);
2358 provide (e);
2359}
2360
4b6455e8
JS
2361void
2362update_visitor::visit_arrayindex (arrayindex* e)
2363{
2364 e->base = require (e->base);
2365 for (unsigned i = 0; i < e->indexes.size(); ++i)
2366 e->indexes[i] = require (e->indexes[i]);
2367 provide (e);
2368}
2369
2370void
2371update_visitor::visit_functioncall (functioncall* e)
2372{
2373 for (unsigned i = 0; i < e->args.size(); ++i)
2374 e->args[i] = require (e->args[i]);
2375 provide (e);
2376}
2377
2378void
2379update_visitor::visit_print_format (print_format* e)
2380{
2381 for (unsigned i = 0; i < e->args.size(); ++i)
2382 e->args[i] = require (e->args[i]);
2383 e->hist = require (e->hist);
2384 provide (e);
2385}
2386
2387void
2388update_visitor::visit_stat_op (stat_op* e)
2389{
2390 e->stat = require (e->stat);
2391 provide (e);
2392}
2393
2394void
2395update_visitor::visit_hist_op (hist_op* e)
2396{
2397 e->stat = require (e->stat);
2398 provide (e);
2399}
2400
2401template <> indexable*
1cd151d5 2402update_visitor::require <indexable*> (indexable* src, bool clearok)
4b6455e8
JS
2403{
2404 indexable *dst = NULL;
2405 if (src != NULL)
2406 {
2407 symbol *array_src=NULL;
2408 hist_op *hist_src=NULL;
2409
2410 classify_indexable(src, array_src, hist_src);
2411
2412 if (array_src)
2413 dst = require (array_src);
2414 else
2415 dst = require (hist_src);
1cd151d5 2416 assert(clearok || dst);
4b6455e8
JS
2417 }
2418 return dst;
2419}
2420
2421
2422// ------------------------------------------------------------------------
2423
2424
2425void
2426deep_copy_visitor::visit_block (block* s)
2427{
2428 update_visitor::visit_block(new block(*s));
85365d1b
GH
2429}
2430
2431void
54dfabe9
FCE
2432deep_copy_visitor::visit_embeddedcode (embeddedcode* s)
2433{
4b6455e8 2434 update_visitor::visit_embeddedcode(new embeddedcode(*s));
54dfabe9
FCE
2435}
2436
2437void
2438deep_copy_visitor::visit_null_statement (null_statement* s)
85365d1b 2439{
4b6455e8 2440 update_visitor::visit_null_statement(new null_statement(*s));
85365d1b
GH
2441}
2442
2443void
54dfabe9 2444deep_copy_visitor::visit_expr_statement (expr_statement* s)
85365d1b 2445{
4b6455e8 2446 update_visitor::visit_expr_statement(new expr_statement(*s));
85365d1b
GH
2447}
2448
2449void
2450deep_copy_visitor::visit_if_statement (if_statement* s)
2451{
4b6455e8 2452 update_visitor::visit_if_statement(new if_statement(*s));
85365d1b
GH
2453}
2454
2455void
2456deep_copy_visitor::visit_for_loop (for_loop* s)
2457{
4b6455e8 2458 update_visitor::visit_for_loop(new for_loop(*s));
85365d1b
GH
2459}
2460
2461void
2462deep_copy_visitor::visit_foreach_loop (foreach_loop* s)
2463{
4b6455e8 2464 update_visitor::visit_foreach_loop(new foreach_loop(*s));
85365d1b
GH
2465}
2466
2467void
2468deep_copy_visitor::visit_return_statement (return_statement* s)
2469{
4b6455e8 2470 update_visitor::visit_return_statement(new return_statement(*s));
85365d1b
GH
2471}
2472
2473void
2474deep_copy_visitor::visit_delete_statement (delete_statement* s)
2475{
4b6455e8 2476 update_visitor::visit_delete_statement(new delete_statement(*s));
85365d1b
GH
2477}
2478
2479void
2480deep_copy_visitor::visit_next_statement (next_statement* s)
2481{
4b6455e8 2482 update_visitor::visit_next_statement(new next_statement(*s));
85365d1b
GH
2483}
2484
2485void
2486deep_copy_visitor::visit_break_statement (break_statement* s)
2487{
4b6455e8 2488 update_visitor::visit_break_statement(new break_statement(*s));
85365d1b
GH
2489}
2490
2491void
2492deep_copy_visitor::visit_continue_statement (continue_statement* s)
2493{
4b6455e8 2494 update_visitor::visit_continue_statement(new continue_statement(*s));
85365d1b
GH
2495}
2496
2497void
2498deep_copy_visitor::visit_literal_string (literal_string* e)
2499{
4b6455e8 2500 update_visitor::visit_literal_string(new literal_string(*e));
85365d1b
GH
2501}
2502
2503void
2504deep_copy_visitor::visit_literal_number (literal_number* e)
2505{
4b6455e8 2506 update_visitor::visit_literal_number(new literal_number(*e));
85365d1b
GH
2507}
2508
2509void
2510deep_copy_visitor::visit_binary_expression (binary_expression* e)
2511{
4b6455e8 2512 update_visitor::visit_binary_expression(new binary_expression(*e));
85365d1b
GH
2513}
2514
2515void
2516deep_copy_visitor::visit_unary_expression (unary_expression* e)
2517{
4b6455e8 2518 update_visitor::visit_unary_expression(new unary_expression(*e));
85365d1b
GH
2519}
2520
2521void
2522deep_copy_visitor::visit_pre_crement (pre_crement* e)
2523{
4b6455e8 2524 update_visitor::visit_pre_crement(new pre_crement(*e));
85365d1b
GH
2525}
2526
2527void
2528deep_copy_visitor::visit_post_crement (post_crement* e)
2529{
4b6455e8 2530 update_visitor::visit_post_crement(new post_crement(*e));
85365d1b
GH
2531}
2532
2533
2534void
2535deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e)
2536{
4b6455e8 2537 update_visitor::visit_logical_or_expr(new logical_or_expr(*e));
85365d1b
GH
2538}
2539
2540void
2541deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e)
2542{
4b6455e8 2543 update_visitor::visit_logical_and_expr(new logical_and_expr(*e));
85365d1b
GH
2544}
2545
2546void
2547deep_copy_visitor::visit_array_in (array_in* e)
2548{
4b6455e8 2549 update_visitor::visit_array_in(new array_in(*e));
85365d1b
GH
2550}
2551
2552void
2553deep_copy_visitor::visit_comparison (comparison* e)
2554{
4b6455e8 2555 update_visitor::visit_comparison(new comparison(*e));
85365d1b
GH
2556}
2557
2558void
2559deep_copy_visitor::visit_concatenation (concatenation* e)
2560{
4b6455e8 2561 update_visitor::visit_concatenation(new concatenation(*e));
85365d1b
GH
2562}
2563
2564void
2565deep_copy_visitor::visit_ternary_expression (ternary_expression* e)
2566{
4b6455e8 2567 update_visitor::visit_ternary_expression(new ternary_expression(*e));
85365d1b
GH
2568}
2569
2570void
2571deep_copy_visitor::visit_assignment (assignment* e)
2572{
4b6455e8 2573 update_visitor::visit_assignment(new assignment(*e));
85365d1b
GH
2574}
2575
2576void
2577deep_copy_visitor::visit_symbol (symbol* e)
2578{
4b6455e8
JS
2579 symbol* n = new symbol(*e);
2580 n->referent = NULL; // don't copy!
2581 update_visitor::visit_symbol(n);
d7f3e0c5
GH
2582}
2583
2584void
2585deep_copy_visitor::visit_target_symbol (target_symbol* e)
2586{
4b6455e8
JS
2587 target_symbol* n = new target_symbol(*e);
2588 n->referent = NULL; // don't copy!
2589 update_visitor::visit_target_symbol(n);
85365d1b
GH
2590}
2591
9b5af295
JS
2592void
2593deep_copy_visitor::visit_cast_op (cast_op* e)
2594{
2595 update_visitor::visit_cast_op(new cast_op(*e));
2596}
2597
85365d1b
GH
2598void
2599deep_copy_visitor::visit_arrayindex (arrayindex* e)
2600{
4b6455e8 2601 update_visitor::visit_arrayindex(new arrayindex(*e));
85365d1b
GH
2602}
2603
2604void
2605deep_copy_visitor::visit_functioncall (functioncall* e)
2606{
4b6455e8
JS
2607 functioncall* n = new functioncall(*e);
2608 n->referent = NULL; // don't copy!
2609 update_visitor::visit_functioncall(n);
85365d1b
GH
2610}
2611
d02548c0
GH
2612void
2613deep_copy_visitor::visit_print_format (print_format* e)
2614{
4b6455e8 2615 update_visitor::visit_print_format(new print_format(*e));
d02548c0
GH
2616}
2617
2618void
2619deep_copy_visitor::visit_stat_op (stat_op* e)
2620{
4b6455e8 2621 update_visitor::visit_stat_op(new stat_op(*e));
d02548c0
GH
2622}
2623
2624void
2625deep_copy_visitor::visit_hist_op (hist_op* e)
2626{
4b6455e8 2627 update_visitor::visit_hist_op(new hist_op(*e));
edc22ba9
DB
2628}
2629
73267b89 2630/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.387328 seconds and 5 git commands to generate.