Richard Sandiford <richard.sandif...@arm.com> writes:
> Yury Khrustalev <yury.khrusta...@arm.com> writes:
>> From: Szabolcs Nagy <szabolcs.n...@arm.com>
>>
>> Add new builtins for GCS:
>>
>>   void *__builtin_aarch64_gcspr (void)
>>   uint64_t __builtin_aarch64_gcspopm (void)
>>   void *__builtin_aarch64_gcsss (void *)
>>
>> The builtins are always enabled, but should be used behind runtime
>> checks in case the target does not support GCS. They are thin
>> wrappers around the corresponding instructions.
>>
>> The GCS pointer is modelled with void * type (normal stores do not
>> work on GCS memory, but it is writable via the gcsss operation or
>> via GCSSTR if enabled so not const) and an entry on the GCS is
>> modelled with uint64_t (since it has fixed size and can be a token
>> that's not a pointer).
>>
>> gcc/ChangeLog:
>>
>>      * config/aarch64/aarch64-builtins.cc (enum aarch64_builtins): Add
>>      AARCH64_BUILTIN_GCSPR, AARCH64_BUILTIN_GCSPOPM, AARCH64_BUILTIN_GCSSS.
>>      (aarch64_init_gcs_builtins): New.
>>      (aarch64_general_init_builtins): Call aarch64_init_gcs_builtins.
>>      (aarch64_expand_gcs_builtin): New.
>>      (aarch64_general_expand_builtin): Call aarch64_expand_gcs_builtin.
>> ---
>>  gcc/config/aarch64/aarch64-builtins.cc | 78 ++++++++++++++++++++++++++
>>  1 file changed, 78 insertions(+)
>>
>> diff --git a/gcc/config/aarch64/aarch64-builtins.cc 
>> b/gcc/config/aarch64/aarch64-builtins.cc
>> index e693a14f4f3..6101f252bfd 100644
>> --- a/gcc/config/aarch64/aarch64-builtins.cc
>> +++ b/gcc/config/aarch64/aarch64-builtins.cc
>> @@ -878,6 +878,9 @@ enum aarch64_builtins
>>    AARCH64_PLIX,
>>    /* Armv8.9-A / Armv9.4-A builtins.  */
>>    AARCH64_BUILTIN_CHKFEAT,
>> +  AARCH64_BUILTIN_GCSPR,
>> +  AARCH64_BUILTIN_GCSPOPM,
>> +  AARCH64_BUILTIN_GCSSS,
>>    AARCH64_BUILTIN_MAX
>>  };
>>  
>> @@ -2240,6 +2243,29 @@ aarch64_init_fpsr_fpcr_builtins (void)
>>                                 AARCH64_BUILTIN_SET_FPSR64);
>>  }
>>  
>> +/* Add builtins for Guarded Control Stack instructions.  */
>> +
>> +static void
>> +aarch64_init_gcs_builtins (void)
>> +{
>> +  tree ftype;
>> +
>> +  ftype = build_function_type_list (ptr_type_node, NULL);
>> +  aarch64_builtin_decls[AARCH64_BUILTIN_GCSPR]
>> +    = aarch64_general_add_builtin ("__builtin_aarch64_gcspr", ftype,
>> +                               AARCH64_BUILTIN_GCSPR);
>> +
>> +  ftype = build_function_type_list (uint64_type_node, NULL);
>> +  aarch64_builtin_decls[AARCH64_BUILTIN_GCSPOPM]
>> +    = aarch64_general_add_builtin ("__builtin_aarch64_gcspopm", ftype,
>> +                               AARCH64_BUILTIN_GCSPOPM);
>> +
>> +  ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL);
>> +  aarch64_builtin_decls[AARCH64_BUILTIN_GCSSS]
>> +    = aarch64_general_add_builtin ("__builtin_aarch64_gcsss", ftype,
>> +                               AARCH64_BUILTIN_GCSSS);
>> +}
>> +
>>  /* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */
>>  
>>  void
>> @@ -2287,6 +2313,8 @@ aarch64_general_init_builtins (void)
>>      = aarch64_general_add_builtin ("__builtin_aarch64_chkfeat", 
>> ftype_chkfeat,
>>                                 AARCH64_BUILTIN_CHKFEAT);
>>  
>> +  aarch64_init_gcs_builtins ();
>> +
>>    if (in_lto_p)
>>      handle_arm_acle_h ();
>>  }
>> @@ -3381,6 +3409,51 @@ aarch64_expand_fpsr_fpcr_getter (enum insn_code 
>> icode, machine_mode mode,
>>    return op.value;
>>  }
>>  
>> +/* Expand GCS builtin EXP with code FCODE, putting the result
>> +   into TARGET.  If IGNORE is true the return value is ignored.  */
>> +
>> +rtx
>> +aarch64_expand_gcs_builtin (tree exp, rtx target, int fcode, int ignore)
>> +{
>> +  if (fcode == AARCH64_BUILTIN_GCSPR)
>> +    {
>> +      expand_operand op;
>> +      create_output_operand (&op, target, DImode);
>> +      expand_insn (CODE_FOR_aarch64_load_gcspr, 1, &op);
>> +      return op.value;
>> +    }
>> +  if (fcode == AARCH64_BUILTIN_GCSPOPM && ignore)
>> +    {
>> +      expand_insn (CODE_FOR_aarch64_gcspopm_xzr, 0, 0);
>> +      return target;
>> +    }
>> +  if (fcode == AARCH64_BUILTIN_GCSPOPM)
>> +    {
>> +      rtx tmp = gen_reg_rtx (DImode);
>> +      emit_move_insn (tmp, const0_rtx);
>> +      expand_operand ops[2];
>> +      create_output_operand (&ops[0], target, Pmode);
>> +      create_input_operand (&ops[1], tmp, Pmode);
>> +      expand_insn (CODE_FOR_aarch64_gcspopm, 2, ops);
>> +      return ops[0].value;
>> +    }
>
> Since the instruction use DImode rather than Pmode, we should probably
> do the same here.

Sorry, I had a brain fade and confused Pmode with ptr_mode.  Please
replace all instances of "Pmode" with "ptr_mode" below.

Thanks,
Richard

> Also, although it's not much of a simplification, it should be possible
> to pass const0_rtx directly to create_input_operand:
>
>   if (fcode == AARCH64_BUILTIN_GCSPOPM)
>     {
>       expand_operand ops[2];
>       create_output_operand (&ops[0], target, DImode);
>       create_input_operand (&ops[1], const0_rtx, DImode);
>       expand_insn (CODE_FOR_aarch64_gcspopm, 2, ops);
>       return gen_lowpart (Pmode, ops[0].value);
>     }
>
>> +  if (fcode == AARCH64_BUILTIN_GCSSS)
>> +    {
>> +      expand_operand opnd;
>> +      rtx arg = expand_normal (CALL_EXPR_ARG (exp, 0));
>> +      create_input_operand (&opnd, arg, Pmode);
>> +      expand_insn (CODE_FOR_aarch64_gcsss1, 1, &opnd);
>> +      expand_operand ops[2];
>> +      rtx tmp = gen_reg_rtx (DImode);
>> +      emit_move_insn (tmp, const0_rtx);
>> +      create_output_operand (&ops[0], target, Pmode);
>> +      create_input_operand (&ops[1], tmp, Pmode);
>> +      expand_insn (CODE_FOR_aarch64_gcsss2, 2, ops);
>> +      return ops[0].value;
>> +    }
>
> Similarly here:
>
>   if (fcode == AARCH64_BUILTIN_GCSSS)
>     {
>       expand_operand opnd;
>       rtx arg = expand_normal (CALL_EXPR_ARG (exp, 0));
>       arg = convert_modes (DImode, Pmode, arg, true);
>       create_input_operand (&opnd, arg, DImode);
>       expand_insn (CODE_FOR_aarch64_gcsss1, 1, &opnd);
>
>       expand_operand ops[2];
>       create_output_operand (&ops[0], target, DImode);
>       create_input_operand (&ops[1], const0_rtx, DImode);
>       expand_insn (CODE_FOR_aarch64_gcsss2, 2, ops);
>       return gen_lowpart (Pmode, ops[0].value);
>     }
>
> Thanks for splitting the instructions up btw.  The new version looks good.
>
> Richard
>
>> +  gcc_unreachable ();
>> +}
>> +
>>  /* Expand an expression EXP that calls built-in function FCODE,
>>     with result going to TARGET if that's convenient.  IGNORE is true
>>     if the result of the builtin is ignored.  */
>> @@ -3515,6 +3588,11 @@ aarch64_general_expand_builtin (unsigned int fcode, 
>> tree exp, rtx target,
>>      expand_insn (CODE_FOR_aarch64_chkfeat, 0, 0);
>>      return copy_to_reg (x16_reg);
>>        }
>> +
>> +    case AARCH64_BUILTIN_GCSPR:
>> +    case AARCH64_BUILTIN_GCSPOPM:
>> +    case AARCH64_BUILTIN_GCSSS:
>> +      return aarch64_expand_gcs_builtin (exp, target, fcode, ignore);
>>      }
>>  
>>    if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= 
>> AARCH64_SIMD_BUILTIN_MAX)

Reply via email to