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