From patchwork Thu Oct 11 16:38:47 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 190961 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]) by ozlabs.org (Postfix) with SMTP id 80F642C03BD for ; Fri, 12 Oct 2012 03:39:10 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1350578351; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=HJ4uKRPKEDS9eniL1TSI C8hGrk8=; b=RJd+HxGPfxAN/z0BmPx0PmFbbDMyXYEnHYsv7LqxTsJsxKcG6jsu XvIii2RFDRkaqFSyP2gDVWT9ZAjK2v7MiCn9T6KMlee6rMuUg4Wft/9GG8PoMLk7 cZDc3SObLnDtcAxmJadGBt33ebtLRluMhdBid7TYdu0fHmQqkddKVkM= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To:MIME-Version:Content-Type:Content-Disposition:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=HW9l5wnKiZ5obqIaUwRBSuVBlyRFtWlmDv0HDX61cIUxgLWUO/tTyamEtFUqbn OdVaCENNc6mhOBwZzbPwzzmE2N4eAFZGJZpjKLTWXBli+VFtSDSy+SazK4zQj0pv m45q4LvSWOkiX9zRvbVVCwRUFPc+WiAyXPU/fB+Dwaxk8=; Received: (qmail 31679 invoked by alias); 11 Oct 2012 16:39:02 -0000 Received: (qmail 31583 invoked by uid 22791); 11 Oct 2012 16:38:57 -0000 X-SWARE-Spam-Status: No, hits=-7.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_SPAMHAUS_DROP, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 11 Oct 2012 16:38:51 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9BGcp73026699 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 11 Oct 2012 12:38:51 -0400 Received: from zalov.redhat.com (vpn1-4-98.ams2.redhat.com [10.36.4.98]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q9BGcmq2027230 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 11 Oct 2012 12:38:50 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id q9BGclb3011340; Thu, 11 Oct 2012 18:38:47 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id q9BGcl3N011339; Thu, 11 Oct 2012 18:38:47 +0200 Date: Thu, 11 Oct 2012 18:38:47 +0200 From: Jakub Jelinek To: Diego Novillo , Dodji Seketeli Cc: gcc-patches@gcc.gnu.org Subject: [asan] Emit GIMPLE directly, small cleanups Message-ID: <20121011163847.GE584@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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 Hi! Building trees, then gimplifying it, is unnecessarily expensive. This patch changes build_check_stmt to emit GIMPLE directly, and a couple of small cleanups here and there. Also, I'm using a different alias set for the shadow memory accesses, those obviously can't alias any other accesses. Ok for asan? 2012-10-11 Jakub Jelinek * Makefile.in (GTFILES): Add $(srcdir)/asan.c. * asan.c (shadow_ptr_types): New variable. (report_error_func): Change is_store argument to bool, don't append newline to function name. (PROB_VERY_UNLIKELY, PROB_ALWAYS): Define. (build_check_stmt): Change is_store argument to bool. Emit GIMPLE directly instead of creating trees and gimplifying them. Mark the error reporting function as very unlikely. (instrument_derefs): Change is_store argument to bool. Use int_size_in_bytes to compute size_in_bytes, simplify size check. Use build_fold_addr_expr instead of build_addr. (transform_statements): Adjust instrument_derefs caller. Use gimple_assign_single_p as stmt test. Don't look at MEM refs in rhs2. (asan_instrument): Don't push/pop gimplify context. Initialize shadow_ptr_types if not yet initialized. * asan.h (ASAN_SHADOW_SHIFT): Adjust comment. Jakub --- gcc/Makefile.in.jj 2012-10-11 16:09:02.000000000 +0200 +++ gcc/Makefile.in 2012-10-11 16:51:59.666672099 +0200 @@ -3681,6 +3681,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp $(srcdir)/lto-streamer.h \ $(srcdir)/target-globals.h \ $(srcdir)/ipa-inline.h \ + $(srcdir)/asan.c \ @all_gtfiles@ # Compute the list of GT header files from the corresponding C sources, --- gcc/asan.c.jj 2012-10-11 16:33:58.000000000 +0200 +++ gcc/asan.c 2012-10-11 18:20:35.265675838 +0200 @@ -79,18 +79,20 @@ along with GCC; see the file COPYING3. to create redzones for stack and global object and poison them. */ +static GTY(()) tree shadow_ptr_types[2]; + /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. IS_STORE is either 1 (for a store) or 0 (for a load). SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */ static tree -report_error_func (int is_store, int size_in_bytes) +report_error_func (bool is_store, int size_in_bytes) { tree fn_type; tree def; char name[100]; - sprintf (name, "__asan_report_%s%d\n", + sprintf (name, "__asan_report_%s%d", is_store ? "store" : "load", size_in_bytes); fn_type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); def = build_fn_decl (name, fn_type); @@ -118,6 +120,9 @@ asan_init_func (void) } +#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1) +#define PROB_ALWAYS (REG_BR_PROB_BASE) + /* Instrument the memory access instruction BASE. Insert new statements before ITER. LOCATION is source code location. @@ -127,21 +132,17 @@ asan_init_func (void) static void build_check_stmt (tree base, gimple_stmt_iterator *iter, - location_t location, int is_store, int size_in_bytes) + location_t location, bool is_store, int size_in_bytes) { gimple_stmt_iterator gsi; basic_block cond_bb, then_bb, join_bb; edge e; - tree cond, t, u; - tree base_addr; - tree shadow_value; + tree t, base_addr, shadow; gimple g; - gimple_seq seq, stmts; - tree shadow_type = size_in_bytes == 16 ? - short_integer_type_node : char_type_node; - tree shadow_ptr_type = build_pointer_type (shadow_type); - tree uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, - /*unsignedp=*/true); + tree shadow_ptr_type = shadow_ptr_types[size_in_bytes == 16]; + tree shadow_type = TREE_TYPE (shadow_ptr_type); + tree uintptr_type + = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1); /* We first need to split the current basic block, and start altering the CFG. This allows us to insert the statements we're about to @@ -166,14 +167,15 @@ build_check_stmt (tree base, /* Create the bb that contains the crash block. */ then_bb = create_empty_bb (cond_bb); - make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); + e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); + e->probability = PROB_VERY_UNLIKELY; make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU); /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */ e = find_edge (cond_bb, join_bb); e->flags = EDGE_FALSE_VALUE; e->count = cond_bb->count; - e->probability = REG_BR_PROB_BASE; + e->probability = PROB_ALWAYS - PROB_VERY_UNLIKELY; /* Update dominance info. Note that bb_join's data was updated by split_block. */ @@ -183,75 +185,123 @@ build_check_stmt (tree base, set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb); } - base_addr = create_tmp_reg (uintptr_type, "__asan_base_addr"); + gsi = gsi_last_bb (cond_bb); + g = gimple_build_assign_with_ops (TREE_CODE (base), + make_ssa_name (TREE_TYPE (base), NULL), + base, NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - seq = NULL; - t = fold_convert_loc (location, uintptr_type, - unshare_expr (base)); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - g = gimple_build_assign (base_addr, t); + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (uintptr_type, NULL), + gimple_assign_lhs (g), NULL_TREE); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + base_addr = gimple_assign_lhs (g); /* Build - (base_addr >> ASAN_SHADOW_SHIFT) | targetm.asan_shadow_offset (). */ + (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ - t = build2 (RSHIFT_EXPR, uintptr_type, base_addr, - build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT)); - t = build2 (PLUS_EXPR, uintptr_type, t, - build_int_cst (uintptr_type, targetm.asan_shadow_offset ())); - t = build1 (INDIRECT_REF, shadow_type, - build1 (VIEW_CONVERT_EXPR, shadow_ptr_type, t)); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - shadow_value = create_tmp_reg (shadow_type, "__asan_shadow"); - g = gimple_build_assign (shadow_value, t); + t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT); + g = gimple_build_assign_with_ops (RSHIFT_EXPR, + make_ssa_name (uintptr_type, NULL), + base_addr, t); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); - t = build2 (NE_EXPR, boolean_type_node, shadow_value, - build_int_cst (shadow_type, 0)); - if (size_in_bytes < 8) - { + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - /* Slow path for 1-, 2- and 4- byte accesses. - Build ((base_addr & 7) + (size_in_bytes - 1)) >= shadow_value. */ - - u = build2 (BIT_AND_EXPR, uintptr_type, - base_addr, - build_int_cst (uintptr_type, 7)); - u = build1 (CONVERT_EXPR, shadow_type, u); - u = build2 (PLUS_EXPR, shadow_type, u, - build_int_cst (shadow_type, size_in_bytes - 1)); - u = build2 (GE_EXPR, uintptr_type, u, shadow_value); - } - else - u = build_int_cst (boolean_type_node, 1); - t = build2 (TRUTH_AND_EXPR, boolean_type_node, t, u); - t = force_gimple_operand (t, &stmts, false, NULL_TREE); - gimple_seq_add_seq (&seq, stmts); - cond = create_tmp_reg (boolean_type_node, "__asan_crash_cond"); - g = gimple_build_assign (cond, t); + t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ()); + g = gimple_build_assign_with_ops (PLUS_EXPR, + make_ssa_name (uintptr_type, NULL), + gimple_assign_lhs (g), t); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); - g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE, - NULL_TREE); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (shadow_ptr_type, NULL), + gimple_assign_lhs (g), NULL_TREE); gimple_set_location (g, location); - gimple_seq_add_stmt (&seq, g); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); - /* Generate call to the run-time library (e.g. __asan_report_load8). */ + t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g), + build_int_cst (shadow_ptr_type, 0)); + g = gimple_build_assign_with_ops (MEM_REF, + make_ssa_name (shadow_type, NULL), + t, NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + shadow = gimple_assign_lhs (g); - gsi = gsi_last_bb (cond_bb); - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); - seq = NULL; - g = gimple_build_call (report_error_func (is_store, size_in_bytes), - 1, base_addr); - gimple_seq_add_stmt (&seq, g); + if (size_in_bytes < 8) + { + /* Slow path for 1, 2 and 4 byte accesses. + Test (shadow != 0) + & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */ + g = gimple_build_assign_with_ops (NE_EXPR, + make_ssa_name (boolean_type_node, + NULL), + shadow, + build_int_cst (shadow_type, 0)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + t = gimple_assign_lhs (g); + + g = gimple_build_assign_with_ops (BIT_AND_EXPR, + make_ssa_name (uintptr_type, + NULL), + base_addr, + build_int_cst (uintptr_type, 7)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (shadow_type, + NULL), + gimple_assign_lhs (g), NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + if (size_in_bytes > 1) + { + g = gimple_build_assign_with_ops (PLUS_EXPR, + make_ssa_name (shadow_type, + NULL), + gimple_assign_lhs (g), + build_int_cst (shadow_type, + size_in_bytes - 1)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + } + + g = gimple_build_assign_with_ops (GE_EXPR, + make_ssa_name (boolean_type_node, + NULL), + gimple_assign_lhs (g), + shadow); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + g = gimple_build_assign_with_ops (BIT_AND_EXPR, + make_ssa_name (boolean_type_node, + NULL), + t, gimple_assign_lhs (g)); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + t = gimple_assign_lhs (g); + } + else + t = shadow; - /* Insert the check code in the THEN block. */ + g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0), + NULL_TREE, NULL_TREE); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + /* Generate call to the run-time library (e.g. __asan_report_load8). */ gsi = gsi_start_bb (then_bb); - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); + g = gimple_build_call (report_error_func (is_store, size_in_bytes), + 1, base_addr); + gimple_set_location (g, location); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); *iter = gsi_start_bb (join_bb); } @@ -262,14 +312,12 @@ build_check_stmt (tree base, static void instrument_derefs (gimple_stmt_iterator *iter, tree t, - location_t location, int is_store) + location_t location, bool is_store) { tree type, base; - int size_in_bytes; + HOST_WIDE_INT size_in_bytes; type = TREE_TYPE (t); - if (type == error_mark_node) - return; switch (TREE_CODE (t)) { case ARRAY_REF: @@ -280,25 +328,25 @@ instrument_derefs (gimple_stmt_iterator default: return; } - size_in_bytes = tree_low_cst (TYPE_SIZE (type), 0) / BITS_PER_UNIT; - if (size_in_bytes != 1 && size_in_bytes != 2 && - size_in_bytes != 4 && size_in_bytes != 8 && size_in_bytes != 16) - return; - { - /* For now just avoid instrumenting bit field acceses. + + size_in_bytes = int_size_in_bytes (type); + if ((size_in_bytes & (size_in_bytes - 1)) != 0 + || (unsigned HOST_WIDE_INT) size_in_bytes - 1 >= 16) + return; + + /* For now just avoid instrumenting bit field acceses. Fixing it is doable, but expected to be messy. */ - HOST_WIDE_INT bitsize, bitpos; - tree offset; - enum machine_mode mode; - int volatilep = 0, unsignedp = 0; - get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); - if (bitpos != 0 || bitsize != size_in_bytes * BITS_PER_UNIT) - return; - } + HOST_WIDE_INT bitsize, bitpos; + tree offset; + enum machine_mode mode; + int volatilep = 0, unsignedp = 0; + get_inner_reference (t, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, false); + if (bitpos != 0 || bitsize != size_in_bytes * BITS_PER_UNIT) + return; - base = build_addr (t, current_function_decl); + base = build_fold_addr_expr (t); build_check_stmt (base, iter, location, is_store, size_in_bytes); } @@ -314,7 +362,6 @@ transform_statements (void) basic_block bb; gimple_stmt_iterator i; int saved_last_basic_block = last_basic_block; - enum gimple_rhs_class grhs_class; FOR_EACH_BB (bb) { @@ -322,16 +369,12 @@ transform_statements (void) for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { gimple s = gsi_stmt (i); - if (gimple_code (s) != GIMPLE_ASSIGN) - continue; + if (!gimple_assign_single_p (s)) + continue; instrument_derefs (&i, gimple_assign_lhs (s), - gimple_location (s), 1); + gimple_location (s), true); instrument_derefs (&i, gimple_assign_rhs1 (s), - gimple_location (s), 0); - grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s)); - if (grhs_class == GIMPLE_BINARY_RHS) - instrument_derefs (&i, gimple_assign_rhs2 (s), - gimple_location (s), 0); + gimple_location (s), false); } } } @@ -356,10 +399,19 @@ asan_finish_file (void) static unsigned int asan_instrument (void) { - struct gimplify_ctx gctx; - push_gimplify_context (&gctx); + if (shadow_ptr_types[0] == NULL_TREE) + { + alias_set_type set = new_alias_set (); + shadow_ptr_types[0] + = build_distinct_type_copy (unsigned_char_type_node); + TYPE_ALIAS_SET (shadow_ptr_types[0]) = set; + shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]); + shadow_ptr_types[1] + = build_distinct_type_copy (short_unsigned_type_node); + TYPE_ALIAS_SET (shadow_ptr_types[1]) = set; + shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]); + } transform_statements (); - pop_gimplify_context (NULL); return 0; } @@ -385,6 +437,8 @@ struct gimple_opt_pass pass_asan = 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_stmts - | TODO_update_ssa /* todo_flags_finish */ + | TODO_update_ssa /* todo_flags_finish */ } }; + +#include "gt-asan.h" --- gcc/asan.h.jj 2012-10-11 16:04:28.000000000 +0200 +++ gcc/asan.h 2012-10-11 18:09:07.430449499 +0200 @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. extern void asan_finish_file(void); /* Shadow memory is found at - (address >> ASAN_SHADOW_SHIFT) | targetm.asan_shadow_offset (). */ + (address >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ #define ASAN_SHADOW_SHIFT 3 #endif /* TREE_ASAN */