Richard Sandiford <[email protected]> writes:
> Yury Khrustalev <[email protected]> writes:
>> From: Szabolcs Nagy <[email protected]>
>>
>> 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)