On Wed, 2021-08-04 at 21:32 +0530, Ankur Saini wrote: [...snip...] > > - From observation, a typical vfunc call that isn't devirtualised by > the compiler's front end looks something like this > "OBJ_TYPE_REF(_2;(struct A)a_ptr_5(D)->0) (a_ptr_5(D))" > where "a_ptr_5(D)" is pointer that is being used to call the virtual > function. > > - We can access it's region to see what is the type of the object the > pointer is actually pointing to. > > - This is then used to find a call with DECL_CONTEXT of the object > from the all the possible targets of that polymorphic call.
[...] > > Patch file ( prototype ) : > > + /* Call is possibly a polymorphic call. > + > + In such case, use devirtisation tools to find > + possible callees of this function call. */ > + > + function *fun = get_current_function (); > + gcall *stmt = const_cast<gcall *> (call); > + cgraph_edge *e = cgraph_node::get (fun->decl)->get_edge (stmt); > + if (e->indirect_info->polymorphic) > + { > + void *cache_token; > + bool final; > + vec <cgraph_node *> targets > + = possible_polymorphic_call_targets (e, &final, &cache_token, true); > + if (!targets.is_empty ()) > + { > + tree most_propbable_taget = NULL_TREE; > + if(targets.length () == 1) > + return targets[0]->decl; > + > + /* From the current state, check which subclass the pointer that > + is being used to this polymorphic call points to, and use to > + filter out correct function call. */ > + tree t_val = gimple_call_arg (call, 0); Maybe rename to "this_expr"? > + const svalue *sval = get_rvalue (t_val, ctxt); and "this_sval"? ...assuming that that's what the value is. Probably should reject the case where there are zero arguments. > + > + const region *reg > + = [&]()->const region * > + { > + switch (sval->get_kind ()) > + { > + case SK_INITIAL: > + { > + const initial_svalue *initial_sval > + = sval->dyn_cast_initial_svalue (); > + return initial_sval->get_region (); > + } > + break; > + case SK_REGION: > + { > + const region_svalue *region_sval > + = sval->dyn_cast_region_svalue (); > + return region_sval->get_pointee (); > + } > + break; > + > + default: > + return NULL; > + } > + } (); I think the above should probably be a subroutine. That said, it's not clear to me what it's doing, or that this is correct. I'm guessing that you need to see if *((void **)this) is a vtable pointer (or something like that), and, if so, which class it is for. Is there a way of getting the vtable pointer as an svalue? > + gcc_assert (reg); > + > + tree known_possible_subclass_type; > + known_possible_subclass_type = reg->get_type (); > + if (reg->get_kind () == RK_FIELD) > + { > + const field_region* field_reg = reg->dyn_cast_field_region (); > + known_possible_subclass_type > + = DECL_CONTEXT (field_reg->get_field ()); > + } > + > + for (cgraph_node *x : targets) > + { > + if (DECL_CONTEXT (x->decl) == known_possible_subclass_type) > + most_propbable_taget = x->decl; > + } > + return most_propbable_taget; > + } > + } > + > return NULL_TREE; > } Dave