From patchwork Tue Nov 19 20:48:46 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 292571 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)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 76E1A2C00E2 for ; Wed, 20 Nov 2013 07:49:53 +1100 (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=e8we2pFrT0bNCypOSzKSLBM7B3Jf+eUJTVr/85QIjSB88BhKP1zFs hsxpYD4F0blY6l6RF7eG58YB7hGQ24DimvnAm98eHUemMze5HToWvKyEc9TXsYHn 9oP/mMNooD2ISb4QBY4UMLSJxXGJAG+WC6rzAGjiMe3kV3UlKjAxf8= 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=cof7qmv3P21UExqevx6eZvmQIt0=; b=lOZ6YCKgnYSB2X5ntPC8 BaVFiJAUflRwSJqVGp8UvJse2Va5gnqXbPl+pY0QZLCn/jUs1XU1ePUS2xai7pZj J0yoLvm1ioRQDymDc/l3vE+jJf9dBcNthbmeYNlIJqxJkR+LlSta+Pr6H91pXrqC grfnIrLC1l15+oIbC4n0aXY= Received: (qmail 2124 invoked by alias); 19 Nov 2013 20:49:43 -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 2111 invoked by uid 89); 19 Nov 2013 20:49:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.6 required=5.0 tests=AWL, BAYES_99, FREEMAIL_FROM, RDNS_NONE, SPF_PASS, URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mail-pb0-f52.google.com Received: from Unknown (HELO mail-pb0-f52.google.com) (209.85.160.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 19 Nov 2013 20:49:40 +0000 Received: by mail-pb0-f52.google.com with SMTP id uo5so2424539pbc.39 for ; Tue, 19 Nov 2013 12:49:32 -0800 (PST) X-Received: by 10.68.101.225 with SMTP id fj1mr28011116pbb.8.1384894171860; Tue, 19 Nov 2013 12:49:31 -0800 (PST) Received: from msticlxl57.ims.intel.com ([192.55.54.41]) by mx.google.com with ESMTPSA id ie6sm6287484pbc.6.2013.11.19.12.49.30 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 19 Nov 2013 12:49:31 -0800 (PST) Date: Wed, 20 Nov 2013 00:48:46 +0400 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [PATCH, i386, MPX, 2/X] Pointers Checker [24/25] MPX ABI support Message-ID: <20131119204846.GV21297@msticlxl57.ims.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Hi, Here is a patch to support MPX ABI (http://software.intel.com/en-us/articles/linux-abi). Thanks, Ilya --- 2013-11-13 Ilya Enkovich * config/i386/i386.c (x86_64_reg_class): Add X86_64_BOUNDED_INTEGER_CLASS and X86_64_BOUNDED_INTEGERSI_CLASS. (ix86_return_pops_args): Pass function type to aggregate_value_p if function decl is not available. (init_cumulative_args): Initialize bound regs info and stdarg info. (merge_classes): Support X86_64_BOUNDED_INTEGER_CLASS and X86_64_BOUNDED_INTEGERSI_CLASS. (classify_argument): Use bounded classes for bounded types when Pointer Bounds Checker is on. (examine_argument): Support X86_64_BOUNDED_INTEGER_CLASS and X86_64_BOUNDED_INTEGERSI_CLASS. (construct_container): Likewise. (function_arg_advance_32): Support bound regs. (function_arg_advance_64): Likewise. (ix86_function_value_regno_p): Likewise. (function_value_64): Adjust construct_container call. (function_value_32): Add bound register for bounded values. (function_value_ms_64): Likewise. (return_in_memory_32): Adjust examine_argument call. (ix86_gimplify_va_arg): Adjust construct_container and examine_argument calls. (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_nregs, bnd_regno 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 d401c4f..1077168 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2195,6 +2195,9 @@ tree x86_mfence; of SSESF, SSEDF classes, that are basically SSE class, just gcc will use SF or DFmode move instead of DImode to avoid reformatting penalties. + X86_64_BOUNDED* classes are similar to integer classes but additionally + mean bounds should be passed for the argument. + Similarly we play games with INTEGERSI_CLASS to use cheaper SImode moves whenever possible (upper half does contain padding). */ enum x86_64_reg_class @@ -2209,7 +2212,9 @@ enum x86_64_reg_class X86_64_X87_CLASS, X86_64_X87UP_CLASS, X86_64_COMPLEX_X87_CLASS, - X86_64_MEMORY_CLASS + X86_64_MEMORY_CLASS, + X86_64_BOUNDED_INTEGER_CLASS, + X86_64_BOUNDED_INTEGERSI_CLASS }; #define MAX_CLASSES 4 @@ -3523,6 +3528,9 @@ ix86_option_override_internal (bool main_args_p, break; } + 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); @@ -5551,7 +5559,7 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size) return size; /* Lose any fake structure return argument if it is passed on the stack. */ - if (aggregate_value_p (TREE_TYPE (funtype), fundecl) + if (aggregate_value_p (TREE_TYPE (funtype), fundecl ? fundecl : funtype) && !ix86_keep_aggregate_return_pointer (funtype)) { int nregs = ix86_function_regparm (funtype, fundecl); @@ -5888,6 +5896,9 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ cum->nregs = (cum->call_abi == SYSV_ABI ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX); + + /* All bound registers are available for argument passing. */ + cum->bnd_nregs = LAST_BND_REG - FIRST_BND_REG + 1; } if (TARGET_SSE) { @@ -5913,6 +5924,7 @@ 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); @@ -5929,6 +5941,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ cum->warn_avx = 0; cum->warn_sse = 0; cum->warn_mmx = 0; + cum->bnd_nregs = 0; return; } @@ -5949,12 +5962,15 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ } else cum->nregs = ix86_function_regparm (fntype, fndecl); + cum->bnd_nregs = cum->nregs; } /* Set up the number of SSE registers used for passing SFmode and DFmode arguments. Warn for mismatching ABI. */ cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl, true); } + + cum->bnd_regno = FIRST_BND_REG; } /* Return the "natural" mode for TYPE. In most cases, this is just TYPE_MODE. @@ -6083,9 +6099,16 @@ merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) return X86_64_MEMORY_CLASS; /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ + /* Rule #4.1 If one of the classes is BOUNDED, the result is BOUNDED. */ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) return X86_64_INTEGERSI_CLASS; + if ((class1 == X86_64_BOUNDED_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) + || (class2 == X86_64_BOUNDED_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) + return X86_64_BOUNDED_INTEGERSI_CLASS; + if (class1 == X86_64_BOUNDED_INTEGER_CLASS || class1 == X86_64_BOUNDED_INTEGERSI_CLASS + || class2 == X86_64_BOUNDED_INTEGER_CLASS || class2 == X86_64_BOUNDED_INTEGERSI_CLASS) + return X86_64_BOUNDED_INTEGER_CLASS; if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) return X86_64_INTEGER_CLASS; @@ -6118,7 +6141,8 @@ merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) static int classify_argument (enum machine_mode mode, const_tree type, - enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset) + enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset, + bool stdarg) { HOST_WIDE_INT bytes = (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode); @@ -6211,7 +6235,7 @@ classify_argument (enum machine_mode mode, const_tree type, num = classify_argument (TYPE_MODE (type), type, subclasses, (int_bit_position (field) - + bit_offset) % 256); + + bit_offset) % 256, stdarg); if (!num) return 0; pos = (int_bit_position (field) @@ -6229,7 +6253,7 @@ classify_argument (enum machine_mode mode, const_tree type, { int num; num = classify_argument (TYPE_MODE (TREE_TYPE (type)), - TREE_TYPE (type), subclasses, bit_offset); + TREE_TYPE (type), subclasses, bit_offset, stdarg); if (!num) return 0; @@ -6260,7 +6284,7 @@ classify_argument (enum machine_mode mode, const_tree type, num = classify_argument (TYPE_MODE (TREE_TYPE (field)), TREE_TYPE (field), subclasses, - bit_offset); + bit_offset, stdarg); if (!num) return 0; for (i = 0; i < num; i++) @@ -6373,12 +6397,20 @@ classify_argument (enum machine_mode mode, const_tree type, if (size <= 32) { - classes[0] = X86_64_INTEGERSI_CLASS; + /* Pass bounds for pointers and unnamed integers. */ + classes[0] = chkp_function_instrumented_p (current_function_decl) + && ((type && BOUNDED_TYPE_P (type)) || stdarg) + ? X86_64_BOUNDED_INTEGERSI_CLASS + : X86_64_INTEGERSI_CLASS; return 1; } else if (size <= 64) { - classes[0] = X86_64_INTEGER_CLASS; + /* Pass bounds for pointers and unnamed integers. */ + classes[0] = chkp_function_instrumented_p (current_function_decl) + && ((type && BOUNDED_TYPE_P (type)) || stdarg) + ? X86_64_BOUNDED_INTEGER_CLASS + : X86_64_INTEGER_CLASS; return 1; } else if (size <= 64+32) @@ -6478,6 +6510,8 @@ classify_argument (enum machine_mode mode, const_tree type, case V8QImode: classes[0] = X86_64_SSE_CLASS; return 1; + case BND32mode: + case BND64mode: case BLKmode: case VOIDmode: return 0; @@ -6502,13 +6536,14 @@ classify_argument (enum machine_mode mode, const_tree type, class. Return 0 iff parameter should be passed in memory. */ static int examine_argument (enum machine_mode mode, const_tree type, int in_return, - int *int_nregs, int *sse_nregs) + int *int_nregs, int *sse_nregs, int *bnd_nregs, bool stdarg) { enum x86_64_reg_class regclass[MAX_CLASSES]; - int n = classify_argument (mode, type, regclass, 0); + int n = classify_argument (mode, type, regclass, 0, stdarg); *int_nregs = 0; *sse_nregs = 0; + *bnd_nregs = 0; if (!n) return 0; for (n--; n >= 0; n--) @@ -6518,6 +6553,11 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return, case X86_64_INTEGERSI_CLASS: (*int_nregs)++; break; + case X86_64_BOUNDED_INTEGER_CLASS: + case X86_64_BOUNDED_INTEGERSI_CLASS: + (*int_nregs)++; + (*bnd_nregs)++; + break; case X86_64_SSE_CLASS: case X86_64_SSESF_CLASS: case X86_64_SSEDF_CLASS: @@ -6545,7 +6585,8 @@ examine_argument (enum machine_mode mode, const_tree type, int in_return, static rtx construct_container (enum machine_mode mode, enum machine_mode orig_mode, const_tree type, int in_return, int nintregs, int nsseregs, - const int *intreg, int sse_regno) + const int *intreg, int sse_regno, + int bnd_regno, bool stdarg) { /* The following variables hold the static issued_error state. */ static bool issued_sse_arg_error; @@ -6559,15 +6600,15 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode, int n; int i; int nexps = 0; - int needed_sseregs, needed_intregs; + int needed_sseregs, needed_intregs, needed_bndregs; rtx exp[MAX_CLASSES]; rtx ret; - n = classify_argument (mode, type, regclass, 0); + n = classify_argument (mode, type, regclass, 0, stdarg); if (!n) return NULL; if (!examine_argument (mode, type, in_return, &needed_intregs, - &needed_sseregs)) + &needed_sseregs, &needed_bndregs, stdarg)) return NULL; if (needed_intregs > nintregs || needed_sseregs > nsseregs) return NULL; @@ -6613,6 +6654,14 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode, if (n == 1 && mode != SCmode) switch (regclass[0]) { + case X86_64_BOUNDED_INTEGER_CLASS: + case X86_64_BOUNDED_INTEGERSI_CLASS: + ret = gen_rtx_PARALLEL (mode, rtvec_alloc (2)); + XVECEXP (ret, 0, 0) = bnd_regno <= LAST_BND_REG + ? gen_rtx_REG (BNDmode, bnd_regno) + : GEN_INT (bnd_regno - LAST_BND_REG); + XVECEXP (ret, 0, 1) = gen_rtx_REG (mode, intreg[0]); + return ret; case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: return gen_rtx_REG (mode, intreg[0]); @@ -6667,6 +6716,17 @@ construct_container (enum machine_mode mode, enum machine_mode orig_mode, { case X86_64_NO_CLASS: break; + case X86_64_BOUNDED_INTEGER_CLASS: + case X86_64_BOUNDED_INTEGERSI_CLASS: + exp [nexps++] + = gen_rtx_EXPR_LIST (VOIDmode, + bnd_regno <= LAST_BND_REG + ? gen_rtx_REG (BNDmode, bnd_regno) + : GEN_INT (bnd_regno - LAST_BND_REG), + GEN_INT (i*8)); + bnd_regno++; + /* FALLTHRU */ + case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: /* Merge TImodes on aligned occasions here too. */ @@ -6778,6 +6838,14 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->words += words; cum->nregs -= words; cum->regno += words; + if (chkp_function_instrumented_p (current_function_decl) + && type + && chkp_type_has_pointer (type)) + { + unsigned count = chkp_type_bounds_count (type); + cum->bnd_nregs -= count; + cum->bnd_regno += count; + } if (cum->nregs <= 0) { @@ -6849,19 +6917,23 @@ static void 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, bnd_nregs, exam; /* Unnamed 256bit vector mode parameters are passed on stack. */ if (!named && VALID_AVX256_REG_MODE (mode)) return; - if (examine_argument (mode, type, 0, &int_nregs, &sse_nregs) + exam = examine_argument (mode, type, 0, &int_nregs, &sse_nregs, &bnd_nregs, cum->stdarg); + + if (exam && sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs) { cum->nregs -= int_nregs; cum->sse_nregs -= sse_nregs; + cum->bnd_nregs -= bnd_nregs; cum->regno += int_nregs; cum->sse_regno += sse_nregs; + cum->bnd_regno += bnd_nregs; } else { @@ -6969,7 +7041,57 @@ function_arg_32 (const CUMULATIVE_ARGS *cum, enum machine_mode mode, if (regno == AX_REG) regno = CX_REG; } - return gen_rtx_REG (mode, regno); + + /* Add bounds slot for each passed pointer. */ + if (chkp_function_instrumented_p (current_function_decl) + && type + && BOUNDED_TYPE_P (type)) + { + rtx bnd = gen_rtx_REG (BNDmode, cum->bnd_regno); + rtx val = gen_rtx_REG (mode, regno); + rtx ret = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); + XVECEXP (ret, 0, 0) = bnd; + XVECEXP (ret, 0, 1) = val; + return ret; + } + else if (chkp_function_instrumented_p (current_function_decl) + && type + && chkp_type_has_pointer (type)) + { + unsigned int i; + vec has_bounds = chkp_find_bound_slots (type); + unsigned int bnd_num = 0; + unsigned int bnd_no = 1; + unsigned int bnd_regno = cum->bnd_regno; + rtx ret; + + /* Compute number of passed bounds. */ + for (i = 0; i < has_bounds.length (); i++) + if (has_bounds[i]) + bnd_num++; + + /* We return PARALLEL holding value reg and all bounds + slots. */ + ret = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (bnd_num + 1)); + /* Add value to the resulting PARALLEL. */ + XVECEXP (ret, 0, 0) = gen_rtx_REG (mode, regno); + + /* Add bounds to the resulting PARALLEL. */ + for (i = 0; i < has_bounds.length (); i++) + if (has_bounds[i]) + { + rtx bnd = bnd_regno <= LAST_BND_REG + ? gen_rtx_REG (BNDmode, bnd_regno) + : GEN_INT (bnd_regno - LAST_BND_REG); + bnd = gen_rtx_EXPR_LIST (VOIDmode, bnd, GEN_INT (i*8)); + XVECEXP (ret, 0, bnd_no++) = bnd; + bnd_regno++; + } + has_bounds.release (); + return ret; + } + else + return gen_rtx_REG (mode, regno); } break; @@ -7077,7 +7199,7 @@ function_arg_64 (const CUMULATIVE_ARGS *cum, enum machine_mode mode, return construct_container (mode, orig_mode, type, 0, cum->nregs, cum->sse_nregs, &x86_64_int_parameter_registers [cum->regno], - cum->sse_regno); + cum->sse_regno, cum->bnd_regno, cum->stdarg); } static rtx @@ -7419,6 +7541,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: @@ -7453,6 +7578,7 @@ function_value_32 (enum machine_mode orig_mode, enum machine_mode mode, const_tree fntype, const_tree fn) { unsigned int regno; + rtx res; /* 8-byte vector modes in %mm0. See ix86_return_in_memory for where we normally prevent this case when mmx is not available. However @@ -7491,7 +7617,18 @@ function_value_32 (enum machine_mode orig_mode, enum machine_mode mode, /* OImode shouldn't be used directly. */ gcc_assert (mode != OImode); - return gen_rtx_REG (orig_mode, regno); + res = gen_rtx_REG (orig_mode, regno); + + /* Add bound register if bounds are returned in addition to + function value. */ + if (chkp_function_instrumented_p (current_function_decl) + && (!fntype || BOUNDED_P (fntype)) && regno == AX_REG) + { + rtx b0 = gen_rtx_REG (BNDmode, FIRST_BND_REG); + res = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, res, b0)); + } + + return res; } static rtx @@ -7537,7 +7674,7 @@ function_value_64 (enum machine_mode orig_mode, enum machine_mode mode, ret = construct_container (mode, orig_mode, valtype, 1, X86_64_REGPARM_MAX, X86_64_SSE_REGPARM_MAX, - x86_64_int_return_registers, 0); + x86_64_int_return_registers, 0, FIRST_BND_REG, false); /* For zero sized structures, construct_container returns NULL, but we need to keep rest of compiler happy by returning meaningful value. */ @@ -7552,8 +7689,11 @@ function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode, const_tree valtype) { unsigned int regno = AX_REG; + rtx res; - if (TARGET_SSE) + if (mode == BND64mode) + regno = FIRST_BND_REG; + else if (TARGET_SSE) { switch (GET_MODE_SIZE (mode)) { @@ -7577,7 +7717,19 @@ function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode, break; } } - return gen_rtx_REG (orig_mode, regno); + + res = gen_rtx_REG (orig_mode, regno); + + /* Add bound register if bounds are returned in addition to + function value. */ + if (chkp_function_instrumented_p (current_function_decl) + && BOUNDED_TYPE_P (valtype)) + { + rtx b0 = gen_rtx_REG (BNDmode, FIRST_BND_REG); + res = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, res, b0)); + } + + return res; } static rtx @@ -7695,8 +7847,9 @@ return_in_memory_32 (const_tree type, enum machine_mode mode) static bool ATTRIBUTE_UNUSED return_in_memory_64 (const_tree type, enum machine_mode mode) { - int needed_intregs, needed_sseregs; - return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs); + int needed_intregs, needed_sseregs, needed_bndregs; + return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs, + &needed_bndregs, true); } static bool ATTRIBUTE_UNUSED @@ -8177,7 +8330,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, int size, rsize; tree lab_false, lab_over = NULL_TREE; tree addr, t2; - rtx container; + rtx container, bndcontainer = NULL; int indirect_p = 0; tree ptrtype; enum machine_mode nat_mode; @@ -8225,7 +8378,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, container = construct_container (nat_mode, TYPE_MODE (type), type, 0, X86_64_REGPARM_MAX, X86_64_SSE_REGPARM_MAX, intreg, - 0); + 0, 0, false); + chkp_split_slot (container, &container, &bndcontainer); break; } @@ -8235,14 +8389,15 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, if (container) { - int needed_intregs, needed_sseregs; + int needed_intregs, needed_sseregs, needed_bndregs; bool need_temp; tree int_addr, sse_addr; lab_false = create_artificial_label (UNKNOWN_LOCATION); lab_over = create_artificial_label (UNKNOWN_LOCATION); - examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs); + examine_argument (nat_mode, type, 0, &needed_intregs, &needed_sseregs, + &needed_bndregs, true); need_temp = (!REG_P (container) && ((needed_intregs && TYPE_ALIGN (type) > 64) @@ -14945,7 +15100,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; @@ -23427,7 +23582,6 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, || !alg_usable_p (algs->unknown_size, memset))) { enum stringop_alg alg; - /* If there aren't any usable algorithms, then recursing on smaller sizes isn't going to find anything. Just return the simple byte-at-a-time copy loop. */ @@ -24403,10 +24557,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); @@ -42988,9 +43164,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 123e3fa..1369c4d 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1664,6 +1664,9 @@ 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_nregs; /* # bnd registers available for passing */ + int bnd_regno; /* next available bnd register number */ + 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 dc7d81a..427ae0c 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -190,6 +190,7 @@ UNSPEC_BNDCU UNSPEC_BNDCN UNSPEC_MPX_FENCE + UNSPEC_BNDRET ]) (define_c_enum "unspecv" [ @@ -11565,7 +11566,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")]) @@ -11573,7 +11576,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")]) @@ -11583,6 +11588,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]);" @@ -11606,6 +11613,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")))] @@ -11617,6 +11626,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 5c758ab..7dd8f99 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -597,14 +597,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;