From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1059) id EF877386186A; Fri, 28 Aug 2020 16:04:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EF877386186A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1598630671; bh=gZwluIbWdbWkEaxYvjyDLYTq2uSDF4ftyTwhZSUX/pU=; h=From:To:Subject:Date:From; b=Stj23BfV0mnA6d14j7zs+2qpLijWbFz897SVh4szTNpKjQck2MJpxcZ9vt4mhbXEu OZjwac1H2GmnYzeWMqtnIfnC1Bs/Oe7nm/8v/wRTTi3HLft9Ki0JokEGA+w7NsLg7Q 9cOqpu6Qem3p9NA5/fMq3wZSlmYw6TF7yqfZ03G4= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Nathan Sidwell To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/c++-modules] IPA symver: allow multiple symvers for a definition X-Act-Checkin: gcc X-Git-Author: Martin Liska X-Git-Refname: refs/heads/devel/c++-modules X-Git-Oldrev: d58e7173ef964ddac3ab3ad8cc97de8f9f3b32ee X-Git-Newrev: 363080bb8bd2cca81dd9e2e774910a8c8226f430 Message-Id: <20200828160431.EF877386186A@sourceware.org> Date: Fri, 28 Aug 2020 16:04:31 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Aug 2020 16:04:32 -0000 https://gcc.gnu.org/g:363080bb8bd2cca81dd9e2e774910a8c8226f430 commit 363080bb8bd2cca81dd9e2e774910a8c8226f430 Author: Martin Liska Date: Mon Aug 24 13:21:10 2020 +0200 IPA symver: allow multiple symvers for a definition gcc/ChangeLog: * cgraphunit.c (process_symver_attribute): Allow multiple symver attributes for one symbol. * doc/extend.texi: Document the change. gcc/testsuite/ChangeLog: * lib/target-supports-dg.exp: Add dg-require-symver. * lib/target-supports.exp: Likewise. * gcc.dg/ipa/symver1.c: New test. Diff: --- gcc/cgraphunit.c | 143 ++++++++++++++++--------------- gcc/doc/extend.texi | 16 ++-- gcc/testsuite/gcc.dg/ipa/symver1.c | 11 +++ gcc/testsuite/lib/target-supports-dg.exp | 10 +++ gcc/testsuite/lib/target-supports.exp | 12 +++ 5 files changed, 116 insertions(+), 76 deletions(-) diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 0b1009d0dea..fa3aec79a48 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -720,80 +720,81 @@ process_symver_attribute (symtab_node *n) { tree value = lookup_attribute ("symver", DECL_ATTRIBUTES (n->decl)); - if (!value) - return; - if (lookup_attribute ("symver", TREE_CHAIN (value))) + for (; value != NULL; value = TREE_CHAIN (value)) { - error_at (DECL_SOURCE_LOCATION (n->decl), - "multiple versions for one symbol"); - return; - } - tree symver = get_identifier_with_length - (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (value))), - TREE_STRING_LENGTH (TREE_VALUE (TREE_VALUE (value)))); - symtab_node *def = symtab_node::get_for_asmname (symver); + /* Starting from bintuils 2.35 gas supports: + # Assign foo to bar@V1 and baz@V2. + .symver foo, bar@V1 + .symver foo, baz@V2 + */ + + tree symver = get_identifier_with_length + (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (value))), + TREE_STRING_LENGTH (TREE_VALUE (TREE_VALUE (value)))); + symtab_node *def = symtab_node::get_for_asmname (symver); + + if (def) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "duplicate definition of a symbol version"); + inform (DECL_SOURCE_LOCATION (def->decl), + "same version was previously defined here"); + return; + } + if (!n->definition) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "symbol needs to be defined to have a version"); + return; + } + if (DECL_COMMON (n->decl)) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "common symbol cannot be versioned"); + return; + } + if (DECL_COMDAT (n->decl)) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "comdat symbol cannot be versioned"); + return; + } + if (n->weakref) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "% cannot be versioned"); + return; + } + if (!TREE_PUBLIC (n->decl)) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "versioned symbol must be public"); + return; + } + if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT) + { + error_at (DECL_SOURCE_LOCATION (n->decl), + "versioned symbol must have default visibility"); + return; + } - if (def) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "duplicate definition of a symbol version"); - inform (DECL_SOURCE_LOCATION (def->decl), - "same version was previously defined here"); - return; - } - if (!n->definition) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "symbol needs to be defined to have a version"); - return; - } - if (DECL_COMMON (n->decl)) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "common symbol cannot be versioned"); - return; - } - if (DECL_COMDAT (n->decl)) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "comdat symbol cannot be versioned"); - return; - } - if (n->weakref) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "% cannot be versioned"); - return; + /* Create new symbol table entry representing the version. */ + tree new_decl = copy_node (n->decl); + + DECL_INITIAL (new_decl) = NULL_TREE; + if (TREE_CODE (new_decl) == FUNCTION_DECL) + DECL_STRUCT_FUNCTION (new_decl) = NULL; + SET_DECL_ASSEMBLER_NAME (new_decl, symver); + TREE_PUBLIC (new_decl) = 1; + DECL_ATTRIBUTES (new_decl) = NULL; + + symtab_node *symver_node = symtab_node::get_create (new_decl); + symver_node->alias = true; + symver_node->definition = true; + symver_node->symver = true; + symver_node->create_reference (n, IPA_REF_ALIAS, NULL); + symver_node->analyzed = true; } - if (!TREE_PUBLIC (n->decl)) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "versioned symbol must be public"); - return; - } - if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT) - { - error_at (DECL_SOURCE_LOCATION (n->decl), - "versioned symbol must have default visibility"); - return; - } - - /* Create new symbol table entry representing the version. */ - tree new_decl = copy_node (n->decl); - - DECL_INITIAL (new_decl) = NULL_TREE; - if (TREE_CODE (new_decl) == FUNCTION_DECL) - DECL_STRUCT_FUNCTION (new_decl) = NULL; - SET_DECL_ASSEMBLER_NAME (new_decl, symver); - TREE_PUBLIC (new_decl) = 1; - DECL_ATTRIBUTES (new_decl) = NULL; - - symtab_node *symver_node = symtab_node::get_create (new_decl); - symver_node->alias = true; - symver_node->definition = true; - symver_node->symver = true; - symver_node->create_reference (n, IPA_REF_ALIAS, NULL); - symver_node->analyzed = true; } /* Process attributes common for vars and functions. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2bb9b2f72f5..3b37aba5795 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3742,13 +3742,19 @@ foo_v1 (void) Will produce a @code{.symver foo_v1, foo@@VERS_1} directive in the assembler output. -It's an error to define multiple version of a given symbol. In such case -an alias can be used. +One can also define multiple version for a given symbol. @smallexample -__attribute__ ((__symver__ ("foo@@VERS_2"))) -__attribute__ ((alias ("foo_v1"))) -int symver_foo_v1 (void); +__attribute__ ((__symver__ ("foo@@VERS_2"), ("foo@@VERS_3"))) +int symver_foo_v1 (void) +@{ +@} + +__attribute__ ((__symver__ ("bar@@VERS_2")))) +__attribute__ ((__symver__ ("bar@@VERS_3")))) +int symver_bar_v1 (void) +@{ +@} @end smallexample This example creates an alias of @code{foo_v1} with symbol name diff --git a/gcc/testsuite/gcc.dg/ipa/symver1.c b/gcc/testsuite/gcc.dg/ipa/symver1.c new file mode 100644 index 00000000000..645de7ea259 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/symver1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +__attribute__ ((__symver__ ("foo@VER_2"))) +__attribute__ ((__symver__ ("foo@VER_3"))) +int foo() +{ + return 2; +} + +/* { dg-final { scan-assembler ".symver.*foo, foo@VER_2" } } */ +/* { dg-final { scan-assembler ".symver.*foo, foo@VER_3" } } */ diff --git a/gcc/testsuite/lib/target-supports-dg.exp b/gcc/testsuite/lib/target-supports-dg.exp index 5bb99f4e8f9..4a03eaae9ce 100644 --- a/gcc/testsuite/lib/target-supports-dg.exp +++ b/gcc/testsuite/lib/target-supports-dg.exp @@ -665,3 +665,13 @@ if { [info procs saved-dg-process-target] == [list] } { return [dg-process-target-1 $selector] } } + +# If this target does not support the "symver" attribute, skip this +# test. + +proc dg-require-symver { args } { + if { ![ check_symver_available ] } { + upvar dg-do-what dg-do-what + set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"] + } +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index c24330a27ab..f3fc5b80aea 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -10445,3 +10445,15 @@ proc check_effective_target_large_initializer { } { return 1 } +# Returns 1 if the target toolchain supports extended +# syntax of .symver directive, 0 otherwise. + +proc check_symver_available { } { + return [check_no_compiler_messages symver_available object { + int foo(void) { return 0; } + int main (void) { + asm volatile (".symver foo,foo@VER_1, local"); + return 0; + } + }] +}