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)