2.2.3.1.5.2.2.5. UNION的布局
在上面854行,rli->t是正在被布局的类的树节点,能到这里,field一定是一个FIELD_DECL。如果rli->t不是一个RECORD_TYPE,在C++里,它一定是一个代表union的节点。它有和class及struct不同的布局方案。
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,对于x86是128。
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_align是0,意味着“对齐量随你喜欢”。
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_DECL的UNION_TYPE或RECORD_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_p,GCC支持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编译器对位域及包含它的结构体的对齐量的处理,定义这个宏。
具体的行为是:具名位域的类型(int,short或其他整型)会对整个结构的对齐施加影响,就好像结构真的包含了该类型的普通的域。另外,这个位域应该这样放置在结构中,它能被放入该类型普通的域占的空间,不会跨过其边界。
因此,在大多数机器上,一个具有int类型的具名位域不会跨过4字节的边界,并使得整个结构具有4字节的对齐量(真正被应用的对齐量可能不是4字节,它还由别的对齐参数控制)【注:下面可以看到,编译器会为具名位域查找最合适的整型,作为它最后的类型】。
一个匿名的位域(unnamed bit-field)不会对包含它的结构的对齐产生影响。
如果这个宏被定义,它的定义应该是一个C的表达式,表达式的值非零,就会采用上面的行为。
注意如果这个宏没有定义,或者它的值为0,一些位域可能会跨越对齐边界。如果具有insv,extv和extzv这些可以直接访问内存的指令,编译器可以支持这样的形式。
其他使得位域能够工作的方法,是把STRUCTURE_SIZE_BOUNDARY定义得和BIGGEST_ALIGNMENT一样大。那么任意一个结构都在字的边界对齐(原句:Then every structure can be accessed with fullwords)。
除非机器有位域指令(注:即insv,extv,extzv)或者你按上面的方法定义了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);
}
如果打印出2和5,那么这个编译器的行为,可以通过设定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.def和i386-mode.def产生的。它记录模式的对齐量。注意到VOID和BLK模式的对齐量为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 }
在470和471行的条件,表示如果域是紧凑的,但对齐量没有由packed属性指定。而472到474行的条件,则表明同时如果域,要么不可取地址(位域即是这样),要么其DECL_SIZE_UNIT为0(DECL_SIZE_UNIT还未设置,似乎不太可能),要么其DECL_SIZE_UNIT是整型常量;那么确保它的对齐量至少是一个字节(这主要是考虑到紧凑格式下,空的基类)。
而上面的478行,maximum_field_alignment由#pragma pack(N)设定。 这个指示(directive)对于用户,最后起作用。
接着在485行,BIGGEST_FIELD_ALIGNMENT由libobjc使用。这里没有定义。
而在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字节,但在32位x86上,除非特别声明,只需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_64BIT对64位芯片成立,而TARGET_ALIGN_DOUBLE成立,则表示使用了编译选项-malign-double(默认是关闭的),使得double,long double,long 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 正按此设置。