From patchwork Fri Dec 4 14:08:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 552717 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 9844E1402BC for ; Sat, 5 Dec 2015 01:08:23 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=KhAtbtSj; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=YXe2yH3qj+keyfSI9YXr+DY+lpglLoQHABSC14rHdcCX46fspo DYELaRfFnY/RN6oEBFLFbCegkkqewlJ9CHwE4o1k0UcfNDaPmm99k89qEli0v2H9 xyH+fr3xDJYMI4rwX8Irt5Nhud7516Z8CmG4XCpan5jsbbkaJcAdcdZGM= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=1Nc4sJIvfL9sR6hb2UATecCPs6U=; b=KhAtbtSjjvwWoa7C+8C5 P1VP65mT7/Pa5OfqyIjNZT/n60p4EIpAsjYF5V9yvYhKRmGfBYob25bMPGz3hpC3 JDc4Q6TGiKp68zkW5eHEBQ4WLH2L1IBvt0GyMFBL8oFCWbENZkH4+hjAAAt1t+aq mUnL1v3lHcVKFIJRcGk5w0A= Received: (qmail 81212 invoked by alias); 4 Dec 2015 14:08:15 -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 81196 invoked by uid 89); 4 Dec 2015 14:08:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qk0-f169.google.com Received: from mail-qk0-f169.google.com (HELO mail-qk0-f169.google.com) (209.85.220.169) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 04 Dec 2015 14:08:13 +0000 Received: by qkfo3 with SMTP id o3so43902784qkf.1 for ; Fri, 04 Dec 2015 06:08:11 -0800 (PST) X-Received: by 10.55.77.134 with SMTP id a128mr18376637qkb.104.1449238091175; Fri, 04 Dec 2015 06:08:11 -0800 (PST) Received: from ?IPv6:2601:181:c000:c497:a2a8:cdff:fe3e:b48? ([2601:181:c000:c497:a2a8:cdff:fe3e:b48]) by smtp.googlemail.com with ESMTPSA id y200sm5547083qka.48.2015.12.04.06.08.10 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 04 Dec 2015 06:08:10 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: [PTX] prologue emission Message-ID: <56619E4A.90103@acm.org> Date: Fri, 4 Dec 2015 09:08:10 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 The PTX backend has to emit PTX function prototypes and prologues in addition to the regular argument marshalling machinery. And of course these all have to agree with each other. The first two are done by two different pieces of code, This patch changes things so that prototype and prologue argument emission is done by the same piece of code. A slight wart there is that prototype emission uses a C++ stdstream where as prologue emission (mainly) used ye olde FILE *. The patch extends the latter's use of stdstream a little further. You'll notice that argument promotion is slightly different in the two paths. I've not changed that behaviour, but I suspect it may be an error. Will relook at that when I'm done reducing the duplication in the function calling machinery. nathan 2015-12-04 Nathan Sidwell * config/nvptx/nvptx.c (write_one_arg): Deal with prologue emission too. Change 'no_arg_types' to 'prototyped'. (write_fn_proto): Use write_one_arg for stdarg, static chain & main. (nvptx_declare_function_name): Use write_one_arg for prologue copies. Index: config/nvptx/nvptx.c =================================================================== --- config/nvptx/nvptx.c (revision 231265) +++ config/nvptx/nvptx.c (working copy) @@ -389,38 +389,67 @@ arg_promotion (machine_mode mode) return mode; } -/* Write the declaration of a function arg of TYPE to S. I is the index - of the argument, MODE its mode. NO_ARG_TYPES is true if this is for - a decl with zero TYPE_ARG_TYPES, i.e. an old-style C decl. */ +/* Process function parameter TYPE, either emitting in a prototype + argument, or as a copy a in a function prologue. ARGNO is the + index of this argument in the PTX function. FOR_REG is negative, + if we're emitting the PTX prototype. It is zero if we're copying + to an argument register and it is greater than zero if we're + copying to a specific hard register. PROTOTYPED is true, if this + is a prototyped function, rather than an old-style C declaration. + + The behaviour here must match the regular GCC function parameter + marshalling machinery. */ static int -write_one_arg (std::stringstream &s, const char *sep, int i, - tree type, machine_mode mode, bool no_arg_types) +write_one_arg (std::stringstream &s, int for_reg, int argno, + tree type, bool prototyped) { + machine_mode mode = TYPE_MODE (type); + if (!PASS_IN_REG_P (mode, type)) mode = Pmode; machine_mode split = maybe_split_mode (mode); if (split != VOIDmode) { - i = write_one_arg (s, sep, i, TREE_TYPE (type), split, false); - sep = ", "; mode = split; + argno = write_one_arg (s, for_reg, argno, + TREE_TYPE (type), prototyped); } - if (no_arg_types && !AGGREGATE_TYPE_P (type)) + if (!prototyped && !AGGREGATE_TYPE_P (type)) { if (mode == SFmode) mode = DFmode; mode = arg_promotion (mode); } - s << sep; - s << ".param" << nvptx_ptx_type_from_mode (mode, false) << " %in_ar" - << i << (mode == QImode || mode == HImode ? "[1]" : ""); - if (mode == BLKmode) - s << "[" << int_size_in_bytes (type) << "]"; - return i + 1; + if (for_reg < 0) + { + /* Writing PTX prototype. */ + s << (argno ? ", " : " ("); + s << ".param" << nvptx_ptx_type_from_mode (mode, false) + << " %in_ar" << argno; + if (mode == QImode || mode == HImode) + s << "[1]"; + } + else + { + mode = arg_promotion (mode); + s << "\t.reg" << nvptx_ptx_type_from_mode (mode, false) << " "; + if (for_reg) + s << reg_names[for_reg]; + else + s << "%ar" << argno; + s << ";\n"; + s << "\tld.param" << nvptx_ptx_type_from_mode (mode, false) << " "; + if (for_reg) + s << reg_names[for_reg]; + else + s << "%ar" << argno; + s<< ", [%in_ar" << argno << "];\n"; + } + return argno + 1; } /* Look for attributes in ATTRS that would indicate we must write a function @@ -507,16 +536,11 @@ write_fn_proto (std::stringstream &s, bo s << name; - const char *sep = " ("; - int i = 0; + int argno = 0; /* Emit argument list. */ if (return_in_mem) - { - s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_ar0"; - sep = ", "; - i++; - } + argno = write_one_arg (s, -1, argno, ptr_type_node, true); /* We get: NULL in TYPE_ARG_TYPES, for old-style functions @@ -524,46 +548,34 @@ write_fn_proto (std::stringstream &s, bo declaration. So we have to pick the best one we have. */ tree args = TYPE_ARG_TYPES (fntype); - bool null_type_args = !args; - if (null_type_args) - args = DECL_ARGUMENTS (decl); + bool prototyped = true; + if (!args) + { + args = DECL_ARGUMENTS (decl); + prototyped = false; + } for (; args; args = TREE_CHAIN (args)) { - tree type = null_type_args ? TREE_TYPE (args) : TREE_VALUE (args); - machine_mode mode = TYPE_MODE (type); + tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args); - if (mode == VOIDmode) - break; - i = write_one_arg (s, sep, i, type, mode, null_type_args); - sep = ", "; + if (type != void_type_node) + argno = write_one_arg (s, -1, argno, type, prototyped); } if (stdarg_p (fntype)) - { - s << sep << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_argp"; - i++; - sep = ", "; - } + argno = write_one_arg (s, -1, argno, ptr_type_node, true); if (DECL_STATIC_CHAIN (decl)) - { - s << sep << ".reg.u" << GET_MODE_BITSIZE (Pmode) - << reg_names [STATIC_CHAIN_REGNUM]; - i++; - sep = ", "; - } + argno = write_one_arg (s, -1, argno, ptr_type_node, true); - if (!i && strcmp (name, "main") == 0) + if (!argno && strcmp (name, "main") == 0) { - s << sep - << ".param.u32 %argc, .param.u" << GET_MODE_BITSIZE (Pmode) - << " %argv"; - i++; - sep = ", "; + argno = write_one_arg (s, -1, argno, integer_type_node, true); + argno = write_one_arg (s, -1, argno, ptr_type_node, true); } - if (i) + if (argno) s << ")"; s << (is_defn ? "\n" : ";\n"); @@ -705,63 +717,43 @@ nvptx_declare_function_name (FILE *file, { tree fntype = TREE_TYPE (decl); tree result_type = TREE_TYPE (fntype); - int argno = 0; + int argno = 0; + /* We construct the initial part of the function into a string + stream, in order to share the prototype writing code. */ std::stringstream s; write_fn_proto (s, true, name, decl); - fprintf (file, "%s", s.str().c_str()); - fprintf (file, "{\n"); + s << "{\n"; bool return_in_mem = (TYPE_MODE (result_type) != VOIDmode && !RETURN_IN_REG_P (TYPE_MODE (result_type))); if (return_in_mem) - { - fprintf (file, "\t.reg.u%d %%ar%d;\n", GET_MODE_BITSIZE (Pmode), argno); - fprintf (file, "\tld.param.u%d %%ar%d, [%%in_ar%d];\n", - GET_MODE_BITSIZE (Pmode), argno, argno); - argno++; - } - + argno = write_one_arg (s, 0, argno, ptr_type_node, true); + /* Declare and initialize incoming arguments. */ - tree args = DECL_ARGUMENTS (decl); - bool prototyped = false; - if (TYPE_ARG_TYPES (fntype)) + tree args = TYPE_ARG_TYPES (fntype); + bool prototyped = true; + if (!args) { - args = TYPE_ARG_TYPES (fntype); - prototyped = true; + args = DECL_ARGUMENTS (decl); + prototyped = false; } for (; args != NULL_TREE; args = TREE_CHAIN (args)) { tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args); - machine_mode mode = TYPE_MODE (type); - int count = 1; - if (mode == VOIDmode) - break; + if (type != void_type_node) + argno = write_one_arg (s, 0, argno, type, prototyped); + } - if (!PASS_IN_REG_P (mode, type)) - mode = Pmode; + if (stdarg_p (fntype)) + argno = write_one_arg (s, ARG_POINTER_REGNUM, argno, ptr_type_node, true); - machine_mode split = maybe_split_mode (mode); - if (split != VOIDmode) - { - count = 2; - mode = split; - } - else if (!prototyped && !AGGREGATE_TYPE_P (type) && mode == SFmode) - mode = DFmode; + if (DECL_STATIC_CHAIN (decl)) + argno = write_one_arg (s, STATIC_CHAIN_REGNUM, argno, ptr_type_node, true); - mode = arg_promotion (mode); - while (count--) - { - fprintf (file, "\t.reg%s %%ar%d;\n", - nvptx_ptx_type_from_mode (mode, false), argno); - fprintf (file, "\tld.param%s %%ar%d, [%%in_ar%d];\n", - nvptx_ptx_type_from_mode (mode, false), argno, argno); - argno++; - } - } + fprintf (file, "%s", s.str().c_str()); /* C++11 ABI causes us to return a reference to the passed in pointer for return_in_mem. */ @@ -773,16 +765,9 @@ nvptx_declare_function_name (FILE *file, nvptx_ptx_type_from_mode (mode, false)); } - if (stdarg_p (fntype)) - { - fprintf (file, "\t.reg.u%d %%argp;\n", GET_MODE_BITSIZE (Pmode)); - fprintf (file, "\tld.param.u%d %%argp, [%%in_argp];\n", - GET_MODE_BITSIZE (Pmode)); - } - fprintf (file, "\t.reg.u%d %s;\n", GET_MODE_BITSIZE (Pmode), reg_names[OUTGOING_STATIC_CHAIN_REGNUM]); - + /* Declare the pseudos we have as ptx registers. */ int maxregs = max_reg_num (); for (int i = LAST_VIRTUAL_REGISTER + 1; i < maxregs; i++)