📄 stor-layout.c
字号:
abort (); /* Usually the size and mode come from the data type without change. */ DECL_MODE (decl) = TYPE_MODE (type); DECL_SIZE (decl) = TYPE_SIZE (type); DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type); TREE_UNSIGNED (decl) = TREE_UNSIGNED (type); if (code == FIELD_DECL && TREE_PACKED (decl)) { /* This is a bit-field. We don't know how to handle them except for integers and enums, and front end should never generate them otherwise. */ if (! (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE)) abort (); if (spec_size == 0) abort (); /* Mode is "integer bit field". */ DECL_MODE (decl) = BImode; /* Size is specified number of bits. */ DECL_SIZE (decl) = size_one_node; DECL_SIZE_UNIT (decl) = spec_size; } /* Force alignment required for the data type. But if the decl itself wants greater alignment, don't override that. */ else if (TYPE_ALIGN (type) > DECL_ALIGN (decl)) DECL_ALIGN (decl) = TYPE_ALIGN (type); if (DECL_SIZE (decl)) bitsize = TREE_INT_CST_LOW (DECL_SIZE (decl)) * DECL_SIZE_UNIT (decl); /* See if we can use a scalar mode such as QImode or SImode in place of BLKmode or a packed byte mode. */ /* Conditions are: a fixed size that is correct for another mode and occupying a complete byte or bytes on proper boundary. */ if ((DECL_MODE (decl) == BLKmode || DECL_MODE (decl) == BImode) /* Don't do this if DECL's type requires it to be BLKmode. */ && TYPE_MODE (type) != BLKmode && TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { register enum machine_mode xmode = agg_mode (bitsize); if (xmode != BLKmode && known_align % GET_MODE_ALIGNMENT (xmode) == 0) { DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode), DECL_ALIGN (decl)); DECL_MODE (decl) = xmode; DECL_SIZE (decl) = build_int (GET_MODE_SIZE (xmode)); DECL_SIZE_UNIT (decl) = BITS_PER_UNIT; bitsize = GET_MODE_BITSIZE (xmode); } } /* Don't let more than one word of an aggregate occupy one register, since then the SUBREG used to access the high part would malfunction. Check that the expected # of registers is big enough that they seem to hold this variable with just a word per register. */ if (DECL_SIZE (decl) != 0 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == ARRAY_TYPE)) { /* This test is not exactly right, since we really want the minimum number of regs in any class that can hold this mode. But it does distinguish the machines we need to distinguish, for now. */ if (CLASS_MAX_NREGS (ALL_REGS, TYPE_MODE (type)) * BITS_PER_WORD < bitsize) TREE_ADDRESSABLE (decl) = 1; } /* Evaluate nonconstant size only once, either now or as soon as safe. */ if (DECL_SIZE (decl) != 0 && ! TREE_LITERAL (DECL_SIZE (decl))) DECL_SIZE (decl) = variable_size (DECL_SIZE (decl));}/* Lay out a RECORD_TYPE type (a C struct). This means laying out the fields, determining their offsets, and computing the overall size and required alignment of the record. Note that if you set the TYPE_ALIGN before calling this then the struct is aligned to at least that boundary. If the type has basetypes, you must call layout_basetypes before calling this function. */static voidlayout_record (rec) tree rec;{ register tree field;#ifdef STRUCTURE_SIZE_BOUNDARY int record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));#else int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));#endif /* These must be laid out *after* the record is. */ tree pending_statics = NULL_TREE; /* Record size so far is CONST_SIZE + VAR_SIZE * SIZE_UNIT bits, where CONST_SIZE is an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using VAR_SIZE. */ register int const_size = 0; register tree var_size = 0; register int size_unit = BITS_PER_UNIT;#if 0 /* If there are basetypes, the caller should already have laid them out. Leave space at the beginning for them. */ if (TYPE_SIZE (rec) != 0) { if (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST) const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec)); else var_size = TYPE_SIZE (rec); size_unit = TYPE_SIZE_UNIT (rec); }#endif /* 0 */ for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field)) { register int desired_align; /* If FIELD is a VAR_DECL, then treat it like a separate variable, not really like a structure field. If it is a FUNCTION_DECL, it's a method. In both cases, all we do is lay out the decl, and we do it *after* the record is laid out. */ if (TREE_CODE (field) == VAR_DECL) { pending_statics = tree_cons (NULL, field, pending_statics); continue; } /* Enumerators and enum types which are local to this class need not be laid out. */ if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL) continue; /* Lay out the field so we know what alignment it needs. For KNOWN_ALIGN, pass the number of bits from start of record or some divisor of it. */ layout_decl (field, var_size ? size_unit : const_size); desired_align = DECL_ALIGN (field); /* Record must have at least as much alignment as any field. Otherwise, the alignment of the field within the record is meaningless. */ record_align = MAX (record_align, desired_align);#ifdef PCC_BITFIELD_TYPE_MATTERS /* In PCC on Vax, Sony, etc., a bit field of declare type `int' forces the entire structure to have `int' alignment. */ if (PCC_BITFIELD_TYPE_MATTERS && DECL_NAME (field) != 0) record_align = MAX (record_align, TYPE_ALIGN (TREE_TYPE (field)));#endif /* Does this field automatically have alignment it needs by virtue of the fields that precede it and the record's own alignment? */ if (const_size % desired_align != 0 || (size_unit % desired_align != 0 && var_size)) { /* No, we need to skip space before this field. Bump the cumulative size to multiple of field alignment. */ if (var_size == 0 || size_unit % desired_align == 0) const_size = CEIL (const_size, desired_align) * desired_align; else { var_size = genop (PLUS_EXPR, var_size, build_int (CEIL (const_size, size_unit))); const_size = 0; var_size = convert_units (var_size, size_unit, desired_align); size_unit = desired_align; } }#ifdef PCC_BITFIELD_TYPE_MATTERS if (PCC_BITFIELD_TYPE_MATTERS && TREE_CODE (field) == FIELD_DECL && TREE_TYPE (field) != error_mark_node) { int type_align = TYPE_ALIGN (TREE_TYPE (field)); int type_size = (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (field))) * TYPE_SIZE_UNIT (TREE_TYPE (field))); register tree dsize = DECL_SIZE (field); int field_size = TREE_INT_CST_LOW (dsize) * DECL_SIZE_UNIT (field); /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. If the type's alignment is less than its size, then the bitfield may span more than one alignment unit, but only up to the number that the type itself occupies. Thus, a bitfield declared int, if int is 4 bytes but aligned to the halfword, must fit within a 4 byte group that is halfword aligned. */ if (const_size / type_align + (type_size / type_align - 1) < (const_size + field_size - 1) / type_align) const_size = CEIL (const_size, type_align) * type_align; }#endif /* Size so far becomes the offset of this field. */ DECL_OFFSET (field) = const_size; DECL_VOFFSET (field) = var_size; DECL_VOFFSET_UNIT (field) = size_unit; /* If this field is an anonymous union, give each union-member the same offset as the union has. */ if (DECL_NAME (field) == 0 && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree uelt = TYPE_FIELDS (TREE_TYPE (field)); for (; uelt; uelt = TREE_CHAIN (uelt)) { DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_OFFSET (uelt) = DECL_OFFSET (field); DECL_VOFFSET (uelt) = DECL_VOFFSET (field); DECL_VOFFSET_UNIT (uelt) = DECL_VOFFSET_UNIT (field); } } /* Now add size of this field to the size of the record. */ { register tree dsize = DECL_SIZE (field); if (TREE_LITERAL (dsize)) const_size += TREE_INT_CST_LOW (dsize) * DECL_SIZE_UNIT (field); else if (var_size == 0) { var_size = dsize; size_unit = DECL_SIZE_UNIT (field); } else { register int tunits = MIN (size_unit, DECL_SIZE_UNIT (field)); var_size = genop (PLUS_EXPR, convert_units (var_size, size_unit, tunits), convert_units (dsize, DECL_SIZE_UNIT (field), tunits)); size_unit = tunits; } } } /* Work out the total size and alignment of the record as one expression and store in the record type. Round it up to a multiple of the record's alignment. */ if (var_size == 0) TYPE_SIZE (rec) = build_int (CEIL (CEIL (const_size, record_align) * record_align, size_unit)); else { if (const_size) var_size = genop (PLUS_EXPR, var_size, build_int (CEIL (const_size, size_unit))); TYPE_SIZE (rec) = convert_units (var_size, size_unit, record_align); size_unit = record_align; } TYPE_SIZE (rec) = convert_units (TYPE_SIZE (rec), size_unit, BITS_PER_UNIT); TYPE_SIZE_UNIT (rec) = BITS_PER_UNIT; TYPE_ALIGN (rec) = MIN (BIGGEST_ALIGNMENT, record_align); /* Lay out any static members. This is done now because their type may use the record's type. */ for (field = pending_statics; field; field = TREE_CHAIN (field)) layout_decl (TREE_VALUE (field), 0);}/* Lay out a UNION_TYPE type. Lay out all the fields, set their offsets to zero, and compute the size and alignment of the union (maximum of any field). Note that if you set the TYPE_ALIGN before calling this then the union align is aligned to at least that boundary. */static voidlayout_union (rec) tree rec;{ register tree field;#ifdef STRUCTURE_SIZE_BOUNDARY int union_align = STRUCTURE_SIZE_BOUNDARY;#else int union_align = BITS_PER_UNIT;#endif /* The size of the union, based on the fields scanned so far, is max (CONST_SIZE, VAR_SIZE). VAR_SIZE may be null; then CONST_SIZE by itself is the size. */ register int const_size = 0; register tree var_size = 0; for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field)) {#if 0 /* Should be in a language-specific file, since message is lang spec. */ if (TREE_STATIC (field)) { error_with_decl (field, "field `%s' declared static in union"); TREE_STATIC (field) = 0; }#endif /* Ignore enumerators and enum types local to the union. */ if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL) continue; layout_decl (field, 0); DECL_OFFSET (field) = 0; DECL_VOFFSET (field) = 0; DECL_VOFFSET_UNIT (field) = BITS_PER_UNIT; /* Union must be at least as aligned as any field requires. */ union_align = MAX (union_align, DECL_ALIGN (field));#ifdef PCC_BITFIELD_TYPE_MATTERS /* On the m88000, a bit field of declare type `int' forces the entire union to have `int' alignment. */ if (PCC_BITFIELD_TYPE_MATTERS) union_align = MAX (union_align, TYPE_ALIGN (TREE_TYPE (field)));#endif /* Set union_size to max (decl_size, union_size). There are more and less general ways to do this. Use only CONST_SIZE unless forced to use VAR_SIZE. */ if (TREE_LITERAL (DECL_SIZE (field))) const_size = MAX (const_size, TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field)); else if (var_size == 0) var_size = convert_units (DECL_SIZE (field), DECL_SIZE_UNIT (field), BITS_PER_UNIT); else var_size = genop (MAX_EXPR, convert_units (DECL_SIZE (field), DECL_SIZE_UNIT (field),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -