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