;;
arm*-*-*)
cpu_type=arm
- extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+ extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o aarch-bti-insert.o"
extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
target_type_format_char='%'
c_target_objs="arm-c.o"
&& known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
}
+/* Only used by the arm backend. */
+void aarch_bti_arch_check (void)
+{}
+
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
bool
aarch_bti_enabled (void)
/* opt_pass methods: */
virtual bool gate (function *)
{
- return aarch_bti_enabled ();
+ if (aarch_bti_enabled ())
+ {
+ aarch_bti_arch_check ();
+ return true;
+ }
+ return false;
}
virtual unsigned int execute (function *)
extern int arm_no_early_mul_dep (rtx, rtx);
extern int arm_no_early_store_addr_dep (rtx, rtx);
extern bool arm_rtx_shift_left_p (rtx);
+extern void aarch_bti_arch_check (void);
extern bool aarch_bti_enabled (void);
extern bool aarch_bti_j_insn_p (rtx_insn *);
extern bool aarch_pac_insn_p (rtx);
--- /dev/null
+/* Arm-specific passes declarations.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ Contributed by Arm Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
#include "sbitmap.h"
+rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+
extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *);
extern int use_return_insn (int, rtx);
extern bool use_simple_return_p (void);
&& !crtl->is_leaf));
}
+/* Raise an error if the current target arch is not bti compatible. */
+void aarch_bti_arch_check (void)
+{
+ if (!arm_arch8m_main)
+ error ("This architecture does not support branch protection instructions");
+}
+
/* Return TRUE if Branch Target Identification Mechanism is enabled. */
-static bool
-aarch_bti_enabled ()
+bool
+aarch_bti_enabled (void)
+{
+ return aarch_enable_bti != 0;
+}
+
+/* Check if INSN is a BTI J insn. */
+bool
+aarch_bti_j_insn_p (rtx_insn *insn)
+{
+ if (!insn || !INSN_P (insn))
+ return false;
+
+ rtx pat = PATTERN (insn);
+ return GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == VUNSPEC_BTI_NOP;
+}
+
+/* Check if X (or any sub-rtx of X) is a PACIASP/PACIBSP instruction. */
+bool
+aarch_pac_insn_p (rtx x)
{
+ if (!x || !INSN_P (x))
+ return false;
+
+ rtx pat = PATTERN (x);
+
+ if (GET_CODE (pat) == SET)
+ {
+ rtx tmp = XEXP (pat, 1);
+ if (tmp
+ && ((GET_CODE (tmp) == UNSPEC
+ && XINT (tmp, 1) == UNSPEC_PAC_NOP)
+ || (GET_CODE (tmp) == UNSPEC_VOLATILE
+ && XINT (tmp, 1) == VUNSPEC_PACBTI_NOP)))
+ return true;
+ }
+
return false;
}
+ /* Target specific mapping for aarch_gen_bti_c and aarch_gen_bti_j.
+ For Arm, both of these map to a simple BTI instruction. */
+
+rtx
+aarch_gen_bti_c (void)
+{
+ return gen_bti_nop ();
+}
+
+rtx
+aarch_gen_bti_j (void)
+{
+ return gen_bti_nop ();
+}
+
/* Implement TARGET_SCHED_CAN_SPECULATE_INSN. Return true if INSN can be
scheduled for speculative execution. Reject the long-running division
and square-root instructions. */
"aut\t%|ip, %|lr, %|sp"
[(set_attr "conds" "unconditional")])
+(define_insn "bti_nop"
+ [(unspec_volatile [(const_int 0)] VUNSPEC_BTI_NOP)]
+ "arm_arch8m_main"
+ "bti"
+ [(set_attr "conds" "unconditional")
+ (set_attr "type" "nop")])
+
;; Vector bits common to IWMMXT, Neon and MVE
(include "vec-common.md")
;; Load the Intel Wireless Multimedia Extension patterns
arm-common.o: arm-cpu-cdata.h
driver-arm.o: arm-native.h
+
+PASSES_EXTRA += $(srcdir)/config/arm/arm-passes.def
+
+aarch-bti-insert.o: $(srcdir)/config/arm/aarch-bti-insert.cc \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
+ dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
+ output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \
+ $(CONTEXT_H) $(TREE_PASS_H) regrename.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/arm/aarch-bti-insert.cc
; instruction.
VUNSPEC_PACBTI_NOP ; Represents PAC signing LR + valid landing pad
VUNSPEC_AUT_NOP ; Represents PAC verifying LR
+ VUNSPEC_BTI_NOP ; Represent BTI
])
;; Enumerators for NEON unspecs.
--- /dev/null
+/* Check that GCC does bti instruction. */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+int
+main (void)
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler "bti" } } */
--- /dev/null
+/* { dg-do compile } */
+/* -Os to create jump table. */
+/* { dg-options "-Os" } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mthumb -mfloat-abi=softfp -mbranch-protection=bti --save-temps" } */
+
+extern int f1 (void);
+extern int f2 (void);
+extern int f3 (void);
+extern int f4 (void);
+extern int f5 (void);
+extern int f6 (void);
+extern int f7 (void);
+extern int f8 (void);
+extern int f9 (void);
+extern int f10 (void);
+
+int (*ptr) (void);
+
+int
+f_jump_table (int y, int n)
+{
+ int i;
+ for (i = 0; i < n ;i ++)
+ {
+ switch (y)
+ {
+ case 0 : ptr = f1; break;
+ case 1 : ptr = f2; break;
+ case 2 : ptr = f3; break;
+ case 3 : ptr = f4; break;
+ case 4 : ptr = f5; break;
+ case 5 : ptr = f6; break;
+ case 6 : ptr = f7; break;
+ case 7 : ptr = f8; break;
+ case 8 : ptr = f9; break;
+ case 9 : ptr = f10; break;
+ default: break;
+ }
+ y += ptr ();
+ }
+ return (y == 0)? y+1:4;
+}
+
+int
+f_label_address ()
+{
+ static void * addr = &&lab1;
+ goto *addr;
+lab1:
+ addr = &&lab2;
+ return 1;
+lab2:
+ addr = &&lab1;
+ return 2;
+}
+
+/* { dg-final { scan-assembler-times "bti" 15 } } */