Studying note of GCC-3.4.6 source (172)

5.13.5.2.2.2.  The variable

After outputting the initializer(s), back assemble_variable , next output the variable.

 

assemble_variable (continue)

 

1468   resolve_unique_section (decl, reloc, flag_data_sections );

 

Above, flag_data_sections gets value of switch –fdata-sections, tegother with switch –ffunction-sections (in flag_function_sections ) are used for following purpose[6] :

Place each function or data item into its own section in the output file if the target supports arbitrary sections. The name of the function or the name of the data item determines the section’s name in the output file.

Use these options on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Most systems using the ELF object format and SPARC processors running Solaris 2 have linkers with such optimizations. AIX may have these optimizations in the future.

Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker will create larger object and executable files and will also be slower. You will not be able to use gprof on all systems if you specify this option and you may have problems with debugging if you specify both this option and ‘-g’.

 

442  void

443  resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,         in varasm.c

444                      int flag_function_or_data_sections)

445  {

446    if (DECL_SECTION_NAME (decl) == NULL_TREE

447        && targetm .have_named_sections

448        && (flag_function_or_data_sections

449             || DECL_ONE_ONLY (decl)))

450      (*targetm .asm_out.unique_section) (decl, reloc);

451  }

 

Here assuming –fdata-sections is not present, by default, flag_data_sections is 0. And at line 449 above DECL_ONE_ONLY is nonzero if copies of decl in multiple translation units should be merged. For x86 chip and Linux OS, at this point, this predicate returns false.

 

assemble_variable (continue)

 

1470   /* Handle uninitialized definitions.  */

1471

1472   /* If the decl has been given an explicit section name, then it

1473     isn't common, and shouldn't be handled as such.  */

1474   if (DECL_SECTION_NAME (decl) || dont_output_data)

1475     ;

1476   /* We don't implement common thread-local data at present.  */

1477   else if (DECL_THREAD_LOCAL (decl))

1478   {

1479     if (DECL_COMMON (decl))

1480       sorry ("thread-local COMMON data not implemented");

1481   }

1482   else if (DECL_INITIAL (decl) == 0

1483         || DECL_INITIAL (decl) == error_mark_node

1484         || (flag_zero_initialized_in_bss

1485           /* Leave constant zeroes in .rodata so they can be shared.  */

1486           && !TREE_READONLY (decl)

1487           && initializer_zerop (DECL_INITIAL (decl))))

1488   {

1489     unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);

1490     unsigned HOST_WIDE_INT rounded = size;

1491

1492     /* Don't allocate zero bytes of common,

1493       since that means "undefined external" in the linker.  */

1494     if (size == 0)

1495       rounded = 1;

1496

1497     /* Round size up to multiple of BIGGEST_ALIGNMENT bits

1498       so that each uninitialized object starts on such a boundary.  */

1499     rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;

1500     rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)

1501               * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));

1502      

1503 #if !defined (ASM_OUTPUT_ALIGNED_COMMON) && !defined (ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined (ASM_OUTPUT_ALIGNED_BSS)

1504     if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded)

1505       warning ("%Jrequested alignment for '%D' is greater than "

1506               "implemented alignment of %d", decl, decl, rounded);

1507 #endif

1508

1509     /* If the target cannot output uninitialized but not common global data

1510       i n .bss, then we have to use .data, so fall through.  */

1511     if (asm_emit_uninitialised (decl, name, size, rounded))

1512       return ;

1513   }

 

Because here resolve_unique_section doesn’t any processing (if required, it will select an unique section for decl ), DECL_SECTION_NAME at line 1474 returns NULL.

5.13.5.2.2.2.1.          Output assemble – variable without initializer

Note that don’t_output_data is 0. At line 1484, flag_zero_initialized_in_bss by default is 1, it indicates to put zero initialized data in the bss section (GCC by default puts variable initialized to 0 into BSS section, unless the target can’t support it).

At line 1267, if DECL_COMMON holds, means putting the declaration into “.comm” section as possible, thus multiple copies of this uninitialized variable cam be merged. But if its DECL_INITIAL isn’t error_mark_node, the declaration can’t be put into “.comm” section.

 

1250 static bool

1251 asm_emit_uninitialised (tree decl, const char *name,                                     in varasm.c

1252                     unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,

1253                     unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)

1254 {

1255   enum

1256   {

1257     asm_dest_common,

1258     asm_dest_bss,

1259     asm_dest_local

1260   }

1261   destination = asm_dest_local;

1262

1263   /* ??? We should handle .bss via select_section mechanisms rather than

1264     via special target hooks. That would eliminate this special case.  */

1265   if (TREE_PUBLIC (decl))

1266   {

1267     if (!DECL_COMMON (decl))

1268 #ifdef ASM_EMIT_BSS

1269       destination = asm_dest_bss;

1270 #else

1271     return false;

1272 #endif

1273     else

1274       destination = asm_dest_common;

1275   }

1276

1277   if (destination == asm_dest_bss)

1278     globalize_decl (decl);

1279   resolve_unique_section (decl, 0, flag_data_sections );

 

Usually, uninitialized global variable (includes static member) has DECL_COMMON set (note that TREE_PUBLIC of static variable is not TRUE, it will be output into “.local” section), but not for declarations having initializer. For object having initialzier, above at line 1278, outputs its property by below function.

 

4355 static void

4356 globalize_decl (tree decl)                                                                             in varasm.c

4357 {

4358   const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);

4359

4360 #if defined (ASM_WEAKEN_LABEL ) || defined (ASM_WEAKEN_DECL)

4361   if (DECL_WEAK (decl))

4362   {

4363     tree *p, t;

4364

4365 #ifdef ASM_WEAKEN_DECL

4366     ASM_WEAKEN_DECL (asm_out_file , decl, name, 0);

4367 #else

4368     ASM_WEAKEN_LABEL (asm_out_file , name);

4369 #endif

4370

4371     /* Remove this function from the pending weak list so that

4372        we do not emit multiple .weak directives for it.  */

4373     for (p = &weak_decls ; (t = *p) ; )

4374     {

4375        if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))

4376         *p = TREE_CHAIN (t);

4377        else

4378         p = &TREE_CHAIN (t);

4379     }

4380     return ;

4381   }

4382 #endif

4383

4384   (*targetm .asm_out.globalize_label ) (asm_out_file , name);

4385 }

 

Above for our target machine, macro ASM_WEAKEN_DECL isn’t defined, and macro ASM_WEAKEN_LABEL has below definition, it outputs the property of weak declaration.

 

240   #define ASM_WEAKEN_LABEL (FILE, NAME)  /                                  in elfos.h

241    do                                    /

242    {                              /

243      fputs ("/t.weak/t", (FILE));    /

244      assemble_name ((FILE), (NAME));      /

245      fputc ('/n', (FILE));              /

246    }                              /

247    while (0)

 

For non-weak global variable, it is output by hook globalize_label at line 4384. On our target machine, the function is default_globalize_label .

 

5252 #ifdef GLOBAL_ASM_OP

5253 void

5254 default_globalize_label (FILE * stream, const char *name)                            in varasm.c

5255 {

5256   fputs (GLOBAL_ASM_OP, stream);

5257   assemble_name (stream, name);

5258   putc ('/n', stream);

5259 }

5260 #endif /* GLOBAL_ASM_OP */

 

GLOBAL_ASM_OP is defined as “.globl” here (another compatible one is “.global”), it makes the symbol visible to ld (GNU linker). So the output of default_globalize_label has form “.globl   b”, in which “b” is the variable name.

After outputting the property and the name, below code determines the section to output the variable and output the section information (if needs to swap current section).

 

asm_emit_unintialised (continue)

 

1281   if (flag_shared_data )

1282   {

1283     switch (destination)

1284     {

1285 #ifdef ASM_OUTPUT_SHARED_BSS

1286       case asm_dest_bss:

1287         ASM_OUTPUT_SHARED_BSS (asm_out_file , decl, name, size, rounded);

1288         return ;

1289 #endif

1290 #ifdef ASM_OUTPUT_SHARED_COMMON

1291       case asm_dest_common:

1292         ASM_OUTPUT_SHARED_COMMON (asm_out_file , name, size, rounded);

1293         return ;

1294 #endif

1295 #ifdef ASM_OUTPUT_SHARED_LOCAL

1296       case asm_dest_local:

1297         ASM_OUTPUT_SHARED_LOCAL (asm_out_file , name, size, rounded);

1298         return ;

1299 #endif

1300       default :

1301         break ;

1302     }

1303   }

1304

1305   switch (destination)

1306   {

1307 #ifdef ASM_EMIT_BSS

1308     case asm_dest_bss:

1309       ASM_EMIT_BSS (decl, name, size, rounded);

1310       break ;

1311 #endif

1312     case asm_dest_common:

1313       ASM_EMIT_COMMON (decl, name, size, rounded);

1314       break ;

1315     case asm_dest_local:

1316       ASM_EMIT_LOCAL (decl, name, size, rounded);

1317       break ;

1318     default :

1319       abort ();

1320   }

1321

1322   return true;

1323 }

 

For x86/Linux, above macros containing “SHARED” field aren’t defined, which indicates at here flag_shared_data does not work.

Macro ASM_EMIT_BSS, for x86/Linux target, is defined by asm_output_aligned_bss .

 

501  static void

502  asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,           in varasm.c

503                       const char *name, unsigned HOST_WIDE_INT size,

504                       int align)

505  {

506    bss_section ();

507    ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));

508  #ifdef ASM_DECLARE_OBJECT_NAME

509    last_assemble_variable_decl = decl;

510    ASM_DECLARE_OBJECT_NAME (file, name, decl);

511  #else

512    /* Standard thing is just output label for the object.  */

513    ASM_OUTPUT_LABEL (file, name);

514  #endif /* ASM_DECLARE_OBJECT_NAME */

515    ASM_OUTPUT_SKIP (file, size ? size : 1);

516  }

 

First via below function to check if we are already in “.bss” section, swap to “.bss” section if it is not. BSS_SECTION_ASM_OP is “/t.bss”.

 

457  void

458  bss_section (void)                                                                                      in varasm.c

459  {

460    if (in_section != in_bss)

461    {

462      fprintf (asm_out_file , "%s/n", BSS_SECTION_ASM_OP);

463      i n_section = in_bss;

464    }

465  }

 

Before we have seen macro ASM_OUTPUT_LABEL, there it is used to output label. Here what output is variable, in some machines, they are different in nature. Here, x86/Linux defines following macros to output variables specially.

 

287  #define ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL)                   /     in elfos.h

288    do                                                         /

289      {                                                      /

290        HOST_WIDE_INT size;                                /

291                                                          /

292        ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");             /

293                                                          /

294        size_directive_output = 0;                       /

295        if (!flag_inhibit_size_directive                         /

296            && (DECL) && DECL_SIZE (DECL))                   /

297        {                                            /

298           size_directive_output = 1;                           /

299           size = int_size_in_bytes (TREE_TYPE (DECL));        /

300           ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size);         /

301        }                                            /

302                                                          /

303        ASM_OUTPUT_LABEL (FILE, NAME);                       /

304      }                                                      /

305    while (0)

 

Here the difference between variable and label is that, variable has additional description which is output by below macro.

 

186  #ifndef ASM_OUTPUT_TYPE_DIRECTIVE                                                 in defaults.h

187  #if defined TYPE_ASM_OP && defined TYPE_OPERAND_FMT

188  #define ASM_OUTPUT_TYPE_DIRECTIVE (STREAM, NAME, TYPE)   /

189    do                                                 /

190      {                                               /

191        fputs (TYPE_ASM_OP, STREAM);                /

192        assemble_name (STREAM, NAME);               /

193        fputs (", ", STREAM);                            /

194        fprintf (STREAM, TYPE_OPERAND_FMT, TYPE);             /

195        putc ('/n', STREAM);                      /

196      }                                               /

197    while (0)

198  #endif

199  #endif

 

Above TYPE_OPERAND_FMT in elfos.h has definition “@%s”, and TYPE_ASM_OP is “/t.type/t”. SO macro ASM_OUTPUT_TYPE_DIRECTIVE will output some like: “.type     b, object”, in which “b” is the variable name.

 

202  #ifndef ASM_OUTPUT_SIZE_DIRECTIVE

203  #ifdef SIZE_ASM_OP

204   #define ASM_OUTPUT_SIZE_DIRECTIVE (STREAM, NAME, SIZE)      /

205    do                                                  /

206      {                                               /

207        HOST_WIDE_INT size_ = (SIZE);                /

208        fputs (SIZE_ASM_OP, STREAM);                 /

209        assemble_name (STREAM, NAME);               /

210        fprintf (STREAM, ", " HOST_WIDE_INT_PRINT_DEC "/n", size_); /

211      }                                               /

212    while (0)

 

If flag_inhibit_size_directive is nonzero, it means to prohibit “.size” in elf format, it is set by option “-finhibit-size-directive”, and the default value is 0. Unless prohibit, using ASM_OUTPUT_SIZE_DIRECTIVE to output the size of the variable. HereSIZE_ASM_OP’s definition is “/t.size/t”. The content output looks like: ”.size   b, 4”, in which “b” is the variable name.

Next in ASM_DECLARE_OBJECT_NAME at line 303 invokes ASM_OUTPUT_LABLE to output the variable name as label, then in asm_output_aligned_bss at line 515, by ASM_OUTPUT_SKIP output default initializer like “.zero       4”, in which “4” is the size of the variable.

If it needs be output into “.comm” section, here the output macro ASM_EMIT_COMMON is defined as ASM_OUTPUT_ALIGNED_COMMON.

 

164  #undef   ASM_OUTPUT_ALIGNED_COMMON

165  #define ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN)/ in elfos.h

166    do                                                                /

167      {                                                             /

168        fprintf ((FILE), "%s", COMMON_ASM_OP);                      /

169        assemble_name ((FILE), (NAME));                              /

170        fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u/n",           /

171                (SIZE), (ALIGN) / BITS_PER_UNIT);                /

172      }                                                             /

173    while (0)

 

Above COMMON_ASM_OP is “/t.comm/t”, at last the output looks like “.comm      b,4,4”, in which “b” is the variable name, the first “4” is the variable size, and the later “4” is the alignment .Note that here it won't output the label of the variable name and the default initializer.

Similarly, for local variable (note, includes static vairable), ASM_EMIT_LOCAL at here is defined as ASM_OUTPUT_ALIGNED_LOCAL.

 

182  #undef   ASM_OUTPUT_ALIGNED_LOCAL

183  #define ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN)      / in elfos.h

184    do                                                         /

185      {                                                      /

186        fprintf ((FILE), "%s", LOCAL_ASM_OP);                    /

187        assemble_name ((FILE), (NAME));                       /

188        fprintf ((FILE), "/n");                             /

189        ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN);      /

190      }                                                      /

191    while (0)

 

Here, LOCAL_ASM_OP is “/t.local/t”, so the output looks like:

.local a

.comm  a,4,4

 

5.13.5.2.2.2.2.          Output assemble – variable with initializer

If global/static variable has initializer, thus coming here. First, below at line 1524, variable_section selects the target section (refer to Select output section ).

 

assemble_variable (continue)

 

1515   /* Handle initialized definitions.

1516     Also handle uninitialized global definitions if -fno-common and the

1517     target doesn't support ASM_OUTPUT_BSS.  */

1518

1519   /* First make the assembler name(s) global if appropriate.  */

1520   if (TREE_PUBLIC (decl) && DECL_NAME (decl))

1521     globalize_decl (decl);

1522

1523   /* Switch to the appropriate section.  */

1524   variable_section (decl, reloc);

1525

1526   /* dbxout.c needs to know this.  */

1527   if (in_text_section ())

1528     DECL_IN_TEXT_SECTION (decl) = 1;

1529

1530   /* Output the alignment of this data.  */

1531   if (align > BITS_PER_UNIT)

1532   {

1533     ASM_OUTPUT_ALIGN (asm_out_file ,

1534                          floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));

1535   }

1536

1537   /* Do any machine/system dependent processing of the object.  */

1538 #ifdef ASM_DECLARE_OBJECT_NAME

1539   last_assemble_variable_decl = decl;

1540   ASM_DECLARE_OBJECT_NAME (asm_out_file , name, decl);

1541 #else

1542   /* Standard thing is just output label for the object.  */

1543   ASM_OUTPUT_LABEL (asm_out_file , name);

1544 #endif /* ASM_DECLARE_OBJECT_NAME */

1545

1546   if (!dont_output_data)

1547   {

1548     if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)

1549       /* Output the actual data.  */

1550       output_constant (DECL_INITIAL (decl),

1551                     tree_low_cst (DECL_SIZE_UNIT (decl), 1),

1552                     align);

1553     else

1554       /* Leave space for it.  */

1555       assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));

1556   }

1557 }

 

The rest procedure is very similar with that we see previously. Note that constant without initializer is handled at line 1555.

 

你可能感兴趣的:(Stream,object,File,tree,output,alignment)