现在的位置: 首页 > 综合 > 正文

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

2013年11月28日 ⁄ 综合 ⁄ 共 4451字 ⁄ 字号 评论关闭

2.2.3.1.5.2.2.5.            UNION的布局

在上面854行,rli->t是正在被布局的类的树节点,能到这里,field一定是一个FIELD_DECL。如果rli->t不是一个RECORD_TYPE,在C++里,它一定是一个代表union的节点。它有和classstruct不同的布局方案。

 

778  static void

779  place_union_field (record_layout_info rli, tree field)                              in stor-layout.c

780  {

781    update_alignment_for_field (rli, field, /*known_align=*/0);

782 

783    DECL_FIELD_OFFSET (field) = size_zero_node;

784    DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;

785    SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);

786 

787    /* We assume the union's size will be a multiple of a byte so we don't

788      bother with BITPOS.  */

789    if (TREE_CODE (rli->t) == UNION_TYPE)

790      rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));

791    else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)

792      rli->offset = fold (build (COND_EXPR, sizetype,

793                              DECL_QUALIFIER (field),

794                              DECL_SIZE_UNIT (field), rli->offset));

795  }

 

函数update_alignment_for_field更新rli中的各个有关对齐的域,并返回给field 的对齐量。注意在上面785行,BIGGEST_ALIGNMENT,对于x86128

 

686  static unsigned int

687  update_alignment_for_field (record_layout_info rli, tree field,                in stor-layout.c

688                           unsigned int known_align)

689  {

690    /* The alignment required for FIELD.  */

691    unsigned int desired_align;

692    /* The type of this field.  */

693    tree type = TREE_TYPE (field);

694    /* True if the field was explicitly aligned by the user.  */

695    bool user_align;

696    bool is_bitfield;

697 

698    /* Lay out the field so we know what alignment it needs.  */

699    layout_decl (field, known_align);

2.2.3.1.5.2.2.5.1.  FIELD_DECL的布局

在前面,我们看到为变量,参数及函数返回值声明创建节点的时候,layout_decl就会被调用。这个函数会为节点设置大小,模式和对齐量。然而在build_decl中,FIELD_DECL没有被立即布局,它延后到现在。注意到在这里known_align0,意味着“对齐量随你喜欢”。

 

352  void

353  layout_decl (tree decl, unsigned int known_align)                                  in stor-layout.c

354  {

355    tree type = TREE_TYPE (decl);

356    enum tree_code code = TREE_CODE (decl);

357    rtx rtl = NULL_RTX;

358 

359    if (code == CONST_DECL)

360      return;

361    else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL

362            && code != TYPE_DECL && code != FIELD_DECL)

363      abort ();

364 

365    rtl = DECL_RTL_IF_SET (decl);

366 

367    if (type == error_mark_node)

368      type = void_type_node;

369 

370    /* Usually the size and mode come from the data type without change,

371      however, the front-end may set the explicit width of the field, so its

372      size may not be the same as the size of its type. This happens with

373      bitfields, of course (an `int' bitfield may be only 2 bits, say), but it

374      also happens with other fields. For example, the C++ front-end creates

375      zero-sized fields corresponding to empty base classes, and depends on

376      layout_type setting DECL_FIELD_BITPOS correctly for the field. Set the

377      size in bytes from the size in bits. If we have already set the mode,

378      don't set it again since we can be called twice for FIELD_DECLs.  */

379 

380    TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);

381    if (DECL_MODE (decl) == VOIDmode)

382      DECL_MODE (decl) = TYPE_MODE (type);

383 

384    if (DECL_SIZE (decl) == 0)

385    {

386      DECL_SIZE (decl) = TYPE_SIZE (type);

387      DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);

388    }

389    else if (DECL_SIZE_UNIT (decl) == 0)

390      DECL_SIZE_UNIT (decl)

391        = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),

392                                     bitsize_unit_node));

 

函数的第一部分仅是按照伴随的TYPE节点,初始化DECL节点的部分域。

2.2.3.1.5.2.2.5.2.  位域声明节点的处理

在下面402行,如果FIELD_DECL是位域,DECL_BIT_FIELD返回非零值。

 

layout_decl (continue)

 

394    if (code != FIELD_DECL)

395      /* For non-fields, update the alignment from the type.  */

396      do_type_align (type, decl);

397    else

398      /* For fields, it's a bit more complicated...  */

399    {

400      bool old_user_align = DECL_USER_ALIGN (decl);

401 

402      if (DECL_BIT_FIELD (decl))

403      {

404        DECL_BIT_FIELD_TYPE (decl) = type;

405 

406        /* A zero-length bit-field affects the alignment of the next

407          field.  */

408        if (integer_zerop (DECL_SIZE (decl))

409            && ! DECL_PACKED (decl)

410            && ! (*targetm.ms_bitfield_layout_p) (DECL_FIELD_CONTEXT (decl)))

411        {

412  #ifdef PCC_BITFIELD_TYPE_MATTERS

413          if (PCC_BITFIELD_TYPE_MATTERS)

414            do_type_align (type, decl);

415          else

416  #endif

417          {

418  #ifdef EMPTY_FIELD_BOUNDARY

419            if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))

420            {

421              DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;

422              DECL_USER_ALIGN (decl) = 0;

423            }

424  #endif

425          }

426        }

 

在位域声明中,有声明大小为0的特殊情况(408行)。如果该域不要求紧凑布局在比特边界,那么需要进一步检查这个聚集类的属性。注意在410行,DECL_FIELD_CONTEXT获取包含这个FIELD_DECLUNION_TYPERECORD_TYPE节点。对象targetm是目标平台相关的,对于x86系统,函数指针ms_bitfield_layout_p指向ix86_ms_bitfield_layout_p

[2]对此的解释如下:

这个目标平台钩子返回

抱歉!评论已关闭.