]> sourceware.org Git - systemtap.git/blame - elaborate.cxx
Added buf info tracking, removed buf-full warning
[systemtap.git] / elaborate.cxx
CommitLineData
2b066ec1 1// elaboration functions
69c68955
FCE
2// Copyright (C) 2005 Red Hat Inc.
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.
2b066ec1
FCE
8
9#include "config.h"
10#include "elaborate.h"
11#include "parse.h"
20c6c071 12#include "tapsets.h"
2b066ec1
FCE
13
14extern "C" {
15#include <sys/utsname.h>
16}
17
2b066ec1 18#include <algorithm>
67c0a579
GH
19#include <fstream>
20#include <map>
21#include <set>
22#include <vector>
2b066ec1 23
2b066ec1
FCE
24using namespace std;
25
26
27// ------------------------------------------------------------------------
28
29
30derived_probe::derived_probe (probe *p):
31 base (p)
32{
77de5e9e
GH
33 if (p)
34 {
35 this->locations = p->locations;
36 this->tok = p->tok;
37 this->body = deep_copy_visitor::deep_copy(p->body);
38 }
2b066ec1
FCE
39}
40
41
42derived_probe::derived_probe (probe *p, probe_point *l):
43 base (p)
44{
45 this->locations.push_back (l);
77de5e9e
GH
46 if (p)
47 {
48 this->tok = p->tok;
49 this->body = deep_copy_visitor::deep_copy(p->body);
50 }
2b066ec1
FCE
51}
52
20c6c071
GH
53// ------------------------------------------------------------------------
54
55// Members of match_key.
56
57match_key::match_key(string const & n)
58 : name(n),
59 have_parameter(false),
60 parameter_type(tok_junk)
61{
62}
63
64match_key::match_key(probe_point::component const & c)
65 : name(c.functor),
66 have_parameter(c.arg != NULL),
67 parameter_type(c.arg ? c.arg->tok->type : tok_junk)
68{
69}
70
71match_key &
72match_key::with_number()
73{
74 have_parameter = true;
75 parameter_type = tok_number;
76 return *this;
77}
78
79match_key &
80match_key::with_string()
81{
82 have_parameter = true;
83 parameter_type = tok_string;
84 return *this;
85}
86
87string
88match_key::str() const
89{
90 if (have_parameter)
91 switch (parameter_type)
92 {
93 case tok_string: return name + "(string)";
94 case tok_number: return name + "(number)";
95 default: return name + "(...)";
96 }
97 return name;
98}
99
100bool
101match_key::operator<(match_key const & other) const
102{
103 return ((name < other.name)
104
105 || (name == name
106 && have_parameter < other.have_parameter)
107
108 || (name == name
109 && have_parameter == other.have_parameter
110 && parameter_type < other.parameter_type));
111}
2b066ec1
FCE
112
113// ------------------------------------------------------------------------
20c6c071
GH
114// Members of match_node
115// ------------------------------------------------------------------------
116
117match_node::match_node()
118 : end(NULL)
119{}
120
121match_node *
122match_node::bind(match_key const & k)
123{
124 map<match_key, match_node *>::const_iterator i = sub.find(k);
125 if (i != sub.end())
126 return i->second;
127 match_node * n = new match_node();
128 sub.insert(make_pair(k, n));
129 return n;
130}
131
132void
133match_node::bind(derived_probe_builder * e)
134{
135 if (end)
136 throw semantic_error("already have a pattern ending");
137 end = e;
138}
139
140match_node *
141match_node::bind(string const & k)
142{
143 return bind(match_key(k));
144}
145
146match_node *
147match_node::bind_str(string const & k)
148{
149 return bind(match_key(k).with_string());
150}
151
152match_node *
153match_node::bind_num(string const & k)
154{
155 return bind(match_key(k).with_number());
156}
157
158derived_probe_builder *
159match_node::find_builder(vector<probe_point::component *> const & components,
160 unsigned pos,
161 vector< pair<string, literal *> > & parameters)
162{
163 assert(pos <= components.size());
164 if (pos == components.size())
165 {
166 // Probe_point ends here. We match iff we have
167 // an "end" entry here. If we don't, it'll be null.
168 return end;
169 }
170 else
171 {
172 // Probe_point contains a component here. We match iff there's
173 // an entry in the sub table, and its value matches the rest
174 // of the probe_point.
175 match_key k(*components[pos]);
f4b28491 176 if (0) // session.verbose
20c6c071
GH
177 clog << "searching for component " << k.str() << endl;
178 map<match_key, match_node *>::const_iterator i = sub.find(k);
179 if (i == sub.end())
180 {
f4b28491 181 if (0) // session.verbose
20c6c071
GH
182 clog << "no match found" << endl;
183 return NULL;
184 }
185 else
186 {
f4b28491 187 if (0) // session.verbose
20c6c071
GH
188 clog << "matched " << k.str() << endl;
189 derived_probe_builder * builder = NULL;
190 if (k.have_parameter)
191 {
192 assert(components[pos]->arg);
193 parameters.push_back(make_pair(components[pos]->functor,
194 components[pos]->arg));
195 }
196 else
197 {
198 // store a "null parameter" for any component we run into, anyways
199 literal_string *empty = NULL;
200 parameters.push_back(make_pair(components[pos]->functor, empty));
201 }
202 builder = i->second->find_builder(components, pos+1, parameters);
203 if (k.have_parameter && !builder)
204 parameters.pop_back();
205 return builder;
206 }
207 }
208}
209
210
211static void
212param_vec_to_map(vector< pair<string, literal *> > const & param_vec,
213 map<string, literal *> & param_map)
214{
215 for (vector< pair<string, literal *> >::const_iterator i = param_vec.begin();
216 i != param_vec.end(); ++i)
217 {
218 param_map[i->first] = i->second;
219 }
220}
221
222// ------------------------------------------------------------------------
223// Alias probes
224// ------------------------------------------------------------------------
225
226struct
227alias_expansion_builder
228 : public derived_probe_builder
229{
230 probe_alias * alias;
231
232 alias_expansion_builder(probe_alias * a)
233 : alias(a)
234 {}
235
5227f1ea
GH
236 virtual void build(systemtap_session & sess,
237 probe * use,
20c6c071
GH
238 probe_point * location,
239 std::map<std::string, literal *> const & parameters,
240 vector<probe *> & results_to_expand_further,
241 vector<derived_probe *> & finished_results)
242 {
243 // We're going to build a new probe and wrap it up in an
244 // alias_expansion_probe so that the expansion loop recognizer it as
245 // such and re-expands its expansion.
246
247 probe * n = new probe();
248 n->body = new block();
249
250 // The new probe gets the location list of the alias,
251 n->locations = alias->locations;
252
253 // the token location of the use,
254 n->tok = use->tok;
255
5227f1ea
GH
256 // and statements representing the concatenation of the alias'
257 // body with the use's.
258 //
259 // NB: locals are *not* copied forward, from either alias or
260 // use. The expansion should have its locals re-inferred since
261 // there's concatenated code here and we only want one vardecl per
262 // resulting variable.
263
85365d1b
GH
264 for (unsigned i = 0; i < alias->body->statements.size(); ++i)
265 {
266 statement *s = deep_copy_visitor::deep_copy(alias->body->statements[i]);
267 n->body->statements.push_back(s);
268 }
269
270 for (unsigned i = 0; i < use->body->statements.size(); ++i)
271 {
272 statement *s = deep_copy_visitor::deep_copy(use->body->statements[i]);
273 n->body->statements.push_back(s);
274 }
20c6c071
GH
275
276 results_to_expand_further.push_back(n);
277 }
278};
279
280
281// ------------------------------------------------------------------------
282// Pattern matching
283// ------------------------------------------------------------------------
284
285
286// Register all the aliases we've seen in library files, and the user
287// file, as patterns.
288
289void
290systemtap_session::register_library_aliases()
291{
292 vector<stapfile*> files(library_files);
293 files.push_back(user_file);
294
295 for (unsigned f = 0; f < files.size(); ++f)
296 {
297 stapfile * file = files[f];
298 for (unsigned a = 0; a < file->aliases.size(); ++a)
299 {
300 probe_alias * alias = file->aliases[a];
301 for (unsigned n = 0; n < alias->alias_names.size(); ++n)
302 {
303 probe_point * name = alias->alias_names[n];
304 if (verbose)
305 {
306 clog << "registering probe alias ";
307 for (unsigned c = 0; c < name->components.size(); ++c)
308 clog << (c > 0 ? "." : "") << name->components[c]->functor;
309 clog << endl;
310 }
311 match_node * n = pattern_root;
312 for (unsigned c = 0; c < name->components.size(); ++c)
313 {
314 probe_point::component * comp = name->components[c];
315 // XXX: alias parameters
316 if (comp->arg)
317 throw semantic_error("alias component "
318 + comp->functor
319 + " contains illegal parameter");
320 n = n->bind(comp->functor);
321 }
322 n->bind(new alias_expansion_builder(alias));
323 }
324 }
325 }
326}
327
328
5227f1ea
GH
329static unsigned max_recursion = 100;
330
331struct
332recursion_guard
333{
334 unsigned & i;
335 recursion_guard(unsigned & i) : i(i)
336 {
337 if (i > max_recursion)
338 throw semantic_error("recursion limit reached");
339 ++i;
340 }
341 ~recursion_guard()
342 {
343 --i;
344 }
345};
346
20c6c071
GH
347// The match-and-expand loop.
348void
349symresolution_info::derive_probes (match_node * root,
350 probe *p, vector<derived_probe*>& dps)
351{
5227f1ea
GH
352 static unsigned depth=0;
353 recursion_guard guard(depth);
354
20c6c071
GH
355 for (unsigned i = 0; i < p->locations.size(); ++i)
356 {
357 probe_point *loc = p->locations[i];
358 vector< pair<string, literal *> > param_vec;
359 map<string, literal *> param_map;
360 vector<probe *> re_expand;
361
fe3d01fa
FCE
362 try
363 {
364 derived_probe_builder * builder =
365 root->find_builder(loc->components, 0, param_vec);
366
367 if (!builder)
368 throw semantic_error ("no match for probe point family");
369
370 param_vec_to_map(param_vec, param_map);
371
372 unsigned num_atbegin = dps.size();
373 builder->build(session, p, loc, param_map, re_expand, dps);
374
375 // Recursively expand any further-expanding results
376 if (!re_expand.empty())
377 {
378 for (unsigned j = 0; j < re_expand.size(); ++j)
379 derive_probes(root, re_expand[j], dps);
380 }
381
382 unsigned num_atend = dps.size();
383 if (num_atbegin == num_atend) // nothing new derived!
384 throw semantic_error ("no match for probe point");
385 }
386 catch (const semantic_error& e)
387 {
388 session.print_error (e);
389 cerr << " while: resolving probe point " << *loc << endl;
390 }
20c6c071
GH
391 }
392}
393
394// ------------------------------------------------------------------------
67c0a579
GH
395//
396// Map usage checks
397//
398
399class lvalue_aware_traversing_visitor
400 : public traversing_visitor
401{
402 unsigned lval_depth;
403public:
404
405 lvalue_aware_traversing_visitor() : lval_depth(0) {}
406
407 bool is_in_lvalue()
408 {
409 return lval_depth > 0;
410 }
411
412 virtual void visit_pre_crement (pre_crement* e)
413 {
414 ++lval_depth;
415 e->operand->visit (this);
416 --lval_depth;
417 }
418
419 virtual void visit_post_crement (post_crement* e)
420 {
421 ++lval_depth;
422 e->operand->visit (this);
423 --lval_depth;
424 }
425
426 virtual void visit_assignment (assignment* e)
427 {
428 ++lval_depth;
429 e->left->visit (this);
430 --lval_depth;
431 e->right->visit (this);
432 }
433
434 virtual void visit_delete_statement (delete_statement* s)
435 {
436 ++lval_depth;
437 s->value->visit (this);
438 --lval_depth;
439 }
440
441};
442
443
444struct mutated_map_collector
445 : public lvalue_aware_traversing_visitor
446{
447 set<vardecl *> * mutated_maps;
448
449 mutated_map_collector(set<vardecl *> * mm)
450 : mutated_maps (mm)
451 {}
452
453 void visit_arrayindex (arrayindex *e)
454 {
455 if (is_in_lvalue())
456 mutated_maps->insert(e->referent);
457 }
458};
459
460
461struct no_map_mutation_during_iteration_check
462 : public lvalue_aware_traversing_visitor
463{
464 systemtap_session & session;
465 map<functiondecl *,set<vardecl *> *> & function_mutates_maps;
466 vector<vardecl *> maps_being_iterated;
467
468 no_map_mutation_during_iteration_check
469 (systemtap_session & sess,
470 map<functiondecl *,set<vardecl *> *> & fmm)
471 : session(sess), function_mutates_maps (fmm)
472 {}
473
474 void visit_arrayindex (arrayindex *e)
475 {
476 if (is_in_lvalue())
477 {
478 for (unsigned i = 0; i < maps_being_iterated.size(); ++i)
479 {
480 vardecl *m = maps_being_iterated[i];
481 if (m == e->referent)
482 {
483 string err = ("map '" + m->name +
484 "' modified during 'foreach' iteration");
485 session.print_error (semantic_error (err, e->tok));
486 }
487 }
488 }
489 }
490
491 void visit_functioncall (functioncall* e)
492 {
493 map<functiondecl *,set<vardecl *> *>::const_iterator i
494 = function_mutates_maps.find (e->referent);
495
496 if (i != function_mutates_maps.end())
497 {
498 for (unsigned j = 0; j < maps_being_iterated.size(); ++j)
499 {
500 vardecl *m = maps_being_iterated[j];
501 if (i->second->find (m) != i->second->end())
502 {
503 string err = ("function call modifies map '" + m->name +
504 "' during 'foreach' iteration");
505 session.print_error (semantic_error (err, e->tok));
506 }
507 }
508 }
509
510 for (unsigned i=0; i<e->args.size(); i++)
511 e->args[i]->visit (this);
512 }
513
514 void visit_foreach_loop(foreach_loop* s)
515 {
516 maps_being_iterated.push_back (s->base_referent);
517 for (unsigned i=0; i<s->indexes.size(); i++)
518 s->indexes[i]->visit (this);
519 s->block->visit (this);
520 maps_being_iterated.pop_back();
521 }
522};
20c6c071 523
2b066ec1 524
67c0a579
GH
525static int
526semantic_pass_maps (systemtap_session & sess)
527{
528
529 map<functiondecl *, set<vardecl *> *> fmm;
530 no_map_mutation_during_iteration_check chk(sess, fmm);
531
532 for (unsigned i = 0; i < sess.functions.size(); ++i)
533 {
534 functiondecl * fn = sess.functions[i];
535 if (fn->body)
536 {
537 set<vardecl *> * m = new set<vardecl *>();
538 mutated_map_collector mc (m);
539 fn->body->visit (&mc);
540 fmm[fn] = m;
541 }
542 }
543
544 for (unsigned i = 0; i < sess.functions.size(); ++i)
545 {
546 if (sess.functions[i]->body)
547 sess.functions[i]->body->visit (&chk);
548 }
549
550 for (unsigned i = 0; i < sess.probes.size(); ++i)
551 {
552 if (sess.probes[i]->body)
553 sess.probes[i]->body->visit (&chk);
554 }
555
556 return sess.num_errors;
557}
558
559// ------------------------------------------------------------------------
560
2b066ec1
FCE
561
562static int semantic_pass_symbols (systemtap_session&);
563static int semantic_pass_types (systemtap_session&);
67c0a579 564static int semantic_pass_maps (systemtap_session&);
2b066ec1
FCE
565
566
567
568// Link up symbols to their declarations. Set the session's
569// files/probes/functions/globals vectors from the transitively
570// reached set of stapfiles in s.library_files, starting from
20c6c071 571// s.user_file. Perform automatic tapset inclusion and probe
2b066ec1
FCE
572// alias expansion.
573static int
574semantic_pass_symbols (systemtap_session& s)
575{
576 symresolution_info sym (s);
577
578 // NB: s.files can grow during this iteration, so size() can
579 // return gradually increasing numbers.
580 s.files.push_back (s.user_file);
581 for (unsigned i = 0; i < s.files.size(); i++)
582 {
583 stapfile* dome = s.files[i];
584
585 // Pass 1: add globals and functions to systemtap-session master list,
586 // so the find_* functions find them
587
588 for (unsigned i=0; i<dome->globals.size(); i++)
589 s.globals.push_back (dome->globals[i]);
590
591 for (unsigned i=0; i<dome->functions.size(); i++)
592 s.functions.push_back (dome->functions[i]);
593
54dfabe9
FCE
594 for (unsigned i=0; i<dome->embeds.size(); i++)
595 s.embeds.push_back (dome->embeds[i]);
596
2b066ec1
FCE
597 // Pass 2: process functions
598
599 for (unsigned i=0; i<dome->functions.size(); i++)
600 {
601 functiondecl* fd = dome->functions[i];
602
603 try
604 {
8a43522c
GH
605 sym.current_function = fd;
606 sym.current_probe = 0;
607 fd->body->visit (& sym);
2b066ec1
FCE
608 }
609 catch (const semantic_error& e)
610 {
611 s.print_error (e);
612 }
613 }
614
5227f1ea
GH
615 // Pass 3: derive probes and resolve any further symbols in the
616 // derived results.
2b066ec1
FCE
617
618 for (unsigned i=0; i<dome->probes.size(); i++)
619 {
620 probe* p = dome->probes [i];
621 vector<derived_probe*> dps;
622
fe3d01fa
FCE
623 // much magic happens here: probe alias expansion,
624 // provider identification
625 sym.derive_probes (s.pattern_root, p, dps);
2b066ec1
FCE
626
627 for (unsigned j=0; j<dps.size(); j++)
628 {
629 derived_probe* dp = dps[j];
630 s.probes.push_back (dp);
631
632 try
633 {
634 sym.current_function = 0;
5227f1ea 635 sym.current_probe = dp;
2b066ec1
FCE
636 dp->body->visit (& sym);
637 }
638 catch (const semantic_error& e)
639 {
640 s.print_error (e);
641 }
642 }
643 }
644 }
fe3d01fa 645
2b066ec1
FCE
646 return s.num_errors; // all those print_error calls
647}
648
649
650
651int
652semantic_pass (systemtap_session& s)
653{
20c6c071 654 s.register_library_aliases();
f8220a7b 655 register_standard_tapsets(s);
20c6c071 656
2b066ec1
FCE
657 int rc = semantic_pass_symbols (s);
658 if (rc == 0) rc = semantic_pass_types (s);
67c0a579 659 if (rc == 0) rc = semantic_pass_maps (s);
2b066ec1
FCE
660 return rc;
661}
662
663
664// ------------------------------------------------------------------------
665
666
667systemtap_session::systemtap_session ():
20c6c071 668 pattern_root(new match_node),
2b066ec1
FCE
669 user_file (0), op (0), up (0), num_errors (0)
670{
671}
672
673
674void
675systemtap_session::print_error (const semantic_error& e)
676{
d8067b24
FCE
677 cerr << "semantic error: " << e.what ();
678 if (e.tok1 || e.tok2)
679 cerr << ": ";
2b066ec1
FCE
680 if (e.tok1) cerr << *e.tok1;
681 cerr << e.msg2;
682 if (e.tok2) cerr << *e.tok2;
683 cerr << endl;
684 num_errors ++;
685}
686
687
688// ------------------------------------------------------------------------
689// semantic processing: symbol resolution
690
691
692symresolution_info::symresolution_info (systemtap_session& s):
5227f1ea 693 session (s), current_function (0), current_probe (0)
2b066ec1
FCE
694{
695}
696
697
698void
699symresolution_info::visit_block (block* e)
700{
701 for (unsigned i=0; i<e->statements.size(); i++)
702 {
703 try
704 {
705 e->statements[i]->visit (this);
706 }
707 catch (const semantic_error& e)
708 {
709 session.print_error (e);
710 }
711 }
712}
713
714
69c68955
FCE
715void
716symresolution_info::visit_foreach_loop (foreach_loop* e)
717{
718 for (unsigned i=0; i<e->indexes.size(); i++)
719 e->indexes[i]->visit (this);
720
721 if (e->base_referent)
722 return;
723
313b2f74 724 vardecl* d = find_var (e->base, e->indexes.size ());
69c68955
FCE
725 if (d)
726 e->base_referent = d;
727 else
728 throw semantic_error ("unresolved global array " + e->base, e->tok);
729
730 e->block->visit (this);
731}
732
733
2b066ec1
FCE
734void
735symresolution_info::visit_symbol (symbol* e)
736{
737 if (e->referent)
738 return;
739
313b2f74 740 vardecl* d = find_var (e->name, 0);
2b066ec1
FCE
741 if (d)
742 e->referent = d;
743 else
744 {
745 // new local
746 vardecl* v = new vardecl;
747 v->name = e->name;
748 v->tok = e->tok;
749 if (current_function)
750 current_function->locals.push_back (v);
751 else if (current_probe)
752 current_probe->locals.push_back (v);
753 else
ce10591c
FCE
754 // must not happen
755 throw semantic_error ("no current probe/function", e->tok);
2b066ec1
FCE
756 e->referent = v;
757 }
758}
759
760
761void
762symresolution_info::visit_arrayindex (arrayindex* e)
763{
764 for (unsigned i=0; i<e->indexes.size(); i++)
765 e->indexes[i]->visit (this);
766
767 if (e->referent)
768 return;
769
313b2f74 770 vardecl* d = find_var (e->base, e->indexes.size ());
2b066ec1
FCE
771 if (d)
772 e->referent = d;
773 else
313b2f74
GH
774 {
775 // new local
776 vardecl* v = new vardecl;
777 v->set_arity(e->indexes.size());
778 v->name = e->base;
779 v->tok = e->tok;
780 if (current_function)
781 current_function->locals.push_back (v);
782 else if (current_probe)
783 current_probe->locals.push_back (v);
784 else
785 // must not happen
786 throw semantic_error ("no current probe/function", e->tok);
787 e->referent = v;
788 }
2b066ec1
FCE
789}
790
791
792void
793symresolution_info::visit_functioncall (functioncall* e)
794{
795 for (unsigned i=0; i<e->args.size(); i++)
796 e->args[i]->visit (this);
797
798 if (e->referent)
799 return;
800
801 functiondecl* d = find_function (e->function, e->args.size ());
802 if (d)
803 e->referent = d;
804 else
805 throw semantic_error ("unresolved function call", e->tok);
806}
807
808
809vardecl*
313b2f74 810symresolution_info::find_var (const string& name, unsigned arity)
2b066ec1 811{
313b2f74 812
2b066ec1
FCE
813 // search locals
814 vector<vardecl*>& locals = (current_function ?
815 current_function->locals :
5227f1ea 816 current_probe->locals);
6deb8173 817
313b2f74 818
2b066ec1 819 for (unsigned i=0; i<locals.size(); i++)
313b2f74
GH
820 if (locals[i]->name == name
821 && locals[i]->compatible_arity(arity))
8846477c 822 {
313b2f74 823 locals[i]->set_arity (arity);
8846477c
FCE
824 return locals[i];
825 }
2b066ec1 826
313b2f74
GH
827 // search function formal parameters (for scalars)
828 if (arity == 0 && current_function)
2b066ec1
FCE
829 for (unsigned i=0; i<current_function->formal_args.size(); i++)
830 if (current_function->formal_args[i]->name == name)
8846477c
FCE
831 {
832 // NB: no need to check arity here: formal args always scalar
833 current_function->formal_args[i]->set_arity (0);
834 return current_function->formal_args[i];
835 }
2b066ec1 836
313b2f74 837 // search processed globals
2b066ec1 838 for (unsigned i=0; i<session.globals.size(); i++)
313b2f74
GH
839 if (session.globals[i]->name == name
840 && session.globals[i]->compatible_arity(arity))
8846477c 841 {
313b2f74 842 session.globals[i]->set_arity (arity);
8846477c
FCE
843 return session.globals[i];
844 }
2b066ec1
FCE
845
846 // search library globals
847 for (unsigned i=0; i<session.library_files.size(); i++)
848 {
849 stapfile* f = session.library_files[i];
850 for (unsigned j=0; j<f->globals.size(); j++)
84e5ea0f
FCE
851 {
852 vardecl* g = f->globals[j];
853 if (g->name == name && g->compatible_arity (arity))
854 {
855 g->set_arity (arity);
856
857 // put library into the queue if not already there
858 if (find (session.files.begin(), session.files.end(), f)
859 == session.files.end())
860 session.files.push_back (f);
861
862 return g;
863 }
864 }
2b066ec1
FCE
865 }
866
867 // search builtins that become locals
868 // XXX: need to invent a proper formalism for this
313b2f74 869 if (arity == 0 && (name == "$pid" || name == "$tid"))
2b066ec1
FCE
870 {
871 vardecl_builtin* vb = new vardecl_builtin;
872 vb->name = name;
873 vb->type = pe_long;
874
875 // XXX: need a better way to synthesize tokens
876 token* t = new token;
877 t->type = tok_identifier;
878 t->content = name;
879 t->location.file = "<builtin>";
880 vb->tok = t;
881
882 locals.push_back (vb);
883 return vb;
884 }
885
886 return 0;
2b066ec1
FCE
887}
888
889
2b066ec1
FCE
890functiondecl*
891symresolution_info::find_function (const string& name, unsigned arity)
892{
893 for (unsigned j = 0; j < session.functions.size(); j++)
894 {
895 functiondecl* fd = session.functions[j];
896 if (fd->name == name &&
897 fd->formal_args.size() == arity)
898 return fd;
899 }
900
901 // search library globals
902 for (unsigned i=0; i<session.library_files.size(); i++)
903 {
904 stapfile* f = session.library_files[i];
905 for (unsigned j=0; j<f->functions.size(); j++)
906 if (f->functions[j]->name == name &&
907 f->functions[j]->formal_args.size() == arity)
908 {
909 // put library into the queue if not already there
910 if (0) // session.verbose_resolution
911 cerr << " function " << name << " "
912 << "is defined from " << f->name << endl;
913
914 if (find (session.files.begin(), session.files.end(), f)
915 == session.files.end())
916 session.files.push_back (f);
917 // else .. print different message?
918
919 return f->functions[j];
920 }
921 }
922
923 return 0;
2b066ec1
FCE
924}
925
926
927// ------------------------------------------------------------------------
928// type resolution
929
930
931static int
932semantic_pass_types (systemtap_session& s)
933{
934 int rc = 0;
935
936 // next pass: type inference
937 unsigned iterations = 0;
938 typeresolution_info ti (s);
939
940 ti.assert_resolvability = false;
941 // XXX: maybe convert to exception-based error signalling
942 while (1)
943 {
944 iterations ++;
945 // cerr << "Type resolution, iteration " << iterations << endl;
946 ti.num_newly_resolved = 0;
947 ti.num_still_unresolved = 0;
948
949 for (unsigned j=0; j<s.functions.size(); j++)
950 {
951 functiondecl* fn = s.functions[j];
8a43522c
GH
952 ti.current_function = fn;
953 ti.t = pe_unknown;
954 fn->body->visit (& ti);
955 // NB: we don't have to assert a known type for
956 // functions here, to permit a "void" function.
957 // The translator phase will omit the "retvalue".
958 //
959 // if (fn->type == pe_unknown)
960 // ti.unresolved (fn->tok);
2b066ec1
FCE
961 }
962
963 for (unsigned j=0; j<s.probes.size(); j++)
964 {
965 derived_probe* pn = s.probes[j];
966 ti.current_function = 0;
967 ti.t = pe_unknown;
968 pn->body->visit (& ti);
969 }
970
971 for (unsigned j=0; j<s.globals.size(); j++)
972 {
973 vardecl* gd = s.globals[j];
974 if (gd->type == pe_unknown)
975 ti.unresolved (gd->tok);
976 }
977
978 if (ti.num_newly_resolved == 0) // converged
979 if (ti.num_still_unresolved == 0)
980 break; // successfully
981 else if (! ti.assert_resolvability)
982 ti.assert_resolvability = true; // last pass, with error msgs
983 else
984 { // unsuccessful conclusion
985 rc ++;
986 break;
987 }
988 }
989
990 return rc + s.num_errors;
991}
992
993
994void
995typeresolution_info::visit_literal_number (literal_number* e)
996{
997 assert (e->type == pe_long);
998 if ((t == e->type) || (t == pe_unknown))
999 return;
1000
1001 mismatch (e->tok, e->type, t);
1002}
1003
1004
1005void
1006typeresolution_info::visit_literal_string (literal_string* e)
1007{
1008 assert (e->type == pe_string);
1009 if ((t == e->type) || (t == pe_unknown))
1010 return;
1011
1012 mismatch (e->tok, e->type, t);
1013}
1014
1015
1016void
1017typeresolution_info::visit_logical_or_expr (logical_or_expr *e)
1018{
1019 visit_binary_expression (e);
1020}
1021
1022
1023void
1024typeresolution_info::visit_logical_and_expr (logical_and_expr *e)
1025{
1026 visit_binary_expression (e);
1027}
1028
1029
1030void
1031typeresolution_info::visit_comparison (comparison *e)
1032{
553d27a5
FCE
1033 if (t == pe_stats || t == pe_string)
1034 invalid (e->tok, t);
1035
1036 t = (e->right->type != pe_unknown) ? e->right->type : pe_unknown;
1037 e->left->visit (this);
1038 t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown;
1039 e->right->visit (this);
1040
1041 if (e->left->type != pe_unknown &&
1042 e->right->type != pe_unknown &&
1043 e->left->type != e->right->type)
1044 mismatch (e->tok, e->left->type, e->right->type);
1045
1046 if (e->type == pe_unknown)
1047 {
1048 e->type = pe_long;
1049 resolved (e->tok, e->type);
1050 }
2b066ec1
FCE
1051}
1052
1053
1054void
1055typeresolution_info::visit_concatenation (concatenation *e)
1056{
553d27a5
FCE
1057 if (t != pe_unknown && t != pe_string)
1058 invalid (e->tok, t);
1059
1060 t = pe_string;
1061 e->left->visit (this);
1062 t = pe_string;
1063 e->right->visit (this);
1064
1065 if (e->type == pe_unknown)
1066 {
1067 e->type = pe_string;
1068 resolved (e->tok, e->type);
1069 }
2b066ec1
FCE
1070}
1071
1072
2b066ec1
FCE
1073void
1074typeresolution_info::visit_assignment (assignment *e)
1075{
553d27a5
FCE
1076 if (t == pe_stats)
1077 invalid (e->tok, t);
2b066ec1 1078
2b066ec1
FCE
1079 if (e->op == "<<<") // stats aggregation
1080 {
553d27a5
FCE
1081 if (t == pe_string)
1082 invalid (e->tok, t);
1083
2b066ec1
FCE
1084 t = pe_stats;
1085 e->left->visit (this);
1086 t = pe_long;
1087 e->right->visit (this);
553d27a5 1088 if (e->type == pe_unknown)
2b066ec1
FCE
1089 {
1090 e->type = pe_long;
1091 resolved (e->tok, e->type);
1092 }
1093 }
553d27a5
FCE
1094 else if (e->op == "+=" || // numeric only
1095 false)
2b066ec1 1096 {
553d27a5 1097 visit_binary_expression (e);
2b066ec1 1098 }
553d27a5 1099 else // overloaded for string & numeric operands
2b066ec1 1100 {
553d27a5 1101 // logic similar to ternary_expression
2b066ec1 1102 exp_type sub_type = t;
553d27a5
FCE
1103
1104 // Infer types across the l/r values
1105 if (sub_type == pe_unknown && e->type != pe_unknown)
2b066ec1 1106 sub_type = e->type;
553d27a5
FCE
1107
1108 t = (sub_type != pe_unknown) ? sub_type :
1109 (e->right->type != pe_unknown) ? e->right->type :
1110 pe_unknown;
2b066ec1 1111 e->left->visit (this);
553d27a5
FCE
1112 t = (sub_type != pe_unknown) ? sub_type :
1113 (e->left->type != pe_unknown) ? e->left->type :
1114 pe_unknown;
2b066ec1 1115 e->right->visit (this);
553d27a5
FCE
1116
1117 if ((sub_type != pe_unknown) && (e->type == pe_unknown))
2b066ec1
FCE
1118 {
1119 e->type = sub_type;
1120 resolved (e->tok, e->type);
1121 }
553d27a5 1122 if ((sub_type == pe_unknown) && (e->left->type != pe_unknown))
2b066ec1
FCE
1123 {
1124 e->type = e->left->type;
1125 resolved (e->tok, e->type);
1126 }
553d27a5
FCE
1127
1128 if (e->left->type != pe_unknown &&
1129 e->right->type != pe_unknown &&
1130 e->left->type != e->right->type)
1131 mismatch (e->tok, e->left->type, e->right->type);
1132 }
1133}
1134
1135
1136void
1137typeresolution_info::visit_binary_expression (binary_expression* e)
1138{
1139 if (t == pe_stats || t == pe_string)
1140 invalid (e->tok, t);
1141
1142 t = pe_long;
1143 e->left->visit (this);
1144 t = pe_long;
1145 e->right->visit (this);
1146
1147 if (e->left->type != pe_unknown &&
1148 e->right->type != pe_unknown &&
1149 e->left->type != e->right->type)
1150 mismatch (e->tok, e->left->type, e->right->type);
1151
1152 if (e->type == pe_unknown)
1153 {
1154 e->type = pe_long;
1155 resolved (e->tok, e->type);
2b066ec1
FCE
1156 }
1157}
1158
1159
1160void
1161typeresolution_info::visit_pre_crement (pre_crement *e)
1162{
1163 visit_unary_expression (e);
1164}
1165
1166
1167void
1168typeresolution_info::visit_post_crement (post_crement *e)
1169{
1170 visit_unary_expression (e);
1171}
1172
1173
1174void
1175typeresolution_info::visit_unary_expression (unary_expression* e)
1176{
553d27a5
FCE
1177 if (t == pe_stats || t == pe_string)
1178 invalid (e->tok, t);
1179
2b066ec1
FCE
1180 t = pe_long;
1181 e->operand->visit (this);
1182
553d27a5 1183 if (e->type == pe_unknown)
2b066ec1
FCE
1184 {
1185 e->type = pe_long;
1186 resolved (e->tok, e->type);
1187 }
1188}
1189
1190
2b066ec1
FCE
1191void
1192typeresolution_info::visit_ternary_expression (ternary_expression* e)
1193{
1194 exp_type sub_type = t;
1195
1196 t = pe_long;
1197 e->cond->visit (this);
1198
553d27a5 1199 // Infer types across the true/false arms of the ternary expression.
2b066ec1
FCE
1200
1201 if (sub_type == pe_unknown && e->type != pe_unknown)
1202 sub_type = e->type;
1203 t = sub_type;
1204 e->truevalue->visit (this);
1205 t = sub_type;
1206 e->falsevalue->visit (this);
1207
1208 if ((sub_type == pe_unknown) && (e->type != pe_unknown))
1209 ; // already resolved
1210 else if ((sub_type != pe_unknown) && (e->type == pe_unknown))
1211 {
1212 e->type = sub_type;
1213 resolved (e->tok, e->type);
1214 }
1215 else if ((sub_type == pe_unknown) && (e->truevalue->type != pe_unknown))
1216 {
1217 e->type = e->truevalue->type;
1218 resolved (e->tok, e->type);
1219 }
1220 else if ((sub_type == pe_unknown) && (e->falsevalue->type != pe_unknown))
1221 {
1222 e->type = e->falsevalue->type;
1223 resolved (e->tok, e->type);
1224 }
1225 else if (e->type != sub_type)
1226 mismatch (e->tok, sub_type, e->type);
1227}
1228
1229
1230template <class Referrer, class Referent>
1231void resolve_2types (Referrer* referrer, Referent* referent,
1232 typeresolution_info* r, exp_type t)
1233{
1234 exp_type& re_type = referrer->type;
1235 const token* re_tok = referrer->tok;
1236 exp_type& te_type = referent->type;
1237 const token* te_tok = referent->tok;
1238
1239 if (t != pe_unknown && re_type == t && re_type == te_type)
1240 ; // do nothing: all three e->types in agreement
1241 else if (t == pe_unknown && re_type != pe_unknown && re_type == te_type)
1242 ; // do nothing: two known e->types in agreement
1243 else if (re_type != pe_unknown && te_type != pe_unknown && re_type != te_type)
1244 r->mismatch (re_tok, re_type, te_type);
1245 else if (re_type != pe_unknown && t != pe_unknown && re_type != t)
1246 r->mismatch (re_tok, re_type, t);
1247 else if (te_type != pe_unknown && t != pe_unknown && te_type != t)
1248 r->mismatch (te_tok, te_type, t);
1249 else if (re_type == pe_unknown && t != pe_unknown)
1250 {
1251 // propagate from upstream
1252 re_type = t;
1253 r->resolved (re_tok, re_type);
1254 // catch re_type/te_type mismatch later
1255 }
1256 else if (re_type == pe_unknown && te_type != pe_unknown)
1257 {
1258 // propagate from referent
1259 re_type = te_type;
1260 r->resolved (re_tok, re_type);
1261 // catch re_type/t mismatch later
1262 }
1263 else if (re_type != pe_unknown && te_type == pe_unknown)
1264 {
1265 // propagate to referent
1266 te_type = re_type;
1267 r->resolved (te_tok, te_type);
1268 // catch re_type/t mismatch later
1269 }
1270 else
1271 r->unresolved (re_tok);
1272}
1273
1274
1275void
1276typeresolution_info::visit_symbol (symbol* e)
1277{
1278 assert (e->referent != 0);
1279
1280 if (e->referent->arity > 0)
1281 unresolved (e->tok); // symbol resolution should not permit this
1282 // XXX: but consider "delete <array>;" and similar constructs
1283 else
1284 resolve_2types (e, e->referent, this, t);
1285}
1286
1287
1288void
1289typeresolution_info::visit_arrayindex (arrayindex* e)
1290{
1291 assert (e->referent != 0);
1292
1293 resolve_2types (e, e->referent, this, t);
1294
1295 // now resolve the array indexes
69c68955
FCE
1296
1297 // if (e->referent->index_types.size() == 0)
1298 // // redesignate referent as array
1299 // e->referent->set_arity (e->indexes.size ());
2b066ec1
FCE
1300
1301 if (e->indexes.size() != e->referent->index_types.size())
1302 unresolved (e->tok); // symbol resolution should prevent this
1303 else for (unsigned i=0; i<e->indexes.size(); i++)
1304 {
1305 expression* ee = e->indexes[i];
1306 exp_type& ft = e->referent->index_types [i];
1307 t = ft;
1308 ee->visit (this);
1309 exp_type at = ee->type;
1310
1311 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
1312 {
1313 // propagate to formal type
1314 ft = at;
1315 resolved (e->referent->tok, ft);
1316 // uses array decl as there is no token for "formal type"
1317 }
1318 if (at == pe_stats)
1319 invalid (ee->tok, at);
1320 if (ft == pe_stats)
1321 invalid (ee->tok, ft);
1322 if (at != pe_unknown && ft != pe_unknown && ft != at)
1323 mismatch (e->tok, at, ft);
1324 if (at == pe_unknown)
313b2f74 1325 unresolved (ee->tok);
2b066ec1
FCE
1326 }
1327}
1328
1329
1330void
1331typeresolution_info::visit_functioncall (functioncall* e)
1332{
1333 assert (e->referent != 0);
1334
1335 resolve_2types (e, e->referent, this, t);
1336
1337 if (e->type == pe_stats)
1338 invalid (e->tok, e->type);
1339
1340 // XXX: but what about functions that return no value,
1341 // and are used only as an expression-statement for side effects?
1342
1343 // now resolve the function parameters
1344 if (e->args.size() != e->referent->formal_args.size())
1345 unresolved (e->tok); // symbol resolution should prevent this
1346 else for (unsigned i=0; i<e->args.size(); i++)
1347 {
1348 expression* ee = e->args[i];
1349 exp_type& ft = e->referent->formal_args[i]->type;
1350 const token* fe_tok = e->referent->formal_args[i]->tok;
1351 t = ft;
1352 ee->visit (this);
1353 exp_type at = ee->type;
1354
1355 if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown)
1356 {
1357 // propagate to formal arg
1358 ft = at;
1359 resolved (e->referent->formal_args[i]->tok, ft);
1360 }
1361 if (at == pe_stats)
1362 invalid (e->tok, at);
1363 if (ft == pe_stats)
1364 invalid (fe_tok, ft);
1365 if (at != pe_unknown && ft != pe_unknown && ft != at)
1366 mismatch (e->tok, at, ft);
1367 if (at == pe_unknown)
1368 unresolved (e->tok);
1369 }
1370}
1371
1372
1373void
1374typeresolution_info::visit_block (block* e)
1375{
1376 for (unsigned i=0; i<e->statements.size(); i++)
1377 {
1378 try
1379 {
1380 t = pe_unknown;
1381 e->statements[i]->visit (this);
1382 }
1383 catch (const semantic_error& e)
1384 {
1385 session.print_error (e);
1386 }
1387 }
1388}
1389
1390
54dfabe9
FCE
1391void
1392typeresolution_info::visit_embeddedcode (embeddedcode* e)
1393{
1394}
1395
1396
2b066ec1
FCE
1397void
1398typeresolution_info::visit_if_statement (if_statement* e)
1399{
1400 t = pe_long;
1401 e->condition->visit (this);
1402
1403 t = pe_unknown;
1404 e->thenblock->visit (this);
1405
1406 if (e->elseblock)
1407 {
1408 t = pe_unknown;
1409 e->elseblock->visit (this);
1410 }
1411}
1412
1413
1414void
1415typeresolution_info::visit_for_loop (for_loop* e)
1416{
1417 t = pe_unknown;
1418 e->init->visit (this);
1419 t = pe_long;
1420 e->cond->visit (this);
1421 t = pe_unknown;
1422 e->incr->visit (this);
1423 t = pe_unknown;
1424 e->block->visit (this);
1425}
1426
1427
69c68955
FCE
1428void
1429typeresolution_info::visit_foreach_loop (foreach_loop* e)
1430{
1431 // See also visit_arrayindex.
1432 // This is different in that, being a statement, we can't assign
1433 // a type to the outer array, only propagate to/from the indexes
1434
1435 // if (e->referent->index_types.size() == 0)
1436 // // redesignate referent as array
1437 // e->referent->set_arity (e->indexes.size ());
1438
1439 if (e->indexes.size() != e->base_referent->index_types.size())
1440 unresolved (e->tok); // symbol resolution should prevent this
1441 else for (unsigned i=0; i<e->indexes.size(); i++)
1442 {
1443 expression* ee = e->indexes[i];
1444 exp_type& ft = e->base_referent->index_types [i];
1445 t = ft;
1446 ee->visit (this);
1447 exp_type at = ee->type;
1448
1449 if ((at == pe_string || at == pe_long) && ft == pe_unknown)
1450 {
1451 // propagate to formal type
1452 ft = at;
1453 resolved (e->base_referent->tok, ft);
1454 // uses array decl as there is no token for "formal type"
1455 }
1456 if (at == pe_stats)
1457 invalid (ee->tok, at);
1458 if (ft == pe_stats)
1459 invalid (ee->tok, ft);
1460 if (at != pe_unknown && ft != pe_unknown && ft != at)
1461 mismatch (e->tok, at, ft);
1462 if (at == pe_unknown)
1463 unresolved (ee->tok);
1464 }
1465
1466 t = pe_unknown;
1467 e->block->visit (this);
1468}
1469
1470
2b066ec1
FCE
1471void
1472typeresolution_info::visit_null_statement (null_statement* e)
1473{
1474}
1475
1476
1477void
1478typeresolution_info::visit_expr_statement (expr_statement* e)
1479{
1480 t = pe_unknown;
1481 e->value->visit (this);
1482}
1483
1484
1485void
1486typeresolution_info::visit_delete_statement (delete_statement* e)
1487{
1488 // XXX: not yet supported
1489 unresolved (e->tok);
1490}
1491
1492
f3c26ea5
FCE
1493void
1494typeresolution_info::visit_next_statement (next_statement* s)
1495{
1496}
1497
1498
1499void
1500typeresolution_info::visit_break_statement (break_statement* s)
1501{
1502}
1503
1504
1505void
1506typeresolution_info::visit_continue_statement (continue_statement* s)
1507{
1508}
1509
1510
2b066ec1
FCE
1511void
1512typeresolution_info::visit_array_in (array_in* e)
1513{
ce10591c
FCE
1514 // all unary operators only work on numerics
1515 exp_type t1 = t;
1516 t = pe_unknown; // array value can be anything
1517 e->operand->visit (this);
1518
1519 if (t1 == pe_unknown && e->type != pe_unknown)
1520 ; // already resolved
1521 else if (t1 == pe_string || t1 == pe_stats)
1522 mismatch (e->tok, t1, pe_long);
1523 else if (e->type == pe_unknown)
1524 {
1525 e->type = pe_long;
1526 resolved (e->tok, e->type);
1527 }
2b066ec1
FCE
1528}
1529
1530
1531void
1532typeresolution_info::visit_return_statement (return_statement* e)
1533{
1534 // This is like symbol, where the referent is
1535 // the return value of the function.
1536
22f46231 1537 // translation pass will print error
2b066ec1 1538 if (current_function == 0)
22f46231 1539 return;
2b066ec1
FCE
1540
1541 exp_type& e_type = current_function->type;
1542 t = current_function->type;
1543 e->value->visit (this);
1544
1545 if (e_type != pe_unknown && e->value->type != pe_unknown
1546 && e_type != e->value->type)
1547 mismatch (current_function->tok, e_type, e->value->type);
1548 if (e_type == pe_unknown &&
1549 (e->value->type == pe_long || e->value->type == pe_string))
1550 {
1551 // propagate non-statistics from value
1552 e_type = e->value->type;
1553 resolved (current_function->tok, e->value->type);
1554 }
1555 if (e->value->type == pe_stats)
1556 invalid (e->value->tok, e->value->type);
1557}
1558
1559
1560void
1561typeresolution_info::unresolved (const token* tok)
1562{
1563 num_still_unresolved ++;
1564
1565 if (assert_resolvability)
1566 {
1567 cerr << "error: unresolved type for ";
1568 if (tok)
1569 cerr << *tok;
1570 else
1571 cerr << "a token";
1572 cerr << endl;
1573 }
1574}
1575
1576
1577void
1578typeresolution_info::invalid (const token* tok, exp_type pe)
1579{
1580 num_still_unresolved ++;
1581
1582 if (assert_resolvability)
1583 {
1584 cerr << "error: invalid type " << pe << " for ";
1585 if (tok)
1586 cerr << *tok;
1587 else
1588 cerr << "a token";
1589 cerr << endl;
1590 }
1591}
1592
1593
1594void
1595typeresolution_info::mismatch (const token* tok, exp_type t1, exp_type t2)
1596{
1597 num_still_unresolved ++;
1598
1599 if (assert_resolvability)
1600 {
1601 cerr << "error: type mismatch for ";
1602 if (tok)
1603 cerr << *tok;
1604 else
1605 cerr << "a token";
1606 cerr << ": " << t1 << " vs. " << t2 << endl;
1607 }
1608}
1609
1610
1611void
1612typeresolution_info::resolved (const token* tok, exp_type t)
1613{
1614 num_newly_resolved ++;
1615 // cerr << "resolved " << *e->tok << " type " << t << endl;
1616}
1617
This page took 0.229236 seconds and 5 git commands to generate.