summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraydon <graydon>2005-10-01 00:10:52 +0000
committergraydon <graydon>2005-10-01 00:10:52 +0000
commite57b735af836fbadd0a92a25b9bd0646eff3860a (patch)
treea2089c3690a0266d3906f02a280355ff3fd5e3ab
parent325be37a7bbb513359c77ebe5cee1cfc143ec0c1 (diff)
downloadsystemtap-steved-e57b735af836fbadd0a92a25b9bd0646eff3860a.tar.gz
systemtap-steved-e57b735af836fbadd0a92a25b9bd0646eff3860a.tar.xz
systemtap-steved-e57b735af836fbadd0a92a25b9bd0646eff3860a.zip
[ChangeLog]
2005-09-30 Graydon Hoare <graydon@redhat.com> PR 1131. * tapsets.cxx (dwflpp::find_variable_and_frame_base) (dwflpp::translate_components) (dwflpp::resolve_unqualified_inner_typedie) (dwflpp::translate_final_fetch_or_store): New functions. (dwflpp::literal_stmt_for_local): Factor a bit. (variable_flavour_calculating_visitor::visit_target_symbol): Don't fault on lvalue, just collect an extra char. (var_expanding_copy_visitor::target_symbol_setter_functioncalls): New member. (var_expanding_copy_visitor::visit_assignment): New method. (var_expanding_copy_visitor::visit_target_symbol): Permit lvalues. [runtime/ChangeLog] 2005-09-30 Graydon Hoare <graydon@redhat.com> * loc2c-runtime.h (_put_user_asm): Fix bracket-matching.
-rw-r--r--ChangeLog15
-rw-r--r--runtime/ChangeLog4
-rw-r--r--runtime/loc2c-runtime.h24
-rw-r--r--tapsets.cxx380
4 files changed, 291 insertions, 132 deletions
diff --git a/ChangeLog b/ChangeLog
index a08ced87..5834b53d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2005-09-30 Graydon Hoare <graydon@redhat.com>
+
+ PR 1131.
+ * tapsets.cxx (dwflpp::find_variable_and_frame_base)
+ (dwflpp::translate_components)
+ (dwflpp::resolve_unqualified_inner_typedie)
+ (dwflpp::translate_final_fetch_or_store): New functions.
+ (dwflpp::literal_stmt_for_local): Factor a bit.
+ (variable_flavour_calculating_visitor::visit_target_symbol):
+ Don't fault on lvalue, just collect an extra char.
+ (var_expanding_copy_visitor::target_symbol_setter_functioncalls):
+ New member.
+ (var_expanding_copy_visitor::visit_assignment): New method.
+ (var_expanding_copy_visitor::visit_target_symbol): Permit lvalues.
+
2005-09-30 Frank Ch. Eigler <fche@elastic.org>
* tapset/system_calls.stp (*_str): Simplified boolean test logic
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index ea2d22b0..548f908e 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,7 @@
+2005-09-30 Graydon Hoare <graydon@redhat.com>
+
+ * loc2c-runtime.h (_put_user_asm): Fix bracket-matching.
+
2005-09-23 Martin Hunt <hunt@redhat.com>
* map.c (_stp_map_sortn): Call _stp_map_sort()
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index e25e0531..ed174db3 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -103,10 +103,10 @@
int _bad = 0; \
switch (size) \
{ \
- case 1: __put_user_asm(((u8)(value),addr,_bad,"b","b","iq",1); break; \
- case 2: __put_user_asm(((u16)(value),addr,_bad,"w","w","ir",1); break; \
- case 4: __put_user_asm(((u32)(value),addr,_bad,"l","k","ir",1); break; \
- case 8: __put_user_asm(((u64)(value),addr,_bad,"q","","ir",1); break; \
+ case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
+ case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break; \
+ case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break; \
+ case 8: __put_user_asm(((u64)(value)),addr,_bad,"q","","ir",1); break; \
default: __put_user_bad(); \
} \
if (_bad) \
@@ -137,10 +137,10 @@
int _bad = 0; \
switch (size) \
{ \
- case 1: __put_user_asm(((u8)(value),addr,_bad,"stb",1); break; \
- case 2: __put_user_asm(((u16)(value),addr,_bad,"sth",1); break; \
- case 4: __put_user_asm(((u32)(value),addr,_bad,"stw",1); break; \
- case 8: __put_user_asm(((u64)(value),addr,_bad,"std",1); break; \
+ case 1: __put_user_asm(((u8)(value)),addr,_bad,"stb",1); break; \
+ case 2: __put_user_asm(((u16)(value)),addr,_bad,"sth",1); break; \
+ case 4: __put_user_asm(((u32)(value)),addr,_bad,"stw",1); break; \
+ case 8: __put_user_asm(((u64)(value)),addr,_bad,"std",1); break; \
default: __put_user_bad(); \
} \
if (_bad) \
@@ -171,10 +171,10 @@
int _bad = 0; \
switch (size) \
{ \
- case 1: __put_user_asm(((u8)(value),addr,_bad,"stb"); break; \
- case 2: __put_user_asm(((u16)(value),addr,_bad,"sth"); break; \
- case 4: __put_user_asm(((u32)(value),addr,_bad,"stw"); break; \
- case 8: __put_user_asm2(((u64)(value),addr,_bad); break; \
+ case 1: __put_user_asm(((u8)(value)),addr,_bad,"stb"); break; \
+ case 2: __put_user_asm(((u16)(value)),addr,_bad,"sth"); break; \
+ case 4: __put_user_asm(((u32)(value)),addr,_bad,"stw"); break; \
+ case 8: __put_user_asm2(((u64)(value)),addr,_bad); break; \
default: __put_user_bad(); \
} \
if (_bad) \
diff --git a/tapsets.cxx b/tapsets.cxx
index fae73e56..05839cfc 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -863,18 +863,18 @@ dwflpp
NULL, NULL, NULL, NULL));
}
- string literal_stmt_for_local(Dwarf_Die *scope_die,
- Dwarf_Addr pc,
+ Dwarf_Attribute *
+ find_variable_and_frame_base (Dwarf_Die *scope_die,
+ Dwarf_Addr pc,
string const & local,
- vector<pair<target_symbol::component_type,
- std::string> > const & components,
- exp_type & ty)
+ Dwarf_Die *vardie,
+ Dwarf_Attribute *fb_attr_mem)
{
- assert (cu);
-
Dwarf_Die *scopes;
- Dwarf_Die vardie;
int nscopes = 0;
+ Dwarf_Attribute *fb_attr = NULL;
+
+ assert (cu);
if (scope_die)
nscopes = dwarf_getscopes_die (scope_die, &scopes);
@@ -891,14 +891,13 @@ dwflpp
int declaring_scope = dwarf_getscopevar (scopes, nscopes,
local.c_str(),
0, NULL, 0, 0,
- &vardie);
+ vardie);
if (declaring_scope < 0)
{
throw semantic_error ("unable to find local '" + local + "'"
+ " near pc " + lex_cast_hex<string>(pc));
}
- Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
for (int inner = 0; inner < nscopes; ++inner)
{
switch (dwarf_tag (&scopes[inner]))
@@ -911,48 +910,29 @@ dwflpp
if (inner >= declaring_scope)
fb_attr = dwarf_attr_integrate (&scopes[inner],
DW_AT_frame_base,
- &fb_attr_mem);
+ fb_attr_mem);
break;
}
}
+ return fb_attr;
+ }
- if (sess.verbose)
- clog << "finding location for local '" << local
- << "' near address " << hex << pc
- << ", module bias " << module_bias << dec
- << endl;
-
- Dwarf_Attribute attr_mem;
- if (dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL)
- {
- throw semantic_error("failed to retrieve location "
- "attribute for local '" + local
- + "' (dieoffset: "
- + lex_cast_hex<string>(dwarf_dieoffset (&vardie))
- + ")");
- }
-
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-
- struct obstack pool;
- obstack_init (&pool);
- struct location *tail = NULL;
- struct location *head = c_translate_location (&pool, &loc2c_error, this,
- &loc2c_emit_address,
- 1, module_bias,
- &attr_mem, pc,
- &tail, fb_attr);
- if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
- throw semantic_error("failed to retrieve type "
- "attribute for local '" + local + "'");
-
- Dwarf_Die die_mem, *die = &vardie;
+ Dwarf_Die *
+ translate_components(struct obstack *pool,
+ struct location **tail,
+ Dwarf_Addr pc,
+ vector<pair<target_symbol::component_type,
+ std::string> > const & components,
+ Dwarf_Die *vardie,
+ Dwarf_Die *die_mem,
+ Dwarf_Attribute *attr_mem)
+ {
+ Dwarf_Die *die = vardie;
unsigned i = 0;
while (i < components.size())
{
- die = dwarf_formref_die (&attr_mem, &die_mem);
+ die = dwarf_formref_die (attr_mem, die_mem);
const int typetag = dwarf_tag (die);
switch (typetag)
{
@@ -966,14 +946,14 @@ dwflpp
if (components[i].first == target_symbol::comp_literal_array_index)
goto subscript;
- c_translate_pointer (&pool, 1, module_bias, die, &tail);
+ c_translate_pointer (pool, 1, module_bias, die, tail);
break;
case DW_TAG_array_type:
if (components[i].first == target_symbol::comp_literal_array_index)
{
subscript:
- c_translate_array (&pool, 1, module_bias, die, &tail,
+ c_translate_array (pool, 1, module_bias, die, tail,
NULL, lex_cast<Dwarf_Word>(components[i].second));
++i;
}
@@ -985,7 +965,7 @@ dwflpp
case DW_TAG_structure_type:
case DW_TAG_union_type:
- switch (dwarf_child (die, &die_mem))
+ switch (dwarf_child (die, die_mem))
{
case 1: /* No children. */
throw semantic_error ("empty struct "
@@ -1005,11 +985,11 @@ dwflpp
while (dwarf_tag (die) != DW_TAG_member
|| ({ const char *member = dwarf_diename_integrate (die);
member == NULL || string(member) != components[i].second; }))
- if (dwarf_siblingof (die, &die_mem) != 0)
+ if (dwarf_siblingof (die, die_mem) != 0)
throw semantic_error ("field name " + components[i].second + " not found");
if (dwarf_attr_integrate (die, DW_AT_data_member_location,
- &attr_mem) == NULL)
+ attr_mem) == NULL)
{
/* Union members don't usually have a location,
but just use the containing union's location. */
@@ -1019,9 +999,9 @@ dwflpp
+ " :" + string(dwarf_errmsg (-1)));
}
else
- c_translate_location (&pool, NULL, NULL, NULL, 1,
- module_bias, &attr_mem, pc,
- &tail, NULL);
+ c_translate_location (pool, NULL, NULL, NULL, 1,
+ module_bias, attr_mem, pc,
+ tail, NULL);
++i;
break;
@@ -1043,40 +1023,61 @@ dwflpp
}
/* Now iterate on the type in DIE's attribute. */
- if (dwarf_attr_integrate (die, DW_AT_type, &attr_mem) == NULL)
+ if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL)
throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
}
+ return die;
+ }
- /* Fetch the type DIE corresponding to the final location to be accessed.
- It must be a base type or a typedef for one. */
- Dwarf_Die typedie_mem;
+ Dwarf_Die *
+ resolve_unqualified_inner_typedie (Dwarf_Die *typedie_mem,
+ Dwarf_Attribute *attr_mem)
+ {
+ ;
Dwarf_Die *typedie;
- int typetag;
+ int typetag = 0;
while (1)
- {
- typedie = dwarf_formref_die (&attr_mem, &typedie_mem);
+ {
+ typedie = dwarf_formref_die (attr_mem, typedie_mem);
if (typedie == NULL)
- throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
+ throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)));
typetag = dwarf_tag (typedie);
if (typetag != DW_TAG_typedef &&
typetag != DW_TAG_const_type &&
typetag != DW_TAG_volatile_type)
break;
- if (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem) == NULL)
- throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)));
+ if (dwarf_attr_integrate (typedie, DW_AT_type, attr_mem) == NULL)
+ throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)));
}
+ return typedie;
+ }
- // If we have a base type, we will fetch it into pe_long.
- //
- // If we have a pointer to non-char, we will cast it to uintptr_t, and fetch
- // into pe_long.
- //
- // If we have a pointer to char, we will fetch into pe_string, using
- // deref_string() over in loc2c-runtime.h
+ void
+ translate_final_fetch_or_store (struct obstack *pool,
+ struct location **tail,
+ Dwarf_Addr module_bias,
+ Dwarf_Die *die,
+ Dwarf_Attribute *attr_mem,
+ bool lvalue,
+ string & prelude,
+ string & postlude,
+ exp_type & ty)
+ {
+ /* First boil away any qualifiers associated with the type DIE of
+ the final location to be accessed. */
- string prelude, postlude;
+ Dwarf_Die typedie_mem;
+ Dwarf_Die *typedie;
+ int typetag;
+
+ typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem);
+ typetag = dwarf_tag (typedie);
+
+ /* Then switch behavior depending on the type of fetch/store we
+ want, and the type and pointer-ness of the final location. */
+
switch (typetag)
{
default:
@@ -1087,43 +1088,35 @@ dwflpp
case DW_TAG_enumeration_type:
case DW_TAG_base_type:
ty = pe_long;
- c_translate_fetch (&pool, 1, module_bias, die, typedie, &tail,
- "THIS->__retvalue");
+ if (lvalue)
+ c_translate_store (pool, 1, module_bias, die, typedie, tail,
+ "THIS->value");
+ else
+ c_translate_fetch (pool, 1, module_bias, die, typedie, tail,
+ "THIS->__retvalue");
break;
case DW_TAG_array_type:
case DW_TAG_pointer_type:
+
+ if (lvalue)
+ throw semantic_error ("cannot store into target pointer value");
+
{
Dwarf_Die pointee_typedie_mem;
Dwarf_Die *pointee_typedie;
Dwarf_Word pointee_encoding;
Dwarf_Word pointee_byte_size = 0;
- int pointee_typetag;
- if (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem) == NULL)
+ if (dwarf_attr_integrate (typedie, DW_AT_type, attr_mem) == NULL)
throw semantic_error ("cannot get type of pointer: " + string(dwarf_errmsg (-1)));
-
- while (1)
- {
- pointee_typedie = dwarf_formref_die (&attr_mem, &pointee_typedie_mem);
-
- if (pointee_typedie == NULL)
- throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)));
-
- pointee_typetag = dwarf_tag (pointee_typedie);
-
- if (pointee_typetag != DW_TAG_typedef &&
- pointee_typetag != DW_TAG_const_type &&
- pointee_typetag != DW_TAG_volatile_type)
- break;
- if (dwarf_attr_integrate (pointee_typedie, DW_AT_type, &attr_mem) == NULL)
- throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)));
- }
- if (dwarf_attr_integrate (pointee_typedie, DW_AT_byte_size, &attr_mem))
- dwarf_formudata (&attr_mem, &pointee_byte_size);
+ pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem);
+
+ if (dwarf_attr_integrate (pointee_typedie, DW_AT_byte_size, attr_mem))
+ dwarf_formudata (attr_mem, &pointee_byte_size);
- dwarf_formudata (dwarf_attr_integrate (pointee_typedie, DW_AT_encoding, &attr_mem),
+ dwarf_formudata (dwarf_attr_integrate (pointee_typedie, DW_AT_encoding, attr_mem),
&pointee_encoding);
// We have the pointer: cast it to an integral type via &(*(...))
@@ -1135,14 +1128,86 @@ dwflpp
ty = pe_long;
if (typetag == DW_TAG_array_type)
- c_translate_array (&pool, 1, module_bias, typedie, &tail, NULL, 0);
+ c_translate_array (pool, 1, module_bias, typedie, tail, NULL, 0);
else
- c_translate_pointer (&pool, 1, module_bias, typedie, &tail);
- c_translate_addressof (&pool, 1, module_bias, NULL, pointee_typedie, &tail,
+ c_translate_pointer (pool, 1, module_bias, typedie, tail);
+ c_translate_addressof (pool, 1, module_bias, NULL, pointee_typedie, tail,
"THIS->__retvalue");
}
break;
}
+ }
+
+
+ string
+ literal_stmt_for_local (Dwarf_Die *scope_die,
+ Dwarf_Addr pc,
+ string const & local,
+ vector<pair<target_symbol::component_type,
+ std::string> > const & components,
+ bool lvalue,
+ exp_type & ty)
+ {
+ Dwarf_Die vardie;
+ Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
+
+ fb_attr = find_variable_and_frame_base (scope_die, pc, local,
+ &vardie, &fb_attr_mem);
+
+ if (sess.verbose)
+ clog << "finding location for local '" << local
+ << "' near address " << hex << pc
+ << ", module bias " << module_bias << dec
+ << endl;
+
+ Dwarf_Attribute attr_mem;
+ if (dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL)
+ {
+ throw semantic_error("failed to retrieve location "
+ "attribute for local '" + local
+ + "' (dieoffset: "
+ + lex_cast_hex<string>(dwarf_dieoffset (&vardie))
+ + ")");
+ }
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+ struct obstack pool;
+ obstack_init (&pool);
+ struct location *tail = NULL;
+
+ /* Given $foo->bar->baz[NN], translate the location of foo. */
+
+ struct location *head = c_translate_location (&pool, &loc2c_error, this,
+ &loc2c_emit_address,
+ 1, module_bias,
+ &attr_mem, pc,
+ &tail, fb_attr);
+
+ if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL)
+ throw semantic_error("failed to retrieve type "
+ "attribute for local '" + local + "'");
+
+
+ /* Translate the ->bar->baz[NN] parts. */
+
+ Dwarf_Die die_mem, *die = NULL;
+ die = translate_components (&pool, &tail, pc, components,
+ &vardie, &die_mem, &attr_mem);
+
+ /* Translate the assignment part, either
+ x = $foo->bar->baz[NN]
+ or
+ $foo->bar->baz[NN] = x
+ */
+
+ string prelude, postlude;
+ translate_final_fetch_or_store (&pool, &tail, module_bias,
+ die, &attr_mem, lvalue,
+ prelude, postlude, ty);
+
+ /* Write the translation to a string. */
size_t bufsz = 1024;
char *buf = static_cast<char*>(malloc(bufsz));
@@ -1500,20 +1565,16 @@ target_variable_flavour_calculating_visitor::visit_target_symbol (target_symbol
{
assert(e->base_name.size() > 0 && e->base_name[0] == '$');
- if (is_active_lvalue(e))
- {
- q.sess.print_error (semantic_error("read-only special variable "
- + e->base_name + " used as lvalue",
- e->tok));
- }
-
try
{
+ bool lvalue = is_active_lvalue(e);
+ flavour += lvalue ? 'w' : 'r';
exp_type ty;
string expr = q.dw.literal_stmt_for_local(scope_die,
addr,
e->base_name.substr(1),
e->components,
+ lvalue,
ty);
switch (ty)
{
@@ -2043,6 +2104,7 @@ var_expanding_copy_visitor
: public deep_copy_visitor
{
static unsigned tick;
+ stack<functioncall**> target_symbol_setter_functioncalls;
dwarf_query & q;
Dwarf_Die *scope_die;
@@ -2051,38 +2113,89 @@ var_expanding_copy_visitor
var_expanding_copy_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a)
: q(q), scope_die(sd), addr(a)
{}
+ void visit_assignment (assignment* e);
void visit_target_symbol (target_symbol* e);
};
unsigned var_expanding_copy_visitor::tick = 0;
-
void
-var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
+var_expanding_copy_visitor::visit_assignment (assignment* e)
{
- assert(e->base_name.size() > 0 && e->base_name[0] == '$');
+ // Our job would normally be to require() the left and right sides
+ // into a new assignment. What we're doing is slightly trickier:
+ // we're pushing a functioncall** onto a stack, and if our left
+ // child sets the functioncall* for that value, we're going to
+ // assume our left child was a target symbol -- transformed into a
+ // set_target_foo(value) call, and it wants to take our right child
+ // as the argument "value".
+ //
+ // This is why some people claim that languages with
+ // constructor-decomposing case expressions have a leg up on
+ // visitors.
+
+ functioncall *fcall = NULL;
+ expression *new_left, *new_right;
- if (is_active_lvalue(e))
+ target_symbol_setter_functioncalls.push (&fcall);
+ require<expression*> (this, &new_left, e->left);
+ target_symbol_setter_functioncalls.pop ();
+ require<expression*> (this, &new_right, e->right);
+
+ if (fcall != NULL)
{
- // No need to be verbose: the flavour-gathering visitor
- // already printed a message for this exact case.
- throw semantic_error ("due to failed target variable resolution");
+ // Our left child is informing us that it was a target variable
+ // and it has been replaced with a set_target_foo() function
+ // call; we are going to provide that function call -- with the
+ // right child spliced in as sole argument -- in place of
+ // ourselves, in the deep copy we're in the middle of making.
+
+ // FIXME: for the time being, we only support plan $foo = bar,
+ // not += or any other op= variant. This is fixable, but a bit
+ // ugly.
+ if (e->op != "=")
+ throw semantic_error ("Operator-assign expressions on target "
+ "variables not implemented", e->tok);
+
+ assert (new_left == fcall);
+ fcall->args.push_back (new_right);
+ provide <expression*> (this, fcall);
}
+ else
+ {
+ assignment* n = new assignment;
+ n->op = e->op;
+ n->tok = e->tok;
+ n->left = new_left;
+ n->right = new_right;
+ provide <assignment*> (this, n);
+ }
+}
- string fname = "get_" + e->base_name.substr(1) + "_" + lex_cast<string>(tick++);
- // synthesize a function
+void
+var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
+{
+ assert(e->base_name.size() > 0 && e->base_name[0] == '$');
+
+ // Synthesize a function.
functiondecl *fdecl = new functiondecl;
embeddedcode *ec = new embeddedcode;
ec->tok = e->tok;
+ bool lvalue = is_active_lvalue(e);
+ string fname = (string(lvalue ? "set" : "get")
+ + "_" + e->base_name.substr(1)
+ + "_" + lex_cast<string>(tick++));
+
try
- {
- ec->code = q.dw.literal_stmt_for_local(scope_die,
- addr,
- e->base_name.substr(1),
- e->components,
- fdecl->type);
+ {
+ ec->code = q.dw.literal_stmt_for_local (scope_die,
+ addr,
+ e->base_name.substr(1),
+ e->components,
+ lvalue,
+ fdecl->type);
}
catch (const semantic_error& er)
{
@@ -2090,15 +2203,42 @@ var_expanding_copy_visitor::visit_target_symbol (target_symbol *e)
// already printed a message for this exact case.
throw semantic_error ("due to failed target variable resolution");
}
+
fdecl->name = fname;
fdecl->body = ec;
+ if (lvalue)
+ {
+ // Modify the fdecl so it carries a single pe_long formal
+ // argument called "value".
+
+ // FIXME: For the time being we only support setting target
+ // variables which have base types; these are 'pe_long' in
+ // stap's type vocabulary. Strings and pointers might be
+ // reasonable, some day, but not today.
+
+ vardecl *v = new vardecl;
+ v->type = pe_long;
+ v->name = "value";
+ v->tok = e->tok;
+ fdecl->formal_args.push_back(v);
+ }
q.sess.functions.push_back(fdecl);
- // synthesize a call
+ // Synthesize a functioncall.
functioncall* n = new functioncall;
n->tok = e->tok;
n->function = fname;
n->referent = NULL;
+
+ if (lvalue)
+ {
+ // Provide the functioncall to our parent, so that it can be
+ // used to substitute for the assignment node immediately above
+ // us.
+ assert(!target_symbol_setter_functioncalls.empty());
+ *(target_symbol_setter_functioncalls.top()) = n;
+ }
+
provide <functioncall*> (this, n);
}