On 18 Sep 21:54, Uros Bizjak wrote: > Hello! > > > 2014-06-11 Ilya Enkovich <ilya.enkov...@intel.com> > > > > * config/i386/i386.c (ix86_option_override_internal): Do not > > support x32 with MPX. > > is not available. > > (init_cumulative_args): Init stdarg, bnd_regno, bnds_in_bt > > and force_bnd_pass. > > (function_arg_advance_32): Return number of used integer > > registers. > > (function_arg_advance_64): Likewise. > > (function_arg_advance_ms_64): Likewise. > > (ix86_function_arg_advance): Handle pointer bounds. > > (ix86_function_arg): Likewise. > > (ix86_function_value_regno_p): Mark fisrt bounds registers as > > possible function value. > > (ix86_function_value_1): Handle pointer bounds type/mode > > (ix86_return_in_memory): Likewise. > > (ix86_print_operand): Analyse insn to decide abounf"bnd" prefix. > > (ix86_expand_call): Generate returned bounds. > > (ix86_bnd_prefixed_insn_p): Check if we have instrumented call > > or function. > > * config/i386/i386.h (ix86_args): Add bnd_regno, bnds_in_bt, > > force_bnd_pass and stdarg fields. > > * config/i386/i386.md (UNSPEC_BNDRET): New. > > (*call_value): Add returned bounds. > > (*sibcall_value): Likewise. > > (*call_value_rex64_ms_sysv): Likewise. > > (*call_value_pop): Likewise. > > (*sibcall_value_pop): Likewise. > > * config/i386/predicates.md (call_rex64_ms_sysv_operation): Adjust > > to changed call patterns. > > > -static void > > +static int > > function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode, > > const_tree type, HOST_WIDE_INT bytes, > > HOST_WIDE_INT words) > > Please also update function comments when function is changed. A > couple of places. > > > + exam = examine_argument (mode, type, 0, &int_nregs, &sse_nregs); > > > > - if (examine_argument (mode, type, 0, &int_nregs, &sse_nregs) > > + if (exam > > && sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs) > > { > > cum->nregs -= int_nregs; > > cum->sse_nregs -= sse_nregs; > > cum->regno += int_nregs; > > cum->sse_regno += sse_nregs; > > + return int_nregs; > > Please note that examine_argument was changed recently to return true > if argument is to be passed in memory. The patch doesn't reflect that, > please update the patch. > > Uros.
Here is an updated version of this patch. Thanks, Ilya -- 2014-09-19 Ilya Enkovich <ilya.enkov...@intel.com> * config/i386/i386.c (ix86_option_override_internal): Do not support x32 with MPX. is not available. (init_cumulative_args): Init stdarg, bnd_regno, bnds_in_bt and force_bnd_pass. (function_arg_advance_32): Return number of used integer registers. (function_arg_advance_64): Likewise. (function_arg_advance_ms_64): Likewise. (ix86_function_arg_advance): Handle pointer bounds. (ix86_function_arg): Likewise. (ix86_function_value_regno_p): Mark fisrt bounds registers as possible function value. (ix86_function_value_1): Handle pointer bounds type/mode (ix86_return_in_memory): Likewise. (ix86_print_operand): Analyse insn to decide abounf"bnd" prefix. (ix86_expand_call): Generate returned bounds. (ix86_bnd_prefixed_insn_p): Check if we have instrumented call or function. * config/i386/i386.h (ix86_args): Add bnd_regno, bnds_in_bt, force_bnd_pass and stdarg fields. * config/i386/i386.md (UNSPEC_BNDRET): New. (*call_value): Add returned bounds. (*sibcall_value): Likewise. (*call_value_rex64_ms_sysv): Likewise. (*call_value_pop): Likewise. (*sibcall_value_pop): Likewise. * config/i386/predicates.md (call_rex64_ms_sysv_operation): Adjust to changed call patterns. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4a58190..da7ffa8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3712,6 +3712,9 @@ ix86_option_override_internal (bool main_args_p, if (TARGET_X32 && (opts->x_ix86_isa_flags & OPTION_MASK_ISA_MPX)) error ("Intel MPX does not support x32"); + if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX)) + error ("Intel MPX does not support x32"); + if (!strcmp (opts->x_ix86_arch_string, "generic")) error ("generic CPU can be used only for %stune=%s %s", prefix, suffix, sw); @@ -6198,10 +6201,15 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ FIXME: once typesytem is fixed, we won't need this code anymore. */ if (i && i->local && i->can_change_signature) fntype = TREE_TYPE (fndecl); + cum->stdarg = fntype ? stdarg_p (fntype) : false; cum->maybe_vaarg = (fntype ? (!prototype_p (fntype) || stdarg_p (fntype)) : !libname); + cum->bnd_regno = FIRST_BND_REG; + cum->bnds_in_bt = 0; + cum->force_bnd_pass = 0; + if (!TARGET_64BIT) { /* If there are variable arguments, then we won't pass anything @@ -7136,13 +7144,17 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode, /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. (TYPE is null for libcalls where that information - may not be available.) */ + may not be available.) -static void + Return a number of integer regsiters advanced over. */ + +static int function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type, HOST_WIDE_INT bytes, HOST_WIDE_INT words) { + int res = 0; + switch (mode) { default: @@ -7160,7 +7172,8 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->words += words; cum->nregs -= words; cum->regno += words; - + if (cum->nregs >= 0) + res = words; if (cum->nregs <= 0) { cum->nregs = 0; @@ -7231,9 +7244,11 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode, } break; } + + return res; } -static void +static int function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type, HOST_WIDE_INT words, bool named) { @@ -7242,7 +7257,7 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, /* Unnamed 512 and 256bit vector mode parameters are passed on stack. */ if (!named && (VALID_AVX512F_REG_MODE (mode) || VALID_AVX256_REG_MODE (mode))) - return; + return 0; if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs) && sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs) @@ -7251,16 +7266,18 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->sse_nregs -= sse_nregs; cum->regno += int_nregs; cum->sse_regno += sse_nregs; + return int_nregs; } else { int align = ix86_function_arg_boundary (mode, type) / BITS_PER_WORD; cum->words = (cum->words + align - 1) & ~(align - 1); cum->words += words; + return 0; } } -static void +static int function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, HOST_WIDE_INT bytes, HOST_WIDE_INT words) { @@ -7272,7 +7289,9 @@ function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, HOST_WIDE_INT bytes, { cum->nregs -= 1; cum->regno += 1; + return 1; } + return 0; } /* Update the data in CUM to advance over an argument of mode MODE and @@ -7285,6 +7304,7 @@ ix86_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, { CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); HOST_WIDE_INT bytes, words; + int nregs; if (mode == BLKmode) bytes = int_size_in_bytes (type); @@ -7295,12 +7315,51 @@ ix86_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, if (type) mode = type_natural_mode (type, NULL, false); + if ((type && POINTER_BOUNDS_TYPE_P (type)) + || POINTER_BOUNDS_MODE_P (mode)) + { + /* If we pass bounds in BT then just update remained bounds count. */ + if (cum->bnds_in_bt) + { + cum->bnds_in_bt--; + return; + } + + /* Update remained number of bounds to force. */ + if (cum->force_bnd_pass) + cum->force_bnd_pass--; + + cum->bnd_regno++; + + return; + } + + /* The first arg not going to Bounds Tables resets this counter. */ + cum->bnds_in_bt = 0; + /* For unnamed args we always pass bounds to avoid bounds mess when + passed and received types do not match. If bounds do not follow + unnamed arg, still pretend required number of bounds were passed. */ + if (cum->force_bnd_pass) + { + cum->bnd_regno += cum->force_bnd_pass; + cum->force_bnd_pass = 0; + } + if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) - function_arg_advance_ms_64 (cum, bytes, words); + nregs = function_arg_advance_ms_64 (cum, bytes, words); else if (TARGET_64BIT) - function_arg_advance_64 (cum, mode, type, words, named); + nregs = function_arg_advance_64 (cum, mode, type, words, named); else - function_arg_advance_32 (cum, mode, type, bytes, words); + nregs = function_arg_advance_32 (cum, mode, type, bytes, words); + + /* For stdarg we expect bounds to be passed for each value passed + in register. */ + if (cum->stdarg) + cum->force_bnd_pass = nregs; + /* For pointers passed in memory we expect bounds passed in Bounds + Table. */ + if (!nregs) + cum->bnds_in_bt = chkp_type_bounds_count (type); } /* Define where to put the arguments to a function. @@ -7541,17 +7600,31 @@ ix86_function_arg (cumulative_args_t cum_v, enum machine_mode omode, bytes = GET_MODE_SIZE (mode); words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - /* To simplify the code below, represent vector types with a vector mode - even if MMX/SSE are not active. */ - if (type && TREE_CODE (type) == VECTOR_TYPE) - mode = type_natural_mode (type, cum, false); - if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) - arg = function_arg_ms_64 (cum, mode, omode, named, bytes); - else if (TARGET_64BIT) - arg = function_arg_64 (cum, mode, omode, type, named); + if ((type && POINTER_BOUNDS_TYPE_P (type)) + || POINTER_BOUNDS_MODE_P (mode)) + { + if (cum->bnds_in_bt) + arg = NULL; + else if (cum->bnd_regno <= LAST_BND_REG) + arg = gen_rtx_REG (BNDmode, cum->bnd_regno); + else + arg = GEN_INT (cum->bnd_regno - LAST_BND_REG - 1); + } else - arg = function_arg_32 (cum, mode, omode, type, bytes, words); + { + /* To simplify the code below, represent vector types with a vector mode + even if MMX/SSE are not active. */ + if (type && TREE_CODE (type) == VECTOR_TYPE) + mode = type_natural_mode (type, cum, false); + + if (TARGET_64BIT && (cum ? cum->call_abi : ix86_abi) == MS_ABI) + arg = function_arg_ms_64 (cum, mode, omode, named, bytes); + else if (TARGET_64BIT) + arg = function_arg_64 (cum, mode, omode, type, named); + else + arg = function_arg_32 (cum, mode, omode, type, bytes, words); + } return arg; } @@ -7808,6 +7881,9 @@ ix86_function_value_regno_p (const unsigned int regno) case SI_REG: return TARGET_64BIT && ix86_abi != MS_ABI; + case FIRST_BND_REG: + return chkp_function_instrumented_p (current_function_decl); + /* Complex values are returned in %st(0)/%st(1) pair. */ case ST0_REG: case ST1_REG: @@ -7984,7 +8060,10 @@ ix86_function_value_1 (const_tree valtype, const_tree fntype_or_decl, fn = fntype_or_decl; fntype = fn ? TREE_TYPE (fn) : fntype_or_decl; - if (TARGET_64BIT && ix86_function_type_abi (fntype) == MS_ABI) + if ((valtype && POINTER_BOUNDS_TYPE_P (valtype)) + || POINTER_BOUNDS_MODE_P (mode)) + return gen_rtx_REG (BNDmode, FIRST_BND_REG); + else if (TARGET_64BIT && ix86_function_type_abi (fntype) == MS_ABI) return function_value_ms_64 (orig_mode, mode, valtype); else if (TARGET_64BIT) return function_value_64 (orig_mode, mode, valtype); @@ -8081,6 +8160,9 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) const enum machine_mode mode = type_natural_mode (type, NULL, true); HOST_WIDE_INT size; + if (POINTER_BOUNDS_TYPE_P (type)) + return false; + if (TARGET_64BIT) { if (ix86_function_type_abi (fntype) == MS_ABI) @@ -15404,7 +15486,7 @@ ix86_print_operand (FILE *file, rtx x, int code) return; case '!': - if (ix86_bnd_prefixed_insn_p (NULL_RTX)) + if (ix86_bnd_prefixed_insn_p (current_output_insn)) fputs ("bnd ", file); return; @@ -25000,10 +25082,32 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, } call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1); + if (retval) - call = gen_rtx_SET (VOIDmode, retval, call); + { + /* For instrumented code we may have GPR + BR in parallel but + it will confuse DF and we need to put each reg + under EXPR_LIST. */ + if (chkp_function_instrumented_p (current_function_decl)) + chkp_put_regs_to_expr_list (retval); + + call = gen_rtx_SET (VOIDmode, retval, call); + } vec[vec_len++] = call; + /* b0 and b1 registers hold bounds for returned value. */ + if (retval) + { + rtx b0 = gen_rtx_REG (BND64mode, FIRST_BND_REG); + rtx unspec0 = gen_rtx_UNSPEC (BND64mode, + gen_rtvec (1, b0), UNSPEC_BNDRET); + rtx b1 = gen_rtx_REG (BND64mode, FIRST_BND_REG + 1); + rtx unspec1 = gen_rtx_UNSPEC (BND64mode, + gen_rtvec (1, b1), UNSPEC_BNDRET); + vec[vec_len++] = gen_rtx_SET (BND64mode, b0, unspec0); + vec[vec_len++] = gen_rtx_SET (BND64mode, b1, unspec1); + } + if (pop) { pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop); @@ -46053,9 +46157,18 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2) bnd by default for current function. */ bool -ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED) +ix86_bnd_prefixed_insn_p (rtx insn) { - return false; + /* For call insns check special flag. */ + if (insn && CALL_P (insn)) + { + rtx call = get_call_rtx_from (insn); + if (call) + return CALL_EXPR_WITH_BOUNDS_P (call); + } + + /* All other insns are prefixed only if function is instrumented. */ + return chkp_function_instrumented_p (current_function_decl); } /* Calculate integer abs() using only SSE2 instructions. */ diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index a38c5d1..8f77343 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1655,6 +1655,10 @@ typedef struct ix86_args { int float_in_sse; /* Set to 1 or 2 for 32bit targets if SFmode/DFmode arguments should be passed in SSE registers. Otherwise 0. */ + int bnd_regno; /* next available bnd register number */ + int bnds_in_bt; /* number of bounds expected in BT. */ + int force_bnd_pass; /* number of bounds expected for stdarg arg. */ + int stdarg; /* Set to 1 if function is stdarg. */ enum calling_abi call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise MS_ABI for ms abi. */ } CUMULATIVE_ARGS; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index db22b06..0f3d555 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -194,6 +194,7 @@ UNSPEC_BNDCU UNSPEC_BNDCN UNSPEC_MPX_FENCE + UNSPEC_BNDRET ]) (define_c_enum "unspecv" [ @@ -11549,7 +11550,9 @@ (define_insn "*call_value" [(set (match_operand 0) (call (mem:QI (match_operand:W 1 "call_insn_operand" "<c>BwBz")) - (match_operand 2)))] + (match_operand 2))) + (set (reg:BND64 BND0_REG) (unspec [(reg:BND64 BND0_REG)] UNSPEC_BNDRET)) + (set (reg:BND64 BND1_REG) (unspec [(reg:BND64 BND1_REG)] UNSPEC_BNDRET))] "!SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" [(set_attr "type" "callv")]) @@ -11557,7 +11560,9 @@ (define_insn "*sibcall_value" [(set (match_operand 0) (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz")) - (match_operand 2)))] + (match_operand 2))) + (set (reg:BND64 BND0_REG) (unspec [(reg:BND64 BND0_REG)] UNSPEC_BNDRET)) + (set (reg:BND64 BND1_REG) (unspec [(reg:BND64 BND1_REG)] UNSPEC_BNDRET))] "SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" [(set_attr "type" "callv")]) @@ -11604,6 +11609,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rBwBz")) (match_operand 2))) + (set (reg:BND64 BND0_REG) (unspec [(reg:BND64 BND0_REG)] UNSPEC_BNDRET)) + (set (reg:BND64 BND1_REG) (unspec [(reg:BND64 BND1_REG)] UNSPEC_BNDRET)) (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])] "TARGET_64BIT && !SIBLING_CALL_P (insn)" "* return ix86_output_call_insn (insn, operands[1]);" @@ -11627,6 +11634,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz")) (match_operand 2))) + (set (reg:BND64 BND0_REG) (unspec [(reg:BND64 BND0_REG)] UNSPEC_BNDRET)) + (set (reg:BND64 BND1_REG) (unspec [(reg:BND64 BND1_REG)] UNSPEC_BNDRET)) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "immediate_operand" "i")))] @@ -11638,6 +11647,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "UBsBz")) (match_operand 2))) + (set (reg:BND64 BND0_REG) (unspec [(reg:BND64 BND0_REG)] UNSPEC_BNDRET)) + (set (reg:BND64 BND1_REG) (unspec [(reg:BND64 BND1_REG)] UNSPEC_BNDRET)) (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand:SI 3 "immediate_operand" "i")))] diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index da01c9a..9991bb2 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -631,14 +631,17 @@ (match_code "parallel") { unsigned creg_size = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers); + unsigned adop = GET_CODE (XVECEXP (op, 0, 0)) == SET + ? 4 + : 2; unsigned i; - if ((unsigned) XVECLEN (op, 0) != creg_size + 2) + if ((unsigned) XVECLEN (op, 0) != creg_size + adop) return false; for (i = 0; i < creg_size; i++) { - rtx elt = XVECEXP (op, 0, i+2); + rtx elt = XVECEXP (op, 0, i+adop); enum machine_mode mode; unsigned regno;