您的位置:首页 > 编程语言

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

2011-03-12 15:29 399 查看
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
2

SPARC
处理器具有有这样优化的链接器。在未来,
AIX
可能会具有这些优化。

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

}

这里假定没使用
–fdata-sections
,默认地,
flag_data_sections


0
。而在
449

DECL_ONE_ONLY
是非
0
值,如果在多个编译单元中
decl

的拷贝需要被合并。对于
x86
芯片及
Linux OS
,在这里,这个断言返回
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

}

因为
resolve_unique_section

在此处不做任何处理(如果需要,它将为
decl

选定一个独有的节),在
1474
行的
DECL_SECTION_NAME
返回
NULL


5.13.5.2.2.2.1.

发布汇编

未指定初始值

注意
don’t_output_data


0
。在
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 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

);

通常没有初始值的全局变量(包括静态成员声明)的
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

#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

}

上面对于我们的目标机器,宏
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
”),它使得该符号对
ld

GNU
链接器)可见。因此
default_globalize_label

的输出形如“
.globl
b
”,其中“
b
”是相应的变量名。

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

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

}

对于
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

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

}

首先通过下面的函数检查我们是否已经在“
.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

i

n_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 && 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

上面的
TYPE_OPERAND_FMT

elfos.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_NAME

303
行调用
ASM_OUTPUT_LABLE
,把变量名输出为标签。然后在
asm_output_aligned_bss


515
行,由
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

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

在这里,
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

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

}

余下的过程与我们上面所见非常相似。注意缺省初始化常量,它们在
1555
行处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: