Ping
2014-06-11 18:00 GMT+04:00 Ilya Enkovich <enkovich....@gmail.com>: > Hi, > > This patch adds i386 target hooks for Pointer Bounds Checker. > > Bootstrapped and tested on linux-x86_64. > > Thanks, > Ilya > -- > gcc/ > > 2014-06-11 Ilya Enkovich <ilya.enkov...@intel.com> > > * config/i386/i386.c: Include tree-iterator.h. > (ix86_function_value_bounds): New. > (ix86_builtin_mpx_function): New. > (ix86_load_bounds): New. > (ix86_store_bounds): New. > (ix86_load_returned_bounds): New. > (ix86_store_returned_bounds): New. > (ix86_fn_abi_va_list_bounds_size): New. > (ix86_mpx_bound_mode): New. > (ix86_make_bounds_constant): New. > (ix86_initialize_bounds): > (TARGET_LOAD_BOUNDS_FOR_ARG): New. > (TARGET_STORE_BOUNDS_FOR_ARG): New. > (TARGET_LOAD_RETURNED_BOUNDS): New. > (TARGET_STORE_RETURNED_BOUNDS): New. > (TARGET_CHKP_BOUND_MODE): New. > (TARGET_BUILTIN_CHKP_FUNCTION): New. > (TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE): New. > (TARGET_CHKP_FUNCTION_VALUE_BOUNDS): New. > (TARGET_CHKP_MAKE_BOUNDS_CONSTANT): New. > (TARGET_CHKP_INITIALIZE_BOUNDS): New. > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index ac79231..dac83d0 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see > #include "context.h" > #include "pass_manager.h" > #include "target-globals.h" > +#include "tree-iterator.h" > #include "tree-chkp.h" > #include "rtl-chkp.h" > > @@ -7971,6 +7972,39 @@ ix86_function_value (const_tree valtype, const_tree > fntype_or_decl, > return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode); > } > > +static rtx > +ix86_function_value_bounds (const_tree valtype, > + const_tree fntype_or_decl ATTRIBUTE_UNUSED, > + bool outgoing ATTRIBUTE_UNUSED) > +{ > + rtx res = NULL_RTX; > + > + if (BOUNDED_TYPE_P (valtype)) > + res = gen_rtx_REG (BNDmode, FIRST_BND_REG); > + else if (chkp_type_has_pointer (valtype)) > + { > + bitmap slots = chkp_find_bound_slots (valtype); > + rtx bounds[2]; > + bitmap_iterator bi; > + unsigned i, bnd_no = 0; > + > + EXECUTE_IF_SET_IN_BITMAP (slots, 0, i, bi) > + { > + rtx reg = gen_rtx_REG (BNDmode, FIRST_BND_REG + bnd_no); > + rtx offs = GEN_INT (i * POINTER_SIZE / BITS_PER_UNIT); > + gcc_assert (bnd_no < 2); > + bounds[bnd_no++] = gen_rtx_EXPR_LIST (VOIDmode, reg, offs); > + } > + > + res = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (bnd_no, bounds)); > + BITMAP_FREE (slots); > + } > + else > + res = NULL_RTX; > + > + return res; > +} > + > /* Pointer function arguments and return values are promoted to > word_mode. */ > > @@ -36620,6 +36654,173 @@ static tree ix86_get_builtin (enum ix86_builtins > code) > return NULL_TREE; > } > > +/* Return function decl for target specific builtin > + for given MPX builtin passed i FCODE. */ > +static tree > +ix86_builtin_mpx_function (unsigned fcode) > +{ > + switch (fcode) > + { > + case BUILT_IN_CHKP_BNDMK: > + return ix86_builtins[IX86_BUILTIN_BNDMK]; > + > + case BUILT_IN_CHKP_BNDSTX: > + return ix86_builtins[IX86_BUILTIN_BNDSTX]; > + > + case BUILT_IN_CHKP_BNDLDX: > + return ix86_builtins[IX86_BUILTIN_BNDLDX]; > + > + case BUILT_IN_CHKP_BNDCL: > + return ix86_builtins[IX86_BUILTIN_BNDCL]; > + > + case BUILT_IN_CHKP_BNDCU: > + return ix86_builtins[IX86_BUILTIN_BNDCU]; > + > + case BUILT_IN_CHKP_BNDRET: > + return ix86_builtins[IX86_BUILTIN_BNDRET]; > + > + case BUILT_IN_CHKP_INTERSECT: > + return ix86_builtins[IX86_BUILTIN_BNDINT]; > + > + case BUILT_IN_CHKP_NARROW: > + return ix86_builtins[IX86_BUILTIN_BNDNARROW]; > + > + case BUILT_IN_CHKP_SIZEOF: > + return ix86_builtins[IX86_BUILTIN_SIZEOF]; > + > + case BUILT_IN_CHKP_EXTRACT_LOWER: > + return ix86_builtins[IX86_BUILTIN_BNDLOWER]; > + > + case BUILT_IN_CHKP_EXTRACT_UPPER: > + return ix86_builtins[IX86_BUILTIN_BNDUPPER]; > + > + default: > + return NULL_TREE; > + } > + > + gcc_unreachable (); > +} > + > +/* Load bounds PTR pointer value loaded from SLOT. > + if SLOT is a register then load bounds associated > + with special address identified by BND. > + > + Return loaded bounds. */ > +static rtx > +ix86_load_bounds (rtx slot, rtx ptr, rtx bnd) > +{ > + rtx addr = NULL; > + rtx reg; > + > + if (!ptr) > + { > + gcc_assert (MEM_P (slot)); > + ptr = copy_to_mode_reg (Pmode, slot); > + } > + > + if (!slot || REG_P (slot)) > + { > + if (slot) > + ptr = slot; > + > + gcc_assert (CONST_INT_P (bnd)); > + > + /* Here we have the case when more than four pointers are > + passed in registers. In this case we are out of bound > + registers and have to use bndldx to load bound. RA, > + RA - 8, etc. are used for address translation in bndldx. */ > + addr = plus_constant (Pmode, arg_pointer_rtx, -(INTVAL (bnd) + 1) * 8); > + } > + else if (MEM_P (slot)) > + { > + addr = XEXP (slot, 0); > + addr = force_reg (Pmode, addr); > + } > + else > + gcc_unreachable (); > + > + ptr = force_reg (Pmode, ptr); > + /* If ptr was a register originally then it may have > + mode other than Pmode. We need to extend in such > + case because bndldx may work only with Pmode regs. */ > + if (GET_MODE (ptr) != Pmode) > + { > + rtx ext = gen_rtx_ZERO_EXTEND (Pmode, ptr); > + ptr = gen_reg_rtx (Pmode); > + emit_move_insn (ptr, ext); > + } > + > + reg = gen_reg_rtx (BNDmode); > + emit_insn (TARGET_64BIT > + ? gen_bnd64_ldx (reg, addr, ptr) > + : gen_bnd32_ldx (reg, addr, ptr)); > + > + return reg; > +} > + > +/* Store bounds BOUNDS for PTR pointer value stored in > + specified ADDR. If ADDR is a register then TO identifies > + which special address to use for bounds store. */ > +static void > +ix86_store_bounds (rtx ptr, rtx addr, rtx bounds, rtx to) > +{ > + if (!ptr) > + { > + gcc_assert (MEM_P (addr)); > + ptr = copy_to_mode_reg (Pmode, addr); > + } > + > + if (!addr || REG_P (addr)) > + { > + gcc_assert (CONST_INT_P (to)); > + addr = plus_constant (Pmode, stack_pointer_rtx, -(INTVAL (to) + 1) * > 8); > + } > + else if (MEM_P (addr)) > + addr = XEXP (addr, 0); > + else > + gcc_unreachable (); > + > + /* Should we also ignore integer modes of incorrect size?. */ > + ptr = force_reg (Pmode, ptr); > + addr = force_reg (Pmode, addr); > + > + /* Avoid registers which connot be used as index. */ > + if (!index_register_operand (ptr, Pmode)) > + { > + rtx temp = gen_reg_rtx (Pmode); > + emit_move_insn (temp, ptr); > + ptr = temp; > + } > + > + gcc_assert (POINTER_BOUNDS_MODE_P (GET_MODE (bounds))); > + bounds = force_reg (GET_MODE (bounds), bounds); > + > + emit_insn (TARGET_64BIT > + ? gen_bnd64_stx (addr, ptr, bounds) > + : gen_bnd32_stx (addr, ptr, bounds)); > +} > + > +/* Load and return bounds returned by function in SLOT. */ > +static rtx > +ix86_load_returned_bounds (rtx slot) > +{ > + rtx res; > + > + gcc_assert (REG_P (slot)); > + res = gen_reg_rtx (BNDmode); > + emit_move_insn (res, slot); > + > + return res; > +} > + > +/* Store BOUNDS returned by function into SLOT. */ > +static void > +ix86_store_returned_bounds (rtx slot, rtx bounds) > +{ > + gcc_assert (REG_P (slot)); > + emit_move_insn (slot, bounds); > +} > + > /* Returns a function decl for a vectorized version of the builtin function > with builtin function code FN and the result vector type TYPE, or > NULL_TREE > if it is not available. */ > @@ -45796,6 +45997,22 @@ ix86_fn_abi_va_list (tree fndecl) > return sysv_va_list_type_node; > } > > +/* This function returns size of bounds for the calling abi > + specific va_list node. */ > + > +static tree > +ix86_fn_abi_va_list_bounds_size (tree fndecl) > +{ > + if (!TARGET_64BIT) > + return integer_zero_node; > + gcc_assert (fndecl != NULL_TREE); > + > + if (ix86_function_abi ((const_tree) fndecl) == MS_ABI) > + return integer_zero_node; > + else > + return TYPE_SIZE (sysv_va_list_type_node); > +} > + > /* Returns the canonical va_list type specified by TYPE. If there > is no valid TYPE provided, it return NULL_TREE. */ > > @@ -47246,6 +47463,61 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree > *clear, tree *update) > atomic_feraiseexcept_call); > } > > +static enum machine_mode > +ix86_mpx_bound_mode () > +{ > + /* Do not support pointer checker if MPX > + is not enabled. */ > + if (!TARGET_MPX) > + { > + if (flag_check_pointer_bounds) > + warning (0, "Pointer Checker requires MPX support on this target." > + " Use -mmpx options to enable MPX."); > + return VOIDmode; > + } > + > + return BNDmode; > +} > + > +static tree > +ix86_make_bounds_constant (HOST_WIDE_INT lb, HOST_WIDE_INT ub) > +{ > + tree low = lb ? build_minus_one_cst (pointer_sized_int_node) > + : build_zero_cst (pointer_sized_int_node); > + tree high = ub ? build_zero_cst (pointer_sized_int_node) > + : build_minus_one_cst (pointer_sized_int_node); > + > + /* This function is supposed to be used to create zero and > + none bounds only. */ > + gcc_assert (lb == 0 || lb == -1); > + gcc_assert (ub == 0 || ub == -1); > + > + return build_complex (NULL, low, high); > +} > + > +static int > +ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts) > +{ > + tree size_ptr = build_pointer_type (size_type_node); > + tree lhs, modify, var_p; > + > + ub = build1 (BIT_NOT_EXPR, size_type_node, ub); > + var_p = build1 (CONVERT_EXPR, size_ptr, > + build_fold_addr_expr (var)); > + > + lhs = build1 (INDIRECT_REF, size_type_node, var_p); > + modify = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, lb); > + append_to_statement_list (modify, stmts); > + > + lhs = build1 (INDIRECT_REF, size_type_node, > + build2 (POINTER_PLUS_EXPR, size_ptr, var_p, > + TYPE_SIZE_UNIT (size_type_node))); > + modify = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, ub); > + append_to_statement_list (modify, stmts); > + > + return 2; > +} > + > /* Initialize the GCC target structure. */ > #undef TARGET_RETURN_IN_MEMORY > #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory > @@ -47642,6 +47914,36 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree > *clear, tree *update) > #define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ > ix86_float_exceptions_rounding_supported_p > > +#undef TARGET_LOAD_BOUNDS_FOR_ARG > +#define TARGET_LOAD_BOUNDS_FOR_ARG ix86_load_bounds > + > +#undef TARGET_STORE_BOUNDS_FOR_ARG > +#define TARGET_STORE_BOUNDS_FOR_ARG ix86_store_bounds > + > +#undef TARGET_LOAD_RETURNED_BOUNDS > +#define TARGET_LOAD_RETURNED_BOUNDS ix86_load_returned_bounds > + > +#undef TARGET_STORE_RETURNED_BOUNDS > +#define TARGET_STORE_RETURNED_BOUNDS ix86_store_returned_bounds > + > +#undef TARGET_CHKP_BOUND_MODE > +#define TARGET_CHKP_BOUND_MODE ix86_mpx_bound_mode > + > +#undef TARGET_BUILTIN_CHKP_FUNCTION > +#define TARGET_BUILTIN_CHKP_FUNCTION ix86_builtin_mpx_function > + > +#undef TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE > +#define TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE ix86_fn_abi_va_list_bounds_size > + > +#undef TARGET_CHKP_FUNCTION_VALUE_BOUNDS > +#define TARGET_CHKP_FUNCTION_VALUE_BOUNDS ix86_function_value_bounds > + > +#undef TARGET_CHKP_MAKE_BOUNDS_CONSTANT > +#define TARGET_CHKP_MAKE_BOUNDS_CONSTANT ix86_make_bounds_constant > + > +#undef TARGET_CHKP_INITIALIZE_BOUNDS > +#define TARGET_CHKP_INITIALIZE_BOUNDS ix86_initialize_bounds > + > struct gcc_target targetm = TARGET_INITIALIZER; > > #include "gt-i386.h"