您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (168)

2011-02-26 15:48 232 查看
5.13.5.2.2.1.

The initializer

Here on our target Linux/x86, the output file would be of format
ELF. ELF is the format supports relocatable and PIC (position independent
code). Chapter 3 of [10] gives a good description about ELF. As summeray gotten
from [10], we find:

ELF files come in three
slightly different flavors: relocatable, executable, and shared object.
Relocatable files are created by compilers and assemblers but need to be
processed by the linker before running. Executable files have all relocation
done and all symbols resolved except perhaps shared library symbols to be
resolved at runtime. Shared objects are shared libraries, containing both
symbol information for the linker and directly runnable code for runtime.

ELF files have an unusual
dual nature. Compilers, assemblers, and linkers treat the file as a set of
logical sections described by a section header table, while the system loader
treats the file as a set of segments described by a program header table. A
single segment will usually consist of several sections. For example, a
‘‘loadable read-only’’ segment could contain sections for executable code,
read-only data, and symbols for the dynamic linker. Relocatable files have
section tables, executable files have program header tables, and shared objects
have both. The sections are intended for further processing by a linker, while
the segments are intended to be mapped into memory.

assemble_variable (continue)

1460

/* Output any data that we will need to use the address
of.
*/

1461

if (DECL_INITIAL (decl) == error_mark_node)

1462

reloc = contains_pointers_p
(TREE_TYPE (decl)) ? 3 : 0;

1463

else if (DECL_INITIAL (decl))

1464

{

1465

reloc = compute_reloc_for_constant
(DECL_INITIAL
(decl));

1466

output_addressed_constants
(DECL_INITIAL (decl));

1467

}

1468

resolve_unique_section
(decl, reloc, flag_data_sections

);

Field DECL_INITIAL if is NULL, means decl

hasn’t initializer; and if is error_mark_node

,
means decl

has initializer but it hasn’t been seen yet. If the initializer unknown, it
needs be conservative. At line 1462, reloc

would hold a value that will be compared with
flag_pic

to select the section the code will be placed. And as we have seen in before
chapter, flag_pic

if is 1 means doing small PIC, and if is 2 means doing big PIC. Later we will
see the effect of these value.

It sets reloc

as 3 if the type of decl

contains pointer (or
reference) which told by below function. This value indicates that uses big PIC
as possible, otherwise tries small PIC.

1561

static
int

1562

contains_pointers_p

(tree type)

in varasm.c

1563

{

1564

switch
(TREE_CODE (type))

1565

{

1566

case
POINTER_TYPE:

1567

case
REFERENCE_TYPE:

1568

/* I'm not sure
whether OFFSET_TYPE needs this treatment,

1569

so I'll play safe and return 1.
*/

1570

case
OFFSET_TYPE:

1571

return
1;

1572

1573

case
RECORD_TYPE:

1574

case
UNION_TYPE:

1575

case
QUAL_UNION_TYPE:

1576

{

1577

tree fields;

1578

/* For a type
that has fields, see if the fields have pointers.
*/

1579

for
(fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))

1580

if (TREE_CODE (fields) == FIELD_DECL

1581

&& contains_pointers_p
(TREE_TYPE (fields)))

1582

return
1;

1583

return
0;

1584

}

1585

1586

case
ARRAY_TYPE:

1587

/* An array
type contains pointers if its element type does.
*/

1588

return
contains_pointers_p (TREE_TYPE (type));

1589

1590

default
:

1591

return
0;

1592

}

1593

}

If the initializer is known, it needs to see what kind of
relocations it may need. If the initializer contains address expression, ELF
code of PIC requires the accessing of the refferred object should via a GOT, below
function searches addressed object within the initializer. If there is no usage
of object address in the initializer, the function will return 0.

The C++ front-end hook expand_constant

bound with function cplus_expand_constant

,
it replaces PTRMEM_CST (the pointer-to-member constants) either with PLUS_EXPR
(case for referring to data member) or with more appropriate PTRMEM_CST (case
for referring to method of base from derived).

3383

int

3384

compute_reloc_for_constant

(tree exp)

in varasm.c

3385

{

3386

int reloc = 0, reloc2;

3387

tree tem;

3388

3389

/* Give the
front-end a chance to convert VALUE to something that

3390

looks more like a constant to the
back-end.
*/

3391

exp = (*lang_hooks

.expand_constant) (exp);

3392

3393

switch
(TREE_CODE (exp))

3394

{

3395

case
ADDR_EXPR:

3396

case
FDESC_EXPR:

3397

/* Go inside
any operations that get_inner_reference can handle and see

3398

if what's inside is a constant: no need
to do anything here for

3399

addresses of variables or
functions.
*/

3400

for
(tem
= TREE_OPERAND (exp, 0); handled_component_p
(tem);

3401

tem = TREE_OPERAND (tem, 0))

3402

;

3403

3404

if (TREE_PUBLIC (tem))

3405

reloc |= 2;

3406

else

3407

reloc |= 1;

3408

break
;

3409

3410

case
PLUS_EXPR:

3411

reloc = compute_reloc_for_constant
(TREE_OPERAND (exp, 0));

3412

reloc |= compute_reloc_for_constant
(TREE_OPERAND (exp, 1));

3413

break
;

3414

3415

case
MINUS_EXPR:

3416

reloc = compute_reloc_for_constant
(TREE_OPERAND (exp, 0));

3417

reloc2 = compute_reloc_for_constant
(TREE_OPERAND (exp, 1));

3418

/* The
difference of two local labels is computable at link time.
*/

3419

if (reloc == 1 && reloc2 == 1)

3420

reloc = 0;

3421

else

3422

reloc |= reloc2;

3423

break
;

3424

3425

case
NOP_EXPR:

3426

case
CONVERT_EXPR:

3427

case
NON_LVALUE_EXPR:

3428

reloc = compute_reloc_for_constant
(TREE_OPERAND (exp, 0));

3429

break
;

3430

3431

case
CONSTRUCTOR:

3432

for
(tem
= CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))

3433

if (TREE_VALUE (tem) != 0)

3434

reloc |= compute_reloc_for_constant
(TREE_VALUE (tem));

3435

3436

break
;

3437

3438

default
:

3439

break
;

3440

}

3441

return
reloc;

3442

}

For non-static data member of class or elment of array, their
address is given in offset from the base address. They also need relocation at
time of loading. Further TREE_PUBLIC in a VAR_DECL or FUNCTION_DECL, if is nonzero
means name is to be accessible from outside this module; in an IDENTIFIER_NODE,
if is nonzero means an external declaration accessible from outside this module
was previously seen for this name in an inner scope. So set reloc

accordingly as line 3404 to 3407 does.

Below function is inovked at line 3400 above, it finds out the
object that gets referred.

5620

int

5621

handled_component_p

(tree t)

in expr.c

5622

{

5623

switch
(TREE_CODE (t))

5624

{

5625

case
BIT_FIELD_REF:

5626

case
COMPONENT_REF:

5627

case
ARRAY_REF:

5628

case
ARRAY_RANGE_REF:

5629

case
NON_LVALUE_EXPR:

5630

case
VIEW_CONVERT_EXPR:

5631

return
1;

5632

5633

/* ??? Sure they
are handled, but get_inner_reference may return

5634

a different PBITSIZE, depending upon whether the expression
is

5635

wrapped up in a NOP_EXPR or not, e.g. for
bitfields.
*/

5636

case
NOP_EXPR:

5637

case
CONVERT_EXPR:

5638

return
(TYPE_MODE (TREE_TYPE (t))

5639

== TYPE_MODE (TREE_TYPE
(TREE_OPERAND (t, 0))));

5640

5641

default
:

5642

return
0;

5643

}

5644

}

5.13.5.2.2.1.1.

Output constant referred

Then at line 1466 in
assemble_variable

,
in the invocation of output_addressed_constants

, its argument is
this initializer. Similiarly, this function searches address used in exp

.

3448

static
void

3449

output_addressed_constants

(tree exp)

in varasm.c

3450

{

3451

tree tem;

3452

3453

/* Give the
front-end a chance to convert VALUE to something that

3454

looks more like a constant to the
back-end.
*/

3455

exp = (*lang_hooks

.expand_constant) (exp);

3456

3457

switch
(TREE_CODE (exp))

3458

{

3459

case
ADDR_EXPR:

3460

case
FDESC_EXPR:

3461

/* Go inside
any operations that get_inner_reference can handle and see

3462

if what's inside is a constant: no need
to do anything here for

3463

addresses of variables or
functions.
*/

3464

for
(tem
= TREE_OPERAND (exp, 0); handled_component_p
(tem);

3465

tem = TREE_OPERAND (tem, 0))

3466

;

3467

3468

if (TREE_CODE_CLASS (TREE_CODE (tem)) ==
'c'

3469

|| TREE_CODE (tem) == CONSTRUCTOR)

3470

output_constant_def

(tem, 0);

3471

break
;

3472

3473

case
PLUS_EXPR:

3474

case
MINUS_EXPR:

3475

output_addressed_constants (TREE_OPERAND
(exp, 1));

3476

/* Fall
through.
*/

3477

3478

case
NOP_EXPR:

3479

case
CONVERT_EXPR:

3480

case
NON_LVALUE_EXPR:

3481

output_addressed_constants (TREE_OPERAND
(exp, 0));

3482

break
;

3483

3484

case
CONSTRUCTOR:

3485

for
(tem
= CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))

3486

if (TREE_VALUE (tem) != 0)

3487

output_addressed_constants
(TREE_VALUE (tem));

3488

3489

break
;

3490

3491

default
:

3492

break
;

3493

}

3494

}

Condition at line 3468 if satisfied, means object upon this address
is constant. And condition at line 3469 if satisfied, represents the
brace-enclosed initializers for a structure or array, which may be read-only.
The front-end uses data structure constant_descriptor_tree to describe these
nodes for (maybe) constant.

2062

struct
constant_descriptor_tree
GTY(())

in varasm.c

2063

{

2064

/* A MEM for the
constant.
*/

2065

rtx rtl;

2066

2067

/* The value of the
constant.
*/

2068

tree value;

2069

};

Every constant is a singleton at least within the translation-unit.
We have seen that in the front-end, tree node for constant is cached within the
hash table. Now for constant descriptor node, it is the same.

2484

rtx

2485

output_constant_def

(tree exp, int
defer)

in varasm.c

2486

{

2487

struct
constant_descriptor_tree
*desc;

2488

struct
constant_descriptor_tree key;

2489

void **loc;

2490

2491

/* Look up EXP in
the table of constant descriptors. If we didn't find

2492

it, create a new one.
*/

2493

key.value = exp;

2494

loc = htab_find_slot (const_desc_htab

, &key, INSERT);

2495

2496

desc = *loc;

2497

if (desc == 0)

2498

{

2499

desc = build_constant_desc
(exp);

2500

*loc = desc;

2501

}

2502

2503

maybe_output_constant_def_contents
(desc, defer);

2504

return
desc->rtl;

2505

}

If the constant descriptor is not found within const_desc_htab

(see that the tree
node of this constant is used as the key, and const_desc_hash

is called to
compare nodes’ content), build_constant_desc

comes to help. Below at
line 2441, copy_constant

copies the tree node of the constants within exp

, as below we may modify the
node’s content, we need own a copy.

2431

static
struct
constant_descriptor_tree *

2432

build_constant_desc

(tree exp)

in varasm.c

2433

{

2434

rtx symbol;

2435

rtx rtl;

2436

char label[256];

2437

int labelno;

2438

struct
constant_descriptor_tree *desc;

2439

2440

desc = ggc_alloc (sizeof
(*desc));

2441

desc->value = copy_constant (exp);

2442

2443

/* Create a string
containing the label name, in LABEL.
*/

2444

labelno = const_labelno

++;

2445

ASM_GENERATE_INTERNAL_LABEL (label,
"LC", labelno);

2446

2447

/* We have a symbol
name; construct the SYMBOL_REF and the MEM.

*/

2448

symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));

2449

SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;

2450

SYMBOL_REF_DECL (symbol) = desc->value;

2451

TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;

2452

2453

rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE
(exp)), symbol);

2454

set_mem_attributes
(rtl, exp, 1);

2455

set_mem_alias_set (rtl, 0);

2456

set_mem_alias_set (rtl, const_alias_set

);

2457

2458

/* Set flags or add
text to the name to record information, such as

2459

that it is a local symbol. If the name is
changed, the macro

2460

ASM_OUTPUT_LABELREF will have to know how
to strip this

2461

information. This call might invalidate our
local variable

2462

SYMBOL; we can't use it afterward.
*/

2463

2464

(*targetm

.encode_section_info) (exp, rtl, true);

2465

2466

desc->rtl = rtl;

2467

2468

return
desc;

2469

}

To visit these constants in a unified way in assemble, the front-end
labels these constants; so the visit can be done via referring the associated
label. It is the so-called internal label. Under our assuming platform and
machine, ASM_GENERATE_INTERNAL_LABEL is defined as below. The label will
contain string like: “*LC1”,
“*LC2”, and so on, according to
the number of constant label generated.

722

#undef
ASM_GENERATE_INTERNAL_LABEL

in darwin.h

723

#define
ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)
/

724

sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM))

Next we make this label into SYMBOL_REF, and build MEM node for it .
Then, according to the property of this (maybe) constant, set memory
attributions.

5.13.5.2.2.1.1.1.


Set
memory attributions


In below function, parameter objectp

if nonzero, means we are making a new MEM
for the type. And if bitpos

is nonzero, it is an offset outstanding on
parameter t
that will be applied
later.

1787

void

1788

set_mem_attributes

(rtx ref, tree t, int
objectp)

in emit-rtl.c

1789

{

1790

set_mem_attributes_minus_bitpos
(ref, t, objectp, 0);

1791

}

Below code between line 1566 and 1569 extracts the content of corresponding
fields of the MEM node. The function is also used to modify already existing
MEM node. Note the caculation of alias set of t

at line 1593, it overwrites the
result at line 1566 anyhow.

1562

void

1563

set_mem_attributes_minus_bitpos

(rtx ref, tree t, int objectp,

in emit-rtl.c

1564

HOST_WIDE_INT
bitpos)

1565

{

1566

HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);

1567

tree expr = MEM_EXPR (ref);

1568

rtx offset = MEM_OFFSET (ref);

1569

rtx size = MEM_SIZE (ref);

1570

unsigned int align = MEM_ALIGN (ref);

1571

HOST_WIDE_INT apply_bitpos = 0;

1572

tree type;

1573

1574

/* It can happen
that type_for_mode was given a mode for which there

1575

is no language-level type. In which case it
returns NULL, which

1576

we can see here.
*/

1577

if (t == NULL_TREE)

1578

return
;

1579

1580

type = TYPE_P (t) ? t : TREE_TYPE (t);

1581

if (type == error_mark_node)

1582

return
;

1583

1584

/* If we have
already set DECL_RTL = ref, get_alias_set will get the

1585

wrong answer, as it assumes that DECL_RTL
already has the right alias

1586

info. Callers should not set DECL_RTL until
after the call to

1587

set_mem_attributes.
*/

1588

if (DECL_P (t) && ref ==
DECL_RTL_IF_SET (t))

1589

abort ();

1590

1591

/* Get the alias
set from the expression or type (perhaps using a

1592

front-end routine) and use it.
*/

1593

alias = get_alias_set
(t);

Remember ref

is the MEM node, and type

is the node of type of
argument t

(usually it is a DECL, but it still can be a type node). Below at line 1598 honor_readonly

in the hook is false for all front-end in GCC current version.

set_mem_attributes_minus_bitpos
(continue)

1595

MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);

1596

MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P
(type);

1597

RTX_UNCHANGING_P (ref)

1598

|= ((lang_hooks

.honor_readonly

1599

&& (TYPE_READONLY (type) ||
TREE_READONLY (t)))

1600

|| (! TYPE_P (t) && TREE_CONSTANT (t)));

1601

1602

/* If we are making
an object of this type, or if this is a DECL, we know

1603

that it is a scalar if the type is not an
aggregate.
*/

1604

if ((objectp || DECL_P (t)) && !
AGGREGATE_TYPE_P (type))

1605

MEM_SCALAR_P (ref) = 1;

1606

1607

/* We can set the
alignment from the type if we are making an object,

1608

this is an INDIRECT_REF, or if
TYPE_ALIGN_OK.
*/

1609

if (objectp || TREE_CODE (t) == INDIRECT_REF
|| TYPE_ALIGN_OK (type))

1610

align = MAX (align, TYPE_ALIGN (type));

1611

1612

/* If the size is
known, we can set that.
*/

1613

if (TYPE_SIZE_UNIT (type) &&
host_integerp (TYPE_SIZE_UNIT (type), 1))

1614

size = GEN_INT (tree_low_cst
(TYPE_SIZE_UNIT (type), 1));

1615

1616

/* If T is not a
type, we may be able to deduce some more information about

1617

the expression.
*/

1618

if (! TYPE_P (t))

1619

{

1620

maybe_set_unchanging
(ref, t);

1621

if (TREE_THIS_VOLATILE (t))

1622

MEM_VOLATILE_P (ref) = 1;

1623

1624

/* Now remove any conversions: they don't
change what the underlying

1625

object is. Likewise for SAVE_EXPR.

*/

1626

while
(TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) ==
CONVERT_EXPR

1627

|| TREE_CODE (t) == NON_LVALUE_EXPR

1628

|| TREE_CODE (t) == VIEW_CONVERT_EXPR

1629

|| TREE_CODE (t) == SAVE_EXPR)

1630

t = TREE_OPERAND (t, 0);

1631

1632

/* If this
expression can't be addressed (e.g., it contains a reference

1633

to a non-addressable field), show we
don't change its alias set.
*/

1634

if (! can_address_p (t))

1635

MEM_KEEP_ALIAS_SET_P (ref) = 1;

1636

1637

/* If this is a
decl, set the attributes of the MEM from it.

*/

1638

if (DECL_P (t))

1639

{

1640

expr = t;

1641

offset = const0_rtx;

1642

apply_bitpos = bitpos;

1643

size = (DECL_SIZE_UNIT (t)

1644

&& host_integerp
(DECL_SIZE_UNIT (t), 1)

1645

? GEN_INT (tree_low_cst
(DECL_SIZE_UNIT (t), 1)) : 0);

1646

align = DECL_ALIGN (t);

1647

}

1648

1649

/* If this is a
constant, we know the alignment.
*/

1650

else if (TREE_CODE_CLASS (TREE_CODE (t)) ==
'c')

1651

{

1652

align = TYPE_ALIGN (type);

1653

#ifdef

CONSTANT_ALIGNMENT

1654

align = CONSTANT_ALIGNMENT (t, align);

1655

#endif

1656

}

1657

1658

/* If this is a
field reference and not a bit-field, record it.

*/

1659

/* ??? There is some information that can
be gleened from bit-fields,

1660

such as the word offset in the structure
that might be modified.

1661

But skip it for now.
*/

1662

else if (TREE_CODE (t) == COMPONENT_REF

1663

&& ! DECL_BIT_FIELD
(TREE_OPERAND (t, 1)))

1664

{

1665

expr = component_ref_for_mem_expr
(t);

1666

offset = const0_rtx;

1667

apply_bitpos = bitpos;

1668

/* ??? Any
reason the field size would be different than

1669

the size we got from the type?
*/

1670

}

RTL node also needs be told if its content is unchangable
(constant), RTX_UNCHANGING_P is the tag for the purpose. If above honor_readonly

in the hook is true, it means setting RTX_UNCHANGING_P if TREE_READONLY or
TYPE_READONLY hold. Pay attention to statement at line 1600, if t’s value is
constant, setting RTX_UNCHANGING_P. Besides, if t satisfies condition at line
602 below, setting RTX_UNCHANGING_P too. See that these two conditions are not
overlapped.

594

void

595

maybe_set_unchanging

(rtx ref, tree t)

in explow.c

596

{

597

/* We can set RTX_UNCHANGING_P from
TREE_READONLY for decls whose

598

initialization is only executed once, or
whose initializer always

599

has the same value. Currently we simplify
this to PARM_DECLs in the

600

first case, and decls with TREE_CONSTANT
initializers in the second.
*/

601

602

if ((TREE_READONLY (t) && DECL_P (t)

603

&& (DECL_EXTERNAL (t)

604

|| TREE_CODE (t) == PARM_DECL

605

|| (DECL_INITIAL (t) &&
TREE_CONSTANT (DECL_INITIAL (t)))))

606

|| TREE_CODE_CLASS (TREE_CODE (t)) == 'c')

607

RTX_UNCHANGING_P (ref) = 1;

608

}

In previous, we have seen the process of conversion in front-end, in
C/C++, conversion only changes the representation of object, but does not
change the property of the memory, such as size, position occupied. The
representation of object only means to semantic and syntax checking done in
front-end, the back-end doesn’t care what the object looks like, but what it is
in memory. So WHILE loop at line 1626 strips these enclosings useless in
back-end.

Next, for constant of specified type, target platform may have
specific alignment requirement, at line 1653 macro CONSTANT_ALIGNMENT is
defined as ix86_constant_alignment

for x86/Linux target. The function does necessary adjustment upon alignment.

Similarly, in COMPONENT_REF node, the front-end, out of purpose of
maintaining the consistency of semanteme and syntax, may encapsulate it several
times. Below function reveals these meaningless encapsulations.

1489

static
tree

1490

component_ref_for_mem_expr

(tree ref)

in emit-rtl.c

1491

{

1492

tree inner = TREE_OPERAND (ref, 0);

1493

1494

if (TREE_CODE (inner) == COMPONENT_REF)

1495

inner = component_ref_for_mem_expr (inner);

1496

else

1497

{

1498

tree placeholder_ptr = 0;

1499

1500

/* Now remove any
conversions: they don't change what the underlying

1501

object is. Likewise for SAVE_EXPR. Also
handle PLACEHOLDER_EXPR.
*/

1502

while
(TREE_CODE (inner) == NOP_EXPR || TREE_CODE (inner) == CONVERT_EXPR

1503

|| TREE_CODE (inner) == NON_LVALUE_EXPR

1504

|| TREE_CODE (inner) ==
VIEW_CONVERT_EXPR

1505

|| TREE_CODE (inner) == SAVE_EXPR

1506

|| TREE_CODE (inner) ==
PLACEHOLDER_EXPR)

1507

if (TREE_CODE (inner) ==
PLACEHOLDER_EXPR)

1508

inner = find_placeholder (inner, &placeholder_ptr);

1509

else

1510

inner = TREE_OPERAND (inner, 0);

1511

1512

if (! DECL_P (inner))

1513

inner = NULL_TREE;

1514

}

1515

1516

if (inner == TREE_OPERAND (ref, 0))

1517

return
ref;

1518

else

1519

return
build (COMPONENT_REF, TREE_TYPE (ref), inner,

1520

TREE_OPERAND (ref, 1));

1521

}

Below ARRAY_REF stands for array accesses; first operand is the
array, the second is the index. So DO WHILE loop at line works out the offset
from the element accessed to the head of the array. This offset is saved in off_tree

below. Note at line 1722, because it uses binary complement code, it gets the
lowest bit of 1 in ioff

,
that is the boundary the accessed element aligns.

set_mem_attributes_minus_bitpos
(continue)

1672

/* If this is an
array reference, look for an outer field reference.
*/

1673

else if (TREE_CODE (t) == ARRAY_REF)

1674

{

1675

tree off_tree = size_zero_node;

1676

/* We can't
modify t, because we use it at the end of the

1677

function.
*/

1678

tree t2 = t;

1679

1680

do

1681

{

1682

tree index = TREE_OPERAND (t2, 1);

1683

tree array = TREE_OPERAND (t2, 0);

1684

tree domain = TYPE_DOMAIN (TREE_TYPE
(array));

1685

tree low_bound = (domain ?
TYPE_MIN_VALUE (domain) : 0);

1686

tree unit_size = TYPE_SIZE_UNIT
(TREE_TYPE (TREE_TYPE (array)));

1687

1688

/* We assume
all arrays have sizes that are a multiple of a byte.

1689

First subtract the lower bound, if
any, in the type of the

1690

index, then convert to sizetype and
multiply by the size of the

1691

array element.
*/

1692

if (low_bound != 0 && ! integer_zerop
(low_bound))

1693

index = fold (build (MINUS_EXPR,
TREE_TYPE (index),

1694

index, low_bound));

1695

1696

/* If the
index has a self-referential type, pass it to a

1697

WITH_RECORD_EXPR; if the component
size is, pass our

1698

component to one.
*/

1699

if (CONTAINS_PLACEHOLDER_P (index))

1700

index = build (WITH_RECORD_EXPR,
TREE_TYPE (index), index, t2);

1701

if (CONTAINS_PLACEHOLDER_P (unit_size))

1702

unit_size = build (WITH_RECORD_EXPR,
sizetype,

1703

unit_size, array);

1704

1705

off_tree

1706

= fold (build (PLUS_EXPR, sizetype,

1707

fold (build (MULT_EXPR,
sizetype,

1708

index,

1709

unit_size)),

1710

off_tree));

1711

t2 = TREE_OPERAND (t2, 0);

1712

}

1713

while
(TREE_CODE (t2) == ARRAY_REF);

1714

1715

if (DECL_P (t2))

1716

{

1717

expr = t2;

1718

offset = NULL;

1719

if (host_integerp (off_tree, 1))

1720

{

1721

HOST_WIDE_INT ioff = tree_low_cst
(off_tree, 1);

1722

HOST_WIDE_INT aoff = (ioff &
-ioff) * BITS_PER_UNIT;

1723

align = DECL_ALIGN (t2);

1724

if (aoff && (unsigned
HOST_WIDE_INT) aoff < align)

1725

align = aoff;

1726

offset = GEN_INT (ioff);

1727

apply_bitpos = bitpos;

1728

}

1729

}

1730

else if (TREE_CODE (t2) == COMPONENT_REF)

1731

{

1732

expr = component_ref_for_mem_expr (t2);

1733

if (host_integerp (off_tree, 1))

1734

{

1735

offset = GEN_INT (tree_low_cst
(off_tree, 1));

1736

apply_bitpos = bitpos;

1737

}

1738

/* ??? Any
reason the field size would be different than

1739

the size we got from the type?
*/

1740

}

1741

else if (flag_argument_noalias

> 1

1742

&& TREE_CODE (t2) ==
INDIRECT_REF

1743

&& TREE_CODE (TREE_OPERAND
(t2, 0)) == PARM_DECL)

1744

{

1745

expr = t2;

1746

offset = NULL;

1747

}

1748

}

1749

1750

/* If this is a
Fortran indirect argument reference, record the

1751

parameter decl.
*/

1752

else if (flag_argument_noalias

> 1

1753

&& TREE_CODE (t) ==
INDIRECT_REF

1754

&& TREE_CODE (TREE_OPERAND
(t, 0)) == PARM_DECL)

1755

{

1756

expr = t;

1757

offset = NULL;

1758

}

1759

}

1760

1761

/* If we modified
OFFSET based on T, then subtract the outstanding

1762

bit position offset. Similarly, increase
the size of the accessed

1763

object to contain the negative offset.
*/

1764

if (apply_bitpos)

1765

{

1766

offset = plus_constant (offset,
-(apply_bitpos / BITS_PER_UNIT));

1767

if (size)

1768

size = plus_constant (size, apply_bitpos
/ BITS_PER_UNIT);

1769

}

1770

1771

/* Now set the
attributes we computed above.
*/

1772

MEM_ATTRS (ref)

1773

= get_mem_attrs (alias, expr, offset, size,
align, GET_MODE (ref));

1774

1775

/* If this is
already known to be a scalar or aggregate, we are done.
*/

1776

if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P
(ref))

1777

return
;

1778

1779

/* If it is a
reference into an aggregate, this is part of an aggregate.

1780

Otherwise we don't know.
*/

1781

else if (TREE_CODE (t) == COMPONENT_REF ||
TREE_CODE (t) == ARRAY_REF

1782

|| TREE_CODE (t) == ARRAY_RANGE_REF

1783

|| TREE_CODE (t) == BIT_FIELD_REF)

1784

MEM_IN_STRUCT_P (ref) = 1;

1785

}

Above flag flag_argument_noalias

, if is 0, pointer arguments
may alias each other (true in C); if is 1, pointer arguments may not alias each
other but may alias global variables; if is 2, pointer arguments may not alias
each other and may not alias global variables (true in Fortran).

Back build_constant_desc

, it should not assign
alias set of the type to the constant, as it can’t be changed. Front-end
prepares const_alias_set

specially for constants. The first call of set_mem_alias_set

at line 2455, sets the
alias set of RTL node of constant into 0, to bypass the checking for alias set
confliction.

1806

void

1807

set_mem_alias_set

(rtx mem,
HOST_WIDE_INT set)

in emit-rtl.c

1808

{

1809

#ifdef
ENABLE_CHECKING

1810

/* If the new and
old alias sets don't conflict, something is wrong.
*/

1811

if (!alias_sets_conflict_p
(set, MEM_ALIAS_SET (mem)))

1812

abort ();

1813

#endif

1814

1815

MEM_ATTRS (mem) = get_mem_attrs
(set, MEM_EXPR (mem), MEM_OFFSET (mem),

1816

MEM_SIZE (mem), MEM_ALIGN (mem),

1817

GET_MODE (mem));

1818

}

Then at line 2464, refers to section Create
RTX object for builtin
for the detail of target platform hook encode_section_info,
the function sets SYMBOL_REF_FLAGS field for the RTL node.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: