expr.c revision 90075
118334Speter/* Convert language-specific tree expression to rtl instructions,
218334Speter   for GNU compiler.
390075Sobrien   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
490075Sobrien   2000, 2001 Free Software Foundation, Inc.
518334Speter
618334SpeterThis file is part of GNU CC.
718334Speter
818334SpeterGNU CC 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
1318334SpeterGNU CC 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
1918334Speteralong with GNU CC; see the file COPYING.  If not, write to
2018334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
2118334SpeterBoston, MA 02111-1307, USA.  */
2218334Speter
2318334Speter
2418334Speter#include "config.h"
2550397Sobrien#include "system.h"
2618334Speter#include "rtl.h"
2718334Speter#include "tree.h"
2818334Speter#include "flags.h"
2918334Speter#include "expr.h"
3018334Speter#include "cp-tree.h"
3150397Sobrien#include "toplev.h"
3290075Sobrien#include "except.h"
3390075Sobrien#include "tm_p.h"
3418334Speter
3590075Sobrienstatic rtx cplus_expand_expr PARAMS ((tree, rtx, enum machine_mode,
3650397Sobrien				    enum expand_modifier));
3718334Speter
3852284Sobrien/* Hook used by output_constant to expand language-specific
3952284Sobrien   constants.  */
4052284Sobrien
4190075Sobrientree
4252284Sobriencplus_expand_constant (cst)
4352284Sobrien     tree cst;
4452284Sobrien{
4552284Sobrien  switch (TREE_CODE (cst))
4652284Sobrien    {
4752284Sobrien    case PTRMEM_CST:
4852284Sobrien      {
4952284Sobrien	tree type = TREE_TYPE (cst);
5052284Sobrien	tree member;
5152284Sobrien
5252284Sobrien	/* Find the member.  */
5352284Sobrien	member = PTRMEM_CST_MEMBER (cst);
5452284Sobrien
5552284Sobrien	if (TREE_CODE (member) == FIELD_DECL)
5652284Sobrien	  {
5752284Sobrien	    /* Find the offset for the field.  */
5890075Sobrien	    tree offset = byte_position (member);
5990075Sobrien	    cst = fold (build1 (NOP_EXPR, type, offset));
6052284Sobrien	  }
6152284Sobrien	else
6252284Sobrien	  {
6352284Sobrien	    tree delta;
6452284Sobrien	    tree pfn;
6552284Sobrien
6690075Sobrien	    expand_ptrmemfunc_cst (cst, &delta, &pfn);
6790075Sobrien	    cst = build_ptrmemfunc1 (type, delta, pfn);
6852284Sobrien	  }
6952284Sobrien      }
7052284Sobrien      break;
7152284Sobrien
7252284Sobrien    default:
7352284Sobrien      /* There's nothing to do.  */
7452284Sobrien      break;
7552284Sobrien    }
7652284Sobrien
7752284Sobrien  return cst;
7852284Sobrien}
7952284Sobrien
8018334Speter/* Hook used by expand_expr to expand language-specific tree codes.  */
8118334Speter
8250397Sobrienstatic rtx
8318334Spetercplus_expand_expr (exp, target, tmode, modifier)
8418334Speter     tree exp;
8518334Speter     rtx target;
8618334Speter     enum machine_mode tmode;
8718334Speter     enum expand_modifier modifier;
8818334Speter{
8918334Speter  tree type = TREE_TYPE (exp);
9018334Speter  register enum machine_mode mode = TYPE_MODE (type);
9118334Speter  register enum tree_code code = TREE_CODE (exp);
9290075Sobrien  rtx ret;
9318334Speter
9418334Speter  /* No sense saving up arithmetic to be done
9518334Speter     if it's all in the wrong mode to form part of an address.
9618334Speter     And force_operand won't know whether to sign-extend or zero-extend.  */
9718334Speter
9818334Speter  if (mode != Pmode && modifier == EXPAND_SUM)
9918334Speter    modifier = EXPAND_NORMAL;
10018334Speter
10118334Speter  switch (code)
10218334Speter    {
10352284Sobrien    case PTRMEM_CST:
10452284Sobrien      return expand_expr (cplus_expand_constant (exp),
10552284Sobrien			  target, tmode, modifier);
10652284Sobrien
10718334Speter    case OFFSET_REF:
10890075Sobrien      /* Offset refs should not make it through to here. */
10990075Sobrien      abort ();
11090075Sobrien      return const0_rtx;
11190075Sobrien
11218334Speter    case THROW_EXPR:
11390075Sobrien      expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
11418334Speter      return NULL;
11518334Speter
11690075Sobrien    case MUST_NOT_THROW_EXPR:
11790075Sobrien      expand_eh_region_start ();
11890075Sobrien      ret = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
11990075Sobrien      expand_eh_region_end_must_not_throw (build_call (terminate_node, 0));
12090075Sobrien      return ret;
12118334Speter
12290075Sobrien    case EMPTY_CLASS_EXPR:
12390075Sobrien      /* We don't need to generate any code for an empty class.  */
12490075Sobrien      return const0_rtx;
12550397Sobrien
12618334Speter    default:
12790075Sobrien      return c_expand_expr (exp, target, tmode, modifier);
12818334Speter    }
12990075Sobrien  abort ();
13018334Speter  /* NOTREACHED */
13118334Speter  return NULL;
13218334Speter}
13318334Speter
13418334Spetervoid
13518334Speterinit_cplus_expand ()
13618334Speter{
13718334Speter  lang_expand_expr = cplus_expand_expr;
13818334Speter}
13918334Speter
14018334Speterint
14118334Speterextract_init (decl, init)
14252284Sobrien     tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
14318334Speter{
14418334Speter  return 0;
14518334Speter}
14650397Sobrien
147