Ping

2014-06-06 13:32 GMT+04:00 Ilya Enkovich <enkovich....@gmail.com>:
> 2014-06-03 12:46 GMT+04:00 Richard Biener <richard.guent...@gmail.com>:
>> On Mon, Jun 2, 2014 at 4:51 PM, Ilya Enkovich <enkovich....@gmail.com> wrote:
>>> Hi,
>>>
>>> This patch adds support for normal builtin function calls (target ones are 
>>> not instrumented).  The basic idea of the patch is to make call expr copy 
>>> with no bounds and expand it instead.  If expr is going to be emitted as a 
>>> function call then original instrumented expr takes place.  Handle string 
>>> function separately because they are of high interest for the checker.
>>
>> It seems to be this should be user-controllable (always expand builtins with
>> bounds as calls, or not), rather than deciding what is of interest yourself.
>
> User has no idea what can be transformed into a builtin call. He may
> pragmas in his source code to control instrumentation. Compiler just
> tries to cover as much code as it can but reasonable compromise with
> performance should be made.
>
>>
>> From a high-level perspective the expansion path doing inline expansion
>> should be separated from that expanding as a call (or expanding as a
>> different call).  I don't like that building of yet another GENERIC call expr
>> in this code ... it goes very much backwards of the idea that we should
>> expand from the GIMPLE representation.  You are making such transition
>> even harder.
>>
>> Can't you do that frobbing from cfgexpand.c:expand_call_stmt instead 
>> (please!)?
>
> I need both instrumented and not instrumented versions of call in
> expand_builtin, so I do not see how it may be handled in
> expand_call_stmt.
>
> Ilya
>>
>> Thanks,
>> Richard.
>>
>>> Bootstrapped and tested on linux-x86_64.
>>>
>>> Thanks,
>>> Ilya
>>> --
>>> gcc/
>>>
>>> 2014-06-02  Ilya Enkovich  <ilya.enkov...@intel.com>
>>>
>>>         * builtins.c: Include rtl-chkp.h, tree-chkp.h.
>>>         (expand_builtin_mempcpy_args): Add orig exp as argument.
>>>         Support BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK.
>>>         (expand_builtin_mempcpy): Adjust expand_builtin_mempcpy_args call.
>>>         (expand_builtin_stpcpy): Likewise.
>>>         (expand_builtin_memset_args): Support 
>>> BUILT_IN_CHKP_MEMSET_NOBND_NOCHK.
>>>         (std_expand_builtin_va_start): Initialize bounds for va_list.
>>>         (expand_builtin): Support instrumented calls.
>>>
>>>
>>> diff --git a/gcc/builtins.c b/gcc/builtins.c
>>> index 7357124..c0140e1 100644
>>> --- a/gcc/builtins.c
>>> +++ b/gcc/builtins.c
>>> @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "builtins.h"
>>>  #include "ubsan.h"
>>>  #include "cilk.h"
>>> +#include "tree-chkp.h"
>>> +#include "rtl-chkp.h"
>>>
>>>
>>>  static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, 
>>> mpc_rnd_t));
>>> @@ -124,7 +126,7 @@ static rtx builtin_memcpy_read_str (void *, 
>>> HOST_WIDE_INT, enum machine_mode);
>>>  static rtx expand_builtin_memcpy (tree, rtx);
>>>  static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
>>>  static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
>>> -                                       enum machine_mode, int);
>>> +                                       enum machine_mode, int, tree);
>>>  static rtx expand_builtin_strcpy (tree, rtx);
>>>  static rtx expand_builtin_strcpy_args (tree, tree, rtx);
>>>  static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
>>> @@ -3284,7 +3286,8 @@ expand_builtin_mempcpy (tree exp, rtx target, enum 
>>> machine_mode mode)
>>>        tree src = CALL_EXPR_ARG (exp, 1);
>>>        tree len = CALL_EXPR_ARG (exp, 2);
>>>        return expand_builtin_mempcpy_args (dest, src, len,
>>> -                                         target, mode, /*endp=*/ 1);
>>> +                                         target, mode, /*endp=*/ 1,
>>> +                                         exp);
>>>      }
>>>  }
>>>
>>> @@ -3296,10 +3299,23 @@ expand_builtin_mempcpy (tree exp, rtx target, enum 
>>> machine_mode mode)
>>>
>>>  static rtx
>>>  expand_builtin_mempcpy_args (tree dest, tree src, tree len,
>>> -                            rtx target, enum machine_mode mode, int endp)
>>> +                            rtx target, enum machine_mode mode, int endp,
>>> +                            tree orig_exp)
>>>  {
>>> +  tree fndecl = get_callee_fndecl (orig_exp);
>>> +
>>>      /* If return value is ignored, transform mempcpy into memcpy.  */
>>> -  if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
>>> +  if (target == const0_rtx
>>> +      && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK
>>> +      && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK))
>>> +    {
>>> +      tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK);
>>> +      tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
>>> +                                          dest, src, len);
>>> +      return expand_expr (result, target, mode, EXPAND_NORMAL);
>>> +    }
>>> +  else if (target == const0_rtx
>>> +          && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
>>>      {
>>>        tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
>>>        tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
>>> @@ -3484,7 +3500,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum 
>>> machine_mode mode)
>>>
>>>        lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
>>>        ret = expand_builtin_mempcpy_args (dst, src, lenp1,
>>> -                                        target, mode, /*endp=*/2);
>>> +                                        target, mode, /*endp=*/2,
>>> +                                        exp);
>>>
>>>        if (ret)
>>>         return ret;
>>> @@ -3778,7 +3795,8 @@ expand_builtin_memset_args (tree dest, tree val, tree 
>>> len,
>>>   do_libcall:
>>>    fndecl = get_callee_fndecl (orig_exp);
>>>    fcode = DECL_FUNCTION_CODE (fndecl);
>>> -  if (fcode == BUILT_IN_MEMSET)
>>> +  if (fcode == BUILT_IN_MEMSET
>>> +      || fcode == BUILT_IN_CHKP_MEMSET_NOBND_NOCHK)
>>>      fn = build_call_nofold_loc (EXPR_LOCATION (orig_exp), fndecl, 3,
>>>                                 dest, val, len);
>>>    else if (fcode == BUILT_IN_BZERO)
>>> @@ -4330,6 +4348,13 @@ std_expand_builtin_va_start (tree valist, rtx 
>>> nextarg)
>>>  {
>>>    rtx va_r = expand_expr (valist, NULL_RTX, VOIDmode, EXPAND_WRITE);
>>>    convert_move (va_r, nextarg, 0);
>>> +
>>> +  /* We do not have any valid bounds for the pointer, so
>>> +     just store zero bounds for it.  */
>>> +  if (chkp_function_instrumented_p (current_function_decl))
>>> +    chkp_expand_bounds_reset_for_mem (valist,
>>> +                                     make_tree (TREE_TYPE (valist),
>>> +                                                nextarg));
>>>  }
>>>
>>>  /* Expand EXP, a call to __builtin_va_start.  */
>>> @@ -5793,6 +5818,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>    enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
>>>    enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
>>>    int flags;
>>> +  tree orig_exp = exp;
>>>
>>>    if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
>>>      return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
>>> @@ -5856,6 +5882,41 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>         }
>>>      }
>>>
>>> +  /* Currently none of builtin expand functions works with bounds.
>>> +     To avoid modification of all expanders we just make a new call
>>> +     expression without bound args.  The original expression is used
>>> +     in case we expand builtin as a call.  */
>>> +  if (CALL_WITH_BOUNDS_P (exp))
>>> +    {
>>> +      int new_arg_no = 0;
>>> +      tree new_call;
>>> +      tree arg;
>>> +      call_expr_arg_iterator iter;
>>> +      tree *new_args = XALLOCAVEC (tree, call_expr_nargs (exp));
>>> +
>>> +      FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
>>> +       if (!POINTER_BOUNDS_P (arg))
>>> +         new_args[new_arg_no++] = arg;
>>> +
>>> +      if (new_arg_no > 0)
>>> +       {
>>> +         new_call = build_call_array (TREE_TYPE (exp), fndecl, new_arg_no, 
>>> new_args);
>>> +         CALL_EXPR_STATIC_CHAIN (new_call) = CALL_EXPR_STATIC_CHAIN (exp);
>>> +         CALL_EXPR_FN (new_call) = CALL_EXPR_FN (exp);
>>> +         TREE_SIDE_EFFECTS (new_call) = TREE_SIDE_EFFECTS (exp);
>>> +         TREE_NOTHROW (new_call) = TREE_NOTHROW (exp);
>>> +         CALL_EXPR_TAILCALL (new_call) = CALL_EXPR_TAILCALL (exp);
>>> +         CALL_EXPR_RETURN_SLOT_OPT (new_call) = CALL_EXPR_RETURN_SLOT_OPT 
>>> (exp);
>>> +         CALL_ALLOCA_FOR_VAR_P (new_call) = CALL_ALLOCA_FOR_VAR_P (exp);
>>> +         CALL_FROM_THUNK_P (new_call) = CALL_FROM_THUNK_P (exp);
>>> +         CALL_EXPR_VA_ARG_PACK (new_call) = CALL_EXPR_VA_ARG_PACK (exp);
>>> +         SET_EXPR_LOCATION (new_call, EXPR_LOCATION (exp));
>>> +         TREE_SET_BLOCK (new_call, TREE_BLOCK (exp));
>>> +
>>> +         exp = new_call;
>>> +        }
>>> +    }
>>> +
>>>    switch (fcode)
>>>      {
>>>      CASE_FLT_FN (BUILT_IN_FABS):
>>> @@ -6146,60 +6207,116 @@ expand_builtin (tree exp, rtx target, rtx 
>>> subtarget, enum machine_mode mode,
>>>        break;
>>>
>>>      case BUILT_IN_STRLEN:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_strlen (exp, target, target_mode);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_STRCPY:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_strcpy (exp, target);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_STRNCPY:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_strncpy (exp, target);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_STPCPY:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_stpcpy (exp, target, mode);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_MEMCPY:
>>> +    case BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp)
>>> +         && fcode == BUILT_IN_MEMCPY)
>>> +       break;
>>>        target = expand_builtin_memcpy (exp, target);
>>>        if (target)
>>> -       return target;
>>> +       {
>>> +         /* We need to set returned bounds for instrumented
>>> +            calls.  */
>>> +         if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +           {
>>> +             rtx bnd = force_reg (BNDmode,
>>> +                                  expand_normal (CALL_EXPR_ARG (orig_exp, 
>>> 1)));
>>> +             target = chkp_join_splitted_slot (target, bnd);
>>> +           }
>>> +         return target;
>>> +       }
>>>        break;
>>>
>>>      case BUILT_IN_MEMPCPY:
>>> +      case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK:
>>> +       if (CALL_WITH_BOUNDS_P (orig_exp)
>>> +           && fcode == BUILT_IN_MEMPCPY)
>>> +       break;
>>>        target = expand_builtin_mempcpy (exp, target, mode);
>>>        if (target)
>>> -       return target;
>>> +       {
>>> +         /* We need to set returned bounds for instrumented
>>> +            calls.  */
>>> +         if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +           {
>>> +             rtx bnd = force_reg (BNDmode,
>>> +                                  expand_normal (CALL_EXPR_ARG (orig_exp, 
>>> 1)));
>>> +             target = chkp_join_splitted_slot (target, bnd);
>>> +           }
>>> +         return target;
>>> +       }
>>>        break;
>>>
>>>      case BUILT_IN_MEMSET:
>>> +    case BUILT_IN_CHKP_MEMSET_NOBND_NOCHK:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp)
>>> +         && fcode == BUILT_IN_MEMSET)
>>> +       break;
>>>        target = expand_builtin_memset (exp, target, mode);
>>>        if (target)
>>> -       return target;
>>> +       {
>>> +         /* We need to set returned bounds for instrumented
>>> +            calls.  */
>>> +         if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +           {
>>> +             rtx bnd = force_reg (BNDmode,
>>> +                                  expand_normal (CALL_EXPR_ARG (orig_exp, 
>>> 1)));
>>> +             target = chkp_join_splitted_slot (target, bnd);
>>> +           }
>>> +         return target;
>>> +       }
>>>        break;
>>>
>>>      case BUILT_IN_BZERO:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_bzero (exp);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_STRCMP:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_strcmp (exp, target);
>>>        if (target)
>>>         return target;
>>>        break;
>>>
>>>      case BUILT_IN_STRNCMP:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_strncmp (exp, target, mode);
>>>        if (target)
>>>         return target;
>>> @@ -6207,6 +6324,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>
>>>      case BUILT_IN_BCMP:
>>>      case BUILT_IN_MEMCMP:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_memcmp (exp, target, mode);
>>>        if (target)
>>>         return target;
>>> @@ -6588,14 +6707,17 @@ expand_builtin (tree exp, rtx target, rtx 
>>> subtarget, enum machine_mode mode,
>>>
>>>         /* If this is turned into an external library call, the weak 
>>> parameter
>>>            must be dropped to match the expected parameter list.  */
>>> -       nargs = call_expr_nargs (exp);
>>> +       nargs = call_expr_nargs (orig_exp);
>>>         vec_alloc (vec, nargs - 1);
>>> -       for (z = 0; z < 3; z++)
>>> -         vec->quick_push (CALL_EXPR_ARG (exp, z));
>>> -       /* Skip the boolean weak parameter.  */
>>> -       for (z = 4; z < 6; z++)
>>> -         vec->quick_push (CALL_EXPR_ARG (exp, z));
>>> -       exp = build_call_vec (TREE_TYPE (exp), CALL_EXPR_FN (exp), vec);
>>> +       for (z = 0; z < nargs; z++)
>>> +         /* Skip the boolean weak parameter.  */
>>> +         if ((!CALL_WITH_BOUNDS_P (orig_exp) && z == 3)
>>> +             || (CALL_WITH_BOUNDS_P (orig_exp) && z == 5))
>>> +           continue;
>>> +         else
>>> +           vec->quick_push (CALL_EXPR_ARG (orig_exp, z));
>>> +       orig_exp = build_call_vec (TREE_TYPE (orig_exp),
>>> +                                  CALL_EXPR_FN (orig_exp), vec);
>>>         break;
>>>        }
>>>
>>> @@ -6819,6 +6941,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>      case BUILT_IN_MEMPCPY_CHK:
>>>      case BUILT_IN_MEMMOVE_CHK:
>>>      case BUILT_IN_MEMSET_CHK:
>>> +      if (CALL_WITH_BOUNDS_P (orig_exp))
>>> +       break;
>>>        target = expand_builtin_memory_chk (exp, target, mode, fcode);
>>>        if (target)
>>>         return target;
>>> @@ -6873,7 +6997,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>      case BUILT_IN_CHKP_GET_PTR_UBOUND:
>>>        /* We allow user CHKP builtins if Pointer Bounds
>>>          Checker is off.  */
>>> -      if (!flag_check_pointer_bounds)
>>> +      if (!chkp_function_instrumented_p (current_function_decl))
>>>         {
>>>           if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS
>>>               || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS
>>> @@ -6911,7 +7035,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, 
>>> enum machine_mode mode,
>>>
>>>    /* The switch statement above can drop through to cause the function
>>>       to be called normally.  */
>>> -  return expand_call (exp, target, ignore);
>>> +  return expand_call (orig_exp, target, ignore);
>>>  }
>>>
>>>  /* Determine whether a tree node represents a call to a built-in

Reply via email to