FreeBSD/contrib/gcc/varasm.c
/* Output assembler code for constant EXP to FILE, with no label.
   This includes the pseudo-op such as ".int" or ".byte", and a newline.
   Assumes output_addressed_constants has been done on EXP already.

   Generate exactly SIZE bytes of assembler data, padding at the end
   with zeros if necessary.  SIZE must always be specified.

   SIZE is important for structure constructors,
   since trailing members may have been omitted from the constructor.
   It is also important for initialization of arrays from string constants
   since the full length of the string constant might not be wanted.
   It is also needed for initialization of unions, where the initializer's
   type is just one member, and that may not be as long as the union.

   There a case in which we would fail to output exactly SIZE bytes:
   for a structure constructor that wants to produce more than SIZE bytes.
   But such constructors will never be generated for any possible input.

   ALIGN is the alignment of the data in bits.  */
Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.

Generate exactly SIZE bytes of assembler data, padding at the end
with zeros if necessary.  SIZE must always be specified.

SIZE is important for structure constructors,
since trailing members may have been omitted from the constructor.
It is also important for initialization of arrays from string constants
since the full length of the string constant might not be wanted.
It is also needed for initialization of unions, where the initializer's
type is just one member, and that may not be as long as the union.

There a case in which we would fail to output exactly SIZE bytes:
for a structure constructor that wants to produce more than SIZE bytes.
But such constructors will never be generated for any possible input.

ALIGN is the alignment of the data in bits.
Output assembler code for constant EXP to FILE with no label . This includes the pseudo - op such as " . int " or " . byte " and a newline . Assumes output_addressed_constants has been done on EXP already . Generate exactly SIZE bytes of assembler data padding at the end with zeros if necessary . SIZE must always be specified . SIZE is important for structure constructors since trailing members may have been omitted from the constructor . It is also important for initialization of arrays from string constants since the full length of the string constant might not be wanted . It is also needed for initialization of unions where the initializer ' s type is just one member and that may not be as long as the union . There a case in which we would fail to output exactly SIZE bytes : for a structure constructor that wants to produce more than SIZE bytes . But such constructors will never be generated for any possible input . ALIGN is the alignment of the data in bits .
void
output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
{
  enum tree_code code;
  unsigned HOST_WIDE_INT thissize;
  exp = lang_hooks.expand_constant (exp);
  if (size == 0 || flag_syntax_only)
    return;
  if (TREE_CODE (exp) == NOP_EXPR
      && POINTER_TYPE_P (TREE_TYPE (exp))
      && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
    {
      tree saved_type = TREE_TYPE (exp);
      while (TREE_CODE (exp) == NOP_EXPR
	     && POINTER_TYPE_P (TREE_TYPE (exp))
	     && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
	exp = TREE_OPERAND (exp, 0);
      if (TREE_CODE (exp) == ADDR_EXPR)
	exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
      else if (TREE_CODE (exp) == INTEGER_CST)
	exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
				  TREE_INT_CST_HIGH (exp));
    }
  while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
	 || TREE_CODE (exp) == NON_LVALUE_EXPR
	 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
    {
      HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
      HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)));
      if (type_size > op_size
	  && TREE_CODE (exp) != VIEW_CONVERT_EXPR
	  && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
	break;
      else
	exp = TREE_OPERAND (exp, 0);
    }
  code = TREE_CODE (TREE_TYPE (exp));
  thissize = int_size_in_bytes (TREE_TYPE (exp));
  exp = lang_hooks.expand_constant (exp);
  if (TREE_CODE (exp) == CONSTRUCTOR
      && VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (exp)))
    {
      assemble_zeros (size);
      return;
    }
  if (TREE_CODE (exp) == FDESC_EXPR)
    {
#ifdef ASM_OUTPUT_FDESC
      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
      tree decl = TREE_OPERAND (exp, 0);
      ASM_OUTPUT_FDESC (asm_out_file, decl, part);
#else
      gcc_unreachable ();
#endif
      return;
    }
  switch (code)
    {
    case BOOLEAN_TYPE:
    case INTEGER_TYPE:
    case ENUMERAL_TYPE:
    case POINTER_TYPE:
    case REFERENCE_TYPE:
    case BLOCK_POINTER_TYPE:
    case OFFSET_TYPE:
      if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
					   EXPAND_INITIALIZER),
			      MIN (size, thissize), align, 0))
	error ("initializer for integer value is too complicated");
      break;
    case REAL_TYPE:
      if (TREE_CODE (exp) != REAL_CST)
	error ("initializer for floating value is not a floating constant");
      assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
      break;
    case COMPLEX_TYPE:
      output_constant (TREE_REALPART (exp), thissize / 2, align);
      output_constant (TREE_IMAGPART (exp), thissize / 2,
		       min_align (align, BITS_PER_UNIT * (thissize / 2)));
      break;
    case ARRAY_TYPE:
    case VECTOR_TYPE:
      switch (TREE_CODE (exp))
	{
	case CONSTRUCTOR:
	  output_constructor (exp, size, align);
	  return;
	case STRING_CST:
	  thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
			  size);
	  assemble_string (TREE_STRING_POINTER (exp), thissize);
	  break;
	case VECTOR_CST:
	  {
	    int elt_size;
	    tree link;
	    unsigned int nalign;
	    enum machine_mode inner;
	    inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
	    nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
	    elt_size = GET_MODE_SIZE (inner);
	    link = TREE_VECTOR_CST_ELTS (exp);
	    output_constant (TREE_VALUE (link), elt_size, align);
	    thissize = elt_size;
	    while ((link = TREE_CHAIN (link)) != NULL)
	      {
		output_constant (TREE_VALUE (link), elt_size, nalign);
		thissize += elt_size;
	      }
	    break;
	  }
	default:
	  gcc_unreachable ();
	}
      break;
    case RECORD_TYPE:
    case UNION_TYPE:
      gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
      output_constructor (exp, size, align);
      return;
    case ERROR_MARK:
      return;
    default:
      gcc_unreachable ();
    }
  if (size > thissize)
    assemble_zeros (size - thissize);
}
void output_constant ( tree exp , unsigned HOST_WIDE_INT size , unsigned int align ) { enum tree_code code ; unsigned HOST_WIDE_INT thissize ; exp = lang_hooks . expand_constant ( exp ) ; if ( size == 0 || flag_syntax_only ) return ; if ( TREE_CODE ( exp ) == NOP_EXPR && POINTER_TYPE_P ( TREE_TYPE ( exp ) ) && targetm . valid_pointer_mode ( TYPE_MODE ( TREE_TYPE ( exp ) ) ) ) { tree saved_type = TREE_TYPE ( exp ) ; while ( TREE_CODE ( exp ) == NOP_EXPR && POINTER_TYPE_P ( TREE_TYPE ( exp ) ) && targetm . valid_pointer_mode ( TYPE_MODE ( TREE_TYPE ( exp ) ) ) ) exp = TREE_OPERAND ( exp , 0 ) ; if ( TREE_CODE ( exp ) == ADDR_EXPR ) exp = build1 ( ADDR_EXPR , saved_type , TREE_OPERAND ( exp , 0 ) ) ; else if ( TREE_CODE ( exp ) == INTEGER_CST ) exp = build_int_cst_wide ( saved_type , TREE_INT_CST_LOW ( exp ) , TREE_INT_CST_HIGH ( exp ) ) ; } while ( TREE_CODE ( exp ) == NOP_EXPR || TREE_CODE ( exp ) == CONVERT_EXPR || TREE_CODE ( exp ) == NON_LVALUE_EXPR || TREE_CODE ( exp ) == VIEW_CONVERT_EXPR ) { HOST_WIDE_INT type_size = int_size_in_bytes ( TREE_TYPE ( exp ) ) ; HOST_WIDE_INT op_size = int_size_in_bytes ( TREE_TYPE ( TREE_OPERAND ( exp , 0 ) ) ) ; if ( type_size > op_size && TREE_CODE ( exp ) != VIEW_CONVERT_EXPR && TREE_CODE ( TREE_TYPE ( exp ) ) != UNION_TYPE ) break ; else exp = TREE_OPERAND ( exp , 0 ) ; } code = TREE_CODE ( TREE_TYPE ( exp ) ) ; thissize = int_size_in_bytes ( TREE_TYPE ( exp ) ) ; exp = lang_hooks . expand_constant ( exp ) ; if ( TREE_CODE ( exp ) == CONSTRUCTOR && VEC_empty ( constructor_elt , CONSTRUCTOR_ELTS ( exp ) ) ) { assemble_zeros ( size ) ; return ; } if ( TREE_CODE ( exp ) == FDESC_EXPR ) { #ifdef ASM_OUTPUT_FDESC HOST_WIDE_INT part = tree_low_cst ( TREE_OPERAND ( exp , 1 ) , 0 ) ; tree decl = TREE_OPERAND ( exp , 0 ) ; ASM_OUTPUT_FDESC ( asm_out_file , decl , part ) ; #else gcc_unreachable ( ) ; #endif return ; } switch ( code ) { case BOOLEAN_TYPE : case INTEGER_TYPE : case ENUMERAL_TYPE : case POINTER_TYPE : case REFERENCE_TYPE : case BLOCK_POINTER_TYPE : case OFFSET_TYPE : if ( ! assemble_integer ( expand_expr ( exp , NULL_RTX , VOIDmode , EXPAND_INITIALIZER ) , MIN ( size , thissize ) , align , 0 ) ) error ( " " ) ; break ; case REAL_TYPE : if ( TREE_CODE ( exp ) != REAL_CST ) error ( " " ) ; assemble_real ( TREE_REAL_CST ( exp ) , TYPE_MODE ( TREE_TYPE ( exp ) ) , align ) ; break ; case COMPLEX_TYPE : output_constant ( TREE_REALPART ( exp ) , thissize / 2 , align ) ; output_constant ( TREE_IMAGPART ( exp ) , thissize / 2 , min_align ( align , BITS_PER_UNIT * ( thissize / 2 ) ) ) ; break ; case ARRAY_TYPE : case VECTOR_TYPE : switch ( TREE_CODE ( exp ) ) { case CONSTRUCTOR : output_constructor ( exp , size , align ) ; return ; case STRING_CST : thissize = MIN ( ( unsigned HOST_WIDE_INT ) TREE_STRING_LENGTH ( exp ) , size ) ; assemble_string ( TREE_STRING_POINTER ( exp ) , thissize ) ; break ; case VECTOR_CST : { int elt_size ; tree link ; unsigned int nalign ; enum machine_mode inner ; inner = TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( exp ) ) ) ; nalign = MIN ( align , GET_MODE_ALIGNMENT ( inner ) ) ; elt_size = GET_MODE_SIZE ( inner ) ; link = TREE_VECTOR_CST_ELTS ( exp ) ; output_constant ( TREE_VALUE ( link ) , elt_size , align ) ; thissize = elt_size ; while ( ( link = TREE_CHAIN ( link ) ) != NULL ) { output_constant ( TREE_VALUE ( link ) , elt_size , nalign ) ; thissize += elt_size ; } break ; } default : gcc_unreachable ( ) ; } break ; case RECORD_TYPE : case UNION_TYPE : gcc_assert ( TREE_CODE ( exp ) == CONSTRUCTOR ) ; output_constructor ( exp , size , align ) ; return ; case ERROR_MARK : return ; default : gcc_unreachable ( ) ; } if ( size > thissize ) assemble_zeros ( size - thissize ) ; }
Output assembler code for constant EXP to FILE, with no label.
Output assembler code for constant EXP to FILE with no label .
/* Some front-ends use constants other than the standard language-independent
     varieties, but which may still be output directly.  Give the front-end a
     chance to convert EXP to a language-independent representation.  */ /* See if we're trying to initialize a pointer in a non-default mode
     to the address of some declaration somewhere.  If the target says
     the mode is valid for pointers, assume the target has a way of
     resolving it.  */ /* Peel off any intermediate conversions-to-pointer for valid
	 pointer modes.  */ /* If what we're left with is the address of something, we can
	 convert the address to the final type and output it that
	 way.  */ /* Likewise for constant ints.  */ /* Eliminate any conversions since we'll be outputting the underlying
     constant.  */ /* Make sure eliminating the conversion is really a no-op, except with
	 VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
	 union types to allow for Ada unchecked unions.  */ /* Keep the conversion. */ /* Give the front end another chance to expand constants.  */ /* Allow a constructor with no elements for any data type.
     This means to fill the space with zeros.  */ /* Now output the underlying data.  If we've handling the padding, return.
     Otherwise, break and ensure SIZE is the size written.  */ /* APPLE LOCAL radar 5822844 */