118334Speter/* Convert language-specific tree expression to rtl instructions,
218334Speter   for GNU compiler.
390075Sobrien   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4132718Skan   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
518334Speter
6132718SkanThis file is part of GCC.
718334Speter
8132718SkanGCC is free software; you can redistribute it and/or modify
918334Speterit under the terms of the GNU General Public License as published by
1018334Speterthe Free Software Foundation; either version 2, or (at your option)
1118334Speterany later version.
1218334Speter
13132718SkanGCC is distributed in the hope that it will be useful,
1418334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1518334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1618334SpeterGNU General Public License for more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
19132718Skanalong with GCC; see the file COPYING.  If not, write to
20169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
21169689SkanBoston, MA 02110-1301, USA.  */
2218334Speter
2318334Speter
2418334Speter#include "config.h"
2550397Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2818334Speter#include "rtl.h"
2918334Speter#include "tree.h"
3018334Speter#include "flags.h"
3118334Speter#include "expr.h"
3218334Speter#include "cp-tree.h"
3350397Sobrien#include "toplev.h"
3490075Sobrien#include "except.h"
3590075Sobrien#include "tm_p.h"
3618334Speter
3752284Sobrien/* Hook used by output_constant to expand language-specific
3852284Sobrien   constants.  */
3952284Sobrien
4090075Sobrientree
41132718Skancplus_expand_constant (tree cst)
4252284Sobrien{
4352284Sobrien  switch (TREE_CODE (cst))
4452284Sobrien    {
4552284Sobrien    case PTRMEM_CST:
4652284Sobrien      {
4752284Sobrien	tree type = TREE_TYPE (cst);
4852284Sobrien	tree member;
49169689Skan
5052284Sobrien	/* Find the member.  */
5152284Sobrien	member = PTRMEM_CST_MEMBER (cst);
5252284Sobrien
53169689Skan	if (TREE_CODE (member) == FIELD_DECL)
5452284Sobrien	  {
5552284Sobrien	    /* Find the offset for the field.  */
56132718Skan	    cst = byte_position (member);
57132718Skan	    while (!same_type_p (DECL_CONTEXT (member),
58132718Skan				 TYPE_PTRMEM_CLASS_TYPE (type)))
59132718Skan	      {
60132718Skan		/* The MEMBER must have been nestled within an
61132718Skan		   anonymous aggregate contained in TYPE.  Find the
62132718Skan		   anonymous aggregate.  */
63132718Skan		member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
64132718Skan					    DECL_CONTEXT (member));
65132718Skan		cst = size_binop (PLUS_EXPR, cst, byte_position (member));
66132718Skan	      }
67132718Skan	    cst = fold (build_nop (type, cst));
6852284Sobrien	  }
6952284Sobrien	else
7052284Sobrien	  {
7152284Sobrien	    tree delta;
7252284Sobrien	    tree pfn;
7352284Sobrien
7490075Sobrien	    expand_ptrmemfunc_cst (cst, &delta, &pfn);
7590075Sobrien	    cst = build_ptrmemfunc1 (type, delta, pfn);
7652284Sobrien	  }
7752284Sobrien      }
7852284Sobrien      break;
7952284Sobrien
8052284Sobrien    default:
8152284Sobrien      /* There's nothing to do.  */
8252284Sobrien      break;
8352284Sobrien    }
8452284Sobrien
8552284Sobrien  return cst;
8652284Sobrien}
8752284Sobrien
8818334Speter/* Hook used by expand_expr to expand language-specific tree codes.  */
89169689Skan/* ??? The only thing that should be here are things needed to expand
90169689Skan   constant initializers; everything else should be handled by the
91169689Skan   gimplification routines.  Are EMPTY_CLASS_EXPR or BASELINK needed?  */
9218334Speter
93117395Skanrtx
94132718Skancxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier,
95132718Skan		 rtx *alt_rtl)
9618334Speter{
9718334Speter  tree type = TREE_TYPE (exp);
98132718Skan  enum machine_mode mode = TYPE_MODE (type);
99132718Skan  enum tree_code code = TREE_CODE (exp);
10018334Speter
10118334Speter  /* No sense saving up arithmetic to be done
10218334Speter     if it's all in the wrong mode to form part of an address.
10318334Speter     And force_operand won't know whether to sign-extend or zero-extend.  */
10418334Speter
10518334Speter  if (mode != Pmode && modifier == EXPAND_SUM)
10618334Speter    modifier = EXPAND_NORMAL;
10718334Speter
10818334Speter  switch (code)
10918334Speter    {
11052284Sobrien    case PTRMEM_CST:
11152284Sobrien      return expand_expr (cplus_expand_constant (exp),
11252284Sobrien			  target, tmode, modifier);
11352284Sobrien
11418334Speter    case OFFSET_REF:
115117395Skan      /* Offset refs should not make it through to here.  */
116169689Skan      gcc_unreachable ();
11718334Speter
11890075Sobrien    case EMPTY_CLASS_EXPR:
11990075Sobrien      /* We don't need to generate any code for an empty class.  */
12090075Sobrien      return const0_rtx;
12150397Sobrien
122132718Skan    case BASELINK:
123132718Skan      return expand_expr (BASELINK_FUNCTIONS (exp), target, tmode,
124132718Skan			  modifier);
125132718Skan
12618334Speter    default:
127132718Skan      return c_expand_expr (exp, target, tmode, modifier, alt_rtl);
12818334Speter    }
12918334Speter}
130