Studying note of GCC-3.4.6 source (169)

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.

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (169))