expr.c revision 50397
118334Speter/* Convert language-specific tree expression to rtl instructions,
218334Speter   for GNU compiler.
318334Speter   Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
418334Speter
518334SpeterThis file is part of GNU CC.
618334Speter
718334SpeterGNU CC is free software; you can redistribute it and/or modify
818334Speterit under the terms of the GNU General Public License as published by
918334Speterthe Free Software Foundation; either version 2, or (at your option)
1018334Speterany later version.
1118334Speter
1218334SpeterGNU CC is distributed in the hope that it will be useful,
1318334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1418334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1518334SpeterGNU General Public License for more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1818334Speteralong with GNU CC; see the file COPYING.  If not, write to
1918334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
2018334SpeterBoston, MA 02111-1307, USA.  */
2118334Speter
2218334Speter
2318334Speter#include "config.h"
2450397Sobrien#include "system.h"
2518334Speter#include "rtl.h"
2618334Speter#include "tree.h"
2718334Speter#include "flags.h"
2818334Speter#include "expr.h"
2918334Speter#include "cp-tree.h"
3050397Sobrien#include "toplev.h"
3118334Speter
3250397Sobrien#if 0
3350397Sobrienstatic tree extract_aggr_init PROTO((tree, tree));
3450397Sobrienstatic tree extract_scalar_init PROTO((tree, tree));
3550397Sobrien#endif
3650397Sobrienstatic rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
3750397Sobrien				    enum expand_modifier));
3818334Speter
3918334Speter/* Hook used by expand_expr to expand language-specific tree codes.  */
4018334Speter
4150397Sobrienstatic rtx
4218334Spetercplus_expand_expr (exp, target, tmode, modifier)
4318334Speter     tree exp;
4418334Speter     rtx target;
4518334Speter     enum machine_mode tmode;
4618334Speter     enum expand_modifier modifier;
4718334Speter{
4818334Speter  tree type = TREE_TYPE (exp);
4918334Speter  register enum machine_mode mode = TYPE_MODE (type);
5018334Speter  register enum tree_code code = TREE_CODE (exp);
5118334Speter  int ignore = target == const0_rtx;
5218334Speter
5318334Speter  if (ignore)
5450397Sobrien    target = 0;
5518334Speter
5618334Speter  /* No sense saving up arithmetic to be done
5718334Speter     if it's all in the wrong mode to form part of an address.
5818334Speter     And force_operand won't know whether to sign-extend or zero-extend.  */
5918334Speter
6018334Speter  if (mode != Pmode && modifier == EXPAND_SUM)
6118334Speter    modifier = EXPAND_NORMAL;
6218334Speter
6318334Speter  switch (code)
6418334Speter    {
6550397Sobrien    case AGGR_INIT_EXPR:
6618334Speter      {
6718334Speter	/* Something needs to be initialized, but we didn't know
6818334Speter	   where that thing was when building the tree.  For example,
6918334Speter	   it could be the return value of a function, or a parameter
7018334Speter	   to a function which lays down in the stack, or a temporary
7118334Speter	   variable which must be passed by reference.
7218334Speter
7318334Speter	   Cleanups are handled in a language-specific way: they
7418334Speter	   might be run by the called function (true in GNU C++
7518334Speter	   for parameters with cleanups), or they might be
7618334Speter	   run by the caller, after the call (true in GNU C++
7718334Speter	   for other cleanup needs).  */
7818334Speter
7918334Speter	tree func = TREE_OPERAND (exp, 0);
8018334Speter	tree args = TREE_OPERAND (exp, 1);
8118334Speter	tree type = TREE_TYPE (exp), slot;
8218334Speter	tree call_exp;
8318334Speter	rtx call_target, return_target;
8418334Speter	int pcc_struct_return = 0;
8518334Speter
8618334Speter	/* The expression `init' wants to initialize what
8718334Speter	   `target' represents.  SLOT holds the slot for TARGET.  */
8818334Speter	slot = TREE_OPERAND (exp, 2);
8918334Speter
9050397Sobrien	/* Should always be called with a target.  */
9150397Sobrien	my_friendly_assert (target != NULL_RTX, 205);
9218334Speter
9318334Speter	/* The target the initializer will initialize (CALL_TARGET)
9418334Speter	   must now be directed to initialize the target we are
9518334Speter	   supposed to initialize (TARGET).  The semantics for
9618334Speter	   choosing what CALL_TARGET is is language-specific,
9718334Speter	   as is building the call which will perform the
9818334Speter	   initialization.  It is left here to show the choices that
9918334Speter	   exist for C++.  */
10018334Speter
10118334Speter	if (TREE_CODE (func) == ADDR_EXPR
10218334Speter	    && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
10318334Speter	    && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
10418334Speter	  {
10518334Speter	    type = build_pointer_type (type);
10618334Speter	    /* Don't clobber a value that might be part of a default
10718334Speter	       parameter value.  */
10818334Speter	    mark_addressable (slot);
10918334Speter	    if (TREE_PERMANENT (args))
11050397Sobrien	      args = expr_tree_cons (0, build1 (ADDR_EXPR, type, slot),
11118334Speter				TREE_CHAIN (args));
11218334Speter	    else
11318334Speter	      TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
11418334Speter	    call_target = 0;
11518334Speter	  }
11618334Speter	else
11718334Speter	  {
11850397Sobrien	    call_target = target;
11918334Speter#ifdef PCC_STATIC_STRUCT_RETURN
12050397Sobrien	    if (aggregate_value_p (type))
12150397Sobrien	      {
12250397Sobrien		pcc_struct_return = 1;
12350397Sobrien		call_target = 0;
12450397Sobrien	      }
12518334Speter#endif
12618334Speter	  }
12718334Speter
12850397Sobrien	call_exp = build (CALL_EXPR, type, func, args, NULL_TREE);
12918334Speter	TREE_SIDE_EFFECTS (call_exp) = 1;
13018334Speter	return_target = expand_call (call_exp, call_target, ignore);
13118334Speter
13250397Sobrien	if (call_target)
13350397Sobrien	  /* Trust that the right thing has been done; it's too hard to
13450397Sobrien	     verify.  */
13550397Sobrien	  return return_target;
13618334Speter
13750397Sobrien	/* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN
13850397Sobrien	   calling convention, we need to copy the return value out of
13950397Sobrien	   the static return buffer into slot.  */
14050397Sobrien	if (pcc_struct_return)
14118334Speter	  {
14250397Sobrien	    extern int flag_access_control;
14350397Sobrien	    int old_ac = flag_access_control;
14418334Speter
14550397Sobrien	    tree init = build_decl (VAR_DECL, NULL_TREE,
14650397Sobrien				    build_reference_type (type));
14750397Sobrien	    DECL_RTL (init) = XEXP (return_target, 0);
14850397Sobrien	    init = convert_from_reference (init);
14918334Speter
15050397Sobrien	    flag_access_control = 0;
15150397Sobrien	    expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
15250397Sobrien	    flag_access_control = old_ac;
15318334Speter
15450397Sobrien	    if (TYPE_NEEDS_DESTRUCTOR (type))
15550397Sobrien	      {
15650397Sobrien		init = maybe_build_cleanup (init);
15750397Sobrien		if (init != NULL_TREE)
15850397Sobrien		  expand_expr (init, const0_rtx, VOIDmode, 0);
15950397Sobrien	      }
16018334Speter	  }
16118334Speter
16218334Speter	return DECL_RTL (slot);
16318334Speter      }
16418334Speter
16518334Speter    case OFFSET_REF:
16618334Speter      {
16718334Speter#if 1
16818334Speter	return expand_expr (default_conversion (resolve_offset_ref (exp)),
16918334Speter			    target, tmode, EXPAND_NORMAL);
17018334Speter#else
17118334Speter	/* This is old crusty code, and does not handle all that the
17218334Speter	   resolve_offset_ref function does.  (mrs) */
17318334Speter	tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
17418334Speter	tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
17518334Speter	return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
17618334Speter			    target, tmode, EXPAND_NORMAL);
17718334Speter#endif
17818334Speter      }
17918334Speter
18018334Speter    case THUNK_DECL:
18118334Speter      return DECL_RTL (exp);
18218334Speter
18318334Speter    case THROW_EXPR:
18418334Speter      expand_throw (TREE_OPERAND (exp, 0));
18518334Speter      return NULL;
18618334Speter
18750397Sobrien    case VEC_INIT_EXPR:
18850397Sobrien      return expand_expr
18950397Sobrien	(expand_vec_init
19050397Sobrien	 (NULL_TREE, TREE_OPERAND (exp, 0),
19150397Sobrien	  build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2),
19250397Sobrien			   integer_one_node, 1),
19350397Sobrien	  TREE_OPERAND (exp, 1), 0), target, tmode, modifier);
19418334Speter
19550397Sobrien    case NEW_EXPR:
19650397Sobrien      return expand_expr (build_new_1 (exp), target, tmode, modifier);
19750397Sobrien
19818334Speter    default:
19918334Speter      break;
20018334Speter    }
20118334Speter  my_friendly_abort (40);
20218334Speter  /* NOTREACHED */
20318334Speter  return NULL;
20418334Speter}
20518334Speter
20618334Spetervoid
20718334Speterinit_cplus_expand ()
20818334Speter{
20918334Speter  lang_expand_expr = cplus_expand_expr;
21018334Speter}
21118334Speter
21218334Speter/* If DECL had its rtl moved from where callers expect it
21318334Speter   to be, fix it up.  RESULT is the nominal rtl for the RESULT_DECL,
21418334Speter   which may be a pseudo instead of a hard register.  */
21518334Speter
21618334Spetervoid
21718334Speterfixup_result_decl (decl, result)
21818334Speter     tree decl;
21918334Speter     rtx result;
22018334Speter{
22118334Speter  if (REG_P (result))
22218334Speter    {
22318334Speter      if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
22418334Speter	{
22518334Speter	  rtx real_decl_result;
22618334Speter
22718334Speter#ifdef FUNCTION_OUTGOING_VALUE
22818334Speter	  real_decl_result
22918334Speter	    = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
23018334Speter#else
23118334Speter	  real_decl_result
23218334Speter	    = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
23318334Speter#endif
23418334Speter	  REG_FUNCTION_VALUE_P (real_decl_result) = 1;
23518334Speter	  result = real_decl_result;
23618334Speter	}
23718334Speter      store_expr (decl, result, 0);
23818334Speter      emit_insn (gen_rtx (USE, VOIDmode, result));
23918334Speter    }
24018334Speter}
24118334Speter
24250397Sobrien#if 0
24318334Speter/* Expand this initialization inline and see if it's simple enough that
24418334Speter   it can be done at compile-time.  */
24518334Speter
24618334Speterstatic tree
24718334Speterextract_aggr_init (decl, init)
24818334Speter     tree decl, init;
24918334Speter{
25018334Speter  return 0;
25118334Speter}
25218334Speter
25318334Speterstatic tree
25418334Speterextract_scalar_init (decl, init)
25518334Speter     tree decl, init;
25618334Speter{
25718334Speter  rtx value, insns, insn;
25818334Speter  extern struct obstack temporary_obstack;
25918334Speter  tree t = NULL_TREE;
26018334Speter
26118334Speter  push_obstacks (&temporary_obstack, &temporary_obstack);
26218334Speter  start_sequence ();
26318334Speter  value = expand_expr (init, NULL_RTX, VOIDmode, 0);
26418334Speter  insns = get_insns ();
26518334Speter  end_sequence ();
26618334Speter  reg_scan (insns, max_reg_num (), 0);
26718334Speter  jump_optimize (insns, 0, 0, 1);
26818334Speter  pop_obstacks ();
26918334Speter
27018334Speter  for (insn = insns; insn; insn = NEXT_INSN (insn))
27118334Speter    {
27218334Speter      rtx r, to;
27318334Speter
27418334Speter      if (GET_CODE (insn) == NOTE)
27518334Speter	continue;
27618334Speter      else if (GET_CODE (insn) != INSN)
27718334Speter	return 0;
27818334Speter
27918334Speter      r = PATTERN (insn);
28018334Speter      if (GET_CODE (r) != SET)
28118334Speter	return 0;
28218334Speter
28318334Speter      to = XEXP (r, 0);
28418334Speter
28550397Sobrien      if (! (to == value
28650397Sobrien	     || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
28718334Speter	return 0;
28818334Speter
28918334Speter      r = XEXP (r, 1);
29018334Speter
29118334Speter      switch (GET_CODE (r))
29218334Speter	{
29318334Speter	case CONST_INT:
29418334Speter	  t = build_int_2 (XEXP (r, 0), 0);
29518334Speter	  break;
29618334Speter	default:
29718334Speter	  return 0;
29818334Speter	}
29918334Speter    }
30018334Speter
30118334Speter  return t;
30218334Speter}
30350397Sobrien#endif
30418334Speter
30518334Speterint
30618334Speterextract_init (decl, init)
30718334Speter     tree decl, init;
30818334Speter{
30918334Speter  return 0;
31018334Speter
31150397Sobrien#if 0
31218334Speter  if (IS_AGGR_TYPE (TREE_TYPE (decl))
31318334Speter      || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
31418334Speter    init = extract_aggr_init (decl, init);
31518334Speter  else
31618334Speter    init = extract_scalar_init (decl, init);
31718334Speter
31818334Speter  if (init == NULL_TREE)
31918334Speter    return 0;
32018334Speter
32118334Speter  DECL_INITIAL (decl) = init;
32218334Speter  return 1;
32350397Sobrien#endif
32418334Speter}
32550397Sobrien
32650397Sobrienvoid
32750397Sobriendo_case (start, end)
32850397Sobrien     tree start, end;
32950397Sobrien{
33050397Sobrien  tree value1 = NULL_TREE, value2 = NULL_TREE, label;
33150397Sobrien
33250397Sobrien  if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE
33350397Sobrien      && POINTER_TYPE_P (TREE_TYPE (start)))
33450397Sobrien    error ("pointers are not permitted as case values");
33550397Sobrien
33650397Sobrien  if (end && pedantic)
33750397Sobrien    pedwarn ("ANSI C++ forbids range expressions in switch statement");
33850397Sobrien
33950397Sobrien  if (processing_template_decl)
34050397Sobrien    {
34150397Sobrien      add_tree (build_min_nt (CASE_LABEL, start, end));
34250397Sobrien      return;
34350397Sobrien    }
34450397Sobrien
34550397Sobrien  if (start)
34650397Sobrien    value1 = check_cp_case_value (start);
34750397Sobrien  if (end)
34850397Sobrien    value2 = check_cp_case_value (end);
34950397Sobrien
35050397Sobrien  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
35150397Sobrien
35250397Sobrien  if (value1 != error_mark_node
35350397Sobrien      && value2 != error_mark_node)
35450397Sobrien    {
35550397Sobrien      tree duplicate;
35650397Sobrien      int success;
35750397Sobrien
35850397Sobrien      if (end)
35950397Sobrien	success = pushcase_range (value1, value2, convert_and_check,
36050397Sobrien				  label, &duplicate);
36150397Sobrien      else if (start)
36250397Sobrien	success = pushcase (value1, convert_and_check, label, &duplicate);
36350397Sobrien      else
36450397Sobrien	success = pushcase (NULL_TREE, 0, label, &duplicate);
36550397Sobrien
36650397Sobrien      if (success == 1)
36750397Sobrien	{
36850397Sobrien	  if (end)
36950397Sobrien	    error ("case label not within a switch statement");
37050397Sobrien	  else if (start)
37150397Sobrien	    cp_error ("case label `%E' not within a switch statement", start);
37250397Sobrien	  else
37350397Sobrien	    error ("default label not within a switch statement");
37450397Sobrien	}
37550397Sobrien      else if (success == 2)
37650397Sobrien	{
37750397Sobrien	  if (end)
37850397Sobrien	    {
37950397Sobrien	      error ("duplicate (or overlapping) case value");
38050397Sobrien	      cp_error_at ("this is the first entry overlapping that value",
38150397Sobrien			   duplicate);
38250397Sobrien	    }
38350397Sobrien	  else if (start)
38450397Sobrien	    {
38550397Sobrien	      cp_error ("duplicate case value `%E'", start);
38650397Sobrien	      cp_error_at ("previously used here", duplicate);
38750397Sobrien	    }
38850397Sobrien	  else
38950397Sobrien	    {
39050397Sobrien	      error ("multiple default labels in one switch");
39150397Sobrien	      cp_error_at ("this is the first default label", duplicate);
39250397Sobrien	    }
39350397Sobrien	}
39450397Sobrien      else if (success == 3)
39550397Sobrien	warning ("case value out of range");
39650397Sobrien      else if (success == 4)
39750397Sobrien	warning ("empty range specified");
39850397Sobrien      else if (success == 5)
39950397Sobrien	{
40050397Sobrien	  if (end)
40150397Sobrien	    error ("case label within scope of cleanup or variable array");
40250397Sobrien	  else if (! start)
40350397Sobrien	    error ("`default' label within scope of cleanup or variable array");
40450397Sobrien	  else
40550397Sobrien	    cp_error ("case label `%E' within scope of cleanup or variable array", start);
40650397Sobrien	}
40750397Sobrien    }
40850397Sobrien  if (start)
40950397Sobrien    define_case_label (label);
41050397Sobrien  else
41150397Sobrien    define_case_label (NULL_TREE);
41250397Sobrien}
413