diff options
author | graydon <graydon> | 2005-07-13 04:47:54 +0000 |
---|---|---|
committer | graydon <graydon> | 2005-07-13 04:47:54 +0000 |
commit | f8220a7b945a3be7975fb2610ca1c79119594534 (patch) | |
tree | d733adba9033184c8250971ce096e51b3dade156 | |
parent | 6f0257ecf703373555ef06044cc25c8083859616 (diff) | |
download | systemtap-steved-f8220a7b945a3be7975fb2610ca1c79119594534.tar.gz systemtap-steved-f8220a7b945a3be7975fb2610ca1c79119594534.tar.xz systemtap-steved-f8220a7b945a3be7975fb2610ca1c79119594534.zip |
2005-07-12 Graydon Hoare <graydon@redhat.com>
* elaborate.cxx
(semantic_pass_symbols): Only enter body if non-null.
(semantic_pass_types): Likewise.
(semantic_pass): Pass session to register_standard_tapsets.
* translate.cxx
(builtin_collector): New struct.
(hookup_builtins): New function.
(translate_pass): Only translate functions with bodies.
(c_unparser::emit_common_header): Likewise, and call hookup_builtins.
* tapsets.hh (builtin_function): New class.
(register_standard_tapsets): Change parameter to session.
* tapsets.cc (bultin_function::*): Implement class.
(register_standard_tapsets): Register printk, log, warn.
* testsuite/transok/six.stp: New test.
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | elaborate.cxx | 32 | ||||
-rw-r--r-- | runtime/ChangeLog | 4 | ||||
-rw-r--r-- | runtime/builtin_functions.h | 60 | ||||
-rw-r--r-- | tapsets.cxx | 57 | ||||
-rw-r--r-- | tapsets.h | 20 | ||||
-rwxr-xr-x | testsuite/transok/six.stp | 8 | ||||
-rw-r--r-- | translate.cxx | 56 |
8 files changed, 233 insertions, 21 deletions
@@ -1,3 +1,20 @@ +2005-07-12 Graydon Hoare <graydon@redhat.com> + + * elaborate.cxx + (semantic_pass_symbols): Only enter body if non-null. + (semantic_pass_types): Likewise. + (semantic_pass): Pass session to register_standard_tapsets. + * translate.cxx + (builtin_collector): New struct. + (hookup_builtins): New function. + (translate_pass): Only translate functions with bodies. + (c_unparser::emit_common_header): Likewise, and call hookup_builtins. + * tapsets.hh (builtin_function): New class. + (register_standard_tapsets): Change parameter to session. + * tapsets.cc (bultin_function::*): Implement class. + (register_standard_tapsets): Register printk, log, warn. + * testsuite/transok/six.stp: New test. + 2005-07-12 Frank Ch. Eigler <fche@redhat.com> * buildrun.cxx (compile_pass): Make non-verbose mode quieter. diff --git a/elaborate.cxx b/elaborate.cxx index e38cef51..5cac937b 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -420,9 +420,12 @@ semantic_pass_symbols (systemtap_session& s) try { - sym.current_function = fd; - sym.current_probe = 0; - fd->body->visit (& sym); + if (fd->body) + { + sym.current_function = fd; + sym.current_probe = 0; + fd->body->visit (& sym); + } } catch (const semantic_error& e) { @@ -478,7 +481,7 @@ int semantic_pass (systemtap_session& s) { s.register_library_aliases(); - register_standard_tapsets(s.pattern_root); + register_standard_tapsets(s); int rc = semantic_pass_symbols (s); if (rc == 0) rc = semantic_pass_types (s); @@ -794,15 +797,18 @@ semantic_pass_types (systemtap_session& s) for (unsigned j=0; j<s.functions.size(); j++) { functiondecl* fn = s.functions[j]; - ti.current_function = fn; - ti.t = pe_unknown; - fn->body->visit (& ti); - // NB: we don't have to assert a known type for - // functions here, to permit a "void" function. - // The translator phase will omit the "retvalue". - // - // if (fn->type == pe_unknown) - // ti.unresolved (fn->tok); + if (fn->body) + { + ti.current_function = fn; + ti.t = pe_unknown; + fn->body->visit (& ti); + // NB: we don't have to assert a known type for + // functions here, to permit a "void" function. + // The translator phase will omit the "retvalue". + // + // if (fn->type == pe_unknown) + // ti.unresolved (fn->tok); + } } for (unsigned j=0; j<s.probes.size(); j++) diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 74a5808e..3be80bf4 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,7 @@ +2005-07-11 Graydon Hoare <graydon@redhat.com> + + * builtin_functions.h: New file. + 2005-07-10 Martin Hunt <hunt@redhat.com> * runtime.h (init_module): Fix return value. diff --git a/runtime/builtin_functions.h b/runtime/builtin_functions.h new file mode 100644 index 00000000..13be00fb --- /dev/null +++ b/runtime/builtin_functions.h @@ -0,0 +1,60 @@ +#ifndef _BUILTIN_FUNCTIONS_ +#define _BUILTIN_FUNCTIONS_ + +/* Builtin function definitions. + * Copyright (C) 2005 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +/* + * This file contains definitions for "builtin functions" which are + * registered in the systemtap translator, but given no definition. + * The translator emits calls to builtins exactly the same way it + * emits calls to functions written in the systemtap language; the + * only difference is that this file (or a C tapset) must supply the + * definition. + * + * Every builtin function "foo" called by a systemtap script is + * translated to a C call to a C function named "function_foo". This + * is the function you must provide in this file. In addition, the + * translator emits a + * + * #define _BUILTIN_FUNCTION_foo_ + * + * symbol for each such function called, which you can use to elide + * function definitions which are not used by a given systemtap + * script. + */ + +#ifdef _BUILTIN_FUNCTION_printk_ +static void +function_printk (struct context *c) +{ + printk (KERN_INFO, c->locals[c->nesting].function_printk.message); +} +#endif /* _BUILTIN_FUNCTION_printk_ */ + + +#ifdef _BUILTIN_FUNCTION_log_ +static void +function_log (struct context *c) +{ + _stp_log (c->locals[c->nesting].function_log.message); +} +#endif /* _BUILTIN_FUNCTION_log_ */ + + +#ifdef _BUILTIN_FUNCTION_warn_ +static void +function_warn (struct context *c) +{ + _stp_warn (c->locals[c->nesting].function_warn.message); +} +#endif /* _BUILTIN_FUNCTION_warn_ */ + + +#endif /* _BUILTIN_FUNCTIONS_ */ diff --git a/tapsets.cxx b/tapsets.cxx index 3dbbfa81..97c538ee 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1166,19 +1166,68 @@ dwarf_builder::build(systemtap_session & sess, #endif /* HAVE_ELFUTILS_LIBDWFL_H */ +// ------------------------------------------------------------------------ +// Built-in function support class +// ------------------------------------------------------------------------ + +token * +builtin_function::id(string const & name) +{ + token *t = new token; + t->type = tok_identifier; + t->content = name; + t->location.file = "<builtin>"; + return t; +} + +builtin_function::builtin_function(exp_type ty, string const & name) +{ + f = new functiondecl; + f->tok = id(name); + f->name = name; + f->type = ty; + f->body = NULL; +} + +builtin_function & +builtin_function::arg(exp_type e, string const & name) +{ + vardecl *arg = new vardecl; + arg->name = name; + arg->tok = id(name); + arg->type = e; + f->formal_args.push_back(arg); + return *this; +} + +void +builtin_function::bind(systemtap_session & s) +{ + for (unsigned i = 0; i < s.functions.size(); ++i) + { + if (s.functions[i]->name == f->name) + throw semantic_error("builtin function " + f->name + " registered twice"); + } + s.functions.push_back(f); +} // ------------------------------------------------------------------------ // Standard tapset registry. // ------------------------------------------------------------------------ void -register_standard_tapsets(match_node * root) +register_standard_tapsets(systemtap_session & s) { // Rudimentary binders for begin and end targets - root->bind("begin")->bind(new be_builder(true)); - root->bind("end")->bind(new be_builder(false)); + s.pattern_root->bind("begin")->bind(new be_builder(true)); + s.pattern_root->bind("end")->bind(new be_builder(false)); #ifdef HAVE_ELFUTILS_LIBDWFL_H - dwarf_derived_probe::register_patterns(root); + dwarf_derived_probe::register_patterns(s.pattern_root); #endif /* HAVE_ELFUTILS_LIBDWFL_H */ + + // Some standard builtins + builtin_function(pe_long, "printk").arg(pe_string, "message").bind(s); + builtin_function(pe_long, "log").arg(pe_string, "message").bind(s); + builtin_function(pe_long, "warn").arg(pe_string, "message").bind(s); } @@ -13,8 +13,26 @@ #include "staptree.h" #include "elaborate.h" + +// Helper class for describing builtin functions. Calls to builtins +// are typechecked and emitted, but the builtin definitions are *not* +// emitted by the translator (in fact, they have no definitions in +// systemtap language); they are assumed to exist outside the +// translator, in the runtime library. + +class +builtin_function +{ + functiondecl *f; + token *id(std::string const & name); + public: + builtin_function(exp_type e, std::string const & name); + builtin_function & arg(exp_type e, std::string const & name); + void bind(systemtap_session & sess); +}; + void -register_standard_tapsets(match_node * root); +register_standard_tapsets(systemtap_session & sess); #endif // TAPSETS_H diff --git a/testsuite/transok/six.stp b/testsuite/transok/six.stp new file mode 100755 index 00000000..8684107e --- /dev/null +++ b/testsuite/transok/six.stp @@ -0,0 +1,8 @@ +#! stap -p3 + +probe begin +{ + printk("kernel time") + log("hello there") + warn("this is a builtin") +} diff --git a/translate.cxx b/translate.cxx index 125c5b2b..52d370f8 100644 --- a/translate.cxx +++ b/translate.cxx @@ -11,7 +11,9 @@ #include "elaborate.h" #include "translate.h" #include <iostream> +#include <set> #include <sstream> +#include <string> using namespace std; @@ -173,6 +175,50 @@ struct c_tmpcounter: public traversing_visitor }; +struct builtin_collector: public traversing_visitor +{ + set<string> called_builtins; + void visit_functioncall (functioncall* e); +}; + +void +builtin_collector::visit_functioncall(functioncall* e) +{ + if (e->referent && !e->referent->body) + called_builtins.insert(e->referent->name); +} + +void +hookup_builtins(systemtap_session *session, + translator_output *o) +{ + builtin_collector bc; + for (unsigned i=0; i<session->functions.size(); i++) + { + functiondecl* fd = session->functions[i]; + if (fd->body) + fd->body->visit(&bc); + } + for (unsigned i=0; i<session->probes.size(); i++) + { + derived_probe* dp = session->probes[i]; + dp->body->visit(&bc); + } + + for (set<string>::const_iterator i = bc.called_builtins.begin(); + i != bc.called_builtins.end(); ++i) + { + o->newline() << "#define _BUILTIN_FUNCTION_" << *i << "_"; + } + + o->newline() << "#include \"builtin_functions.h\""; + + for (set<string>::const_iterator i = bc.called_builtins.begin(); + i != bc.called_builtins.end(); ++i) + { + o->newline() << "#undef _BUILTIN_FUNCTION_" << *i << "_"; + } +} void c_unparser::emit_common_header () @@ -234,7 +280,8 @@ c_unparser::emit_common_header () << c_varname (v->name) << ";"; } c_tmpcounter ct (this); - fd->body->visit (& ct); + if (fd->body) + fd->body->visit (& ct); if (fd->type == pe_unknown) o->newline() << "/* no return value */"; else @@ -245,6 +292,7 @@ c_unparser::emit_common_header () } o->newline(-1) << "} locals [MAXNESTING];"; o->newline(-1) << "} contexts [MAXCONCURRENCY];" << endl; + hookup_builtins(session, o); } @@ -1452,11 +1500,13 @@ translate_pass (systemtap_session& s) s.op->newline() << "/* function signatures */"; for (unsigned i=0; i<s.functions.size(); i++) - s.up->emit_functionsig (s.functions[i]); + if (s.functions[i]->body) + s.up->emit_functionsig (s.functions[i]); s.op->newline() << "/* functions */"; for (unsigned i=0; i<s.functions.size(); i++) - s.up->emit_function (s.functions[i]); + if (s.functions[i]->body) + s.up->emit_function (s.functions[i]); s.op->newline() << "/* probes */"; for (unsigned i=0; i<s.probes.size(); i++) |