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

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]对此的解释如下:

这个目标平台钩子返回true,如果在给定的RECORD_TYPE中,其位域按照Microsoft Visual C/C++的规则进行布局。也就是,(i)如果一个位域与其前一个位域是大小不同的类型,它们不能共享同一个存储单元,而且该位域要根据,其类型和前一个位域类型的对齐量大者,来对齐;(ii)一个0大小的位域,即使是无名的,也会对整个包含它的结构的对齐产生影响;除了(iii)一个0大小的位域,除非跟在另一个非0大小的位域后,它会被忽略。 如果这个钩子返回true,其他控制位域布局的宏都会被忽略。

当一个位域被插入一个紧凑的结构(record),其类型大小的空间被相邻的多个大小相同的位域所使用(也就是说,如果有long:3,在结构体中32比特会被占用,随后加入的相邻的long型位域也会被放入这32个比特中。但是,如果类型尺寸变了,一个拥有这个尺寸的新区域会被分配出来)。在一个非紧凑的结构体中,这和对齐量的使用相同,但在紧凑时是不同的。

如果MS位域和__attribute__((packed))同时被使用,后者将有优先权。当MS位域在应用时,__attribute__((packed))用在单个位域上,它在那个位域上有优先权,但结构体其余部分的对齐可能会影响它的放置 [2]

 

15481 static bool

15482 ix86_ms_bitfield_layout_p (tree record_type)                                                   in i386.c

15483 {

15484   return (TARGET_USE_MS_BITFIELD_LAYOUT &&

15485       !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))

15486     || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));

15487 }

 

上面,TYPE_ATTRIBUTES从应用属性的IDENTIFIER节点,获取了一个TREE_LIST。函数lookup_attribute遍历这个TREE_LIST,寻找有attr_name名字的IDENTIFIER节点。

 

2733 tree

2734 lookup_attribute (const char *attr_name, tree list)                                               in tree.c

2735 {

2736   tree l;

2737

2738   for (l = list; l; l = TREE_CHAIN (l))

2739   {

2740     if (TREE_CODE (TREE_PURPOSE (l)) != IDENTIFIER_NODE)

2741       abort ();

2742     if (is_attribute_p (attr_name, TREE_PURPOSE (l)))

2743       return l;

2744   }

2745

2746   return NULL_TREE;

2747 }

 

GCC里,属性的名字可以加上前后缀“__”,和没有前后缀的名字是一样的。函数is_attribute_p来识别这些属性(属性由GNU C++定义,编译器提供,其可用属性及意义参见[6])。

 

2688 int

2689 is_attribute_p (const char *attr, tree ident)                                                          in tree.c

2690 {

2691   int ident_len, attr_len;

2692   const char *p;

2693

2694   if (TREE_CODE (ident) != IDENTIFIER_NODE)

2695     return 0;

2696

2697   if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0)

2698     return 1;

2699

2700   p = IDENTIFIER_POINTER (ident);

2701   ident_len = strlen (p);

2702   attr_len = strlen (attr);

2703

2704   /* If ATTR is `__text__', IDENT must be `text'; and vice versa.  */

2705   if (attr[0] == '_')

2706   {

2707     if (attr[1] != '_'

2708        || attr[attr_len - 2] != '_'

2709        || attr[attr_len - 1] != '_')

2710       abort ();

2711     if (ident_len == attr_len - 4

2712        && strncmp (attr + 2, p, attr_len - 4) == 0)

2713       return 1;

2714   }

2715   else

2716   {

2717     if (ident_len == attr_len + 4

2718        && p[0] == '_' && p[1] == '_'

2719        && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'

2720        && strncmp (attr, p + 2, attr_len) == 0)

2721       return 1;

2722   }

2723

2724   return 0;

2725 }

 

回到ix86_ms_bitfield_layout_pGCC支持2种结构体的布局,其一是微软使用的(也称作native),另一种则是GCC使用的。TARGET_USE_MS_BITFIELD_LAYOUT为非零值如果使用了编译选项-ms-bitfields,这个选项表示使用MS的布局。而ix86_ms_bitfield_layout_p 就会返回非零值。

如果要求的是GCC布局,412行的PCC_BITFIELD_TYPE_MATTERS,对于x86的系统,值是1。因此非紧凑的,0大小位域的对齐量,根据其的类型来设置。例如,域short i: 0,对于GCC布局,对齐量将是16比特(和类型short相同)。

对于PCC_BITFIELD_TYPE_MATTERS[2]给出了如下的详细解释:

如果你希望模仿其他C编译器对位域及包含它的结构体的对齐量的处理,定义这个宏。

具体的行为是:具名位域的类型(intshort或其他整型)会对整个结构的对齐施加影响,就好像结构真的包含了该类型的普通的域。另外,这个位域应该这样放置在结构中,它能被放入该类型普通的域占的空间,不会跨过其边界。

因此,在大多数机器上,一个具有int类型的具名位域不会跨过4字节的边界,并使得整个结构具有4字节的对齐量(真正被应用的对齐量可能不是4字节,它还由别的对齐参数控制)【注:下面可以看到,编译器会为具名位域查找最合适的整型,作为它最后的类型】。

一个匿名的位域(unnamed bit-field)不会对包含它的结构的对齐产生影响。

如果这个宏被定义,它的定义应该是一个C的表达式,表达式的值非零,就会采用上面的行为。

注意如果这个宏没有定义,或者它的值为0,一些位域可能会跨越对齐边界。如果具有insvextvextzv这些可以直接访问内存的指令,编译器可以支持这样的形式。

其他使得位域能够工作的方法,是把STRUCTURE_SIZE_BOUNDARY定义得和BIGGEST_ALIGNMENT一样大。那么任意一个结构都在字的边界对齐(原句:Then every structure can be accessed with fullwords)。

除非机器有位域指令(注:即insvextvextzv)或者你按上面的方法定义了STRUCTURE_SIZE_BOUNDARY,你必须将PCC_BITFIELD_TYPE_MATTERS定义为非0值。

如果你的目的是,使得GCC采用其他编译器布局位域的方案,这里给出查看别的编译器是如何做的方法。编译并运行下面的程序:

          struct foo1 {

            char x;

            char :0;

            char y;

          };

         

          struct foo2 {

            char x;

            int :0;

            char y;

          };

         

          main () {

            printf ("Size of foo1 is %d/n", sizeof (struct foo1));

            printf ("Size of foo2 is %d/n", sizeof (struct foo2));

            exit (0);

          }

如果打印出25,那么这个编译器的行为,可以通过设定PCC_BITFIELD_TYPE_MATTERS得到的[2]

接下来,对于非0大小的位域,函数要查找合用的,用于替代的整型模式,例如,int j: 8会被char j所代替。

 

layout_decl (continue)

 

428        /* See if we can use an ordinary integer mode for a bit-field.

429          Conditions are: a fixed size that is correct for another mode

430          and occupying a complete byte or bytes on proper boundary.  */

431        if (TYPE_SIZE (type) != 0

432            && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST

433            && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)

434        {

435          enum machine_mode xmode

436               = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);

437 

438          if (xmode != BLKmode

439               && (known_align == 0

440                   || known_align >= GET_MODE_ALIGNMENT (xmode)))

441          {

442            DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),

443                                     DECL_ALIGN (decl));

444            DECL_MODE (decl) = xmode;

445            DECL_BIT_FIELD (decl) = 0;

446          }

447        }

448 

449             /* Turn off DECL_BIT_FIELD if we won't need it set.  */

450             if (TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode

451            && known_align >= TYPE_ALIGN (type)

452            && DECL_ALIGN (decl) >= TYPE_ALIGN (type))

453           DECL_BIT_FIELD (decl) = 0;

454      }

 

436行,我们已经看到函数mode_for_size_tree会找出比声明的尺寸大的,最接近的整型模式。而440行的GET_MODE_ALIGNMENT只是调用get_mode_alignment

 

299  unsigned int

300  get_mode_alignment (enum machine_mode mode)                                 in stor-layout.c

301  {

302    return MIN (BIGGEST_ALIGNMENT, MAX (1, mode_base_align[mode]*BITS_PER_UNIT));

303  }

 

mode_base_align是由genmode 根据文件machmode.defi386-mode.def产生的。它记录模式的对齐量。注意到VOIDBLK模式的对齐量为0

BIGGEST_ALIGNMENT定义了硬件支持的,所有基本类型(fundamental data type)都能被对齐的最小边界的比特数。没有数据类型需要更宽的对齐。对于x86系统,Pentium+倾向DFmode的值对齐在64位边界,而Pentium Pro倾向Xfmode的值对齐在128位的边界。

然而,这仍然隐藏了一个重要的事实。如果位域不是0大小的,而且没有被合适的模式所替代,其DECL_ALIGN 在这里仍然是未设置的(在make_node中初始化为0)。对于RECORD_TYPE,对位域的布局,这是重要的线索。

2.2.3.1.5.2.2.5.3.  其他域声明的处理

其他非位域则由下面的代码来处理。

 

layout_decl (continue)

 

455      else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))

456        /* Don't touch DECL_ALIGN. For other packed fields, go ahead and

457          round up; we'll reduce it again below. We want packing to

458          supersede USER_ALIGN inherited from the type, but defer to

459        alignment explicitly specified on the field decl.  */;

460      else

461        do_type_align (type, decl);

 

以下面的声明为例:

  struct sdla_cmd {

   char  opp_flag         __attribute__((packed));

   char  cmd               __attribute__((packed));

   short length                     __attribute__((packed));

   char  retval             __attribute__((packed));

   short dlci                  __attribute__((packed));

   char  flags               __attribute__((packed));

   short rxlost_int         __attribute__((packed));

   long  rxlost_app      __attribute__((packed));

   char  reserve[2]              __attribute__((packed));

   char  data[SDLA_MAX_DATA]     __attribute__((packed)); /* transfer data buffer */

} __attribute__((aligned (2)));

 

对于上面的域声明,DECL_PACKED会被设置,而DECL_USER_ALIGN也会被设置,因为包含它们的结构体被声明为对齐在边界2。对于这种情况,我们把DECL_ALIGN留待下面处理。

对于其他域声明,do_type_align会根据伴随的类型,更新声明的对齐属性。这个对齐信息也来自mode_base_align

2.2.3.1.5.2.2.5.4.  进一步调整

接下来,还需要根据目标平台,进行一些调整。

 

layout_decl (continue)

 

463      /* If the field is of variable size, we can't misalign it since we

464        have no way to make a temporary to align the result. But this

465        isn't an issue if the decl is not addressable. Likewise if it

466        is of unknown size.

467 

468        Note that do_type_align may set DECL_USER_ALIGN, so we need to

469        check old_user_align instead.  */

470      if (DECL_PACKED (decl)

471         && !old_user_align

472         && (DECL_NONADDRESSABLE_P (decl)

473             || DECL_SIZE_UNIT (decl) == 0

474             || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))

475        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);

476 

477      /* Should this be controlled by DECL_USER_ALIGN, too?  */

478      if (maximum_field_alignment != 0)

479        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);

480      if (!DECL_USER_ALIGN (decl))

481      {

482        /* Some targets (i.e. i386, VMS) limit struct field alignment

483          to a lower boundary than alignment of variables unless

484          it was overridden by attribute aligned.  */

485  #ifdef BIGGEST_FIELD_ALIGNMENT

486        DECL_ALIGN (decl)

487          = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);

488  #endif

489  #ifdef ADJUST_FIELD_ALIGN

490        DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));

491  #endif

492      }

493    }

 

470471行的条件,表示如果域是紧凑的,但对齐量没有由packed属性指定。而472474行的条件,则表明同时如果域,要么不可取地址(位域即是这样),要么其DECL_SIZE_UNIT0DECL_SIZE_UNIT还未设置,似乎不太可能),要么其DECL_SIZE_UNIT是整型常量;那么确保它的对齐量至少是一个字节(这主要是考虑到紧凑格式下,空的基类)。

而上面的478行,maximum_field_alignment#pragma pack(N)设定。 这个指示(directive)对于用户,最后起作用。

接着在485行,BIGGEST_FIELD_ALIGNMENTlibobjc使用。这里没有定义。

而在489行,对于x86系统,ADJUST_FIELD_ALIGN被定义如下。它和BIGGEST_FIELD_ALIGNMENT的出现是互斥的。

 

843  #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) /                                   in i386.h

844     x86_field_alignment (FIELD, COMPUTED)

845  #endif

 

x86_field_alignment执行与目标平台相关的调整。走到这里,非紧凑类型的声明节点已经根据其类型进行了布局。其对齐量信息根据machmode.def而来。这是所有平台都通用的信息。对于某些类型,在特定的目标平台还需要微调。例如,double类型,machmode.def给出的对齐量为8字节,但在32x86上,除非特别声明,只需4字节。

 

15705 int

15706 x86_field_alignment (tree field, int computed)                                                         in i386.c

15707 {

15708   enum machine_mode mode;

15709   tree type = TREE_TYPE (field);

15710

15711   if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)

15712     return computed;

15713   mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE

15714                ? get_inner_array_type (type) : type);

15715   if (mode == DFmode || mode == DCmode

15716       || GET_MODE_CLASS (mode) == MODE_INT

15717       || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)

15718     return MIN (32, computed);

15719   return computed;

15720 }

 

上面15711行,TARGET_64BIT64位芯片成立,而TARGET_ALIGN_DOUBLE成立,则表示使用了编译选项-malign-double(默认是关闭的),使得doublelong doublelong long类型放在双倍,即8字节边界。在这些情况下,显然不需要调整。

15714行的get_inner_array_type,用于获取数组的元素的类型。

 

3827 tree

3828 get_inner_array_type (tree array)                                                                      in tree.c

3829 {

3830   tree type = TREE_TYPE (array);

3831

3832   while (TREE_CODE (type) == ARRAY_TYPE)

3833     type = TREE_TYPE (type);

3834

3835   return type;

3836 }

 

layout_decl余下部分处理大小未定的声明。例如,GNU C++支持局部的数组维度为非常量,比如:int j = 5; char arrC[i]; ,不过对于类域这个扩展不适用。

2.2.3.1.5.2.2.5.5.  更新record_layout_info

接下来,我们要把布局数据更新入record_layout_info。在下面,field持有从layout_decl得到的数据。

 

update_alignment_for_field (continue)

 

700    desired_align = DECL_ALIGN (field);

701    user_align = DECL_USER_ALIGN (field);

702 

703    is_bitfield = (type != error_mark_node

704                && DECL_BIT_FIELD_TYPE (field)

705                && ! integer_zerop (TYPE_SIZE (type)));

706 

707    /* Record must have at least as much alignment as any field.

708      Otherwise, the alignment of the field within the record is

709      meaningless.  */

710    if (is_bitfield && (* targetm.ms_bitfield_layout_p) (rli->t))

711    {

712      /* Here, the alignment of the underlying type of a bitfield can

713        affect the alignment of a record; even a zero-sized field

714        can do this. The alignment should be to the alignment of

715        the type, except that for zero-size bitfields this only

716        applies if there was an immediately prior, nonzero-size

717        bitfield. (That's the way it is, experimentally.) */

718      if (!integer_zerop (DECL_SIZE (field))

719          ? ! DECL_PACKED (field)

720           : (rli->prev_field

721             && DECL_BIT_FIELD_TYPE (rli->prev_field)

722             && ! integer_zerop (DECL_SIZE (rli->prev_field))))

723      {

724        unsigned int type_align = TYPE_ALIGN (type);

725        type_align = MAX (type_align, desired_align);

726        if (maximum_field_alignment != 0)

727          type_align = MIN (type_align, maximum_field_alignment);

728        rli->record_align = MAX (rli->record_align, type_align);

729        rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

730      }

731    }

732  #ifdef PCC_BITFIELD_TYPE_MATTERS

733    else if (is_bitfield && PCC_BITFIELD_TYPE_MATTERS)

734    {

735      /* Named bit-fields cause the entire structure to have the

736        alignment implied by their type.  */

737      if (DECL_NAME (field) != 0)

738      {

739        unsigned int type_align = TYPE_ALIGN (type);

740 

741  #ifdef ADJUST_FIELD_ALIGN

742        if (!TYPE_USER_ALIGN (type))

743          type_align = ADJUST_FIELD_ALIGN (field, type_align);

744  #endif

745 

746        if (maximum_field_alignment != 0)

747          type_align = MIN (type_align, maximum_field_alignment);

748        else if (DECL_PACKED (field))

749          type_align = MIN (type_align, BITS_PER_UNIT);

750 

751        /* The alignment of the record is increased to the maximum

752          of the current alignment, the alignment indicated on the

753          field (i.e., the alignment specified by an __aligned__

754          attribute), and the alignment indicated by the type of

755          the field.  */

756        rli->record_align = MAX (rli->record_align, desired_align);

757        rli->record_align = MAX (rli->record_align, type_align);

758 

759        if (warn_packed)

760          rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

761        user_align |= TYPE_USER_ALIGN (type);

762      }

763    }

764  #endif

765    else

766    {

767      rli->record_align = MAX (rli->record_align, desired_align);

768      rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

769    }

770 

771    TYPE_USER_ALIGN (rli->t) |= user_align;

772 

773    return desired_align;

774  }

 

上面的710行条件表示,如果采用MS的布局,而且是位域。再则它是紧凑的,或者它大小为0,而其前趋的位域声明为非0大小,那么进入724行的代码块。注意对于GCC的缺省位域布局,只有具名声明(naming declaration)会对结构体的对齐构成影响。

正如我们所理解的,union的大小由其最大成员的确定。在place_union_field中,rtl->offset 正按此设置。

 

 

你可能感兴趣的:(user,tree,layout,Integer,alignment,attributes)