From 66facfa3d0190a2f6da7fd755a73a29f526c169b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 7 May 2014 13:07:37 -0700 Subject: [PATCH] Start expanding autocast during type resolution There's no real propagation yet, so you can only try directly transferred types so far, like: probe oneshot { println( (& @cast(task_current(), "task_struct")) ->pid ) } So that captures the task_current() address *with* the type, and then the "->pid" is working as a separate expression to dereference it. * elaborate.cxx (semantic_pass_symbols): Move build_no_more from here... (semantic_pass): ... to here, well after all types are resolved. (autocast_expanding_visitor): New, call on the type_details to expand autocast_op into a functioncall, like any $var/@cast would. (semantic_pass_types): Use autocast_expanding_visitor whenever the normal type resolution indicated there might be something to do. (typeresolution_info::visit_autocast_op): Don't fail immediately; just visit the operand, and note when type_details show up. * tapsets.cxx (exp_type_dwarf::expand): Expand that autocast_op! (dwarf_autocast_expanding_visitor): Removed in favor of just having autocast_expanding_visitor call exp_type_ptr->expand(). --- elaborate.cxx | 62 ++++++++++++++++++++++++++++++++++++++++++++++++--- elaborate.h | 1 + staptree.h | 5 +++++ tapsets.cxx | 50 ++++++++++++++++++++++++++++------------- 4 files changed, 99 insertions(+), 19 deletions(-) diff --git a/elaborate.cxx b/elaborate.cxx index 7579dad9e..0dc11f974 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1735,8 +1735,6 @@ semantic_pass_symbols (systemtap_session& s) } } - build_no_more (s); - if(s.systemtap_v_check){ for(unsigned i=0;isystemtap_v_conditional) @@ -1942,6 +1940,8 @@ semantic_pass (systemtap_session& s) rc ++; } + build_no_more (s); + // PR11443 // NB: listing mode only cares whether we have any probes, // so all previous error conditions are disregarded. @@ -4181,6 +4181,38 @@ semantic_pass_optimize2 (systemtap_session& s) // ------------------------------------------------------------------------ // type resolution +struct autocast_expanding_visitor: public var_expanding_visitor +{ + typeresolution_info& ti; + autocast_expanding_visitor(typeresolution_info& ti): ti(ti) {} + + void visit_autocast_op (autocast_op* e) + { + const bool lvalue = is_active_lvalue (e); + const exp_type_ptr& details = e->operand->type_details; + if (details) + { + functioncall* n = details->expand (e, lvalue); + if (n) + { + ti.num_newly_resolved++; + + 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; + } + + n->visit (this); + return; + } + } + var_expanding_visitor::visit_autocast_op (e); + } +}; static int semantic_pass_types (systemtap_session& s) @@ -4200,6 +4232,7 @@ semantic_pass_types (systemtap_session& s) iterations ++; ti.num_newly_resolved = 0; ti.num_still_unresolved = 0; + ti.num_available_autocasts = 0; for (map::iterator it = s.functions.begin(); it != s.functions.end(); it++) @@ -4219,6 +4252,14 @@ semantic_pass_types (systemtap_session& s) // ti.unresolved (fd->tok); for (unsigned i=0; i < fd->locals.size(); ++i) ti.check_local (fd->locals[i]); + + // Check and run the autocast expanding visitor. + if (ti.num_available_autocasts > 0) + { + autocast_expanding_visitor aev (ti); + aev.replace (fd->body); + ti.num_available_autocasts = 0; + } } for (unsigned j=0; jlocals.size(); ++i) ti.check_local (pn->locals[i]); + // Check and run the autocast expanding visitor. + if (ti.num_available_autocasts > 0) + { + autocast_expanding_visitor aev (ti); + aev.replace (pn->body); + ti.num_available_autocasts = 0; + } + probe_point* pp = pn->sole_location(); if (pp->condition) { @@ -4752,8 +4801,15 @@ typeresolution_info::visit_autocast_op (autocast_op* e) // unless it was not resolved and its value is really needed. if (e->saved_conversion_error) throw (* (e->saved_conversion_error)); - else + else if (assert_resolvability) throw SEMANTIC_ERROR(_("unknown type in dereference"), e->tok); + + t = pe_long; + e->operand->visit (this); + + num_still_unresolved++; + if (e->operand->type_details) + num_available_autocasts++; } diff --git a/elaborate.h b/elaborate.h index 9cc59bb75..679a4fcec 100644 --- a/elaborate.h +++ b/elaborate.h @@ -70,6 +70,7 @@ struct typeresolution_info: public visitor systemtap_session& session; unsigned num_newly_resolved; unsigned num_still_unresolved; + unsigned num_available_autocasts; bool assert_resolvability; int mismatch_complexity; functiondecl* current_function; diff --git a/staptree.h b/staptree.h index 31e9adea6..9df28c350 100644 --- a/staptree.h +++ b/staptree.h @@ -107,6 +107,8 @@ enum exp_type std::ostream& operator << (std::ostream& o, const exp_type& e); +struct functioncall; +struct autocast_op; struct exp_type_details { virtual ~exp_type_details () {}; @@ -115,6 +117,9 @@ struct exp_type_details virtual uintptr_t id () const = 0; bool operator==(const exp_type_details& other) const { return id () == other.id (); } + + // Expand this autocast_op into a function call + virtual functioncall *expand(autocast_op* e, bool lvalue) = 0; }; typedef shared_ptr exp_type_ptr; diff --git a/tapsets.cxx b/tapsets.cxx index 346251d34..fb905a81d 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -433,8 +433,11 @@ struct exp_type_dwarf : public exp_type_details // that we'd probably never clear all references... :/ dwflpp* dw; Dwarf_Die die; - exp_type_dwarf(dwflpp* dw, Dwarf_Die* die): dw(dw), die(*die) {} + bool userspace_p; + exp_type_dwarf(dwflpp* dw, Dwarf_Die* die, bool userspace_p) + : dw(dw), die(*die), userspace_p(userspace_p) {} uintptr_t id () const { return reinterpret_cast(die.addr); } + functioncall *expand(autocast_op* e, bool lvalue); }; @@ -3184,7 +3187,7 @@ synthetic_embedded_deref_call(dwflpp& dw, fcall->referent = fdecl; fcall->function = fdecl->name; fcall->type = fdecl->type; - fcall->type_details.reset(new exp_type_dwarf(&dw, function_type)); + fcall->type_details.reset(new exp_type_dwarf(&dw, function_type, userspace_p)); // If this code snippet uses a precomputed pointer, // pass that as the first argument. @@ -4236,21 +4239,40 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) } -struct dwarf_autocast_expanding_visitor: public var_expanding_visitor +functioncall * +exp_type_dwarf::expand(autocast_op* e, bool lvalue) { - systemtap_session& s; + static unsigned tick = 0; - dwarf_autocast_expanding_visitor(systemtap_session& s): s(s) {} - void visit_autocast_op (autocast_op* e); -}; + try + { + Dwarf_Die cu_mem; + dw->focus_on_cu(dwarf_diecu(&die, &cu_mem, NULL, NULL)); + if (!e->components.empty() && + e->components.back().type == target_symbol::comp_pretty_print) + { + if (lvalue) + throw SEMANTIC_ERROR(_("cannot write to pretty-printed variable"), e->tok); -void -dwarf_autocast_expanding_visitor::visit_autocast_op (autocast_op* e) -{ - // TODO PR13664, glean the type from e->operand, then expand like @cast. + dwarf_pretty_print dpp(*dw, &die, e->operand, true, userspace_p, *e); + return dpp.expand(); + } - var_expanding_visitor::visit_autocast_op (e); + Dwarf_Die endtype; + string code = dw->literal_stmt_for_pointer (&die, e, lvalue, &endtype); + + string fname = (string(lvalue ? "_dwarf_autocast_set" : "_dwarf_autocast_get") + + "_" + lex_cast(tick++)); + + return synthetic_embedded_deref_call(*dw, &endtype, fname, code, + userspace_p, lvalue, e, e->operand); + } + catch (const semantic_error &er) + { + e->chain (er); + return NULL; + } } @@ -5090,10 +5112,6 @@ dwarf_derived_probe::register_patterns(systemtap_session& s) filter = new dwarf_atvar_expanding_visitor(s, *dw); s.code_filters.push_back(filter); - // NB: visit autocast last, so it can use types resolved from @cast/@var - filter = new dwarf_autocast_expanding_visitor(s); - s.code_filters.push_back(filter); - register_function_and_statement_variants(s, root->bind(TOK_KERNEL), dw, pr_privileged); register_function_and_statement_variants(s, root->bind_str(TOK_MODULE), dw, pr_privileged); root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE) -- 2.43.5