Studying note of GCC-3.4.6 source (172)

来源:互联网 发布:宁波每日新房成交数据 编辑:程序博客网 时间:2024/06/01 07:12

5.13.5.2.2.2. The variable

Afteroutputting 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_sectionsgets 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, intreloc ATTRIBUTE_UNUSED,         in varasm.c

444                      intflag_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_sectionsis 0. And at line 449 above DECL_ONE_ONLY is nonzero if copies of decl inmultiple translation units should be merged. For x86 chip and Linux OS, at thispoint, this predicate returns false.

 

assemble_variable (continue)

 

1470   /* Handleuninitialized definitions.  */

1471

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

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

1474   if (DECL_SECTION_NAME (decl) ||dont_output_data)

1475     ;

1476   /* We don'timplement 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 notimplemented");

1481   }

1482   else if (DECL_INITIAL (decl) == 0

1483         || DECL_INITIAL (decl) ==error_mark_node

1484         || (flag_zero_initialized_in_bss

1485           /* Leaveconstant 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 allocatezero bytes of common,

1493       since that means "undefinedexternal" in the linker.  */

1494     if (size == 0)

1495       rounded = 1;

1496

1497     /* Round size upto multiple of BIGGEST_ALIGNMENT bits

1498       so that each uninitialized object startson 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 targetcannot output uninitialized but not common global data

1510       in .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 line1474 returns NULL.

5.13.5.2.2.2.1.         Output assemble – variablewithout initializer

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

At line 1267, if DECL_COMMON holds, means putting the declarationinto “.comm” section as possible, thus multiple copies of this uninitializedvariable cam be merged. But if its DECL_INITIAL isn’t error_mark_node, thedeclaration 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 sizeATTRIBUTE_UNUSED,

1253                     unsigned HOST_WIDE_INTrounded 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 shouldhandle .bss via select_section mechanisms rather than

1264     via special target hooks. That wouldeliminate 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 havinginitialzier, 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 #ifdefined (ASM_WEAKEN_LABEL)|| defined (ASM_WEAKEN_DECL)

4361   if (DECL_WEAK (decl))

4362   {

4363     tree *p, t;

4364

4365 #ifdefASM_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 thisfunction 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 ofweak 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_labelat 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_labelhas form “.globl   b”, in which “b” is thevariable name.

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

 

asm_emit_unintialised (continue)

 

1281   if (flag_shared_data)

1282   {

1283     switch(destination)

1284     {

1285 #ifdefASM_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 #ifdefASM_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’tdefined, 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                       intalign)

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 theobject.  */

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      in_section = in_bss;

464   }

465  }

 

Before we have seen macro ASM_OUTPUT_LABEL, there it is used tooutput label. Here what output is variable, in some machines, they aredifferent in nature. Here, x86/Linux defines following macros to outputvariables 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 hasadditional description which is output by below macro.

 

186  #ifndef ASM_OUTPUT_TYPE_DIRECTIVE                                                 in defaults.h

187  #if defined TYPE_ASM_OP && definedTYPE_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_OPis “/t.type/t”. SO macro ASM_OUTPUT_TYPE_DIRECTIVE will output some like: “.type     b, object”, in which “b” is the variablename.

 

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_directiveis 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 tooutput 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 thevariable name.

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

If it needs be output into “.comm” section, here the output macro ASM_EMIT_COMMONis 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_OPis “/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 nameand the default initializer.

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

 

182  #undef ASM_OUTPUT_ALIGNED_LOCAL

183  #defineASM_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 withinitializer

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   /* Handleinitialized definitions.

1516     Also handle uninitialized globaldefinitions if -fno-common and the

1517     target doesn't support ASM_OUTPUT_BSS.  */

1518

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

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

1521     globalize_decl(decl);

1522

1523   /* Switch to theappropriate section.  */

1524   variable_section (decl, reloc);

1525

1526   /* dbxout.c needsto know this.  */

1527   if (in_text_section ())

1528     DECL_IN_TEXT_SECTION (decl) = 1;

1529

1530   /* Output thealignment 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 anymachine/system dependent processing of the object.  */

1538 #ifdefASM_DECLARE_OBJECT_NAME

1539   last_assemble_variable_decl = decl;

1540   ASM_DECLARE_OBJECT_NAME(asm_out_file,name, decl);

1541 #else

1542  /* Standard thing isjust 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 theactual data.  */

1550       output_constant(DECL_INITIAL (decl),

1551                     tree_low_cst (DECL_SIZE_UNIT(decl), 1),

1552                     align);

1553     else

1554       /* Leave spacefor 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. Notethat constant without initializer is handled at line 1555.

 

原创粉丝点击