⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stor-layout.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 3 页
字号:
/* C-compiler utilities for types and variables storage layout   Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include <stdio.h>#include "tree.h"#include "flags.h"#include "function.h"#define CEIL(x,y) (((x) + (y) - 1) / (y))/* Data type for the expressions representing sizes of data types.   It is the first integer type laid out.   In C, this is int.  */tree sizetype;/* An integer constant with value 0 whose type is sizetype.  */tree size_zero_node;/* An integer constant with value 1 whose type is sizetype.  */tree size_one_node;/* If nonzero, this is an upper limit on alignment of structure fields.   The value is measured in bits.  */int maximum_field_alignment;/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.   May be overridden by front-ends.  */int set_alignment = 0;#define GET_MODE_ALIGNMENT(MODE)   \  MIN (BIGGEST_ALIGNMENT, 	   \       MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)))static enum machine_mode smallest_mode_for_size  PROTO((unsigned int,							enum mode_class));static tree layout_record	PROTO((tree));static void layout_union	PROTO((tree));/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded.  */static tree pending_sizes;/* Nonzero means cannot safely call expand_expr now,   so put variable sizes onto `pending_sizes' instead.  */int immediate_size_expand;treeget_pending_sizes (){  tree chain = pending_sizes;  tree t;  /* Put each SAVE_EXPR into the current function.  */  for (t = chain; t; t = TREE_CHAIN (t))    SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = current_function_decl;  pending_sizes = 0;  return chain;}voidput_pending_sizes (chain)     tree chain;{  if (pending_sizes)    abort ();  pending_sizes = chain;}/* Given a size SIZE that may not be a constant, return a SAVE_EXPR   to serve as the actual size-expression for a type or decl.  */treevariable_size (size)     tree size;{  /* If the language-processor is to take responsibility for variable-sized     items (e.g., languages which have elaboration procedures like Ada),     just return SIZE unchanged.  Likewise for self-referential sizes.  */  if (TREE_CONSTANT (size)      || global_bindings_p () < 0 || contains_placeholder_p (size))    return size;  size = save_expr (size);  if (global_bindings_p ())    {      if (TREE_CONSTANT (size))	error ("type size can't be explicitly evaluated");      else	error ("variable-size type declared outside of any function");      return size_int (1);    }  if (immediate_size_expand)    /* NULL_RTX is not defined; neither is the rtx type.        Also, we would like to pass const0_rtx here, but don't have it.  */    expand_expr (size, expand_expr (integer_zero_node, NULL_PTR, VOIDmode, 0),		 VOIDmode, 0);  else    pending_sizes = tree_cons (NULL_TREE, size, pending_sizes);  return size;}#ifndef MAX_FIXED_MODE_SIZE#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)#endif/* Return the machine mode to use for a nonscalar of SIZE bits.   The mode must be in class CLASS, and have exactly that many bits.   If LIMIT is nonzero, modes of wider than MAX_FIXED_MODE_SIZE will not   be used.  */enum machine_modemode_for_size (size, class, limit)     unsigned int size;     enum mode_class class;     int limit;{  register enum machine_mode mode;  if (limit && size > MAX_FIXED_MODE_SIZE)    return BLKmode;  /* Get the first mode which has this size, in the specified class.  */  for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;       mode = GET_MODE_WIDER_MODE (mode))    if (GET_MODE_BITSIZE (mode) == size)      return mode;  return BLKmode;}/* Similar, but never return BLKmode; return the narrowest mode that   contains at least the requested number of bits.  */static enum machine_modesmallest_mode_for_size (size, class)     unsigned int size;     enum mode_class class;{  register enum machine_mode mode;  /* Get the first mode which has at least this size, in the     specified class.  */  for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;       mode = GET_MODE_WIDER_MODE (mode))    if (GET_MODE_BITSIZE (mode) >= size)      return mode;  abort ();}/* Return the value of VALUE, rounded up to a multiple of DIVISOR.  */treeround_up (value, divisor)     tree value;     int divisor;{  return size_binop (MULT_EXPR,		     size_binop (CEIL_DIV_EXPR, value, size_int (divisor)),		     size_int (divisor));}/* Set the size, mode and alignment of a ..._DECL node.   TYPE_DECL does need this for C++.   Note that LABEL_DECL and CONST_DECL nodes do not need this,   and FUNCTION_DECL nodes have them set up in a special (and simple) way.   Don't call layout_decl for them.   KNOWN_ALIGN is the amount of alignment we can assume this   decl has with no special effort.  It is relevant only for FIELD_DECLs   and depends on the previous fields.   All that matters about KNOWN_ALIGN is which powers of 2 divide it.   If KNOWN_ALIGN is 0, it means, "as much alignment as you like":   the record will be aligned to suit.  */voidlayout_decl (decl, known_align)     tree decl;     unsigned known_align;{  register tree type = TREE_TYPE (decl);  register enum tree_code code = TREE_CODE (decl);  int spec_size = DECL_FIELD_SIZE (decl);  if (code == CONST_DECL)    return;  if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL      && code != FIELD_DECL && code != TYPE_DECL)    abort ();  if (type == error_mark_node)    {      type = void_type_node;      spec_size = 0;    }  /* Usually the size and mode come from the data type without change.  */  DECL_MODE (decl) = TYPE_MODE (type);  TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);  if (DECL_SIZE (decl) == 0)    DECL_SIZE (decl) = TYPE_SIZE (type);  if (code == FIELD_DECL && DECL_BIT_FIELD (decl))    {      if (spec_size == 0 && DECL_NAME (decl) != 0)	abort ();      /* Size is specified number of bits.  */      DECL_SIZE (decl) = size_int (spec_size);    }  /* Force alignment required for the data type.     But if the decl itself wants greater alignment, don't override that.     Likewise, if the decl is packed, don't override it.  */  else if (DECL_ALIGN (decl) == 0	   || (! DECL_PACKED (decl) &&  TYPE_ALIGN (type) > DECL_ALIGN (decl)))    DECL_ALIGN (decl) = TYPE_ALIGN (type);  /* See if we can use an ordinary integer mode for a bit-field.  */  /* Conditions are: a fixed size that is correct for another mode     and occupying a complete byte or bytes on proper boundary.  */  if (code == FIELD_DECL)    {      DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;      if (maximum_field_alignment != 0)	DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);      else if (flag_pack_struct)	DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);    }  if (DECL_BIT_FIELD (decl)      && TYPE_SIZE (type) != 0      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)    {      register enum machine_mode xmode	= mode_for_size (TREE_INT_CST_LOW (DECL_SIZE (decl)), MODE_INT, 1);      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) = size_int (GET_MODE_BITSIZE (xmode));	  /* This no longer needs to be accessed as a bit field.  */	  DECL_BIT_FIELD (decl) = 0;	}    }  /* Evaluate nonconstant size only once, either now or as soon as safe.  */  if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)    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 positions,   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.   The return value is a list of static members of the record.   They still need to be laid out.  */static treelayout_record (rec)     tree rec;{  register tree field;#ifdef STRUCTURE_SIZE_BOUNDARY  unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));#else  unsigned 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 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;  /* Once we start using VAR_SIZE, this is the maximum alignment     that we know VAR_SIZE has.  */  register int var_align = BITS_PER_UNIT;  for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))    {      register int known_align = var_size ? var_align : const_size;      register int desired_align;      /* If FIELD is static, 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_STATIC (field))	{	  pending_statics = tree_cons (NULL_TREE, field, pending_statics);	  continue;	}      /* Enumerators and enum types which are local to this class need not	 be laid out.  Likewise for initialized constant fields.  */      if (TREE_CODE (field) != FIELD_DECL)	continue;      /* Lay out the field so we know what alignment it needs.	 For a packed field, use the alignment as specified,	 disregarding what the type would want.  */      if (DECL_PACKED (field))	desired_align = DECL_ALIGN (field);      layout_decl (field, known_align);      if (! DECL_PACKED (field))	desired_align = DECL_ALIGN (field);      /* Some targets (i.e. VMS) limit struct field alignment	 to a lower boundary than alignment of variables.  */#ifdef BIGGEST_FIELD_ALIGNMENT      desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);#endif      /* Record must have at least as much alignment as any field.	 Otherwise, the alignment of the field within the record	 is meaningless.  */#ifndef PCC_BITFIELD_TYPE_MATTERS      record_align = MAX (record_align, desired_align);#else      if (PCC_BITFIELD_TYPE_MATTERS && TREE_TYPE (field) != error_mark_node	  && DECL_BIT_FIELD_TYPE (field)	  && ! integer_zerop (TYPE_SIZE (TREE_TYPE (field))))	{	  /* For these machines, a zero-length field does not	     affect the alignment of the structure as a whole.	     It does, however, affect the alignment of the next field	     within the structure.  */	  if (! integer_zerop (DECL_SIZE (field)))	    record_align = MAX (record_align, desired_align);	  else if (! DECL_PACKED (field))	    desired_align = TYPE_ALIGN (TREE_TYPE (field));	  /* A named bit field of declared type `int'	     forces the entire structure to have `int' alignment.  */	  if (DECL_NAME (field) != 0)	    {	      int type_align = TYPE_ALIGN (TREE_TYPE (field));	      if (maximum_field_alignment != 0)		type_align = MIN (type_align, maximum_field_alignment);	      else if (flag_pack_struct)		type_align = MIN (type_align, BITS_PER_UNIT);	      record_align = MAX (record_align, type_align);	    }	}      else	record_align = MAX (record_align, desired_align);#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	  || (var_align % desired_align != 0	      && var_size != 0))	{	  /* No, we need to skip space before this field.	     Bump the cumulative size to multiple of field alignment.  */	  if (var_size == 0	      || var_align % desired_align == 0)	    const_size	      = CEIL (const_size, desired_align) * desired_align;	  else	    {	      if (const_size > 0)		var_size = size_binop (PLUS_EXPR, var_size,				       size_int (const_size));	      const_size = 0;	      var_size = round_up (var_size, desired_align);	      var_align = MIN (var_align, desired_align);	    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -