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