summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx740
1 files changed, 379 insertions, 361 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 9186ba82..4ddf4160 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1699,6 +1699,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor
dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a):
q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {}
+ void visit_target_symbol_saved_return (target_symbol* e);
+ void visit_target_symbol_context (target_symbol* e);
void visit_target_symbol (target_symbol* e);
void visit_cast_op (cast_op* e);
};
@@ -1758,415 +1760,431 @@ var_expanding_visitor::visit_assignment (assignment* e)
void
-dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
-{
- assert(e->base_name.size() > 0 && e->base_name[0] == '$');
- visited = true;
-
- bool lvalue = is_active_lvalue(e);
- if (lvalue && !q.sess.guru_mode)
- throw semantic_error("write to target variable not permitted", e->tok);
-
- // See if we need to generate a new probe to save/access function
- // parameters from a return probe. PR 1382.
- if (q.has_return
- && e->base_name != "$return" // not the special return-value variable handled below
- && e->base_name != "$$return") // nor the other special variable handled below
+dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e)
+{
+ // Get the full name of the target symbol.
+ stringstream ts_name_stream;
+ e->print(ts_name_stream);
+ string ts_name = ts_name_stream.str();
+
+ // Check and make sure we haven't already seen this target
+ // variable in this return probe. If we have, just return our
+ // last replacement.
+ map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
+ if (i != return_ts_map.end())
{
- if (lvalue)
- throw semantic_error("write to target variable not permitted in .return probes", e->tok);
-
- // Get the full name of the target symbol.
- stringstream ts_name_stream;
- e->print(ts_name_stream);
- string ts_name = ts_name_stream.str();
-
- // Check and make sure we haven't already seen this target
- // variable in this return probe. If we have, just return our
- // last replacement.
- map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
- if (i != return_ts_map.end())
- {
- provide (i->second);
- return;
- }
-
- // We've got to do several things here to handle target
- // variables in return probes.
+ provide (i->second);
+ return;
+ }
- // (1) Synthesize two global arrays. One is the cache of the
- // target variable and the other contains a thread specific
- // nesting level counter. The arrays will look like
- // this:
- //
- // _dwarf_tvar_{name}_{num}
- // _dwarf_tvar_{name}_{num}_ctr
+ // We've got to do several things here to handle target
+ // variables in return probes.
- string aname = (string("_dwarf_tvar_")
- + e->base_name.substr(1)
- + "_" + lex_cast<string>(tick++));
- vardecl* vd = new vardecl;
- vd->name = aname;
- vd->tok = e->tok;
- q.sess.globals.push_back (vd);
+ // (1) Synthesize two global arrays. One is the cache of the
+ // target variable and the other contains a thread specific
+ // nesting level counter. The arrays will look like
+ // this:
+ //
+ // _dwarf_tvar_{name}_{num}
+ // _dwarf_tvar_{name}_{num}_ctr
+
+ string aname = (string("_dwarf_tvar_")
+ + e->base_name.substr(1)
+ + "_" + lex_cast<string>(tick++));
+ vardecl* vd = new vardecl;
+ vd->name = aname;
+ vd->tok = e->tok;
+ q.sess.globals.push_back (vd);
+
+ string ctrname = aname + "_ctr";
+ vd = new vardecl;
+ vd->name = ctrname;
+ vd->tok = e->tok;
+ q.sess.globals.push_back (vd);
+
+ // (2) Create a new code block we're going to insert at the
+ // beginning of this probe to get the cached value into a
+ // temporary variable. We'll replace the target variable
+ // reference with the temporary variable reference. The code
+ // will look like this:
+ //
+ // _dwarf_tvar_tid = tid()
+ // _dwarf_tvar_{name}_{num}_tmp
+ // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
+ // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
+ // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
+
+ // (2a) Synthesize the tid temporary expression, which will look
+ // like this:
+ //
+ // _dwarf_tvar_tid = tid()
+ symbol* tidsym = new symbol;
+ tidsym->name = string("_dwarf_tvar_tid");
+ tidsym->tok = e->tok;
- string ctrname = aname + "_ctr";
- vd = new vardecl;
- vd->name = ctrname;
- vd->tok = e->tok;
- q.sess.globals.push_back (vd);
-
- // (2) Create a new code block we're going to insert at the
- // beginning of this probe to get the cached value into a
- // temporary variable. We'll replace the target variable
- // reference with the temporary variable reference. The code
- // will look like this:
- //
- // _dwarf_tvar_tid = tid()
- // _dwarf_tvar_{name}_{num}_tmp
- // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
- // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
- // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
-
- // (2a) Synthesize the tid temporary expression, which will look
- // like this:
- //
- // _dwarf_tvar_tid = tid()
- symbol* tidsym = new symbol;
- tidsym->name = string("_dwarf_tvar_tid");
- tidsym->tok = e->tok;
-
- if (add_block == NULL)
- {
- add_block = new block;
- add_block->tok = e->tok;
-
- // Synthesize a functioncall to grab the thread id.
- functioncall* fc = new functioncall;
- fc->tok = e->tok;
- fc->function = string("tid");
-
- // Assign the tid to '_dwarf_tvar_tid'.
- assignment* a = new assignment;
- a->tok = e->tok;
- a->op = "=";
- a->left = tidsym;
- a->right = fc;
-
- expr_statement* es = new expr_statement;
- es->tok = e->tok;
- es->value = a;
- add_block->statements.push_back (es);
- }
+ if (add_block == NULL)
+ {
+ add_block = new block;
+ add_block->tok = e->tok;
- // (2b) Synthesize an array reference and assign it to a
- // temporary variable (that we'll use as replacement for the
- // target variable reference). It will look like this:
- //
- // _dwarf_tvar_{name}_{num}_tmp
- // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
-
- arrayindex* ai_tvar_base = new arrayindex;
- ai_tvar_base->tok = e->tok;
-
- symbol* sym = new symbol;
- sym->name = aname;
- sym->tok = e->tok;
- ai_tvar_base->base = sym;
-
- ai_tvar_base->indexes.push_back(tidsym);
-
- // We need to create a copy of the array index in its current
- // state so we can have 2 variants of it (the original and one
- // that post-decrements the second index).
- arrayindex* ai_tvar = new arrayindex;
- arrayindex* ai_tvar_postdec = new arrayindex;
- *ai_tvar = *ai_tvar_base;
- *ai_tvar_postdec = *ai_tvar_base;
-
- // Synthesize the
- // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the
- // second index into the array.
- arrayindex* ai_ctr = new arrayindex;
- ai_ctr->tok = e->tok;
-
- sym = new symbol;
- sym->name = ctrname;
- sym->tok = e->tok;
- ai_ctr->base = sym;
- ai_ctr->indexes.push_back(tidsym);
- ai_tvar->indexes.push_back(ai_ctr);
-
- symbol* tmpsym = new symbol;
- tmpsym->name = aname + "_tmp";
- tmpsym->tok = e->tok;
+ // Synthesize a functioncall to grab the thread id.
+ functioncall* fc = new functioncall;
+ fc->tok = e->tok;
+ fc->function = string("tid");
+ // Assign the tid to '_dwarf_tvar_tid'.
assignment* a = new assignment;
a->tok = e->tok;
a->op = "=";
- a->left = tmpsym;
- a->right = ai_tvar;
+ a->left = tidsym;
+ a->right = fc;
expr_statement* es = new expr_statement;
es->tok = e->tok;
es->value = a;
-
add_block->statements.push_back (es);
+ }
- // (2c) Add a post-decrement to the second array index and
- // delete the array value. It will look like this:
- //
- // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
-
- post_crement* pc = new post_crement;
- pc->tok = e->tok;
- pc->op = "--";
- pc->operand = ai_ctr;
- ai_tvar_postdec->indexes.push_back(pc);
-
- delete_statement* ds = new delete_statement;
- ds->tok = e->tok;
- ds->value = ai_tvar_postdec;
-
- add_block->statements.push_back (ds);
-
- // (2d) Delete the counter value if it is 0. It will look like
- // this:
- // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
- // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
-
- ds = new delete_statement;
- ds->tok = e->tok;
- ds->value = ai_ctr;
-
- unary_expression *ue = new unary_expression;
- ue->tok = e->tok;
- ue->op = "!";
- ue->operand = ai_ctr;
-
- if_statement *ifs = new if_statement;
- ifs->tok = e->tok;
- ifs->condition = ue;
- ifs->thenblock = ds;
- ifs->elseblock = NULL;
-
- add_block->statements.push_back (ifs);
-
- // (3) We need an entry probe that saves the value for us in the
- // global array we created. Create the entry probe, which will
- // look like this:
- //
- // probe kernel.function("{function}") {
- // _dwarf_tvar_tid = tid()
- // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // = ${param}
- // }
-
- if (add_probe == NULL)
+ // (2b) Synthesize an array reference and assign it to a
+ // temporary variable (that we'll use as replacement for the
+ // target variable reference). It will look like this:
+ //
+ // _dwarf_tvar_{name}_{num}_tmp
+ // = _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+
+ arrayindex* ai_tvar_base = new arrayindex;
+ ai_tvar_base->tok = e->tok;
+
+ symbol* sym = new symbol;
+ sym->name = aname;
+ sym->tok = e->tok;
+ ai_tvar_base->base = sym;
+
+ ai_tvar_base->indexes.push_back(tidsym);
+
+ // We need to create a copy of the array index in its current
+ // state so we can have 2 variants of it (the original and one
+ // that post-decrements the second index).
+ arrayindex* ai_tvar = new arrayindex;
+ arrayindex* ai_tvar_postdec = new arrayindex;
+ *ai_tvar = *ai_tvar_base;
+ *ai_tvar_postdec = *ai_tvar_base;
+
+ // Synthesize the
+ // "_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]" used as the
+ // second index into the array.
+ arrayindex* ai_ctr = new arrayindex;
+ ai_ctr->tok = e->tok;
+
+ sym = new symbol;
+ sym->name = ctrname;
+ sym->tok = e->tok;
+ ai_ctr->base = sym;
+ ai_ctr->indexes.push_back(tidsym);
+ ai_tvar->indexes.push_back(ai_ctr);
+
+ symbol* tmpsym = new symbol;
+ tmpsym->name = aname + "_tmp";
+ tmpsym->tok = e->tok;
+
+ assignment* a = new assignment;
+ a->tok = e->tok;
+ a->op = "=";
+ a->left = tmpsym;
+ a->right = ai_tvar;
+
+ expr_statement* es = new expr_statement;
+ es->tok = e->tok;
+ es->value = a;
+
+ add_block->statements.push_back (es);
+
+ // (2c) Add a post-decrement to the second array index and
+ // delete the array value. It will look like this:
+ //
+ // delete _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]--]
+
+ post_crement* pc = new post_crement;
+ pc->tok = e->tok;
+ pc->op = "--";
+ pc->operand = ai_ctr;
+ ai_tvar_postdec->indexes.push_back(pc);
+
+ delete_statement* ds = new delete_statement;
+ ds->tok = e->tok;
+ ds->value = ai_tvar_postdec;
+
+ add_block->statements.push_back (ds);
+
+ // (2d) Delete the counter value if it is 0. It will look like
+ // this:
+ // if (! _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid])
+ // delete _dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]
+
+ ds = new delete_statement;
+ ds->tok = e->tok;
+ ds->value = ai_ctr;
+
+ unary_expression *ue = new unary_expression;
+ ue->tok = e->tok;
+ ue->op = "!";
+ ue->operand = ai_ctr;
+
+ if_statement *ifs = new if_statement;
+ ifs->tok = e->tok;
+ ifs->condition = ue;
+ ifs->thenblock = ds;
+ ifs->elseblock = NULL;
+
+ add_block->statements.push_back (ifs);
+
+ // (3) We need an entry probe that saves the value for us in the
+ // global array we created. Create the entry probe, which will
+ // look like this:
+ //
+ // probe kernel.function("{function}") {
+ // _dwarf_tvar_tid = tid()
+ // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // = ${param}
+ // }
+
+ if (add_probe == NULL)
+ {
+ add_probe = new probe;
+ add_probe->tok = e->tok;
+
+ // We need the name of the current probe point, minus the
+ // ".return" (or anything after it, such as ".maxactive(N)").
+ // Create a new probe point, copying all the components,
+ // stopping when we see the ".return" component.
+ probe_point* pp = new probe_point;
+ for (unsigned c = 0; c < q.base_loc->components.size(); c++)
{
- add_probe = new probe;
- add_probe->tok = e->tok;
-
- // We need the name of the current probe point, minus the
- // ".return" (or anything after it, such as ".maxactive(N)").
- // Create a new probe point, copying all the components,
- // stopping when we see the ".return" component.
- probe_point* pp = new probe_point;
- for (unsigned c = 0; c < q.base_loc->components.size(); c++)
- {
- if (q.base_loc->components[c]->functor == "return")
- break;
- else
- pp->components.push_back(q.base_loc->components[c]);
- }
- pp->tok = e->tok;
- pp->optional = q.base_loc->optional;
- add_probe->locations.push_back(pp);
-
- add_probe->body = new block;
- add_probe->body->tok = e->tok;
-
- // Synthesize a functioncall to grab the thread id.
- functioncall* fc = new functioncall;
- fc->tok = e->tok;
- fc->function = string("tid");
-
- // Assign the tid to '_dwarf_tvar_tid'.
- assignment* a = new assignment;
- a->tok = e->tok;
- a->op = "=";
- a->left = tidsym;
- a->right = fc;
-
- expr_statement* es = new expr_statement;
- es->tok = e->tok;
- es->value = a;
- add_probe->body = new block(add_probe->body, es);
-
- vardecl* vd = new vardecl;
- vd->tok = e->tok;
- vd->name = tidsym->name;
- vd->type = pe_long;
- vd->set_arity(0);
- add_probe->locals.push_back(vd);
- }
+ if (q.base_loc->components[c]->functor == "return")
+ break;
+ else
+ pp->components.push_back(q.base_loc->components[c]);
+ }
+ pp->tok = e->tok;
+ pp->optional = q.base_loc->optional;
+ add_probe->locations.push_back(pp);
- // Save the value, like this:
- // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
- // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
- // = ${param}
- arrayindex* ai_tvar_preinc = new arrayindex;
- *ai_tvar_preinc = *ai_tvar_base;
+ add_probe->body = new block;
+ add_probe->body->tok = e->tok;
- pre_crement* preinc = new pre_crement;
- preinc->tok = e->tok;
- preinc->op = "++";
- preinc->operand = ai_ctr;
- ai_tvar_preinc->indexes.push_back(preinc);
+ // Synthesize a functioncall to grab the thread id.
+ functioncall* fc = new functioncall;
+ fc->tok = e->tok;
+ fc->function = string("tid");
- a = new assignment;
+ // Assign the tid to '_dwarf_tvar_tid'.
+ assignment* a = new assignment;
a->tok = e->tok;
a->op = "=";
- a->left = ai_tvar_preinc;
- a->right = e;
+ a->left = tidsym;
+ a->right = fc;
- es = new expr_statement;
+ expr_statement* es = new expr_statement;
es->tok = e->tok;
es->value = a;
-
add_probe->body = new block(add_probe->body, es);
- // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to
- // our parent so it can be used as a substitute for the target
- // symbol.
- provide (tmpsym);
-
- // (5) Remember this replacement since we might be able to reuse
- // it later if the same return probe references this target
- // symbol again.
- return_ts_map[ts_name] = tmpsym;
- return;
+ vardecl* vd = new vardecl;
+ vd->tok = e->tok;
+ vd->name = tidsym->name;
+ vd->type = pe_long;
+ vd->set_arity(0);
+ add_probe->locals.push_back(vd);
}
- if (e->base_name == "$$vars"
- || e->base_name == "$$parms"
- || e->base_name == "$$locals"
- || (q.has_return && (e->base_name == "$$return")))
- {
- Dwarf_Die *scopes;
- if (dwarf_getscopes_die (scope_die, &scopes) == 0)
- return;
+ // Save the value, like this:
+ // _dwarf_tvar_{name}_{num}[_dwarf_tvar_tid,
+ // ++_dwarf_tvar_{name}_{num}_ctr[_dwarf_tvar_tid]]
+ // = ${param}
+ arrayindex* ai_tvar_preinc = new arrayindex;
+ *ai_tvar_preinc = *ai_tvar_base;
+
+ pre_crement* preinc = new pre_crement;
+ preinc->tok = e->tok;
+ preinc->op = "++";
+ preinc->operand = ai_ctr;
+ ai_tvar_preinc->indexes.push_back(preinc);
+
+ a = new assignment;
+ a->tok = e->tok;
+ a->op = "=";
+ a->left = ai_tvar_preinc;
+ a->right = e;
+
+ es = new expr_statement;
+ es->tok = e->tok;
+ es->value = a;
+
+ add_probe->body = new block(add_probe->body, es);
+
+ // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to
+ // our parent so it can be used as a substitute for the target
+ // symbol.
+ provide (tmpsym);
+
+ // (5) Remember this replacement since we might be able to reuse
+ // it later if the same return probe references this target
+ // symbol again.
+ return_ts_map[ts_name] = tmpsym;
+}
- if (e->addressof)
- throw semantic_error("cannot take address of context variable", e->tok);
- target_symbol *tsym = new target_symbol;
- print_format* pf = new print_format;
+void
+dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
+{
+ Dwarf_Die *scopes;
+ if (dwarf_getscopes_die (scope_die, &scopes) == 0)
+ return;
- // Convert $$parms to sprintf of a list of parms and active local vars
- // which we recursively evaluate
+ target_symbol *tsym = new target_symbol;
+ print_format* pf = new print_format;
- // NB: we synthesize a new token here rather than reusing
- // e->tok, because print_format::print likes to use
- // its tok->content.
- token* pf_tok = new token;
- pf_tok->location = e->tok->location;
- pf_tok->type = tok_identifier;
- pf_tok->content = "sprint";
+ // Convert $$parms to sprintf of a list of parms and active local vars
+ // which we recursively evaluate
- pf->tok = pf_tok;
- pf->print_to_stream = false;
- pf->print_with_format = true;
- pf->print_with_delim = false;
- pf->print_with_newline = false;
- pf->print_char = false;
+ // NB: we synthesize a new token here rather than reusing
+ // e->tok, because print_format::print likes to use
+ // its tok->content.
+ token* pf_tok = new token;
+ pf_tok->location = e->tok->location;
+ pf_tok->type = tok_identifier;
+ pf_tok->content = "sprint";
- if (q.has_return && (e->base_name == "$$return"))
- {
- tsym->tok = e->tok;
- tsym->base_name = "$return";
+ pf->tok = pf_tok;
+ pf->print_to_stream = false;
+ pf->print_with_format = true;
+ pf->print_with_delim = false;
+ pf->print_with_newline = false;
+ pf->print_char = false;
- // Ignore any variable that isn't accessible.
- tsym->saved_conversion_error = 0;
- expression *texp = tsym;
- texp = require (texp); // NB: throws nothing ...
- if (tsym->saved_conversion_error) // ... but this is how we know it happened.
- {
+ if (q.has_return && (e->base_name == "$$return"))
+ {
+ tsym->tok = e->tok;
+ tsym->base_name = "$return";
+
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ expression *texp = tsym;
+ texp = require (texp); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
+ {
- }
- else
- {
- pf->raw_components += "return";
- pf->raw_components += "=%#x ";
- pf->args.push_back(texp);
- }
}
else
{
- // non-.return probe: support $$parms, $$vars, $$locals
- Dwarf_Die result;
- if (dwarf_child (&scopes[0], &result) == 0)
- do
+ pf->raw_components += "return";
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(texp);
+ }
+ }
+ else
+ {
+ // non-.return probe: support $$parms, $$vars, $$locals
+ Dwarf_Die result;
+ if (dwarf_child (&scopes[0], &result) == 0)
+ do
+ {
+ switch (dwarf_tag (&result))
{
- switch (dwarf_tag (&result))
- {
- case DW_TAG_variable:
- if (e->base_name == "$$parms")
- continue;
- break;
- case DW_TAG_formal_parameter:
- if (e->base_name == "$$locals")
- continue;
- break;
-
- default:
- continue;
- }
+ case DW_TAG_variable:
+ if (e->base_name == "$$parms")
+ continue;
+ break;
+ case DW_TAG_formal_parameter:
+ if (e->base_name == "$$locals")
+ continue;
+ break;
+
+ default:
+ continue;
+ }
- const char *diename = dwarf_diename (&result);
- if (! diename) continue;
+ const char *diename = dwarf_diename (&result);
+ if (! diename) continue;
- tsym->tok = e->tok;
- tsym->base_name = "$";
- tsym->base_name += diename;
+ tsym->tok = e->tok;
+ tsym->base_name = "$";
+ tsym->base_name += diename;
- // Ignore any variable that isn't accessible.
- tsym->saved_conversion_error = 0;
- expression *texp = tsym;
- texp = require (texp); // NB: throws nothing ...
- if (tsym->saved_conversion_error) // ... but this is how we know it happened.
- {
- if (q.sess.verbose>2)
- {
- for (semantic_error *c = tsym->saved_conversion_error;
- c != 0;
- c = c->chain) {
- clog << "variable location problem: " << c->what() << endl;
- }
- }
-
- pf->raw_components += diename;
- pf->raw_components += "=? ";
- }
- else
+ // Ignore any variable that isn't accessible.
+ tsym->saved_conversion_error = 0;
+ expression *texp = tsym;
+ texp = require (texp); // NB: throws nothing ...
+ if (tsym->saved_conversion_error) // ... but this is how we know it happened.
+ {
+ if (q.sess.verbose>2)
{
- pf->raw_components += diename;
- pf->raw_components += "=%#x ";
- pf->args.push_back(texp);
+ for (semantic_error *c = tsym->saved_conversion_error;
+ c != 0;
+ c = c->chain) {
+ clog << "variable location problem: " << c->what() << endl;
+ }
}
+
+ pf->raw_components += diename;
+ pf->raw_components += "=? ";
}
- while (dwarf_siblingof (&result, &result) == 0);
- }
+ else
+ {
+ pf->raw_components += diename;
+ pf->raw_components += "=%#x ";
+ pf->args.push_back(texp);
+ }
+ }
+ while (dwarf_siblingof (&result, &result) == 0);
+ }
- pf->components = print_format::string_to_components(pf->raw_components);
- provide (pf);
+ pf->components = print_format::string_to_components(pf->raw_components);
+ provide (pf);
+}
+
+
+void
+dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
+{
+ assert(e->base_name.size() > 0 && e->base_name[0] == '$');
+ visited = true;
+
+ bool lvalue = is_active_lvalue(e);
+ if (lvalue && !q.sess.guru_mode)
+ throw semantic_error("write to target variable not permitted", e->tok);
+
+ // See if we need to generate a new probe to save/access function
+ // parameters from a return probe. PR 1382.
+ if (q.has_return
+ && e->base_name != "$return" // not the special return-value variable handled below
+ && e->base_name != "$$return") // nor the other special variable handled below
+ {
+ if (lvalue)
+ throw semantic_error("write to target variable not permitted in .return probes", e->tok);
+
+ visit_target_symbol_saved_return(e);
+ return;
+ }
+
+ if (e->base_name == "$$vars"
+ || e->base_name == "$$parms"
+ || e->base_name == "$$locals"
+ || (q.has_return && (e->base_name == "$$return")))
+ {
+ if (lvalue)
+ throw semantic_error("cannot write to context variable", e->tok);
+
+ if (e->addressof)
+ throw semantic_error("cannot take address of context variable", e->tok);
+ visit_target_symbol_context(e);
return;
}