Studying note of GCC-3.4.6 source (168)

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.

 

你可能感兴趣的:(tree,reference,Descriptor,attributes,Constants,Pointers)