📄 stor-layout.c
字号:
/* 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; if (TREE_CODE (field) != FIELD_DECL) continue; if (TYPE_MODE (TREE_TYPE (field)) == BLKmode && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))) goto record_lose; if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST) goto record_lose; bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)); /* Must be BLKmode if any field crosses a word boundary, since extract_bit_field can't handle that in registers. */ if (bitpos / BITS_PER_WORD != ((TREE_INT_CST_LOW (DECL_SIZE (field)) + bitpos - 1) / BITS_PER_WORD) /* But there is no problem if the field is entire words. */ && TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD == 0) goto record_lose; } TYPE_MODE (type) = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)), MODE_INT, 1); /* If structure's known alignment is less than what the scalar mode would need, and it matters, then stick with BLKmode. */ if (STRICT_ALIGNMENT && ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT || (TYPE_ALIGN (type) >= TREE_INT_CST_LOW (TYPE_SIZE (type))))) { if (TYPE_MODE (type) != BLKmode) /* If this is the only reason this type is BLKmode, then don't force containing types to be BLKmode. */ TYPE_NO_FORCE_BLK (type) = 1; TYPE_MODE (type) = BLKmode; } record_lose: ; } /* Lay out any static members. This is done now because their type may use the record's type. */ while (pending_statics) { layout_decl (TREE_VALUE (pending_statics), 0); pending_statics = TREE_CHAIN (pending_statics); } break; case UNION_TYPE: case QUAL_UNION_TYPE: layout_union (type); TYPE_MODE (type) = BLKmode; if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST /* If structure's known alignment is less than what the scalar mode would need, and it matters, then stick with BLKmode. */ && (! STRICT_ALIGNMENT || TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT || TYPE_ALIGN (type) >= TREE_INT_CST_LOW (TYPE_SIZE (type)))) { tree field; /* A union 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)) { if (TREE_CODE (field) != FIELD_DECL) continue; if (TYPE_MODE (TREE_TYPE (field)) == BLKmode && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))) goto union_lose; } TYPE_MODE (type) = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)), MODE_INT, 1); union_lose: ; } break; /* Pascal and Chill types */ case BOOLEAN_TYPE: /* store one byte/boolean for now. */ TYPE_MODE (type) = QImode; TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TYPE_PRECISION (type) = 1; TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0) TREE_UNSIGNED (type) = 1; break; case CHAR_TYPE: TYPE_MODE (type) = QImode; TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type)); TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); break; case SET_TYPE: if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST) abort(); else {#ifndef SET_WORD_SIZE#define SET_WORD_SIZE BITS_PER_WORD#endif int alignment = set_alignment ? set_alignment : SET_WORD_SIZE; int size_in_bits = TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1; int rounded_size = ((size_in_bits + alignment - 1) / alignment) * alignment; if (rounded_size > alignment) TYPE_MODE (type) = BLKmode; else TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1); TYPE_SIZE (type) = size_int (rounded_size); TYPE_ALIGN (type) = alignment; TYPE_PRECISION (type) = size_in_bits; } break; case FILE_TYPE: /* The size may vary in different languages, so the language front end should fill in the size. */ TYPE_ALIGN (type) = BIGGEST_ALIGNMENT; TYPE_MODE (type) = BLKmode; break; default: abort (); } /* end switch */ /* Normally, use the alignment corresponding to the mode chosen. However, where strict alignment is not required, avoid over-aligning structures, since most compilers do not do this alignment. */ if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode && (STRICT_ALIGNMENT || (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE && TREE_CODE (type) != QUAL_UNION_TYPE && TREE_CODE (type) != ARRAY_TYPE))) TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); /* Evaluate nonconstant size only once, either now or as soon as safe. */ if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) TYPE_SIZE (type) = variable_size (TYPE_SIZE (type)); /* Also layout any other variants of the type. */ if (TYPE_NEXT_VARIANT (type) || type != TYPE_MAIN_VARIANT (type)) { tree variant; /* Record layout info of this variant. */ tree size = TYPE_SIZE (type); int align = TYPE_ALIGN (type); enum machine_mode mode = TYPE_MODE (type); /* Copy it into all variants. */ for (variant = TYPE_MAIN_VARIANT (type); variant; variant = TYPE_NEXT_VARIANT (variant)) { TYPE_SIZE (variant) = size; TYPE_ALIGN (variant) = align; TYPE_MODE (variant) = mode; } } pop_obstacks (); resume_momentary (old);}/* Create and return a type for signed integers of PRECISION bits. */treemake_signed_type (precision) int precision;{ register tree type = make_node (INTEGER_TYPE); TYPE_PRECISION (type) = precision; /* Create the extreme values based on the number of bits. */ TYPE_MIN_VALUE (type) = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)), (((HOST_WIDE_INT) (-1) << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ? precision - HOST_BITS_PER_WIDE_INT - 1 : 0)))); TYPE_MAX_VALUE (type) = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1), (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ? (((HOST_WIDE_INT) 1 << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1 : 0)); /* Give this type's extreme values this type as their type. */ TREE_TYPE (TYPE_MIN_VALUE (type)) = type; TREE_TYPE (TYPE_MAX_VALUE (type)) = type; /* The first type made with this or `make_unsigned_type' is the type for size values. */ if (sizetype == 0) { sizetype = type; } /* Lay out the type: set its alignment, size, etc. */ layout_type (type); return type;}/* Create and return a type for unsigned integers of PRECISION bits. */treemake_unsigned_type (precision) int precision;{ register tree type = make_node (INTEGER_TYPE); TYPE_PRECISION (type) = precision; /* The first type made with this or `make_signed_type' is the type for size values. */ if (sizetype == 0) { sizetype = type; } fixup_unsigned_type (type); return type;}/* Set the extreme values of TYPE based on its precision in bits, then lay it out. Used when make_signed_type won't do because the tree code is not INTEGER_TYPE. E.g. for Pascal, when the -fsigned-char option is given. */voidfixup_signed_type (type) tree type;{ register int precision = TYPE_PRECISION (type); TYPE_MIN_VALUE (type) = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)), (((HOST_WIDE_INT) (-1) << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ? precision - HOST_BITS_PER_WIDE_INT - 1 : 0)))); TYPE_MAX_VALUE (type) = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1), (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ? (((HOST_WIDE_INT) 1 << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1 : 0)); TREE_TYPE (TYPE_MIN_VALUE (type)) = type; TREE_TYPE (TYPE_MAX_VALUE (type)) = type; /* Lay out the type: set its alignment, size, etc. */ layout_type (type);}/* Set the extreme values of TYPE based on its precision in bits, then lay it out. This is used both in `make_unsigned_type' and for enumeral types. */voidfixup_unsigned_type (type) tree type;{ register int precision = TYPE_PRECISION (type); TYPE_MIN_VALUE (type) = build_int_2 (0, 0); TYPE_MAX_VALUE (type) = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0 ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1, precision - HOST_BITS_PER_WIDE_INT > 0 ? ((unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_WIDE_INT - (precision - HOST_BITS_PER_WIDE_INT))) : 0); TREE_TYPE (TYPE_MIN_VALUE (type)) = type; TREE_TYPE (TYPE_MAX_VALUE (type)) = type; /* Lay out the type: set its alignment, size, etc. */ layout_type (type);}/* Find the best machine mode to use when referencing a bit field of length BITSIZE bits starting at BITPOS. The underlying object is known to be aligned to a boundary of ALIGN bits. If LARGEST_MODE is not VOIDmode, it means that we should not use a mode larger than LARGEST_MODE (usually SImode). If no mode meets all these conditions, we return VOIDmode. Otherwise, if VOLATILEP is true or SLOW_BYTE_ACCESS is false, we return the smallest mode meeting these conditions. Otherwise (VOLATILEP is false and SLOW_BYTE_ACCESS is true), we return the largest mode (but a mode no wider than UNITS_PER_WORD) that meets all the conditions. */enum machine_modeget_best_mode (bitsize, bitpos, align, largest_mode, volatilep) int bitsize, bitpos; int align; enum machine_mode largest_mode; int volatilep;{ enum machine_mode mode; int unit; /* Find the narrowest integer mode that contains the bit field. */ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { unit = GET_MODE_BITSIZE (mode); if (bitpos / unit == (bitpos + bitsize - 1) / unit) break; } if (mode == MAX_MACHINE_MODE /* It is tempting to omit the following line if STRICT_ALIGNMENT is true. But that is incorrect, since if the bitfield uses part of 3 bytes and we use a 4-byte mode, we could get a spurious segv if the extra 4th byte is past the end of memory. (Though at least one Unix compiler ignores this problem: that on the Sequent 386 machine. */ || MIN (unit, BIGGEST_ALIGNMENT) > align || (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode))) return VOIDmode; if (SLOW_BYTE_ACCESS && ! volatilep) { enum machine_mode wide_mode = VOIDmode, tmode; for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) { unit = GET_MODE_BITSIZE (tmode); if (bitpos / unit == (bitpos + bitsize - 1) / unit && unit <= BITS_PER_WORD && unit <= MIN (align, BIGGEST_ALIGNMENT) && (largest_mode == VOIDmode || unit <= GET_MODE_BITSIZE (largest_mode))) wide_mode = tmode; } if (wide_mode != VOIDmode) return wide_mode; } return mode;}/* Save all variables describing the current status into the structure *P. This is used before starting a nested function. */voidsave_storage_status (p) struct function *p;{#if 0 /* Need not save, since always 0 and non0 (resp.) within a function. */ p->pending_sizes = pending_sizes; p->immediate_size_expand = immediate_size_expand;#endif /* 0 */}/* Restore all variables describing the current status from the structure *P. This is used after a nested function. */voidrestore_storage_status (p) struct function *p;{#if 0 pending_sizes = p->pending_sizes; immediate_size_expand = p->immediate_size_expand;#endif /* 0 */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -