📄 stor-layout.c
字号:
register tree dsize = DECL_SIZE (field); int field_size = TREE_INT_CST_LOW (dsize); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. */ /* ??? There is some uncertainty here as to what should be done if type_align is less than the width of the type. That can happen because the width exceeds BIGGEST_ALIGNMENT or because it exceeds maximum_field_alignment. */ if (const_size / type_align != (const_size + field_size - 1) / type_align) const_size = CEIL (const_size, type_align) * type_align; }#endif/* No existing machine description uses this parameter. So I have made it in this aspect identical to PCC_BITFIELD_TYPE_MATTERS. */#ifdef BITFIELD_NBYTES_LIMITED if (BITFIELD_NBYTES_LIMITED && TREE_CODE (field) == FIELD_DECL && TREE_TYPE (field) != error_mark_node && DECL_BIT_FIELD_TYPE (field) && !DECL_PACKED (field) && !integer_zerop (DECL_SIZE (field))) { int type_align = TYPE_ALIGN (TREE_TYPE (field)); register tree dsize = DECL_SIZE (field); int field_size = TREE_INT_CST_LOW (dsize); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. */ if (const_size / type_align != (const_size + field_size - 1) / type_align) const_size = CEIL (const_size, type_align) * type_align; }#endif /* Size so far becomes the position of this field. */ if (var_size && const_size) DECL_FIELD_BITPOS (field) = size_binop (PLUS_EXPR, var_size, size_int (const_size)); else if (var_size) DECL_FIELD_BITPOS (field) = var_size; else DECL_FIELD_BITPOS (field) = size_int (const_size); /* If this field is an anonymous union, give each union-member the same position 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_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); } } /* Now add size of this field to the size of the record. */ { register tree dsize = DECL_SIZE (field); /* This can happen when we have an invalid nested struct definition, such as struct j { struct j { int i; } }. The error message is printed in finish_struct. */ if (dsize == 0) /* Do nothing. */; else if (TREE_CODE (dsize) == INTEGER_CST) const_size += TREE_INT_CST_LOW (dsize); else { if (var_size == 0) var_size = dsize; else var_size = size_binop (PLUS_EXPR, var_size, dsize); } } } /* 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) = size_int (const_size); } else { if (const_size) var_size = size_binop (PLUS_EXPR, var_size, size_int (const_size)); TYPE_SIZE (rec) = var_size; } /* Determine the desired alignment. */#ifdef ROUND_TYPE_ALIGN TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), record_align);#else TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), record_align);#endif#ifdef ROUND_TYPE_SIZE TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));#else /* Round the size up to be a multiple of the required alignment */ TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));#endif return pending_statics;}/* Lay out a UNION_TYPE type. Lay out all the fields, set their positions 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 unsigned union_align = STRUCTURE_SIZE_BOUNDARY;#else unsigned 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)) { /* Enums which are local to this class need not be laid out. */ if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL) continue; layout_decl (field, 0); DECL_FIELD_BITPOS (field) = size_int (0); /* 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 && DECL_BIT_FIELD_TYPE (field)) 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_CODE (DECL_SIZE (field)) == INTEGER_CST) const_size = MAX (const_size, TREE_INT_CST_LOW (DECL_SIZE (field))); else if (var_size == 0) var_size = DECL_SIZE (field); else var_size = size_binop (MAX_EXPR, var_size, DECL_SIZE (field)); } /* Determine the ultimate size of the union (in bytes). */ if (NULL == var_size) TYPE_SIZE (rec) = size_int (CEIL (const_size, BITS_PER_UNIT) * BITS_PER_UNIT); else if (const_size == 0) TYPE_SIZE (rec) = var_size; else TYPE_SIZE (rec) = size_binop (MAX_EXPR, var_size, round_up (size_int (const_size), BITS_PER_UNIT)); /* Determine the desired alignment. */#ifdef ROUND_TYPE_ALIGN TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), union_align);#else TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), union_align);#endif#ifdef ROUND_TYPE_SIZE TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));#else /* Round the size up to be a multiple of the required alignment */ TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));#endif}/* Calculate the mode, size, and alignment for TYPE. For an array type, calculate the element separation as well. Record TYPE on the chain of permanent or temporary types so that dbxout will find out about it. TYPE_SIZE of a type is nonzero if the type has been laid out already. layout_type does nothing on such a type. If the type is incomplete, its TYPE_SIZE remains zero. */voidlayout_type (type) tree type;{ int old; tree pending_statics; if (type == 0) abort (); /* Do nothing if type has been laid out before. */ if (TYPE_SIZE (type)) return; /* Make sure all nodes we allocate are not momentary; they must last past the current statement. */ old = suspend_momentary (); /* If we are processing a permanent type, make nodes permanent. If processing a temporary type, make it saveable, since the type node itself is. This is important if the function is inline, since its decls will get copied later. */ push_obstacks_nochange (); if (allocation_temporary_p ()) { if (TREE_PERMANENT (type)) end_temporary_allocation (); else saveable_allocation (); } switch (TREE_CODE (type)) { case LANG_TYPE: /* This kind of type is the responsibility of the languge-specific code. */ abort (); case INTEGER_TYPE: case ENUMERAL_TYPE: if (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) >= 0) TREE_UNSIGNED (type) = 1; /* We pass 0 for the last arg of mode_for_size because otherwise on the Apollo using long long causes a crash. It seems better to use integer modes than to try to support integer types with BLKmode. */ TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_INT, 0); TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); break; case REAL_TYPE: TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0); TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); break; case COMPLEX_TYPE: TREE_UNSIGNED (type) = TREE_UNSIGNED (TREE_TYPE (type)); TYPE_MODE (type) = mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)), (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE ? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT), 0); TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); break; case VOID_TYPE: TYPE_SIZE (type) = size_zero_node; TYPE_ALIGN (type) = 1; TYPE_MODE (type) = VOIDmode; break; case OFFSET_TYPE: TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (Pmode)); TYPE_MODE (type) = Pmode; break; case FUNCTION_TYPE: case METHOD_TYPE: TYPE_MODE (type) = mode_for_size (2 * GET_MODE_BITSIZE (Pmode), MODE_INT, 0); TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); break; case POINTER_TYPE: case REFERENCE_TYPE: TYPE_MODE (type) = Pmode; TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TREE_UNSIGNED (type) = 1; TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type)); break; case ARRAY_TYPE: { register tree index = TYPE_DOMAIN (type); register tree element = TREE_TYPE (type); build_pointer_type (element); /* We need to know both bounds in order to compute the size. */ if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index) && TYPE_SIZE (element)) { tree length = size_binop (PLUS_EXPR, size_one_node, size_binop (MINUS_EXPR, TYPE_MAX_VALUE (index), TYPE_MIN_VALUE (index))); TYPE_SIZE (type) = size_binop (MULT_EXPR, length, TYPE_SIZE (element)); } /* Now round the alignment and size, using machine-dependent criteria if any. */#ifdef ROUND_TYPE_ALIGN TYPE_ALIGN (type) = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (element), BITS_PER_UNIT);#else TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);#endif#ifdef ROUND_TYPE_SIZE if (TYPE_SIZE (type) != 0) TYPE_SIZE (type) = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));#endif TYPE_MODE (type) = BLKmode; if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST /* BLKmode elements force BLKmode aggregate; else extract/store fields may lose. */ && (TYPE_MODE (TREE_TYPE (type)) != BLKmode || TYPE_NO_FORCE_BLK (TREE_TYPE (type)))) { TYPE_MODE (type) = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)), MODE_INT, 1); if (STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT && TYPE_ALIGN (type) < TREE_INT_CST_LOW (TYPE_SIZE (type)) && TYPE_MODE (type) != BLKmode) { TYPE_NO_FORCE_BLK (type) = 1; TYPE_MODE (type) = BLKmode; } } break; } case RECORD_TYPE: pending_statics = layout_record (type); TYPE_MODE (type) = BLKmode; if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) { tree field; /* A record which has any BLKmode members must itself be BLKmode; it can't go in a register. Unless the member is BLKmode only because it isn't aligned. */ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { int bitpos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -