From patchwork Tue Jan 9 20:42:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 857719 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-470605-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="OfcxQIud"; dkim-atps=neutral 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 3zGPGG0Wwnz9s75 for ; Wed, 10 Jan 2018 07:42:28 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=YRodHHgHw1d/mwpNiKzz/sf/6hs+BuD6yttgHZIbyzUAkk 4Glgk0r8457pQvgzYDSOG8utDZeHvKAQyKLwxP7feUCucfY0NUpOyiWi3pBEcRAR G4UMdeFHf+ZpSXPsWuvyAeGd423k+Ay6YWmToSPhdR4U64Lm1WnfFU1LvwhEc= 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 :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=thL1Z2cmEYtNu1yxgIgjOxs8upY=; b=OfcxQIudoQqdfZ6zEO5r OeheWCS6zsftthXgommxje9TKskg/aEnEJf0qxEN6H0JKG3dvBoSpGEsla+3Hsdr KwTBQkeL9ll8TfWAHiZsw/9wxnq3DA9VX37aU3dNx0cjWzNImBtGthyk7iQEnY0U tBLANvCr9saxAdh1Js12JBY= Received: (qmail 44946 invoked by alias); 9 Jan 2018 20:42:20 -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 44937 invoked by uid 89); 9 Jan 2018 20:42:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-13.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS, UNSUBSCRIBE_BODY autolearn=ham version=3.3.2 spammy=cerr, 10356, uncover X-HELO: mail-wm0-f46.google.com Received: from mail-wm0-f46.google.com (HELO mail-wm0-f46.google.com) (74.125.82.46) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 09 Jan 2018 20:42:17 +0000 Received: by mail-wm0-f46.google.com with SMTP id f140so23040179wmd.2 for ; Tue, 09 Jan 2018 12:42:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=iu5tb/d/oANPVktXI0jbewNT6gRCs4G/FZIXlXSx744=; b=c2oO9DJevyfmxdIRJLUbEEz3iT6iTeJQXzUZD9Ajt4SkteO+8NAGjCGV8LU07oXMQ2 QdJsATqqKyT+ag9W+sbJFISZYfDv9c/k1/bfuvh7Ck4jsLUynRubM5fV5UbaMnQmmnEC +kI5GQJ6sYwuLuCKzPkOJoqJtUiqgLucDdv+38um1+9x7HVJHzouGVsfv0QKJQ1Gy5Pr BzpM1mEOb0q58J7kLFHdSPRewJg+8WraAkosOos382thY97Jmtgr5kAUA60NZDSXdFvK QGulgOFM325AJf2yrS8MpsqM7mS1QzR3x6RQtGKndULrilfvnUJ4AFJgm+E4U7rbObWk /L4w== X-Gm-Message-State: AKwxyteG6zzZsjwDY6jyjMzw8YffJXlRktZn9aiV5EjBftZDc+a/+hW1 CHpvVzfKnCskquWNdFtbFpntYSH3jqLPIibn3laVwazg X-Google-Smtp-Source: ACJfBou76wn1IiD5zNJo/QkQ3pwpLooV2b/u7s8QaA3Kqb93coQBqzLWWNdmkcXD8AaBSN75WnXK1+Cn/oNFbHCPhl8= X-Received: by 10.80.168.164 with SMTP id k33mr18751edc.31.1515530535570; Tue, 09 Jan 2018 12:42:15 -0800 (PST) MIME-Version: 1.0 Received: by 10.80.179.221 with HTTP; Tue, 9 Jan 2018 12:42:14 -0800 (PST) From: Ian Lance Taylor Date: Tue, 9 Jan 2018 12:42:14 -0800 Message-ID: Subject: Go patch committed: Add escape analysis debug hash To: gcc-patches , gofrontend-dev@googlegroups.com This patch by Cherry Zhang adds a new -fgo-debug-escape-hash option to the Go frontend. This option takes a string that can be used to select specific functions on which to run escape analysis. This makes it easier to find escape analysis bugs by doing a binary search over all the functions, enabling or disabling escape analysis for each one. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian 2018-01-09 Cherry Zhang * lang.opt (fgo-debug-escape-hash): New option. * go-c.h (struct go_create_gogo_args): Add debug_escape_hash field. * go-lang.c (go_langhook_init): Set debug_escape_hash field. * gccgo.texi (Invoking gccgo): Document -fgo-debug-escape-hash. Index: gcc/go/gccgo.texi =================================================================== --- gcc/go/gccgo.texi (revision 256366) +++ gcc/go/gccgo.texi (working copy) @@ -239,6 +239,13 @@ heap when possible. In the future this Output escape analysis debugging information. Larger values of @var{n} generate more information. +@item -fgo-debug-escape-hash=@var{n} +@cindex @option{-fgo-debug-escape-hash} +A hash value to debug escape analysis. @var{n} is a binary string. +This runs escape analysis only on functions whose names hash to values +that match the given suffix @var{n}. This can be used to binary +search across functions to uncover escape analysis bugs. + @item -fgo-c-header=@var{file} @cindex @option{-fgo-c-header} Write top-level named Go struct definitions to @var{file} as C code. Index: gcc/go/go-c.h =================================================================== --- gcc/go/go-c.h (revision 256366) +++ gcc/go/go-c.h (working copy) @@ -47,6 +47,7 @@ struct go_create_gogo_args bool check_divide_overflow; bool compiling_runtime; int debug_escape_level; + const char* debug_escape_hash; int64_t nil_check_size_threshold; }; Index: gcc/go/go-lang.c =================================================================== --- gcc/go/go-lang.c (revision 256366) +++ gcc/go/go-lang.c (working copy) @@ -116,6 +116,7 @@ go_langhook_init (void) args.check_divide_overflow = go_check_divide_overflow; args.compiling_runtime = go_compiling_runtime; args.debug_escape_level = go_debug_escape_level; + args.debug_escape_hash = go_debug_escape_hash; args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096; args.linemap = go_get_linemap(); args.backend = go_get_backend(); Index: gcc/go/gofrontend/escape.cc =================================================================== --- gcc/go/gofrontend/escape.cc (revision 256389) +++ gcc/go/gofrontend/escape.cc (working copy) @@ -19,6 +19,7 @@ #include "ast-dump.h" #include "go-optimize.h" #include "go-diagnostics.h" +#include "go-sha1.h" // class Node. @@ -821,6 +822,39 @@ Escape_note::parse_tag(std::string* tag) Go_optimize optimize_allocation_flag("allocs"); +// A helper function to compute whether a function name has a +// matching hash value. + +static bool +escape_hash_match(std::string suffix, std::string name) +{ + if (suffix.empty()) + return true; + if (suffix.at(0) == '-') + return !escape_hash_match(suffix.substr(1), name); + + const char* p = name.c_str(); + Go_sha1_helper* sha1_helper = go_create_sha1_helper(); + sha1_helper->process_bytes(p, strlen(p)); + std::string s = sha1_helper->finish(); + delete sha1_helper; + + int j = suffix.size() - 1; + for (int i = s.size() - 1; i >= 0; i--) + { + char c = s.at(i); + for (int k = 0; k < 8; k++, j--, c>>=1) + { + if (j < 0) + return true; + char bit = suffix.at(j) - '0'; + if ((c&1) != bit) + return false; + } + } + return false; +} + // Analyze the program flow for escape information. void @@ -839,11 +873,46 @@ Gogo::analyze_escape() // information in this package. this->discover_analysis_sets(); + if (!this->debug_escape_hash().empty()) + std::cerr << "debug-escape-hash " << this->debug_escape_hash() << "\n"; + for (std::vector::iterator p = this->analysis_sets_.begin(); p != this->analysis_sets_.end(); ++p) { std::vector stack = p->first; + + if (!this->debug_escape_hash().empty()) + { + bool match = false; + for (std::vector::const_iterator fn = stack.begin(); + fn != stack.end(); + ++fn) + match = match || escape_hash_match(this->debug_escape_hash(), (*fn)->message_name()); + if (!match) + { + // Escape analysis won't run on these functions, but still + // need to tag them, so the caller knows. + for (std::vector::iterator fn = stack.begin(); + fn != stack.end(); + ++fn) + if ((*fn)->is_function()) + { + Function_type* fntype = (*fn)->func_value()->type(); + fntype->set_is_tagged(); + + std::cerr << "debug-escape-hash disables " << debug_function_name(*fn) << "\n"; + } + + continue; + } + for (std::vector::const_iterator fn = stack.begin(); + fn != stack.end(); + ++fn) + if ((*fn)->is_function()) + std::cerr << "debug-escape-hash triggers " << debug_function_name(*fn) << "\n"; + } + Escape_context* context = new Escape_context(this, p->second); // Analyze the flow of each function; build the connection graph. Index: gcc/go/gofrontend/go.cc =================================================================== --- gcc/go/gofrontend/go.cc (revision 256366) +++ gcc/go/gofrontend/go.cc (working copy) @@ -41,6 +41,8 @@ go_create_gogo(const struct go_create_go if (args->c_header != NULL) ::gogo->set_c_header(args->c_header); ::gogo->set_debug_escape_level(args->debug_escape_level); + if (args->debug_escape_hash != NULL) + ::gogo->set_debug_escape_hash(args->debug_escape_hash); ::gogo->set_nil_check_size_threshold(args->nil_check_size_threshold); } Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 256366) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -318,6 +318,16 @@ class Gogo set_debug_escape_level(int level) { this->debug_escape_level_ = level; } + // Return the hash for debug escape analysis. + std::string + debug_escape_hash() const + { return this->debug_escape_hash_; } + + // Set the hash value for debug escape analysis. + void + set_debug_escape_hash(const std::string& s) + { this->debug_escape_hash_ = s; } + // Return the size threshold used to determine whether to issue // a nil-check for a given pointer dereference. A threshold of -1 // implies that all potentially faulting dereference ops should @@ -1035,6 +1045,10 @@ class Gogo // The level of escape analysis debug information to emit, from the // -fgo-debug-escape option. int debug_escape_level_; + // A hash value for debug escape analysis, from the + // -fgo-debug-escape-hash option. The analysis is run only on + // functions with names that hash to the matching value. + std::string debug_escape_hash_; // Nil-check size threshhold. int64_t nil_check_size_threshold_; // A list of types to verify. Index: gcc/go/lang.opt =================================================================== --- gcc/go/lang.opt (revision 256366) +++ gcc/go/lang.opt (working copy) @@ -81,6 +81,10 @@ fgo-debug-escape Go Joined UInteger Var(go_debug_escape_level) Init(0) Emit debugging information related to the escape analysis pass when run with -fgo-optimize-allocs. +fgo-debug-escape-hash= +Go Joined RejectNegative Var(go_debug_escape_hash) Init(0) +-fgo-debug-escape-hash= Hash value to debug escape analysis. + o Go Joined Separate ; Documented in common.opt