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