From patchwork Mon Dec 9 15:18:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 299094 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 518772C008F for ; Tue, 10 Dec 2013 02:19:06 +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 :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; q=dns; s=default; b=HT4LloA4UYqwAjqZR 1v7pMS0ZV5wpJeDlp568Tr/Z7KKaDz3g1WDjDmaPOyG7Z2Q0633i9Ofs/5mM/4PG zfyT9pBRlKTpQv/0MRPtepeIA9FD9s9n+upmvVP4PTnLqaGOvM02mRcQzV+BxGO9 x8cA9NcoNZqmvCH+hbbyWC8UmI= 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 :message-id:date:from:mime-version:to:subject:references :in-reply-to:content-type; s=default; bh=2wDdIDMq/PEVAF8fRS/f1VZ 1pSE=; b=KBUHSfpD1pBl8IYDsOPe7fnYjudAdoMveRx3UelzFkXMB7Zj5Zdxk2K eD6bfv2ZL27RgreM0hweIlPOQnaTOYoO0tg5EXi3DOqGxlerG3LOUnt2ewz4dCRj eePRwyYYVJamiLJvItpHPDVNXqEdt+hhn0OsvS735ntTyotwC7C0= Received: (qmail 28638 invoked by alias); 9 Dec 2013 15:18:59 -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 28628 invoked by uid 89); 9 Dec 2013 15:18:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from Unknown (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Dec 2013 15:18:30 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1Vq2b8-00016A-US from Bernd_Schmidt@mentor.com for gcc-patches@gcc.gnu.org; Mon, 09 Dec 2013 07:18:14 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 9 Dec 2013 07:18:15 -0800 Received: from [127.0.0.1] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.2.247.3; Mon, 9 Dec 2013 15:18:12 +0000 Message-ID: <52A5DF2E.80208@codesourcery.com> Date: Mon, 9 Dec 2013 16:18:06 +0100 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130926 Thunderbird/17.0.9 MIME-Version: 1.0 To: GCC Patches Subject: [gomp4, 21/23] Order variables, and print undefined symbols in assembly output References: <52A5D8D4.2030803@codesourcery.com> In-Reply-To: <52A5D8D4.2030803@codesourcery.com> ptx assembly has some unusual requirements, Symbols must be declared before use, and only functions (but not variables) can have forward declarations. This patch deals with getting variable definitions in the right order, emitting declarations for undefined symbols, and emitting declarations for all functions, whether defined or not. All of these are required by the ptx assembler. We don't quite produce everything in the right order (function declarations are written too late), so this still needs an extra sorting step after compilation, for which we currently use a small "assembler" shell script. gcc/ * target.def (need_var_decl_before_use, assemble_undefined_decl, predeclare_function): New hooks. * hooks.c (hook_void_FILEptr_constcharptr_const_tree): New function. * hooks.h (hook_void_FILEptr_constcharptr_const_tree): Declare. * doc/tm.texi.in (TARGET_ASM_PREDECLARE_FUNCTION, TARGET_ASM_NEED_VAR_DECL_BEFORE_USE, TARGET_ASM_ASSEMBLE_UNDEFINED_DECL): Add. * doc/tm.texi: Regenerate. * cgraph.h (struct symtab_node_base): New flag visited. * cgraphunit.c (declare_all_functions): New static function. (compile): Call it. * output.h (assemble_undefined_decl): Declare. (get_fnname_from_decl): Declare. * varasm.c (assemble_undefined_decl): New function. (get_fnname_from_decl): New function. * final.c (rest_of_handle_final): Use it. * varpool.c (output_vars_in_decl_initial): New static function. (varpool_assemble_decl): Call it if declaration before use is needed. Return early if node was visited. Set visited flag. (varpool_output_variables): Call assemble_undefined_decl for nodes without a definition. ------------------------------------------------------------------------ Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi.orig +++ gcc/doc/tm.texi @@ -8007,6 +8007,12 @@ usual manner as a label (by means of @co You may wish to use @code{ASM_OUTPUT_TYPE_DIRECTIVE} in this target hook. @end deftypefn +@deftypefn {Target Hook} void TARGET_ASM_PREDECLARE_FUNCTION (FILE *@var{file}, const char *@var{name}, const_tree @var{decl}) +A target hook to output to the stdio stream @var{file} any text necessary +for declaring the name @var{name} of a function which will be output later on +in the compilation. Most targets do not require this hook to be defined. +@end deftypefn + @defmac ASM_DECLARE_REGISTER_GLOBAL (@var{stream}, @var{decl}, @var{regno}, @var{name}) A C statement (sans semicolon) to output to the stdio stream @var{stream} any text necessary for claiming a register @var{regno} @@ -8047,6 +8053,20 @@ global; that is, available for reference The default implementation uses the TARGET_ASM_GLOBALIZE_LABEL target hook. @end deftypefn +@deftypevr {Target Hook} bool TARGET_ASM_NEED_VAR_DECL_BEFORE_USE +If defined to true, this target hook causes the compiler to try to emit +variable definitions in an order that ensures that references to a variable +in an initializer occur only after it has been output. If there are circular +references, the order is chosen at random. +@end deftypevr + +@deftypefn {Target Hook} void TARGET_ASM_ASSEMBLE_UNDEFINED_DECL (FILE *@var{stream}, const char *@var{name}, const_tree @var{decl}) +This target hook is a function to output to the stdio stream +@var{stream} some commands that will declare the name associated with +@var{decl} which is not defined in the current translation unit. Most +assemblers do not require anything to be output in this case. +@end deftypefn + @defmac ASM_WEAKEN_LABEL (@var{stream}, @var{name}) A C statement (sans semicolon) to output to the stdio stream @var{stream} some commands that will make the label @var{name} weak; Index: gcc/doc/tm.texi.in =================================================================== --- gcc/doc/tm.texi.in.orig +++ gcc/doc/tm.texi.in @@ -5798,6 +5798,8 @@ You may wish to use @code{ASM_OUTPUT_TYP @hook TARGET_ASM_DECLARE_CONSTANT_NAME +@hook TARGET_ASM_PREDECLARE_FUNCTION + @defmac ASM_DECLARE_REGISTER_GLOBAL (@var{stream}, @var{decl}, @var{regno}, @var{name}) A C statement (sans semicolon) to output to the stdio stream @var{stream} any text necessary for claiming a register @var{regno} @@ -5825,6 +5827,10 @@ You may wish to use @code{ASM_OUTPUT_SIZ @hook TARGET_ASM_GLOBALIZE_DECL_NAME +@hook TARGET_ASM_NEED_VAR_DECL_BEFORE_USE + +@hook TARGET_ASM_ASSEMBLE_UNDEFINED_DECL + @defmac ASM_WEAKEN_LABEL (@var{stream}, @var{name}) A C statement (sans semicolon) to output to the stdio stream @var{stream} some commands that will make the label @var{name} weak; Index: gcc/hooks.c =================================================================== --- gcc/hooks.c.orig +++ gcc/hooks.c @@ -139,6 +139,13 @@ hook_void_FILEptr_constcharptr (FILE *a { } +/* Generic hook that takes (FILE *, const char *, constr_tree *) and does + nothing. */ +void +hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *, const_tree) +{ +} + /* Generic hook that takes (FILE *, rtx) and returns false. */ bool hook_bool_FILEptr_rtx_false (FILE *a ATTRIBUTE_UNUSED, Index: gcc/hooks.h =================================================================== --- gcc/hooks.h.orig +++ gcc/hooks.h @@ -68,6 +68,8 @@ extern void hook_void_void (void); extern void hook_void_constcharptr (const char *); extern void hook_void_rtx_int (rtx, int); extern void hook_void_FILEptr_constcharptr (FILE *, const char *); +extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *, + const_tree); extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx); extern void hook_void_rtx (rtx); extern void hook_void_tree (tree); Index: gcc/target.def =================================================================== --- gcc/target.def.orig +++ gcc/target.def @@ -158,6 +158,24 @@ global; that is, available for reference The default implementation uses the TARGET_ASM_GLOBALIZE_LABEL target hook.", void, (FILE *stream, tree decl), default_globalize_decl_name) +DEFHOOKPOD +(need_var_decl_before_use, + "If defined to true, this target hook causes the compiler to try to emit\n\ +variable definitions in an order that ensures that references to a variable\n\ +in an initializer occur only after it has been output. If there are circular\n\ +references, the order is chosen at random.", + bool, false) + +/* Output code that will declare an external variable. */ +DEFHOOK +(assemble_undefined_decl, + "This target hook is a function to output to the stdio stream\n\ +@var{stream} some commands that will declare the name associated with\n\ +@var{decl} which is not defined in the current translation unit. Most\n\ +assemblers do not require anything to be output in this case.", + void, (FILE *stream, const char *name, const_tree decl), + hook_void_FILEptr_constcharptr_const_tree) + /* Output code that will emit a label for unwind info, if this target requires such labels. Second argument is the decl the unwind info is associated with, third is a boolean: true if @@ -258,6 +276,14 @@ You may wish to use @code{ASM_OUTPUT_TYP void, (FILE *file, const char *name, const_tree expr, HOST_WIDE_INT size), default_asm_declare_constant_name) +/* Output a forward declaration of a function. */ +DEFHOOK +(predeclare_function, + "A target hook to output to the stdio stream @var{file} any text necessary\n\ +for declaring the name @var{name} of a function which will be output later on\n\ +in the compilation. Most targets do not require this hook to be defined.", + void, (FILE *file, const char *name, const_tree decl), NULL) + /* Emit a ttype table reference to a typeinfo object. */ DEFHOOK (ttype, Index: gcc/cgraph.h =================================================================== --- gcc/cgraph.h.orig +++ gcc/cgraph.h @@ -104,6 +104,9 @@ public: multiple partitions. */ unsigned in_other_partition : 1; + /* Set when a symbol is being visited. Used when recursively outputting + definitions. */ + unsigned visited : 1; /*** other flags. ***/ Index: gcc/final.c =================================================================== --- gcc/final.c.orig +++ gcc/final.c @@ -4422,17 +4422,7 @@ leaf_renumber_regs_insn (rtx in_rtx) static unsigned int rest_of_handle_final (void) { - rtx x; - const char *fnname; - - /* Get the function's name, as described by its RTL. This may be - different from the DECL_NAME name used in the source file. */ - - x = DECL_RTL (current_function_decl); - gcc_assert (MEM_P (x)); - x = XEXP (x, 0); - gcc_assert (GET_CODE (x) == SYMBOL_REF); - fnname = XSTR (x, 0); + const char *fnname = get_fnname_from_decl (current_function_decl); assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c.orig +++ gcc/cgraphunit.c @@ -1830,6 +1830,31 @@ expand_function (struct cgraph_node *nod } +/* For targets that require it, write out extra declarations of all functions + encountered, whether defined in this translation unit or not. */ + +static void +declare_all_functions (void) +{ + if (targetm.asm_out.predeclare_function == NULL) + return; + + struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); + int order_pos; + + order_pos = ipa_reverse_postorder (order); + gcc_assert (order_pos == cgraph_n_nodes); + + for (int i = 0; i < order_pos; i++) + { + tree decl = order[i]->decl; + const char *name = get_fnname_from_decl (decl); + targetm.asm_out.predeclare_function (asm_out_file, name, decl); + } + + free (order); +} + /* Expand all functions that must be output. Attempt to topologically sort the nodes so function is output when @@ -2210,6 +2235,7 @@ compile (void) output_asm_statements (); expand_all_functions (); + declare_all_functions (); varpool_output_variables (); } Index: gcc/varasm.c =================================================================== --- gcc/varasm.c.orig +++ gcc/varasm.c @@ -1583,6 +1583,18 @@ decide_function_section (tree decl) in_cold_section_p = first_function_block_is_cold; } +/* Get the function's name, as described by its RTL. This may be + different from the DECL_NAME name used in the source file. */ +const char * +get_fnname_from_decl (tree decl) +{ + rtx x = DECL_RTL (decl); + gcc_assert (MEM_P (x)); + x = XEXP (x, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + return XSTR (x, 0); +} + /* Output assembler code for the constant pool of a function and associated with defining the name of the function. DECL describes the function. NAME is the function's name. For the constant pool, we use the current @@ -1949,6 +1961,15 @@ assemble_variable_contents (tree decl, c } } +/* Write out assembly for the variable DECL, which is not defined in + the current translation unit. */ +void +assemble_undefined_decl (tree decl) +{ + const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + targetm.asm_out.assemble_undefined_decl (asm_out_file, name, decl); +} + /* Assemble everything that is needed for a variable or function declaration. Not used for automatic variables, and not used for function definitions. Should not be called for variables of incomplete structure type. Index: gcc/output.h =================================================================== --- gcc/output.h.orig +++ gcc/output.h @@ -176,6 +176,9 @@ extern void default_assemble_visibility for an `asm' keyword used between functions. */ extern void assemble_asm (tree); +/* Get the function's name from a decl, as described by its RTL. */ +extern const char *get_fnname_from_decl (tree); + /* Output assembler code for the constant pool of a function and associated with defining the name of the function. DECL describes the function. NAME is the function's name. For the constant pool, we use the current @@ -201,6 +204,10 @@ extern void assemble_variable (tree, int into the preinit array. */ extern void assemble_vtv_preinit_initializer (tree); +/* Assemble everything that is needed for a variable declaration that has + no definition in the current translation unit. */ +extern void assemble_undefined_decl (tree); + /* Compute the alignment of variable specified by DECL. DONT_OUTPUT_DATA is from assemble_variable. */ extern void align_variable (tree decl, bool dont_output_data); Index: gcc/varpool.c =================================================================== --- gcc/varpool.c.orig +++ gcc/varpool.c @@ -418,6 +418,27 @@ assemble_aliases (struct varpool_node *n } } +/* Called through walk_tree to examine an initializer, and output all + variables referenced in it. Used to ensure definition before use for + assemblers that require this. */ + +static tree +output_vars_in_decl_initial (tree *xp, int *, void *) +{ + tree x = *xp; + enum tree_code code = TREE_CODE (x); + + if (code == VAR_DECL) + { + if (TREE_ASM_WRITTEN (x) || DECL_HAS_VALUE_EXPR_P (x)) + return NULL; + + struct varpool_node *node = varpool_node_for_decl (x); + varpool_assemble_decl (node); + } + return NULL; +} + /* Output one variable, if necessary. Return whether we output it. */ bool @@ -430,6 +451,10 @@ varpool_assemble_decl (struct varpool_no if (node->alias) return false; + if (node->visited + || TREE_ASM_WRITTEN (decl)) + return false; + /* Constant pool is output from RTL land when the reference survive till this level. */ if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl)) @@ -454,6 +479,13 @@ varpool_assemble_decl (struct varpool_no if (!node->in_other_partition && !DECL_EXTERNAL (decl)) { + node->visited = true; + if (targetm.asm_out.need_var_decl_before_use + && DECL_INITIAL (decl)) + walk_tree (&DECL_INITIAL (decl), + output_vars_in_decl_initial, NULL, NULL); + node->visited = false; + assemble_variable (decl, 0, 1, 0); gcc_assert (TREE_ASM_WRITTEN (decl)); node->definition = true; @@ -588,6 +620,9 @@ varpool_output_variables (void) FOR_EACH_DEFINED_VARIABLE (node) if (varpool_assemble_decl (node)) changed = true; + FOR_EACH_VARIABLE (node) + if (!node->definition) + assemble_undefined_decl (node->decl); timevar_pop (TV_VAROUT); return changed; }