aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2019-11-30 22:03:25 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2019-11-30 21:03:25 +0000
commitd7ddfbcb7fa6e700639c9b916bf8a5ed15600950 (patch)
tree3e8ad36922e2df05cdc896aec48daa30135163d6 /gcc/cgraphunit.c
parent65ef05d0b7fb429c5760189e638c441dc3da33f4 (diff)
downloadgcc-d7ddfbcb7fa6e700639c9b916bf8a5ed15600950.zip
gcc-d7ddfbcb7fa6e700639c9b916bf8a5ed15600950.tar.gz
gcc-d7ddfbcb7fa6e700639c9b916bf8a5ed15600950.tar.bz2
cgraph.h (symtab_node): Add symver flag.
2019-11-30 Jan Hubicka <hubicka@ucw.cz> * cgraph.h (symtab_node): Add symver flag. * cgraphunit.c (process_symver_attribute): New. (process_common_attributes): Use process_symver_attribute. * lto-cgraph.c (lto_output_node): Stream symver. (lto_output_varpool_node): Stream symver. (input_overwrite_node): Stream symver. (input_varpool_node): Stream symver. * output.h (do_assemble_symver): Decalre. * symtab.c (symtab_node::dump_base): Dump symver. (symtab_node::verify_base): Verify symver. (symtab_node::resolve_alias): Handle symver. * varasm.c (do_assemble_symver): New function. * varpool.c (varpool_node::assemble_aliases): Use it. * doc/extend.texi: (symver attribute): Document. * config/elfos.h (ASM_OUTPUT_SYMVER_DIRECTIVE): New. c-family/ChangeLog: 2019-11-30 Jan Hubicka <hubicka@ucw.cz> * c-attribs.c (handle_symver_attribute): New function (c_common_attributes): Add symver. From-SVN: r278878
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c92
1 files changed, 90 insertions, 2 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index aa26160..75ff10b 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -711,6 +711,89 @@ symbol_table::process_same_body_aliases (void)
cpp_implicit_aliases_done = true;
}
+/* Process a symver attribute. */
+
+static void
+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)))
+ {
+ 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);
+
+ 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),
+ "weakref 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;
+ }
+
+ /* 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. */
static void
@@ -730,6 +813,7 @@ process_common_attributes (symtab_node *node, tree decl)
if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
node->no_reorder = 1;
+ process_symver_attribute (node);
}
/* Look for externally_visible and used attributes and mark cgraph nodes
@@ -2137,8 +2221,12 @@ cgraph_node::assemble_thunks_and_aliases (void)
/* Force assemble_alias to really output the alias this time instead
of buffering it in same alias pairs. */
TREE_ASM_WRITTEN (decl) = 1;
- do_assemble_alias (alias->decl,
- DECL_ASSEMBLER_NAME (decl));
+ if (alias->symver)
+ do_assemble_symver (alias->decl,
+ DECL_ASSEMBLER_NAME (decl));
+ else
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (decl));
alias->assemble_thunks_and_aliases ();
TREE_ASM_WRITTEN (decl) = saved_written;
}