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

📄 varasm.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	      != ((HOST_WIDE_INT) (-1) << (width - 1))))	i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;      else if (width == HOST_BITS_PER_WIDE_INT	       && ! (i1 == ~0 && i0 < 0))	i1 = 0;      else if (width > 2 * HOST_BITS_PER_WIDE_INT)	/* We cannot represent this value as a constant.  */	abort ();      /* If this would be an entire word for the target, but is not for	 the host, then sign-extend on the host so that the number will look	 the same way on the host that it would on the target.	 For example, when building a 64 bit alpha hosted 32 bit sparc	 targeted compiler, then we want the 32 bit unsigned value -1 to be	 represented as a 64 bit value -1, and not as 0x00000000ffffffff.	 The later confuses the sparc backend.  */      if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width	  && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))	i0 |= ((HOST_WIDE_INT) (-1) << width);      /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.	 ??? Strictly speaking, this is wrong if we create a CONST_INT	 for a large unsigned constant with the size of MODE being	 HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a	 wider mode.  In that case we will mis-interpret it as a negative	 number.	 Unfortunately, the only alternative is to make a CONST_DOUBLE	 for any constant in any mode if it is an unsigned constant larger	 than the maximum signed integer in an int on the host.  However,	 doing this will break everyone that always expects to see a CONST_INT	 for SImode and smaller.	 We have always been making CONST_INTs in this case, so nothing new	 is being broken.  */      if (width <= HOST_BITS_PER_WIDE_INT)	i1 = (i0 < 0) ? ~0 : 0;      /* If this integer fits in one word, return a CONST_INT.  */      if ((i1 == 0 && i0 >= 0)	  || (i1 == ~0 && i0 < 0))	return GEN_INT (i0);      /* We use VOIDmode for integers.  */      mode = VOIDmode;    }  /* Search the chain for an existing CONST_DOUBLE with the right value.     If one is found, return it.  */  for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))    if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1	&& GET_MODE (r) == mode)      return r;  /* No; make a new one and add it to the chain.     We may be called by an optimizer which may be discarding any memory     allocated during its processing (such as combine and loop).  However,     we will be leaving this constant on the chain, so we cannot tolerate     freed memory.  So switch to saveable_obstack for this allocation     and then switch back if we were in current_obstack.  */  push_obstacks_nochange ();  rtl_in_saveable_obstack ();  r = gen_rtx (CONST_DOUBLE, mode, 0, i0, i1);  pop_obstacks ();  /* Don't touch const_double_chain in nested function; see force_const_mem.     Also, don't touch it if not inside any function.  */  if (outer_function_chain == 0 && current_function_decl != 0)    {      CONST_DOUBLE_CHAIN (r) = const_double_chain;      const_double_chain = r;    }  /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain.     Actual use of mem-slot is only through force_const_mem.  */  CONST_DOUBLE_MEM (r) = const0_rtx;  return r;}/* Return a CONST_DOUBLE for a specified `double' value   and machine mode.  */rtximmed_real_const_1 (d, mode)     REAL_VALUE_TYPE d;     enum machine_mode mode;{  union real_extract u;  register rtx r;  int in_current_obstack;  /* Get the desired `double' value as a sequence of ints     since that is how they are stored in a CONST_DOUBLE.  */  u.d = d;  /* Detect special cases.  */  /* Avoid REAL_VALUES_EQUAL here in order to distinguish minus zero.  */  if (!bcmp ((char *) &dconst0, (char *) &d, sizeof d))    return CONST0_RTX (mode);  /* Check for NaN first, because some ports (specifically the i386) do not     emit correct ieee-fp code by default, and thus will generate a core     dump here if we pass a NaN to REAL_VALUES_EQUAL and if REAL_VALUES_EQUAL     does a floating point comparison.  */  else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))    return CONST1_RTX (mode);  if (sizeof u == 2 * sizeof (HOST_WIDE_INT))    return immed_double_const (u.i[0], u.i[1], mode);  /* The rest of this function handles the case where     a float value requires more than 2 ints of space.     It will be deleted as dead code on machines that don't need it.  */  /* Search the chain for an existing CONST_DOUBLE with the right value.     If one is found, return it.  */  for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))    if (! bcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)	&& GET_MODE (r) == mode)      return r;  /* No; make a new one and add it to the chain.     We may be called by an optimizer which may be discarding any memory     allocated during its processing (such as combine and loop).  However,     we will be leaving this constant on the chain, so we cannot tolerate     freed memory.  So switch to saveable_obstack for this allocation     and then switch back if we were in current_obstack.  */  push_obstacks_nochange ();  rtl_in_saveable_obstack ();  r = rtx_alloc (CONST_DOUBLE);  PUT_MODE (r, mode);  bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u);  pop_obstacks ();  /* Don't touch const_double_chain in nested function; see force_const_mem.     Also, don't touch it if not inside any function.  */  if (outer_function_chain == 0 && current_function_decl != 0)    {      CONST_DOUBLE_CHAIN (r) = const_double_chain;      const_double_chain = r;    }  /* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the     chain, but has not been allocated memory.  Actual use of CONST_DOUBLE_MEM     is only through force_const_mem.  */  CONST_DOUBLE_MEM (r) = const0_rtx;  return r;}/* Return a CONST_DOUBLE rtx for a value specified by EXP,   which must be a REAL_CST tree node.  */rtximmed_real_const (exp)     tree exp;{  return immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)));}/* At the end of a function, forget the memory-constants   previously made for CONST_DOUBLEs.  Mark them as not on real_constant_chain.   Also clear out real_constant_chain and clear out all the chain-pointers.  */voidclear_const_double_mem (){  register rtx r, next;  /* Don't touch CONST_DOUBLE_MEM for nested functions.     See force_const_mem for explanation.  */  if (outer_function_chain != 0)    return;  for (r = const_double_chain; r; r = next)    {      next = CONST_DOUBLE_CHAIN (r);      CONST_DOUBLE_CHAIN (r) = 0;      CONST_DOUBLE_MEM (r) = cc0_rtx;    }  const_double_chain = 0;}/* Given an expression EXP with a constant value,   reduce it to the sum of an assembler symbol and an integer.   Store them both in the structure *VALUE.   Abort if EXP does not reduce.  */struct addr_const{  rtx base;  HOST_WIDE_INT offset;};static voiddecode_addr_const (exp, value)     tree exp;     struct addr_const *value;{  register tree target = TREE_OPERAND (exp, 0);  register int offset = 0;  register rtx x;  while (1)    {      if (TREE_CODE (target) == COMPONENT_REF	  && (TREE_CODE (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1)))	      == INTEGER_CST))	{	  offset += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) / BITS_PER_UNIT;	  target = TREE_OPERAND (target, 0);	}      else if (TREE_CODE (target) == ARRAY_REF)	{	  if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST	      || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)	    abort ();	  offset += ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))		      * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))		     / BITS_PER_UNIT);	  target = TREE_OPERAND (target, 0);	}      else	break;    }  switch (TREE_CODE (target))    {    case VAR_DECL:    case FUNCTION_DECL:      x = DECL_RTL (target);      break;    case LABEL_DECL:      if (output_bytecode)	/* FIXME: this may not be correct, check it */	x = bc_gen_rtx (TREE_STRING_POINTER (target), 0, (struct bc_label *) 0);      else	x = gen_rtx (MEM, FUNCTION_MODE,		     gen_rtx (LABEL_REF, VOIDmode,			      label_rtx (TREE_OPERAND (exp, 0))));      break;    case REAL_CST:    case STRING_CST:    case COMPLEX_CST:    case CONSTRUCTOR:      x = TREE_CST_RTL (target);      break;    default:      abort ();    }  if (!output_bytecode)    {      if (GET_CODE (x) != MEM)	abort ();      x = XEXP (x, 0);    }  value->base = x;  value->offset = offset;}/* Uniquize all constants that appear in memory.   Each constant in memory thus far output is recorded   in `const_hash_table' with a `struct constant_descriptor'   that contains a polish representation of the value of   the constant.   We cannot store the trees in the hash table   because the trees may be temporary.  */struct constant_descriptor{  struct constant_descriptor *next;  char *label;  char contents[1];};#define HASHBITS 30#define MAX_HASH_TABLE 1009static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];/* Compute a hash code for a constant expression.  */static intconst_hash (exp)     tree exp;{  register char *p;  register int len, hi, i;  register enum tree_code code = TREE_CODE (exp);  if (code == INTEGER_CST)    {      p = (char *) &TREE_INT_CST_LOW (exp);      len = 2 * sizeof TREE_INT_CST_LOW (exp);    }  else if (code == REAL_CST)    {      p = (char *) &TREE_REAL_CST (exp);      len = sizeof TREE_REAL_CST (exp);    }  else if (code == STRING_CST)    p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp);  else if (code == COMPLEX_CST)    return const_hash (TREE_REALPART (exp)) * 5      + const_hash (TREE_IMAGPART (exp));  else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)    {      len = int_size_in_bytes (TREE_TYPE (exp));      p = (char*) alloca (len);      get_set_constructor_bytes (exp, (unsigned char *) p, len);    }  else if (code == CONSTRUCTOR)    {      register tree link;      /* For record type, include the type in the hashing.	 We do not do so for array types	 because (1) the sizes of the elements are sufficient	 and (2) distinct array types can have the same constructor.	 Instead, we include the array size because the constructor could	 be shorter.  */      if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)	hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1))	  % MAX_HASH_TABLE;      else	hi = ((5 + int_size_in_bytes (TREE_TYPE (exp)))	       & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;      for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))	if (TREE_VALUE (link))	  hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;      return hi;    }  else if (code == ADDR_EXPR)    {      struct addr_const value;      decode_addr_const (exp, &value);      if (GET_CODE (value.base) == SYMBOL_REF)	{	  /* Don't hash the address of the SYMBOL_REF;	     only use the offset and the symbol name.  */	  hi = value.offset;	  p = XSTR (value.base, 0);	  for (i = 0; p[i] != 0; i++)	    hi = ((hi * 613) + (unsigned)(p[i]));	}      else if (GET_CODE (value.base) == LABEL_REF)	hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;      hi &= (1 << HASHBITS) - 1;      hi %= MAX_HASH_TABLE;      return hi;    }  else if (code == PLUS_EXPR || code == MINUS_EXPR)    return const_hash (TREE_OPERAND (exp, 0)) * 9      +  const_hash (TREE_OPERAND (exp, 1));  else if (code == NOP_EXPR || code == CONVERT_EXPR)    return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;  /* Compute hashing function */  hi = len;  for (i = 0; i < len; i++)    hi = ((hi * 613) + (unsigned)(p[i]));  hi &= (1 << HASHBITS) - 1;  hi %= MAX_HASH_TABLE;  return hi;}/* Compare a constant expression EXP with a constant-descriptor DESC.   Return 1 if DESC describes a constant with the same value as EXP.  */static intcompare_constant (exp, desc)     tree exp;     struct constant_descriptor *desc;{  return 0 != compare_constant_1 (exp, desc->contents);}/* Compare constant expression EXP with a substring P of a constant descriptor.   If they match, return a pointer to the end of the substring matched.   If they do not match, return 0.   Since descriptors are written in polish prefix notation,   this function can be used recursively to test one operand of EXP   against a subdescriptor, and if it succeeds it returns the   address of the subdescriptor for the next operand.  */static char *compare_constant_1 (exp, p)     tree exp;     char *p;{  register char *strp;  register int len;  register enum tree_code code = TREE_CODE (exp);  if (code != (enum tree_code) *p++)    return 0;  if (code == INTEGER_CST)    {      /* Integer constants are the same only if the same width of type.  */      if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))	return 0;      strp = (char *) &TREE_INT_CST_LOW (exp);      len = 2 * sizeof TREE_INT_CST_LOW (exp);    }  else if (code == REAL_CST)    {      /* Real constants are the same only if the same width of type.  */      if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))	return 0;      strp = (char *) &TREE_REAL_CST (exp);      len = sizeof TREE_REAL_CST (exp);    }  else if (code == STRING_CST)    {      if (flag_writable_strings)	return 0;      strp = TREE_STRING_POINTER (exp);      len = TREE_STRING_LENGTH (exp);      if (bcmp ((char *) &TREE_STRING_LENGTH (exp), p,		sizeof TREE_STRING_LENGTH (exp)))	return 0;      p += sizeof TREE_STRING_LENGTH (exp);    }  else if (code == COMPLEX_CST)    {      p = compare_constant_1 (TREE_REALPART (exp), p);      if (p == 0) return 0;      p = compare_constant_1 (TREE_IMAGPART (exp), p);      return p;    }  else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)    {      len = int_size_in_bytes (TREE_TYPE (exp));      strp = (char*) alloca (len);      get_set_constructor_bytes (exp, (unsigned char *) strp, len);    }  else if (code == CONSTRUCTOR)    {      register tree link;      int length = list_length (CONSTRUCTOR_ELTS (exp));      tree type;      if (bcmp ((char *) &length, p, sizeof 

⌨️ 快捷键说明

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