From patchwork Wed Jun 11 14:03:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 358682 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 91FCE1400E1 for ; Thu, 12 Jun 2014 00:03:45 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=MEq7tjaHqZckRcdFytbKuq78zzGeUnCc3oxdeCOESKMjCLb9gbYdv nLfXxcEhy0JsrVE8j4aLOB/Rn11t/wh8ZZ2Xdr4gHaQRnmLi0E+MGDA4NkGPCRKb ejRvHPtXi4xTl76NlJP8tu/f1cHZRozO9685fR0fYGi7sqR2Py7HRo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=tX3ri/xUZzh59Tdqg+JLHbbCc+w=; b=gdEDGbwGP8f3UYDoVlCC 7jdWjzX/hK2Qks4T+D1TyLbVUlWTfuW+dZhzR+ZYYSItSxUCBsBgvC88JvR2jlpa 9piNwhVN9LfF8tM8lehHeHasU42xum7L3NHq/FNaH0GRZggjF2uER9YpF8lCl8oI EXPKzE8lIsWnZlNTgLQQwaQ= Received: (qmail 24916 invoked by alias); 11 Jun 2014 14:03:38 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 24899 invoked by uid 89); 11 Jun 2014 14:03:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f49.google.com Received: from mail-pa0-f49.google.com (HELO mail-pa0-f49.google.com) (209.85.220.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 11 Jun 2014 14:03:30 +0000 Received: by mail-pa0-f49.google.com with SMTP id lj1so1067648pab.22 for ; Wed, 11 Jun 2014 07:03:28 -0700 (PDT) X-Received: by 10.66.162.74 with SMTP id xy10mr14376019pab.4.1402495408195; Wed, 11 Jun 2014 07:03:28 -0700 (PDT) Received: from msticlxl57.ims.intel.com ([192.55.54.40]) by mx.google.com with ESMTPSA id cj1sm29837609pac.40.2014.06.11.07.03.26 for (version=TLSv1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 11 Jun 2014 07:03:27 -0700 (PDT) Date: Wed, 11 Jun 2014 18:03:21 +0400 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [PATCH, i386, Pointer Bounds Checker 33/x] MPX ABI Message-ID: <20140611140321.GH17894@msticlxl57.ims.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Hi, This patch adds MPX ABI support for i386 target. Bootstrapped and tested on linux-x86_64. Thanks, Ilya --- gcc/ 2014-06-11 Ilya Enkovich * 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 dac83d0..a67e6e7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3693,6 +3693,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); @@ -6170,10 +6173,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 @@ -7108,11 +7116,13 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode, and data type TYPE. (TYPE is null for libcalls where that information may not be available.) */ -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) { + int res = 0; + switch (mode) { default: @@ -7130,7 +7140,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; @@ -7201,36 +7212,42 @@ 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) { - int int_nregs, sse_nregs; + int int_nregs, sse_nregs, exam; /* 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; + + 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; } 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) { @@ -7242,7 +7259,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 @@ -7255,6 +7274,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); @@ -7265,12 +7285,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. @@ -7511,17 +7570,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; } @@ -7777,6 +7850,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: @@ -7953,7 +8029,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); @@ -8122,6 +8201,9 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) #else const enum machine_mode mode = type_natural_mode (type, NULL, true); + if (POINTER_BOUNDS_TYPE_P (type)) + return false; + if (TARGET_64BIT) { if (ix86_function_type_abi (fntype) == MS_ABI) @@ -15380,7 +15462,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; @@ -24964,10 +25046,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); @@ -45839,9 +45943,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 e0ced33..759d1f8 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1645,6 +1645,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 5fd556b..fb9f8e3 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -193,6 +193,7 @@ UNSPEC_BNDCU UNSPEC_BNDCN UNSPEC_MPX_FENCE + UNSPEC_BNDRET ]) (define_c_enum "unspecv" [ @@ -11481,7 +11482,9 @@ (define_insn "*call_value" [(set (match_operand 0) (call (mem:QI (match_operand:W 1 "call_insn_operand" "zw")) - (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")]) @@ -11489,7 +11492,9 @@ (define_insn "*sibcall_value" [(set (match_operand 0) (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uz")) - (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")]) @@ -11499,6 +11504,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw")) (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]);" @@ -11522,6 +11529,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lzm")) (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")))] @@ -11533,6 +11542,8 @@ [(set (match_operand 0) (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz")) (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 e4c5d21..8cb15a2 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -611,14 +611,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;