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