]> sourceware.org Git - systemtap.git/blob - translate.cxx
Merge branch 'master' of git://sources.redhat.com/git/systemtap
[systemtap.git] / translate.cxx
1 // translation pass
2 // Copyright (C) 2005-2009 Red Hat Inc.
3 // Copyright (C) 2005-2008 Intel Corporation.
4 //
5 // This file is part of systemtap, and is free software. You can
6 // redistribute it and/or modify it under the terms of the GNU General
7 // Public License (GPL); either version 2, or (at your option) any
8 // later version.
9
10 #include "config.h"
11 #include "staptree.h"
12 #include "elaborate.h"
13 #include "translate.h"
14 #include "session.h"
15 #include "tapsets.h"
16 #include "util.h"
17 #include "dwarf_wrappers.h"
18
19 #include <cstdlib>
20 #include <iostream>
21 #include <set>
22 #include <sstream>
23 #include <string>
24 #include <cassert>
25 #include <cstring>
26
27 extern "C" {
28 #include <elfutils/libdwfl.h>
29 #ifdef HAVE_ELFUTILS_VERSION_H
30 #include <elfutils/version.h>
31 #endif
32 }
33
34 using namespace std;
35
36 struct var;
37 struct tmpvar;
38 struct aggvar;
39 struct mapvar;
40 struct itervar;
41
42 struct c_unparser: public unparser, public visitor
43 {
44 systemtap_session* session;
45 translator_output* o;
46
47 derived_probe* current_probe;
48 functiondecl* current_function;
49 unsigned tmpvar_counter;
50 unsigned label_counter;
51 unsigned action_counter;
52 bool probe_or_function_needs_deref_fault_handler;
53
54 varuse_collecting_visitor vcv_needs_global_locks;
55
56 map<string, string> probe_contents;
57
58 c_unparser (systemtap_session* ss):
59 session (ss), o (ss->op), current_probe(0), current_function (0),
60 tmpvar_counter (0), label_counter (0) {}
61 ~c_unparser () {}
62
63 void emit_map_type_instantiations ();
64 void emit_common_header ();
65 void emit_global (vardecl* v);
66 void emit_global_init (vardecl* v);
67 void emit_global_param (vardecl* v);
68 void emit_functionsig (functiondecl* v);
69 void emit_module_init ();
70 void emit_module_exit ();
71 void emit_function (functiondecl* v);
72 void emit_locks (const varuse_collecting_visitor& v);
73 void emit_probe (derived_probe* v);
74 void emit_unlocks (const varuse_collecting_visitor& v);
75
76 // for use by stats (pmap) foreach
77 set<string> aggregations_active;
78
79 // for use by looping constructs
80 vector<string> loop_break_labels;
81 vector<string> loop_continue_labels;
82
83 string c_typename (exp_type e);
84 string c_varname (const string& e);
85 string c_expression (expression* e);
86
87 void c_assign (var& lvalue, const string& rvalue, const token* tok);
88 void c_assign (const string& lvalue, expression* rvalue, const string& msg);
89 void c_assign (const string& lvalue, const string& rvalue, exp_type type,
90 const string& msg, const token* tok);
91
92 void c_declare(exp_type ty, const string &name);
93 void c_declare_static(exp_type ty, const string &name);
94
95 void c_strcat (const string& lvalue, const string& rvalue);
96 void c_strcat (const string& lvalue, expression* rvalue);
97
98 void c_strcpy (const string& lvalue, const string& rvalue);
99 void c_strcpy (const string& lvalue, expression* rvalue);
100
101 bool is_local (vardecl const* r, token const* tok);
102
103 tmpvar gensym(exp_type ty);
104 aggvar gensym_aggregate();
105
106 var getvar(vardecl* v, token const* tok = NULL);
107 itervar getiter(symbol* s);
108 mapvar getmap(vardecl* v, token const* tok = NULL);
109
110 void load_map_indices(arrayindex* e,
111 vector<tmpvar> & idx);
112
113 void load_aggregate (expression *e, aggvar & agg, bool pre_agg=false);
114 string histogram_index_check(var & vase, tmpvar & idx) const;
115
116 void collect_map_index_types(vector<vardecl* > const & vars,
117 set< pair<vector<exp_type>, exp_type> > & types);
118
119 void record_actions (unsigned actions, bool update=false);
120
121 void visit_block (block* s);
122 void visit_embeddedcode (embeddedcode* s);
123 void visit_null_statement (null_statement* s);
124 void visit_expr_statement (expr_statement* s);
125 void visit_if_statement (if_statement* s);
126 void visit_for_loop (for_loop* s);
127 void visit_foreach_loop (foreach_loop* s);
128 void visit_return_statement (return_statement* s);
129 void visit_delete_statement (delete_statement* s);
130 void visit_next_statement (next_statement* s);
131 void visit_break_statement (break_statement* s);
132 void visit_continue_statement (continue_statement* s);
133 void visit_literal_string (literal_string* e);
134 void visit_literal_number (literal_number* e);
135 void visit_binary_expression (binary_expression* e);
136 void visit_unary_expression (unary_expression* e);
137 void visit_pre_crement (pre_crement* e);
138 void visit_post_crement (post_crement* e);
139 void visit_logical_or_expr (logical_or_expr* e);
140 void visit_logical_and_expr (logical_and_expr* e);
141 void visit_array_in (array_in* e);
142 void visit_comparison (comparison* e);
143 void visit_concatenation (concatenation* e);
144 void visit_ternary_expression (ternary_expression* e);
145 void visit_assignment (assignment* e);
146 void visit_symbol (symbol* e);
147 void visit_target_symbol (target_symbol* e);
148 void visit_arrayindex (arrayindex* e);
149 void visit_functioncall (functioncall* e);
150 void visit_print_format (print_format* e);
151 void visit_stat_op (stat_op* e);
152 void visit_hist_op (hist_op* e);
153 void visit_cast_op (cast_op* e);
154 };
155
156 // A shadow visitor, meant to generate temporary variable declarations
157 // for function or probe bodies. Member functions should exactly match
158 // the corresponding c_unparser logic and traversal sequence,
159 // to ensure interlocking naming and declaration of temp variables.
160 struct c_tmpcounter:
161 public traversing_visitor
162 {
163 c_unparser* parent;
164 c_tmpcounter (c_unparser* p):
165 parent (p)
166 {
167 parent->tmpvar_counter = 0;
168 }
169
170 void load_map_indices(arrayindex* e);
171
172 void visit_block (block *s);
173 void visit_for_loop (for_loop* s);
174 void visit_foreach_loop (foreach_loop* s);
175 // void visit_return_statement (return_statement* s);
176 void visit_delete_statement (delete_statement* s);
177 void visit_binary_expression (binary_expression* e);
178 // void visit_unary_expression (unary_expression* e);
179 void visit_pre_crement (pre_crement* e);
180 void visit_post_crement (post_crement* e);
181 // void visit_logical_or_expr (logical_or_expr* e);
182 // void visit_logical_and_expr (logical_and_expr* e);
183 void visit_array_in (array_in* e);
184 // void visit_comparison (comparison* e);
185 void visit_concatenation (concatenation* e);
186 // void visit_ternary_expression (ternary_expression* e);
187 void visit_assignment (assignment* e);
188 void visit_arrayindex (arrayindex* e);
189 void visit_functioncall (functioncall* e);
190 void visit_print_format (print_format* e);
191 void visit_stat_op (stat_op* e);
192 };
193
194 struct c_unparser_assignment:
195 public throwing_visitor
196 {
197 c_unparser* parent;
198 string op;
199 expression* rvalue;
200 bool post; // true == value saved before modify operator
201 c_unparser_assignment (c_unparser* p, const string& o, expression* e):
202 throwing_visitor ("invalid lvalue type"),
203 parent (p), op (o), rvalue (e), post (false) {}
204 c_unparser_assignment (c_unparser* p, const string& o, bool pp):
205 throwing_visitor ("invalid lvalue type"),
206 parent (p), op (o), rvalue (0), post (pp) {}
207
208 void prepare_rvalue (string const & op,
209 tmpvar & rval,
210 token const* tok);
211
212 void c_assignop(tmpvar & res,
213 var const & lvar,
214 tmpvar const & tmp,
215 token const* tok);
216
217 // only symbols and arrayindex nodes are possible lvalues
218 void visit_symbol (symbol* e);
219 void visit_arrayindex (arrayindex* e);
220 };
221
222
223 struct c_tmpcounter_assignment:
224 public traversing_visitor
225 // leave throwing for illegal lvalues to the c_unparser_assignment instance
226 {
227 c_tmpcounter* parent;
228 const string& op;
229 expression* rvalue;
230 bool post; // true == value saved before modify operator
231 c_tmpcounter_assignment (c_tmpcounter* p, const string& o, expression* e, bool pp = false):
232 parent (p), op (o), rvalue (e), post (pp) {}
233
234 void prepare_rvalue (tmpvar & rval);
235
236 void c_assignop(tmpvar & res);
237
238 // only symbols and arrayindex nodes are possible lvalues
239 void visit_symbol (symbol* e);
240 void visit_arrayindex (arrayindex* e);
241 };
242
243
244 ostream & operator<<(ostream & o, var const & v);
245
246
247 /*
248 Some clarification on the runtime structures involved in statistics:
249
250 The basic type for collecting statistics in the runtime is struct
251 stat_data. This contains the count, min, max, sum, and possibly
252 histogram fields.
253
254 There are two places struct stat_data shows up.
255
256 1. If you declare a statistic variable of any sort, you want to make
257 a struct _Stat. A struct _Stat* is also called a Stat. Struct _Stat
258 contains a per-CPU array of struct stat_data values, as well as a
259 struct stat_data which it aggregates into. Writes into a Struct
260 _Stat go into the per-CPU struct stat. Reads involve write-locking
261 the struct _Stat, aggregating into its aggregate struct stat_data,
262 unlocking, read-locking the struct _Stat, then reading values out of
263 the aggregate and unlocking.
264
265 2. If you declare a statistic-valued map, you want to make a
266 pmap. This is a per-CPU array of maps, each of which holds struct
267 stat_data values, as well as an aggregate *map*. Writes into a pmap
268 go into the per-CPU map. Reads involve write-locking the pmap,
269 aggregating into its aggregate map, unlocking, read-locking the
270 pmap, then reading values out of its aggregate (which is a normal
271 map) and unlocking.
272
273 Because, at the moment, the runtime does not support the concept of
274 a statistic which collects multiple histogram types, we may need to
275 instantiate one pmap or struct _Stat for each histogram variation
276 the user wants to track.
277 */
278
279 class var
280 {
281
282 protected:
283 bool local;
284 exp_type ty;
285 statistic_decl sd;
286 string name;
287
288 public:
289
290 var(bool local, exp_type ty, statistic_decl const & sd, string const & name)
291 : local(local), ty(ty), sd(sd), name(name)
292 {}
293
294 var(bool local, exp_type ty, string const & name)
295 : local(local), ty(ty), name(name)
296 {}
297
298 virtual ~var() {}
299
300 bool is_local() const
301 {
302 return local;
303 }
304
305 statistic_decl const & sdecl() const
306 {
307 return sd;
308 }
309
310 void assert_hist_compatible(hist_op const & hop)
311 {
312 // Semantic checks in elaborate should have caught this if it was
313 // false. This is just a double-check.
314 switch (sd.type)
315 {
316 case statistic_decl::linear:
317 assert(hop.htype == hist_linear);
318 assert(hop.params.size() == 3);
319 assert(hop.params[0] == sd.linear_low);
320 assert(hop.params[1] == sd.linear_high);
321 assert(hop.params[2] == sd.linear_step);
322 break;
323 case statistic_decl::logarithmic:
324 assert(hop.htype == hist_log);
325 assert(hop.params.size() == 0);
326 break;
327 case statistic_decl::none:
328 assert(false);
329 }
330 }
331
332 exp_type type() const
333 {
334 return ty;
335 }
336
337 string value() const
338 {
339 if (local)
340 return "l->" + name;
341 else
342 return "global.s_" + name;
343 }
344
345 virtual string hist() const
346 {
347 assert (ty == pe_stats);
348 assert (sd.type != statistic_decl::none);
349 return "(&(" + value() + "->hist))";
350 }
351
352 virtual string buckets() const
353 {
354 assert (ty == pe_stats);
355 assert (sd.type != statistic_decl::none);
356 return "(" + value() + "->hist.buckets)";
357 }
358
359 string init() const
360 {
361 switch (type())
362 {
363 case pe_string:
364 if (! local)
365 return ""; // module_param
366 else
367 return value() + "[0] = '\\0';";
368 case pe_long:
369 if (! local)
370 return ""; // module_param
371 else
372 return value() + " = 0;";
373 case pe_stats:
374 {
375 // See also mapvar::init().
376
377 string prefix = value() + " = _stp_stat_init (";
378 // Check for errors during allocation.
379 string suffix = "if (" + value () + " == NULL) rc = -ENOMEM;";
380
381 switch (sd.type)
382 {
383 case statistic_decl::none:
384 prefix += "HIST_NONE";
385 break;
386
387 case statistic_decl::linear:
388 prefix += string("HIST_LINEAR")
389 + ", " + stringify(sd.linear_low)
390 + ", " + stringify(sd.linear_high)
391 + ", " + stringify(sd.linear_step);
392 break;
393
394 case statistic_decl::logarithmic:
395 prefix += string("HIST_LOG");
396 break;
397
398 default:
399 throw semantic_error("unsupported stats type for " + value());
400 }
401
402 prefix = prefix + "); ";
403 return string (prefix + suffix);
404 }
405
406 default:
407 throw semantic_error("unsupported initializer for " + value());
408 }
409 }
410
411 string fini () const
412 {
413 switch (type())
414 {
415 case pe_string:
416 case pe_long:
417 return ""; // no action required
418 case pe_stats:
419 return "_stp_stat_del (" + value () + ");";
420 default:
421 throw semantic_error("unsupported deallocator for " + value());
422 }
423 }
424
425 void declare(c_unparser &c) const
426 {
427 c.c_declare(ty, name);
428 }
429 };
430
431 ostream & operator<<(ostream & o, var const & v)
432 {
433 return o << v.value();
434 }
435
436 struct stmt_expr
437 {
438 c_unparser & c;
439 stmt_expr(c_unparser & c) : c(c)
440 {
441 c.o->newline() << "({";
442 c.o->indent(1);
443 }
444 ~stmt_expr()
445 {
446 c.o->newline(-1) << "})";
447 }
448 };
449
450
451 struct tmpvar
452 : public var
453 {
454 protected:
455 bool overridden;
456 string override_value;
457
458 public:
459 tmpvar(exp_type ty,
460 unsigned & counter)
461 : var(true, ty, ("__tmp" + stringify(counter++))), overridden(false)
462 {}
463
464 tmpvar(const var& source)
465 : var(source), overridden(false)
466 {}
467
468 void override(const string &value)
469 {
470 overridden = true;
471 override_value = value;
472 }
473
474 string value() const
475 {
476 if (overridden)
477 return override_value;
478 else
479 return var::value();
480 }
481 };
482
483 ostream & operator<<(ostream & o, tmpvar const & v)
484 {
485 return o << v.value();
486 }
487
488 struct aggvar
489 : public var
490 {
491 aggvar(unsigned & counter)
492 : var(true, pe_stats, ("__tmp" + stringify(counter++)))
493 {}
494
495 string init() const
496 {
497 assert (type() == pe_stats);
498 return value() + " = NULL;";
499 }
500
501 void declare(c_unparser &c) const
502 {
503 assert (type() == pe_stats);
504 c.o->newline() << "struct stat_data *" << name << ";";
505 }
506 };
507
508 struct mapvar
509 : public var
510 {
511 vector<exp_type> index_types;
512 int maxsize;
513 mapvar (bool local, exp_type ty,
514 statistic_decl const & sd,
515 string const & name,
516 vector<exp_type> const & index_types,
517 int maxsize)
518 : var (local, ty, sd, name),
519 index_types (index_types),
520 maxsize (maxsize)
521 {}
522
523 static string shortname(exp_type e);
524 static string key_typename(exp_type e);
525 static string value_typename(exp_type e);
526
527 string keysym () const
528 {
529 string result;
530 vector<exp_type> tmp = index_types;
531 tmp.push_back (type ());
532 for (unsigned i = 0; i < tmp.size(); ++i)
533 {
534 switch (tmp[i])
535 {
536 case pe_long:
537 result += 'i';
538 break;
539 case pe_string:
540 result += 's';
541 break;
542 case pe_stats:
543 result += 'x';
544 break;
545 default:
546 throw semantic_error("unknown type of map");
547 break;
548 }
549 }
550 return result;
551 }
552
553 string call_prefix (string const & fname, vector<tmpvar> const & indices, bool pre_agg=false) const
554 {
555 string mtype = (is_parallel() && !pre_agg) ? "pmap" : "map";
556 string result = "_stp_" + mtype + "_" + fname + "_" + keysym() + " (";
557 result += pre_agg? fetch_existing_aggregate() : value();
558 for (unsigned i = 0; i < indices.size(); ++i)
559 {
560 if (indices[i].type() != index_types[i])
561 throw semantic_error("index type mismatch");
562 result += ", ";
563 result += indices[i].value();
564 }
565
566 return result;
567 }
568
569 bool is_parallel() const
570 {
571 return type() == pe_stats;
572 }
573
574 string calculate_aggregate() const
575 {
576 if (!is_parallel())
577 throw semantic_error("aggregating non-parallel map type");
578
579 return "_stp_pmap_agg (" + value() + ")";
580 }
581
582 string fetch_existing_aggregate() const
583 {
584 if (!is_parallel())
585 throw semantic_error("fetching aggregate of non-parallel map type");
586
587 return "_stp_pmap_get_agg(" + value() + ")";
588 }
589
590 string del (vector<tmpvar> const & indices) const
591 {
592 return (call_prefix("del", indices) + ")");
593 }
594
595 string exists (vector<tmpvar> const & indices) const
596 {
597 if (type() == pe_long || type() == pe_string)
598 return (call_prefix("exists", indices) + ")");
599 else if (type() == pe_stats)
600 return ("((uintptr_t)" + call_prefix("get", indices)
601 + ") != (uintptr_t) 0)");
602 else
603 throw semantic_error("checking existence of an unsupported map type");
604 }
605
606 string get (vector<tmpvar> const & indices, bool pre_agg=false) const
607 {
608 // see also itervar::get_key
609 if (type() == pe_string)
610 // impedance matching: NULL -> empty strings
611 return ("({ char *v = " + call_prefix("get", indices, pre_agg) + ");"
612 + "if (!v) v = \"\"; v; })");
613 else if (type() == pe_long || type() == pe_stats)
614 return call_prefix("get", indices, pre_agg) + ")";
615 else
616 throw semantic_error("getting a value from an unsupported map type");
617 }
618
619 string add (vector<tmpvar> const & indices, tmpvar const & val) const
620 {
621 string res = "{ int rc = ";
622
623 // impedance matching: empty strings -> NULL
624 if (type() == pe_stats)
625 res += (call_prefix("add", indices) + ", " + val.value() + ")");
626 else
627 throw semantic_error("adding a value of an unsupported map type");
628
629 res += "; if (unlikely(rc)) { c->last_error = \"Array overflow, check " +
630 stringify(maxsize > 0 ?
631 "size limit (" + stringify(maxsize) + ")" : "MAXMAPENTRIES")
632 + "\"; goto out; }}";
633
634 return res;
635 }
636
637 string set (vector<tmpvar> const & indices, tmpvar const & val) const
638 {
639 string res = "{ int rc = ";
640
641 // impedance matching: empty strings -> NULL
642 if (type() == pe_string)
643 res += (call_prefix("set", indices)
644 + ", (" + val.value() + "[0] ? " + val.value() + " : NULL))");
645 else if (type() == pe_long)
646 res += (call_prefix("set", indices) + ", " + val.value() + ")");
647 else
648 throw semantic_error("setting a value of an unsupported map type");
649
650 res += "; if (unlikely(rc)) { c->last_error = \"Array overflow, check " +
651 stringify(maxsize > 0 ?
652 "size limit (" + stringify(maxsize) + ")" : "MAXMAPENTRIES")
653 + "\"; goto out; }}";
654
655 return res;
656 }
657
658 string hist() const
659 {
660 assert (ty == pe_stats);
661 assert (sd.type != statistic_decl::none);
662 return "(&(" + fetch_existing_aggregate() + "->hist))";
663 }
664
665 string buckets() const
666 {
667 assert (ty == pe_stats);
668 assert (sd.type != statistic_decl::none);
669 return "(" + fetch_existing_aggregate() + "->hist.buckets)";
670 }
671
672 string init () const
673 {
674 string mtype = is_parallel() ? "pmap" : "map";
675 string prefix = value() + " = _stp_" + mtype + "_new_" + keysym() + " (" +
676 (maxsize > 0 ? stringify(maxsize) : "MAXMAPENTRIES") ;
677
678 // See also var::init().
679
680 // Check for errors during allocation.
681 string suffix = "if (" + value () + " == NULL) rc = -ENOMEM;";
682
683 if (type() == pe_stats)
684 {
685 switch (sdecl().type)
686 {
687 case statistic_decl::none:
688 prefix = prefix + ", HIST_NONE";
689 break;
690
691 case statistic_decl::linear:
692 // FIXME: check for "reasonable" values in linear stats
693 prefix = prefix + ", HIST_LINEAR"
694 + ", " + stringify(sdecl().linear_low)
695 + ", " + stringify(sdecl().linear_high)
696 + ", " + stringify(sdecl().linear_step);
697 break;
698
699 case statistic_decl::logarithmic:
700 prefix = prefix + ", HIST_LOG";
701 break;
702 }
703 }
704
705 prefix = prefix + "); ";
706 return (prefix + suffix);
707 }
708
709 string fini () const
710 {
711 // NB: fini() is safe to call even for globals that have not
712 // successfully initialized (that is to say, on NULL pointers),
713 // because the runtime specifically tolerates that in its _del
714 // functions.
715
716 if (is_parallel())
717 return "_stp_pmap_del (" + value() + ");";
718 else
719 return "_stp_map_del (" + value() + ");";
720 }
721 };
722
723
724 class itervar
725 {
726 exp_type referent_ty;
727 string name;
728
729 public:
730
731 itervar (symbol* e, unsigned & counter)
732 : referent_ty(e->referent->type),
733 name("__tmp" + stringify(counter++))
734 {
735 if (referent_ty == pe_unknown)
736 throw semantic_error("iterating over unknown reference type", e->tok);
737 }
738
739 string declare () const
740 {
741 return "struct map_node *" + name + ";";
742 }
743
744 string start (mapvar const & mv) const
745 {
746 string res;
747
748 if (mv.type() != referent_ty)
749 throw semantic_error("inconsistent iterator type in itervar::start()");
750
751 if (mv.is_parallel())
752 return "_stp_map_start (" + mv.fetch_existing_aggregate() + ")";
753 else
754 return "_stp_map_start (" + mv.value() + ")";
755 }
756
757 string next (mapvar const & mv) const
758 {
759 if (mv.type() != referent_ty)
760 throw semantic_error("inconsistent iterator type in itervar::next()");
761
762 if (mv.is_parallel())
763 return "_stp_map_iter (" + mv.fetch_existing_aggregate() + ", " + value() + ")";
764 else
765 return "_stp_map_iter (" + mv.value() + ", " + value() + ")";
766 }
767
768 string value () const
769 {
770 return "l->" + name;
771 }
772
773 string get_key (exp_type ty, unsigned i) const
774 {
775 // bug translator/1175: runtime uses base index 1 for the first dimension
776 // see also mapval::get
777 switch (ty)
778 {
779 case pe_long:
780 return "_stp_key_get_int64 ("+ value() + ", " + stringify(i+1) + ")";
781 case pe_string:
782 // impedance matching: NULL -> empty strings
783 return "({ char *v = "
784 "_stp_key_get_str ("+ value() + ", " + stringify(i+1) + "); "
785 "if (! v) v = \"\"; "
786 "v; })";
787 default:
788 throw semantic_error("illegal key type");
789 }
790 }
791 };
792
793 ostream & operator<<(ostream & o, itervar const & v)
794 {
795 return o << v.value();
796 }
797
798 // ------------------------------------------------------------------------
799
800
801 translator_output::translator_output (ostream& f):
802 buf(0), o2 (0), o (f), tablevel (0)
803 {
804 }
805
806
807 translator_output::translator_output (const string& filename, size_t bufsize):
808 buf (new char[bufsize]),
809 o2 (new ofstream (filename.c_str ())),
810 o (*o2),
811 tablevel (0)
812 {
813 o2->rdbuf()->pubsetbuf(buf, bufsize);
814 }
815
816
817 translator_output::~translator_output ()
818 {
819 delete o2;
820 delete [] buf;
821 }
822
823
824 ostream&
825 translator_output::newline (int indent)
826 {
827 if (! (indent > 0 || tablevel >= (unsigned)-indent)) o.flush ();
828 assert (indent > 0 || tablevel >= (unsigned)-indent);
829
830 tablevel += indent;
831 o << "\n";
832 for (unsigned i=0; i<tablevel; i++)
833 o << " ";
834 return o;
835 }
836
837
838 void
839 translator_output::indent (int indent)
840 {
841 if (! (indent > 0 || tablevel >= (unsigned)-indent)) o.flush ();
842 assert (indent > 0 || tablevel >= (unsigned)-indent);
843 tablevel += indent;
844 }
845
846
847 ostream&
848 translator_output::line ()
849 {
850 return o;
851 }
852
853
854 // ------------------------------------------------------------------------
855
856 void
857 c_unparser::emit_common_header ()
858 {
859 o->newline();
860 o->newline() << "typedef char string_t[MAXSTRINGLEN];";
861 o->newline();
862 o->newline() << "#define STAP_SESSION_STARTING 0";
863 o->newline() << "#define STAP_SESSION_RUNNING 1";
864 o->newline() << "#define STAP_SESSION_ERROR 2";
865 o->newline() << "#define STAP_SESSION_STOPPING 3";
866 o->newline() << "#define STAP_SESSION_STOPPED 4";
867 o->newline() << "static atomic_t session_state = ATOMIC_INIT (STAP_SESSION_STARTING);";
868 o->newline() << "static atomic_t error_count = ATOMIC_INIT (0);";
869 o->newline() << "static atomic_t skipped_count = ATOMIC_INIT (0);";
870 o->newline() << "#ifdef STP_TIMING";
871 o->newline() << "static atomic_t skipped_count_lowstack = ATOMIC_INIT (0);";
872 o->newline() << "static atomic_t skipped_count_reentrant = ATOMIC_INIT (0);";
873 o->newline() << "static atomic_t skipped_count_uprobe_reg = ATOMIC_INIT (0);";
874 o->newline() << "static atomic_t skipped_count_uprobe_unreg = ATOMIC_INIT (0);";
875 o->newline() << "#endif";
876 o->newline();
877 o->newline() << "struct context {";
878 o->newline(1) << "atomic_t busy;";
879 o->newline() << "const char *probe_point;";
880 o->newline() << "int actionremaining;";
881 o->newline() << "unsigned nesting;";
882 o->newline() << "string_t error_buffer;";
883 o->newline() << "const char *last_error;";
884 // NB: last_error is used as a health flag within a probe.
885 // While it's 0, execution continues
886 // When it's "something", probe code unwinds, _stp_error's, sets error state
887 o->newline() << "const char *last_stmt;";
888 o->newline() << "struct pt_regs *regs;";
889 o->newline() << "unsigned long *unwaddr;";
890 // unwaddr is caching unwound address in each probe handler on ia64.
891 o->newline() << "struct kretprobe_instance *pi;";
892 o->newline() << "int regparm;";
893 o->newline() << "va_list *mark_va_list;";
894 o->newline() << "const char * marker_name;";
895 o->newline() << "const char * marker_format;";
896 o->newline() << "void *data;";
897 o->newline() << "#ifdef STP_TIMING";
898 o->newline() << "Stat *statp;";
899 o->newline() << "#endif";
900 o->newline() << "#ifdef STP_OVERLOAD";
901 o->newline() << "cycles_t cycles_base;";
902 o->newline() << "cycles_t cycles_sum;";
903 o->newline() << "#endif";
904 o->newline() << "union {";
905 o->indent(1);
906
907 // To elide context variables for probe handler functions that
908 // themselves are about to get duplicate-eliminated, we XXX
909 // duplicate the parse-tree-hash method from ::emit_probe().
910 map<string, string> tmp_probe_contents;
911 // The reason we don't use c_unparser::probe_contents itself
912 // for this is that we don't want to muck up the data for
913 // that later routine.
914
915 for (unsigned i=0; i<session->probes.size(); i++)
916 {
917 derived_probe* dp = session->probes[i];
918
919 // NB: see c_unparser::emit_probe() for original copy of duplicate-hashing logic.
920 ostringstream oss;
921 oss << "c->statp = & time_" << dp->basest()->name << ";" << endl; // -t anti-dupe
922 oss << "# needs_global_locks: " << dp->needs_global_locks () << endl;
923 dp->body->print(oss);
924 // NB: dependent probe conditions *could* be listed here, but don't need to be.
925 // That's because they're only dependent on the probe body, which is already
926 // "hashed" in above.
927
928
929 if (tmp_probe_contents.count(oss.str()) == 0) // unique
930 {
931 tmp_probe_contents[oss.str()] = dp->name; // save it
932
933 // XXX: probe locals need not be recursion-nested, only function locals
934
935 o->newline() << "struct " << dp->name << "_locals {";
936 o->indent(1);
937 for (unsigned j=0; j<dp->locals.size(); j++)
938 {
939 vardecl* v = dp->locals[j];
940 try
941 {
942 o->newline() << c_typename (v->type) << " "
943 << c_varname (v->name) << ";";
944 } catch (const semantic_error& e) {
945 semantic_error e2 (e);
946 if (e2.tok1 == 0) e2.tok1 = v->tok;
947 throw e2;
948 }
949 }
950
951 // NB: This part is finicky. The logic here must
952 // match up with
953 c_tmpcounter ct (this);
954 dp->emit_probe_context_vars (o);
955 dp->body->visit (& ct);
956
957 o->newline(-1) << "} " << dp->name << ";";
958 }
959 }
960
961 for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++)
962 {
963 functiondecl* fd = it->second;
964 o->newline()
965 << "struct function_" << c_varname (fd->name) << "_locals {";
966 o->indent(1);
967 for (unsigned j=0; j<fd->locals.size(); j++)
968 {
969 vardecl* v = fd->locals[j];
970 try
971 {
972 o->newline() << c_typename (v->type) << " "
973 << c_varname (v->name) << ";";
974 } catch (const semantic_error& e) {
975 semantic_error e2 (e);
976 if (e2.tok1 == 0) e2.tok1 = v->tok;
977 throw e2;
978 }
979 }
980 for (unsigned j=0; j<fd->formal_args.size(); j++)
981 {
982 vardecl* v = fd->formal_args[j];
983 try
984 {
985 o->newline() << c_typename (v->type) << " "
986 << c_varname (v->name) << ";";
987 } catch (const semantic_error& e) {
988 semantic_error e2 (e);
989 if (e2.tok1 == 0) e2.tok1 = v->tok;
990 throw e2;
991 }
992 }
993 c_tmpcounter ct (this);
994 fd->body->visit (& ct);
995 if (fd->type == pe_unknown)
996 o->newline() << "/* no return value */";
997 else
998 {
999 o->newline() << c_typename (fd->type) << " __retvalue;";
1000 }
1001 o->newline(-1) << "} function_" << c_varname (fd->name) << ";";
1002 }
1003 o->newline(-1) << "} locals [MAXNESTING];";
1004 o->newline(-1) << "};\n";
1005 o->newline() << "static void *contexts = NULL; /* alloc_percpu */\n";
1006
1007 emit_map_type_instantiations ();
1008
1009 if (!session->stat_decls.empty())
1010 o->newline() << "#include \"stat.c\"\n";
1011
1012 o->newline();
1013 }
1014
1015
1016 void
1017 c_unparser::emit_global_param (vardecl *v)
1018 {
1019 string vn = c_varname (v->name);
1020
1021 // NB: systemtap globals can collide with linux macros,
1022 // e.g. VM_FAULT_MAJOR. We want the parameter name anyway. This
1023 // #undef is spit out at the end of the C file, so that removing the
1024 // definition won't affect any other embedded-C or generated code.
1025 // XXX: better not have a global variable named module_param_named etc.!
1026 o->newline() << "#undef " << vn;
1027
1028 // Emit module_params for this global, if its type is convenient.
1029 if (v->arity == 0 && v->type == pe_long)
1030 {
1031 o->newline() << "module_param_named (" << vn << ", "
1032 << "global.s_" << vn << ", int64_t, 0);";
1033 }
1034 else if (v->arity == 0 && v->type == pe_string)
1035 {
1036 // NB: no special copying is needed.
1037 o->newline() << "module_param_string (" << vn << ", "
1038 << "global.s_" << vn
1039 << ", MAXSTRINGLEN, 0);";
1040 }
1041 }
1042
1043
1044 void
1045 c_unparser::emit_global (vardecl *v)
1046 {
1047 string vn = c_varname (v->name);
1048
1049 if (v->arity == 0)
1050 o->newline() << c_typename (v->type) << " s_" << vn << ";";
1051 else if (v->type == pe_stats)
1052 o->newline() << "PMAP s_" << vn << ";";
1053 else
1054 o->newline() << "MAP s_" << vn << ";";
1055 o->newline() << "rwlock_t s_" << vn << "_lock;";
1056 o->newline() << "#ifdef STP_TIMING";
1057 o->newline() << "atomic_t s_" << vn << "_lock_skip_count;";
1058 o->newline() << "#endif\n";
1059 }
1060
1061
1062 void
1063 c_unparser::emit_global_init (vardecl *v)
1064 {
1065 string vn = c_varname (v->name);
1066
1067 if (v->arity == 0) // can only statically initialize some scalars
1068 {
1069 if (v->init)
1070 {
1071 o->newline() << ".s_" << vn << " = ";
1072 v->init->visit(this);
1073 o->line() << ",";
1074 }
1075 }
1076 o->newline() << "#ifdef STP_TIMING";
1077 o->newline() << ".s_" << vn << "_lock_skip_count = ATOMIC_INIT(0),";
1078 o->newline() << "#endif";
1079 }
1080
1081
1082
1083 void
1084 c_unparser::emit_functionsig (functiondecl* v)
1085 {
1086 o->newline() << "static void function_" << v->name
1087 << " (struct context * __restrict__ c);";
1088 }
1089
1090
1091
1092 void
1093 c_unparser::emit_module_init ()
1094 {
1095 vector<derived_probe_group*> g = all_session_groups (*session);
1096 for (unsigned i=0; i<g.size(); i++)
1097 g[i]->emit_module_decls (*session);
1098
1099 o->newline();
1100 o->newline() << "static int systemtap_module_init (void) {";
1101 o->newline(1) << "int rc = 0;";
1102 o->newline() << "int i=0, j=0;"; // for derived_probe_group use
1103 o->newline() << "const char *probe_point = \"\";";
1104
1105 // Compare actual and targeted kernel releases/machines. Sometimes
1106 // one may install the incorrect debuginfo or -devel RPM, and try to
1107 // run a probe compiled for a different version. Catch this early,
1108 // just in case modversions didn't.
1109 o->newline() << "{";
1110 o->newline(1) << "const char* release = UTS_RELEASE;";
1111
1112 // NB: This UTS_RELEASE compile-time macro directly checks only that
1113 // the compile-time kbuild tree matches the compile-time debuginfo/etc.
1114 // It does not check the run time kernel value. However, this is
1115 // probably OK since the kbuild modversions system aims to prevent
1116 // mismatches between kbuild and runtime versions at module-loading time.
1117
1118 // o->newline() << "const char* machine = UTS_MACHINE;";
1119 // NB: We could compare UTS_MACHINE too, but on x86 it lies
1120 // (UTS_MACHINE=i386, but uname -m is i686). Sheesh.
1121
1122 o->newline() << "if (strcmp (release, "
1123 << lex_cast_qstring (session->kernel_release) << ")) {";
1124 o->newline(1) << "_stp_error (\"module release mismatch (%s vs %s)\", "
1125 << "release, "
1126 << lex_cast_qstring (session->kernel_release)
1127 << ");";
1128 o->newline() << "rc = -EINVAL;";
1129 o->newline(-1) << "}";
1130
1131 // perform buildid-based checking if able
1132 o->newline() << "if (_stp_module_check()) rc = -EINVAL;";
1133
1134 o->newline(-1) << "}";
1135 o->newline() << "if (rc) goto out;";
1136
1137 o->newline() << "(void) probe_point;";
1138 o->newline() << "(void) i;";
1139 o->newline() << "(void) j;";
1140 o->newline() << "atomic_set (&session_state, STAP_SESSION_STARTING);";
1141 // This signals any other probes that may be invoked in the next little
1142 // while to abort right away. Currently running probes are allowed to
1143 // terminate. These may set STAP_SESSION_ERROR!
1144
1145 // per-cpu context
1146 o->newline() << "if (sizeof (struct context) <= 131072)";
1147 o->newline(1) << "contexts = alloc_percpu (struct context);";
1148 o->newline(-1) << "if (contexts == NULL) {";
1149 o->newline(1) << "_stp_error (\"percpu context (size %lu) allocation failed\", sizeof (struct context));";
1150 o->newline() << "rc = -ENOMEM;";
1151 o->newline() << "goto out;";
1152 o->newline(-1) << "}";
1153
1154 for (unsigned i=0; i<session->globals.size(); i++)
1155 {
1156 vardecl* v = session->globals[i];
1157 if (v->index_types.size() > 0)
1158 o->newline() << getmap (v).init();
1159 else
1160 o->newline() << getvar (v).init();
1161 // NB: in case of failure of allocation, "rc" will be set to non-zero.
1162 // Allocation can in general continue.
1163
1164 o->newline() << "if (rc) {";
1165 o->newline(1) << "_stp_error (\"global variable " << v->name << " allocation failed\");";
1166 o->newline() << "goto out;";
1167 o->newline(-1) << "}";
1168
1169 o->newline() << "rwlock_init (& global.s_" << c_varname (v->name) << "_lock);";
1170 }
1171
1172 // initialize each Stat used for timing information
1173 o->newline() << "#ifdef STP_TIMING";
1174 set<string> basest_names;
1175 for (unsigned i=0; i<session->probes.size(); i++)
1176 {
1177 string nm = session->probes[i]->basest()->name;
1178 if (basest_names.find(nm) == basest_names.end())
1179 {
1180 o->newline() << "time_" << nm << " = _stp_stat_init (HIST_NONE);";
1181 // NB: we don't check for null return here, but instead at
1182 // passage to probe handlers and at final printing.
1183 basest_names.insert (nm);
1184 }
1185 }
1186 o->newline() << "#endif";
1187
1188 // Print a message to the kernel log about this module. This is
1189 // intended to help debug problems with systemtap modules.
1190
1191 o->newline() << "_stp_print_kernel_info("
1192 << "\"" << VERSION
1193 << "/" << dwfl_version (NULL) << "\""
1194 << ", (num_online_cpus() * sizeof(struct context))"
1195 << ", " << session->probes.size()
1196 << ");";
1197
1198 // Run all probe registrations. This actually runs begin probes.
1199
1200 for (unsigned i=0; i<g.size(); i++)
1201 {
1202 g[i]->emit_module_init (*session);
1203 // NB: this gives O(N**2) amount of code, but luckily there
1204 // are only seven or eight derived_probe_groups, so it's ok.
1205 o->newline() << "if (rc) {";
1206 o->newline(1) << "_stp_error (\"probe %s registration error (rc %d)\", probe_point, rc);";
1207 // NB: we need to be in the error state so timers can shutdown cleanly,
1208 // and so end probes don't run. OTOH, error probes can run.
1209 o->newline() << "atomic_set (&session_state, STAP_SESSION_ERROR);";
1210 if (i>0)
1211 for (int j=i-1; j>=0; j--)
1212 g[j]->emit_module_exit (*session);
1213 o->newline() << "goto out;";
1214 o->newline(-1) << "}";
1215 }
1216
1217 // All registrations were successful. Consider the system started.
1218 o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_STARTING)";
1219 // NB: only other valid state value is ERROR, in which case we don't
1220 o->newline(1) << "atomic_set (&session_state, STAP_SESSION_RUNNING);";
1221 o->newline(-1) << "return 0;";
1222
1223 // Error handling path; by now all partially registered probe groups
1224 // have been unregistered.
1225 o->newline(-1) << "out:";
1226 o->indent(1);
1227
1228 // If any registrations failed, we will need to deregister the globals,
1229 // as this is our only chance.
1230 for (unsigned i=0; i<session->globals.size(); i++)
1231 {
1232 vardecl* v = session->globals[i];
1233 if (v->index_types.size() > 0)
1234 o->newline() << getmap (v).fini();
1235 else
1236 o->newline() << getvar (v).fini();
1237 }
1238
1239 o->newline() << "return rc;";
1240 o->newline(-1) << "}\n";
1241 }
1242
1243
1244 void
1245 c_unparser::emit_module_exit ()
1246 {
1247 o->newline() << "static void systemtap_module_exit (void) {";
1248 // rc?
1249 o->newline(1) << "int holdon;";
1250 o->newline() << "int i=0, j=0;"; // for derived_probe_group use
1251
1252 o->newline() << "(void) i;";
1253 o->newline() << "(void) j;";
1254 // If we aborted startup, then everything has been cleaned up already, and
1255 // module_exit shouldn't even have been called. But since it might be, let's
1256 // beat a hasty retreat to avoid double uninitialization.
1257 o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_STARTING)";
1258 o->newline(1) << "return;";
1259 o->indent(-1);
1260
1261 o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_RUNNING)";
1262 // NB: only other valid state value is ERROR, in which case we don't
1263 o->newline(1) << "atomic_set (&session_state, STAP_SESSION_STOPPING);";
1264 o->indent(-1);
1265 // This signals any other probes that may be invoked in the next little
1266 // while to abort right away. Currently running probes are allowed to
1267 // terminate. These may set STAP_SESSION_ERROR!
1268
1269 // We're processing the derived_probe_group list in reverse
1270 // order. This ensures that probes get unregistered in reverse
1271 // order of the way they were registered.
1272 vector<derived_probe_group*> g = all_session_groups (*session);
1273 for (vector<derived_probe_group*>::reverse_iterator i = g.rbegin();
1274 i != g.rend(); i++)
1275 (*i)->emit_module_exit (*session); // NB: runs "end" probes
1276
1277 // But some other probes may have launched too during unregistration.
1278 // Let's wait a while to make sure they're all done, done, done.
1279
1280 // cargo cult prologue
1281 o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
1282 o->newline() << "synchronize_sched();";
1283 o->newline() << "#endif";
1284
1285 // NB: systemtap_module_exit is assumed to be called from ordinary
1286 // user context, say during module unload. Among other things, this
1287 // means we can sleep a while.
1288 o->newline() << "do {";
1289 o->newline(1) << "int i;";
1290 o->newline() << "holdon = 0;";
1291 o->newline() << "for (i=0; i < NR_CPUS; i++)";
1292 o->newline(1) << "if (cpu_possible (i) && "
1293 << "atomic_read (& ((struct context *)per_cpu_ptr(contexts, i))->busy)) "
1294 << "holdon = 1;";
1295 // NB: we run at least one of these during the shutdown sequence:
1296 o->newline () << "yield ();"; // aka schedule() and then some
1297 o->newline(-2) << "} while (holdon);";
1298
1299 // cargo cult epilogue
1300 o->newline() << "#ifdef STAPCONF_SYNCHRONIZE_SCHED";
1301 o->newline() << "synchronize_sched();";
1302 o->newline() << "#endif";
1303
1304 // XXX: might like to have an escape hatch, in case some probe is
1305 // genuinely stuck somehow
1306
1307 for (unsigned i=0; i<session->globals.size(); i++)
1308 {
1309 vardecl* v = session->globals[i];
1310 if (v->index_types.size() > 0)
1311 o->newline() << getmap (v).fini();
1312 else
1313 o->newline() << getvar (v).fini();
1314 }
1315
1316 o->newline() << "free_percpu (contexts);";
1317
1318 // print probe timing statistics
1319 {
1320 o->newline() << "#ifdef STP_TIMING";
1321 o->newline() << "{";
1322 o->indent(1);
1323 set<string> basest_names;
1324 for (unsigned i=0; i<session->probes.size(); i++)
1325 {
1326 probe* p = session->probes[i]->basest();
1327 string nm = p->name;
1328 if (basest_names.find(nm) == basest_names.end())
1329 {
1330 basest_names.insert (nm);
1331 // NB: check for null stat object
1332 o->newline() << "if (likely (time_" << p->name << ")) {";
1333 o->newline(1) << "const char *probe_point = "
1334 << lex_cast_qstring (* p->locations[0])
1335 << (p->locations.size() > 1 ? "\"+\"" : "")
1336 << (p->locations.size() > 1 ? lex_cast_qstring(p->locations.size()-1) : "")
1337 << ";";
1338 o->newline() << "const char *decl_location = "
1339 << lex_cast_qstring (p->tok->location)
1340 << ";";
1341 o->newline() << "struct stat_data *stats = _stp_stat_get (time_"
1342 << p->name
1343 << ", 0);";
1344 o->newline() << "if (stats->count) {";
1345 o->newline(1) << "int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);";
1346 o->newline() << "_stp_printf (\"probe %s (%s), hits: %lld, cycles: %lldmin/%lldavg/%lldmax\\n\",";
1347 o->newline() << "probe_point, decl_location, (long long) stats->count, (long long) stats->min, (long long) avg, (long long) stats->max);";
1348 o->newline(-1) << "}";
1349 o->newline() << "_stp_stat_del (time_" << p->name << ");";
1350 o->newline(-1) << "}";
1351 }
1352 }
1353 o->newline() << "_stp_print_flush();";
1354 o->newline(-1) << "}";
1355 o->newline() << "#endif";
1356 }
1357
1358 // print final error/reentrancy counts if non-zero
1359 o->newline() << "if (atomic_read (& skipped_count) || "
1360 << "atomic_read (& error_count)) {";
1361 o->newline(1) << "_stp_warn (\"Number of errors: %d, "
1362 << "skipped probes: %d\\n\", "
1363 << "(int) atomic_read (& error_count), "
1364 << "(int) atomic_read (& skipped_count));";
1365 o->newline() << "#ifdef STP_TIMING";
1366 o->newline() << "{";
1367 o->newline(1) << "int ctr;";
1368 for (unsigned i=0; i<session->globals.size(); i++)
1369 {
1370 string vn = c_varname (session->globals[i]->name);
1371 o->newline() << "ctr = atomic_read (& global.s_" << vn << "_lock_skip_count);";
1372 o->newline() << "if (ctr) _stp_warn (\"Skipped due to global '%s' lock timeout: %d\\n\", "
1373 << lex_cast_qstring(vn) << ", ctr);";
1374 }
1375 o->newline() << "ctr = atomic_read (& skipped_count_lowstack);";
1376 o->newline() << "if (ctr) _stp_warn (\"Skipped due to low stack: %d\\n\", ctr);";
1377 o->newline() << "ctr = atomic_read (& skipped_count_reentrant);";
1378 o->newline() << "if (ctr) _stp_warn (\"Skipped due to reentrancy: %d\\n\", ctr);";
1379 o->newline() << "ctr = atomic_read (& skipped_count_uprobe_reg);";
1380 o->newline() << "if (ctr) _stp_warn (\"Skipped due to uprobe register failure: %d\\n\", ctr);";
1381 o->newline() << "ctr = atomic_read (& skipped_count_uprobe_unreg);";
1382 o->newline() << "if (ctr) _stp_warn (\"Skipped due to uprobe unregister failure: %d\\n\", ctr);";
1383 o->newline(-1) << "}";
1384 o->newline () << "#endif";
1385 o->newline() << "_stp_print_flush();";
1386 o->newline(-1) << "}";
1387 o->newline(-1) << "}\n";
1388 }
1389
1390
1391 void
1392 c_unparser::emit_function (functiondecl* v)
1393 {
1394 o->newline() << "static void function_" << c_varname (v->name)
1395 << " (struct context* __restrict__ c) {";
1396 o->indent(1);
1397 this->current_probe = 0;
1398 this->current_function = v;
1399 this->tmpvar_counter = 0;
1400 this->action_counter = 0;
1401
1402 o->newline()
1403 << "struct function_" << c_varname (v->name) << "_locals * "
1404 << " __restrict__ l =";
1405 o->newline(1)
1406 << "& c->locals[c->nesting+1].function_" << c_varname (v->name) // NB: nesting+1
1407 << ";";
1408 o->newline(-1) << "(void) l;"; // make sure "l" is marked used
1409 o->newline() << "#define CONTEXT c";
1410 o->newline() << "#define THIS l";
1411 o->newline() << "if (0) goto out;"; // make sure out: is marked used
1412
1413 // set this, in case embedded-c code sets last_error but doesn't otherwise identify itself
1414 o->newline() << "c->last_stmt = " << lex_cast_qstring(*v->tok) << ";";
1415
1416 // check/increment nesting level
1417 o->newline() << "if (unlikely (c->nesting+2 >= MAXNESTING)) {";
1418 o->newline(1) << "c->last_error = \"MAXNESTING exceeded\";";
1419 o->newline() << "return;";
1420 o->newline(-1) << "} else {";
1421 o->newline(1) << "c->nesting ++;";
1422 o->newline(-1) << "}";
1423
1424 // initialize locals
1425 // XXX: optimization: use memset instead
1426 for (unsigned i=0; i<v->locals.size(); i++)
1427 {
1428 if (v->locals[i]->index_types.size() > 0) // array?
1429 throw semantic_error ("array locals not supported, missing global declaration?",
1430 v->locals[i]->tok);
1431
1432 o->newline() << getvar (v->locals[i]).init();
1433 }
1434
1435 // initialize return value, if any
1436 if (v->type != pe_unknown)
1437 {
1438 var retvalue = var(true, v->type, "__retvalue");
1439 o->newline() << retvalue.init();
1440 }
1441
1442 o->newline() << "#define return goto out"; // redirect embedded-C return
1443 this->probe_or_function_needs_deref_fault_handler = false;
1444 v->body->visit (this);
1445 o->newline() << "#undef return";
1446
1447 this->current_function = 0;
1448
1449 record_actions(0, true);
1450
1451 if (this->probe_or_function_needs_deref_fault_handler) {
1452 // Emit this handler only if the body included a
1453 // print/printf/etc. using a string or memory buffer!
1454 o->newline() << "CATCH_DEREF_FAULT ();";
1455 }
1456
1457 o->newline(-1) << "out:";
1458 o->newline(1) << ";";
1459
1460 // Function prologue: this is why we redirect the "return" above.
1461 // Decrement nesting level.
1462 o->newline() << "c->nesting --;";
1463
1464 o->newline() << "#undef CONTEXT";
1465 o->newline() << "#undef THIS";
1466 o->newline(-1) << "}\n";
1467 }
1468
1469
1470 #define DUPMETHOD_CALL 0
1471 #define DUPMETHOD_ALIAS 0
1472 #define DUPMETHOD_RENAME 1
1473
1474 void
1475 c_unparser::emit_probe (derived_probe* v)
1476 {
1477 this->current_function = 0;
1478 this->current_probe = v;
1479 this->tmpvar_counter = 0;
1480 this->action_counter = 0;
1481
1482 // If we about to emit a probe that is exactly the same as another
1483 // probe previously emitted, make the second probe just call the
1484 // first one.
1485 //
1486 // Notice we're using the probe body itself instead of the emitted C
1487 // probe body to compare probes. We need to do this because the
1488 // emitted C probe body has stuff in it like:
1489 // c->last_stmt = "identifier 'printf' at foo.stp:<line>:<column>";
1490 //
1491 // which would make comparisons impossible.
1492 //
1493 // --------------------------------------------------------------------------
1494 // NB: see also c_unparser:emit_common_header(), which deliberately but sadly
1495 // duplicates this calculation.
1496 // --------------------------------------------------------------------------
1497 //
1498 ostringstream oss;
1499
1500 // NB: statp is just for avoiding designation as duplicate. It need not be C.
1501 // NB: This code *could* be enclosed in an "if (session->timing)". That would
1502 // recognize more duplicate probe handlers, but then the generated code could
1503 // be very different with or without -t.
1504 oss << "c->statp = & time_" << v->basest()->name << ";" << endl;
1505
1506 v->body->print(oss);
1507
1508 // Since the generated C changes based on whether or not the probe
1509 // needs locks around global variables, this needs to be reflected
1510 // here. We don't want to treat as duplicate the handlers of
1511 // begin/end and normal probes that differ only in need_global_locks.
1512 oss << "# needs_global_locks: " << v->needs_global_locks () << endl;
1513
1514 // If an identical probe has already been emitted, just call that
1515 // one.
1516 if (probe_contents.count(oss.str()) != 0)
1517 {
1518 string dupe = probe_contents[oss.str()];
1519
1520 // NB: Elision of context variable structs is a separate
1521 // operation which has already taken place by now.
1522 if (session->verbose > 1)
1523 clog << v->name << " elided, duplicates " << dupe << endl;
1524
1525 #if DUPMETHOD_CALL
1526 // This one emits a direct call to the first copy.
1527 o->newline();
1528 o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
1529 o->newline() << "{ " << dupe << " (c); }";
1530 #elif DUPMETHOD_ALIAS
1531 // This one defines a function alias, arranging gcc to emit
1532 // several equivalent symbols for the same function body.
1533 // For some reason, on gcc 4.1, this is twice as slow as
1534 // the CALL option.
1535 o->newline();
1536 o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
1537 o->line() << "__attribute__ ((alias (\"" << dupe << "\")));";
1538 #elif DUPMETHOD_RENAME
1539 // This one is sneaky. It emits nothing for duplicate probe
1540 // handlers. It instead redirects subsequent references to the
1541 // probe handler function to the first copy, *by name*.
1542 v->name = dupe;
1543 #else
1544 #error "Unknown duplicate elimination method"
1545 #endif
1546 }
1547 else // This probe is unique. Remember it and output it.
1548 {
1549 this->probe_or_function_needs_deref_fault_handler = false;
1550
1551 o->newline();
1552 o->newline() << "#ifdef STP_TIMING";
1553 o->newline() << "static __cacheline_aligned Stat " << "time_" << v->basest()->name << ";";
1554 o->newline() << "#endif";
1555 o->newline();
1556 o->newline() << "static void " << v->name << " (struct context * __restrict__ c) ";
1557 o->line () << "{";
1558 o->indent (1);
1559
1560 probe_contents[oss.str()] = v->name;
1561
1562 // initialize frame pointer
1563 o->newline() << "struct " << v->name << "_locals * __restrict__ l =";
1564 o->newline(1) << "& c->locals[0]." << v->name << ";";
1565 o->newline(-1) << "(void) l;"; // make sure "l" is marked used
1566
1567 o->newline() << "#ifdef STP_TIMING";
1568 o->newline() << "c->statp = & time_" << v->basest()->name << ";";
1569 o->newline() << "#endif";
1570
1571 // emit probe local initialization block
1572 v->emit_probe_local_init(o);
1573
1574 // emit all read/write locks for global variables
1575 varuse_collecting_visitor vut;
1576 if (v->needs_global_locks ())
1577 {
1578 v->body->visit (& vut);
1579 emit_locks (vut);
1580 }
1581
1582 // initialize locals
1583 for (unsigned j=0; j<v->locals.size(); j++)
1584 {
1585 if (v->locals[j]->index_types.size() > 0) // array?
1586 throw semantic_error ("array locals not supported, missing global declaration?",
1587 v->locals[j]->tok);
1588 else if (v->locals[j]->type == pe_long)
1589 o->newline() << "l->" << c_varname (v->locals[j]->name)
1590 << " = 0;";
1591 else if (v->locals[j]->type == pe_string)
1592 o->newline() << "l->" << c_varname (v->locals[j]->name)
1593 << "[0] = '\\0';";
1594 else
1595 throw semantic_error ("unsupported local variable type",
1596 v->locals[j]->tok);
1597 }
1598
1599 v->initialize_probe_context_vars (o);
1600
1601 v->body->visit (this);
1602
1603 record_actions(0, true);
1604
1605 if (this->probe_or_function_needs_deref_fault_handler) {
1606 // Emit this handler only if the body included a
1607 // print/printf/etc. using a string or memory buffer!
1608 o->newline() << "CATCH_DEREF_FAULT ();";
1609 }
1610
1611 o->newline(-1) << "out:";
1612 // NB: no need to uninitialize locals, except if arrays/stats can
1613 // someday be local
1614
1615 // XXX: do this flush only if the body included a
1616 // print/printf/etc. routine!
1617 o->newline(1) << "_stp_print_flush();";
1618
1619 if (v->needs_global_locks ())
1620 emit_unlocks (vut);
1621
1622 o->newline(-1) << "}\n";
1623 }
1624
1625
1626 this->current_probe = 0;
1627 }
1628
1629
1630 void
1631 c_unparser::emit_locks(const varuse_collecting_visitor& vut)
1632 {
1633 o->newline() << "{";
1634 o->newline(1) << "unsigned numtrylock = 0;";
1635 o->newline() << "(void) numtrylock;";
1636
1637 string last_locked_var;
1638 for (unsigned i = 0; i < session->globals.size(); i++)
1639 {
1640 vardecl* v = session->globals[i];
1641 bool read_p = vut.read.find(v) != vut.read.end();
1642 bool write_p = vut.written.find(v) != vut.written.end();
1643 if (!read_p && !write_p) continue;
1644
1645 if (v->type == pe_stats) // read and write locks are flipped
1646 // Specifically, a "<<<" to a stats object is considered a
1647 // "shared-lock" operation, since it's implicitly done
1648 // per-cpu. But a "@op(x)" extraction is an "exclusive-lock"
1649 // one, as is a (sorted or unsorted) foreach, so those cases
1650 // are excluded by the w & !r condition below.
1651 {
1652 if (write_p && !read_p) { read_p = true; write_p = false; }
1653 else if (read_p && !write_p) { read_p = false; write_p = true; }
1654 }
1655
1656 // We don't need to read lock "read-mostly" global variables. A
1657 // "read-mostly" global variable is only written to within
1658 // probes that don't need global variable locking (such as
1659 // begin/end probes). If vcv_needs_global_locks doesn't mark
1660 // the global as written to, then we don't have to lock it
1661 // here to read it safely.
1662 if (read_p && !write_p)
1663 {
1664 if (vcv_needs_global_locks.written.find(v)
1665 == vcv_needs_global_locks.written.end())
1666 continue;
1667 }
1668
1669 string lockcall =
1670 string (write_p ? "write" : "read") +
1671 "_trylock (& global.s_" + v->name + "_lock)";
1672
1673 o->newline() << "while (! " << lockcall
1674 << "&& (++numtrylock < MAXTRYLOCK))";
1675 o->newline(1) << "ndelay (TRYLOCKDELAY);";
1676 o->newline(-1) << "if (unlikely (numtrylock >= MAXTRYLOCK)) {";
1677 o->newline(1) << "atomic_inc (& skipped_count);";
1678 o->newline() << "#ifdef STP_TIMING";
1679 o->newline() << "atomic_inc (& global.s_" << c_varname (v->name) << "_lock_skip_count);";
1680 o->newline() << "#endif";
1681 // The following works even if i==0. Note that using
1682 // globals[i-1]->name is wrong since that global may not have
1683 // been lockworthy by this probe.
1684 o->newline() << "goto unlock_" << last_locked_var << ";";
1685 o->newline(-1) << "}";
1686
1687 last_locked_var = v->name;
1688 }
1689
1690 o->newline() << "if (0) goto unlock_;";
1691
1692 o->newline(-1) << "}";
1693 }
1694
1695
1696 void
1697 c_unparser::emit_unlocks(const varuse_collecting_visitor& vut)
1698 {
1699 unsigned numvars = 0;
1700
1701 if (session->verbose>1)
1702 clog << current_probe->name << " locks ";
1703
1704 for (int i = session->globals.size()-1; i>=0; i--) // in reverse order!
1705 {
1706 vardecl* v = session->globals[i];
1707 bool read_p = vut.read.find(v) != vut.read.end();
1708 bool write_p = vut.written.find(v) != vut.written.end();
1709 if (!read_p && !write_p) continue;
1710
1711 // Duplicate lock flipping logic from above
1712 if (v->type == pe_stats)
1713 {
1714 if (write_p && !read_p) { read_p = true; write_p = false; }
1715 else if (read_p && !write_p) { read_p = false; write_p = true; }
1716 }
1717
1718 // Duplicate "read-mostly" global variable logic from above.
1719 if (read_p && !write_p)
1720 {
1721 if (vcv_needs_global_locks.written.find(v)
1722 == vcv_needs_global_locks.written.end())
1723 continue;
1724 }
1725
1726 numvars ++;
1727 o->newline(-1) << "unlock_" << v->name << ":";
1728 o->indent(1);
1729
1730 if (session->verbose>1)
1731 clog << v->name << "[" << (read_p ? "r" : "")
1732 << (write_p ? "w" : "") << "] ";
1733
1734 if (write_p) // emit write lock
1735 o->newline() << "write_unlock (& global.s_" << v->name << "_lock);";
1736 else // (read_p && !write_p) : emit read lock
1737 o->newline() << "read_unlock (& global.s_" << v->name << "_lock);";
1738
1739 // fall through to next variable; thus the reverse ordering
1740 }
1741
1742 // emit plain "unlock" label, used if the very first lock failed.
1743 o->newline(-1) << "unlock_: ;";
1744 o->indent(1);
1745
1746 if (numvars) // is there a chance that any lock attempt failed?
1747 {
1748 // Formerly, we checked skipped_count > MAXSKIPPED here, and set
1749 // SYSTEMTAP_SESSION_ERROR if so. But now, this check is shared
1750 // via common_probe_entryfn_epilogue().
1751
1752 if (session->verbose>1)
1753 clog << endl;
1754 }
1755 else if (session->verbose>1)
1756 clog << "nothing" << endl;
1757 }
1758
1759
1760 void
1761 c_unparser::collect_map_index_types(vector<vardecl *> const & vars,
1762 set< pair<vector<exp_type>, exp_type> > & types)
1763 {
1764 for (unsigned i = 0; i < vars.size(); ++i)
1765 {
1766 vardecl *v = vars[i];
1767 if (v->arity > 0)
1768 {
1769 types.insert(make_pair(v->index_types, v->type));
1770 }
1771 }
1772 }
1773
1774 string
1775 mapvar::value_typename(exp_type e)
1776 {
1777 switch (e)
1778 {
1779 case pe_long:
1780 return "INT64";
1781 case pe_string:
1782 return "STRING";
1783 case pe_stats:
1784 return "STAT";
1785 default:
1786 throw semantic_error("array type is neither string nor long");
1787 }
1788 return "";
1789 }
1790
1791 string
1792 mapvar::key_typename(exp_type e)
1793 {
1794 switch (e)
1795 {
1796 case pe_long:
1797 return "INT64";
1798 case pe_string:
1799 return "STRING";
1800 default:
1801 throw semantic_error("array key is neither string nor long");
1802 }
1803 return "";
1804 }
1805
1806 string
1807 mapvar::shortname(exp_type e)
1808 {
1809 switch (e)
1810 {
1811 case pe_long:
1812 return "i";
1813 case pe_string:
1814 return "s";
1815 default:
1816 throw semantic_error("array type is neither string nor long");
1817 }
1818 return "";
1819 }
1820
1821
1822 void
1823 c_unparser::emit_map_type_instantiations ()
1824 {
1825 set< pair<vector<exp_type>, exp_type> > types;
1826
1827 collect_map_index_types(session->globals, types);
1828
1829 for (unsigned i = 0; i < session->probes.size(); ++i)
1830 collect_map_index_types(session->probes[i]->locals, types);
1831
1832 for (map<string,functiondecl*>::iterator it = session->functions.begin(); it != session->functions.end(); it++)
1833 collect_map_index_types(it->second->locals, types);
1834
1835 if (!types.empty())
1836 o->newline() << "#include \"alloc.c\"";
1837
1838 for (set< pair<vector<exp_type>, exp_type> >::const_iterator i = types.begin();
1839 i != types.end(); ++i)
1840 {
1841 o->newline() << "#define VALUE_TYPE " << mapvar::value_typename(i->second);
1842 for (unsigned j = 0; j < i->first.size(); ++j)
1843 {
1844 string ktype = mapvar::key_typename(i->first.at(j));
1845 o->newline() << "#define KEY" << (j+1) << "_TYPE " << ktype;
1846 }
1847 if (i->second == pe_stats)
1848 o->newline() << "#include \"pmap-gen.c\"";
1849 else
1850 o->newline() << "#include \"map-gen.c\"";
1851 o->newline() << "#undef VALUE_TYPE";
1852 for (unsigned j = 0; j < i->first.size(); ++j)
1853 {
1854 o->newline() << "#undef KEY" << (j+1) << "_TYPE";
1855 }
1856
1857 /* FIXME
1858 * For pmaps, we also need to include map-gen.c, because we might be accessing
1859 * the aggregated map. The better way to handle this is for pmap-gen.c to make
1860 * this include, but that's impossible with the way they are set up now.
1861 */
1862 if (i->second == pe_stats)
1863 {
1864 o->newline() << "#define VALUE_TYPE " << mapvar::value_typename(i->second);
1865 for (unsigned j = 0; j < i->first.size(); ++j)
1866 {
1867 string ktype = mapvar::key_typename(i->first.at(j));
1868 o->newline() << "#define KEY" << (j+1) << "_TYPE " << ktype;
1869 }
1870 o->newline() << "#include \"map-gen.c\"";
1871 o->newline() << "#undef VALUE_TYPE";
1872 for (unsigned j = 0; j < i->first.size(); ++j)
1873 {
1874 o->newline() << "#undef KEY" << (j+1) << "_TYPE";
1875 }
1876 }
1877 }
1878
1879 if (!types.empty())
1880 o->newline() << "#include \"map.c\"";
1881
1882 };
1883
1884
1885 string
1886 c_unparser::c_typename (exp_type e)
1887 {
1888 switch (e)
1889 {
1890 case pe_long: return string("int64_t");
1891 case pe_string: return string("string_t");
1892 case pe_stats: return string("Stat");
1893 case pe_unknown:
1894 default:
1895 throw semantic_error ("cannot expand unknown type");
1896 }
1897 }
1898
1899
1900 string
1901 c_unparser::c_varname (const string& e)
1902 {
1903 // XXX: safeify, uniquefy, given name
1904 return e;
1905 }
1906
1907
1908 string
1909 c_unparser::c_expression (expression *e)
1910 {
1911 // We want to evaluate expression 'e' and return its value as a
1912 // string. In the case of expressions that are just numeric
1913 // constants, if we just print the value into a string, it won't
1914 // have the same value as being visited by c_unparser. For
1915 // instance, a numeric constant evaluated using print() would return
1916 // "5", while c_unparser::visit_literal_number() would
1917 // return "((int64_t)5LL)". String constants evaluated using
1918 // print() would just return the string, while
1919 // c_unparser::visit_literal_string() would return the string with
1920 // escaped double quote characters. So, we need to "visit" the
1921 // expression.
1922
1923 // However, we have to be careful of side effects. Currently this
1924 // code is only being used for evaluating literal numbers and
1925 // strings, which currently have no side effects. Until needed
1926 // otherwise, limit the use of this function to literal numbers and
1927 // strings.
1928 if (e->tok->type != tok_number && e->tok->type != tok_string)
1929 throw semantic_error("unsupported c_expression token type");
1930
1931 // Create a fake output stream so we can grab the string output.
1932 ostringstream oss;
1933 translator_output tmp_o(oss);
1934
1935 // Temporarily swap out the real translator_output stream with our
1936 // fake one.
1937 translator_output *saved_o = o;
1938 o = &tmp_o;
1939
1940 // Visit the expression then restore the original output stream
1941 e->visit (this);
1942 o = saved_o;
1943
1944 return (oss.str());
1945 }
1946
1947
1948 void
1949 c_unparser::c_assign (var& lvalue, const string& rvalue, const token *tok)
1950 {
1951 switch (lvalue.type())
1952 {
1953 case pe_string:
1954 c_strcpy(lvalue.value(), rvalue);
1955 break;
1956 case pe_long:
1957 o->newline() << lvalue << " = " << rvalue << ";";
1958 break;
1959 default:
1960 throw semantic_error ("unknown lvalue type in assignment", tok);
1961 }
1962 }
1963
1964 void
1965 c_unparser::c_assign (const string& lvalue, expression* rvalue,
1966 const string& msg)
1967 {
1968 if (rvalue->type == pe_long)
1969 {
1970 o->newline() << lvalue << " = ";
1971 rvalue->visit (this);
1972 o->line() << ";";
1973 }
1974 else if (rvalue->type == pe_string)
1975 {
1976 c_strcpy (lvalue, rvalue);
1977 }
1978 else
1979 {
1980 string fullmsg = msg + " type unsupported";
1981 throw semantic_error (fullmsg, rvalue->tok);
1982 }
1983 }
1984
1985
1986 void
1987 c_unparser::c_assign (const string& lvalue, const string& rvalue,
1988 exp_type type, const string& msg, const token* tok)
1989 {
1990 if (type == pe_long)
1991 {
1992 o->newline() << lvalue << " = " << rvalue << ";";
1993 }
1994 else if (type == pe_string)
1995 {
1996 c_strcpy (lvalue, rvalue);
1997 }
1998 else
1999 {
2000 string fullmsg = msg + " type unsupported";
2001 throw semantic_error (fullmsg, tok);
2002 }
2003 }
2004
2005
2006 void
2007 c_unparser_assignment::c_assignop(tmpvar & res,
2008 var const & lval,
2009 tmpvar const & rval,
2010 token const * tok)
2011 {
2012 // This is common code used by scalar and array-element assignments.
2013 // It assumes an operator-and-assignment (defined by the 'pre' and
2014 // 'op' fields of c_unparser_assignment) is taking place between the
2015 // following set of variables:
2016 //
2017 // res: the result of evaluating the expression, a temporary
2018 // lval: the lvalue of the expression, which may be damaged
2019 // rval: the rvalue of the expression, which is a temporary or constant
2020
2021 // we'd like to work with a local tmpvar so we can overwrite it in
2022 // some optimized cases
2023
2024 translator_output* o = parent->o;
2025
2026 if (res.type() == pe_string)
2027 {
2028 if (post)
2029 throw semantic_error ("post assignment on strings not supported",
2030 tok);
2031 if (op == "=")
2032 {
2033 parent->c_strcpy (lval.value(), rval.value());
2034 // no need for second copy
2035 res = rval;
2036 }
2037 else if (op == ".=")
2038 {
2039 parent->c_strcat (lval.value(), rval.value());
2040 res = lval;
2041 }
2042 else
2043 throw semantic_error ("string assignment operator " +
2044 op + " unsupported", tok);
2045 }
2046 else if (op == "<<<")
2047 {
2048 assert(lval.type() == pe_stats);
2049 assert(rval.type() == pe_long);
2050 assert(res.type() == pe_long);
2051 o->newline() << res << " = " << rval << ";";
2052 o->newline() << "_stp_stat_add (" << lval << ", " << res << ");";
2053 }
2054 else if (res.type() == pe_long)
2055 {
2056 // a lot of operators come through this "gate":
2057 // - vanilla assignment "="
2058 // - stats aggregation "<<<"
2059 // - modify-accumulate "+=" and many friends
2060 // - pre/post-crement "++"/"--"
2061 // - "/" and "%" operators, but these need special handling in kernel
2062
2063 // compute the modify portion of a modify-accumulate
2064 string macop;
2065 unsigned oplen = op.size();
2066 if (op == "=")
2067 macop = "*error*"; // special shortcuts below
2068 else if (op == "++" || op == "+=")
2069 macop = "+=";
2070 else if (op == "--" || op == "-=")
2071 macop = "-=";
2072 else if (oplen > 1 && op[oplen-1] == '=') // for *=, <<=, etc...
2073 macop = op;
2074 else
2075 // internal error
2076 throw semantic_error ("unknown macop for assignment", tok);
2077
2078 if (post)
2079 {
2080 if (macop == "/" || macop == "%" || op == "=")
2081 throw semantic_error ("invalid post-mode operator", tok);
2082
2083 o->newline() << res << " = " << lval << ";";
2084
2085 if (macop == "+=" || macop == "-=")
2086 o->newline() << lval << " " << macop << " " << rval << ";";
2087 else
2088 o->newline() << lval << " = " << res << " " << macop << " " << rval << ";";
2089 }
2090 else
2091 {
2092 if (op == "=") // shortcut simple assignment
2093 {
2094 o->newline() << lval << " = " << rval << ";";
2095 res = rval;
2096 }
2097 else
2098 {
2099 if (macop == "/=" || macop == "%=")
2100 {
2101 o->newline() << "if (unlikely(!" << rval << ")) {";
2102 o->newline(1) << "c->last_error = \"division by 0\";";
2103 o->newline() << "goto out;";
2104 o->newline(-1) << "}";
2105 o->newline() << lval << " = "
2106 << ((macop == "/=") ? "_stp_div64" : "_stp_mod64")
2107 << " (NULL, " << lval << ", " << rval << ");";
2108 }
2109 else
2110 o->newline() << lval << " " << macop << " " << rval << ";";
2111 res = lval;
2112 }
2113 }
2114 }
2115 else
2116 throw semantic_error ("assignment type not yet implemented", tok);
2117 }
2118
2119
2120 void
2121 c_unparser::c_declare(exp_type ty, const string &name)
2122 {
2123 o->newline() << c_typename (ty) << " " << c_varname (name) << ";";
2124 }
2125
2126
2127 void
2128 c_unparser::c_declare_static(exp_type ty, const string &name)
2129 {
2130 o->newline() << "static " << c_typename (ty) << " " << c_varname (name) << ";";
2131 }
2132
2133
2134 void
2135 c_unparser::c_strcpy (const string& lvalue, const string& rvalue)
2136 {
2137 o->newline() << "strlcpy ("
2138 << lvalue << ", "
2139 << rvalue << ", MAXSTRINGLEN);";
2140 }
2141
2142
2143 void
2144 c_unparser::c_strcpy (const string& lvalue, expression* rvalue)
2145 {
2146 o->newline() << "strlcpy (" << lvalue << ", ";
2147 rvalue->visit (this);
2148 o->line() << ", MAXSTRINGLEN);";
2149 }
2150
2151
2152 void
2153 c_unparser::c_strcat (const string& lvalue, const string& rvalue)
2154 {
2155 o->newline() << "strlcat ("
2156 << lvalue << ", "
2157 << rvalue << ", MAXSTRINGLEN);";
2158 }
2159
2160
2161 void
2162 c_unparser::c_strcat (const string& lvalue, expression* rvalue)
2163 {
2164 o->newline() << "strlcat (" << lvalue << ", ";
2165 rvalue->visit (this);
2166 o->line() << ", MAXSTRINGLEN);";
2167 }
2168
2169
2170 bool
2171 c_unparser::is_local(vardecl const *r, token const *tok)
2172 {
2173 if (current_probe)
2174 {
2175 for (unsigned i=0; i<current_probe->locals.size(); i++)
2176 {
2177 if (current_probe->locals[i] == r)
2178 return true;
2179 }
2180 }
2181 else if (current_function)
2182 {
2183 for (unsigned i=0; i<current_function->locals.size(); i++)
2184 {
2185 if (current_function->locals[i] == r)
2186 return true;
2187 }
2188
2189 for (unsigned i=0; i<current_function->formal_args.size(); i++)
2190 {
2191 if (current_function->formal_args[i] == r)
2192 return true;
2193 }
2194 }
2195
2196 for (unsigned i=0; i<session->globals.size(); i++)
2197 {
2198 if (session->globals[i] == r)
2199 return false;
2200 }
2201
2202 if (tok)
2203 throw semantic_error ("unresolved symbol", tok);
2204 else
2205 throw semantic_error ("unresolved symbol: " + r->name);
2206 }
2207
2208
2209 tmpvar
2210 c_unparser::gensym(exp_type ty)
2211 {
2212 return tmpvar (ty, tmpvar_counter);
2213 }
2214
2215 aggvar
2216 c_unparser::gensym_aggregate()
2217 {
2218 return aggvar (tmpvar_counter);
2219 }
2220
2221
2222 var
2223 c_unparser::getvar(vardecl *v, token const *tok)
2224 {
2225 bool loc = is_local (v, tok);
2226 if (loc)
2227 return var (loc, v->type, v->name);
2228 else
2229 {
2230 statistic_decl sd;
2231 std::map<std::string, statistic_decl>::const_iterator i;
2232 i = session->stat_decls.find(v->name);
2233 if (i != session->stat_decls.end())
2234 sd = i->second;
2235 return var (loc, v->type, sd, v->name);
2236 }
2237 }
2238
2239
2240 mapvar
2241 c_unparser::getmap(vardecl *v, token const *tok)
2242 {
2243 if (v->arity < 1)
2244 throw semantic_error("attempt to use scalar where map expected", tok);
2245 statistic_decl sd;
2246 std::map<std::string, statistic_decl>::const_iterator i;
2247 i = session->stat_decls.find(v->name);
2248 if (i != session->stat_decls.end())
2249 sd = i->second;
2250 return mapvar (is_local (v, tok), v->type, sd,
2251 v->name, v->index_types, v->maxsize);
2252 }
2253
2254
2255 itervar
2256 c_unparser::getiter(symbol *s)
2257 {
2258 return itervar (s, tmpvar_counter);
2259 }
2260
2261
2262 // Queue up some actions to remove from actionremaining. Set update=true at
2263 // the end of basic blocks to actually update actionremaining and check it
2264 // against MAXACTION.
2265 void
2266 c_unparser::record_actions (unsigned actions, bool update)
2267 {
2268 action_counter += actions;
2269
2270 // Update if needed, or after queueing up a few actions, in case of very
2271 // large code sequences.
2272 if ((update && action_counter > 0) || action_counter >= 10/*<-arbitrary*/)
2273 {
2274 o->newline() << "c->actionremaining -= " << action_counter << ";";
2275 o->newline() << "if (unlikely (c->actionremaining <= 0)) {";
2276 o->newline(1) << "c->last_error = \"MAXACTION exceeded\";";
2277 o->newline() << "goto out;";
2278 o->newline(-1) << "}";
2279 action_counter = 0;
2280 }
2281 }
2282
2283
2284 void
2285 c_unparser::visit_block (block *s)
2286 {
2287 o->newline() << "{";
2288 o->indent (1);
2289
2290 for (unsigned i=0; i<s->statements.size(); i++)
2291 {
2292 try
2293 {
2294 s->statements[i]->visit (this);
2295 o->newline();
2296 }
2297 catch (const semantic_error& e)
2298 {
2299 session->print_error (e);
2300 }
2301 }
2302 o->newline(-1) << "}";
2303 }
2304
2305
2306 void
2307 c_unparser::visit_embeddedcode (embeddedcode *s)
2308 {
2309 o->newline() << "{";
2310 o->newline(1) << s->code;
2311 o->newline(-1) << "}";
2312 }
2313
2314
2315 void
2316 c_unparser::visit_null_statement (null_statement *)
2317 {
2318 o->newline() << "/* null */;";
2319 }
2320
2321
2322 void
2323 c_unparser::visit_expr_statement (expr_statement *s)
2324 {
2325 o->newline() << "(void) ";
2326 s->value->visit (this);
2327 o->line() << ";";
2328 record_actions(1);
2329 }
2330
2331
2332 void
2333 c_unparser::visit_if_statement (if_statement *s)
2334 {
2335 record_actions(1, true);
2336 o->newline() << "if (";
2337 o->indent (1);
2338 s->condition->visit (this);
2339 o->indent (-1);
2340 o->line() << ") {";
2341 o->indent (1);
2342 s->thenblock->visit (this);
2343 record_actions(0, true);
2344 o->newline(-1) << "}";
2345 if (s->elseblock)
2346 {
2347 o->newline() << "else {";
2348 o->indent (1);
2349 s->elseblock->visit (this);
2350 record_actions(0, true);
2351 o->newline(-1) << "}";
2352 }
2353 }
2354
2355
2356 void
2357 c_tmpcounter::visit_block (block *s)
2358 {
2359 // Key insight: individual statements of a block can reuse
2360 // temporary variable slots, since temporaries don't survive
2361 // statement boundaries. So we use gcc's anonymous union/struct
2362 // facility to explicitly overlay the temporaries.
2363 parent->o->newline() << "union {";
2364 parent->o->indent(1);
2365 for (unsigned i=0; i<s->statements.size(); i++)
2366 {
2367 // To avoid lots of empty structs inside the union, remember
2368 // where we are now. Then, output the struct start and remember
2369 // that positon. If when we get done with the statement we
2370 // haven't moved, then we don't really need the struct. To get
2371 // rid of the struct start we output, we'll seek back to where
2372 // we were before we output the struct.
2373 std::ostream::pos_type before_struct_pos = parent->o->tellp();
2374 parent->o->newline() << "struct {";
2375 parent->o->indent(1);
2376 std::ostream::pos_type after_struct_pos = parent->o->tellp();
2377 s->statements[i]->visit (this);
2378 parent->o->indent(-1);
2379 if (after_struct_pos == parent->o->tellp())
2380 parent->o->seekp(before_struct_pos);
2381 else
2382 parent->o->newline() << "};";
2383 }
2384 parent->o->newline(-1) << "};";
2385 }
2386
2387 void
2388 c_tmpcounter::visit_for_loop (for_loop *s)
2389 {
2390 if (s->init) s->init->visit (this);
2391 s->cond->visit (this);
2392 s->block->visit (this);
2393 if (s->incr) s->incr->visit (this);
2394 }
2395
2396
2397 void
2398 c_unparser::visit_for_loop (for_loop *s)
2399 {
2400 string ctr = stringify (label_counter++);
2401 string toplabel = "top_" + ctr;
2402 string contlabel = "continue_" + ctr;
2403 string breaklabel = "break_" + ctr;
2404
2405 // initialization
2406 if (s->init) s->init->visit (this);
2407 record_actions(1, true);
2408
2409 // condition
2410 o->newline(-1) << toplabel << ":";
2411
2412 // Emit an explicit action here to cover the act of iteration.
2413 // Equivalently, it can stand for the evaluation of the condition
2414 // expression.
2415 o->indent(1);
2416 record_actions(1);
2417
2418 o->newline() << "if (! (";
2419 if (s->cond->type != pe_long)
2420 throw semantic_error ("expected numeric type", s->cond->tok);
2421 s->cond->visit (this);
2422 o->line() << ")) goto " << breaklabel << ";";
2423
2424 // body
2425 loop_break_labels.push_back (breaklabel);
2426 loop_continue_labels.push_back (contlabel);
2427 s->block->visit (this);
2428 record_actions(0, true);
2429 loop_break_labels.pop_back ();
2430 loop_continue_labels.pop_back ();
2431
2432 // iteration
2433 o->newline(-1) << contlabel << ":";
2434 o->indent(1);
2435 if (s->incr) s->incr->visit (this);
2436 o->newline() << "goto " << toplabel << ";";
2437
2438 // exit
2439 o->newline(-1) << breaklabel << ":";
2440 o->newline(1) << "; /* dummy statement */";
2441 }
2442
2443
2444 struct arrayindex_downcaster
2445 : public traversing_visitor
2446 {
2447 arrayindex *& arr;
2448
2449 arrayindex_downcaster (arrayindex *& arr)
2450 : arr(arr)
2451 {}
2452
2453 void visit_arrayindex (arrayindex* e)
2454 {
2455 arr = e;
2456 }
2457 };
2458
2459
2460 static bool
2461 expression_is_arrayindex (expression *e,
2462 arrayindex *& hist)
2463 {
2464 arrayindex *h = NULL;
2465 arrayindex_downcaster d(h);
2466 e->visit (&d);
2467 if (static_cast<void*>(h) == static_cast<void*>(e))
2468 {
2469 hist = h;
2470 return true;
2471 }
2472 return false;
2473 }
2474
2475
2476 void
2477 c_tmpcounter::visit_foreach_loop (foreach_loop *s)
2478 {
2479 symbol *array;
2480 hist_op *hist;
2481 classify_indexable (s->base, array, hist);
2482
2483 if (array)
2484 {
2485 itervar iv = parent->getiter (array);
2486 parent->o->newline() << iv.declare();
2487 }
2488 else
2489 {
2490 // See commentary in c_tmpcounter::visit_arrayindex for
2491 // discussion of tmpvars required to look into @hist_op(...)
2492 // expressions.
2493
2494 // First make sure we have exactly one pe_long variable to use as
2495 // our bucket index.
2496
2497 if (s->indexes.size() != 1 || s->indexes[0]->referent->type != pe_long)
2498 throw semantic_error("Invalid indexing of histogram", s->tok);
2499
2500 // Then declare what we need to form the aggregate we're
2501 // iterating over, and all the tmpvars needed by our call to
2502 // load_aggregate().
2503
2504 aggvar agg = parent->gensym_aggregate ();
2505 agg.declare(*(this->parent));
2506
2507 symbol *sym = get_symbol_within_expression (hist->stat);
2508 var v = parent->getvar(sym->referent, sym->tok);
2509 if (sym->referent->arity != 0)
2510 {
2511 arrayindex *arr = NULL;
2512 if (!expression_is_arrayindex (hist->stat, arr))
2513 throw semantic_error("expected arrayindex expression in iterated hist_op", s->tok);
2514
2515 for (unsigned i=0; i<sym->referent->index_types.size(); i++)
2516 {
2517 tmpvar ix = parent->gensym (sym->referent->index_types[i]);
2518 ix.declare (*parent);
2519 arr->indexes[i]->visit(this);
2520 }
2521 }
2522 }
2523
2524 // Create a temporary for the loop limit counter and the limit
2525 // expression result.
2526 if (s->limit)
2527 {
2528 tmpvar res_limit = parent->gensym (pe_long);
2529 res_limit.declare(*parent);
2530
2531 s->limit->visit (this);
2532
2533 tmpvar limitv = parent->gensym (pe_long);
2534 limitv.declare(*parent);
2535 }
2536
2537 s->block->visit (this);
2538 }
2539
2540 void
2541 c_unparser::visit_foreach_loop (foreach_loop *s)
2542 {
2543 symbol *array;
2544 hist_op *hist;
2545 classify_indexable (s->base, array, hist);
2546
2547 if (array)
2548 {
2549 mapvar mv = getmap (array->referent, s->tok);
2550 itervar iv = getiter (array);
2551 vector<var> keys;
2552
2553 string ctr = stringify (label_counter++);
2554 string toplabel = "top_" + ctr;
2555 string contlabel = "continue_" + ctr;
2556 string breaklabel = "break_" + ctr;
2557
2558 // NB: structure parallels for_loop
2559
2560 // initialization
2561
2562 tmpvar *res_limit = NULL;
2563 if (s->limit)
2564 {
2565 // Evaluate the limit expression once.
2566 res_limit = new tmpvar(gensym(pe_long));
2567 c_assign (res_limit->value(), s->limit, "foreach limit");
2568 }
2569
2570 // aggregate array if required
2571 if (mv.is_parallel())
2572 {
2573 o->newline() << "if (unlikely(NULL == " << mv.calculate_aggregate() << ")) {";
2574 o->newline(1) << "c->last_error = \"aggregation overflow in " << mv << "\";";
2575 o->newline() << "goto out;";
2576 o->newline(-1) << "}";
2577
2578 // sort array if desired
2579 if (s->sort_direction)
2580 {
2581 int sort_column;
2582
2583 // If the user wanted us to sort by value, we'll sort by
2584 // @count instead for aggregates. '-5' tells the
2585 // runtime to sort by count.
2586 if (s->sort_column == 0)
2587 sort_column = -5;
2588 else
2589 sort_column = s->sort_column;
2590
2591 o->newline() << "else"; // only sort if aggregation was ok
2592 if (s->limit)
2593 {
2594 o->newline(1) << "_stp_map_sortn ("
2595 << mv.fetch_existing_aggregate() << ", "
2596 << *res_limit << ", " << sort_column << ", "
2597 << - s->sort_direction << ");";
2598 }
2599 else
2600 {
2601 o->newline(1) << "_stp_map_sort ("
2602 << mv.fetch_existing_aggregate() << ", "
2603 << sort_column << ", "
2604 << - s->sort_direction << ");";
2605 }
2606 o->indent(-1);
2607 }
2608 }
2609 else
2610 {
2611 // sort array if desired
2612 if (s->sort_direction)
2613 {
2614 if (s->limit)
2615 {
2616 o->newline() << "_stp_map_sortn (" << mv.value() << ", "
2617 << *res_limit << ", " << s->sort_column << ", "
2618 << - s->sort_direction << ");";
2619 }
2620 else
2621 {
2622 o->newline() << "_stp_map_sort (" << mv.value() << ", "
2623 << s->sort_column << ", "
2624 << - s->sort_direction << ");";
2625 }
2626 }
2627 }
2628
2629 // NB: sort direction sense is opposite in runtime, thus the negation
2630
2631 if (mv.is_parallel())
2632 aggregations_active.insert(mv.value());
2633 o->newline() << iv << " = " << iv.start (mv) << ";";
2634
2635 tmpvar *limitv = NULL;
2636 if (s->limit)
2637 {
2638 // Create the loop limit variable here and initialize it.
2639 limitv = new tmpvar(gensym (pe_long));
2640 o->newline() << *limitv << " = 0LL;";
2641 }
2642
2643 record_actions(1, true);
2644
2645 // condition
2646 o->newline(-1) << toplabel << ":";
2647
2648 // Emit an explicit action here to cover the act of iteration.
2649 // Equivalently, it can stand for the evaluation of the
2650 // condition expression.
2651 o->indent(1);
2652 record_actions(1);
2653
2654 o->newline() << "if (! (" << iv << ")) goto " << breaklabel << ";";
2655
2656 // body
2657 loop_break_labels.push_back (breaklabel);
2658 loop_continue_labels.push_back (contlabel);
2659 o->newline() << "{";
2660 o->indent (1);
2661
2662 if (s->limit)
2663 {
2664 // If we've been through LIMIT loop iterations, quit.
2665 o->newline() << "if (" << *limitv << "++ >= " << *res_limit
2666 << ") goto " << breaklabel << ";";
2667
2668 // We're done with limitv and res_limit.
2669 delete limitv;
2670 delete res_limit;
2671 }
2672
2673 for (unsigned i = 0; i < s->indexes.size(); ++i)
2674 {
2675 // copy the iter values into the specified locals
2676 var v = getvar (s->indexes[i]->referent);
2677 c_assign (v, iv.get_key (v.type(), i), s->tok);
2678 }
2679 s->block->visit (this);
2680 record_actions(0, true);
2681 o->newline(-1) << "}";
2682 loop_break_labels.pop_back ();
2683 loop_continue_labels.pop_back ();
2684
2685 // iteration
2686 o->newline(-1) << contlabel << ":";
2687 o->newline(1) << iv << " = " << iv.next (mv) << ";";
2688 o->newline() << "goto " << toplabel << ";";
2689
2690 // exit
2691 o->newline(-1) << breaklabel << ":";
2692 o->newline(1) << "; /* dummy statement */";
2693
2694 if (mv.is_parallel())
2695 aggregations_active.erase(mv.value());
2696 }
2697 else
2698 {
2699 // Iterating over buckets in a histogram.
2700 assert(s->indexes.size() == 1);
2701 assert(s->indexes[0]->referent->type == pe_long);
2702 var bucketvar = getvar (s->indexes[0]->referent);
2703
2704 aggvar agg = gensym_aggregate ();
2705 load_aggregate(hist->stat, agg);
2706
2707 symbol *sym = get_symbol_within_expression (hist->stat);
2708 var v = getvar(sym->referent, sym->tok);
2709 v.assert_hist_compatible(*hist);
2710
2711 tmpvar *res_limit = NULL;
2712 tmpvar *limitv = NULL;
2713 if (s->limit)
2714 {
2715 // Evaluate the limit expression once.
2716 res_limit = new tmpvar(gensym(pe_long));
2717 c_assign (res_limit->value(), s->limit, "foreach limit");
2718
2719 // Create the loop limit variable here and initialize it.
2720 limitv = new tmpvar(gensym (pe_long));
2721 o->newline() << *limitv << " = 0LL;";
2722 }
2723
2724 // XXX: break / continue don't work here yet
2725 record_actions(1, true);
2726 o->newline() << "for (" << bucketvar << " = 0; "
2727 << bucketvar << " < " << v.buckets() << "; "
2728 << bucketvar << "++) { ";
2729 o->newline(1);
2730
2731 if (s->limit)
2732 {
2733 // If we've been through LIMIT loop iterations, quit.
2734 o->newline() << "if (" << *limitv << "++ >= " << *res_limit
2735 << ") break;";
2736
2737 // We're done with limitv and res_limit.
2738 delete limitv;
2739 delete res_limit;
2740 }
2741
2742 s->block->visit (this);
2743 record_actions(1, true);
2744 o->newline(-1) << "}";
2745 }
2746 }
2747
2748
2749 void
2750 c_unparser::visit_return_statement (return_statement* s)
2751 {
2752 if (current_function == 0)
2753 throw semantic_error ("cannot 'return' from probe", s->tok);
2754
2755 if (s->value->type != current_function->type)
2756 throw semantic_error ("return type mismatch", current_function->tok,
2757 "vs", s->tok);
2758
2759 c_assign ("l->__retvalue", s->value, "return value");
2760 record_actions(1, true);
2761 o->newline() << "goto out;";
2762 }
2763
2764
2765 void
2766 c_unparser::visit_next_statement (next_statement* s)
2767 {
2768 if (current_probe == 0)
2769 throw semantic_error ("cannot 'next' from function", s->tok);
2770
2771 record_actions(1, true);
2772 o->newline() << "goto out;";
2773 }
2774
2775
2776 struct delete_statement_operand_tmp_visitor:
2777 public traversing_visitor
2778 {
2779 c_tmpcounter *parent;
2780 delete_statement_operand_tmp_visitor (c_tmpcounter *p):
2781 parent (p)
2782 {}
2783 //void visit_symbol (symbol* e);
2784 void visit_arrayindex (arrayindex* e);
2785 };
2786
2787
2788 struct delete_statement_operand_visitor:
2789 public throwing_visitor
2790 {
2791 c_unparser *parent;
2792 delete_statement_operand_visitor (c_unparser *p):
2793 throwing_visitor ("invalid operand of delete expression"),
2794 parent (p)
2795 {}
2796 void visit_symbol (symbol* e);
2797 void visit_arrayindex (arrayindex* e);
2798 };
2799
2800 void
2801 delete_statement_operand_visitor::visit_symbol (symbol* e)
2802 {
2803 assert (e->referent != 0);
2804 if (e->referent->arity > 0)
2805 {
2806 mapvar mvar = parent->getmap(e->referent, e->tok);
2807 /* NB: Memory deallocation/allocation operations
2808 are not generally safe.
2809 parent->o->newline() << mvar.fini ();
2810 parent->o->newline() << mvar.init ();
2811 */
2812 if (mvar.is_parallel())
2813 parent->o->newline() << "_stp_pmap_clear (" << mvar.value() << ");";
2814 else
2815 parent->o->newline() << "_stp_map_clear (" << mvar.value() << ");";
2816 }
2817 else
2818 {
2819 var v = parent->getvar(e->referent, e->tok);
2820 switch (e->type)
2821 {
2822 case pe_stats:
2823 parent->o->newline() << "_stp_stat_clear (" << v.value() << ");";
2824 break;
2825 case pe_long:
2826 parent->o->newline() << v.value() << " = 0;";
2827 break;
2828 case pe_string:
2829 parent->o->newline() << v.value() << "[0] = '\\0';";
2830 break;
2831 case pe_unknown:
2832 default:
2833 throw semantic_error("Cannot delete unknown expression type", e->tok);
2834 }
2835 }
2836 }
2837
2838 void
2839 delete_statement_operand_tmp_visitor::visit_arrayindex (arrayindex* e)
2840 {
2841 symbol *array;
2842 hist_op *hist;
2843 classify_indexable (e->base, array, hist);
2844
2845 if (array)
2846 {
2847 assert (array->referent != 0);
2848 vardecl* r = array->referent;
2849
2850 // One temporary per index dimension.
2851 for (unsigned i=0; i<r->index_types.size(); i++)
2852 {
2853 tmpvar ix = parent->parent->gensym (r->index_types[i]);
2854 ix.declare (*(parent->parent));
2855 e->indexes[i]->visit(parent);
2856 }
2857 }
2858 else
2859 {
2860 throw semantic_error("cannot delete histogram bucket entries\n", e->tok);
2861 }
2862 }
2863
2864 void
2865 delete_statement_operand_visitor::visit_arrayindex (arrayindex* e)
2866 {
2867 symbol *array;
2868 hist_op *hist;
2869 classify_indexable (e->base, array, hist);
2870
2871 if (array)
2872 {
2873 vector<tmpvar> idx;
2874 parent->load_map_indices (e, idx);
2875
2876 {
2877 mapvar mvar = parent->getmap (array->referent, e->tok);
2878 parent->o->newline() << mvar.del (idx) << ";";
2879 }
2880 }
2881 else
2882 {
2883 throw semantic_error("cannot delete histogram bucket entries\n", e->tok);
2884 }
2885 }
2886
2887
2888 void
2889 c_tmpcounter::visit_delete_statement (delete_statement* s)
2890 {
2891 delete_statement_operand_tmp_visitor dv (this);
2892 s->value->visit (&dv);
2893 }
2894
2895
2896 void
2897 c_unparser::visit_delete_statement (delete_statement* s)
2898 {
2899 delete_statement_operand_visitor dv (this);
2900 s->value->visit (&dv);
2901 record_actions(1);
2902 }
2903
2904
2905 void
2906 c_unparser::visit_break_statement (break_statement* s)
2907 {
2908 if (loop_break_labels.size() == 0)
2909 throw semantic_error ("cannot 'break' outside loop", s->tok);
2910
2911 record_actions(1, true);
2912 string label = loop_break_labels[loop_break_labels.size()-1];
2913 o->newline() << "goto " << label << ";";
2914 }
2915
2916
2917 void
2918 c_unparser::visit_continue_statement (continue_statement* s)
2919 {
2920 if (loop_continue_labels.size() == 0)
2921 throw semantic_error ("cannot 'continue' outside loop", s->tok);
2922
2923 record_actions(1, true);
2924 string label = loop_continue_labels[loop_continue_labels.size()-1];
2925 o->newline() << "goto " << label << ";";
2926 }
2927
2928
2929
2930 void
2931 c_unparser::visit_literal_string (literal_string* e)
2932 {
2933 const string& v = e->value;
2934 o->line() << '"';
2935 for (unsigned i=0; i<v.size(); i++)
2936 // NB: The backslash character is specifically passed through as is.
2937 // This is because our parser treats "\" as an ordinary character, not
2938 // an escape sequence, leaving it to the C compiler (and this function)
2939 // to treat it as such. If we were to escape it, there would be no way
2940 // of generating C-level escapes from script code.
2941 // See also print_format::components_to_string and lex_cast_qstring
2942 if (v[i] == '"') // or other escapeworthy characters?
2943 o->line() << '\\' << '"';
2944 else
2945 o->line() << v[i];
2946 o->line() << '"';
2947 }
2948
2949
2950 void
2951 c_unparser::visit_literal_number (literal_number* e)
2952 {
2953 // This looks ugly, but tries to be warning-free on 32- and 64-bit
2954 // hosts.
2955 // NB: this needs to be signed!
2956 if (e->value == -9223372036854775807LL-1) // PR 5023
2957 o->line() << "((int64_t)" << (unsigned long long) e->value << "ULL)";
2958 else
2959 o->line() << "((int64_t)" << e->value << "LL)";
2960 }
2961
2962
2963 void
2964 c_tmpcounter::visit_binary_expression (binary_expression* e)
2965 {
2966 if (e->op == "/" || e->op == "%")
2967 {
2968 tmpvar left = parent->gensym (pe_long);
2969 tmpvar right = parent->gensym (pe_long);
2970 if (e->left->tok->type != tok_number)
2971 left.declare (*parent);
2972 if (e->right->tok->type != tok_number)
2973 right.declare (*parent);
2974 }
2975
2976 e->left->visit (this);
2977 e->right->visit (this);
2978 }
2979
2980
2981 void
2982 c_unparser::visit_binary_expression (binary_expression* e)
2983 {
2984 if (e->type != pe_long ||
2985 e->left->type != pe_long ||
2986 e->right->type != pe_long)
2987 throw semantic_error ("expected numeric types", e->tok);
2988
2989 if (e->op == "+" ||
2990 e->op == "-" ||
2991 e->op == "*" ||
2992 e->op == "&" ||
2993 e->op == "|" ||
2994 e->op == "^")
2995 {
2996 o->line() << "((";
2997 e->left->visit (this);
2998 o->line() << ") " << e->op << " (";
2999 e->right->visit (this);
3000 o->line() << "))";
3001 }
3002 else if (e->op == ">>" ||
3003 e->op == "<<")
3004 {
3005 o->line() << "((";
3006 e->left->visit (this);
3007 o->line() << ") " << e->op << "max(min(";
3008 e->right->visit (this);
3009 o->line() << ", (int64_t)64LL), (int64_t)0LL))"; // between 0 and 64
3010 }
3011 else if (e->op == "/" ||
3012 e->op == "%")
3013 {
3014 // % and / need a division-by-zero check; and thus two temporaries
3015 // for proper evaluation order
3016 tmpvar left = gensym (pe_long);
3017 tmpvar right = gensym (pe_long);
3018
3019 o->line() << "({";
3020 o->indent(1);
3021
3022 if (e->left->tok->type == tok_number)
3023 left.override(c_expression(e->left));
3024 else
3025 {
3026 o->newline() << left << " = ";
3027 e->left->visit (this);
3028 o->line() << ";";
3029 }
3030
3031 if (e->right->tok->type == tok_number)
3032 right.override(c_expression(e->right));
3033 else
3034 {
3035 o->newline() << right << " = ";
3036 e->right->visit (this);
3037 o->line() << ";";
3038 }
3039
3040 o->newline() << "if (unlikely(!" << right << ")) {";
3041 o->newline(1) << "c->last_error = \"division by 0\";";
3042 o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3043 o->newline() << "goto out;";
3044 o->newline(-1) << "}";
3045 o->newline() << ((e->op == "/") ? "_stp_div64" : "_stp_mod64")
3046 << " (NULL, " << left << ", " << right << ");";
3047
3048 o->newline(-1) << "})";
3049 }
3050 else
3051 throw semantic_error ("operator not yet implemented", e->tok);
3052 }
3053
3054
3055 void
3056 c_unparser::visit_unary_expression (unary_expression* e)
3057 {
3058 if (e->type != pe_long ||
3059 e->operand->type != pe_long)
3060 throw semantic_error ("expected numeric types", e->tok);
3061
3062 if (e->op == "-")
3063 {
3064 // NB: Subtraction is special, since negative literals in the
3065 // script language show up as unary negations over positive
3066 // literals here. This makes it "exciting" for emitting pure
3067 // C since: - 0x8000_0000_0000_0000 ==> - (- 9223372036854775808)
3068 // This would constitute a signed overflow, which gcc warns on
3069 // unless -ftrapv/-J are in CFLAGS - which they're not.
3070
3071 o->line() << "(int64_t)(0 " << e->op << " (uint64_t)(";
3072 e->operand->visit (this);
3073 o->line() << "))";
3074 }
3075 else
3076 {
3077 o->line() << "(" << e->op << " (";
3078 e->operand->visit (this);
3079 o->line() << "))";
3080 }
3081 }
3082
3083 void
3084 c_unparser::visit_logical_or_expr (logical_or_expr* e)
3085 {
3086 if (e->type != pe_long ||
3087 e->left->type != pe_long ||
3088 e->right->type != pe_long)
3089 throw semantic_error ("expected numeric types", e->tok);
3090
3091 o->line() << "((";
3092 e->left->visit (this);
3093 o->line() << ") " << e->op << " (";
3094 e->right->visit (this);
3095 o->line() << "))";
3096 }
3097
3098
3099 void
3100 c_unparser::visit_logical_and_expr (logical_and_expr* e)
3101 {
3102 if (e->type != pe_long ||
3103 e->left->type != pe_long ||
3104 e->right->type != pe_long)
3105 throw semantic_error ("expected numeric types", e->tok);
3106
3107 o->line() << "((";
3108 e->left->visit (this);
3109 o->line() << ") " << e->op << " (";
3110 e->right->visit (this);
3111 o->line() << "))";
3112 }
3113
3114
3115 void
3116 c_tmpcounter::visit_array_in (array_in* e)
3117 {
3118 symbol *array;
3119 hist_op *hist;
3120 classify_indexable (e->operand->base, array, hist);
3121
3122 if (array)
3123 {
3124 assert (array->referent != 0);
3125 vardecl* r = array->referent;
3126
3127 // One temporary per index dimension.
3128 for (unsigned i=0; i<r->index_types.size(); i++)
3129 {
3130 tmpvar ix = parent->gensym (r->index_types[i]);
3131 ix.declare (*parent);
3132 e->operand->indexes[i]->visit(this);
3133 }
3134
3135 // A boolean result.
3136 tmpvar res = parent->gensym (e->type);
3137 res.declare (*parent);
3138 }
3139 else
3140 {
3141 // By definition:
3142 //
3143 // 'foo in @hist_op(...)' is true iff
3144 // '@hist_op(...)[foo]' is nonzero
3145 //
3146 // so we just delegate to the latter call, since int64_t is also
3147 // our boolean type.
3148 e->operand->visit(this);
3149 }
3150 }
3151
3152
3153 void
3154 c_unparser::visit_array_in (array_in* e)
3155 {
3156 symbol *array;
3157 hist_op *hist;
3158 classify_indexable (e->operand->base, array, hist);
3159
3160 if (array)
3161 {
3162 stmt_expr block(*this);
3163
3164 vector<tmpvar> idx;
3165 load_map_indices (e->operand, idx);
3166 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3167
3168 tmpvar res = gensym (pe_long);
3169 mapvar mvar = getmap (array->referent, e->tok);
3170 c_assign (res, mvar.exists(idx), e->tok);
3171
3172 o->newline() << res << ";";
3173 }
3174 else
3175 {
3176 // By definition:
3177 //
3178 // 'foo in @hist_op(...)' is true iff
3179 // '@hist_op(...)[foo]' is nonzero
3180 //
3181 // so we just delegate to the latter call, since int64_t is also
3182 // our boolean type.
3183 e->operand->visit(this);
3184 }
3185 }
3186
3187
3188 void
3189 c_unparser::visit_comparison (comparison* e)
3190 {
3191 o->line() << "(";
3192
3193 if (e->left->type == pe_string)
3194 {
3195 if (e->right->type != pe_string)
3196 throw semantic_error ("expected string types", e->tok);
3197
3198 o->line() << "strncmp (";
3199 e->left->visit (this);
3200 o->line() << ", ";
3201 e->right->visit (this);
3202 o->line() << ", MAXSTRINGLEN";
3203 o->line() << ") " << e->op << " 0";
3204 }
3205 else if (e->left->type == pe_long)
3206 {
3207 if (e->right->type != pe_long)
3208 throw semantic_error ("expected numeric types", e->tok);
3209
3210 o->line() << "((";
3211 e->left->visit (this);
3212 o->line() << ") " << e->op << " (";
3213 e->right->visit (this);
3214 o->line() << "))";
3215 }
3216 else
3217 throw semantic_error ("unexpected type", e->left->tok);
3218
3219 o->line() << ")";
3220 }
3221
3222
3223 void
3224 c_tmpcounter::visit_concatenation (concatenation* e)
3225 {
3226 tmpvar t = parent->gensym (e->type);
3227 t.declare (*parent);
3228 e->left->visit (this);
3229 e->right->visit (this);
3230 }
3231
3232
3233 void
3234 c_unparser::visit_concatenation (concatenation* e)
3235 {
3236 if (e->op != ".")
3237 throw semantic_error ("unexpected concatenation operator", e->tok);
3238
3239 if (e->type != pe_string ||
3240 e->left->type != pe_string ||
3241 e->right->type != pe_string)
3242 throw semantic_error ("expected string types", e->tok);
3243
3244 tmpvar t = gensym (e->type);
3245
3246 o->line() << "({ ";
3247 o->indent(1);
3248 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3249 c_assign (t.value(), e->left, "assignment");
3250 c_strcat (t.value(), e->right);
3251 o->newline() << t << ";";
3252 o->newline(-1) << "})";
3253 }
3254
3255
3256 void
3257 c_unparser::visit_ternary_expression (ternary_expression* e)
3258 {
3259 if (e->cond->type != pe_long)
3260 throw semantic_error ("expected numeric condition", e->cond->tok);
3261
3262 if (e->truevalue->type != e->falsevalue->type ||
3263 e->type != e->truevalue->type ||
3264 (e->truevalue->type != pe_long && e->truevalue->type != pe_string))
3265 throw semantic_error ("expected matching types", e->tok);
3266
3267 o->line() << "((";
3268 e->cond->visit (this);
3269 o->line() << ") ? (";
3270 e->truevalue->visit (this);
3271 o->line() << ") : (";
3272 e->falsevalue->visit (this);
3273 o->line() << "))";
3274 }
3275
3276
3277 void
3278 c_tmpcounter::visit_assignment (assignment *e)
3279 {
3280 c_tmpcounter_assignment tav (this, e->op, e->right);
3281 e->left->visit (& tav);
3282 }
3283
3284
3285 void
3286 c_unparser::visit_assignment (assignment* e)
3287 {
3288 if (e->op == "<<<")
3289 {
3290 if (e->type != pe_long)
3291 throw semantic_error ("non-number <<< expression", e->tok);
3292
3293 if (e->left->type != pe_stats)
3294 throw semantic_error ("non-stats left operand to <<< expression", e->left->tok);
3295
3296 if (e->right->type != pe_long)
3297 throw semantic_error ("non-number right operand to <<< expression", e->right->tok);
3298
3299 }
3300 else
3301 {
3302 if (e->type != e->left->type)
3303 throw semantic_error ("type mismatch", e->tok,
3304 "vs", e->left->tok);
3305 if (e->right->type != e->left->type)
3306 throw semantic_error ("type mismatch", e->right->tok,
3307 "vs", e->left->tok);
3308 }
3309
3310 c_unparser_assignment tav (this, e->op, e->right);
3311 e->left->visit (& tav);
3312 }
3313
3314
3315 void
3316 c_tmpcounter::visit_pre_crement (pre_crement* e)
3317 {
3318 c_tmpcounter_assignment tav (this, e->op, 0);
3319 e->operand->visit (& tav);
3320 }
3321
3322
3323 void
3324 c_unparser::visit_pre_crement (pre_crement* e)
3325 {
3326 if (e->type != pe_long ||
3327 e->type != e->operand->type)
3328 throw semantic_error ("expected numeric type", e->tok);
3329
3330 c_unparser_assignment tav (this, e->op, false);
3331 e->operand->visit (& tav);
3332 }
3333
3334
3335 void
3336 c_tmpcounter::visit_post_crement (post_crement* e)
3337 {
3338 c_tmpcounter_assignment tav (this, e->op, 0, true);
3339 e->operand->visit (& tav);
3340 }
3341
3342
3343 void
3344 c_unparser::visit_post_crement (post_crement* e)
3345 {
3346 if (e->type != pe_long ||
3347 e->type != e->operand->type)
3348 throw semantic_error ("expected numeric type", e->tok);
3349
3350 c_unparser_assignment tav (this, e->op, true);
3351 e->operand->visit (& tav);
3352 }
3353
3354
3355 void
3356 c_unparser::visit_symbol (symbol* e)
3357 {
3358 assert (e->referent != 0);
3359 vardecl* r = e->referent;
3360
3361 if (r->index_types.size() != 0)
3362 throw semantic_error ("invalid reference to array", e->tok);
3363
3364 var v = getvar(r, e->tok);
3365 o->line() << v;
3366 }
3367
3368
3369 void
3370 c_tmpcounter_assignment::prepare_rvalue (tmpvar & rval)
3371 {
3372 if (rvalue)
3373 {
3374 // literal number and strings don't need any temporaries declared
3375 if (rvalue->tok->type != tok_number && rvalue->tok->type != tok_string)
3376 rval.declare (*(parent->parent));
3377
3378 rvalue->visit (parent);
3379 }
3380 }
3381
3382 void
3383 c_tmpcounter_assignment::c_assignop(tmpvar & res)
3384 {
3385 if (res.type() == pe_string)
3386 {
3387 // string assignment doesn't need any temporaries declared
3388 }
3389 else if (op == "<<<")
3390 res.declare (*(parent->parent));
3391 else if (res.type() == pe_long)
3392 {
3393 // Only the 'post' operators ('x++') need a temporary declared.
3394 if (post)
3395 res.declare (*(parent->parent));
3396 }
3397 }
3398
3399 // Assignment expansion is tricky.
3400 //
3401 // Because assignments are nestable expressions, we have
3402 // to emit C constructs that are nestable expressions too.
3403 // We have to evaluate the given expressions the proper number of times,
3404 // including array indices.
3405 // We have to lock the lvalue (if global) against concurrent modification,
3406 // especially with modify-assignment operations (+=, ++).
3407 // We have to check the rvalue (for division-by-zero checks).
3408
3409 // In the normal "pre=false" case, for (A op B) emit:
3410 // ({ tmp = B; check(B); lock(A); res = A op tmp; A = res; unlock(A); res; })
3411 // In the "pre=true" case, emit instead:
3412 // ({ tmp = B; check(B); lock(A); res = A; A = res op tmp; unlock(A); res; })
3413 //
3414 // (op is the plain operator portion of a combined calculate/assignment:
3415 // "+" for "+=", and so on. It is in the "macop" variable below.)
3416 //
3417 // For array assignments, additional temporaries are used for each
3418 // index, which are expanded before the "tmp=B" expression, in order
3419 // to consistently order evaluation of lhs before rhs.
3420 //
3421
3422 void
3423 c_tmpcounter_assignment::visit_symbol (symbol *e)
3424 {
3425 exp_type ty = rvalue ? rvalue->type : e->type;
3426 tmpvar rval = parent->parent->gensym (ty);
3427 tmpvar res = parent->parent->gensym (ty);
3428
3429 prepare_rvalue(rval);
3430
3431 c_assignop (res);
3432 }
3433
3434
3435 void
3436 c_unparser_assignment::prepare_rvalue (string const & op,
3437 tmpvar & rval,
3438 token const * tok)
3439 {
3440 if (rvalue)
3441 {
3442 if (rvalue->tok->type == tok_number || rvalue->tok->type == tok_string)
3443 // Instead of assigning the numeric or string constant to a
3444 // temporary, then assigning the temporary to the final, let's
3445 // just override the temporary with the constant.
3446 rval.override(parent->c_expression(rvalue));
3447 else
3448 parent->c_assign (rval.value(), rvalue, "assignment");
3449 }
3450 else
3451 {
3452 if (op == "++" || op == "--")
3453 // Here is part of the conversion proccess of turning "x++" to
3454 // "x += 1".
3455 rval.override("1");
3456 else
3457 throw semantic_error ("need rvalue for assignment", tok);
3458 }
3459 }
3460
3461 void
3462 c_unparser_assignment::visit_symbol (symbol *e)
3463 {
3464 stmt_expr block(*parent);
3465
3466 assert (e->referent != 0);
3467 if (e->referent->index_types.size() != 0)
3468 throw semantic_error ("unexpected reference to array", e->tok);
3469
3470 // parent->o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3471 exp_type ty = rvalue ? rvalue->type : e->type;
3472 tmpvar rval = parent->gensym (ty);
3473 tmpvar res = parent->gensym (ty);
3474
3475 prepare_rvalue (op, rval, e->tok);
3476
3477 var lvar = parent->getvar (e->referent, e->tok);
3478 c_assignop (res, lvar, rval, e->tok);
3479
3480 parent->o->newline() << res << ";";
3481 }
3482
3483
3484 void
3485 c_unparser::visit_target_symbol (target_symbol* e)
3486 {
3487 throw semantic_error("cannot translate general target-symbol expression", e->tok);
3488 }
3489
3490
3491 void
3492 c_unparser::visit_cast_op (cast_op* e)
3493 {
3494 throw semantic_error("cannot translate general cast expression", e->tok);
3495 }
3496
3497
3498 void
3499 c_tmpcounter::load_map_indices(arrayindex *e)
3500 {
3501 symbol *array;
3502 hist_op *hist;
3503 classify_indexable (e->base, array, hist);
3504
3505 if (array)
3506 {
3507 assert (array->referent != 0);
3508 vardecl* r = array->referent;
3509
3510 // One temporary per index dimension, except in the case of
3511 // number or string constants.
3512 for (unsigned i=0; i<r->index_types.size(); i++)
3513 {
3514 tmpvar ix = parent->gensym (r->index_types[i]);
3515 if (e->indexes[i]->tok->type == tok_number
3516 || e->indexes[i]->tok->type == tok_string)
3517 {
3518 // Do nothing
3519 }
3520 else
3521 ix.declare (*parent);
3522 e->indexes[i]->visit(this);
3523 }
3524 }
3525 }
3526
3527
3528 void
3529 c_unparser::load_map_indices(arrayindex *e,
3530 vector<tmpvar> & idx)
3531 {
3532 symbol *array;
3533 hist_op *hist;
3534 classify_indexable (e->base, array, hist);
3535
3536 if (array)
3537 {
3538 idx.clear();
3539
3540 assert (array->referent != 0);
3541 vardecl* r = array->referent;
3542
3543 if (r->index_types.size() == 0 ||
3544 r->index_types.size() != e->indexes.size())
3545 throw semantic_error ("invalid array reference", e->tok);
3546
3547 for (unsigned i=0; i<r->index_types.size(); i++)
3548 {
3549 if (r->index_types[i] != e->indexes[i]->type)
3550 throw semantic_error ("array index type mismatch", e->indexes[i]->tok);
3551
3552 tmpvar ix = gensym (r->index_types[i]);
3553 if (e->indexes[i]->tok->type == tok_number
3554 || e->indexes[i]->tok->type == tok_string)
3555 // Instead of assigning the numeric or string constant to a
3556 // temporary, then using the temporary, let's just
3557 // override the temporary with the constant.
3558 ix.override(c_expression(e->indexes[i]));
3559 else
3560 {
3561 // o->newline() << "c->last_stmt = "
3562 // << lex_cast_qstring(*e->indexes[i]->tok) << ";";
3563 c_assign (ix.value(), e->indexes[i], "array index copy");
3564 }
3565 idx.push_back (ix);
3566 }
3567 }
3568 else
3569 {
3570 assert (e->indexes.size() == 1);
3571 assert (e->indexes[0]->type == pe_long);
3572 tmpvar ix = gensym (pe_long);
3573 // o->newline() << "c->last_stmt = "
3574 // << lex_cast_qstring(*e->indexes[0]->tok) << ";";
3575 c_assign (ix.value(), e->indexes[0], "array index copy");
3576 idx.push_back(ix);
3577 }
3578 }
3579
3580
3581 void
3582 c_unparser::load_aggregate (expression *e, aggvar & agg, bool pre_agg)
3583 {
3584 symbol *sym = get_symbol_within_expression (e);
3585
3586 if (sym->referent->type != pe_stats)
3587 throw semantic_error ("unexpected aggregate of non-statistic", sym->tok);
3588
3589 var v = getvar(sym->referent, e->tok);
3590
3591 if (sym->referent->arity == 0)
3592 {
3593 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";";
3594 o->newline() << agg << " = _stp_stat_get (" << v << ", 0);";
3595 }
3596 else
3597 {
3598 arrayindex *arr = NULL;
3599 if (!expression_is_arrayindex (e, arr))
3600 throw semantic_error("unexpected aggregate of non-arrayindex", e->tok);
3601
3602 vector<tmpvar> idx;
3603 load_map_indices (arr, idx);
3604 mapvar mvar = getmap (sym->referent, sym->tok);
3605 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";";
3606 o->newline() << agg << " = " << mvar.get(idx, pre_agg) << ";";
3607 }
3608 }
3609
3610
3611 string
3612 c_unparser::histogram_index_check(var & base, tmpvar & idx) const
3613 {
3614 return "((" + idx.value() + " >= 0)"
3615 + " && (" + idx.value() + " < " + base.buckets() + "))";
3616 }
3617
3618
3619 void
3620 c_tmpcounter::visit_arrayindex (arrayindex *e)
3621 {
3622 symbol *array;
3623 hist_op *hist;
3624 classify_indexable (e->base, array, hist);
3625
3626 if (array)
3627 {
3628 load_map_indices(e);
3629
3630 // The index-expression result.
3631 tmpvar res = parent->gensym (e->type);
3632 res.declare (*parent);
3633 }
3634 else
3635 {
3636
3637 assert(hist);
3638
3639 // Note: this is a slightly tricker-than-it-looks allocation of
3640 // temporaries. The reason is that we're in the branch handling
3641 // histogram-indexing, and the histogram might be build over an
3642 // indexable entity itself. For example if we have:
3643 //
3644 // global foo
3645 // ...
3646 // foo[getpid(), geteuid()] <<< 1
3647 // ...
3648 // print @log_hist(foo[pid, euid])[bucket]
3649 //
3650 // We are looking at the @log_hist(...)[bucket] expression, so
3651 // allocating one tmpvar for calculating bucket (the "index" of
3652 // this arrayindex expression), and one tmpvar for storing the
3653 // result in, just as normal.
3654 //
3655 // But we are *also* going to call load_aggregate on foo, which
3656 // will itself require tmpvars for each of its indices. Since
3657 // this is not handled by delving into the subexpression (it
3658 // would be if hist were first-class in the type system, but
3659 // it's not) we we allocate all the tmpvars used in such a
3660 // subexpression up here: first our own aggvar, then our index
3661 // (bucket) tmpvar, then all the index tmpvars of our
3662 // pe_stat-valued subexpression, then our result.
3663
3664
3665 // First all the stuff related to indexing into the histogram
3666
3667 if (e->indexes.size() != 1)
3668 throw semantic_error("Invalid indexing of histogram", e->tok);
3669 tmpvar ix = parent->gensym (pe_long);
3670 ix.declare (*parent);
3671 e->indexes[0]->visit(this);
3672 tmpvar res = parent->gensym (pe_long);
3673 res.declare (*parent);
3674
3675 // Then the aggregate, and all the tmpvars needed by our call to
3676 // load_aggregate().
3677
3678 aggvar agg = parent->gensym_aggregate ();
3679 agg.declare(*(this->parent));
3680
3681 symbol *sym = get_symbol_within_expression (hist->stat);
3682 var v = parent->getvar(sym->referent, sym->tok);
3683 if (sym->referent->arity != 0)
3684 {
3685 arrayindex *arr = NULL;
3686 if (!expression_is_arrayindex (hist->stat, arr))
3687 throw semantic_error("expected arrayindex expression in indexed hist_op", e->tok);
3688
3689 for (unsigned i=0; i<sym->referent->index_types.size(); i++)
3690 {
3691 tmpvar ix = parent->gensym (sym->referent->index_types[i]);
3692 ix.declare (*parent);
3693 arr->indexes[i]->visit(this);
3694 }
3695 }
3696 }
3697 }
3698
3699
3700 void
3701 c_unparser::visit_arrayindex (arrayindex* e)
3702 {
3703 symbol *array;
3704 hist_op *hist;
3705 classify_indexable (e->base, array, hist);
3706
3707 if (array)
3708 {
3709 // Visiting an statistic-valued array in a non-lvalue context is prohibited.
3710 if (array->referent->type == pe_stats)
3711 throw semantic_error ("statistic-valued array in rvalue context", e->tok);
3712
3713 stmt_expr block(*this);
3714
3715 // NB: Do not adjust the order of the next few lines; the tmpvar
3716 // allocation order must remain the same between
3717 // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex
3718
3719 vector<tmpvar> idx;
3720 load_map_indices (e, idx);
3721 tmpvar res = gensym (e->type);
3722
3723 mapvar mvar = getmap (array->referent, e->tok);
3724 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3725 c_assign (res, mvar.get(idx), e->tok);
3726
3727 o->newline() << res << ";";
3728 }
3729 else
3730 {
3731 // See commentary in c_tmpcounter::visit_arrayindex
3732
3733 assert(hist);
3734 stmt_expr block(*this);
3735
3736 // NB: Do not adjust the order of the next few lines; the tmpvar
3737 // allocation order must remain the same between
3738 // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex
3739
3740 vector<tmpvar> idx;
3741 load_map_indices (e, idx);
3742 tmpvar res = gensym (e->type);
3743
3744 aggvar agg = gensym_aggregate ();
3745
3746 // These should have faulted during elaboration if not true.
3747 assert(idx.size() == 1);
3748 assert(idx[0].type() == pe_long);
3749
3750 symbol *sym = get_symbol_within_expression (hist->stat);
3751
3752 var *v;
3753 if (sym->referent->arity < 1)
3754 v = new var(getvar(sym->referent, e->tok));
3755 else
3756 v = new mapvar(getmap(sym->referent, e->tok));
3757
3758 v->assert_hist_compatible(*hist);
3759
3760 if (aggregations_active.count(v->value()))
3761 load_aggregate(hist->stat, agg, true);
3762 else
3763 load_aggregate(hist->stat, agg, false);
3764
3765 o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3766
3767 // PR 2142+2610: empty aggregates
3768 o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
3769 << " || " << agg.value() << "->count == 0) {";
3770 o->newline(1) << "c->last_error = \"empty aggregate\";";
3771 o->newline() << "goto out;";
3772 o->newline(-1) << "} else {";
3773 o->newline(1) << "if (" << histogram_index_check(*v, idx[0]) << ")";
3774 o->newline(1) << res << " = " << agg << "->histogram[" << idx[0] << "];";
3775 o->newline(-1) << "else {";
3776 o->newline(1) << "c->last_error = \"histogram index out of range\";";
3777 o->newline() << "goto out;";
3778 o->newline(-1) << "}";
3779
3780 o->newline(-1) << "}";
3781 o->newline() << res << ";";
3782
3783 delete v;
3784 }
3785 }
3786
3787
3788 void
3789 c_tmpcounter_assignment::visit_arrayindex (arrayindex *e)
3790 {
3791 symbol *array;
3792 hist_op *hist;
3793 classify_indexable (e->base, array, hist);
3794
3795 if (array)
3796 {
3797 parent->load_map_indices(e);
3798
3799 // The expression rval, lval, and result.
3800 exp_type ty = rvalue ? rvalue->type : e->type;
3801 tmpvar rval = parent->parent->gensym (ty);
3802 tmpvar lval = parent->parent->gensym (ty);
3803 tmpvar res = parent->parent->gensym (ty);
3804
3805 prepare_rvalue(rval);
3806 lval.declare (*(parent->parent));
3807
3808 if (op == "<<<")
3809 res.declare (*(parent->parent));
3810 else
3811 c_assignop(res);
3812 }
3813 else
3814 {
3815 throw semantic_error("cannot assign to histogram buckets", e->tok);
3816 }
3817 }
3818
3819
3820 void
3821 c_unparser_assignment::visit_arrayindex (arrayindex *e)
3822 {
3823 symbol *array;
3824 hist_op *hist;
3825 classify_indexable (e->base, array, hist);
3826
3827 if (array)
3828 {
3829
3830 stmt_expr block(*parent);
3831
3832 translator_output *o = parent->o;
3833
3834 if (array->referent->index_types.size() == 0)
3835 throw semantic_error ("unexpected reference to scalar", e->tok);
3836
3837 // nb: Do not adjust the order of the next few lines; the tmpvar
3838 // allocation order must remain the same between
3839 // c_unparser_assignment::visit_arrayindex and
3840 // c_tmpcounter_assignment::visit_arrayindex
3841
3842 vector<tmpvar> idx;
3843 parent->load_map_indices (e, idx);
3844 exp_type ty = rvalue ? rvalue->type : e->type;
3845 tmpvar rvar = parent->gensym (ty);
3846 tmpvar lvar = parent->gensym (ty);
3847 tmpvar res = parent->gensym (ty);
3848
3849 // NB: because these expressions are nestable, emit this construct
3850 // thusly:
3851 // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs); lvar; res;
3852 // lock (array);
3853 // lvar = get (array,idx0...N); // if necessary
3854 // assignop (res, lvar, rvar);
3855 // set (array, idx0...N, lvar);
3856 // unlock (array);
3857 // res; })
3858 //
3859 // we store all indices in temporary variables to avoid nasty
3860 // reentrancy issues that pop up with nested expressions:
3861 // e.g. ++a[a[c]=5] could deadlock
3862 //
3863 //
3864 // There is an exception to the above form: if we're doign a <<< assigment to
3865 // a statistic-valued map, there's a special form we follow:
3866 //
3867 // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs);
3868 // *no need to* lock (array);
3869 // _stp_map_add_stat (array, idx0...N, rvar);
3870 // *no need to* unlock (array);
3871 // rvar; })
3872 //
3873 // To simplify variable-allocation rules, we assign rvar to lvar and
3874 // res in this block as well, even though they are technically
3875 // superfluous.
3876
3877 prepare_rvalue (op, rvar, e->tok);
3878
3879 if (op == "<<<")
3880 {
3881 assert (e->type == pe_stats);
3882 assert (rvalue->type == pe_long);
3883
3884 mapvar mvar = parent->getmap (array->referent, e->tok);
3885 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3886 o->newline() << mvar.add (idx, rvar) << ";";
3887 res = rvar;
3888 // no need for these dummy assignments
3889 // o->newline() << lvar << " = " << rvar << ";";
3890 // o->newline() << res << " = " << rvar << ";";
3891 }
3892 else
3893 {
3894 mapvar mvar = parent->getmap (array->referent, e->tok);
3895 // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
3896 if (op != "=") // don't bother fetch slot if we will just overwrite it
3897 parent->c_assign (lvar, mvar.get(idx), e->tok);
3898 c_assignop (res, lvar, rvar, e->tok);
3899 o->newline() << mvar.set (idx, lvar) << ";";
3900 }
3901
3902 o->newline() << res << ";";
3903 }
3904 else
3905 {
3906 throw semantic_error("cannot assign to histogram buckets", e->tok);
3907 }
3908 }
3909
3910
3911 void
3912 c_tmpcounter::visit_functioncall (functioncall *e)
3913 {
3914 assert (e->referent != 0);
3915 functiondecl* r = e->referent;
3916 // one temporary per argument, unless literal numbers or strings
3917 for (unsigned i=0; i<r->formal_args.size(); i++)
3918 {
3919 tmpvar t = parent->gensym (r->formal_args[i]->type);
3920 if (e->args[i]->tok->type != tok_number
3921 && e->args[i]->tok->type != tok_string)
3922 t.declare (*parent);
3923 e->args[i]->visit (this);
3924 }
3925 }
3926
3927
3928 void
3929 c_unparser::visit_functioncall (functioncall* e)
3930 {
3931 assert (e->referent != 0);
3932 functiondecl* r = e->referent;
3933
3934 if (r->formal_args.size() != e->args.size())
3935 throw semantic_error ("invalid length argument list", e->tok);
3936
3937 stmt_expr block(*this);
3938
3939 // NB: we store all actual arguments in temporary variables,
3940 // to avoid colliding sharing of context variables with
3941 // nested function calls: f(f(f(1)))
3942
3943 // compute actual arguments
3944 vector<tmpvar> tmp;
3945
3946 for (unsigned i=0; i<e->args.size(); i++)
3947 {
3948 tmpvar t = gensym(e->args[i]->type);
3949
3950 if (r->formal_args[i]->type != e->args[i]->type)
3951 throw semantic_error ("function argument type mismatch",
3952 e->args[i]->tok, "vs", r->formal_args[i]->tok);
3953
3954 if (e->args[i]->tok->type == tok_number
3955 || e->args[i]->tok->type == tok_string)
3956 t.override(c_expression(e->args[i]));
3957 else
3958 {
3959 // o->newline() << "c->last_stmt = "
3960 // << lex_cast_qstring(*e->args[i]->tok) << ";";
3961 c_assign (t.value(), e->args[i],
3962 "function actual argument evaluation");
3963 }
3964 tmp.push_back(t);
3965 }
3966
3967 // copy in actual arguments
3968 for (unsigned i=0; i<e->args.size(); i++)
3969 {
3970 if (r->formal_args[i]->type != e->args[i]->type)
3971 throw semantic_error ("function argument type mismatch",
3972 e->args[i]->tok, "vs", r->formal_args[i]->tok);
3973
3974 c_assign ("c->locals[c->nesting+1].function_" +
3975 c_varname (r->name) + "." +
3976 c_varname (r->formal_args[i]->name),
3977 tmp[i].value(),
3978 e->args[i]->type,
3979 "function actual argument copy",
3980 e->args[i]->tok);
3981 }
3982
3983 // call function
3984 o->newline() << "function_" << c_varname (r->name) << " (c);";
3985 o->newline() << "if (unlikely(c->last_error)) goto out;";
3986
3987 // return result from retvalue slot
3988 if (r->type == pe_unknown)
3989 // If we passed typechecking, then nothing will use this return value
3990 o->newline() << "(void) 0;";
3991 else
3992 o->newline() << "c->locals[c->nesting+1]"
3993 << ".function_" << c_varname (r->name)
3994 << ".__retvalue;";
3995 }
3996
3997 void
3998 c_tmpcounter::visit_print_format (print_format* e)
3999 {
4000 if (e->hist)
4001 {
4002 symbol *sym = get_symbol_within_expression (e->hist->stat);
4003 var v = parent->getvar(sym->referent, sym->tok);
4004 aggvar agg = parent->gensym_aggregate ();
4005
4006 agg.declare(*(this->parent));
4007
4008 if (sym->referent->arity != 0)
4009 {
4010 // One temporary per index dimension.
4011 for (unsigned i=0; i<sym->referent->index_types.size(); i++)
4012 {
4013 arrayindex *arr = NULL;
4014 if (!expression_is_arrayindex (e->hist->stat, arr))
4015 throw semantic_error("expected arrayindex expression in printed hist_op", e->tok);
4016
4017 tmpvar ix = parent->gensym (sym->referent->index_types[i]);
4018 ix.declare (*parent);
4019 arr->indexes[i]->visit(this);
4020 }
4021 }
4022 }
4023 else
4024 {
4025 // One temporary per argument
4026 for (unsigned i=0; i < e->args.size(); i++)
4027 {
4028 tmpvar t = parent->gensym (e->args[i]->type);
4029 if (e->args[i]->type == pe_unknown)
4030 {
4031 throw semantic_error("unknown type of arg to print operator",
4032 e->args[i]->tok);
4033 }
4034
4035 if (e->args[i]->tok->type != tok_number
4036 && e->args[i]->tok->type != tok_string)
4037 t.declare (*parent);
4038 e->args[i]->visit (this);
4039 }
4040
4041 // And the result
4042 exp_type ty = e->print_to_stream ? pe_long : pe_string;
4043 tmpvar res = parent->gensym (ty);
4044 if (ty == pe_string)
4045 res.declare (*parent);
4046 }
4047 }
4048
4049
4050 void
4051 c_unparser::visit_print_format (print_format* e)
4052 {
4053 // Print formats can contain a general argument list *or* a special
4054 // type of argument which gets its own processing: a single,
4055 // non-format-string'ed, histogram-type stat_op expression.
4056
4057 if (e->hist)
4058 {
4059 stmt_expr block(*this);
4060 symbol *sym = get_symbol_within_expression (e->hist->stat);
4061 aggvar agg = gensym_aggregate ();
4062
4063 var *v;
4064 if (sym->referent->arity < 1)
4065 v = new var(getvar(sym->referent, e->tok));
4066 else
4067 v = new mapvar(getmap(sym->referent, e->tok));
4068
4069 v->assert_hist_compatible(*e->hist);
4070
4071 {
4072 if (aggregations_active.count(v->value()))
4073 load_aggregate(e->hist->stat, agg, true);
4074 else
4075 load_aggregate(e->hist->stat, agg, false);
4076
4077 // PR 2142+2610: empty aggregates
4078 o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
4079 << " || " << agg.value() << "->count == 0) {";
4080 o->newline(1) << "c->last_error = \"empty aggregate\";";
4081 o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
4082 o->newline() << "goto out;";
4083 o->newline(-1) << "} else";
4084 o->newline(1) << "_stp_stat_print_histogram (" << v->hist() << ", " << agg.value() << ");";
4085 o->indent(-1);
4086 }
4087
4088 delete v;
4089 }
4090 else
4091 {
4092 stmt_expr block(*this);
4093
4094 // Compute actual arguments
4095 vector<tmpvar> tmp;
4096
4097 for (unsigned i=0; i<e->args.size(); i++)
4098 {
4099 tmpvar t = gensym(e->args[i]->type);
4100 tmp.push_back(t);
4101
4102 // o->newline() << "c->last_stmt = "
4103 // << lex_cast_qstring(*e->args[i]->tok) << ";";
4104
4105 // If we've got a numeric or string constant, instead of
4106 // assigning the numeric or string constant to a temporary,
4107 // then passing the temporary to _stp_printf/_stp_snprintf,
4108 // let's just override the temporary with the constant.
4109 if (e->args[i]->tok->type == tok_number
4110 || e->args[i]->tok->type == tok_string)
4111 tmp[i].override(c_expression(e->args[i]));
4112 else
4113 c_assign (t.value(), e->args[i],
4114 "print format actual argument evaluation");
4115 }
4116
4117 std::vector<print_format::format_component> components;
4118
4119 if (e->print_with_format)
4120 {
4121 components = e->components;
4122 }
4123 else
4124 {
4125 // Synthesize a print-format string if the user didn't
4126 // provide one; the synthetic string simply contains one
4127 // directive for each argument.
4128 for (unsigned i = 0; i < e->args.size(); ++i)
4129 {
4130 if (i > 0 && e->print_with_delim)
4131 components.push_back (e->delimiter);
4132 print_format::format_component curr;
4133 curr.clear();
4134 switch (e->args[i]->type)
4135 {
4136 case pe_unknown:
4137 throw semantic_error("cannot print unknown expression type", e->args[i]->tok);
4138 case pe_stats:
4139 throw semantic_error("cannot print a raw stats object", e->args[i]->tok);
4140 case pe_long:
4141 curr.type = print_format::conv_signed_decimal;
4142 break;
4143 case pe_string:
4144 curr.type = print_format::conv_string;
4145 break;
4146 }
4147 components.push_back (curr);
4148 }
4149
4150 if (e->print_with_newline)
4151 {
4152 print_format::format_component curr;
4153 curr.clear();
4154 curr.type = print_format::conv_literal;
4155 curr.literal_string = "\\n";
4156 components.push_back (curr);
4157 }
4158 }
4159
4160 // Allocate the result
4161 exp_type ty = e->print_to_stream ? pe_long : pe_string;
4162 tmpvar res = gensym (ty);
4163 int use_print = 0;
4164
4165 string format_string = print_format::components_to_string(components);
4166 if (tmp.size() == 0 || (tmp.size() == 1 && format_string == "%s"))
4167 use_print = 1;
4168 else if (tmp.size() == 1
4169 && e->args[0]->tok->type == tok_string
4170 && format_string == "%s\\n")
4171 {
4172 use_print = 1;
4173 tmp[0].override(tmp[0].value() + "\"\\n\"");
4174 components[0].type = print_format::conv_literal;
4175 }
4176
4177 // Make the [s]printf call...
4178
4179 // Generate code to check that any pointer arguments are actually accessible. */
4180 int arg_ix = 0;
4181 for (unsigned i = 0; i < components.size(); ++i) {
4182 if (components[i].type == print_format::conv_literal)
4183 continue;
4184
4185 /* Take note of the width and precision arguments, if any. */
4186 int width_ix = -1, prec_ix= -1;
4187 if (components[i].widthtype == print_format::width_dynamic)
4188 width_ix = arg_ix++;
4189 if (components[i].prectype == print_format::prec_dynamic)
4190 prec_ix = arg_ix++;
4191
4192 /* Generate a noop call to deref_buffer for %m. */
4193 if (components[i].type == print_format::conv_memory
4194 || components[i].type == print_format::conv_memory_hex) {
4195 this->probe_or_function_needs_deref_fault_handler = true;
4196 o->newline() << "deref_buffer (0, " << tmp[arg_ix].value() << ", ";
4197 if (prec_ix == -1)
4198 if (width_ix != -1)
4199 prec_ix = width_ix;
4200 if (prec_ix != -1)
4201 o->line() << tmp[prec_ix].value();
4202 else
4203 o->line() << "1";
4204 o->line() << ");";
4205 }
4206
4207 ++arg_ix;
4208 }
4209
4210 if (e->print_to_stream)
4211 {
4212 if (e->print_char)
4213 {
4214 o->newline() << "_stp_print_char (";
4215 if (tmp.size())
4216 o->line() << tmp[0].value() << ");";
4217 else
4218 o->line() << '"' << format_string << "\");";
4219 return;
4220 }
4221 if (use_print)
4222 {
4223 o->newline() << "_stp_print (";
4224 if (tmp.size())
4225 o->line() << tmp[0].value() << ");";
4226 else
4227 o->line() << '"' << format_string << "\");";
4228 return;
4229 }
4230
4231 // We'll just hardcode the result of 0 instead of using the
4232 // temporary.
4233 res.override("((int64_t)0LL)");
4234 o->newline() << "_stp_printf (";
4235 }
4236 else
4237 o->newline() << "_stp_snprintf (" << res.value() << ", MAXSTRINGLEN, ";
4238
4239 o->line() << '"' << format_string << '"';
4240
4241 /* Generate the actual arguments. Make sure that they match the expected type of the
4242 format specifier. */
4243 arg_ix = 0;
4244 for (unsigned i = 0; i < components.size(); ++i) {
4245 if (components[i].type == print_format::conv_literal)
4246 continue;
4247
4248 /* Cast the width and precision arguments, if any, to 'int'. */
4249 if (components[i].widthtype == print_format::width_dynamic)
4250 o->line() << ", (int)" << tmp[arg_ix++].value();
4251 if (components[i].prectype == print_format::prec_dynamic)
4252 o->line() << ", (int)" << tmp[arg_ix++].value();
4253
4254 /* The type of the %m argument is 'char*'. */
4255 if (components[i].type == print_format::conv_memory
4256 || components[i].type == print_format::conv_memory_hex)
4257 o->line() << ", (char*)(uintptr_t)" << tmp[arg_ix++].value();
4258 /* The type of the %c argument is 'int'. */
4259 else if (components[i].type == print_format::conv_char)
4260 o->line() << ", (int)" << tmp[arg_ix++].value();
4261 else if (arg_ix < (int) tmp.size())
4262 o->line() << ", " << tmp[arg_ix++].value();
4263 }
4264
4265 o->line() << ");";
4266 o->newline() << res.value() << ";";
4267 }
4268 }
4269
4270
4271 void
4272 c_tmpcounter::visit_stat_op (stat_op* e)
4273 {
4274 symbol *sym = get_symbol_within_expression (e->stat);
4275 var v = parent->getvar(sym->referent, e->tok);
4276 aggvar agg = parent->gensym_aggregate ();
4277 tmpvar res = parent->gensym (pe_long);
4278
4279 agg.declare(*(this->parent));
4280 res.declare(*(this->parent));
4281
4282 if (sym->referent->arity != 0)
4283 {
4284 // One temporary per index dimension.
4285 for (unsigned i=0; i<sym->referent->index_types.size(); i++)
4286 {
4287 // Sorry about this, but with no dynamic_cast<> and no
4288 // constructor patterns, this is how things work.
4289 arrayindex *arr = NULL;
4290 if (!expression_is_arrayindex (e->stat, arr))
4291 throw semantic_error("expected arrayindex expression in stat_op of array", e->tok);
4292
4293 tmpvar ix = parent->gensym (sym->referent->index_types[i]);
4294 ix.declare (*parent);
4295 arr->indexes[i]->visit(this);
4296 }
4297 }
4298 }
4299
4300 void
4301 c_unparser::visit_stat_op (stat_op* e)
4302 {
4303 // Stat ops can be *applied* to two types of expression:
4304 //
4305 // 1. An arrayindex expression on a pe_stats-valued array.
4306 //
4307 // 2. A symbol of type pe_stats.
4308
4309 // FIXME: classify the expression the stat_op is being applied to,
4310 // call appropriate stp_get_stat() / stp_pmap_get_stat() helper,
4311 // then reach into resultant struct stat_data.
4312
4313 // FIXME: also note that summarizing anything is expensive, and we
4314 // really ought to pass a timeout handler into the summary routine,
4315 // check its response, possibly exit if it ran out of cycles.
4316
4317 {
4318 stmt_expr block(*this);
4319 symbol *sym = get_symbol_within_expression (e->stat);
4320 aggvar agg = gensym_aggregate ();
4321 tmpvar res = gensym (pe_long);
4322 var v = getvar(sym->referent, e->tok);
4323 {
4324 if (aggregations_active.count(v.value()))
4325 load_aggregate(e->stat, agg, true);
4326 else
4327 load_aggregate(e->stat, agg, false);
4328
4329 // PR 2142+2610: empty aggregates
4330 if (e->ctype == sc_count)
4331 {
4332 o->newline() << "if (unlikely (" << agg.value() << " == NULL))";
4333 o->indent(1);
4334 c_assign(res, "0", e->tok);
4335 o->indent(-1);
4336 }
4337 else
4338 {
4339 o->newline() << "if (unlikely (" << agg.value() << " == NULL)"
4340 << " || " << agg.value() << "->count == 0) {";
4341 o->newline(1) << "c->last_error = \"empty aggregate\";";
4342 o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
4343 o->newline() << "goto out;";
4344 o->newline(-1) << "}";
4345 }
4346 o->newline() << "else";
4347 o->indent(1);
4348 switch (e->ctype)
4349 {
4350 case sc_average:
4351 c_assign(res, ("_stp_div64(NULL, " + agg.value() + "->sum, "
4352 + agg.value() + "->count)"),
4353 e->tok);
4354 break;
4355 case sc_count:
4356 c_assign(res, agg.value() + "->count", e->tok);
4357 break;
4358 case sc_sum:
4359 c_assign(res, agg.value() + "->sum", e->tok);
4360 break;
4361 case sc_min:
4362 c_assign(res, agg.value() + "->min", e->tok);
4363 break;
4364 case sc_max:
4365 c_assign(res, agg.value() + "->max", e->tok);
4366 break;
4367 }
4368 o->indent(-1);
4369 }
4370 o->newline() << res << ";";
4371 }
4372 }
4373
4374
4375 void
4376 c_unparser::visit_hist_op (hist_op*)
4377 {
4378 // Hist ops can only occur in a limited set of circumstances:
4379 //
4380 // 1. Inside an arrayindex expression, as the base referent. See
4381 // c_unparser::visit_arrayindex for handling of this case.
4382 //
4383 // 2. Inside a foreach statement, as the base referent. See
4384 // c_unparser::visit_foreach_loop for handling this case.
4385 //
4386 // 3. Inside a print_format expression, as the sole argument. See
4387 // c_unparser::visit_print_format for handling this case.
4388 //
4389 // Note that none of these cases involves the c_unparser ever
4390 // visiting this node. We should not get here.
4391
4392 assert(false);
4393 }
4394
4395
4396
4397 struct unwindsym_dump_context
4398 {
4399 systemtap_session& session;
4400 ostream& output;
4401 unsigned stp_module_index;
4402 set<string> undone_unwindsym_modules;
4403 };
4404
4405
4406 // Get the .debug_frame section for the given module.
4407 // l will be set to the length of the size of the unwind data if found.
4408 static void *get_unwind_data (Dwfl_Module *m, size_t *l)
4409 {
4410 Dwarf_Addr bias = 0;
4411 Dwarf *dw;
4412 GElf_Ehdr *ehdr, ehdr_mem;
4413 GElf_Shdr *shdr, shdr_mem;
4414 Elf_Scn *scn = NULL;
4415 Elf_Data *data = NULL;
4416
4417 dw = dwfl_module_getdwarf(m, &bias);
4418 if (dw != NULL)
4419 {
4420 Elf *elf = dwarf_getelf(dw);
4421 ehdr = gelf_getehdr(elf, &ehdr_mem);
4422 while ((scn = elf_nextscn(elf, scn)))
4423 {
4424 shdr = gelf_getshdr(scn, &shdr_mem);
4425 if (strcmp(elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name),
4426 ".debug_frame") == 0)
4427 {
4428 data = elf_rawdata(scn, NULL);
4429 break;
4430 }
4431 }
4432 }
4433
4434 if (data != NULL)
4435 {
4436 *l = data->d_size;
4437 return data->d_buf;
4438 }
4439
4440 return NULL;
4441 }
4442
4443 static int
4444 dump_unwindsyms (Dwfl_Module *m,
4445 void **userdata __attribute__ ((unused)),
4446 const char *name,
4447 Dwarf_Addr base,
4448 void *arg)
4449 {
4450 unwindsym_dump_context* c = (unwindsym_dump_context*) arg;
4451 assert (c);
4452 unsigned stpmod_idx = c->stp_module_index;
4453
4454 string modname = name;
4455
4456 // skip modules/files we're not actually interested in
4457 if (c->session.unwindsym_modules.find(modname) == c->session.unwindsym_modules.end())
4458 return DWARF_CB_OK;
4459
4460 c->stp_module_index ++;
4461
4462 if (c->session.verbose > 1)
4463 clog << "dump_unwindsyms " << name
4464 << " index=" << stpmod_idx
4465 << " base=0x" << hex << base << dec << endl;
4466
4467 // We want to extract several bits of information:
4468 //
4469 // - parts of the program-header that map the file's physical offsets to the text section
4470 // - section table: just a list of section (relocation) base addresses
4471 // - symbol table of the text-like sections, with all addresses relativized to each base
4472 // - the contents of .debug_frame section, for unwinding purposes
4473 //
4474 // In the future, we'll also care about data symbols.
4475
4476 int syments = dwfl_module_getsymtab(m);
4477 assert(syments);
4478
4479 //extract build-id from debuginfo file
4480 int build_id_len = 0;
4481 unsigned char *build_id_bits;
4482 GElf_Addr build_id_vaddr;
4483
4484 if ((build_id_len=dwfl_module_build_id(m,
4485 (const unsigned char **)&build_id_bits,
4486 &build_id_vaddr)) > 0)
4487 {
4488 // Enable workaround for elfutils dwfl bug.
4489 // see https://bugzilla.redhat.com/show_bug.cgi?id=465872
4490 // and http://sourceware.org/ml/systemtap/2008-q4/msg00579.html
4491 #ifdef _ELFUTILS_PREREQ
4492 #if _ELFUTILS_PREREQ(0,138)
4493 // Let's standardize to the buggy "end of build-id bits" behavior.
4494 build_id_vaddr += build_id_len;
4495 #endif
4496 #endif
4497 if (c->session.verbose > 1) {
4498 clog << "Found build-id in " << name
4499 << ", length " << build_id_len;
4500 clog << ", end at 0x" << hex << build_id_vaddr
4501 << dec << endl;
4502 }
4503 }
4504
4505 // Look up the relocation basis for symbols
4506 int n = dwfl_module_relocations (m);
4507
4508 dwfl_assert ("dwfl_module_relocations", n >= 0);
4509
4510
4511 // XXX: unfortunate duplication with tapsets.cxx:emit_address()
4512
4513 typedef map<Dwarf_Addr,const char*> addrmap_t; // NB: plain map, sorted by address
4514 vector<string> seclist; // encountered relocation bases (section names)
4515 map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap
4516
4517 Dwarf_Addr extra_offset = 0;
4518
4519 for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i)
4520 {
4521 GElf_Sym sym;
4522 const char *name = dwfl_module_getsym(m, i, &sym, NULL);
4523 if (name)
4524 {
4525 // NB: Yey, we found the kernel's _stext value.
4526 // Sess.sym_stext may be unset (0) at this point, since
4527 // there may have been no kernel probes set. We could
4528 // use tapsets.cxx:lookup_symbol_address(), but then
4529 // we're already iterating over the same data here...
4530 if (modname == "kernel" && !strcmp(name, "_stext"))
4531 {
4532 int ki;
4533 extra_offset = sym.st_value;
4534 ki = dwfl_module_relocate_address (m, &extra_offset);
4535 dwfl_assert ("dwfl_module_relocate_address extra_offset",
4536 ki >= 0);
4537 if (c->session.verbose > 2)
4538 clog << "Found kernel _stext 0x" << hex << extra_offset << dec << endl;
4539 }
4540
4541 // We only need the function symbols to identify kernel-mode
4542 // PC's, so we omit undefined or "fake" absolute addresses.
4543 // These fake absolute addresses occur in some older i386
4544 // kernels to indicate they are vDSO symbols, not real
4545 // functions in the kernel.
4546 if (GELF_ST_TYPE (sym.st_info) == STT_FUNC &&
4547 ! (sym.st_shndx == SHN_UNDEF || sym.st_shndx == SHN_ABS))
4548 {
4549 Dwarf_Addr sym_addr = sym.st_value;
4550 const char *secname = NULL;
4551
4552 if (n > 0) // only try to relocate if there exist relocation bases
4553 {
4554 int ki = dwfl_module_relocate_address (m, &sym_addr);
4555 dwfl_assert ("dwfl_module_relocate_address", ki >= 0);
4556 secname = dwfl_module_relocation_info (m, ki, NULL);
4557 }
4558
4559 if (n == 1 && modname == "kernel")
4560 {
4561 // This is a symbol within a (possibly relocatable)
4562 // kernel image.
4563 secname = "_stext";
4564 // NB: don't subtract session.sym_stext, which could be inconveniently NULL.
4565 // Instead, sym_addr will get compensated later via extra_offset.
4566 }
4567 else if (n > 0)
4568 {
4569 assert (secname != NULL);
4570 // secname adequately set
4571
4572 // NB: it may be an empty string for ET_DYN objects
4573 // like shared libraries, as their relocation base
4574 // is implicit.
4575 if (secname[0] == '\0')
4576 secname = ".dynamic";
4577 }
4578 else
4579 {
4580 assert (n == 0);
4581 // sym_addr is absolute, as it must be since there are no relocation bases
4582 secname = ".absolute"; // sentinel
4583 }
4584
4585 // Compute our section number
4586 unsigned secidx;
4587 for (secidx=0; secidx<seclist.size(); secidx++)
4588 if (seclist[secidx]==secname) break;
4589
4590 if (secidx == seclist.size()) // new section name
4591 seclist.push_back (secname);
4592
4593 (addrmap[secidx])[sym_addr] = name;
4594 }
4595 }
4596 }
4597
4598 // Add unwind data to be included if it exists for this module.
4599 size_t len = 0;
4600 void *unwind = get_unwind_data (m, &len);
4601 if (unwind != NULL)
4602 {
4603 c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
4604 c->output << "static uint8_t _stp_module_" << stpmod_idx
4605 << "_unwind_data[] = \n";
4606 c->output << " {";
4607 for (size_t i = 0; i < len; i++)
4608 {
4609 int h = ((uint8_t *)unwind)[i];
4610 c->output << "0x" << hex << h << dec << ",";
4611 if ((i + 1) % 16 == 0)
4612 c->output << "\n" << " ";
4613 }
4614 c->output << "};\n";
4615 c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA */\n";
4616 }
4617 else
4618 {
4619 // There would be only a small benefit to warning. A user
4620 // likely can't do anything about this; backtraces for the
4621 // affected module would just get all icky heuristicy.
4622 #if 0
4623 c->session.print_warning ("No unwind data for " + modname
4624 + ", " + dwfl_errmsg (-1));
4625 #endif
4626 }
4627
4628 for (unsigned secidx = 0; secidx < seclist.size(); secidx++)
4629 {
4630 c->output << "static struct _stp_symbol "
4631 << "_stp_module_" << stpmod_idx<< "_symbols_" << secidx << "[] = {\n";
4632
4633 // Only include symbols if they will be used
4634 c->output << "#ifdef STP_NEED_SYMBOL_DATA\n";
4635
4636 // We write out a *sorted* symbol table, so the runtime doesn't have to sort them later.
4637 for (addrmap_t::iterator it = addrmap[secidx].begin(); it != addrmap[secidx].end(); it++)
4638 {
4639 if (it->first < extra_offset)
4640 continue; // skip symbols that occur before our chosen base address
4641
4642 c->output << " { 0x" << hex << it->first-extra_offset << dec
4643 << ", " << lex_cast_qstring (it->second) << " },\n";
4644 }
4645
4646 c->output << "#endif /* STP_NEED_SYMBOL_DATA */\n";
4647
4648 c->output << "};\n";
4649 }
4650
4651 c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n";
4652 for (unsigned secidx = 0; secidx < seclist.size(); secidx++)
4653 {
4654 c->output << "{\n"
4655 << ".name = " << lex_cast_qstring(seclist[secidx]) << ",\n"
4656 << ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n"
4657 << ".num_symbols = sizeof(_stp_module_" << stpmod_idx << "_symbols_" << secidx << ")/sizeof(struct _stp_symbol)\n"
4658 << "},\n";
4659 }
4660 c->output << "};\n";
4661
4662 c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
4663 c->output << ".name = " << lex_cast_qstring (modname) << ", \n";
4664 c->output << ".dwarf_module_base = 0x" << hex << base << dec << ", \n";
4665
4666 if (unwind != NULL)
4667 {
4668 c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
4669 c->output << ".unwind_data = "
4670 << "_stp_module_" << stpmod_idx << "_unwind_data, \n";
4671 c->output << ".unwind_data_len = " << len << ", \n";
4672 c->output << "#else\n";
4673 }
4674
4675 c->output << ".unwind_data = NULL,\n";
4676 c->output << ".unwind_data_len = 0,\n";
4677
4678 if (unwind != NULL)
4679 c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA*/\n";
4680
4681 c->output << ".unwind_hdr = NULL,\n";
4682 c->output << ".unwind_hdr_len = 0,\n";
4683 c->output << ".unwind_is_ehframe = 0,\n";
4684
4685 c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ",\n";
4686 c->output << ".num_sections = sizeof(_stp_module_" << stpmod_idx << "_sections)/"
4687 << "sizeof(struct _stp_section),\n";
4688
4689 if (build_id_len > 0) {
4690 c->output << ".build_id_bits = \"" ;
4691 for (int j=0; j<build_id_len;j++)
4692 c->output << "\\x" << hex
4693 << (unsigned short) *(build_id_bits+j) << dec;
4694
4695 c->output << "\",\n";
4696 c->output << ".build_id_len = " << build_id_len << ",\n";
4697
4698 /* XXX: kernel data boot-time relocation works differently from text.
4699 This hack disables relocation altogether, but that's not necessarily
4700 correct either. We may instead need a relocation basis different
4701 from _stext, such as __start_notes. */
4702 if (modname == "kernel")
4703 c->output << ".build_id_offset = 0x" << hex << build_id_vaddr
4704 << dec << ",\n";
4705 else
4706 c->output << ".build_id_offset = 0x" << hex
4707 << build_id_vaddr - base
4708 << dec << ",\n";
4709 } else
4710 c->output << ".build_id_len = 0,\n";
4711
4712 //initialize the note section representing unloaded
4713 c->output << ".notes_sect = 0,\n";
4714
4715 c->output << "};\n\n";
4716
4717 c->undone_unwindsym_modules.erase (modname);
4718
4719 return DWARF_CB_OK;
4720 }
4721
4722
4723 // Emit symbol table & unwind data, plus any calls needed to register
4724 // them with the runtime.
4725
4726 void
4727 emit_symbol_data (systemtap_session& s)
4728 {
4729 string symfile = "stap-symbols.h";
4730
4731 s.op->newline() << "#include " << lex_cast_qstring (symfile);
4732
4733 ofstream kallsyms_out ((s.tmpdir + "/" + symfile).c_str());
4734
4735 unwindsym_dump_context ctx = { s, kallsyms_out, 0, s.unwindsym_modules };
4736
4737 // XXX: copied from tapsets.cxx dwflpp::, sadly
4738 static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:build";
4739 static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH");
4740 static const char *debuginfo_path = (debuginfo_env_arr ?: debuginfo_path_arr);
4741
4742 // ---- step 1: process any kernel modules listed
4743 static const Dwfl_Callbacks kernel_callbacks =
4744 {
4745 dwfl_linux_kernel_find_elf,
4746 dwfl_standard_find_debuginfo,
4747 dwfl_offline_section_address,
4748 (char **) & debuginfo_path
4749 };
4750
4751 Dwfl *dwfl = dwfl_begin (&kernel_callbacks);
4752 if (!dwfl)
4753 throw semantic_error ("cannot open dwfl");
4754 dwfl_report_begin (dwfl);
4755
4756 // We have a problem with -r REVISION vs -r BUILDDIR here. If
4757 // we're running against a fedora/rhel style kernel-debuginfo
4758 // tree, s.kernel_build_tree is not the place where the unstripped
4759 // vmlinux will be installed. Rather, it's over yonder at
4760 // /usr/lib/debug/lib/modules/$REVISION/. It seems that there is
4761 // no way to set the dwfl_callback.debuginfo_path and always
4762 // passs the plain kernel_release here. So instead we have to
4763 // hard-code this magic here.
4764 string elfutils_kernel_path;
4765 if (s.kernel_build_tree == string("/lib/modules/" + s.kernel_release + "/build"))
4766 elfutils_kernel_path = s.kernel_release;
4767 else
4768 elfutils_kernel_path = s.kernel_build_tree;
4769
4770 int rc = dwfl_linux_kernel_report_offline (dwfl,
4771 elfutils_kernel_path.c_str(),
4772 NULL /* XXX: filtering callback */);
4773 dwfl_report_end (dwfl, NULL, NULL);
4774 if (rc == 0) // tolerate missing data; will warn user about it anyway
4775 {
4776 ptrdiff_t off = 0;
4777 do
4778 {
4779 if (pending_interrupts) return;
4780 off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0);
4781 }
4782 while (off > 0);
4783 dwfl_assert("dwfl_getmodules", off == 0);
4784 }
4785 dwfl_end(dwfl);
4786
4787
4788 // ---- step 2: process any user modules (files) listed
4789 // XXX: see dwflpp::setup_user.
4790 static const Dwfl_Callbacks user_callbacks =
4791 {
4792 NULL, /* dwfl_linux_kernel_find_elf, */
4793 dwfl_standard_find_debuginfo,
4794 dwfl_offline_section_address,
4795 (char **) & debuginfo_path
4796 };
4797
4798 for (std::set<std::string>::iterator it = s.unwindsym_modules.begin();
4799 it != s.unwindsym_modules.end();
4800 it++)
4801 {
4802 string modname = *it;
4803 assert (modname.length() != 0);
4804 if (modname[0] != '/') continue; // user-space files must be full paths
4805 Dwfl *dwfl = dwfl_begin (&user_callbacks);
4806 if (!dwfl)
4807 throw semantic_error ("cannot create dwfl for " + modname);
4808
4809 dwfl_report_begin (dwfl);
4810 Dwfl_Module* mod = dwfl_report_offline (dwfl, modname.c_str(), modname.c_str(), -1);
4811 dwfl_report_end (dwfl, NULL, NULL);
4812 if (mod != 0) // tolerate missing data; will warn below
4813 {
4814 ptrdiff_t off = 0;
4815 do
4816 {
4817 if (pending_interrupts) return;
4818 off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0);
4819 }
4820 while (off > 0);
4821 dwfl_assert("dwfl_getmodules", off == 0);
4822 }
4823 dwfl_end(dwfl);
4824 }
4825
4826
4827 // Print out a definition of the runtime's _stp_modules[] globals.
4828 kallsyms_out << "\n";
4829 kallsyms_out << "static struct _stp_module *_stp_modules [] = {\n";
4830 for (unsigned i=0; i<ctx.stp_module_index; i++)
4831 {
4832 kallsyms_out << "& _stp_module_" << i << ",\n";
4833 }
4834 kallsyms_out << "};\n";
4835 kallsyms_out << "static unsigned _stp_num_modules = " << ctx.stp_module_index << ";\n";
4836
4837 // Some nonexistent modules may have been identified with "-d". Note them.
4838 for (set<string>::iterator it = ctx.undone_unwindsym_modules.begin();
4839 it != ctx.undone_unwindsym_modules.end();
4840 it ++)
4841 {
4842 s.print_warning ("missing unwind/symbol data for module '" + (*it) + "'");
4843 }
4844 }
4845
4846
4847 int
4848 translate_pass (systemtap_session& s)
4849 {
4850 int rc = 0;
4851
4852 s.op = new translator_output (s.translated_source);
4853 c_unparser cup (& s);
4854 s.up = & cup;
4855
4856 try
4857 {
4858 // This is at the very top of the file.
4859
4860 s.op->newline() << "#ifndef MAXNESTING";
4861 s.op->newline() << "#define MAXNESTING 10";
4862 s.op->newline() << "#endif";
4863 s.op->newline() << "#ifndef MAXSTRINGLEN";
4864 s.op->newline() << "#define MAXSTRINGLEN 128";
4865 s.op->newline() << "#endif";
4866 s.op->newline() << "#ifndef MAXACTION";
4867 s.op->newline() << "#define MAXACTION 1000";
4868 s.op->newline() << "#endif";
4869 s.op->newline() << "#ifndef MAXACTION_INTERRUPTIBLE";
4870 s.op->newline() << "#define MAXACTION_INTERRUPTIBLE (MAXACTION * 10)";
4871 s.op->newline() << "#endif";
4872 s.op->newline() << "#ifndef MAXTRYLOCK";
4873 s.op->newline() << "#define MAXTRYLOCK MAXACTION";
4874 s.op->newline() << "#endif";
4875 s.op->newline() << "#ifndef TRYLOCKDELAY";
4876 s.op->newline() << "#define TRYLOCKDELAY 100";
4877 s.op->newline() << "#endif";
4878 s.op->newline() << "#ifndef MAXMAPENTRIES";
4879 s.op->newline() << "#define MAXMAPENTRIES 2048";
4880 s.op->newline() << "#endif";
4881 s.op->newline() << "#ifndef MAXERRORS";
4882 s.op->newline() << "#define MAXERRORS 0";
4883 s.op->newline() << "#endif";
4884 s.op->newline() << "#ifndef MAXSKIPPED";
4885 s.op->newline() << "#define MAXSKIPPED 100";
4886 s.op->newline() << "#endif";
4887 s.op->newline() << "#ifndef MINSTACKSPACE";
4888 s.op->newline() << "#define MINSTACKSPACE 1024";
4889 s.op->newline() << "#endif";
4890
4891 // Overload processing
4892 s.op->newline() << "#ifndef STP_OVERLOAD_INTERVAL";
4893 s.op->newline() << "#define STP_OVERLOAD_INTERVAL 1000000000LL";
4894 s.op->newline() << "#endif";
4895 s.op->newline() << "#ifndef STP_OVERLOAD_THRESHOLD";
4896 s.op->newline() << "#define STP_OVERLOAD_THRESHOLD 500000000LL";
4897 s.op->newline() << "#endif";
4898 // We allow the user to completely turn overload processing off
4899 // (as opposed to tuning it by overriding the values above) by
4900 // running: stap -DSTP_NO_OVERLOAD {other options}
4901 s.op->newline() << "#ifndef STP_NO_OVERLOAD";
4902 s.op->newline() << "#define STP_OVERLOAD";
4903 s.op->newline() << "#endif";
4904
4905 if (s.bulk_mode)
4906 s.op->newline() << "#define STP_BULKMODE";
4907
4908 if (s.timing)
4909 s.op->newline() << "#define STP_TIMING";
4910
4911 if (s.perfmon)
4912 s.op->newline() << "#define STP_PERFMON";
4913
4914 s.op->newline() << "#include \"runtime.h\"";
4915 s.op->newline() << "#include \"regs.c\"";
4916 s.op->newline() << "#include \"stack.c\"";
4917 s.op->newline() << "#include \"regs-ia64.c\"";
4918 s.op->newline() << "#include \"stat.c\"";
4919 s.op->newline() << "#include <linux/string.h>";
4920 s.op->newline() << "#include <linux/timer.h>";
4921 s.op->newline() << "#include <linux/sched.h>";
4922 s.op->newline() << "#include <linux/delay.h>";
4923 s.op->newline() << "#include <linux/profile.h>";
4924 s.op->newline() << "#include <linux/random.h>";
4925 // s.op->newline() << "#include <linux/utsrelease.h>"; // newer kernels only
4926 s.op->newline() << "#include <linux/vermagic.h>";
4927 s.op->newline() << "#include <linux/utsname.h>";
4928 s.op->newline() << "#include <linux/version.h>";
4929 // s.op->newline() << "#include <linux/compile.h>";
4930 s.op->newline() << "#include \"loc2c-runtime.h\" ";
4931
4932 // XXX: old 2.6 kernel hack
4933 s.op->newline() << "#ifndef read_trylock";
4934 s.op->newline() << "#define read_trylock(x) ({ read_lock(x); 1; })";
4935 s.op->newline() << "#endif";
4936
4937 s.up->emit_common_header (); // context etc.
4938
4939 for (unsigned i=0; i<s.embeds.size(); i++)
4940 {
4941 s.op->newline() << s.embeds[i]->code << "\n";
4942 }
4943
4944 s.op->newline() << "static struct {";
4945 s.op->indent(1);
4946 for (unsigned i=0; i<s.globals.size(); i++)
4947 {
4948 s.up->emit_global (s.globals[i]);
4949 }
4950 s.op->newline(-1) << "} global = {";
4951 s.op->newline(1);
4952 for (unsigned i=0; i<s.globals.size(); i++)
4953 {
4954 if (pending_interrupts) return 1;
4955 s.up->emit_global_init (s.globals[i]);
4956 }
4957 s.op->newline(-1) << "};";
4958 s.op->assert_0_indent();
4959
4960 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
4961 {
4962 if (pending_interrupts) return 1;
4963 s.op->newline();
4964 s.up->emit_functionsig (it->second);
4965 }
4966 s.op->assert_0_indent();
4967
4968 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
4969 {
4970 if (pending_interrupts) return 1;
4971 s.op->newline();
4972 s.up->emit_function (it->second);
4973 }
4974 s.op->assert_0_indent();
4975
4976 // Run a varuse_collecting_visitor over probes that need global
4977 // variable locks. We'll use this information later in
4978 // emit_locks()/emit_unlocks().
4979 for (unsigned i=0; i<s.probes.size(); i++)
4980 {
4981 if (pending_interrupts) return 1;
4982 if (s.probes[i]->needs_global_locks())
4983 s.probes[i]->body->visit (&cup.vcv_needs_global_locks);
4984 }
4985 s.op->assert_0_indent();
4986
4987 for (unsigned i=0; i<s.probes.size(); i++)
4988 {
4989 if (pending_interrupts) return 1;
4990 s.up->emit_probe (s.probes[i]);
4991 }
4992 s.op->assert_0_indent();
4993
4994 s.op->newline();
4995 s.up->emit_module_init ();
4996 s.op->assert_0_indent();
4997 s.op->newline();
4998 s.up->emit_module_exit ();
4999 s.op->assert_0_indent();
5000 s.op->newline();
5001
5002 // XXX impedance mismatch
5003 s.op->newline() << "static int probe_start () {";
5004 s.op->newline(1) << "return systemtap_module_init () ? -1 : 0;";
5005 s.op->newline(-1) << "}";
5006 s.op->newline();
5007 s.op->newline() << "static void probe_exit () {";
5008 s.op->newline(1) << "systemtap_module_exit ();";
5009 s.op->newline(-1) << "}";
5010 s.op->assert_0_indent();
5011
5012 for (unsigned i=0; i<s.globals.size(); i++)
5013 {
5014 s.op->newline();
5015 s.up->emit_global_param (s.globals[i]);
5016 }
5017 s.op->assert_0_indent();
5018
5019 emit_symbol_data (s);
5020
5021 s.op->newline() << "MODULE_DESCRIPTION(\"systemtap-generated probe\");";
5022 s.op->newline() << "MODULE_LICENSE(\"GPL\");";
5023 s.op->assert_0_indent();
5024 }
5025 catch (const semantic_error& e)
5026 {
5027 s.print_error (e);
5028 }
5029
5030 s.op->line() << "\n";
5031
5032 delete s.op;
5033 s.op = 0;
5034 s.up = 0;
5035
5036 return rc + s.num_errors();
5037 }
5038
5039 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.306703 seconds and 6 git commands to generate.