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


Reply via email to