Ejemplo n.º 1
0
static void
record_target_from_binfo (vec <cgraph_node *> &nodes,
			  tree binfo,
			  tree otr_type,
			  tree type_binfo,
			  HOST_WIDE_INT otr_token,
			  tree outer_type,
			  HOST_WIDE_INT offset,
			  pointer_set_t *inserted,
			  pointer_set_t *matched_vtables,
			  bool anonymous)
{
  tree type = BINFO_TYPE (binfo);
  int i;
  tree base_binfo;

  gcc_checking_assert (BINFO_VTABLE (type_binfo));

  if (types_same_for_odr (type, outer_type))
    {
      tree inner_binfo = get_binfo_at_offset (type_binfo,
					      offset, otr_type);
      /* For types in anonymous namespace first check if the respective vtable
	 is alive. If not, we know the type can't be called.  */
      if (!flag_ltrans && anonymous)
	{
	  tree vtable = BINFO_VTABLE (inner_binfo);
	  struct varpool_node *vnode;

	  if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
	    vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
	  vnode = varpool_get_node (vtable);
	  if (!vnode || !vnode->definition)
	    return;
	}
      gcc_assert (inner_binfo);
      if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo)))
	{
	  tree target = gimple_get_virt_method_for_binfo (otr_token, inner_binfo);
	  if (target)
	    maybe_record_node (nodes, target, inserted, NULL);
	}
      return;
    }

  /* Walk bases.  */
  for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
    /* Walking bases that have no virtual method is pointless excercise.  */
    if (polymorphic_type_binfo_p (base_binfo))
      record_target_from_binfo (nodes, base_binfo, otr_type,
				/* In the case of single inheritance,
				   the virtual table is shared with
				   the outer type.  */
				BINFO_VTABLE (base_binfo) ? base_binfo : type_binfo,
				otr_token, outer_type, offset, inserted,
				matched_vtables, anonymous);
}
Ejemplo n.º 2
0
static bool
ipcp_copy_types (struct ipa_node_params *caller_info,
		 struct ipa_node_params *callee_info,
		 int callee_idx, struct ipa_jump_func *jf)
{
  int caller_idx, j, count;
  bool res;

  if (ipa_param_cannot_devirtualize_p (callee_info, callee_idx))
    return false;

  if (jf->type == IPA_JF_PASS_THROUGH)
    {
      if (jf->value.pass_through.operation != NOP_EXPR)
	{
	  ipa_set_param_cannot_devirtualize (callee_info, callee_idx);
	  return true;
	}
      caller_idx = jf->value.pass_through.formal_id;
    }
  else
    caller_idx = jf->value.ancestor.formal_id;

  if (ipa_param_cannot_devirtualize_p (caller_info, caller_idx))
    {
      ipa_set_param_cannot_devirtualize (callee_info, callee_idx);
      return true;
    }

  if (!caller_info->params[caller_idx].types)
    return false;

  res = false;
  count = VEC_length (tree, caller_info->params[caller_idx].types);
  for (j = 0; j < count; j++)
    {
      tree binfo = VEC_index (tree, caller_info->params[caller_idx].types, j);
      if (jf->type == IPA_JF_ANCESTOR)
	{
	  binfo = get_binfo_at_offset (binfo, jf->value.ancestor.offset,
				       jf->value.ancestor.type);
	  if (!binfo)
	    {
	      ipa_set_param_cannot_devirtualize (callee_info, callee_idx);
	      return true;
	    }
	}
      res |= ipcp_add_param_type (callee_info, callee_idx, binfo);
    }
  return res;
}