GCC-3.4.6源代码学习笔记(172)

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

5.13.5.2.2.2. 变量

输出初始值后,回到assemble_variable,接下来处理对应的变量。

 

assemble_variable (continue)

 

1468   resolve_unique_section(decl, reloc, flag_data_sections);

 

上面的flag_data_sections由选项–fdata-sections设置,它连同选项–ffunction-sections(设置flag_function_sections)被用于下面的目的[6

如果目标机器支持任意节,在输出文件中,把每个函数或数据项放在它自己的节中。该函数或数据项的名字确定了在输出文件中对应节的名字。

在那些链接器可以执行优化以提高指令空间中引用的局部性的系统上使用这些选项。大多数系统使用ELF目标格式,并且运行Solaris 2SPARC处理器具有有这样优化的链接器。在未来,AIX可能会具有这些优化。

仅当这样做会带来大的利益时,才使用这些选项。当你指定这些选项时,汇编器及链接器将构建更大的目标及执行文件,同时汇编器及链接器将运行得更慢。如果你指定了这个选项,你将不能在所有的系统上使用gprof,并且如果你同时指定这个选项及‘-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  }

 

这里假定没使用–fdata-sections,默认地,flag_data_sections0。而在449DECL_ONE_ONLY是非0值,如果在多个编译单元中decl的拷贝需要被合并。对于x86芯片及Linux OS,在这里,这个断言返回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   }

 

因为resolve_unique_section在此处不做任何处理(如果需要,它将为decl选定一个独有的节),在1474行的DECL_SECTION_NAME返回NULL

5.13.5.2.2.2.1.         发布汇编 未指定初始值

注意don’t_output_data0。在1484行,flag_zero_initialized_in_bss默认的是1,它表示把0初始化的数据放入bss节(GCC默认地把初始化为0的变量放入BSS,除非目标机器不支持BSS)。

1267行,DECL_COMMON如果成立,表示该声明尽可能放入“.comm”节,这样多个未初始化的变量实例可以被合并。但是如果变量的DECL_INITIAL不是error_mark_node,该变量则不能放入“.comm”节。

 

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);

 

通常没有初始值的全局变量(包括静态成员声明)的DECL_COMMON成立(注意静态变量的TREE_PUBLIC是不成立的,它将被输出到“.local”节),而具有初始值的声明则不成立。对于具有初始值的对象,在上面1278行,通过下面的函数输出声明的属性。

 

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 }

 

上面对于我们的目标机器,宏ASM_WEAKEN_DECL没有定义,而宏ASM_WEAKEN_LABEL则定义如下,输出所谓的弱声明的属性。

 

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)

 

对于非弱全局声明,则是通过4384行的钩子globalize_label输出。在我们的目标机器上,这个钩子函数是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在这里被定义为“.globl”(另一个兼容的形式是“.global”),它使得该符号对ldGNU链接器)可见。因此default_globalize_label的输出形如“.globl       b”,其中“b”是相应的变量名。

输出了对象的属性及其名字之后,接着由下面的代码确定并输出其所在节(如果需要改变当前的节)。

 

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 }

 

对于x86/Linux,上面带有“SHARED”字段的宏都没有定义,这表明flag_shared_data在这里其实不起作用。

ASM_EMIT_BSS,对于x86/Linux目标机器,被定义为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  }

 

首先通过下面的函数检查我们是否已经在“.bss”节,不是的话需要切换到“.bss”节。BSS_SECTION_ASM_OP被定义为“/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  }

 

前面我们已经看过宏ASM_OUTPUT_LABEL,在那里它被用来输出标签。在这里我们要输出的是变量,在某些机器上,它们在本质上是不同的。这里,x86/Linux定义了下面的宏来专门输出变量。

 

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)

 

这里变量与标签的不同之处在于,变量有附加的说明,它由下面的宏输出。

 

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

 

上面的TYPE_OPERAND_FMTelfos.h中定义为“@%s”,而TYPE_ASM_OP则是“/t.type/t”。那么宏ASM_OUTPUT_TYPE_DIRECTIVE将输出形如:“.type b, @object”的内容,其中“b”是相应的变量名。

 

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)

 

如果flag_inhibit_size_directive不是0,表示禁止在elf中使用“.size”,它由编译选项-finhibit-size-directive设置,默认为0。只要不禁止,就使用ASM_OUTPUT_SIZE_DIRECTIVE输出变量的大小。这里SIZE_ASM_OP的定义是“/t.size/t”。输出的内容形如:“.size   b, 4”,其中“b”是相应的变量名。

接着在ASM_DECLARE_OBJECT_NAME303行调用ASM_OUTPUT_LABLE,把变量名输出为标签。然后在asm_output_aligned_bss515行,由ASM_OUTPUT_SKIP输出形如“.zero     4”的缺省初始值,其中“4”是变量的大小。

若要输出到“.comm”节,在这里,其输出宏ASM_EMIT_COMMON被定义为宏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)

 

上面的COMMON_ASM_OP被定义为“/t.comm/t”,最终的输出形如“.comm  b,4,4”,其中“b”是相应的变量名,第一个“4”是变量大小,后面的“4”是变量的对齐量。注意这里不会输出变量名的标签,及默认的初始值。

同样,对于局部变量(注意,包括静态变量),ASM_EMIT_LOCAL在这里被定义为宏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)

 

在这里,LOCAL_ASM_OP的定义是“/t.local/t”,因此这里的输出形如:

.local a

.comm  a,4,4

 

5.13.5.2.2.2.2.         发布汇编 指定初始值

如果全局/静态变量具有初始值,则来到这里。首先由下面1524行的variable_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 }

 

余下的过程与我们上面所见非常相似。注意缺省初始化常量,它们在1555行处理。

 

原创粉丝点击