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

5.13.5.2.2.1.1.3.3.            浮点数

与形式多样的整形常量不同,在 C++ 的前端中,具有 REAL_TYPE 类型的常量只能是 REAL_CST

 

output_constant (continue)

 

3791     case REAL_TYPE:

3792       if (TREE_CODE (exp) != REAL_CST)

3793         error ("initializer for floating value is not a floating constant");

3794

3795       assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);

3796       break ;

 

有关浮点常量的内容,在 创建浮点常量节点 一节已经有详细的描述,这里不再重复。

 

1918 void

1919 assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)

1920 {

1921   long data[4];

1922   int i;

1923   int bitsize, nelts, nunits, units_per;

1924

1925   /* This is hairy. We have a quantity of known size. real_to_target

1926     will put it into an array of *host* longs, 32 bits per element

1927     (even if long is more than 32 bits). We need to determine the

1928     number of array elements that are occupied (nelts) and the number

1929     of *target* min-addressable units that will be occupied in the

1930     object file (nunits). We cannot assume that 32 divides the

1931     mode's bitsize (size * BITS_PER_UNIT) evenly.

1932

1933     size * BITS_PER_UNIT is used here to make sure that padding bits

1934     (which might appear at either end of the value; real_to_target

1935     will include the padding bits in its output array) are included.  */

1936

1937   nunits = GET_MODE_SIZE (mode);

1938   bitsize = nunits * BITS_PER_UNIT;

1939   nelts = CEIL (bitsize, 32);

1940   units_per = 32 / BITS_PER_UNIT;

1941

1942   real_to_target (data, &d, mode);

1943

1944   /* Put out the first word with the specified alignment.  */

1945   assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);

1946   nunits -= units_per;

1947

1948   /* Subsequent words need only 32-bit alignment.  */

1949   align = min_align (align, 32);

1950

1951   for (i = 1; i < nelts; i++)

1952   {

1953     assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);

1954      nunits -= units_per;

1955   }

1956 }

 

上面 1942 行的 real_to_target 的核心是 round_for_format 函数,及与目标机器关联的 real_format 结构中的格式编码函数(通常是 encode_ieee_single encode_ieee_double )。

5.13.5.2.2.1.1.3.4.            字符串

字符串,在 C/C++ 中,默认就被视为常量。其对应的节点是 STRING_CST

 

output_constant (continue)

 

3798     case COMPLEX_TYPE:

3799       output_constant (TREE_REALPART (exp), thissize / 2, align);

3800       output_constant (TREE_IMAGPART (exp), thissize / 2,

3801                     min_align (align, BITS_PER_UNIT * (thissize / 2)));

3802       break ;

3803

3804     case ARRAY_TYPE:

3805     case VECTOR_TYPE:

3806       if (TREE_CODE (exp) == CONSTRUCTOR)

3807       {

3808         output_constructor (exp, size, align);

3809         return ;

3810       }

3811       else if (TREE_CODE (exp) == STRING_CST)

3812       {

3813         thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),

3814                       size);

3815         assemble_string (TREE_STRING_POINTER (exp), thissize);

3816       }

3817       else if (TREE_CODE (exp) == VECTOR_CST)

3818       {

3819         int elt_size;

3820         tree link;

3821         unsigned int nalign;

3822         enum machine_mode inner;

3823

3824         inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));

3825         nalign = MIN (align, GET_MODE_ALIGNMENT (inner));

3826

3827         elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));

3828

3829         link = TREE_VECTOR_CST_ELTS (exp);

3830         output_constant (TREE_VALUE (link), elt_size, align);

3831         while ((link = TREE_CHAIN (link)) != NULL)

3832             output_constant (TREE_VALUE (link), elt_size, nalign);

3833       }

3834       else

3835         abort ();

3836       break ;

 

STRING_CST 只是简单地封装了字符串,通过 TREE_STRING_POINTER TREE_STRING_LENGTH 可以获得这个字符串及其长度。

 

1190 void

1191 assemble_string (const char *p, int size)                                                      in varasm.c

1192 {

1193   int pos = 0;

1194   int maximum = 2000;

1195

1196   /* If the string is very long, split it up.  */

1197

1198   while (pos < size)

1199   {

1200     int thissize = size - pos;

1201     if (thissize > maximum)

1202       thissize = maximum;

1203

1204     ASM_OUTPUT_ASCII (asm_out_file , p, thissize);

1205

1206      pos += thissize;

1207     p += thissize;

1208   }

1209 }

 

为了避免汇编代码中对段长度的限制,每块字符串长度不超过 2000 个字符。下面的宏输出字符串的内容。在 452 行, STRING_LIMIT 被定义为 256 。也就是说如果字符串(剩下)部分少于 256 个字符,就通过 ASM_OUTPUT_LIMITED_STRING 来输出,这个宏与这里的 ASM_OUTPUT_ASCII 很类似。在 445 456 行,输出的是字符“ ”并换行。可以想见,这个宏将输出形如:

“………”

“………”

的字符串。

 

430  #undef   ASM_OUTPUT_ASCII

431  #define ASM_OUTPUT_ASCII (FILE, STR, LENGTH)                           /      in elfos.h

432    do                                                                /

433      {                                                             /

434        register const unsigned char *_ascii_bytes =                 /

435              (const unsigned char *) (STR);                                /

436        register const unsigned char *limit = _ascii_bytes + (LENGTH);   /

437        register unsigned bytes_in_chunk = 0;                          /

438                                                                 /

439        for (; _ascii_bytes < limit; _ascii_bytes++)                    /

440        {                                                  /

441           register const unsigned char *p;                        /

442                                                                 /

443           if (bytes_in_chunk >= 60)                                /

444           {                                                      /

445             fprintf ((FILE), "/"/n");                                 /

446             bytes_in_chunk = 0;                              /

447           }                                                      /

448                                                                 /

449           for (p = _ascii_bytes; p < limit && *p != '/0'; p++)           /

450             continue ;                                              /

451                                                                 /

452           if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT)  /

453           {                                                      /

454             if (bytes_in_chunk > 0)                                 /

455            {                                           /

456               fprintf ((FILE), "/"/n");                       /

457               bytes_in_chunk = 0;                                  /

458            }                                           /

459                                                                 /

460             ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes);        /

461             _ascii_bytes = p;                                          /

462           }                                                      /

463           else                                                  /

464           {                                                      /

465             register int escape;                                 /

466             register unsigned ch;                              /

467                                                                 /

468             if (bytes_in_chunk == 0)                               /

469              fprintf ((FILE), "%s/"", ASCII_DATA_ASM_OP);             /

470                                                                 /

471             switch (escape = ESCAPES[ch = *_ascii_bytes])          /

472            {                                           /

473              case 0:                                              /

474                 putc (ch, (FILE));                                 /

475                 bytes_in_chunk++;                                /

476                 break ;                                    /

477              case 1:                                              /

478                 fprintf ((FILE), "//%03o", ch);                /

479                 bytes_in_chunk += 4;                                   /

480                 break ;                                    /

481              default :                                      /

482                 putc ('//', (FILE));                                 /

483                 putc (escape, (FILE));                           /

484                 bytes_in_chunk += 2;                                   /

485                 break ;                                    /

486            }                                           /

487           }                                                      /

488        }                                                  /

489                                                                 /

490        if (bytes_in_chunk > 0)                                        /

491          fprintf ((FILE), "/"/n");                              /

492      }                                                             /

493    while (0)

 

469 行, ASCII_DATA_ASM_OP 被定义为“ /t.ascii/t ”。 471 行的 ESCAPES 是一个如下的字符串。

"/1/1/1/1/1/1/1/1btn/1fr/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/

/0/0/"/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/

/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0///0/0/0/

/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/1/

/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/

/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/

/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/

/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1"

它指定了如何输出对应的 ASCII 码的字母。

5.13.5.2.2.1.1.3.5.            聚集类初始值

如果聚集类型的存在初始值常量(初始值为空的情形由 output_constant 3756 行处理,参见 0的内容 一节),则来到下面的代码中。

 

output_constant (continue)

 

3838     case RECORD_TYPE:

3839     case UNION_TYPE:

3840       if (TREE_CODE (exp) == CONSTRUCTOR)

3841         output_constructor (exp, size, align);

3842       else

3843         abort ();

3844       return ;

3845

3846     case SET_TYPE:

3847       if (TREE_CODE (exp) == INTEGER_CST)

3848         assemble_integer (expand_expr (exp, NULL_RTX,

3849                                    VOIDmode, EXPAND_INITIALIZER),

3850                        thissize, align, 1);

3851       else if (TREE_CODE (exp) == CONSTRUCTOR)

3852       {

3853         unsigned char *buffer = alloca (thissize);

3854         if (get_set_constructor_bytes (exp, buffer, thissize))

3855           abort ();

3856         assemble_string ((char *) buffer, thissize);

3857       }

3858       else

3859         error ("unknown set constructor type");

3860       return ;

3861

3862     case ERROR_MARK:

3863       return ;

3864

3865     default :

3866       abort ();

3867   }

3868

3869   if (size > thissize)

3870     assemble_zeros (size - thissize);

3871 }

 

前面我们看到 CONSTRUCTOR 节点在其 CONSTRUCTOR_ELTS 处保存了对应每个成员的初始值的 tree_list 链表。在这个链表的每个节点中,其 TREE_VALUE 域是初始值,其 TREE_PURPOSE 域,对于类类型是 FIELD_DECL 节点,对于数组类型则是索引。

 

3918 static void

3919 output_constructor (tree exp, unsigned HOST_WIDE_INT size,                            in varasm.c

3920                  unsigned int align)

3921 {

3922   tree type = TREE_TYPE (exp);

3923   tree link, field = 0;

3924   tree min_index = 0;

3925   /* Number of bytes output or skipped so far.

3926     I n other words, current position within the constructor.  */

3927   HOST_WIDE_INT total_bytes = 0;

3928   /* Nonzero means BYTE contains part of a byte, to be output.  */

3929   int byte_buffer_in_use = 0;

3930   int byte = 0;

3931

3932   if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)

3933     abort ();

3934

3935   if (TREE_CODE (type) == RECORD_TYPE)

3936     field = TYPE_FIELDS (type);

3937

3938   if (TREE_CODE (type) == ARRAY_TYPE

3939       && TYPE_DOMAIN (type) != 0)

3940     min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));

3941

3942   /* As LINK goes through the elements of the constant,

3943     FIELD goes through the structure fields, if the constant is a structure.

3944     if the constant is a union, then we override this,

3945     by getting the field from the TREE_LIST element.

3946     But the constant could also be an array. Then FIELD is zero.

3947

3948     There is always a maximum of one element in the chain LINK for unions

3949     (even if the initializer in a source program incorrectly contains

3950     more one).  */

3951   for (link = CONSTRUCTOR_ELTS (exp);

3952        link;

3953        link = TREE_CHAIN (link),

3954        field = field ? TREE_CHAIN (field) : 0)

3955   {

3956     tree val = TREE_VALUE (link);

3957     tree index = 0;

3958

3959     /* The element in a union constructor specifies the proper field

3960        or index.  */

3961     if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE

3962            || TREE_CODE (type) == QUAL_UNION_TYPE)

3963           && TREE_PURPOSE (link) != 0)

3964       field = TREE_PURPOSE (link);

3965

3966     else if (TREE_CODE (type) == ARRAY_TYPE)

3967       index = TREE_PURPOSE (link);

3968

3969 #ifdef ASM_COMMENT_START

3970     if (field && flag_verbose_asm )

3971       fprintf (asm_out_file , "%s %s:/n",

3972             ASM_COMMENT_START,

3973             DECL_NAME (field)

3974                 ? IDENTIFIER_POINTER (DECL_NAME (field))

3975                 : "<anonymous>");

3976 #endif

3977

3978     /* Eliminate the marker that makes a cast not be an lvalue.  */

3979     if (val != 0)

3980       STRIP_NOPS (val);

 

注意在上面对于数组,变量 field NULL ,它使用变量 index ;对于类类型则反之。在 3980 行, STRIP_NOPS 将不影响汇编输出的封装(例如不需要产生代码的转换)去掉。

 

output_constructor (continue)

 

3982     if (index && TREE_CODE (index) == RANGE_EXPR)

3983     {

3984        unsigned HOST_WIDE_INT fieldsize

3985            = int_size_in_bytes (TREE_TYPE (type));

3986        HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);

3987        HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);

3988        HOST_WIDE_INT index;

3989        unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);

3990

3991        for (index = lo_index; index <= hi_index; index++)

3992        {

3993          /* Output the element's initial value. */

3994          if (val == 0)

3995           assemble_zeros (fieldsize);

3996          else

3997           output_constant (val, fieldsize, align2);

3998

3999          /* Count its size.  */

4000          total_bytes += fieldsize;

4001        }

4002     }

 

前端的节点 RANGE_EXPR 用于数组,表示一个范围的元素。例如,

int a [8] = {0};

其初始值就是一个 RANGE_EXPR ,表示在索引 0 7 的范围内使用初始值 0 。在上面的代码中可用看到,其第一个操作数是下限,而第二个操作数则是上限。在 C++ 中, RANGE_EXPR 的初始值只可能是 0

满足下面 4003 行条件的节点是:数组( field NULL )、非位域的类成员。变量 pos 保存了初始值所应用的位置。对于类成员,由于已经完成布局, 4010 行的 int_byte_position 通过调用 byte_position 获得其相对类头的偏移。对于数组,元素大小 x 索引跨度,就可以得到其到数组头的偏移( 4014 行)。

 

output_constructor (continue)

 

4003     else if (field == 0 || !DECL_BIT_FIELD (field))

4004     {

4005        /* An element that is not a bit-field.  */

4006

4007        unsigned HOST_WIDE_INT fieldsize;

4008        /* Since this structure is static,

4009          we know the positions are constant.  */

4010        HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;

4011        unsigned int align2;

4012

4013        if (index != 0)

4014          pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)

4015                * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));

4016

4017        /* Output any buffered-up bit-fields preceding this element.  */

4018        if (byte_buffer_in_use)

4019        {

4020          assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);

4021          total_bytes++;

4022          byte_buffer_in_use = 0;

4023        }

4024

4025        /* Advance to offset of this element.

4026          Note no alignment needed in an array, since that is guaranteed

4027          if each element has the proper size.  */

4028        if ((field != 0 || index != 0) && pos != total_bytes)

4029        {

4030          assemble_zeros (pos - total_bytes);

4031          total_bytes = pos;

4032        }

4033

4034        /* Find the alignment of this element.  */

4035        align2 = min_align (align, BITS_PER_UNIT * pos);

4036

4037        /* Determine size this element should occupy.  */

4038        if (field)

4039        {

4040          fieldsize = 0;

4041

4042          /* If this is an array with an unspecified upper bound,

4043            the initializer determines the size.  */

4044          /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,

4045            but we cannot do this until the deprecated support for

4046            initializing zero-length array members is removed.  */

4047          if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE

4048             && TYPE_DOMAIN (TREE_TYPE (field))

4049             && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))

4050         {

4051            fieldsize = array_size_for_constructor (val);

4052            /* Given a non-empty initialization, this field had

4053               better be last.  */

4054            if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE)

4055              abort ();

4056         }

4057            else if (DECL_SIZE_UNIT (field))

4058         {

4059            /* ??? This can't be right. If the decl size overflows

4060              a host integer we will silently emit no data.  */

4061            if (host_integerp (DECL_SIZE_UNIT (field), 1))

4062              fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);

4063         }

4064        }

4065        else

4066          fieldsize = int_size_in_bytes (TREE_TYPE (type));

4067

4068        /* Output the element's initial value.  */

4069        if (val == 0)

4070          assemble_zeros (fieldsize);

4071        else

4072           output_constant (val, fieldsize, align2);

4073

4074        /* Count its size.  */

4075        total_bytes += fieldsize;

4076     }

 

变量 total_bytes 记录着已初始化的大小。对于类, C++ 要求按成员声明的次序初始化(前端在布局时亦按照声明次序),因此如果出现 pos 不等于 total_bytes 的情况,则表明 pos total_bytes 之间是一个填充域。按标准要求,用 0 填充之。对于数组,因为元素大小一致,元素之间不需要填充域,若 pos 不等于 total_bytes ,则表明这部分元素的初始值没有给出,根据标准,需初始化为 0 。在 4018 行,变量 byte_buffer_in_use 来自下面位域初始值的处理。

那么下面的代码就是对类中位域成员初始值的处理。首先,其初始值必须是整型常量, 4077 行条件保证这一点。另外,位域与其之前的域之间亦可能有填充域,在 4098 行完成这个填充。

 

output_constructor (continue)

 

4077     else if (val != 0 && TREE_CODE (val) != INTEGER_CST)

4078       error ("invalid initial value for member `%s'",

4079              IDENTIFIER_POINTER (DECL_NAME (field)));

4080      else

4081     {

4082        /* Element that is a bit-field.  */

4083

4084        HOST_WIDE_INT next_offset = int_bit_position (field);

4085        HOST_WIDE_INT end_offset

4086            = (next_offset + tree_low_cst (DECL_SIZE (field), 1));

4087

4088        if (val == 0)

4089          val = integer_zero_node;

4090

4091        /* If this field does not start in this (or, next) byte,

4092          skip some bytes.  */

4093        if (next_offset / BITS_PER_UNIT != total_bytes)

4094        {

4095          /* Output remnant of any bit field in previous bytes.  */

4096          if (byte_buffer_in_use)

4097         {

4098            assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);

4099            total_bytes++;

4100            byte_buffer_in_use = 0;

4101         }

4102

4103          /* If still not at proper byte, advance to there.  */

4104          if (next_offset / BITS_PER_UNIT != total_bytes)

4105         {

4106            assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);

4107            total_bytes = next_offset / BITS_PER_UNIT;

4108         }

4109        }

4110

4111        if (! byte_buffer_in_use)

4112          byte = 0;

4113

4114        /* We must split the element into pieces that fall within

4115          separate bytes, and combine each byte with previous or

4116          following bit-fields.  */

4117

4118        /* next_offset is the offset n fbits from the beginning of

4119          the structure to the next bit of this element to be processed.

4120          end_offset is the offset of the first bit past the end of

4121          this element.  */

4122        while (next_offset < end_offset)

4123        {

4124          int this_time;

4125          int shift;

4126          HOST_WIDE_INT value;

4127          HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;

4128          HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;

4129

4130          /* Advance from byte to byte

4131            within this element when necessary.  */

4132           while (next_byte != total_bytes)

4133         {

4134            assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);

4135            total_bytes++;

4136            byte = 0;

4137          }

4138

4139          /* Number of bits we can process at once

4140            (all part of the same byte).  */

4141          this_time = MIN (end_offset - next_offset,

4142                         BITS_PER_UNIT - next_bit);

4143          if (BYTES_BIG_ENDIAN)

4144         {

4145            /* On big-endian machine, take the most significant bits

4146              first (of the bits that are significant)

4147              and put them into bytes from the most significant end.  */

4148            shift = end_offset - next_offset - this_time;

4149

4150            /* Don't try to take a bunch of bits that cross

4151               the word boundary in the INTEGER_CST. We can

4152              only select bits from the LOW or HIGH part

4153              not from both.  */

4154            if (shift < HOST_BITS_PER_WIDE_INT

4155                && shift + this_time > HOST_BITS_PER_WIDE_INT)

4156            {

4157              this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;

4158              shift = HOST_BITS_PER_WIDE_INT;

4159            }

4160

4161            /* Now get the bits from the appropriate constant word.  */

4162            if (shift < HOST_BITS_PER_WIDE_INT)

4163              value = TREE_INT_CST_LOW (val);

4164            else if (shift < 2 * HOST_BITS_PER_WIDE_INT)

4165            {

4166              value = TREE_INT_CST_HIGH (val);

4167              shift -= HOST_BITS_PER_WIDE_INT;

4168            }

4169            else

4170              abort ();

4171

4172            /* Get the result. This works only when:

4173               1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */

4174            byte |= (((value >> shift)

4175                    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))

4176                         << (BITS_PER_UNIT - this_time - next_bit));

4177         }

4178          else

4179         {

4180            /* On little-endian machines,

4181              take first the least significant bits of the value

4182              and pack them starting at the least significant

4183              bits of the bytes.  */

4184             shift = next_offset - int_bit_position (field);

4185

4186            /* Don't try to take a bunch of bits that cross

4187              the word boundary in the INTEGER_CST. We can

4188              only select bits from the LOW or HIGH part

4189                not from both.  */

4190            if (shift < HOST_BITS_PER_WIDE_INT

4191                && shift + this_time > HOST_BITS_PER_WIDE_INT)

4192              this_time = (HOST_BITS_PER_WIDE_INT - shift);

4193

4194            /* Now get the bits from the appropriate constant word.  */

4195            if (shift < HOST_BITS_PER_WIDE_INT)

4196              value = TREE_INT_CST_LOW (val);

4197            else if (shift < 2 * HOST_BITS_PER_WIDE_INT)

4198            {

4199              value = TREE_INT_CST_HIGH (val);

4200              shift -= HOST_BITS_PER_WIDE_INT;

4201            }

4202            else

4203              abort ();

4204

4205            /* Get the result. This works only when:

4206              1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */

4207            byte |= (((value >> shift)

4208                   & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))

4209                       << next_bit);

4210         }

4211

4212          next_offset += this_time;

4213          byte_buffer_in_use = 1;

4214        }

4215     }

4216   }

4217

4218   if (byte_buffer_in_use)

4219   {

4220     assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);

4221     total_bytes++;

4222   }

4223

4224   if ((unsigned HOST_WIDE_INT)total_bytes < size)

4225     assemble_zeros (size - total_bytes);

4226 }

 

上面的变量 next_offset 是这个位域的偏移(单位是比特),变量 end_offset 则记录着这个位域所要占用的内存的末尾(注意这个占用的内存可能多于一个字节,因此需要 4122 行的 WHILE 循环)。记得在类布局中(参见 GCC默认布局下位域 MS布局下的位域 一节)多个位域可能将共享同一块内存,因此我们只写入整字节的数据,还没占满整字节的数据保存在 byte 中,并由 byte_buffer_in_use 指示。又因为多个位域可以共享同一块内存,那么在写入它们共同形成的比特位图(也就是数值)时,就有“大小头”( big-endian little-endian )的考量。比如:

char a:2;

char b:3;

char c:3;

如果除了 a 的初始值为 1 外,其他都是 0 ,那么在小头( little-endian )机器上,我们需要向这个字节写入 1 ,而在大头( big-endian )机器上,则是 128 。因此还要根据宏 BYTES_BIG_ENDIAN 的定义分别处理。对于 x86/Linux ,这个宏定义为 0 ,是小头机器。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值