summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraydon <graydon>2005-07-13 04:47:54 +0000
committergraydon <graydon>2005-07-13 04:47:54 +0000
commitf8220a7b945a3be7975fb2610ca1c79119594534 (patch)
treed733adba9033184c8250971ce096e51b3dade156
parent6f0257ecf703373555ef06044cc25c8083859616 (diff)
downloadsystemtap-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--ChangeLog17
-rw-r--r--elaborate.cxx32
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/builtin_functions.h60
-rw-r--r--tapsets.cxx57
-rw-r--r--tapsets.h20
-rwxr-xr-xtestsuite/transok/six.stp8
-rw-r--r--translate.cxx56
8 files changed, 233 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index e44d5dbb..4ccbc9a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
}
diff --git a/tapsets.h b/tapsets.h
index 774fa59b..e2f5a8db 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -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++)