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. 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)