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

来源:互联网 发布:网络教育英语统考试题 编辑:程序博客网 时间:2024/06/04 18:58

5.13.5.2.2.1.1.3.3.           浮点数

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

 

output_constant (continue)

 

3791     caseREAL_TYPE:

3792       if (TREE_CODE (exp) != REAL_CST)

3793         error ("initializer for floatingvalue 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_TYPEd, 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 intoan array of *host* longs, 32 bits per element

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

1928     number of arrayelements 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 mightappear at either end of the value; real_to_target

1935     will include thepadding 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 thefirst 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 wordsneed 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_singleencode_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     caseARRAY_TYPE:

3805     caseVECTOR_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 ((unsignedHOST_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         enummachine_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_POINTERTREE_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 isvery 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很类似。在445456行,输出的是字符“”并换行。可以想见,这个宏将输出形如:

“………”

“………”

的字符串。

 

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              (constunsigned char *) (STR);                                /

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

437        registerunsigned bytes_in_chunk = 0;                          /

438                                                                 /

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

440        {                                                  /

441          register constunsigned 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            registerint escape;                                 /

466            registerunsigned 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              case0:                                              /

474                putc (ch, (FILE));                                 /

475                bytes_in_chunk++;                                /

476                break;                                    /

477              case1:                                              /

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_constant3756行处理,参见0的内容一节),则来到下面的代码中。

 

output_constant (continue)

 

3838     caseRECORD_TYPE:

3839     caseUNION_TYPE:

3840       if (TREE_CODE (exp) == CONSTRUCTOR)

3841         output_constructor(exp, size, align);

3842       else

3843         abort ();

3844       return;

3845

3846     caseSET_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 constructortype");

3860       return;

3861

3862     caseERROR_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 bytesoutput or skipped so far.

3926     In other words, current position within theconstructor.  */

3927   HOST_WIDE_INT total_bytes = 0;

3928   /* Nonzero meansBYTE 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 goesthrough the elements of the constant,

3943     FIELD goesthrough the structure fields, if the constant is a structure.

3944     if the constantis a union, then we override this,

3945     by getting thefield from the TREE_LIST element.

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

3947

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

3949     (even if theinitializer 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 ina 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 themarker that makes a cast not be an lvalue. */

3979     if (val != 0)

3980       STRIP_NOPS(val);

 

注意在上面对于数组,变量fieldNULL,它使用变量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,表示在索引07的范围内使用初始值0。在上面的代码中可用看到,其第一个操作数是下限,而第二个操作数则是上限。在C++中,RANGE_EXPR的初始值只可能是0

满足下面4003行条件的节点是:数组(fieldNULL)、非位域的类成员。变量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 thiselement.  */

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 isguaranteed

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 initializerdetermines the size.  */

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

4045           but we cannot dothis until the deprecated support for

4046           initializingzero-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 anon-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'tbe right. If the decl size overflows

4060             a host integer we will silently emit nodata.  */

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的情况,则表明postotal_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 formember `%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 beprocessed.

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 whennecessary.  */

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 thesame byte).  */

4141         this_time = MIN (end_offset -next_offset,

4142                        BITS_PER_UNIT - next_bit);

4143         if (BYTES_BIG_ENDIAN)

4144         {

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

4146            first (of thebits that are significant)

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

4148           shift = end_offset - next_offset - this_time;

4149

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

4151             the word boundary in the INTEGER_CST. We can

4152             only select bitsfrom the LOW or HIGH part

4153             not fromboth.  */

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 bitsfrom 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-endianmachines,

4181             take first theleast significant bits of the value

4182             and pack themstarting at the least significant

4183             bits of thebytes.  */

4184           shift = next_offset - int_bit_position(field);

4185

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

4187             the wordboundary in the INTEGER_CST. We can

4188             only select bitsfrom 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 bitsfrom 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-endianlittle-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,是小头机器。

 

原创粉丝点击