From patchwork Wed Jun 11 14:00:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 358681 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 F0982140079 for ; Thu, 12 Jun 2014 00:01:35 +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=Jb+Me4kX4uksEnkzXIS26l70V9kJuquSRqsb57VDL/jrjgGoXM0Yy N9aCKaRDalCjUOhXOtu0l/Rh1bSJMV0bA/U1qo2ieDC8uJoDR4JexZnmhv4uf14B 4yBKMj+5LnA0olcroc66phG2hTwGeEQTJE1nhxqIr9iuGvspKyWuSc= 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=2IEbZ+oUt0Z9FdOiD3mHWHrBWZQ=; b=RAHxu++WDenKky/7x2JL UcavseiD4UgwpegnwXD3aFQ6Kl1TdsSrZt1tZ7sT5p6sMD76K2WseoNG1Z6pqhVd 8JWTlW67AosChn7QFfpie6etT71z81cq9Mk+5xmOGUEyMjOWjWaHLbhwDi99xrUp cvlz/OlC8ht58EbBWzAThZY= Received: (qmail 22806 invoked by alias); 11 Jun 2014 14:01:29 -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 22794 invoked by uid 89); 11 Jun 2014 14:01:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 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-f52.google.com Received: from mail-pa0-f52.google.com (HELO mail-pa0-f52.google.com) (209.85.220.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 11 Jun 2014 14:01:03 +0000 Received: by mail-pa0-f52.google.com with SMTP id eu11so1949571pac.11 for ; Wed, 11 Jun 2014 07:01:01 -0700 (PDT) X-Received: by 10.68.215.3 with SMTP id oe3mr5447935pbc.109.1402495261444; Wed, 11 Jun 2014 07:01:01 -0700 (PDT) Received: from msticlxl57.ims.intel.com ([192.55.54.40]) by mx.google.com with ESMTPSA id ci4sm75217357pbb.50.2014.06.11.07.00.59 for (version=TLSv1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 11 Jun 2014 07:01:00 -0700 (PDT) Date: Wed, 11 Jun 2014 18:00:55 +0400 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [PATCH, i386, Pointer Bounds Checker 32/x] Pointer Bounds Checker hooks for i386 target Message-ID: <20140611140055.GG17894@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 i386 target hooks for Pointer Bounds Checker. Bootstrapped and tested on linux-x86_64. Thanks, Ilya --- gcc/ 2014-06-11 Ilya Enkovich * 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"