5.13.5.2.2.1.1.2. Select output section
After finding out or creating the constant descriptor, next in output_constant_def invokes below function to try to output this constant in memory.
2509 static void
2510 maybe_output_constant_def_contents (struct constant_descriptor_tree *desc, in varasm.c
2511 int defer)
2512 {
2513 rtx symbol = XEXP (desc->rtl, 0);
2514 tree exp = desc->value;
2515
2516 if (flag_syntax_only )
2517 return ;
2518
2519 if (TREE_ASM_WRITTEN (exp))
2520 /* Already output; don't do it again. */
2521 return ;
2522
2523 /* The only constants that cannot safely be deferred, assuming the
2524 context allows it, are strings under flag_writable_strings. */
2525 if (defer && (TREE_CODE (exp) != STRING_CST || !flag_writable_strings ))
2526 {
2527 /* Increment n_deferred_constants if it exists. It needs to be at
2528 least as large as the number of constants actually referred to
2529 by the function. If it's too small we'll stop looking too early
2530 and fail to emit constants; if it's too large we'll only look
2531 through the entire function when we could have stopped earlier. */
2532 if (cfun )
2533 n_deferred_constants ++;
2534 return ;
2535 }
2536
2537 output_constant_def_contents (symbol);
2538 }
If assembler code has been writen, TREE_ASM_WRITTEN is set, no needs to output it again. Below at line 2545, SYMBOL_REF_DECL is the copied node of the constant in build_constant_desc at line 2454. It also invokes compute_reloc_for_constant for the node to decide reloc , then output_addressed_constants to output constants it contains.
2542 static void
2543 output_constant_def_contents (rtx symbol) in varasm.c
2544 {
2545 tree exp = SYMBOL_REF_DECL (symbol);
2546 const char *label = XSTR (symbol, 0);
2547 HOST_WIDE_INT size;
2548
2549 /* Make sure any other constants whose addresses appear in EXP
2550 are assigned label numbers. */
2551 int reloc = compute_reloc_for_constant (exp);
2552
2553 /* Align the location counter as required by EXP's data type. */
2554 int align = TYPE_ALIGN (TREE_TYPE (exp));
2555 #ifdef CONSTANT_ALIGNMENT
2556 align = CONSTANT_ALIGNMENT (exp, align);
2557 #endif
2558
2559 output_addressed_constants (exp);
2560
2561 /* We are no longer deferring this constant. */
2562 TREE_ASM_WRITTEN (exp) = 1;
2563
2564 if (IN_NAMED_SECTION (exp))
2565 named_section (exp, NULL, reloc);
2566 else
2567 (*targetm .asm_out.select_section ) (exp, reloc, align);
2568
2569 if (align > BITS_PER_UNIT)
2570 {
2571 ASM_OUTPUT_ALIGN (asm_out_file , floor_log2 (align / BITS_PER_UNIT));
2572 }
2573
2574 size = int_size_in_bytes (TREE_TYPE (exp));
2575 if (TREE_CODE (exp) == STRING_CST)
2576 size = MAX (TREE_STRING_LENGTH (exp), size);
2577
2578 /* Do any machine/system dependent processing of the constant. */
2579 #ifdef ASM_DECLARE_CONSTANT_NAME
2580 ASM_DECLARE_CONSTANT_NAME (asm_out_file , label, exp, size);
2581 #else
2582 /* Standard thing is just output label for the constant. */
2583 ASM_OUTPUT_LABEL (asm_out_file , label);
2584 #endif /* ASM_DECLARE_CONSTANT_NAME */
2585
2586 /* Output the value of EXP. */
2587 output_constant (exp, size, align);
2588 }
If the output section has been selected, for FUNCTION_DECL and VAR_DECL node, IN_NANED_SECTION returns true. Otherwise invokes target hook select_section , which points to following function.
4792 void
4793 default_select_section (tree decl, int reloc, in varasm.c
4794 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4795 {
4796 bool readonly = false;
4797
4798 if (DECL_P (decl))
4799 {
4800 if (decl_readonly_section (decl, reloc))
4801 readonly = true;
4802 }
4803 else if (TREE_CODE (decl) == CONSTRUCTOR)
4804 {
4805 if (! ((flag_pic && reloc)
4806 || !TREE_READONLY (decl)
4807 || TREE_SIDE_EFFECTS (decl)
4808 || !TREE_CONSTANT (decl)))
4809 readonly = true;
4810 }
4811 else if (TREE_CODE (decl) == STRING_CST)
4812 readonly = !flag_writable_strings ;
4813 else if (! (flag_pic && reloc))
4814 readonly = true;
4815
4816 if (readonly)
4817 readonly_data_section ();
4818 else
4819 data_section ();
4820 }
Above DECL_P holds if decl is a real DECL node. And below routine decides if decl is read-only or not.
4941 bool
4942 decl_readonly_section (tree decl, int reloc) in varasm.c
4943 {
4944 return decl_readonly_section_1 (decl, reloc, flag_pic );
4945 }
Variable flag_pic holds the value of option –fpic/-fPIC or –fpie/-fPIE (if –fpic/-fPIC absent). [6] gives below description about the options:
-fpic Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system). If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that ‘-fpic’ does not work; in that case, recompile with ‘-fPIC’ instead. (These maximums are 8k on the SPARC and 32k on the m68k and RS/6000. The 386 has no such limit.) Position-independent code requires special support, and therefore works only on certain machines. For the 386, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent. When this flag is set, the macros __pic__ and __PIC__ are defined to 1. -fPIC If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on the m68k, PowerPC and SPARC. Position-independent code requires special support, and therefore works only on certain machines. When this flag is set, the macros __pic__ and __PIC__ are defined to 2. -fpie -fPIE These options are similar to ‘-fpic’ and ‘-fPIC’, but generated position independent code can be only linked into executables. Usually these options are used when ‘-pie’ GCC option will be used during linking. ‘-fpie’ and ‘-fPIE’ both define the macros __pie__ and __PIE__. The macros have the value 1 for ‘-fpie’ and 2 for ‘-fPIE’. |
4947 bool
4948 decl_readonly_section_1 (tree decl, int reloc, int shlib) in varasm.c
4949 {
4950 switch (categorize_decl_for_section (decl, reloc, shlib))
4951 {
4952 case SECCAT_RODATA:
4953 case SECCAT_RODATA_MERGE_STR:
4954 case SECCAT_RODATA_MERGE_STR_INIT:
4955 case SECCAT_RODATA_MERGE_CONST:
4956 case SECCAT_SRODATA:
4957 return true;
4958 break;
4959 default :
4960 return false;
4961 break ;
4962 }
4963 }
In the name of enumerators of section_category, part “_REL” means the section contains data that has relocations, so they get grouped together and dynamic linker will visit fewer pages in memory. And “_RO” means the section contains data that is otherwise read-only. This is useful with prelinking as most relocations won't be dynamically linked and thus stay read only. Then “_LOCAL” means the section contains data containing relocations only to local objects. These relocations will get fully resolved by prelinking.
4862 static enum section_category
4863 categorize_decl_for_section (tree decl, int reloc, int shlib) in varasm.c
4864 {
4865 enum section_category ret;
4866
4867 if (TREE_CODE (decl) == FUNCTION_DECL)
4868 return SECCAT_TEXT;
4869 else if (TREE_CODE (decl) == STRING_CST)
4870 {
4871 if (flag_writable_strings )
4872 return SECCAT_DATA;
4873 else
4874 return SECCAT_RODATA_MERGE_STR;
4875 }
4876 else if (TREE_CODE (decl) == VAR_DECL)
4877 {
4878 if (DECL_INITIAL (decl) == NULL
4879 || DECL_INITIAL (decl) == error_mark_node)
4880 ret = SECCAT_BSS;
4881 else if (! TREE_READONLY (decl)
4882 || TREE_SIDE_EFFECTS (decl)
4883 || ! TREE_CONSTANT (DECL_INITIAL (decl)))
4884 {
4885 if (shlib && (reloc & 2))
4886 ret = SECCAT_DATA_REL;
4887 else if (shlib && reloc)
4888 ret = SECCAT_DATA_REL_LOCAL;
4889 else
4890 ret = SECCAT_DATA;
4891 }
4892 else if (shlib && (reloc & 2))
4893 ret = SECCAT_DATA_REL_RO;
4894 else if (shlib && reloc)
4895 ret = SECCAT_DATA_REL_RO_LOCAL;
4896 else if (reloc || flag_merge_constants < 2)
4897 /* C and C++ don't allow different variables to share the same
4898 location. -fmerge-all-constants allows even that (at the
4899 expense of not conforming). */
4900 ret = SECCAT_RODATA;
4901 else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
4902 ret = SECCAT_RODATA_MERGE_STR_INIT;
4903 else
4904 ret = SECCAT_RODATA_MERGE_CONST;
4905 }
4906 else if (TREE_CODE (decl) == CONSTRUCTOR)
4907 {
4908 if ((shlib && reloc)
4909 || TREE_SIDE_EFFECTS (decl)
4910 || ! TREE_CONSTANT (decl))
4911 ret = SECCAT_DATA;
4912 else
4913 ret = SECCAT_RODATA;
4914 }
4915 else
4916 ret = SECCAT_RODATA;
4917
4918 /* There are no read-only thread-local sections. */
4919 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4920 {
4921 if (ret == SECCAT_BSS)
4922 ret = SECCAT_TBSS;
4923 else
4924 ret = SECCAT_TDATA;
4925 }
4926
4927 /* If the target uses small data sections, select it. */
4928 else if ((*targetm .in_small_data_p) (decl))
4929 {
4930 if (ret == SECCAT_BSS)
4931 ret = SECCAT_SBSS;
4932 else if (targetm .have_srodata_section && ret == SECCAT_RODATA)
4933 ret = SECCAT_SRODATA;
4934 else
4935 ret = SECCAT_SDATA;
4936 }
4937
4938 return ret;
4939 }
Unless using option ‘-fwritable-string’, flag flag_writable_strings is false, by which string is treated as constant, and can be merged with read-only data. Thus selects section SECCAT_RODATA_MERGE_STR, in which read-only data and string can coexist.
While for variable (VAR_DECL), if it hasn’t initializer, according to C++ specification, it should be put into BSS section (line 4880). If its content can be revised (condition at line 4881~4883, and note that condition at line 4883 finds the initializer for pointer-to-constant), then if reloc has 2nd bit set (TREE_PUBLIC of this VAR_DECL is true, see compute_reloc_for_constant ) and require PIC code generated, put the data into SECCAT_DATA_REL section; or if reloc only has 1st bit set and require PIC code, then put the date into SECCAT_DATA_REL_LOCAL section.
At line 4919, DECL_THREAD_LOCAL if nonzero means using thread-local storage for the variable. And at line 4928, hook in_small_data_p tells if the data can be put into small data section. This is particularly important for 32-bit RISC cpus (like the PPC), were an addressing mode of the form "Rx + 16bit" can fit in one instruction, while an absolute 32-bit address takes a lot of messing around to get the address into a register and then doing the real load or store. Using small data section can generate addressing mode of "Rx + 16bit" as possible. However, x86 needsn’t such concept.
Back default_select_section , if the section selected is read-only, then calls below function.
265 void
266 readonly_data_section (void) in varasm.c
267 {
268 #ifde f READONLY_DATA_SECTION
269 READONLY_DATA_SECTION (); /* Note this can call data_section. */
270 #else
271 #ifdef READONLY_DATA_SECTION_ASM_OP
272 if (in_section != in_readonly_data)
273 {
274 i n_section = in_readonly_data;
275 fputs (READONLY_DATA_SECTION_ASM_OP, asm_out_file );
276 fputc ('/n', asm_out_file );
277 }
278 #else
279 text_section ();
280 #endif
281 #endif
282 }
If the target specifies a rule to switch to the proper section for read-only data, it defines macro READONLY_DATA_SECTION. And if the target has assembler operation to identify read-only initialized data, it needs define macro READONLY_DATA_SECTION_ASM_OP instead. For x86, it defines neither macro, so it calls text_section at line 279.
231 void
232 text_section (void) in varasm.c
233 {
234 if (in_section != in_text)
235 {
236 i n_section = in_text;
237 fprintf (asm_out_file , "%s/n", TEXT_SECTION_ASM_OP);
238 }
239 }
Static variable in_section records the type of section being written. While TEXT_SECTION_ASM_OP, for most targets, is defined as ”/t.text”.
If it is not for read-only data, then use below function.
243 void
244 data_section (void) in varasm.c
245 {
246 if (in_section != in_data)
247 {
248 i n_section = in_data;
249 if (flag_shared_data )
250 {
251 #ifdef SHARED_SECTION_ASM_OP
252 fprintf (asm_out_file , "%s/n", SHARED_SECTION_ASM_OP);
253 #else
254 fprintf (asm_out_file , "%s/n", DATA_SECTION_ASM_OP);
255 #endif
256 }
257 else
258 fprintf (asm_out_file , "%s/n", DATA_SECTION_ASM_OP);
259 }
260 }
Flag flag_shared_data is set by option ‘-fshared-data’, which requests that the data and non- const variables of this compilation be shared data rather than private data. The distinction makes sense only on certain operating systems, where shared data is shared between processes running the same program, while private data exists in one copy per process. Above can see that only if defining SHARED_SECTION_ASM_OP, shared data is meaningful to the system. Currently only 370/MVS, 370/OpenEdition define this macro.