xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/sol2.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* General Solaris system support.
2    Copyright (C) 2004-2022 Free Software Foundation, Inc.
3    Contributed by CodeSourcery, LLC.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "rtl.h"
26 #include "tree.h"
27 #include "memmodel.h"
28 #include "tm_p.h"
29 #include "stringpool.h"
30 #include "attribs.h"
31 #include "diagnostic-core.h"
32 #include "varasm.h"
33 #include "output.h"
34 #include "opts.h"
35 
36 tree solaris_pending_aligns, solaris_pending_inits, solaris_pending_finis;
37 
38 /* Attach any pending attributes for DECL to the list in *ATTRIBUTES.
39    Pending attributes come from #pragma or _Pragma, so this code is
40    only useful in the C family front ends, but it is included in
41    all languages to avoid changing the target machine initializer
42    depending on the language.  */
43 
44 void
solaris_insert_attributes(tree decl,tree * attributes)45 solaris_insert_attributes (tree decl, tree *attributes)
46 {
47   tree *x, next;
48 
49   if (solaris_pending_aligns != NULL && TREE_CODE (decl) == VAR_DECL)
50     for (x = &solaris_pending_aligns; *x; x = &TREE_CHAIN (*x))
51       {
52 	tree name = TREE_PURPOSE (*x);
53 	tree value = TREE_VALUE (*x);
54 	if (DECL_NAME (decl) == name)
55 	  {
56 	    if (lookup_attribute ("aligned", DECL_ATTRIBUTES (decl))
57 		|| lookup_attribute ("aligned", *attributes))
58 	      warning (0, "ignoring %<#pragma align%> for explicitly "
59 		       "aligned %q+D", decl);
60 	    else
61 	      *attributes = tree_cons (get_identifier ("aligned"), value,
62 				       *attributes);
63 	    next = TREE_CHAIN (*x);
64 	    ggc_free (*x);
65 	    *x = next;
66 	    break;
67 	  }
68       }
69 
70   if (solaris_pending_inits != NULL && TREE_CODE (decl) == FUNCTION_DECL)
71     for (x = &solaris_pending_inits; *x; x = &TREE_CHAIN (*x))
72       {
73 	tree name = TREE_PURPOSE (*x);
74 	if (DECL_NAME (decl) == name)
75 	  {
76 	    *attributes = tree_cons (get_identifier ("init"), NULL,
77 				     *attributes);
78 	    TREE_USED (decl) = 1;
79 	    DECL_PRESERVE_P (decl) = 1;
80 	    next = TREE_CHAIN (*x);
81 	    ggc_free (*x);
82 	    *x = next;
83 	    break;
84 	  }
85       }
86 
87   if (solaris_pending_finis != NULL && TREE_CODE (decl) == FUNCTION_DECL)
88     for (x = &solaris_pending_finis; *x; x = &TREE_CHAIN (*x))
89       {
90 	tree name = TREE_PURPOSE (*x);
91 	if (DECL_NAME (decl) == name)
92 	  {
93 	    *attributes = tree_cons (get_identifier ("fini"), NULL,
94 				     *attributes);
95 	    TREE_USED (decl) = 1;
96 	    DECL_PRESERVE_P (decl) = 1;
97 	    next = TREE_CHAIN (*x);
98 	    ggc_free (*x);
99 	    *x = next;
100 	    break;
101 	  }
102       }
103 }
104 
105 /* Output initializer or finalizer entries for DECL to FILE.  */
106 
107 void
solaris_output_init_fini(FILE * file,tree decl)108 solaris_output_init_fini (FILE *file, tree decl)
109 {
110   if (lookup_attribute ("init", DECL_ATTRIBUTES (decl)))
111     {
112       fprintf (file, "\t.pushsection\t" SECTION_NAME_FORMAT "\n", ".init");
113       ASM_OUTPUT_CALL (file, decl);
114       fprintf (file, "\t.popsection\n");
115     }
116 
117   if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl)))
118     {
119       fprintf (file, "\t.pushsection\t" SECTION_NAME_FORMAT "\n", ".fini");
120       ASM_OUTPUT_CALL (file, decl);
121       fprintf (file, "\t.popsection\n");
122     }
123 }
124 
125 /* Emit an assembler directive to set symbol for DECL visibility to
126    the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
127 
128 void
solaris_assemble_visibility(tree decl,int vis ATTRIBUTE_UNUSED)129 solaris_assemble_visibility (tree decl, int vis ATTRIBUTE_UNUSED)
130 {
131 #ifdef HAVE_GAS_HIDDEN
132   /* Sun as uses .symbolic for STV_PROTECTED.  STV_INTERNAL is marked as
133      `currently reserved', but the linker treats it like STV_HIDDEN.  Sun
134      Studio 12.1 cc emits .hidden instead.
135 
136      There are 3 Sun extensions GCC doesn't yet know about: STV_EXPORTED,
137      STV_SINGLETON, and STV_ELIMINATE.
138 
139      See Linker and Libraries Guide, Ch. 2, Link-Editor, Defining
140      Additional Symbols, and Ch. 7, Object-File Format, Symbol Table
141      Section.  */
142 
143   static const char * const visibility_types[] = {
144     NULL, "symbolic", "hidden", "hidden"
145   };
146 
147   const char *name, *type;
148   tree id = DECL_ASSEMBLER_NAME (decl);
149 
150   while (IDENTIFIER_TRANSPARENT_ALIAS (id))
151     id = TREE_CHAIN (id);
152   name = IDENTIFIER_POINTER (id);
153   type = visibility_types[vis];
154 
155   fprintf (asm_out_file, "\t.%s\t", type);
156   assemble_name (asm_out_file, name);
157   fprintf (asm_out_file, "\n");
158 #else
159   if (!DECL_ARTIFICIAL (decl))
160     warning (OPT_Wattributes, "visibility attribute not supported "
161 			      "in this configuration; ignored");
162 #endif
163 }
164 
165 /* Group section information entry stored in solaris_comdat_htab.  */
166 
167 typedef struct comdat_entry
168 {
169   const char *name;
170   unsigned int flags;
171   tree decl;
172   const char *sig;
173 } comdat_entry;
174 
175 /* Helpers for maintaining solaris_comdat_htab.  */
176 
177 struct comdat_entry_hasher : nofree_ptr_hash <comdat_entry>
178 {
179   static inline hashval_t hash (const comdat_entry *);
180   static inline bool equal (const comdat_entry *, const comdat_entry *);
181   static inline void remove (comdat_entry *);
182 };
183 
184 inline hashval_t
hash(const comdat_entry * entry)185 comdat_entry_hasher::hash (const comdat_entry *entry)
186 {
187   return htab_hash_string (entry->sig);
188 }
189 
190 inline bool
equal(const comdat_entry * entry1,const comdat_entry * entry2)191 comdat_entry_hasher::equal (const comdat_entry *entry1,
192 			    const comdat_entry *entry2)
193 {
194   return strcmp (entry1->sig, entry2->sig) == 0;
195 }
196 
197 /* Hash table of group signature symbols.  */
198 
199 static hash_table<comdat_entry_hasher> *solaris_comdat_htab;
200 
201 /* Output assembly to switch to COMDAT group section NAME with attributes
202    FLAGS and group signature symbol DECL, using Sun as syntax.  */
203 
204 void
solaris_elf_asm_comdat_section(const char * name,unsigned int flags,tree decl)205 solaris_elf_asm_comdat_section (const char *name, unsigned int flags, tree decl)
206 {
207   const char *signature;
208   char *section;
209   comdat_entry entry, **slot;
210 
211   if (TREE_CODE (decl) == IDENTIFIER_NODE)
212     signature = IDENTIFIER_POINTER (decl);
213   else
214     signature = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl));
215 
216   /* Sun as requires group sections to be fragmented, i.e. to have names of
217      the form <section>%<fragment>.  Strictly speaking this is only
218      necessary to support cc -xF, but is enforced globally in violation of
219      the ELF gABI.  We keep the section names generated by GCC (generally
220      of the form .text.<signature>) and append %<signature> to pacify as,
221      despite the redundancy.  */
222   section = concat (name, "%", signature, NULL);
223 
224   /* Clear SECTION_LINKONCE flag so targetm.asm_out.named_section only
225      emits this as a regular section.  Emit section before .group
226      directive since Sun as treats undeclared sections as @progbits,
227      which conflicts with .bss* sections which are @nobits.  */
228   targetm.asm_out.named_section (section, flags & ~SECTION_LINKONCE, decl);
229 
230   /* Sun as separates declaration of a group section and of the group
231      itself, using the .group directive and the #comdat flag.  */
232   fprintf (asm_out_file, "\t.group\t%s," SECTION_NAME_FORMAT ",#comdat\n",
233 	   signature, section);
234 
235   /* Unlike GNU as, group signature symbols need to be defined explicitly
236      for Sun as.  With a few exceptions, this is already the case.  To
237      identify the missing ones without changing the affected frontents,
238      remember the signature symbols and emit those not marked
239      TREE_SYMBOL_REFERENCED in solaris_file_end.  */
240   if (!solaris_comdat_htab)
241     solaris_comdat_htab = new hash_table<comdat_entry_hasher> (37);
242 
243   entry.sig = signature;
244   slot = solaris_comdat_htab->find_slot (&entry, INSERT);
245 
246   if (*slot == NULL)
247     {
248       *slot = XCNEW (comdat_entry);
249       /* Remember fragmented section name.  */
250       (*slot)->name = section;
251       /* Emit as regular section, .group declaration has already been done.  */
252       (*slot)->flags = flags & ~SECTION_LINKONCE;
253       (*slot)->decl = decl;
254       (*slot)->sig = signature;
255     }
256 }
257 
258 /* Define unreferenced COMDAT group signature symbol corresponding to SLOT.  */
259 
260 int
solaris_define_comdat_signature(comdat_entry ** slot,void * aux ATTRIBUTE_UNUSED)261 solaris_define_comdat_signature (comdat_entry **slot,
262 				 void *aux ATTRIBUTE_UNUSED)
263 {
264   comdat_entry *entry = *slot;
265   tree decl = entry->decl;
266 
267   if (TREE_CODE (decl) != IDENTIFIER_NODE)
268     decl = DECL_COMDAT_GROUP (decl);
269 
270   if (!TREE_SYMBOL_REFERENCED (decl))
271     {
272       /* Switch to group section, otherwise Sun as complains
273 	 `Group Id symbol defined outside of group'.  */
274       switch_to_section (get_section (entry->name, entry->flags, entry->decl));
275 
276       ASM_OUTPUT_LABEL (asm_out_file, entry->sig);
277     }
278 
279   /* Continue with scan.  */
280   return 1;
281 }
282 
283 /* Emit unreferenced COMDAT group signature symbols for Sun as.  */
284 
285 void
solaris_file_end(void)286 solaris_file_end (void)
287 {
288   if (!solaris_comdat_htab)
289     return;
290 
291   solaris_comdat_htab->traverse <void *, solaris_define_comdat_signature>
292     (NULL);
293 }
294 
295 void
solaris_override_options(void)296 solaris_override_options (void)
297 {
298   /* Older versions of Solaris ld cannot handle CIE version 3 in .eh_frame.
299      Don't emit DWARF3/4 unless specifically selected if so.  */
300   if (!HAVE_LD_EH_FRAME_CIEV3 && !OPTION_SET_P (dwarf_version))
301     dwarf_version = 2;
302 }
303