• Main Page
  • Modules
  • Data Types
  • Files

osprey/kg++fe/wfe_expr.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006. QLogic Corporation. All Rights Reserved.
00003  */
00004 
00005 /* 
00006    Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
00007    File modified October 9, 2003 by PathScale, Inc. to update Open64 C/C++ 
00008    front-ends to GNU 3.3.1 release.
00009  */
00010 
00011 
00012 /* 
00013    Copyright (C) 2002 Tensilica, Inc.  All Rights Reserved.
00014    Revised to support Tensilica processors and to improve overall performance
00015  */
00016 
00017 /*
00018 
00019   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00020 
00021   This program is free software; you can redistribute it and/or modify it
00022   under the terms of version 2 of the GNU General Public License as
00023   published by the Free Software Foundation.
00024 
00025   This program is distributed in the hope that it would be useful, but
00026   WITHOUT ANY WARRANTY; without even the implied warranty of
00027   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00028 
00029   Further, this software is distributed without any warranty that it is
00030   free of the rightful claim of any third person regarding infringement 
00031   or the like.  Any license provided herein, whether implied or 
00032   otherwise, applies only to this software file.  Patent licenses, if 
00033   any, provided herein do not apply to combinations of this program with 
00034   other software, or any other product whatsoever.  
00035 
00036   You should have received a copy of the GNU General Public License along
00037   with this program; if not, write the Free Software Foundation, Inc., 59
00038   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00039 
00040   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00041   Mountain View, CA 94043, or:
00042 
00043   http://www.sgi.com
00044 
00045   For further information regarding this notice, see:
00046 
00047   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00048 
00049 */
00050 
00051 
00052 #include <values.h>
00053 #include "defs.h"
00054 #include "glob.h"
00055 #include "config.h"
00056 #ifdef TARG_X8664
00057 #include "config_opt.h"
00058 #endif
00059 #include "wn.h"
00060 #include "wn_util.h"
00061 #include "targ_sim.h"
00062 #include "const.h"
00063 #include "c_int_model.h"
00064 
00065 extern "C" {
00066 #include "gnu_config.h"
00067 }
00068 #include "gnu/system.h"
00069 
00070 extern "C" {
00071 #include "gnu/flags.h"
00072 #include "gnu/machmode.h"
00073 }
00074 
00075 extern "C" {
00076 #include "gnu/system.h"
00077 #include "gnu/tree.h"
00078 extern void warning (char*,...);  // from gnu
00079 #ifdef GPLUSPLUS_FE
00080 #include "gnu/cp/cp-tree.h"
00081 #endif /* GPLUSPLUS_FE */
00082 #ifdef KEY
00083 #include "real.h"
00084 #endif // KEY
00085 }
00086 
00087 #include "ir_reader.h"
00088 #include "wfe_misc.h"
00089 #include "wfe_dst.h"
00090 #include "tree_symtab.h"
00091 #include "wfe_decl.h"
00092 #include "wfe_expr.h"
00093 #include "wfe_stmt.h"
00094 #include "tree_cmp.h"
00095 
00096 // #define WFE_DEBUG
00097 #ifdef KEY
00098 extern void WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_ID, ST *);
00099 #endif // KEY
00100 
00101 LABEL_IDX loop_expr_exit_label = 0; // exit label for LOOP_EXPRs
00102 
00103 struct operator_from_tree_t {
00104   int      tree_code;
00105   char*    name;
00106   char     code;
00107   int      nkids;
00108   OPERATOR opr;
00109 } Operator_From_Tree [] = {
00110   ERROR_MARK,              "error_mark",              'x', 0,  OPERATOR_UNKNOWN,
00111   IDENTIFIER_NODE,         "identifier_node",         'x', -1, OPERATOR_UNKNOWN,
00112   OP_IDENTIFIER,           "op_identifier",           'x', 2,  OPERATOR_UNKNOWN,
00113   TREE_LIST,               "tree_list",               'x', 2,  OPERATOR_UNKNOWN,
00114   TREE_VEC,                "tree_vec",                'x', 2,  OPERATOR_UNKNOWN,
00115   BLOCK,                   "block",                   'b', 0,  OPERATOR_UNKNOWN,
00116   VOID_TYPE,               "void_type",               't', 0,  OPERATOR_UNKNOWN,
00117   INTEGER_TYPE,            "integer_type",            't', 0,  OPERATOR_UNKNOWN,
00118   REAL_TYPE,               "real_type",               't', 0,  OPERATOR_UNKNOWN,
00119   COMPLEX_TYPE,            "complex_type",            't', 0,  OPERATOR_UNKNOWN,
00120   VECTOR_TYPE,             "vector_type",             't', 0,  OPERATOR_UNKNOWN,
00121   ENUMERAL_TYPE,           "enumeral_type",           't', 0,  OPERATOR_UNKNOWN,
00122   BOOLEAN_TYPE,            "boolean_type",            't', 0,  OPERATOR_UNKNOWN,
00123   CHAR_TYPE,               "char_type",               't', 0,  OPERATOR_UNKNOWN,
00124   POINTER_TYPE,            "pointer_type",            't', 0,  OPERATOR_UNKNOWN,
00125   OFFSET_TYPE,             "offset_type",             't', 0,  OPERATOR_UNKNOWN,
00126   REFERENCE_TYPE,          "reference_type",          't', 0,  OPERATOR_UNKNOWN,
00127   METHOD_TYPE,             "method_type",             't', 0,  OPERATOR_UNKNOWN,
00128   FILE_TYPE,               "file_type",               't', 0,  OPERATOR_UNKNOWN,
00129   ARRAY_TYPE,              "array_type",              't', 0,  OPERATOR_UNKNOWN,
00130   SET_TYPE,                "set_type",                't', 0,  OPERATOR_UNKNOWN,
00131   RECORD_TYPE,             "record_type",             't', 0,  OPERATOR_UNKNOWN,
00132   UNION_TYPE,              "union_type",              't', 0,  OPERATOR_UNKNOWN,
00133   QUAL_UNION_TYPE,         "qual_union_type",         't', 0,  OPERATOR_UNKNOWN,
00134   FUNCTION_TYPE,           "function_type",           't', 0,  OPERATOR_UNKNOWN,
00135   LANG_TYPE,               "lang_type",               't', 0,  OPERATOR_UNKNOWN,
00136   INTEGER_CST,             "integer_cst",             'c', 2,  OPERATOR_UNKNOWN,
00137   REAL_CST,                "real_cst",                'c', 3,  OPERATOR_UNKNOWN,
00138   COMPLEX_CST,             "complex_cst",             'c', 3,  OPERATOR_UNKNOWN,
00139   VECTOR_CST,              "vector_cst",              'c', 3,  OPERATOR_UNKNOWN,
00140   STRING_CST,              "string_cst",              'c', 3,  OPERATOR_UNKNOWN,
00141   FUNCTION_DECL,           "function_decl",           'd', 0,  OPERATOR_UNKNOWN,
00142   LABEL_DECL,              "label_decl",              'd', 0,  OPERATOR_UNKNOWN,
00143   CONST_DECL,              "const_decl",              'd', 0,  OPERATOR_UNKNOWN,
00144   TYPE_DECL,               "type_decl",               'd', 0,  OPERATOR_UNKNOWN,
00145   VAR_DECL,                "var_decl",                'd', 0,  OPERATOR_UNKNOWN,
00146   PARM_DECL,               "parm_decl",               'd', 0,  OPERATOR_UNKNOWN,
00147   RESULT_DECL,             "result_decl",             'd', 0,  OPERATOR_UNKNOWN,
00148   FIELD_DECL,              "field_decl",              'd', 0,  OPERATOR_UNKNOWN,
00149   NAMESPACE_DECL,          "namespace_decl",          'd', 0,  OPERATOR_UNKNOWN,
00150   COMPONENT_REF,           "component_ref",           'r', 2,  OPERATOR_UNKNOWN,
00151   BIT_FIELD_REF,           "bit_field_ref",           'r', 3,  OPERATOR_UNKNOWN,
00152   INDIRECT_REF,            "indirect_ref",            'r', 1,  OPERATOR_UNKNOWN,
00153   BUFFER_REF,              "buffer_ref",              'r', 1,  OPERATOR_UNKNOWN,
00154   ARRAY_REF,               "array_ref",               'r', 2,  OPERATOR_UNKNOWN,
00155   ARRAY_RANGE_REF,         "array_range_ref",         'r', 2,  OPERATOR_UNKNOWN,
00156   VTABLE_REF,              "vtable_ref",              'r', 3,  OPERATOR_UNKNOWN,
00157   CONSTRUCTOR,             "constructor",             'e', 2,  OPERATOR_UNKNOWN,
00158   COMPOUND_EXPR,           "compound_expr",           'e', 2,  OPERATOR_UNKNOWN,
00159   MODIFY_EXPR,             "modify_expr",             'e', 2,  OPERATOR_UNKNOWN,
00160   INIT_EXPR,               "init_expr",               'e', 2,  OPERATOR_UNKNOWN,
00161   TARGET_EXPR,             "target_expr",             'e', 4,  OPERATOR_UNKNOWN,
00162   COND_EXPR,               "cond_expr",               'e', 3,  OPERATOR_UNKNOWN,
00163   BIND_EXPR,               "bind_expr",               'e', 3,  OPERATOR_UNKNOWN,
00164   CALL_EXPR,               "call_expr",               'e', 3,  OPERATOR_UNKNOWN,
00165   METHOD_CALL_EXPR,        "method_call_expr",        'e', 4,  OPERATOR_UNKNOWN,
00166   WITH_CLEANUP_EXPR,       "with_cleanup_expr",       'e', 3,  OPERATOR_UNKNOWN,
00167   CLEANUP_POINT_EXPR,      "cleanup_point_expr",      'e', 1,  OPERATOR_UNKNOWN,
00168   PLACEHOLDER_EXPR,        "placeholder_expr",        'x', 0,  OPERATOR_UNKNOWN,
00169   WITH_RECORD_EXPR,        "with_record_expr",        'e', 2,  OPERATOR_UNKNOWN,
00170   PLUS_EXPR,               "plus_expr",               '2', 2,  OPR_ADD,
00171   MINUS_EXPR,              "minus_expr",              '2', 2,  OPR_SUB,
00172   MULT_EXPR,               "mult_expr",               '2', 2,  OPR_MPY,
00173   TRUNC_DIV_EXPR,          "trunc_div_expr",          '2', 2,  OPR_DIV,
00174   CEIL_DIV_EXPR,           "ceil_div_expr",           '2', 2,  OPR_DIV,
00175   FLOOR_DIV_EXPR,          "floor_div_expr",          '2', 2,  OPERATOR_UNKNOWN,
00176   ROUND_DIV_EXPR,          "round_div_expr",          '2', 2,  OPERATOR_UNKNOWN,
00177   TRUNC_MOD_EXPR,          "trunc_mod_expr",          '2', 2,  OPR_REM,
00178   CEIL_MOD_EXPR,           "ceil_mod_expr",           '2', 2,  OPERATOR_UNKNOWN,
00179   FLOOR_MOD_EXPR,          "floor_mod_expr",          '2', 2,  OPERATOR_UNKNOWN,
00180   ROUND_MOD_EXPR,          "round_mod_expr",          '2', 2,  OPERATOR_UNKNOWN,
00181   RDIV_EXPR,               "rdiv_expr",               '2', 2,  OPR_DIV,
00182   EXACT_DIV_EXPR,          "exact_div_expr",          '2', 2,  OPR_DIV,
00183   FIX_TRUNC_EXPR,          "fix_trunc_expr",          '1', 1,  OPERATOR_UNKNOWN,
00184   FIX_CEIL_EXPR,           "fix_ceil_expr",           '1', 1,  OPERATOR_UNKNOWN,
00185   FIX_FLOOR_EXPR,          "fix_floor_expr",          '1', 1,  OPERATOR_UNKNOWN,
00186   FIX_ROUND_EXPR,          "fix_round_expr",          '1', 1,  OPERATOR_UNKNOWN,
00187   FLOAT_EXPR,              "float_expr",              '1', 1,  OPERATOR_UNKNOWN,
00188   EXPON_EXPR,              "expon_expr",              '2', 2,  OPERATOR_UNKNOWN,
00189   NEGATE_EXPR,             "negate_expr",             '1', 1,  OPR_NEG,
00190   MIN_EXPR,                "min_expr",                '2', 2,  OPR_MIN,
00191   MAX_EXPR,                "max_expr",                '2', 2,  OPR_MAX,
00192   ABS_EXPR,                "abs_expr",                '1', 1,  OPR_ABS,
00193   FFS_EXPR,                "ffs_expr",                '1', 1,  OPERATOR_UNKNOWN,
00194   LSHIFT_EXPR,             "lshift_expr",             '2', 2,  OPR_SHL,
00195   RSHIFT_EXPR,             "rshift_expr",             '2', 2,  OPERATOR_UNKNOWN,
00196   LROTATE_EXPR,            "lrotate_expr",            '2', 2,  OPR_RROTATE,
00197   RROTATE_EXPR,            "rrotate_expr",            '2', 2,  OPR_RROTATE,
00198   BIT_IOR_EXPR,            "bit_ior_expr",            '2', 2,  OPR_BIOR,
00199   BIT_XOR_EXPR,            "bit_xor_expr",            '2', 2,  OPR_BXOR,
00200   BIT_AND_EXPR,            "bit_and_expr",            '2', 2,  OPR_BAND,
00201   BIT_ANDTC_EXPR,          "bit_andtc_expr",          '2', 2,  OPERATOR_UNKNOWN,
00202   BIT_NOT_EXPR,            "bit_not_expr",            '1', 1,  OPR_BNOT,
00203   TRUTH_ANDIF_EXPR,        "truth_andif_expr",        'e', 2,  OPR_CAND,
00204   TRUTH_ORIF_EXPR,         "truth_orif_expr",         'e', 2,  OPR_CIOR,
00205   TRUTH_AND_EXPR,          "truth_and_expr",          'e', 2,  OPR_BAND,
00206   TRUTH_OR_EXPR,           "truth_or_expr",           'e', 2,  OPR_BIOR,
00207   TRUTH_XOR_EXPR,          "truth_xor_expr",          'e', 2,  OPR_BXOR,
00208   TRUTH_NOT_EXPR,          "truth_not_expr",          'e', 1,  OPR_LNOT,
00209   LT_EXPR,                 "lt_expr",                 '<', 2,  OPR_LT,
00210   LE_EXPR,                 "le_expr",                 '<', 2,  OPR_LE,
00211   GT_EXPR,                 "gt_expr",                 '<', 2,  OPR_GT,
00212   GE_EXPR,                 "ge_expr",                 '<', 2,  OPR_GE,
00213   EQ_EXPR,                 "eq_expr",                 '<', 2,  OPR_EQ,
00214   NE_EXPR,                 "ne_expr",                 '<', 2,  OPR_NE,
00215   UNORDERED_EXPR,          "unordered_expr",          '<', 2,  OPERATOR_UNKNOWN,
00216   ORDERED_EXPR,            "ordered_expr",            '<', 2,  OPERATOR_UNKNOWN,
00217   UNLT_EXPR,               "unlt_expr",               '<', 2,  OPERATOR_UNKNOWN,
00218   UNLE_EXPR,               "unle_expr",               '<', 2,  OPERATOR_UNKNOWN,
00219   UNGT_EXPR,               "ungt_expr",               '<', 2,  OPERATOR_UNKNOWN,
00220   UNGE_EXPR,               "unge_expr",               '<', 2,  OPERATOR_UNKNOWN,
00221   UNEQ_EXPR,               "uneq_expr",               '<', 2,  OPERATOR_UNKNOWN,
00222   IN_EXPR,                 "in_expr",                 '2', 2,  OPERATOR_UNKNOWN,
00223   SET_LE_EXPR,             "set_le_expr",             '<', 2,  OPERATOR_UNKNOWN,
00224   CARD_EXPR,               "card_expr",               '1', 1,  OPERATOR_UNKNOWN,
00225   RANGE_EXPR,              "range_expr",              '2', 2,  OPERATOR_UNKNOWN,
00226   CONVERT_EXPR,            "convert_expr",            '1', 1,  OPERATOR_UNKNOWN,
00227   NOP_EXPR,                "nop_expr",                '1', 1,  OPERATOR_UNKNOWN,
00228   NON_LVALUE_EXPR,         "non_lvalue_expr",         '1', 1,  OPERATOR_UNKNOWN,
00229   VIEW_CONVERT_EXPR,       "view_convert_expr",       '1', 1,  OPERATOR_UNKNOWN,
00230   SAVE_EXPR,               "save_expr",               'e', 3,  OPERATOR_UNKNOWN,
00231   UNSAVE_EXPR,             "unsave_expr",             'e', 1,  OPERATOR_UNKNOWN,
00232   RTL_EXPR,                "rtl_expr",                'e', 2,  OPERATOR_UNKNOWN,
00233   ADDR_EXPR,               "addr_expr",               'e', 1,  OPERATOR_UNKNOWN,
00234   REFERENCE_EXPR,          "reference_expr",          'e', 1,  OPERATOR_UNKNOWN,
00235   ENTRY_VALUE_EXPR,        "entry_value_expr",        'e', 1,  OPERATOR_UNKNOWN,
00236   FDESC_EXPR,              "fdesc_expr",              'e', 2,  OPERATOR_UNKNOWN,
00237   COMPLEX_EXPR,            "complex_expr",            '2', 2,  OPR_PAIR,
00238   CONJ_EXPR,               "conj_expr",               '1', 1,  OPERATOR_UNKNOWN,
00239   REALPART_EXPR,           "realpart_expr",           '1', 1,  OPR_FIRSTPART,
00240   IMAGPART_EXPR,           "imagpart_expr",           '1', 1,  OPR_SECONDPART,
00241   PREDECREMENT_EXPR,       "predecrement_expr",       'e', 2,  OPR_SUB,
00242   PREINCREMENT_EXPR,       "preincrement_expr",       'e', 2,  OPR_ADD,
00243   POSTDECREMENT_EXPR,      "postdecrement_expr",      'e', 2,  OPR_SUB,
00244   POSTINCREMENT_EXPR,      "postincrement_expr",      'e', 2,  OPR_ADD,
00245   VA_ARG_EXPR,             "va_arg_expr",             'e', 1,  OPERATOR_UNKNOWN,
00246   TRY_CATCH_EXPR,          "try_catch_expr",          'e', 2,  OPERATOR_UNKNOWN,
00247   TRY_FINALLY_EXPR,        "try_finally",             'e', 2,  OPERATOR_UNKNOWN,
00248   GOTO_SUBROUTINE_EXPR,    "goto_subroutine",         'e', 2,  OPERATOR_UNKNOWN,
00249   POPDHC_EXPR,             "popdhc_expr",             's', 0,  OPERATOR_UNKNOWN,
00250   POPDCC_EXPR,             "popdcc_expr",             's', 0,  OPERATOR_UNKNOWN,
00251   LABEL_EXPR,              "label_expr",              's', 1,  OPERATOR_UNKNOWN,
00252   GOTO_EXPR,               "goto_expr",               's', 1,  OPERATOR_UNKNOWN,
00253   RETURN_EXPR,             "return_expr",             's', 1,  OPERATOR_UNKNOWN,
00254   EXIT_EXPR,               "exit_expr",               's', 1,  OPERATOR_UNKNOWN,
00255   LOOP_EXPR,               "loop_expr",               's', 1,  OPERATOR_UNKNOWN,
00256   LABELED_BLOCK_EXPR,      "labeled_block_expr",      'e', 2,  OPERATOR_UNKNOWN,
00257   EXIT_BLOCK_EXPR,         "exit_block_expr",         'e', 2,  OPERATOR_UNKNOWN,
00258   EXPR_WITH_FILE_LOCATION, "expr_with_file_location", 'e', 3,  OPERATOR_UNKNOWN,
00259   SWITCH_EXPR,             "switch_expr",             'e', 2,  OPERATOR_UNKNOWN,
00260   EXC_PTR_EXPR,            "exc_ptr_expr",            'e', 0,  OPERATOR_UNKNOWN,
00261   LAST_AND_UNUSED_TREE_CODE,"last_and_unused_tree_code",0, 0,  OPERATOR_UNKNOWN,
00262 
00263   SRCLOC,                  "srcloc",                  'x', 2,  OPERATOR_UNKNOWN,
00264   SIZEOF_EXPR,             "sizeof_expr",             '1', 1,  OPERATOR_UNKNOWN,
00265   ARROW_EXPR,              "arrow_expr",              'e', 1,  OPERATOR_UNKNOWN,
00266   ALIGNOF_EXPR,            "alignof_expr",            '1', 1,  OPERATOR_UNKNOWN,
00267   EXPR_STMT,               "expr_stmt",               'e', 1,  OPERATOR_UNKNOWN,
00268   COMPOUND_STMT,           "compound_stmt",           'e', 1,  OPERATOR_UNKNOWN,
00269   DECL_STMT,               "decl_stmt",               'e', 1,  OPERATOR_UNKNOWN,
00270   IF_STMT,                 "if_stmt",                 'e', 3,  OPERATOR_UNKNOWN,
00271   FOR_STMT,                "for_stmt",                'e', 4,  OPERATOR_UNKNOWN,
00272   WHILE_STMT,              "while_stmt",              'e', 2,  OPERATOR_UNKNOWN,
00273   DO_STMT,                 "do_stmt",                 'e', 2,  OPERATOR_UNKNOWN,
00274   RETURN_STMT,             "return_stmt",             'e', 1,  OPERATOR_UNKNOWN,
00275   BREAK_STMT,              "break_stmt",              'e', 0,  OPERATOR_UNKNOWN,
00276   CONTINUE_STMT,           "continue_stmt",           'e', 0,  OPERATOR_UNKNOWN,
00277   SWITCH_STMT,             "switch_stmt",             'e', 2,  OPERATOR_UNKNOWN,
00278   GOTO_STMT,               "goto_stmt",               'e', 1,  OPERATOR_UNKNOWN,
00279   LABEL_STMT,              "label_stmt",              'e', 1,  OPERATOR_UNKNOWN,
00280   ASM_STMT,                "asm_stmt",                'e', 5,  OPERATOR_UNKNOWN,
00281   SCOPE_STMT,              "scope_stmt",              'e', 1,  OPERATOR_UNKNOWN,
00282   FILE_STMT,               "file_stmt",               'e', 1,  OPERATOR_UNKNOWN,
00283   CASE_LABEL,              "case_label",              'e', 2,  OPERATOR_UNKNOWN,
00284   STMT_EXPR,               "stmt_expr",               'e', 1,  OPERATOR_UNKNOWN,
00285   COMPOUND_LITERAL_EXPR,   "compound_literal_expr",   'e', 1,  OPERATOR_UNKNOWN,
00286   CLEANUP_STMT,            "cleanup_stmt",            'e', 2,  OPERATOR_UNKNOWN,
00287 #ifdef KEY
00288   OMP_MARKER_STMT,         "omp_marker_stmt",         'e', 0,  OPERATOR_UNKNOWN,
00289 #endif // KEY
00290   FREQ_HINT_STMT,               "freq_hint_stmt",              'e', 1,   OPERATOR_UNKNOWN,   
00291   LAST_C_TREE_CODE,        "last_c_tree_code",          0, 0,  OPERATOR_UNKNOWN,
00292 
00293 #ifdef GPLUSPLUS_FE
00294   OFFSET_REF,              "offset_ref",              'r', 2,  OPERATOR_UNKNOWN,
00295   PTRMEM_CST,              "ptrmem_cst",              'c', 2,  OPERATOR_UNKNOWN,
00296   NEW_EXPR,                "nw_expr",                 'e', 3,  OPERATOR_UNKNOWN,
00297   VEC_NEW_EXPR,            "vec_nw_expr",             'e', 3,  OPERATOR_UNKNOWN,
00298   DELETE_EXPR,             "dl_expr",                 'e', 2,  OPERATOR_UNKNOWN,
00299   VEC_DELETE_EXPR,         "vec_dl_expr",             'e', 2,  OPERATOR_UNKNOWN,
00300   SCOPE_REF,               "scope_ref",               'r', 2,  OPERATOR_UNKNOWN,
00301   MEMBER_REF,              "member_ref",              'r', 2,  OPERATOR_UNKNOWN,
00302   TYPE_EXPR,               "type_expr",               'e', 1,  OPERATOR_UNKNOWN,
00303   AGGR_INIT_EXPR,          "aggr_init_expr",          'e', 3,  OPERATOR_UNKNOWN,
00304   THROW_EXPR,              "throw_expr",              'e', 1,  OPERATOR_UNKNOWN,
00305   EMPTY_CLASS_EXPR,        "empty_class_expr",        'e', 0,  OPERATOR_UNKNOWN,
00306 #ifdef KEY
00307   BASELINK,      "baselink",          'e', 3,  OPERATOR_UNKNOWN,
00308 #endif // KEY
00309   TEMPLATE_DECL,           "template_decl",           'd', 0,  OPERATOR_UNKNOWN,
00310   TEMPLATE_PARM_INDEX,     "template_parm_index",     'x', 0,  OPERATOR_UNKNOWN,
00311   TEMPLATE_TYPE_PARM,      "template_type_parm",      't', 0,  OPERATOR_UNKNOWN,
00312   TEMPLATE_TEMPLATE_PARM,  "template_template_parm",  't', 0,  OPERATOR_UNKNOWN,
00313   BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", 't', 0, OPERATOR_UNKNOWN,
00314   TYPENAME_TYPE,           "typename_type",           't', 0,  OPERATOR_UNKNOWN,
00315   UNBOUND_CLASS_TEMPLATE,  "unbound_class_template",  't', 0,  OPERATOR_UNKNOWN,
00316   TYPEOF_TYPE,             "typeof_type",             't', 0,  OPERATOR_UNKNOWN,
00317   USING_DECL,              "using_decl",              'd', 0,  OPERATOR_UNKNOWN,
00318   USING_STMT,              "using_directive",         'e', 1,  OPERATOR_UNKNOWN,
00319 #ifdef KEY
00320   DEFAULT_ARG,             "default_arg",             'x', 2,  OPERATOR_UNKNOWN,
00321 #else
00322   DEFAULT_ARG,             "default_arg",             'c', 2,  OPERATOR_UNKNOWN,
00323 #endif // KEY
00324   TEMPLATE_ID_EXPR,        "template_id_expr",        'e', 2,  OPERATOR_UNKNOWN,
00325 #ifndef KEY // CPLUS_BINDING does not exist
00326   CPLUS_BINDING,           "binding",                 'x', 2,  OPERATOR_UNKNOWN,
00327 #endif // !KEY
00328   OVERLOAD,                "overload",                'x', 1,  OPERATOR_UNKNOWN,
00329   WRAPPER,                 "wrapper",                 'x', 1,  OPERATOR_UNKNOWN,
00330   LOOKUP_EXPR,             "lookup_expr",             'e', 1,  OPERATOR_UNKNOWN,
00331   MODOP_EXPR,              "modop_expr",              'e', 3,  OPERATOR_UNKNOWN,
00332   CAST_EXPR,               "cast_expr",               '1', 1,  OPERATOR_UNKNOWN,
00333   REINTERPRET_CAST_EXPR,   "reinterpret_cast_expr",   '1', 1,  OPERATOR_UNKNOWN,
00334   CONST_CAST_EXPR,         "const_cast_expr",         '1', 1,  OPERATOR_UNKNOWN,
00335   STATIC_CAST_EXPR,        "static_cast_expr",        '1', 1,  OPERATOR_UNKNOWN,
00336   DYNAMIC_CAST_EXPR,       "dynamic_cast_expr",       '1', 1,  OPERATOR_UNKNOWN,
00337   DOTSTAR_EXPR,            "dotstar_expr",            'e', 2,  OPERATOR_UNKNOWN,
00338   TYPEID_EXPR,             "typeid_expr",             'e', 1,  OPERATOR_UNKNOWN,
00339   PSEUDO_DTOR_EXPR,        "pseudo_dtor_expr",        'e', 3,  OPERATOR_UNKNOWN,
00340 #ifndef KEY // SUBOBJECT, CTOR_STMT removed
00341   SUBOBJECT,               "subobject",               'e', 1,  OPERATOR_UNKNOWN,
00342   CTOR_STMT,               "ctor_stmt",               'e', 0,  OPERATOR_UNKNOWN,
00343   CTOR_INITIALIZER,        "ctor_initializer",        'e', 2,  OPERATOR_UNKNOWN,
00344 #else
00345   CTOR_INITIALIZER,        "ctor_initializer",        'e', 1,  OPERATOR_UNKNOWN,
00346 #endif // !KEY
00347   RETURN_INIT,             "return_init",             'e', 2,  OPERATOR_UNKNOWN,
00348   TRY_BLOCK,               "try_block",               'e', 2,  OPERATOR_UNKNOWN,
00349   EH_SPEC_BLOCK,           "eh_spec_block",           'e', 2,  OPERATOR_UNKNOWN,
00350   HANDLER,                 "handler",                 'e', 2,  OPERATOR_UNKNOWN,
00351   MUST_NOT_THROW_EXPR,     "must_not_throw_expr",     'e', 1,  OPERATOR_UNKNOWN,
00352   TAG_DEFN,                "tag_defn",                'e', 0,  OPERATOR_UNKNOWN,
00353   IDENTITY_CONV,           "identity_conv",           'e', 1,  OPERATOR_UNKNOWN,
00354   LVALUE_CONV,             "lvalue_conv",             'e', 1,  OPERATOR_UNKNOWN,
00355   QUAL_CONV,               "qual_conv",               'e', 1,  OPERATOR_UNKNOWN,
00356   STD_CONV,                "std_conv",                'e', 1,  OPERATOR_UNKNOWN,
00357   PTR_CONV,                "ptr_conv",                'e', 1,  OPERATOR_UNKNOWN,
00358   PMEM_CONV,               "pmem_conv",               'e', 1,  OPERATOR_UNKNOWN,
00359   BASE_CONV,               "base_conv",               'e', 1,  OPERATOR_UNKNOWN,
00360   REF_BIND,                "ref_bind",                'e', 1,  OPERATOR_UNKNOWN,
00361   USER_CONV,               "user_conv",               'e', 2,  OPERATOR_UNKNOWN,
00362   AMBIG_CONV,              "ambig_conv",              'e', 1,  OPERATOR_UNKNOWN,
00363   RVALUE_CONV,             "rvalue_conv",             'e', 1,  OPERATOR_UNKNOWN,
00364   LAST_CPLUS_TREE_CODE,    "last_cplus_tree_code",     0,  0,  OPERATOR_UNKNOWN
00365 #endif /* GPLUSPLUSFE */
00366 };
00367 
00368 #ifdef TARG_SL
00369 /*
00370   *  some side-effect intrinsic op need to be extended 
00371   */
00372 typedef enum EXTEND_PARM_POS {
00373  PZERO,   // no extend
00374  P0,
00375  P1,
00376  P2,
00377  P3,
00378  P4,
00379  P0_P2,
00380  P1_P3,
00381  P2_P4, 
00382  P3_P4,
00383 }EXTEND_PARM_POS;
00384 
00385 typedef struct intrinsicop_attr_extended {
00386   INTRINSIC id;
00387   BOOL need_extend; //
00388   int extend_kid;
00389   EXTEND_PARM_POS pos;
00390   INTRINSIC aux_id;   // extend intrinsic opr
00391 } INTRN_ATTR_EXTEND; 
00392 
00393 #define INTRN_EATTR_LAST 27 
00394 static INTRN_ATTR_EXTEND intrn_eattr[INTRN_EATTR_LAST] = {
00395   INTRN_C2_LD_V,  FALSE, 1, P1,INTRN_C3_PTR,
00396   INTRN_C2_LD_G,    FALSE, 1, P0,INTRN_C3_PTR,
00397   INTRN_C2_LD_V2G,   FALSE, 1, P0,INTRN_C3_PTR,
00398   INTRN_C2_LD_C_IMM,     FALSE, 1, P1,INTRN_C3_PTR,
00399   INTRN_C2_LD_V_IMM,     FALSE, 1, P4,INTRN_C3_PTR,
00400   INTRN_C2_LD_G_IMM,     FALSE, 1, P2,INTRN_C3_PTR,
00401   INTRN_C2_LD_V2G_IMM,  FALSE, 1, P2,INTRN_C3_PTR,
00402   INTRN_C2_ST_V,    FALSE, 1, P1,INTRN_C3_PTR,
00403   INTRN_C2_ST_G,   FALSE, 1, P1,INTRN_C3_PTR,
00404   INTRN_C2_ST_G2V,  FALSE, 1, P1,INTRN_C3_PTR,
00405   INTRN_C2_ST_C_IMM,   FALSE, 1, P1,INTRN_C3_PTR,
00406   INTRN_C2_ST_V_IMM,   FALSE, 1, P3,INTRN_C3_PTR,
00407   INTRN_C2_ST_G_IMM,   FALSE, 1, P2,INTRN_C3_PTR,
00408   INTRN_C2_ST_G2V_IMM,  FALSE, 1, P2,INTRN_C3_PTR,
00409   // new C3
00410   INTRN_C3DMAC_A, TRUE, 2, P2_P4, INTRN_C3_PTR,
00411   INTRN_C3DMULA_A, TRUE, 1, P2, INTRN_C3_PTR,
00412   INTRN_C3LD, TRUE, 1, P0, INTRN_C3_PTR,
00413   INTRN_C3ST, TRUE, 1, P1, INTRN_C3_PTR,
00414   INTRN_C3MAC_A, TRUE, 2, P2_P4, INTRN_C3_PTR,
00415   INTRN_C3MAC_AR, TRUE, 1, P3, INTRN_C3_PTR,
00416   INTRN_C3MULA_A, TRUE, 1, P2_P4, INTRN_C3_PTR,
00417   INTRN_C3MULA_AR, TRUE, 1, P3, INTRN_C3_PTR,
00418   INTRN_C3SAADD_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00419   INTRN_C3SAADDH_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00420   INTRN_C3SADDA_A, TRUE, 1, P2, INTRN_C3_PTR,
00421   INTRN_C3SAMULH_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00422   INTRN_C3_SET_CIRCBUF, FALSE, 2, P3_P4, INTRN_C3_PTR,
00423 };
00424 
00425 static BOOL intrinsic_op_need_extend (INTRINSIC id) {
00426 
00427   INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00428   int i=0;
00429   while (p && (i<INTRN_EATTR_LAST)) {
00430     if (p->id == id ) {
00431     return p->need_extend;
00432     }
00433   i++;
00434   p++;
00435   }
00436   return FALSE;
00437   
00438 }
00439 
00440 static BOOL intrinsic_need_deref (INTRINSIC id) {
00441 
00442   INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00443   int i=0; 
00444   while (p && (i<INTRN_EATTR_LAST)) {
00445         if (p->id == id ) {
00446                 return TRUE;
00447         }
00448         i++;
00449         p++;
00450   }
00451   return FALSE;
00452 
00453 }
00454 
00455 static INTRN_ATTR_EXTEND *Get_intrinsic_op_Eattr (INTRINSIC id) {
00456   INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00457   int i =0;
00458   while (p && (i<INTRN_EATTR_LAST)) {
00459     if (p->id == id ) {
00460     return p;
00461     }
00462   p++;
00463   i++;
00464   }
00465   return NULL;  
00466 }
00467 
00468 static void WN_Set_Deref_If_Needed(WN *wn) {
00469   INTRINSIC intrn=WN_intrinsic(wn);
00470         if(intrinsic_need_deref(intrn)){
00471                 INTRN_ATTR_EXTEND *p=Get_intrinsic_op_Eattr(intrn);
00472 
00473                 switch (p->pos) {
00474                         case P0:
00475                                 WN_Set_Parm_Dereference(WN_kid(wn,0));  break;
00476                         case P1:
00477                                 WN_Set_Parm_Dereference(WN_kid(wn,1));  break;
00478                         case P2:
00479                                 WN_Set_Parm_Dereference(WN_kid(wn,2));  break;
00480                         case P3:
00481                                 WN_Set_Parm_Dereference(WN_kid(wn,3));  break;
00482       case P4:
00483         WN_Set_Parm_Dereference(WN_kid(wn,4));  break;
00484                         case P0_P2:
00485                                 WN_Set_Parm_Dereference(WN_kid(wn,0)); WN_Set_Parm_Dereference(WN_kid(wn,2)); break;
00486                         case P1_P3:
00487                                 WN_Set_Parm_Dereference(WN_kid(wn,1)); WN_Set_Parm_Dereference(WN_kid(wn,3)); break;
00488                         case P2_P4:
00489                                 WN_Set_Parm_Dereference(WN_kid(wn,2)); WN_Set_Parm_Dereference(WN_kid(wn,4)); break;
00490                         case P3_P4:
00491                                 WN_Set_Parm_Dereference(WN_kid(wn,3)); WN_Set_Parm_Dereference(WN_kid(wn,4)); break;
00492                         default:
00493                                 Is_True(0, ("intrinsic has no extended attribution"));
00494                 }
00495         }
00496   return;
00497 }
00498 
00499 static int intrinsic_op_extend_kid (int index) {
00500    return intrn_eattr[index].extend_kid;  
00501 }
00502 
00503 static EXTEND_PARM_POS intrinsic_op_parm_pos (int index) {
00504    return intrn_eattr[index].pos; 
00505 }
00506 
00507 static BOOL WN_Need_Append_Intrinsic(WN *rhs) {
00508    OPERATOR opr=WN_operator(rhs);
00509    if (opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL) {
00510     INTRINSIC inid = WN_intrinsic(rhs);
00511   if (intrinsic_op_need_extend(inid)) {
00512     return TRUE;
00513   }
00514   } else  if (opr == OPR_CVTL) {
00515     WN *tmp = WN_kid0(rhs);
00516   OPERATOR kid_opr=WN_operator(tmp);
00517   if (kid_opr == OPR_INTRINSIC_OP || kid_opr == OPR_INTRINSIC_CALL) {
00518       INTRINSIC inid = WN_intrinsic(tmp);
00519     if (intrinsic_op_need_extend(inid)) {
00520     return TRUE;
00521     }
00522   }
00523   } 
00524   return FALSE;
00525 }
00526 /*
00527  *  given a side effect intrinsic op:  sum = intrinsic_c3_mac_a(sum, p, 1, q, 1, 0) which doing sum=; p++; q++ 
00528  *  we need extend it to
00529  *   sum = intrinsic_c3_mac_a(sum, p, 1, q, 1, 0)
00530  *   p = intrinsic_c3_ptr(p, sum);  <-slave intrinsic op
00531  *   q = intrinsic_c3_ptr(q, sum);
00532 */
00533 static void WFE_Stmt_Append_Extend_Intrinsic(WN *wn, WN *master_variable, SRCPOS src) {
00534    WN *kid1s[5];
00535    WN *op1;
00536    int aux_kid = -1;  // parameter numbers of slave intrinsic op
00537    int extend_num = -1;
00538    int pos[5]= {-1, -1, -1, -1, -1};
00539   
00540    WN *tmp_wn;
00541    INTRN_ATTR_EXTEND *p ;
00542    if (WN_operator(WN_kid0(wn)) == OPR_INTRINSIC_OP) {
00543      p = Get_intrinsic_op_Eattr(WN_intrinsic(WN_kid0(wn)));
00544      tmp_wn = wn;
00545    } else if (WN_operator(WN_kid0(wn)) == OPR_CVTL && WN_operator(WN_kid0(WN_kid0(wn))) == OPR_INTRINSIC_OP ) {
00546      p = Get_intrinsic_op_Eattr(WN_intrinsic(WN_kid0(WN_kid0(wn))));
00547      tmp_wn = WN_kid0(wn);
00548    } else if (WN_operator(wn) == OPR_INTRINSIC_CALL) {
00549      p = Get_intrinsic_op_Eattr(WN_intrinsic(wn));
00550      tmp_wn = wn;
00551    }
00552  
00553    if (p) {
00554     extend_num = p->extend_kid;
00555        switch (p->aux_id) {
00556      case INTRN_C3_PTR:  aux_kid = 2; break;
00557      default:  
00558       Is_True(0, ("unsupport internal intrinsic op"));
00559        }
00560        switch (p->pos) {
00561       case P0:
00562                 pos[0] = 0; break;
00563       case P1:
00564                 pos[0] = 1; break;
00565       case P2:
00566       pos[0] = 2;  break;
00567       case P3:
00568     pos[0] = 3;  break; 
00569       case P0_P2: 
00570       pos[0] = 0; pos[1] = 2; break;
00571       case P1_P3:
00572       pos[0] = 1; pos[1] = 3; break;
00573       case P2_P4:
00574       pos[0] = 2; pos[1] = 4; break;
00575       case P3_P4:
00576       pos[0] = 3; pos[1] = 4; break;
00577       default:
00578       Is_True(0, ("intrinsic has no extended attribution"));
00579        }
00580    } else {
00581      Is_True(0, ("intrinsic has no extended attribution"));
00582    }
00583    
00584    TY_IDX  ti2 = WN_ty(master_variable);
00585    TYPE_ID tm2 = TY_mtype(ti2);
00586    master_variable = WN_CreateParm (Mtype_comparison (tm2), master_variable,
00587             ti2, WN_PARM_BY_VALUE);
00588    kid1s[0]= master_variable;
00589    for (int i =0; i < extend_num; i++) {
00590      WN *op1;
00591      if (WN_operator(wn) == OPR_INTRINSIC_CALL) {
00592        op1 = WN_kid0(WN_kid(tmp_wn, pos[i]));
00593      } else {
00594        op1 = WN_kid0(WN_kid(WN_kid0(tmp_wn), pos[i]));
00595      }
00596      
00597      ST *st1;
00598      if (WN_has_sym(op1)) {
00599        st1 = WN_st(op1);
00600      } else {
00601        // parameter is an expression, don't extend it
00602        continue;
00603      }
00604      TY_IDX  ti1 = WN_ty(op1);
00605      TYPE_ID tm1 = TY_mtype(ti1);
00606      op1 = WN_CreateParm (Mtype_comparison (tm1), op1,
00607         ti1, WN_PARM_BY_VALUE);
00608      kid1s[1]= op1;
00609      WN *app1 = WN_Create_Intrinsic(OPR_INTRINSIC_OP,TY_mtype(ST_type(st1)), MTYPE_V, p->aux_id, aux_kid, kid1s);   
00610      WN *stmt1 = WN_Stid(TY_mtype(ST_type(st1)), ST_ofst(st1), st1, ST_type(st1), app1, 0);   
00611      WFE_Stmt_Append(stmt1, src);
00612   }
00613 }
00614 
00615 #endif
00616 
00617 
00618 #ifdef KEY
00619 static bool WFE_Call_Returns_Ptr_To_Member_Func (tree exp);
00620 
00621 static WN *WFE_Expand_Ptr_To_Member_Func_Call_Expr (tree exp,
00622        TY_IDX nop_ty_idx, TYPE_ID rtype, TYPE_ID desc,
00623        WN_OFFSET offset = 0, UINT field_id = 0);
00624 
00625 // The words in 'buf' are in target order. Convert them to host order
00626 // in place. 'buf' is a two word array.
00627 void
00628 WFE_Convert_To_Host_Order (long *buf)
00629 {
00630   if (!Same_Byte_Sex)
00631     {
00632       int t = buf[0];
00633       buf[0] = buf[1];
00634       buf[1] = t;
00635     }
00636 }
00637 
00638 // Add guard variable GUARD_VAR to a conditional expression that may or may
00639 // not be evaluated, such as x and y in "foo ? x : y", or y in "if (x && y)".
00640 // Transform the code to:
00641 //   guard_var=0
00642 //   foo ? (guard_var=1, x) : y   // assuming VALUE_WN is x
00643 // and:
00644 //   guard_var=0
00645 //   if (x && (guard_var=1, y))
00646 static void
00647 WFE_add_guard_var (tree guard_var, WN *value_wn)
00648 {
00649   WN *stid, *comma;
00650 
00651   // Set the guard variable to 0 before the condition is evaluated.
00652   WN *zero_wn = WN_Intconst(MTYPE_I4, 0);
00653   stid = WN_Stid(MTYPE_I4, 0, Get_ST(guard_var), MTYPE_To_TY(MTYPE_I4),
00654      zero_wn, 0);
00655   WFE_Stmt_Append(stid, Get_Srcpos());
00656 
00657   // Set the guard variable to 1 while evaluating the value of the conditional
00658   // expression.
00659   WN *one_wn = WN_Intconst(MTYPE_I4, 1);
00660   stid = WN_Stid(MTYPE_I4, 0, Get_ST(guard_var), MTYPE_To_TY(MTYPE_I4),
00661      one_wn, 0);
00662   if (WN_operator(value_wn) == OPR_COMMA) {
00663     comma = value_wn;
00664   } else if (WN_operator(WN_kid0(value_wn)) == OPR_COMMA) {
00665     comma = WN_kid0(value_wn);
00666   } else {
00667     // Create a comma.
00668     WN *wn0 = WN_CreateBlock();
00669     WN *wn1 = WN_kid0(value_wn);
00670     WN_Set_Linenum (wn0, Get_Srcpos());
00671     comma = WN_CreateComma (OPR_COMMA, WN_rtype(wn1), MTYPE_V, wn0, wn1);
00672     WN_kid0(value_wn) = comma;
00673   }
00674   WN *wn = WN_kid0(comma);
00675   FmtAssert(WN_operator(wn) == OPR_BLOCK,
00676     ("WFE_add_guard_var: unexpected WN operator"));
00677   WN_INSERT_BlockFirst(wn, stid);
00678 }
00679 #endif
00680 
00681 // check whether the WHIRL operator has subsumed cvtl in its semantics
00682 // (intended only for integer operations)
00683 bool
00684 Has_Subsumed_Cvtl(OPERATOR opr)
00685 {
00686   if (OPERATOR_is_load(opr) || OPERATOR_is_leaf(opr))
00687     return TRUE;
00688   if (opr == OPR_CVT || opr == OPR_CVTL || opr == OPR_TAS)
00689     return TRUE;
00690   if (opr == OPR_EQ || opr == OPR_NE ||
00691       opr == OPR_GE || opr == OPR_GT ||
00692       opr == OPR_LE || opr == OPR_LT ||
00693       opr == OPR_LNOT || opr == OPR_LAND || opr == OPR_LIOR ||
00694       opr == OPR_CAND || opr == OPR_CIOR)
00695     return TRUE;
00696   return FALSE;
00697 }
00698 
00699 // Round up an object size to the size it would require in the parameter
00700 // area on the stack.  This is defined to be the difference between its
00701 // start address and the lowest possible starting address of the next parameter.
00702 inline UINT64 Parameter_Size(UINT64 sz)
00703 {
00704 #   if WORDS_BIG_ENDIAN
00705   return sz;
00706 #   else
00707   return (sz + UNITS_PER_WORD - 1) & ~(UNITS_PER_WORD - 1);
00708 #   endif
00709 }
00710 
00711 inline TYPE_ID
00712 Widen_Mtype (TYPE_ID t)
00713 {
00714   if (MTYPE_is_m(t))
00715     return t;
00716   if (MTYPE_is_void(t) || t == MTYPE_BS) {
00717     Fail_FmtAssertion ("Widen_Mtype: for MTYPE_V or MTYPE_BS");
00718     return t;
00719   }
00720   if (MTYPE_byte_size(t) >= 4)
00721     return t;
00722   return Mtype_TransferSize(MTYPE_I4, t);
00723 }
00724 
00725 // Traverse the tree to see if the address of a variable is being taken
00726 
00727 void
00728 WFE_Set_ST_Addr_Saved (WN *wn)
00729 {
00730   OPERATOR  Operator;
00731   ST       *st;
00732 
00733   Operator = WN_operator (wn);
00734 
00735   switch ( Operator ) {
00736 
00737     case OPR_LDA:
00738     case OPR_LDMA:
00739 
00740       st = WN_st (wn);
00741 
00742       if (ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_FUNC)
00743         Set_ST_addr_saved (st);
00744       break;
00745 
00746     case OPR_ARRAY:
00747 
00748       WFE_Set_ST_Addr_Saved (WN_kid0 (wn));
00749       break;
00750 
00751     case OPR_LDID:
00752 
00753       st = WN_st (wn);
00754       if (ST_pt_to_unique_mem (st))
00755         Clear_ST_pt_to_unique_mem (st);
00756       break;
00757 
00758     case OPR_CONST:
00759     case OPR_ILOAD:
00760     case OPR_MLOAD:
00761     case OPR_INTCONST:
00762     case OPR_INTRINSIC_OP:
00763     case OPR_CALL:
00764     case OPR_EQ:
00765     case OPR_NE:
00766     case OPR_GT:
00767     case OPR_GE:
00768     case OPR_LT:
00769     case OPR_LE:
00770     case OPR_ALLOCA:
00771       break;
00772 
00773     case OPR_EVAL:
00774     case OPR_TAS:
00775     case OPR_CVT:
00776     case OPR_CVTL:
00777     case OPR_NEG:
00778     case OPR_ABS:
00779     case OPR_SQRT:
00780     case OPR_REALPART:
00781     case OPR_IMAGPART:
00782     case OPR_PAREN:
00783     case OPR_RND:
00784     case OPR_TRUNC:
00785     case OPR_CEIL:
00786     case OPR_FLOOR:
00787     case OPR_BNOT:
00788     case OPR_LNOT:
00789     case OPR_LOWPART:
00790     case OPR_HIGHPART:
00791     case OPR_MINPART:
00792     case OPR_MAXPART:
00793     case OPR_RECIP:
00794     case OPR_RSQRT:
00795     case OPR_PARM:
00796     case OPR_EXTRACT_BITS:
00797 
00798       WFE_Set_ST_Addr_Saved (WN_kid0(wn));
00799       break;
00800 
00801     case OPR_CSELECT:
00802 
00803       WFE_Set_ST_Addr_Saved (WN_kid1(wn));
00804       WFE_Set_ST_Addr_Saved (WN_kid2(wn));
00805       break;
00806 
00807     case OPR_SELECT:
00808     case OPR_ADD:
00809     case OPR_SUB:
00810     case OPR_MPY:
00811     case OPR_DIV:
00812     case OPR_MOD:
00813     case OPR_REM:
00814     case OPR_DIVREM:
00815     case OPR_MAX:
00816     case OPR_MIN:
00817     case OPR_MINMAX:
00818     case OPR_BAND:
00819     case OPR_BIOR:
00820     case OPR_BXOR:
00821     case OPR_BNOR:
00822     case OPR_LAND:
00823     case OPR_LIOR:
00824     case OPR_SHL:
00825     case OPR_ASHR:
00826     case OPR_LSHR:
00827     case OPR_COMPLEX:
00828     case OPR_HIGHMPY:
00829     case OPR_RROTATE:
00830     case OPR_COMPOSE_BITS:
00831 
00832       WFE_Set_ST_Addr_Saved (WN_kid0(wn));
00833       WFE_Set_ST_Addr_Saved (WN_kid1(wn));
00834       break;
00835 
00836     case OPR_CAND:
00837     case OPR_CIOR:
00838 
00839       break;
00840 
00841     case OPR_COMMA:
00842 
00843       WFE_Set_ST_Addr_Saved (WN_kid1(wn));
00844       break;
00845 
00846     case OPR_RCOMMA:
00847 
00848       WFE_Set_ST_Addr_Saved (WN_kid0(wn));
00849       break;
00850 
00851     default:
00852 
00853       DevWarn ("WFE_Set_ST_Addr_Saved not implemented");
00854   }
00855 } /* WFE_Set_ST_Addr_Saved */
00856 
00857 #ifndef GPLUSPLUS_FE
00858 typedef struct wfe_bind_expr_t {
00859   tree  rtl_expr;
00860   WN   *block;
00861 } WFE_BIND_EXPR;
00862 
00863 WFE_BIND_EXPR *wfe_bind_expr_stack       = NULL;
00864 INT32          wfe_bind_expr_stack_last  = -1;
00865 INT32          wfe_bind_expr_stack_max   = 0;
00866 
00867 void
00868 WFE_Expand_Start_Stmt_Expr (tree t)
00869 {
00870   WN *block = WN_CreateBlock ();
00871   WFE_Stmt_Push (block, wfe_stmk_comma, Get_Srcpos ());
00872 } /* WFE_Start_Stmt_Expr */
00873 
00874 void
00875 WFE_Expand_End_Stmt_Expr (tree t)
00876 {
00877   WN *block = WFE_Stmt_Pop (wfe_stmk_comma);
00878   ++wfe_bind_expr_stack_last;
00879   if (wfe_bind_expr_stack_last == wfe_bind_expr_stack_max) {
00880     if (wfe_bind_expr_stack == NULL) {
00881       wfe_bind_expr_stack_max = 32;
00882       wfe_bind_expr_stack     =
00883         (WFE_BIND_EXPR *) malloc (wfe_bind_expr_stack_max *
00884                                   sizeof (WFE_BIND_EXPR));
00885     }
00886     else {
00887       wfe_bind_expr_stack_max = wfe_bind_expr_stack_max +
00888                                 (wfe_bind_expr_stack_max >> 1);
00889       wfe_bind_expr_stack     =
00890         (WFE_BIND_EXPR *) realloc (wfe_bind_expr_stack,
00891                                    wfe_bind_expr_stack_max *
00892                                    sizeof (WFE_BIND_EXPR));
00893     }
00894   }
00895   wfe_bind_expr_stack [wfe_bind_expr_stack_last].rtl_expr = t;
00896   wfe_bind_expr_stack [wfe_bind_expr_stack_last].block    = block;
00897 } /* WFE_End_Stmt_Expr */
00898 #endif /* GPLUSPLUS_FE */
00899 
00900 typedef struct wfe_save_expr_t {
00901   tree  exp;
00902   ST   *st;
00903 #ifdef KEY
00904   INT32  level; // to identify which cleanup the save expr belongs to
00905 #endif
00906 } WFE_SAVE_EXPR;
00907 
00908 WFE_SAVE_EXPR *wfe_save_expr_stack      = NULL;
00909 INT32          wfe_save_expr_stack_last = -1;
00910 INT32          wfe_save_expr_stack_max  = 0;
00911 
00912 #ifdef KEY
00913 INT32 wfe_save_expr_level;  // identify the current cleanup
00914 INT32 wfe_last_save_expr_level; // the last cleanup level used
00915 #endif
00916 
00917 static WN*
00918 WFE_Save_Expr (tree save_exp,
00919                bool need_result,
00920                TY_IDX nop_ty_idx,
00921                TY_IDX component_ty_idx,
00922                INT64 component_offset,
00923                UINT16 field_id)
00924 {
00925   INT32     i;
00926   tree      exp     = TREE_OPERAND (save_exp, 0);
00927   TY_IDX    ty_idx  = Get_TY (TREE_TYPE (exp));
00928   TYPE_ID   mtype   = TY_mtype (ty_idx);
00929   ST       *st;
00930   WN       *wn;
00931   bool     found = false;  
00932 
00933   for (i = wfe_save_expr_stack_last; i >= 0; i--) {
00934 #ifndef KEY
00935     if (wfe_save_expr_stack [i].exp == exp) {
00936 #else
00937     if (wfe_save_expr_stack [i].exp == save_exp &&
00938       wfe_save_expr_stack [i].level == wfe_save_expr_level) {
00939 #endif
00940       st = wfe_save_expr_stack [i].st;
00941       FmtAssert (st != 0,
00942                  ("WFE_Save_Expr: st not yet assigned"));
00943       found = true;
00944       break;
00945     }
00946   }
00947   
00948   if (!found) {
00949     i = ++wfe_save_expr_stack_last;
00950     if (i == wfe_save_expr_stack_max) {
00951       if (wfe_save_expr_stack == NULL) {
00952         wfe_save_expr_stack_max = 32;
00953         wfe_save_expr_stack     =
00954           (WFE_SAVE_EXPR *) malloc (wfe_save_expr_stack_max *
00955                                     sizeof (WFE_SAVE_EXPR));
00956       }
00957       else {
00958         wfe_save_expr_stack_max = wfe_save_expr_stack_max +
00959                                   (wfe_save_expr_stack_max >> 1);
00960         wfe_save_expr_stack     =
00961           (WFE_SAVE_EXPR *) realloc (wfe_save_expr_stack,
00962                                      wfe_save_expr_stack_max *
00963                                      sizeof (WFE_SAVE_EXPR));
00964       }
00965     }
00966 #ifndef KEY
00967     wfe_save_expr_stack [i].exp = exp;
00968 #else
00969     wfe_save_expr_stack [i].exp = save_exp;
00970     wfe_save_expr_stack [i].level = wfe_save_expr_level;
00971 #endif
00972     wfe_save_expr_stack [i].st  = 0;
00973 #ifdef KEY
00974     // If exp is a CALL_EXPR that returns a ptr-to-member-function, then call
00975     // WFE_Expand_Ptr_To_Member_Func_Call_Expr to expand it.  Otherwise, call
00976     // WFE_Expand_Expr to do regular expansion.  Bug 3400.
00977     if (WFE_Call_Returns_Ptr_To_Member_Func(exp)) {
00978       TYPE_ID desc = TY_mtype(Get_TY(TREE_TYPE(exp)));
00979       wn = WFE_Expand_Ptr_To_Member_Func_Call_Expr(exp, nop_ty_idx,
00980                Widen_Mtype(desc), desc);
00981     } else
00982 #endif
00983     wn = WFE_Expand_Expr (exp);
00984 
00985     st = Gen_Temp_Symbol (ty_idx, "__save_expr");
00986 #ifdef KEY
00987     WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
00988 #endif
00989     WFE_Set_ST_Addr_Saved (wn);
00990     wn = WN_Stid (mtype, 0, st, ty_idx, wn);
00991     WFE_Stmt_Append (wn, Get_Srcpos());
00992     wfe_save_expr_stack [i].st = st;
00993   }
00994 
00995   if (component_ty_idx == 0)
00996     wn = WN_Ldid (mtype, 0, st, ty_idx);
00997   else {
00998     TYPE_ID desc  = TY_mtype(component_ty_idx);
00999     TYPE_ID rtype = Widen_Mtype(desc);
01000     wn = WN_CreateLdid(OPR_LDID, rtype, desc, component_offset, st,
01001          field_id? ty_idx : component_ty_idx, field_id);  
01002   }
01003   return wn;
01004 } /* WFE_Save_Expr */
01005 
01006 /* process the tree doing array indicing and return the WN that performs
01007  * the address computation; ty_idx returns the high-level array type if it
01008  * is a DECL node, and the element type if it is an ARRAY_REF node.
01009  */
01010 static WN *
01011 WFE_Array_Expr(tree exp, 
01012          TY_IDX *ty_idx, 
01013          TY_IDX component_ty_idx,
01014          INT64 component_offset,
01015          UINT32 field_id)
01016 {
01017   WN *wn;
01018   enum tree_code code = TREE_CODE (exp);
01019   if (code == COMPONENT_REF) {
01020     TY_IDX ty_idx0;
01021     tree arg0 = TREE_OPERAND(exp, 0); 
01022     tree arg1 = TREE_OPERAND(exp, 1); 
01023     if (component_ty_idx == 0)
01024       ty_idx0 = Get_TY(TREE_TYPE(exp));
01025     else ty_idx0 = component_ty_idx;
01026 #ifdef KEY // bug 10728
01027     if (TREE_THIS_VOLATILE(exp))
01028       Set_TY_is_volatile(ty_idx0);
01029 #endif
01030     Is_True(! DECL_BIT_FIELD(arg1),
01031       ("WFE_Array_Expr: address arithmetic cannot use bitfield addresses"));
01032     INT64 ofst = (BITSPERBYTE * Get_Integer_Value(DECL_FIELD_OFFSET(arg1)) +
01033         Get_Integer_Value(DECL_FIELD_BIT_OFFSET(arg1)))
01034             / BITSPERBYTE;
01035 #ifdef KEY
01036     // OSP_7, MODIFY_EXPR in ARRAY_REF
01037     // Refer GCC 4.0.2: gcc.c-torture/compile/struct-non-lval-3.c
01038     // We only handle this case so far:
01039     // (p = q).x[index]
01040     // the lhs of modify_expr is var_decl, not an expression
01041     // ARRAY_REF
01042     //     |---> MODIFY_EXPT
01043     if (TREE_CODE(arg0) == MODIFY_EXPR) {
01044       WFE_Expand_Expr(arg0);
01045       tree lhs = TREE_OPERAND(arg0, 0);
01046       Is_True (lhs != NULL && 
01047          (TREE_CODE(lhs) == VAR_DECL || TREE_CODE(lhs) == INDIRECT_REF),
01048           ("Unsupported lhs for `(p=q).x[n]'"));
01049       arg0 = lhs;
01050     }
01051 #endif
01052 
01053 #ifdef KEY // bug 9725: If the field is an array of struct, it is considered
01054            // a single field.
01055     return WFE_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
01056         DECL_FIELD_ID(arg1));
01057 #else
01058     return WFE_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
01059         field_id + DECL_FIELD_ID(arg1));
01060 #endif
01061   }
01062   else if (code == VAR_DECL || code == PARM_DECL) {
01063     ST *st = Get_ST (exp);
01064     ST *base_st = ST_base (st);
01065     // for VLAs the instead of using the ST use its base st
01066     // also for the time being do not support VLAs within structs
01067     if (st != base_st) {
01068       FmtAssert (component_ty_idx == 0,
01069                  ("Variable Length Arrays within struct not currently implemented"));
01070       wn = WN_Ldid (Pointer_Mtype, 0, base_st, ST_type (base_st));
01071     }
01072     else
01073       wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01074     if (component_ty_idx == 0)
01075       *ty_idx = ST_type(st);
01076     else {
01077       *ty_idx = component_ty_idx;
01078       if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01079   Set_TY_align(*ty_idx, TY_align(ST_type(st)));//pick more stringent align
01080     }
01081     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01082       ("WFE_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01083     return wn;
01084   }
01085   else if (code == CONSTRUCTOR) {
01086     ST *st = WFE_Generate_Temp_For_Initialized_Aggregate (exp, "");
01087     wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01088     if (component_ty_idx == 0)
01089       *ty_idx = ST_type(st);
01090     else *ty_idx = component_ty_idx;
01091     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01092       ("WFE_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01093     return wn;
01094   }
01095   else if (code == STRING_CST) {
01096     wn = WFE_Expand_Expr(exp);
01097     *ty_idx = ST_type (TREE_STRING_ST (exp));
01098     return wn;
01099   }
01100   else if (code == INDIRECT_REF) {
01101     wn = WFE_Expand_Expr(TREE_OPERAND (exp, 0));
01102     if (component_ty_idx == 0)
01103       *ty_idx = Get_TY (TREE_TYPE(exp));
01104     else {
01105       *ty_idx = component_ty_idx;
01106       INT node_align = TYPE_ALIGN(TREE_TYPE(exp)) / BITSPERBYTE;
01107       if (node_align < TY_align(component_ty_idx))
01108   Set_TY_align(*ty_idx, node_align);//pick more stringent align
01109     }
01110     if (component_offset != 0) { // TODO: use ILDA instead
01111       WN *wn0 = WN_Intconst(MTYPE_I4, component_offset);
01112       wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn, wn0);
01113     }
01114     return wn;
01115   }
01116   else if (code == CALL_EXPR) {
01117     wn = WFE_Expand_Expr(exp);
01118     FmtAssert (WN_opcode (wn) == OPC_MCOMMA,
01119                ("opcode other than OPC_MCOMMA for call underneath ARRAY_REF"));
01120     WFE_Stmt_Append (WN_kid0 (wn), Get_Srcpos ());
01121     ST *st = WN_st (WN_kid1 (wn));
01122     WN_Delete (WN_kid1 (wn));
01123     WN_Delete (wn);
01124     wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01125     if (component_ty_idx == 0)
01126       *ty_idx = ST_type(st);
01127     else {
01128       *ty_idx = component_ty_idx;
01129       if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01130   Set_TY_align(*ty_idx, TY_align(ST_type(st)));//pick more stringent align
01131     }
01132     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01133       ("WFE_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01134     return wn;
01135   }
01136   else if (code == ARRAY_REF) { // recursive call
01137     WN *wn0, *wn1, *wn2;
01138     TY_IDX ty_idx0;
01139 #ifdef KEY  // Bug 5831.
01140     wn0 = WFE_Array_Expr(TREE_OPERAND (exp, 0), &ty_idx0, 0,
01141        component_offset, field_id);
01142 #else
01143     wn0 = WFE_Array_Expr(TREE_OPERAND (exp, 0), &ty_idx0, component_ty_idx,
01144        component_offset, field_id);
01145 #endif
01146     Is_True(TY_kind(ty_idx0) == KIND_ARRAY,
01147       ("WFE_Array_Expr: arg 0 of ARRAY_REF not of type KIND_ARRAY"));
01148     ARB_HANDLE arb = TY_arb(ty_idx0);
01149     if (ARB_dimension(arb) == 1 && 
01150   ARB_first_dimen(arb) && ARB_last_dimen(arb) &&
01151   ARB_const_lbnd(arb)) {
01152       if (ARB_const_ubnd(arb))
01153         wn1 = WN_Intconst(MTYPE_I4, ARB_ubnd_val(arb) - ARB_lbnd_val(arb) + 1);
01154 #ifdef KEY
01155       // Variable upper bound.  Bug 4692.
01156       else if (ARB_ubnd_var(arb)) {
01157         ST *ubnd_st = &St_Table[ARB_ubnd_var(arb)];
01158   wn1 = WN_Binary(OPR_SUB, MTYPE_I4,
01159       WN_Ldid(MTYPE_I4, 0, ubnd_st, ST_type(ubnd_st)),
01160       WN_Intconst(MTYPE_I4, ARB_lbnd_val(arb) - 1));
01161       }
01162 #endif
01163       else
01164         wn1 = WN_Intconst(MTYPE_I4, 0);
01165       wn2 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
01166 #ifdef TARG_X8664 // bug 11705
01167       if (WN_operator(wn2) == OPR_SUB)
01168         WN_set_rtype(wn2, Mtype_TransferSign(MTYPE_I4, WN_rtype(wn2)));
01169 #endif
01170 #ifdef KEY // bug 14871, OSP_455
01171       if (TARGET_64BIT && OPCODE_is_load(WN_opcode(wn2)))
01172         WN_set_rtype(wn2, Mtype_TransferSize(MTYPE_U8, WN_rtype(wn2)));
01173 #endif
01174 #ifdef KEY
01175       // Expand the current dimension by growing the array just expanded.  Bug
01176       // 4692.
01177       if (TREE_CODE(TREE_OPERAND(exp, 0)) == ARRAY_REF) {
01178         Is_True(WN_operator(wn0) == OPR_ARRAY,
01179     ("WFE_Array_Expr: ARRAY_REF not translated to OPR_ARRAY"));
01180   int old_kid_count = WN_kid_count(wn0);
01181   int new_kid_count = old_kid_count + 2;
01182   wn = WN_Create(OPR_ARRAY, Pointer_Mtype, MTYPE_V, new_kid_count);
01183   for (int kid = 0; kid < (old_kid_count >> 1); kid++) {
01184     WN_kid(wn, kid + 1) = WN_kid(wn0, kid + 1);
01185     WN_kid(wn, (new_kid_count >> 1) + kid + 1) =
01186       WN_kid(wn0, (old_kid_count >> 1) + kid + 1);
01187   }
01188   WN_kid(wn, 0) = WN_kid(wn0, 0);
01189   WN_kid(wn, new_kid_count >> 1) = wn1;
01190   WN_kid(wn, new_kid_count - 1) = wn2;
01191   WN_Delete(wn0);
01192       } else
01193 #endif
01194       wn = WN_Ternary(OPR_ARRAY, Pointer_Mtype, wn0, wn1, wn2);
01195 
01196       WN_element_size(wn) = TY_size(Get_TY (TREE_TYPE(exp)));
01197     }
01198     else Is_True(FALSE,
01199      ("WFE_Array_Expr: only const-bounds 1-dimension arrays handled now"));
01200     if (component_ty_idx == 0) {
01201       *ty_idx = TY_etype(ty_idx0);
01202       if (TY_align(ty_idx0) < TY_align(*ty_idx))
01203   Set_TY_align(*ty_idx, TY_align(ty_idx0));// pick more stringent align
01204 #ifdef KEY // bug 10728
01205       if (TREE_THIS_VOLATILE(exp))
01206   Set_TY_is_volatile(*ty_idx);
01207 #endif
01208     }
01209     else *ty_idx = component_ty_idx;
01210     return wn;
01211   }
01212 #ifdef KEY
01213   else if (code == COMPOUND_LITERAL_EXPR) {
01214     tree arg0 = DECL_INITIAL (TREE_OPERAND (TREE_OPERAND (exp, 0), 0));
01215     ST *st = WFE_Generate_Temp_For_Initialized_Aggregate (arg0, "");
01216     wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
01217     *ty_idx = component_ty_idx == 0 ? ST_type(st) : component_ty_idx;
01218     return wn;
01219   } else if (code == TARGET_EXPR) {
01220     wn = WFE_Expand_Expr(exp);
01221     Is_True(WN_operator(wn) == OPR_LDID,
01222       ("WFE_Array_Expr: OPR_LDID not found"));
01223     ST *st = WN_st(wn);
01224     wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01225     if (component_ty_idx == 0)
01226       *ty_idx = ST_type(st);
01227     else {
01228       *ty_idx = component_ty_idx;
01229       if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01230   Set_TY_align(*ty_idx, TY_align(ST_type(st)));//pick more stringent align
01231     }
01232     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01233       ("WFE_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01234     return wn;
01235   }
01236 #endif /* KEY */
01237   else {
01238     Is_True(FALSE,
01239       ("WFE_Array_Expr: unsupported node for base of ARRAY_REF"));
01240     return NULL;
01241   }
01242 }
01243 
01244 /* access to different vbuf array need to adjust offset. Following function 
01245  * used as one general interface to adjust kinds of cases. It is far away from
01246  * finished. 
01247  */
01248 #if defined(TARG_SL)
01249 /* decide if the wn tree has LDA node and if the node has vbuf symbol. if so, we
01250  * need traverse the tree and return the ST symbol. 
01251  */ 
01252 ST*
01253 WN_Include_Vbuf_Symbol( WN* wn, BOOL need_initialize) {
01254   WN* tmp = wn;
01255   static ST* st = NULL;
01256   if(need_initialize) {
01257     st = NULL;
01258     need_initialize=FALSE;
01259   }
01260   for( INT i = 0; i < WN_kid_count(wn); i++) {
01261     if(WN_operator(WN_kid(wn,i)) != OPR_LDA) {
01262       st = WN_Include_Vbuf_Symbol(WN_kid(wn,i), need_initialize);
01263     }
01264     else {
01265       if(WN_has_sym(WN_kid(wn,i)) && ST_in_vbuf(WN_st(WN_kid(wn,i)))) {
01266   return WN_st(WN_kid(wn,i));
01267       }
01268     }
01269   }
01270   return st; 
01271 }
01272 
01273 /* do actual adjustment work, this function only needed for v2buf/v4buf */ 
01274  
01275 void
01276 WN_Adjust_Vbuf_Ofst(WN* wn, ST* st){
01277   INT shft_num = ST_in_v2buf(st) ? 1 : (ST_in_v4buf(st) ? 2 : 0);
01278   /* OPR_INTCONST && OPR_LDA has kid_count is zero */ 
01279   if(WN_operator(wn) == OPR_LDA) {
01280     Is_True(WN_has_sym(wn), ("this symbol don't has base address symbole"));
01281     Is_True(ST_in_vbuf(st), ("this symbol for adjusting offset is not vbuf variable"));
01282     /* __v2buf char array[5][4][16]
01283      * array[3][2][8] = value;
01284      * lda_offset equals 3*4*16+2*16+8 
01285      * the actual offset we need is (3*4*16 + 2*16)*2 + 8
01286      * so we need do seperate the lower dimension from higher dimension using formula:
01287      * 
01288      *       lda_offset = (((lda_offset/16)*16)<<shft_num) + lda_offset % 16;
01289      */
01290     // testing only adjust lda_offset in cgemit r_apply_l_const
01291     if(!WN_vbuf_ofst_adjusted(wn)) {
01292       WN_lda_offset(wn) = (((WN_lda_offset(wn) / 16) * 16) << shft_num ) \
01293   + (WN_lda_offset(wn) % 16);
01294       WN_Set_vbuf_ofst_adjusted(wn);
01295     }
01296     return;
01297   }
01298   else if(WN_operator(wn) == OPR_INTCONST) {
01299     if(WN_vbuf_ofst_adjusted(wn)) return;
01300     else {
01301       WN_const_val(wn) <<= shft_num;
01302       WN_Set_vbuf_ofst_adjusted(wn);
01303     }
01304     return;
01305   }
01306   else if(WN_kid_count(wn)) {
01307     for( INT i = 0; (i < WN_kid_count(wn) || !WN_kid_count(wn)); i++) {
01308       /* if there is sub-tree which has one type of above four, all addend and ofst 
01309        * in sub-tree must have been adjusted again, so we don't adjust twice. 
01310        */              
01311       
01312       if(WN_operator(wn) == OPR_STID ||
01313    WN_operator(wn) == OPR_LDID ||
01314    WN_operator(wn) == OPR_ISTORE || 
01315    WN_operator(wn) == OPR_ILOAD)
01316   continue;
01317       /* For operator array, kid1 means the size of the dimension 
01318        * we don't adjust this const value
01319        */
01320       else if(WN_operator(wn) == OPR_ARRAY && i == 1) {
01321   continue;
01322       }
01323 /* __v2buf char array[3][2][16]; 
01324  * ptr_2_v2buf = array[i][j]
01325  * ptr_2_v2buf = array + (i*2+j)*16*2
01326  *   U4LDA 0 <1,31,array> T<60,anon_ptr.,4>
01327  *     U4U4LDID 0 <2,2,j> T<8,.predef_U4,4>
01328  *      U4U4LDID 0 <2,1,i> T<8,.predef_U4,4>
01329  *      I4INTCONST 2 (0x2)  <=== don't adjust this const 
01330  *     U4MPY
01331  *    U4ADD
01332  *    U4INTCONST 32 (0x20)  <== only adjust this const 
01333  *   U4MPY
01334  *  U4ADD
01335  * U4STID 0 <1,35,ptr2> T<55,anon_ptr.,4>
01336  */
01337       else if(WN_operator(wn) == OPR_MPY)
01338         {
01339           continue;
01340         }
01341 /*__v4buf char b4_mv[16]
01342  * 
01343  *    I4I4LDID 0 <2,9,i0> T<4,.predef_I4,4>
01344  *      I4I4LDID 0 <2,10,j0> T<4,.predef_I4,4>
01345  *      I4INTCONST 2 (0x2)   <==== don't adjust this constant
01346  *     I4SHL
01347  *    I4ADD
01348  *   U4I4CVT
01349  *  U4LDA 0 <1,31,b4_mv> T<57,anon_ptr.,4>
01350  * U4ADD
01351  */
01352       else if(WN_operator(wn) == OPR_SHL) {
01353            continue;
01354   }
01355       else {
01356   WN_Adjust_Vbuf_Ofst(WN_kid(wn,i), st);
01357       }
01358     }
01359     return;
01360   }
01361   return;
01362 }
01363 
01364 
01365 WN* 
01366 Shft_Vbuf_Array_Ofst(WN* wn, INT shft_num = 0) {
01367   if(WN_operator(wn) == OPR_INTCONST) {
01368     WN_const_val(wn) <<= shft_num;
01369   }
01370   else if(WN_operator(wn) == OPR_LDA) {
01371     WN_lda_offset(wn) <<= shft_num;
01372   } 
01373   return wn;
01374 }
01375 
01376 WN* 
01377 Adjust_Vbuf_Array_Ofst(WN* wn) {
01378   Is_True((WN_operator(wn) == OPR_STID ||
01379           WN_operator(wn) == OPR_LDID || 
01380           WN_operator(wn) == OPR_ISTORE || 
01381           WN_operator(wn) == OPR_ILOAD ||
01382           WN_operator(wn) == OPR_PARM) , 
01383           ( " invalid operator for adjusting vbuf ofst"));
01384   ST* st = WN_Include_Vbuf_Symbol(wn, TRUE); 
01385   /* compiler only adjust v2buf and v4buf variable */
01386   if(!st || ! (ST_in_v2buf(st) || ST_in_v4buf(st))) return wn;
01387 
01388        /* case 1:
01389         *    __v2buf char array[4][10][16];
01390         *    __v2buf char * ptr;
01391         *    ptr = array[4][6];
01392         */
01393   for( INT i = 0; i < WN_kid_count(wn); i++) {
01394     WN_Adjust_Vbuf_Ofst(WN_kid(wn,i), st);
01395   }
01396   return wn;
01397 }
01398 #endif 
01399 #ifdef TARG_SL
01400 /* Same_Var: 
01401  *      To check whether tree (rhs) contains the reference
01402  *      to the variable with the same name as var_name
01403  */
01404 static BOOL sameness;
01405 static BOOL Same_Var( char* var_name, tree rhs )
01406 {
01407   if (!rhs) {
01408      DevWarn("Same_Var::rhs is NULL");
01409      return FALSE;
01410   }
01411 
01412   /* put the constant tree nodes here.
01413    */
01414   if( TREE_CODE_CLASS(TREE_CODE(rhs)) == 'c' )
01415     return FALSE;
01416 
01417   /* I dont want to handle component reference, it's
01418    * too complicated.
01419    * //TODO
01420    */
01421   if( TREE_CODE(rhs) == COMPONENT_REF )
01422     return FALSE;
01423 
01424   BOOL tempsame = FALSE;
01425   /* check if the names are the same.
01426    * I'm very sorry, since there is no traversing function for
01427    * gcc AST tree. So this code segment is very ugly
01428    */
01429   switch( TREE_CODE(rhs) ) {
01430     case VAR_DECL :
01431       if( DECL_NAME(rhs) && !strcmp(var_name,IDENTIFIER_POINTER(DECL_NAME(rhs))))
01432         return TRUE;
01433       else
01434         return FALSE;
01435     case PARM_DECL:
01436       if( DECL_NAME(rhs) && !strcmp(var_name,IDENTIFIER_POINTER(DECL_NAME(rhs))))
01437         return TRUE;
01438       else if( TREE_CHAIN(rhs) ) 
01439           tempsame |= Same_Var( var_name, TREE_CHAIN(rhs) );
01440       else
01441         return FALSE;
01442       break;
01443     case FUNCTION_DECL:
01444       tempsame |= Same_Var( var_name, DECL_ARGUMENTS(rhs) );
01445       break;
01446     case INDIRECT_REF:
01447       /* Like the treatment of l.h.s, we only treat the simple case,
01448        * where *p with p being a parm_decl or var_decl
01449        */
01450       if( TREE_CODE(TREE_OPERAND(rhs,0))==PARM_DECL ||
01451           TREE_CODE(TREE_OPERAND(rhs,0))==VAR_DECL ) {
01452         tempsame |= Same_Var( var_name, TREE_OPERAND(rhs,0) );
01453       } else
01454         return FALSE;
01455     default:
01456       if( TREE_OPERAND(rhs,0) )
01457         tempsame |= Same_Var( var_name, TREE_OPERAND(rhs,0) );
01458       if( TREE_OPERAND(rhs,1) )
01459         tempsame |= Same_Var( var_name, TREE_OPERAND(rhs,1) );
01460       break;
01461   }
01462   /* I dont know how to get all the kids of a tree node,
01463    * but I use the common case : each node has only two kids
01464    */
01465  
01466   return tempsame;
01467 } 
01468 #endif
01469 
01470 
01471 
01472 /* rhs_wn is the WN representing the rhs of a MODIFY_EXPR node; this
01473  * routine processes the lhs of the node and generate the appropriate
01474  * form of store.
01475  *
01476  * In special cases where the RHS of the store is unknown but the
01477  * statement being expanded is nonetheless semantically a store,
01478  * rhs_wn can be NULL. This happens, for example, for each output
01479  * operand of an asm statement. When rhs_wn is NULL, we manufacture an
01480  * RHS that is an LDID of a PREG specified by rhs_preg_num (generally
01481  * a negative-numbered PREG). If rhs_st is non-NULL, rhs_preg_num is
01482  * ignored.  assign_code tells if it is {PRE,POST}{IN,DE}CREMENT_EXPR.
01483  * Ordinarily, it is MODIFY_EXPR.
01484  */
01485 WN *
01486 WFE_Lhs_Of_Modify_Expr(tree_code assign_code,
01487            tree lhs, 
01488 #ifdef TARG_SL
01489                        /* To make consistent with gcc on some
01490                         * undefined behavior: *p++=...
01491                         */
01492                        tree rhs,
01493 #endif
01494            bool need_result,
01495            TY_IDX component_ty_idx, 
01496            INT64 component_offset,
01497            UINT32 field_id,
01498            bool is_bit_field,
01499            WN *rhs_wn,
01500            PREG_NUM rhs_preg_num,
01501            bool is_realpart,
01502            bool is_imagpart)
01503 {
01504   WN *wn = NULL;
01505   ST *st;
01506   bool result_in_temp = FALSE;
01507   ST *result_preg_st;
01508   PREG_NUM result_preg;
01509   PREG_NUM lhs_preg_num = 0;
01510   enum tree_code code = TREE_CODE (lhs);
01511   BOOL volt = FALSE;
01512 #ifdef TARG_SL
01513   BOOL need_append = FALSE;
01514 #endif
01515   if (rhs_wn != NULL) {
01516     WFE_Set_ST_Addr_Saved (rhs_wn);
01517 #ifdef TARG_SL  
01518     need_append = WN_Need_Append_Intrinsic(rhs_wn); 
01519 #endif
01520   }
01521 
01522   switch (code) {
01523   case COMPONENT_REF:
01524     {
01525       INT64 ofst;
01526       TY_IDX ty_idx0;
01527 
01528       tree arg0 = TREE_OPERAND(lhs, 0);
01529       tree arg1 = TREE_OPERAND(lhs, 1);
01530 #ifdef GPLUSPLUS_FE
01531       // for g++ ensure that the WHIRL type for the enclosing structure has been
01532       // created in order to set the field id to a non zero value
01533       (void) Get_TY (TREE_TYPE (arg0));
01534 #endif /* GPLUSPLUS_FE */
01535       if (component_ty_idx == 0)
01536         ty_idx0 = Get_TY(TREE_TYPE(lhs));
01537       else ty_idx0 = component_ty_idx;
01538       if (DECL_BIT_FIELD(arg1)) 
01539         is_bit_field = TRUE;
01540       if (! is_bit_field)
01541         ofst = (BITSPERBYTE * Get_Integer_Value(DECL_FIELD_OFFSET(arg1)) +
01542             Get_Integer_Value(DECL_FIELD_BIT_OFFSET(arg1)))
01543           / BITSPERBYTE;
01544       else ofst = 0;
01545 #ifdef KEY    // bug 10422: check if the field is volatile
01546       if (TREE_THIS_VOLATILE(arg1)) {
01547   Set_TY_is_volatile(ty_idx0);
01548   volt = TRUE;
01549       }
01550 #endif
01551 #ifdef KEY
01552       FmtAssert (DECL_FIELD_ID(arg1) != 0,
01553                  ("WFE_Lhs_Of_Modify_Expr: DECL_FIELD_ID used but not set"));
01554 #endif
01555 #ifdef TARG_SL
01556       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0, 
01557 #else
01558       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, need_result, ty_idx0, 
01559 #endif
01560           ofst+component_offset,
01561                 field_id + DECL_FIELD_ID(arg1), is_bit_field, 
01562           rhs_wn, rhs_preg_num, is_realpart,
01563           is_imagpart);
01564     }
01565     return wn;
01566 
01567   case REALPART_EXPR:
01568     {
01569       tree arg0 = TREE_OPERAND(lhs, 0);
01570       TY_IDX ty_idx0 = Get_TY(TREE_TYPE(arg0));
01571 #ifdef TARG_SL
01572       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0,
01573 #else
01574       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, need_result, ty_idx0,
01575 #endif
01576           component_offset, field_id, is_bit_field,
01577           rhs_wn, rhs_preg_num, TRUE, FALSE);
01578     }
01579     return wn;
01580 
01581   case IMAGPART_EXPR:
01582     {
01583       tree arg0 = TREE_OPERAND(lhs, 0);
01584       TY_IDX ty_idx0 = Get_TY(TREE_TYPE(arg0));
01585 #ifdef TARG_SL
01586       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0,
01587 #else
01588       wn = WFE_Lhs_Of_Modify_Expr(assign_code, arg0, need_result, ty_idx0,
01589 #endif
01590           component_offset, field_id, is_bit_field,
01591           rhs_wn, rhs_preg_num, FALSE, TRUE);
01592     }
01593     return wn;
01594 
01595 #ifdef KEY
01596   case TARGET_EXPR: // bug 6907
01597     {
01598       WN *wn = WFE_Expand_Expr(lhs);
01599       Is_True(WN_operator(wn) == OPR_LDID,
01600         ("WFE_Lhs_Of_Modify_Expr: wrong operator from TARGET_EXPR"));
01601       st = WN_st(wn);
01602     }
01603     // fall through
01604 #endif
01605 
01606   case PARM_DECL:
01607   case VAR_DECL:
01608   case RESULT_DECL:
01609     {
01610       TY_IDX hi_ty_idx = Get_TY(TREE_TYPE(lhs)); // type associated with field_id
01611       if (TREE_THIS_VOLATILE(lhs)) {
01612         Set_TY_is_volatile(hi_ty_idx);
01613         volt = TRUE;
01614       }
01615       TY_IDX desc_ty_idx = component_ty_idx;
01616       if (desc_ty_idx == 0)
01617         desc_ty_idx = hi_ty_idx;
01618       if (TY_is_volatile(desc_ty_idx)) {
01619         Clear_TY_is_volatile(desc_ty_idx);
01620         volt = TRUE;
01621       }
01622 
01623 #ifdef KEY
01624       if (code != TARGET_EXPR)
01625 #endif
01626       st = Get_ST (lhs);
01627 
01628       if (ST_assigned_to_dedicated_preg (st)) {
01629         Set_TY_is_volatile(hi_ty_idx);
01630         volt = TRUE;
01631       }
01632       Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
01633         ("WFE_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
01634 
01635       TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
01636       TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
01637 
01638       if (rhs_wn == NULL) {
01639         // Manufacture a negative-PREG RHS for the STID we are about to
01640         // generate. This feature is used in preparing WHIRL ASM
01641         // statements.
01642         // TODO: How to support a bit-field output of non-integral
01643         // number of bytes?
01644         if (rtype == MTYPE_M && desc == MTYPE_M) {
01645 #ifndef KEY
01646           FmtAssert(TY_size(desc_ty_idx) == MTYPE_byte_size(Def_Int_Mtype),
01647                     ("Size of ASM struct opnd must be equal to register size"));
01648           desc = rtype = Def_Int_Mtype;
01649           desc_ty_idx = hi_ty_idx = MTYPE_To_TY(Def_Int_Mtype);
01650 #else
01651     // Handle asm like:
01652     //        asm("cfc1 %0,$31":"=r"(*s));
01653     // where, s is a pointer to a structure.
01654     if (rtype == MTYPE_M && desc == MTYPE_M) {
01655       if (TY_size(desc_ty_idx) == MTYPE_byte_size(Def_Int_Mtype)) {
01656         desc = rtype = Def_Int_Mtype;
01657         desc_ty_idx = hi_ty_idx = MTYPE_To_TY(Def_Int_Mtype);
01658       } else {
01659         desc = rtype = MTYPE_I4;
01660         desc_ty_idx = hi_ty_idx = MTYPE_To_TY(MTYPE_I4);
01661       }
01662     }
01663 #endif
01664         }
01665         ST *rhs_st = MTYPE_To_PREG(desc);
01666         rhs_wn = WN_CreateLdid (OPR_LDID, rtype,
01667               desc, rhs_preg_num, rhs_st,
01668               desc_ty_idx, 0);
01669       }
01670       else {
01671         WN *result_wn;  // the result wn to be returned
01672         if (assign_code == MODIFY_EXPR) {
01673     if (is_realpart)
01674       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01675              rhs_wn,
01676              WN_Unary(OPR_IMAGPART,
01677                 Mtype_complex_to_real (rtype),
01678                 WN_CreateLdid(OPR_LDID, rtype, desc,
01679                   ST_ofst(st) + component_offset,
01680                   st, hi_ty_idx, field_id)));
01681     else
01682     if (is_imagpart)
01683       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01684              WN_Unary(OPR_REALPART,
01685                 Mtype_complex_to_real (rtype),
01686                 WN_CreateLdid(OPR_LDID, rtype, desc,
01687                   ST_ofst(st) + component_offset,
01688                   st, hi_ty_idx, field_id)),
01689              rhs_wn);
01690         }
01691         else {
01692     if (is_realpart)
01693       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01694              rhs_wn,
01695              WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
01696     else
01697     if (is_imagpart)
01698       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01699              WN_Floatconst (Mtype_complex_to_real (rtype), 0.0),
01700              rhs_wn);
01701         }
01702 
01703         if (assign_code == PREINCREMENT_EXPR ||
01704       assign_code == PREDECREMENT_EXPR) {
01705           wn = WN_CreateLdid (OPR_LDID, rtype, desc, 
01706             ST_ofst(st) + component_offset,
01707             st, hi_ty_idx, field_id);
01708           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01709                  rtype, wn, rhs_wn);
01710     result_wn = rhs_wn;
01711         }
01712         else if (assign_code == POSTINCREMENT_EXPR ||
01713            assign_code == POSTDECREMENT_EXPR) {
01714           result_wn = WN_CreateLdid (OPR_LDID, rtype, desc, 
01715              ST_ofst(st) + component_offset,
01716              st, hi_ty_idx, field_id);
01717         }
01718         else result_wn = rhs_wn;
01719 
01720   // OSP_382, do not store MTYPE_M into temp
01721         if (need_result && rtype != MTYPE_M &&
01722       (volt ||
01723        assign_code == POSTINCREMENT_EXPR ||
01724        assign_code == POSTDECREMENT_EXPR)) { // save result in a preg
01725           result_in_temp = TRUE;
01726           result_preg_st = MTYPE_To_PREG(rtype);
01727           result_preg = Create_Preg(rtype, NULL);
01728           wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
01729            result_wn, 0);
01730           WFE_Stmt_Append (wn, Get_Srcpos());
01731           result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
01732             0);
01733         }
01734 
01735         if (assign_code == POSTINCREMENT_EXPR ||
01736       assign_code == POSTDECREMENT_EXPR) {
01737           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01738                  rtype, result_wn, rhs_wn);
01739         }
01740         else rhs_wn = result_wn;
01741 
01742         // rhs_wn is now always the right-hand-side of the assignment
01743       }
01744 
01745       // the assignment
01746       if (!WFE_Keep_Zero_Length_Structs &&
01747           desc == MTYPE_M               &&
01748           TY_size (hi_ty_idx) == 0) {
01749         // ignore zero length structs
01750       }
01751       else {
01752 #ifdef KEY    // bug 10422: check if the field is volatile
01753   if (volt) 
01754     Set_TY_is_volatile(hi_ty_idx);
01755 #endif
01756         wn = WN_Stid (desc, ST_ofst(st) + component_offset + lhs_preg_num, st,
01757           hi_ty_idx, rhs_wn, field_id);
01758 #if defined(TARG_SL)
01759         wn = Adjust_Vbuf_Array_Ofst(wn);
01760 #endif 
01761         WFE_Stmt_Append(wn, Get_Srcpos());
01762 #if defined(TARG_SL)
01763       if (need_append) {
01764   WN *ldid_wn;
01765         if (! result_in_temp)
01766            ldid_wn =  WN_CreateLdid(OPR_LDID, rtype, desc,
01767                            ST_ofst(st) + component_offset, st, hi_ty_idx,
01768                            field_id);
01769  
01770   else 
01771            ldid_wn =  WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01772   
01773         WFE_Stmt_Append_Extend_Intrinsic(wn, ldid_wn, Get_Srcpos());
01774       }
01775 #endif
01776       }
01777       if (need_result) {
01778         if (! result_in_temp)
01779           wn = WN_CreateLdid(OPR_LDID, rtype, desc, 
01780            ST_ofst(st) + component_offset, st, hi_ty_idx,
01781            field_id);
01782         else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01783         if (is_realpart)
01784     wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
01785         else
01786         if (is_imagpart)
01787     wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
01788       }
01789       else wn = NULL;
01790     }
01791     break;
01792 
01793   case INDIRECT_REF:
01794     {
01795       TY_IDX hi_ty_idx = Get_TY(TREE_TYPE(lhs));
01796       if (TREE_THIS_VOLATILE(lhs)) {
01797         Set_TY_is_volatile(hi_ty_idx);
01798         volt = TRUE;
01799       }
01800       tree op = TREE_OPERAND(lhs, 0);
01801       WN *addr_wn = WFE_Expand_Expr (TREE_OPERAND (lhs, 0));
01802       TY_IDX desc_ty_idx = component_ty_idx;
01803       if (desc_ty_idx == 0)
01804         desc_ty_idx = hi_ty_idx;
01805       if (TY_is_volatile(desc_ty_idx)) {
01806         Clear_TY_is_volatile(desc_ty_idx);
01807         volt = TRUE;
01808       }
01809       Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
01810         ("WFE_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
01811       if (WN_has_side_effects(addr_wn) &&
01812     (need_result || 
01813      assign_code == PREINCREMENT_EXPR ||
01814      assign_code == PREDECREMENT_EXPR ||
01815      assign_code == POSTINCREMENT_EXPR ||
01816      assign_code == POSTDECREMENT_EXPR)) {
01817         ST       *preg_st;
01818         PREG_NUM  preg;
01819         TY_IDX    address_ty_idx = Get_TY (TREE_TYPE (TREE_OPERAND (lhs, 0)));
01820 #ifdef KEY
01821         //Bug 8738: PREG should NOT be VOLATILE in whirl
01822         if (TY_is_volatile(address_ty_idx)) {
01823            Clear_TY_is_volatile(address_ty_idx);
01824            volt = TRUE;
01825         }
01826 #endif
01827         preg_st = MTYPE_To_PREG(Pointer_Mtype);
01828         preg    = Create_Preg (Pointer_Mtype, NULL);
01829         wn      = WN_Stid (Pointer_Mtype, preg, preg_st, address_ty_idx, addr_wn);
01830         WFE_Set_ST_Addr_Saved (addr_wn);
01831         WFE_Stmt_Append (wn, Get_Srcpos());
01832         addr_wn = WN_Ldid (Pointer_Mtype, preg, preg_st, address_ty_idx);
01833       }
01834 
01835       TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
01836       TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
01837 
01838       if (rhs_wn == NULL) {
01839         // Manufacture a negative-PREG RHS for the ISTORE we are about to
01840         // generate. This feature is used in preparing WHIRL ASM
01841         // statements.
01842         ST *rhs_st;
01843         // TODO: How to support a bit-field output of non-integral
01844         // number of bytes?
01845         rhs_st = MTYPE_To_PREG(desc);
01846         // Types are likely to be wrong in the following
01847         rhs_wn = WN_CreateLdid (OPR_LDID, rtype, desc, rhs_preg_num, rhs_st,
01848               desc_ty_idx, 0);
01849 #ifdef KEY
01850       // Bug 8056: Need to preserve the semantics on the preg if it's size
01851       // is less than 4 bytes.
01852       if (MTYPE_byte_size(desc) < 4) {
01853                                                                                                                                                             
01854          rhs_wn = WN_CreateCvtl(!MTYPE_signed(desc) ? OPC_U4CVTL : OPC_I4CVTL,
01855                                 MTYPE_bit_size(desc),
01856                                 rhs_wn);
01857                                                                                                                                                             
01858       }
01859 #endif
01860       }
01861       else {
01862         WN *result_wn;  // the result wn to be returned
01863 
01864         if (assign_code == MODIFY_EXPR) {
01865     if (is_realpart)
01866       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01867              rhs_wn,
01868              WN_Unary(OPR_IMAGPART,
01869                 Mtype_complex_to_real (rtype),
01870                 WN_CreateIload(OPR_ILOAD, rtype, desc,
01871                    component_offset,
01872                    field_id != 0 ? hi_ty_idx : desc_ty_idx,
01873                    Make_Pointer_Type(hi_ty_idx, FALSE),
01874                    WN_COPY_Tree (addr_wn),
01875                    field_id)));
01876     else
01877     if (is_imagpart)
01878       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01879              WN_Unary(OPR_REALPART,
01880                 Mtype_complex_to_real (rtype),
01881                 WN_CreateIload(OPR_ILOAD, rtype, desc,
01882                    component_offset,
01883                    field_id != 0 ? hi_ty_idx : desc_ty_idx,
01884                    Make_Pointer_Type(hi_ty_idx, FALSE),
01885                    WN_COPY_Tree (addr_wn),
01886                    field_id)),
01887              rhs_wn);
01888         }
01889         else {
01890     if (is_realpart)
01891       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01892              rhs_wn,
01893              WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
01894     else
01895     if (is_imagpart)
01896       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01897              WN_Floatconst(Mtype_complex_to_real(rtype), 0.0),
01898              rhs_wn);
01899         }
01900 
01901         if (assign_code == PREINCREMENT_EXPR ||
01902       assign_code == PREDECREMENT_EXPR) {
01903           wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
01904              field_id != 0 ? hi_ty_idx : desc_ty_idx,
01905              Make_Pointer_Type(hi_ty_idx, FALSE),
01906              WN_COPY_Tree (addr_wn),
01907              field_id);
01908           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01909                              rtype, wn, rhs_wn);
01910           result_wn = rhs_wn;
01911         }
01912         else if (assign_code == POSTINCREMENT_EXPR ||
01913            assign_code == POSTDECREMENT_EXPR) {
01914     result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
01915               field_id != 0 ? hi_ty_idx : desc_ty_idx,
01916               Make_Pointer_Type(hi_ty_idx, FALSE),
01917               WN_COPY_Tree (addr_wn),
01918               field_id);
01919         }
01920         else result_wn = rhs_wn;
01921 
01922   // OSP_382, do not store MTYPE_M into temp
01923         if (need_result && rtype != MTYPE_M &&
01924       (volt ||
01925              assign_code == POSTINCREMENT_EXPR ||
01926              assign_code == POSTDECREMENT_EXPR)) { // save result in a preg
01927     result_in_temp = TRUE;
01928           result_preg_st = MTYPE_To_PREG(rtype);
01929           result_preg = Create_Preg(rtype, NULL);
01930           wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
01931            result_wn, 0);
01932           WFE_Stmt_Append (wn, Get_Srcpos());;
01933           result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
01934             0);
01935         }
01936 
01937         if (assign_code == POSTINCREMENT_EXPR ||
01938       assign_code == POSTDECREMENT_EXPR) {
01939           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01940                              rtype, result_wn, rhs_wn);
01941         }
01942         else rhs_wn = result_wn;
01943 
01944         // rhs_wn is now always the right-hand-side of the assignment
01945       }
01946 
01947       // the assignment
01948       if (!WFE_Keep_Zero_Length_Structs &&
01949           desc == MTYPE_M               &&
01950           TY_size (hi_ty_idx) == 0) {
01951         // ignore zero length structs
01952         if (WN_has_side_effects (addr_wn)) {
01953     wn = WN_CreateEval (addr_wn);
01954     WFE_Stmt_Append (wn, Get_Srcpos());
01955         }
01956         wn = NULL;
01957       }
01958       else {
01959 #ifdef KEY
01960   // The store target could be an INDIRECT_REF that kg++fe added to make
01961   // the store write to the area pointed to by the fake first param.  If
01962   // so, check that copying the object does not involve a copy
01963   // constructor.  kg++fe cannot call the copy constructor whenever it
01964   // wants because g++ might not have generated the copy constructor
01965   // definition, since the
01966   // copy constructor was never called.  Furthermore, copying the object
01967   // implies we need to destroy the source object, but g++ might not have
01968   // generated the destructor definition for the same reason.
01969         //
01970   // This checking is only necessary when we are copying through the fake
01971   // param.  Normally g++ calls the copy constructor explicitly if an
01972   // object requires it.  In such a case, the copy constructor is always
01973   // defined.
01974         tree addr = TREE_OPERAND(lhs, 0);
01975         WN *first_formal = WN_formal(Current_Entry_WN(), 0);
01976         if (TY_return_in_mem(hi_ty_idx) &&
01977       field_id == 0 &&
01978       // See if it is an indirect ref of the fake first parm.
01979       // bug fix for OSP_314
01980       //
01981       first_formal != NULL && WN_operator(first_formal) != OPR_BLOCK &&
01982       TREE_CODE(addr) == VAR_DECL &&
01983       DECL_ST(addr) == WN_st(first_formal)) {
01984     FmtAssert(TY_mtype(hi_ty_idx) == MTYPE_M,
01985         ("WFE_Lhs_Of_Modify_Expr: return_in_mem type not MTYPE_M"));
01986     tree ptr_type = TREE_TYPE(TREE_OPERAND(lhs, 0));
01987     tree type = TREE_TYPE(ptr_type);
01988     FmtAssert(TREE_CODE(ptr_type) == POINTER_TYPE,
01989       ("WFE_Lhs_Of_Modify_Expr: INDIRECT_REF opnd0 is not POINTER_TYPE"));
01990     FmtAssert(component_offset == 0,
01991         ("WFE_Lhs_Of_Modify_Expr: component_offset nonzero"));
01992     TY_IDX tidx = Get_TY(ptr_type);
01993     // Check object has no copy constructor.
01994     FmtAssert(!WFE_has_copy_constructor(type),
01995         ("WFE_Lhs_Of_Modify_Expr: object needs copy constructor"));
01996         }
01997 #endif
01998         wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
01999            Make_Pointer_Type (hi_ty_idx, FALSE),
02000            rhs_wn, addr_wn, field_id);
02001 #ifdef TARG_SL
02002       /* so far I only handle *p++=... cases, change this case to 
02003        *   *p = ... ;
02004        *   p++;
02005        * This is to make our compiler consistent with gcc. So far,
02006        * only POST(INC/DEC) differs from gcc.
02007        *
02008        * NOTE! here, we are already in the INDIRECT_REF node, so I
02009        * only need to make sure : (1) the last whirl stmt is for 
02010        * the POST(INC/DEC); (2) the r.h.s doesnt re-define the 
02011        * pointer 'p', but how to make sure about this ? 
02012        */
02013       tree post_inc_dec = TREE_OPERAND(lhs, 0);
02014       tree var_node = TREE_OPERAND(post_inc_dec, 0);
02015       if( TREE_CODE(post_inc_dec) == POSTINCREMENT_EXPR ||
02016           TREE_CODE(post_inc_dec) == POSTDECREMENT_EXPR ){
02017         /* Here I need to make sure it's of form *p++=.., and 
02018          * 'p' is of a reasonable type which I can compare with the
02019          * symbol name
02020          */
02021         Is_True( var_node && ( TREE_CODE(var_node)==VAR_DECL 
02022                  || TREE_CODE(var_node)==PARM_DECL
02023                  || TREE_CODE(var_node)==COMPONENT_REF
02024                  || TREE_CODE(var_node)==INDIRECT_REF ), 
02025                  ("Post{Inc|Dec} should be on variables or parameters, or component of struct"));
02026 
02027         /* For indirect_ref, the actual symbol name for comparison is
02028          * the first operand. However if the 1st operand is still a
02029          * indirect ref, things will got too complex, just forget it
02030          */
02031         if( TREE_CODE(var_node) == INDIRECT_REF ) {
02032           if( TREE_CODE(var_node) != PARM_DECL && 
02033               TREE_CODE(var_node) != VAR_DECL ) {
02034             DevWarn(" When handling *p++ consistent with gcc, there is *p++, p is a pointer to non-var-decl, non-parm-decl, NOT HANDLED yet!" );
02035           } else 
02036             var_node = TREE_OPERAND(var_node, 0);
02037         }
02038 
02039         sameness = FALSE;
02040         /* for lhs being component ref (having no name), or lhs has 
02041          * no name, I dont want to handle them, since too complex.
02042          */
02043         
02044         if( DECL_NAME(var_node) && 
02045             IDENTIFIER_POINTER(DECL_NAME(var_node)) )
02046           sameness |= Same_Var( IDENTIFIER_POINTER(DECL_NAME(var_node)), rhs );
02047         if( sameness ) {
02048           DevWarn("ANSI C undefined behavior: *p++=...,p,.. or *p--=...,p,...");
02049           WFE_Stmt_Prepend_Last(wn, Get_Srcpos());
02050         }
02051         else
02052         WFE_Stmt_Append(wn, Get_Srcpos());
02053       } else 
02054         WFE_Stmt_Append(wn, Get_Srcpos());
02055 #else
02056       WFE_Stmt_Append(wn, Get_Srcpos());
02057 #endif
02058 #if defined(TARG_SL)
02059       if (need_append) {
02060          WN *ldid_wn;
02061          if (! result_in_temp)
02062           ldid_wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
02063             field_id != 0 ? hi_ty_idx : desc_ty_idx,
02064             Make_Pointer_Type (hi_ty_idx, FALSE),
02065             WN_COPY_Tree (addr_wn),
02066             field_id);
02067   else 
02068           ldid_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0); 
02069   
02070         WFE_Stmt_Append_Extend_Intrinsic(wn, ldid_wn, Get_Srcpos());
02071       }
02072 #endif
02073 
02074         if (need_result) {
02075     if (! result_in_temp)
02076             wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
02077               field_id != 0 ? hi_ty_idx : desc_ty_idx,
02078               Make_Pointer_Type (hi_ty_idx, FALSE),
02079               WN_COPY_Tree (addr_wn),
02080               field_id);
02081     else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
02082     if (is_realpart)
02083       wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
02084     else
02085     if (is_imagpart)
02086       wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
02087         }
02088         else wn = NULL;
02089       }
02090     }
02091     break;
02092 
02093   case ARRAY_REF:
02094     {
02095       TY_IDX elem_ty_idx;
02096       // generate the WHIRL array node
02097       WN *addr_wn = WFE_Array_Expr(lhs, &elem_ty_idx, 0, 0, 0);
02098       if (TY_is_volatile(elem_ty_idx))
02099         volt = TRUE;
02100       TY_IDX desc_ty_idx = component_ty_idx;
02101       if (desc_ty_idx == 0)
02102         desc_ty_idx = Get_TY (TREE_TYPE(lhs));
02103       if (TY_is_volatile(desc_ty_idx)) {
02104         Clear_TY_is_volatile(desc_ty_idx);
02105         volt = TRUE;
02106       }
02107       Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
02108         ("WFE_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
02109       if (WN_has_side_effects(addr_wn) &&
02110           (need_result ||
02111            assign_code == PREINCREMENT_EXPR ||
02112            assign_code == PREDECREMENT_EXPR ||
02113            assign_code == POSTINCREMENT_EXPR ||
02114      assign_code == POSTDECREMENT_EXPR)) {
02115         ST       *preg_st;
02116         PREG_NUM  preg;
02117         TY_IDX    address_ty_idx = Make_Pointer_Type(elem_ty_idx, FALSE);
02118         preg_st = MTYPE_To_PREG(Pointer_Mtype);
02119         preg    = Create_Preg (Pointer_Mtype, NULL);
02120         wn      = WN_Stid (Pointer_Mtype, preg, preg_st, address_ty_idx, addr_wn);
02121         WFE_Set_ST_Addr_Saved (addr_wn);
02122         WFE_Stmt_Append (wn, Get_Srcpos());
02123         addr_wn = WN_Ldid (Pointer_Mtype, preg, preg_st, address_ty_idx);
02124       }
02125 
02126       TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
02127       TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
02128 
02129       if (rhs_wn == NULL) {
02130         // Manufacture a negative-PREG RHS for the ISTORE we are about to
02131         // generate. This feature is used in preparing WHIRL ASM
02132         // statements.
02133         ST *rhs_st;
02134         // TODO: How to support a bit-field output of non-integral
02135         // number of bytes?
02136         rhs_st = MTYPE_To_PREG(desc);
02137         rhs_wn = WN_CreateLdid (OPR_LDID, rtype, desc, rhs_preg_num, rhs_st,
02138               desc_ty_idx, 0);
02139       }
02140       else {
02141         WN *result_wn;    // the result wn to be returned
02142 
02143         if (assign_code == MODIFY_EXPR) {
02144     if (is_realpart)
02145       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02146              rhs_wn,
02147              WN_Unary(OPR_IMAGPART,
02148                 Mtype_complex_to_real (rtype),
02149                 WN_CreateIload(OPR_ILOAD, rtype, desc,
02150                    component_offset,
02151                    field_id != 0 ? elem_ty_idx : desc_ty_idx,
02152                    Make_Pointer_Type(elem_ty_idx, FALSE),
02153                    WN_COPY_Tree (addr_wn),
02154                    field_id)));
02155     else
02156     if (is_imagpart)
02157       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02158              WN_Unary(OPR_REALPART,
02159                 Mtype_complex_to_real (rtype),
02160                 WN_CreateIload(OPR_ILOAD, rtype, desc,
02161                    component_offset,
02162                    field_id != 0 ? elem_ty_idx : desc_ty_idx,
02163                    Make_Pointer_Type(elem_ty_idx, FALSE),
02164                    WN_COPY_Tree (addr_wn),
02165                    field_id)),
02166              rhs_wn);
02167         }
02168         else {
02169     if (is_realpart)
02170       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02171              rhs_wn,
02172              WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
02173     else
02174     if (is_imagpart)
02175       rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02176              WN_Floatconst(Mtype_complex_to_real(rtype), 0.0),
02177              rhs_wn);
02178         }
02179 
02180         if (assign_code == PREINCREMENT_EXPR ||
02181             assign_code == PREDECREMENT_EXPR) {
02182           wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02183                                field_id != 0 ? elem_ty_idx : desc_ty_idx,
02184                                Make_Pointer_Type(elem_ty_idx, FALSE),
02185                                WN_COPY_Tree (addr_wn),
02186                                field_id);
02187           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
02188                              rtype, wn, rhs_wn);
02189     result_wn = rhs_wn;
02190         }
02191         else if (assign_code == POSTINCREMENT_EXPR ||
02192            assign_code == POSTDECREMENT_EXPR) {
02193           result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02194               field_id != 0 ? elem_ty_idx : desc_ty_idx,
02195               Make_Pointer_Type(elem_ty_idx, FALSE),
02196               WN_COPY_Tree (addr_wn),
02197               field_id);
02198         }
02199         else result_wn = rhs_wn;
02200 
02201   // OSP_382, do not store MTYPE_M into temp
02202         if (need_result && rtype != MTYPE_M &&
02203       (volt ||
02204              assign_code == POSTINCREMENT_EXPR ||
02205        assign_code == POSTDECREMENT_EXPR)) { // save result in a preg
02206           result_in_temp = TRUE;
02207           result_preg_st = MTYPE_To_PREG(rtype);
02208           result_preg = Create_Preg(rtype, NULL);
02209           wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
02210            result_wn, 0);
02211           WFE_Stmt_Append (wn, Get_Srcpos());;
02212           result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
02213             0);
02214         }
02215 
02216         if (assign_code == POSTINCREMENT_EXPR ||
02217             assign_code == POSTDECREMENT_EXPR) {
02218           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
02219                              rtype, result_wn, rhs_wn);
02220         }
02221         else rhs_wn = result_wn;
02222 
02223         // rhs_wn is now always the right-hand-side of the assignment
02224       }
02225 
02226       // the assignment
02227       if (!WFE_Keep_Zero_Length_Structs &&
02228           desc == MTYPE_M               &&
02229           TY_size (elem_ty_idx) == 0) {
02230         // ignore zero length structs
02231         if (WN_has_side_effects (addr_wn)) {
02232           wn = WN_CreateEval (addr_wn);
02233           WFE_Stmt_Append (wn, Get_Srcpos());
02234         }
02235         wn = NULL;
02236       }
02237       else {
02238         wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
02239            Make_Pointer_Type(elem_ty_idx, FALSE), rhs_wn,
02240            addr_wn, field_id);
02241         WFE_Stmt_Append(wn, Get_Srcpos());
02242 #ifdef TARG_SL
02243       if (need_append) {
02244         WN *iload;
02245         if (!result_in_temp)  
02246             iload = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02247                                     field_id != 0 ? elem_ty_idx : desc_ty_idx,
02248                                     Make_Pointer_Type (elem_ty_idx, FALSE),
02249                                     WN_COPY_Tree (addr_wn),
02250                                     field_id);
02251         else 
02252             iload = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
02253         WFE_Stmt_Append_Extend_Intrinsic(wn, iload, Get_Srcpos()); 
02254       }
02255 #endif
02256         if (need_result) {
02257           if (! result_in_temp)
02258       wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02259                field_id != 0 ? elem_ty_idx : desc_ty_idx,
02260                                  Make_Pointer_Type (elem_ty_idx, FALSE),
02261                WN_COPY_Tree (addr_wn),
02262                field_id);
02263     else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
02264     if (is_realpart)
02265       wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
02266     else
02267     if (is_imagpart)
02268       wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
02269         }
02270         else wn = NULL;
02271       }
02272     }
02273     break;
02274 #ifdef KEY // bug 10073
02275   case MIN_EXPR:
02276   case MAX_EXPR:
02277     {
02278       tree arg0 = TREE_OPERAND(lhs, 0);
02279       tree arg1 = TREE_OPERAND(lhs, 1);
02280 
02281       WN *then_block = WN_CreateBlock ();
02282       WN *else_block = WN_CreateBlock ();
02283 
02284       WFE_Stmt_Push (then_block, wfe_stmk_if_then, Get_Srcpos());
02285 #ifdef TARG_SL
02286       WN * wn1 = WFE_Lhs_Of_Modify_Expr (assign_code, arg0, NULL,
02287 #else
02288       WN * wn1 = WFE_Lhs_Of_Modify_Expr (assign_code, arg0, 
02289 #endif
02290                  TRUE,
02291                                          component_ty_idx, component_offset,
02292                                          field_id, is_bit_field,
02293                                          rhs_wn, rhs_preg_num, is_realpart,
02294                                          is_imagpart);
02295       WFE_Stmt_Pop (wfe_stmk_if_then);
02296 
02297       WFE_Stmt_Push (else_block, wfe_stmk_if_else, Get_Srcpos());
02298 #ifdef TARG_SL
02299       WN * wn2 = WFE_Lhs_Of_Modify_Expr (assign_code, arg1, NULL,
02300 #else
02301       WN * wn2 = WFE_Lhs_Of_Modify_Expr (assign_code, arg1,
02302 #endif
02303            TRUE,
02304                                          component_ty_idx, component_offset,
02305                                          field_id, is_bit_field,
02306                                          rhs_wn, rhs_preg_num, is_realpart,
02307                                          is_imagpart);
02308       WFE_Stmt_Pop (wfe_stmk_if_else);
02309 
02310       Is_True (wn1 && wn2,
02311                ("WFE_Lhs_Of_Modify_Expr: null operands of MIN/MAX_EXPR?"));
02312       WN * wn0 = WN_Relational (code == MIN_EXPR ? OPR_LE : OPR_GE,
02313                                 Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(lhs)))),
02314                                 wn1, wn2);
02315       WN *if_stmt = WN_CreateIf (wn0, then_block, else_block);
02316       WFE_Stmt_Append (if_stmt, Get_Srcpos());
02317     }
02318     break;
02319 #endif
02320 
02321   default:
02322     Fail_FmtAssertion ("WFE_Lhs_Of_Modify_Expr: unhandled tree node in LHS of MODIFY_EXPR");
02323   }
02324 
02325   return wn;
02326 }
02327 
02328 /* ============================================================================
02329  *
02330  * WFE_Expand_Expr_With_Sequence_Point
02331  *
02332  * This routine is invoked instead of WN_Expand_Expr to handle the
02333  * following expression nodes
02334  *
02335  *   both operands of && and ||
02336  *   all three operands of conditional ?
02337  *   controlling expression of if
02338  *   controlling expression of switch
02339  *   controlling expression of while
02340  *   statement expression
02341  *
02342  * In order to generate WHIRL for an expression with side effects,
02343  * we would like to move operations such as calls, pre increment/decrement
02344  * into a comma operator, and operations such as post increment/decrement
02345  * into a rcomma operator.
02346  *
02347  * Sequence points related to function call and return are not handled
02348  * here as we cannot generate RCOMMA nodes in these cases.
02349  *
02350  * ============================================================================
02351  */
02352 
02353 WN*
02354 WFE_Expand_Expr_With_Sequence_Point (tree exp, TYPE_ID mtype, WN* target_wn)
02355 {
02356   WN *wn;
02357 
02358   if (mtype == MTYPE_V)
02359 #ifdef KEY
02360     wn = WFE_Expand_Expr (exp, FALSE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
02361 #else
02362     wn = WFE_Expand_Expr (exp, FALSE);
02363 #endif
02364 
02365   else {
02366 
02367     WN *comma_block      = WN_CreateBlock ();
02368 
02369     WFE_Stmt_Push (comma_block, wfe_stmk_comma, Get_Srcpos ());
02370 #ifdef KEY
02371     wn = WFE_Expand_Expr (exp, TRUE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
02372 #else
02373     wn = WFE_Expand_Expr (exp);
02374 #endif
02375 
02376     // normalize bool expressions
02377     if (TREE_TYPE (exp) == boolean_type_node) {
02378       if (WN_operator (wn) == OPR_LDID ||
02379           WN_operator (wn) == OPR_ILOAD) {
02380         WN *zero = WN_Intconst (WN_rtype (wn), 0);
02381         wn = WN_Relational (OPR_NE, MTYPE_I4, wn, zero);
02382       }
02383     }
02384 
02385     WFE_Stmt_Pop (wfe_stmk_comma);
02386     if (WN_first (comma_block)) {
02387       if (wn)
02388   wn = WN_CreateComma (OPR_COMMA, Mtype_comparison (mtype), MTYPE_V,
02389            comma_block, wn);
02390       else
02391   WFE_Stmt_Append (comma_block, Get_Srcpos());
02392     }
02393     else
02394       WN_Delete (comma_block);
02395   }
02396 
02397   return wn;
02398 } /* WFE_Expand_Expr_With_Sequence_Point */
02399 
02400 static void
02401 emit_barrier (bool type, tree list, INT32 k)
02402 {
02403   INT32  i;
02404   WN    *wn = WN_CreateBarrier (type, k);
02405 
02406   for (i = 0; i < k; i++) {
02407     tree exp = TREE_VALUE (list);
02408     ST *st   = Get_ST (exp);
02409     WN_kid (wn, i) = WN_Lda (Pointer_Mtype, 0, st,
02410                              Make_Pointer_Type (ST_type (st), FALSE));
02411     list = TREE_CHAIN (list);
02412   }
02413 
02414   WFE_Stmt_Append (wn, Get_Srcpos());
02415 } /* emit_barrier */
02416 
02417 static WN *
02418 emit_builtin_lock_test_and_set (tree exp, INT32 k)
02419 {
02420   WN        *wn;
02421   WN        *arg_wn;
02422   WN        *ikids [2];
02423   TYPE_ID    obj_mtype;
02424   TY_IDX     arg_ty_idx;
02425   TYPE_ID    arg_mtype;
02426   tree       list = TREE_OPERAND (exp, 1);
02427   OPCODE     opc;
02428   INTRINSIC  iopc;
02429 
02430   obj_mtype  = TY_mtype (TY_pointed (Get_TY(TREE_TYPE(TREE_VALUE(list)))));
02431   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02432   arg_mtype  = TY_mtype (arg_ty_idx);
02433   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02434   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02435   ikids [0]  = arg_wn;
02436   list       = TREE_CHAIN (list);
02437   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02438   arg_mtype  = TY_mtype (arg_ty_idx);
02439   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02440   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02441   ikids [1]  = arg_wn;
02442   list       = TREE_CHAIN (list);
02443 
02444   if (obj_mtype == MTYPE_I4) {
02445     opc  = OPC_I4INTRINSIC_CALL;
02446     iopc = INTRN_LOCK_TEST_AND_SET_I4;
02447   }
02448   else
02449   if (obj_mtype == MTYPE_U4) {
02450     opc  = OPC_U4INTRINSIC_CALL;
02451     iopc = INTRN_LOCK_TEST_AND_SET_I4;
02452   }
02453   else
02454   if (obj_mtype == MTYPE_I8) {
02455     opc  = OPC_I8INTRINSIC_CALL;
02456     iopc = INTRN_LOCK_TEST_AND_SET_I8;
02457   }
02458   else
02459   if (obj_mtype == MTYPE_U8) {
02460     opc  = OPC_U8INTRINSIC_CALL;
02461     iopc = INTRN_LOCK_TEST_AND_SET_I8;
02462   }
02463   else {
02464     Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02465     opc  = OPCODE_UNKNOWN;
02466     iopc = INTRINSIC_NONE;
02467   }
02468 
02469   wn = WN_Create_Intrinsic (opc, iopc, 2, ikids);
02470   WFE_Stmt_Append (wn, Get_Srcpos());
02471 
02472   ST       *preg_st = MTYPE_To_PREG(obj_mtype);
02473   TY_IDX    preg_ty_idx = Be_Type_Tbl(obj_mtype);
02474   PREG_NUM  preg = Create_Preg (obj_mtype, NULL);
02475 
02476   wn = WN_Ldid (obj_mtype, -1, Return_Val_Preg, preg_ty_idx);
02477   wn = WN_Stid (obj_mtype, preg, preg_st, preg_ty_idx, wn),
02478   WFE_Stmt_Append (wn, Get_Srcpos());
02479 
02480   emit_barrier (FALSE, list, k);
02481 
02482   wn = WN_Ldid (obj_mtype, preg, preg_st, preg_ty_idx);
02483 
02484   return wn;
02485 } /* emit_builtin_lock_test_and_set */
02486 
02487 static void
02488 emit_builtin_lock_release (tree exp, INT32 k)
02489 {
02490   WN        *wn;
02491   WN        *arg_wn;
02492   WN        *ikids [1];
02493   TYPE_ID    obj_mtype;
02494   TY_IDX     arg_ty_idx;
02495   TYPE_ID    arg_mtype;
02496   tree       list = TREE_OPERAND (exp, 1);
02497   OPCODE     opc;
02498   INTRINSIC  iopc;
02499 
02500   obj_mtype  = TY_mtype (TY_pointed (Get_TY(TREE_TYPE(TREE_VALUE(list)))));
02501   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02502   arg_mtype  = TY_mtype (arg_ty_idx);
02503   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02504   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02505   ikids [0]  = arg_wn;
02506   list       = TREE_CHAIN (list);
02507 
02508   emit_barrier (TRUE, list, k);
02509 
02510   opc = OPC_VINTRINSIC_CALL;
02511   if (obj_mtype == MTYPE_I4)
02512     iopc = INTRN_LOCK_RELEASE_I4;
02513   else
02514   if (obj_mtype == MTYPE_U4)
02515     iopc = INTRN_LOCK_RELEASE_I4;
02516   else
02517   if (obj_mtype == MTYPE_I8)
02518     iopc = INTRN_LOCK_RELEASE_I8;
02519   else
02520   if (obj_mtype == MTYPE_U8)
02521     iopc = INTRN_LOCK_RELEASE_I8;
02522   else {
02523     Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02524     opc  = OPCODE_UNKNOWN;
02525     iopc = INTRINSIC_NONE;
02526   }
02527 
02528   wn = WN_Create_Intrinsic (opc, iopc, 1, ikids);
02529   WFE_Stmt_Append (wn, Get_Srcpos());
02530 } /* emit_builtin_lock_release */
02531 
02532 static WN *
02533 emit_builtin_compare_and_swap (tree exp, INT32 k)
02534 {
02535   WN        *wn;
02536   WN        *arg_wn;
02537   WN        *ikids [3];
02538   TYPE_ID    obj_mtype;
02539   TY_IDX     arg_ty_idx;
02540   TYPE_ID    arg_mtype;
02541   tree       list = TREE_OPERAND (exp, 1);
02542   OPCODE     opc;
02543   INTRINSIC  iopc;
02544 
02545   obj_mtype  = TY_mtype (TY_pointed (Get_TY(TREE_TYPE(TREE_VALUE(list)))));
02546   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02547   arg_mtype  = TY_mtype (arg_ty_idx);
02548   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02549   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02550   ikids [0]  = arg_wn;
02551   list       = TREE_CHAIN (list);
02552   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02553   arg_mtype  = TY_mtype (arg_ty_idx);
02554   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02555   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02556   ikids [1]  = arg_wn;
02557   list       = TREE_CHAIN (list);
02558   arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
02559   arg_mtype  = TY_mtype (arg_ty_idx);
02560   arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
02561   arg_wn     = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02562   ikids [2]  = arg_wn;
02563   list       = TREE_CHAIN (list);
02564 
02565   emit_barrier (TRUE, list, k);
02566 
02567   opc = OPC_I4INTRINSIC_CALL;
02568   if (obj_mtype == MTYPE_I4)
02569     iopc = INTRN_COMPARE_AND_SWAP_I4;
02570   else
02571   if (obj_mtype == MTYPE_U4)
02572     iopc = INTRN_COMPARE_AND_SWAP_I4;
02573   else
02574   if (obj_mtype == MTYPE_I8)
02575     iopc = INTRN_COMPARE_AND_SWAP_I8;
02576   else
02577   if (obj_mtype == MTYPE_U8)
02578     iopc = INTRN_COMPARE_AND_SWAP_I8;
02579   else {
02580     Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02581     opc  = OPCODE_UNKNOWN;
02582     iopc = INTRINSIC_NONE;
02583   }
02584 
02585   wn = WN_Create_Intrinsic (opc, iopc, 3, ikids);
02586   WFE_Stmt_Append (wn, Get_Srcpos());
02587 
02588   ST       *preg_st = MTYPE_To_PREG(MTYPE_I4);
02589   TY_IDX    preg_ty_idx = Be_Type_Tbl(MTYPE_I4);
02590   PREG_NUM  preg = Create_Preg (MTYPE_I4, NULL);
02591 
02592   wn = WN_Ldid (MTYPE_I4, -1, Return_Val_Preg, preg_ty_idx);
02593   wn = WN_Stid (MTYPE_I4, preg, preg_st, preg_ty_idx, wn),
02594   WFE_Stmt_Append (wn, Get_Srcpos());
02595 
02596   emit_barrier (FALSE, list, k);
02597 
02598   wn = WN_Ldid (MTYPE_I4, preg, preg_st, preg_ty_idx);
02599 
02600   return wn;
02601 } /* emit_builtin_compare_and_swap */
02602 
02603 static void
02604 emit_builtin_synchronize (tree exp, INT32 k)
02605 {
02606   WN *wn;
02607   tree list = TREE_OPERAND (exp, 1);
02608   emit_barrier (TRUE,  list, k);
02609   wn = WN_Create_Intrinsic (OPC_VINTRINSIC_CALL, INTRN_SYNCHRONIZE, 0, NULL);
02610   WFE_Stmt_Append (wn, Get_Srcpos());
02611   emit_barrier (FALSE, list, k);
02612 } /* emit_builtin_synchronize */
02613 
02614 static char *
02615 get_string_pointer (WN *wn)
02616 {
02617   char *ptr = NULL;
02618 
02619   if (WN_operator (wn) == OPR_LDA) {
02620     ST *st = WN_st (wn);
02621     if (ST_class (st) == CLASS_CONST) {
02622       TCON tcon = Tcon_Table [ST_tcon (st)];
02623       if (TCON_ty (tcon) == MTYPE_STRING)
02624         ptr = ((char *) Targ_String_Address (tcon)) + WN_offset (wn);
02625     }
02626   }
02627 
02628   return ptr;
02629 } /* get_string_pointer */
02630 
02631 #ifdef KEY
02632 // Bug 12781: code taken from unemitted_tinfo_decl_p() in gnu/cp/rtti.c.
02633 // Return 1 if t is a typeinfo, 0 otherwise.
02634 int
02635 tinfo_decl_p (tree t)
02636 {
02637   if (/* It's a var decl */
02638       TREE_CODE (t) == VAR_DECL
02639       /* whos name points back to itself */
02640       && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t
02641       /* and whose type is a struct */
02642       && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
02643       /* with a field */
02644       && TYPE_FIELDS (TREE_TYPE (t))
02645       /* which is our pseudo type info */
02646       && TREE_TYPE (TYPE_FIELDS (TREE_TYPE (t))) == ti_desc_type_node)
02647     return 1;
02648   return 0;
02649 }
02650 #endif
02651 
02652 // Auxiliary function for WFE_Expand_Expr, return the address of
02653 // a tree operand.  (Used for ADDR_EXPR.)
02654 WN*
02655 WFE_Address_Of(tree arg0)
02656 {
02657   enum tree_code code0 = TREE_CODE (arg0);
02658   ST *st = 0;
02659   WN* wn = 0;
02660   WN* wn0;
02661   WN* wn1;
02662   TY_IDX ty_idx;
02663 
02664   switch (code0) {
02665   case VAR_DECL:
02666   case PARM_DECL:
02667   case FUNCTION_DECL:
02668 #ifdef KEY
02669   case RESULT_DECL: // bug 3878
02670 #endif
02671     {
02672       st = Get_ST (arg0);
02673       ty_idx = ST_type (st);
02674 #ifdef KEY
02675       // Arg0 is the virtual function table (vtable) for a class.  Initialize
02676       // the table.
02677       if (code0 == VAR_DECL) {
02678   if (DECL_INITIAL(arg0) &&
02679 #ifdef PATHSCALE_MERGE
02680             (DECL_VIRTUAL_P(arg0) || tinfo_decl_p(arg0) /* bug 12781: typeinfo ? */) &&
02681 #else
02682       DECL_VIRTUAL_P(arg0) &&
02683 #endif
02684       !DECL_EXTERNAL(arg0)) {
02685     tree init = DECL_INITIAL(arg0);
02686     if (TREE_CODE(init) != ERROR_MARK) {
02687       FmtAssert (TREE_CODE(init) == CONSTRUCTOR,
02688            ("Unexpected initializer for virtual table"));
02689       WFE_Initialize_Decl(arg0);
02690     }
02691   }
02692       }
02693 #endif
02694       // for VLAs, use the base_st instead of st
02695       if (code0 == VAR_DECL &&
02696           st != ST_base(st)) {
02697         FmtAssert (ST_ofst (st) == 0,
02698                    ("Variable Length Arrays within struct not currently implemented"));
02699         wn = WN_Ldid (Pointer_Mtype, 0, ST_base(st), ST_type(ST_base(st)));
02700       }
02701       else
02702         if (!WFE_Keep_Zero_Length_Structs &&
02703             code0 == PARM_DECL            &&
02704             TY_mtype (ty_idx) == MTYPE_M  &&
02705             TY_size (ty_idx) == 0) {
02706           // taking address of zero length struct passed as parameter
02707           DevWarn ("taking address of zero length struct %s at line %d",
02708                    ST_name (st), lineno);
02709           wn = WN_Intconst (Pointer_Mtype, 0);
02710         }
02711         else
02712           wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02713     }
02714     break;
02715 
02716   case INDIRECT_REF:
02717     wn = WFE_Expand_Expr (TREE_OPERAND(arg0, 0));
02718     break;
02719 
02720   case STRING_CST:
02721     {
02722       TCON tcon;
02723       tcon = Host_To_Targ_String (MTYPE_STRING,
02724                                   const_cast<char*>TREE_STRING_POINTER(arg0),
02725                                   TREE_STRING_LENGTH(arg0));
02726       ty_idx = Get_TY(TREE_TYPE(arg0));
02727       st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
02728       wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02729       TREE_STRING_ST (arg0) = st;
02730     }
02731     break;
02732 
02733   case CONSTRUCTOR:
02734     {
02735       st = WFE_Generate_Temp_For_Initialized_Aggregate (arg0, "");
02736       wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02737     }
02738     break;
02739 
02740   case LABEL_DECL:
02741     {
02742       DevWarn ("taking address of a label at line %d", lineno);
02743       LABEL_IDX label_idx = WFE_Get_LABEL (arg0, FALSE);
02744 #if 0
02745       FmtAssert (arg0->decl.symtab_idx == CURRENT_SYMTAB,
02746                  ("line %d: taking address of a label not defined in current function currently not implemented", lineno));
02747 #endif
02748       wn = WN_LdaLabel (Pointer_Mtype, label_idx);
02749       Set_LABEL_addr_saved (label_idx);
02750     }
02751     break;
02752 
02753   case TARGET_EXPR:
02754     {
02755       WFE_Expand_Expr (arg0);
02756       st = Get_ST (TREE_OPERAND(arg0, 0));
02757       wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02758     }
02759     break;
02760 
02761   case COMPOUND_EXPR:
02762     {
02763 #ifdef KEY
02764       wn = WFE_Expand_Expr(arg0);
02765       if (WN_operator(wn) == OPR_CSELECT) {
02766   // If WN is a CSELECT, get the ST from CSELECT's kids.  Bug 8472.
02767   //
02768   // Handle case where CSELECT's kid1 and kid2 are LDID or COMMAs that
02769   // return the same ST:
02770   //     ...
02771   //     U8U8LDID 0 <2,21,anon954> T<1402,anon_ptr.,8>
02772   //    U8COMMA
02773   //    U8U8LDID 0 <2,21,anon954> T<1402,anon_ptr.,8>
02774   //   U8CSELECT
02775   //
02776   // Handle other cases as they arise.
02777   int i;
02778   ST *st1 = NULL, *st2 = NULL;
02779   for (i = 0; i < 2; i++) {
02780     WN *kid = (i == 0) ? WN_kid1(wn) : WN_kid2(wn);
02781     WN *comma_kid1;
02782     ST **st_ptr = (i == 0) ? &st1 : &st2;
02783     switch (WN_operator(kid)) {
02784       case OPR_LDID:
02785         *st_ptr = WN_st(kid);
02786         break;
02787       case OPR_COMMA:
02788         comma_kid1 = WN_kid1(kid);
02789         Is_True(WN_operator(comma_kid1) == OPR_LDID,
02790           ("WFE_Address_Of: kid1 of COMMA is not LDID"));
02791         *st_ptr = WN_st(comma_kid1);
02792         break;
02793       default:
02794         FmtAssert(FALSE, ("WFE_Address_Of: CSELECT kid NYI"));
02795     }
02796   }
02797   Is_True((st1 != NULL) && (st1 == st2),
02798     ("WFE_Address_Of: CSELECT kids returns different STs"));
02799   st = st1;
02800       } else
02801   st = WN_st(wn);
02802 #else
02803       st = WN_st (WFE_Expand_Expr (arg0));
02804 #endif
02805       wn = WN_Lda (Pointer_Mtype,  ST_ofst (st), st);
02806     }
02807     break;
02808 
02809   case NOP_EXPR:
02810     {
02811       wn = WFE_Address_Of(TREE_OPERAND(arg0, 0));
02812     }
02813     break;
02814 
02815   case MIN_EXPR:
02816   case MAX_EXPR:
02817     {
02818       // &(a <? b) or &(a >? b)
02819       tree op0 = TREE_OPERAND(arg0, 0);
02820       tree op1 = TREE_OPERAND(arg0, 1);
02821       WN* a = WFE_Expand_Expr(op0);
02822       WN* b = WFE_Expand_Expr(op1);
02823       FmtAssert(!WN_has_side_effects(a) && !WN_has_side_effects(b),
02824                 ("Addr of MIN/MAX_EXPR with side effects not yet supported"));
02825 
02826       FmtAssert(same_type_p(TREE_TYPE(op0), TREE_TYPE(op1)),
02827                 ("Types of MIN/MAX_EXPR operands differ"));
02828       TY_IDX  ptr_ty    = Make_Pointer_Type (Get_TY(TREE_TYPE(op0)), FALSE);
02829       TYPE_ID ptr_mtype = TY_mtype(ptr_ty);
02830       TY_IDX  arg_ty    = Get_TY(TREE_TYPE(TREE_OPERAND(arg0, 0)));
02831       TYPE_ID arg_mtype = TY_mtype(arg_ty);
02832 
02833       WN* aptr = WFE_Address_Of(op0);
02834       WN* bptr = WFE_Address_Of(op1);
02835       wn = WN_Select(Widen_Mtype(ptr_mtype),
02836                      WN_Relational(code0 == MIN_EXPR ? OPR_LT : OPR_GT,
02837                                    Widen_Mtype(arg_mtype),
02838                                    a, b),
02839                      aptr, bptr);
02840       Set_PU_has_very_high_whirl (Get_Current_PU ());
02841     }
02842     break;
02843 
02844   case COMPONENT_REF:
02845     {
02846       wn = WFE_Expand_Expr (arg0);
02847       ty_idx = Get_TY(TREE_TYPE(arg0));
02848       if (WN_operator (wn) == OPR_LDID) {
02849         WN_set_operator (wn, OPR_LDA);
02850         WN_set_desc (wn, MTYPE_V);
02851         WN_set_rtype(wn, Pointer_Mtype);
02852         WN_set_ty (wn, Make_Pointer_Type(WN_ty(wn))); // bug 10098, bug 10352
02853      }
02854       else
02855       if (WN_operator (wn) == OPR_ILOAD) {
02856         wn0 = WN_kid0 (wn);
02857         wn1 = WN_Intconst (Pointer_Mtype, WN_offset (wn));
02858         wn  = WN_Binary (OPR_ADD, Pointer_Mtype, wn0, wn1);
02859       }
02860       else
02861         Fail_FmtAssertion ("WFE_Address_Of has unhandled %s",
02862                            Operator_From_Tree [code0].name);
02863     }
02864     break;
02865 
02866 #ifdef KEY // bug 3228
02867   case ARRAY_REF:
02868     wn = WFE_Expand_Expr (arg0);
02869     if (WN_operator(wn) == OPR_ILOAD) // bug 10105
02870       wn = WN_kid0(wn);
02871     ty_idx = Get_TY(TREE_TYPE(arg0));
02872     break;
02873 #endif
02874 
02875 #ifdef KEY
02876     case COMPOUND_LITERAL_EXPR:
02877     {
02878       arg0 = DECL_INITIAL (TREE_OPERAND (TREE_OPERAND (arg0, 0), 0));
02879       st = WFE_Generate_Temp_For_Initialized_Aggregate (arg0, "");
02880       wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02881     }
02882     break;
02883 
02884     // bug 2399
02885     case SAVE_EXPR:
02886     {
02887       st = WN_st (WFE_Expand_Expr (arg0));
02888       wn = WN_Lda (Pointer_Mtype,  ST_ofst (st), st);
02889     }
02890     break;
02891 
02892     // bug 5532, 5609
02893     case REALPART_EXPR:
02894     {
02895       wn = WFE_Expand_Expr (TREE_OPERAND (arg0, 0));
02896       if (WN_operator (wn) == OPR_ILOAD)
02897         wn = WN_kid0 (wn);
02898       else if (WN_operator (wn) == OPR_LDID)
02899   wn = WN_Lda (Pointer_Mtype, WN_offset(wn), WN_st(wn));
02900       else Fail_FmtAssertion ("WFE_Address_Of: NYI for REALPART_EXPR");
02901     }
02902     break;
02903 
02904     case IMAGPART_EXPR:
02905     {
02906       wn = WFE_Expand_Expr (TREE_OPERAND (arg0, 0));
02907       if (WN_operator (wn) == OPR_ILOAD)
02908       {
02909         wn0 = WN_kid0 (wn);
02910   TYPE_ID imag_mtype;
02911   switch (WN_rtype (wn))
02912   {
02913     case MTYPE_C4:
02914       imag_mtype = MTYPE_F4;
02915       break;
02916     case MTYPE_C8:
02917       imag_mtype = MTYPE_F8;
02918       break;
02919     case MTYPE_C10:
02920       imag_mtype = MTYPE_F10;
02921       break;
02922     case MTYPE_CQ:
02923       imag_mtype = MTYPE_FQ;
02924       break;
02925     default:
02926       Fail_FmtAssertion ("WFE_Address_Of: Unexpected rtype in IMAGPART_EXPR");
02927   }
02928   INT ofst;
02929   if (imag_mtype == MTYPE_FQ)
02930   {
02931 #ifdef TARG_X8664
02932     if (Is_Target_32bit()) ofst = 12; else
02933 #endif // TARG_X8664
02934     ofst = 16;
02935   }
02936   else ofst = MTYPE_byte_size (imag_mtype);
02937 
02938   wn1 = WN_Intconst (Pointer_Mtype, ofst);
02939   wn  = WN_Binary (OPR_ADD, Pointer_Mtype, wn0, wn1);
02940       }
02941       else if (WN_operator (wn) == OPR_LDID)
02942   wn = WN_Lda (Pointer_Mtype, 
02943          WN_offset(wn) + MTYPE_byte_size(WN_rtype(wn)) / 2,
02944          WN_st(wn));
02945       else Fail_FmtAssertion ("WFE_Address_Of: NYI for IMAGPART_EXPR");
02946     }
02947     break;
02948 #endif
02949 
02950   default:
02951     {
02952       Fail_FmtAssertion ("WFE_Address_Of: Unexpected operand %s",
02953                          Operator_From_Tree [code0].name);
02954     }
02955     break;
02956   }
02957 
02958   FmtAssert(wn != 0, ("WFE_Address_Of: null WHIRL tree for %s",
02959                       Operator_From_Tree [code0].name));
02960   return wn;
02961 }
02962 
02963 #ifdef TARG_X8664
02964 /* expand a VA_ARG_EXPR node for scalar type according to X86-64 ABI and 
02965  * return the WHIRL node that represents the address to be dereferenced;
02966  * 'twice' is true is loading two consecutive parameters of the same type
02967  * because they belong to a struct; currently, twice is TRUE only if isfloat
02968  * is FALSE */
02969 static WN *WFE_x8664_va_arg(WN *ap_wn, BOOL isfloat, TY_IDX ty_idx, BOOL twice)
02970 {
02971   /* compare gp_offset with 48 or fp_offset with 176 */
02972   WN *wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4), 
02973                WN_CopyNode(ap_wn));
02974   WN *wn1 = WN_Intconst(MTYPE_I4, (!isfloat ? 48 : 176) - (twice ? 8 : 0));
02975   WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
02976   LABEL_IDX lab1;
02977   New_LABEL (CURRENT_SYMTAB, lab1);
02978   WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
02979   wn = WN_CreateTruebr(lab1, wn);
02980   WFE_Stmt_Append (wn, Get_Srcpos ());
02981 
02982   ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
02983   WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
02984   /* compute reg_save_area+gp_offset/fp_offset and store to arg_temp_st */
02985   wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4), 
02986            WN_CopyNode(ap_wn));
02987   wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype), 
02988      WN_CopyNode(ap_wn));
02989   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
02990   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
02991   WFE_Stmt_Append (wn, Get_Srcpos ());
02992 
02993   /* increment gp_offset by 8 or fp_offset by 16 */
02994   wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4), 
02995            WN_CopyNode(ap_wn));
02996   wn1 = WN_Intconst(MTYPE_I4, (!isfloat ? 8 : 16) * ((INT)twice+1));
02997   wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
02998   wn = WN_Istore(MTYPE_I4, !isfloat ? 0 : 4, 
02999      Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)), 
03000      WN_CopyNode(ap_wn), wn);
03001   WFE_Stmt_Append (wn, Get_Srcpos ());
03002 
03003   /* branch around next part */
03004   LABEL_IDX lab2;
03005   New_LABEL (CURRENT_SYMTAB, lab2);
03006   WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03007   wn = WN_CreateGoto(lab2);
03008   WFE_Stmt_Append (wn, Get_Srcpos ());
03009 
03010   WFE_Stmt_Append (lab1_wn, Get_Srcpos ());
03011 
03012   /* store overflow_arg_area pointer to arg_temp_st */
03013   wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx), 
03014      WN_CopyNode(ap_wn));
03015   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03016   WFE_Stmt_Append (wn, Get_Srcpos ());
03017 
03018   /* increment overflow_arg_area pointer by 8 */
03019   wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype), 
03020      WN_CopyNode(ap_wn));
03021   wn1 = WN_Intconst(MTYPE_U8, twice ? 16 : 8);
03022   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03023   wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03024      WN_CopyNode(ap_wn), wn);
03025   WFE_Stmt_Append (wn, Get_Srcpos ());
03026 
03027   WFE_Stmt_Append (lab2_wn, Get_Srcpos ());
03028 
03029   return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03030 }
03031 
03032 /* expand a VA_ARG_EXPR node for struct type being passed in 2 different classes
03033  * of registers, according to X86-64 ABI and return the WHIRL node that 
03034  * represents the address to be dereferenced; this requires allocating a
03035  * temporary for assembling the struct if passed in registers; isfloat0 is 
03036  * for the first 8-byte and isfloat1 is for the second 8-byte  */
03037 static WN *WFE_x8664_va_arg_2_mixed(WN *ap_wn, BOOL isfloat0, BOOL isfloat1, 
03038             TY_IDX ty_idx)
03039 {
03040   /* compare gp_offset with 48 */
03041   WN *wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03042   WN *wn1 = WN_Intconst(MTYPE_I4, 48);
03043   WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03044   LABEL_IDX lab1;
03045   New_LABEL (CURRENT_SYMTAB, lab1);
03046   WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
03047   wn = WN_CreateTruebr(lab1, wn);
03048   WFE_Stmt_Append (wn, Get_Srcpos ());
03049   /* compare fp_offset with 176 */
03050   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03051   wn1 = WN_Intconst(MTYPE_I4, 176);
03052   wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03053   wn = WN_CreateTruebr(lab1, wn);
03054   WFE_Stmt_Append (wn, Get_Srcpos ());
03055 
03056   /* allocate a temporary location to assemble the structure value */
03057   ST *struct_temp_st = Gen_Temp_Symbol(ty_idx, ".va_arg_struct");
03058   WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, struct_temp_st);
03059 
03060   /* compute reg_save_area+gp_offset and store dereferenced value to 
03061    * struct_temp_st */
03062   wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03063   wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype), 
03064      WN_CopyNode(ap_wn));
03065   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03066   wn = WN_Iload(MTYPE_I8, 0, MTYPE_To_TY(MTYPE_I8), wn);
03067   wn = WN_Stid(MTYPE_I8, isfloat0 ? 8 : 0, struct_temp_st, 
03068          MTYPE_To_TY(MTYPE_I8), wn);
03069   WFE_Stmt_Append (wn, Get_Srcpos ());
03070   /* compute reg_save_area+fp_offset and store dereferenced value to 
03071    * struct_temp_st */
03072   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03073   wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype), 
03074      WN_CopyNode(ap_wn));
03075   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03076   wn = WN_Iload(MTYPE_F8, 0, MTYPE_To_TY(MTYPE_F8), wn);
03077   wn = WN_Stid(MTYPE_F8, isfloat0 ? 0 : 8, struct_temp_st, 
03078          MTYPE_To_TY(MTYPE_F8), wn);
03079   WFE_Stmt_Append (wn, Get_Srcpos ());
03080 
03081   /* increment gp_offset by 8 */
03082   wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03083   wn1 = WN_Intconst(MTYPE_I4, 8);
03084   wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03085   wn = WN_Istore(MTYPE_I4, 0, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)), 
03086      WN_CopyNode(ap_wn), wn);
03087   WFE_Stmt_Append (wn, Get_Srcpos ());
03088   /* increment fp_offset by 16 */
03089   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03090   wn1 = WN_Intconst(MTYPE_I4, 16);
03091   wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03092   wn = WN_Istore(MTYPE_I4, 4, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)), 
03093      WN_CopyNode(ap_wn), wn);
03094   WFE_Stmt_Append (wn, Get_Srcpos ());
03095 
03096   /* put the address of struct_temp_st in arg_temp_st */
03097   ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
03098   WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
03099   wn = WN_Lda(Pointer_Mtype, 0, struct_temp_st, 0);
03100   Set_ST_addr_saved(struct_temp_st);
03101   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
03102   WFE_Stmt_Append (wn, Get_Srcpos ());
03103 
03104   /* branch around next part */
03105   LABEL_IDX lab2;
03106   New_LABEL (CURRENT_SYMTAB, lab2);
03107   WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03108   wn = WN_CreateGoto(lab2);
03109   WFE_Stmt_Append (wn, Get_Srcpos ());
03110 
03111   WFE_Stmt_Append (lab1_wn, Get_Srcpos ());
03112 
03113   /* store overflow_arg_area pointer to arg_temp_st */
03114   wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx), 
03115      WN_CopyNode(ap_wn));
03116   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03117   WFE_Stmt_Append (wn, Get_Srcpos ());
03118 
03119   /* increment overflow_arg_area pointer by 16 */
03120   wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype), 
03121      WN_CopyNode(ap_wn));
03122   wn1 = WN_Intconst(MTYPE_U8, 16);
03123   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03124   wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03125      WN_CopyNode(ap_wn), wn);
03126   WFE_Stmt_Append (wn, Get_Srcpos ());
03127 
03128   WFE_Stmt_Append (lab2_wn, Get_Srcpos ());
03129 
03130   return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03131 }
03132 
03133 /* expand a VA_ARG_EXPR node for struct type being passed in 2 float
03134  * registers, according to X86-64 ABI and return the WHIRL node that 
03135  * represents the address to be dereferenced; this requires allocating a
03136  * temporary for assembling the struct if passed in registers, because each
03137  * float register is saved into 128 bit locations */
03138 static WN *WFE_x8664_va_arg_2_float(WN *ap_wn, TY_IDX ty_idx)
03139 {
03140   LABEL_IDX lab1;
03141   New_LABEL (CURRENT_SYMTAB, lab1);
03142   WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
03143   /* compare fp_offset with 160 (176 - 16) */
03144   WN *wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03145   WN *wn1 = WN_Intconst(MTYPE_I4, 160);
03146   WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03147   wn = WN_CreateTruebr(lab1, wn);
03148   WFE_Stmt_Append (wn, Get_Srcpos ());
03149 
03150   /* allocate a temporary location to assemble the structure value */
03151   ST *struct_temp_st = Gen_Temp_Symbol(ty_idx, ".va_arg_struct");
03152   WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, struct_temp_st);
03153 
03154   /* compute reg_save_area+fp_offset and store 1st dereferenced value to 
03155    * struct_temp_st */
03156   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03157   wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype), 
03158      WN_CopyNode(ap_wn));
03159   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03160   wn = WN_Iload(MTYPE_F8, 0, MTYPE_To_TY(MTYPE_F8), wn);
03161   wn = WN_Stid(MTYPE_F8, 0, struct_temp_st, MTYPE_To_TY(MTYPE_F8), wn);
03162   WFE_Stmt_Append (wn, Get_Srcpos ());
03163   /* compute reg_save_area+fp_offset and store 2nd dereferenced value to 
03164    * struct_temp_st */
03165   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03166   wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype), 
03167      WN_CopyNode(ap_wn));
03168   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03169   wn = WN_Iload(MTYPE_F8, 16, MTYPE_To_TY(MTYPE_F8), wn);
03170   wn = WN_Stid(MTYPE_F8, 8, struct_temp_st, MTYPE_To_TY(MTYPE_F8), wn);
03171   WFE_Stmt_Append (wn, Get_Srcpos ());
03172 
03173   /* increment fp_offset by 32 */
03174   wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03175   wn1 = WN_Intconst(MTYPE_I4, 32);
03176   wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03177   wn = WN_Istore(MTYPE_I4, 4, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)), 
03178      WN_CopyNode(ap_wn), wn);
03179   WFE_Stmt_Append (wn, Get_Srcpos ());
03180 
03181   /* put the address of struct_temp_st in arg_temp_st */
03182   ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
03183   WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
03184   wn = WN_Lda(Pointer_Mtype, 0, struct_temp_st, 0);
03185   Set_ST_addr_saved(struct_temp_st);
03186   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
03187   WFE_Stmt_Append (wn, Get_Srcpos ());
03188 
03189   /* branch around next part */
03190   LABEL_IDX lab2;
03191   New_LABEL (CURRENT_SYMTAB, lab2);
03192   WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03193   wn = WN_CreateGoto(lab2);
03194   WFE_Stmt_Append (wn, Get_Srcpos ());
03195 
03196   WFE_Stmt_Append (lab1_wn, Get_Srcpos ());
03197 
03198   /* store overflow_arg_area pointer to arg_temp_st */
03199   wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx), 
03200      WN_CopyNode(ap_wn));
03201   wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03202   WFE_Stmt_Append (wn, Get_Srcpos ());
03203 
03204   /* increment overflow_arg_area pointer by 16 */
03205   wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype), 
03206      WN_CopyNode(ap_wn));
03207   wn1 = WN_Intconst(MTYPE_U8, 16);
03208   wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03209   wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03210      WN_CopyNode(ap_wn), wn);
03211   WFE_Stmt_Append (wn, Get_Srcpos ());
03212 
03213   WFE_Stmt_Append (lab2_wn, Get_Srcpos ());
03214 
03215   return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03216 }
03217 #endif
03218 
03219 #ifdef KEY
03220 static bool inside_eh_region = false;
03221 // Setup an EH region, typically across a function call.
03222 void
03223 Setup_EH_Region (bool for_unwinding)
03224 {
03225     WN * region_body;
03226 
03227     if (for_unwinding)
03228   region_body = WFE_Stmt_Pop (wfe_stmk_region_body);
03229     else
03230       {
03231       region_body = WFE_Stmt_Pop (wfe_stmk_call_region_body);
03232       inside_eh_region = false;
03233   }
03234     INITV_IDX iv;
03235     LABEL_IDX pad = 0;
03236 
03237     if (!for_unwinding) pad = lookup_cleanups (iv);
03238     else
03239     {
03240   iv = New_INITV();
03241         INITV_Set_ZERO (Initv_Table[iv], MTYPE_U4, 1);
03242     }
03243 
03244     INITV_IDX initv_label = New_INITV();
03245     if (pad)
03246       INITV_Init_Label (initv_label, pad, 1);
03247     else
03248   INITV_Set_ZERO (Initv_Table[initv_label], MTYPE_U4, 1);
03249     INITV_IDX blk = New_INITV();
03250     INITV_Init_Block (blk, initv_label);
03251 
03252     Set_INITV_next (initv_label, iv);
03253 
03254     TY_IDX ty = MTYPE_TO_TY_array[MTYPE_U4];
03255     ST * ereg = Gen_Temp_Named_Symbol (ty, "dummy1", CLASS_VAR,
03256         SCLASS_EH_REGION_SUPP);
03257     Set_ST_is_initialized (*ereg);
03258     Set_ST_is_not_used (*ereg);
03259     INITO_IDX ereg_supp = New_INITO (ST_st_idx(ereg), blk);
03260 
03261     WFE_Stmt_Append (WN_CreateRegion (REGION_KIND_EH, region_body,
03262       WN_CreateBlock(), WN_CreateBlock(), New_Region_Id(), ereg_supp), Get_Srcpos());
03263     Set_PU_has_region (Get_Current_PU());
03264     Set_PU_has_exc_scopes (Get_Current_PU());
03265     
03266     // The following code creat a new TY for the ST that is created 
03267     // above. Because in CG, we will get the size of the ST from its
03268     // TY, we should get its right size from the INITO attached with 
03269     // it, and write it into a new TY
03270     TY_IDX tyi;            
03271     TY& zty = New_TY (tyi);
03272     UINT inito_size = Get_INITO_Size(ereg_supp);
03273     TY_Init (zty, inito_size, KIND_STRUCT, MTYPE_M,ereg->u1.name_idx);
03274     Set_TY_align (tyi, 4);
03275     ST_Init (ereg, TY_name_idx (zty),
03276        CLASS_VAR, SCLASS_EH_REGION_SUPP, EXPORT_LOCAL, tyi);
03277     Set_ST_is_initialized (ereg);
03278 }
03279 #endif // KEY
03280 
03281 static TY_IDX
03282 get_field_type (TY_IDX struct_type, UINT field_id)
03283 {
03284   Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
03285   UINT cur_field_id = 0;
03286   FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
03287   Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
03288                           field_id, struct_type));
03289   return FLD_type (fld);
03290 }
03291 
03292 #ifdef TARG_X8664
03293 // Handle GNU x86 builtins
03294 static WN *
03295 WFE_target_builtins (tree exp, INTRINSIC * iopc, BOOL * intrinsic_op)
03296 {
03297   WN * wn = NULL;
03298                                                                                 
03299   // Assumption: we would be generating intrinsics for most of the builtins
03300   *intrinsic_op = TRUE;
03301                                                                                 
03302   tree func = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
03303   Is_True (TREE_CODE (func) == FUNCTION_DECL && DECL_BUILT_IN (func) &&
03304            DECL_BUILT_IN_CLASS (func) == BUILT_IN_MD, ("Invalid tree node"));
03305                                                                                 
03306   unsigned int ins_code = DECL_FUNCTION_CODE (func);
03307   TYPE_ID res_type = TY_mtype(Get_TY(TREE_TYPE(exp)));
03308   tree t_list = TREE_OPERAND (exp, 1);
03309   WN * arg0 = NULL, * arg1 = NULL;
03310   if (t_list)
03311   {
03312     // Assumption: every builtin has 2 kids: this will change
03313     arg0 = WFE_Expand_Expr (TREE_VALUE (t_list));
03314     if (TREE_CHAIN (t_list))
03315       arg1 = WFE_Expand_Expr (TREE_VALUE (TREE_CHAIN (t_list)));
03316   }
03317                                                                                 
03318   switch (ins_code)
03319   {
03320     // Generate WN
03321     case IX86_BUILTIN_PADDB:
03322     case IX86_BUILTIN_PADDW:
03323     case IX86_BUILTIN_PADDD:
03324     case IX86_BUILTIN_ADDPD:
03325     case IX86_BUILTIN_PADDB128:
03326     case IX86_BUILTIN_PADDW128:
03327     case IX86_BUILTIN_PADDD128:
03328       wn = WN_Add (res_type, arg0, arg1);
03329       *intrinsic_op = FALSE;
03330       break;
03331     case IX86_BUILTIN_PSUBB:
03332     case IX86_BUILTIN_PSUBW:
03333     case IX86_BUILTIN_PSUBD:
03334     case IX86_BUILTIN_SUBPD:
03335     case IX86_BUILTIN_PSUBB128:
03336     case IX86_BUILTIN_PSUBW128:
03337     case IX86_BUILTIN_PSUBD128:
03338       wn = WN_Sub (res_type, arg0, arg1);
03339       *intrinsic_op = FALSE;
03340       break;
03341     case IX86_BUILTIN_PAND:
03342       wn = WN_Band (res_type, arg0, arg1);
03343       *intrinsic_op = FALSE;
03344       break;
03345     case IX86_BUILTIN_PANDN:
03346       wn = WN_Band (res_type, WN_Bnot (res_type, arg0), arg1);
03347       *intrinsic_op = FALSE;
03348       break;
03349     case IX86_BUILTIN_POR:
03350       wn = WN_Bior (res_type, arg0, arg1);
03351       *intrinsic_op = FALSE;
03352       break;
03353     case IX86_BUILTIN_PXOR:
03354       wn = WN_Bxor (res_type, arg0, arg1);
03355       *intrinsic_op = FALSE;
03356       break;
03357                                                                                 
03358     // Generate intrinsics to be expanded in CG expand
03359     case IX86_BUILTIN_PADDSB:
03360       *iopc = INTRN_PADDSB;
03361       break;
03362     case IX86_BUILTIN_PADDSW:
03363       *iopc = INTRN_PADDSW;
03364       break;
03365     case IX86_BUILTIN_PSUBSB:
03366       *iopc = INTRN_PSUBSB;
03367       break;
03368     case IX86_BUILTIN_PSUBSW:
03369       *iopc = INTRN_PSUBSW;
03370       break;
03371     case IX86_BUILTIN_PADDUSB:
03372       *iopc = INTRN_PADDUSB;
03373       break;
03374     case IX86_BUILTIN_PADDUSW:
03375       *iopc = INTRN_PADDUSW;
03376       break;
03377     case IX86_BUILTIN_PSUBUSB:
03378       *iopc = INTRN_PSUBUSB;
03379       break;
03380     case IX86_BUILTIN_PSUBUSW:
03381       *iopc = INTRN_PSUBUSW;
03382       break;
03383     case IX86_BUILTIN_PMULLW:
03384       *iopc = INTRN_PMULLW;
03385       break;
03386     case IX86_BUILTIN_PMULHW:
03387       *iopc = INTRN_PMULHW;
03388       break;
03389     case IX86_BUILTIN_PCMPEQB:
03390       *iopc = INTRN_PCMPEQB;
03391       break;
03392     case IX86_BUILTIN_PCMPEQW:
03393       *iopc = INTRN_PCMPEQW;
03394       break;
03395     case IX86_BUILTIN_PCMPEQD:
03396       *iopc = INTRN_PCMPEQD;
03397       break;
03398     case IX86_BUILTIN_PCMPGTB:
03399       *iopc = INTRN_PCMPGTB;
03400       break;
03401     case IX86_BUILTIN_PCMPGTW:
03402       *iopc = INTRN_PCMPGTW;
03403       break;
03404     case IX86_BUILTIN_PCMPGTD:
03405       *iopc = INTRN_PCMPGTD;
03406       break;
03407     case IX86_BUILTIN_PUNPCKHBW:
03408       *iopc = INTRN_PUNPCKHBW;
03409       break;
03410     case IX86_BUILTIN_PUNPCKHWD:
03411       *iopc = INTRN_PUNPCKHWD;
03412       break;
03413     case IX86_BUILTIN_PUNPCKHDQ:
03414       *iopc = INTRN_PUNPCKHDQ;
03415       break;
03416     case IX86_BUILTIN_PUNPCKLBW:
03417       *iopc = INTRN_PUNPCKLBW;
03418       break;
03419     case IX86_BUILTIN_PUNPCKLWD:
03420       *iopc = INTRN_PUNPCKLWD;
03421       break;
03422     case IX86_BUILTIN_PUNPCKLDQ:
03423       *iopc = INTRN_PUNPCKLDQ;
03424       break;
03425     case IX86_BUILTIN_PACKSSWB:
03426       *iopc = INTRN_PACKSSWB;
03427       break;
03428     case IX86_BUILTIN_PACKSSDW:
03429       *iopc = INTRN_PACKSSDW;
03430       break;
03431     case IX86_BUILTIN_PACKUSWB:
03432       *iopc = INTRN_PACKUSWB;
03433       break;
03434     case IX86_BUILTIN_PMULHUW:
03435       *iopc = INTRN_PMULHUW;
03436       break;
03437     case IX86_BUILTIN_PAVGB:
03438       *iopc = INTRN_PAVGB;
03439       break;
03440     case IX86_BUILTIN_PAVGW:
03441       *iopc = INTRN_PAVGW;
03442       break;
03443     case IX86_BUILTIN_PSADBW:
03444       *iopc = INTRN_PSADBW;
03445       break;
03446     case IX86_BUILTIN_PMAXUB:
03447       *iopc = INTRN_PMAXUB;
03448       break;
03449     case IX86_BUILTIN_PMAXSW:
03450       *iopc = INTRN_PMAXSW;
03451       break;
03452     case IX86_BUILTIN_PMINUB:
03453       *iopc = INTRN_PMINUB;
03454       break;
03455     case IX86_BUILTIN_PMINSW:
03456       *iopc = INTRN_PMINSW;
03457       break;
03458     case IX86_BUILTIN_PEXTRW:
03459       {
03460         Is_True (TREE_CODE (TREE_VALUE (TREE_CHAIN (t_list))) == INTEGER_CST,
03461                  ("Immediate value required by pextrw"));
03462         UINT val = Get_Integer_Value (TREE_VALUE (TREE_CHAIN (t_list)));
03463         switch (val)
03464         {
03465           case 0:
03466             *iopc = INTRN_PEXTRW0;
03467             break;
03468           case 1:
03469             *iopc = INTRN_PEXTRW1;
03470             break;
03471           case 2:
03472             *iopc = INTRN_PEXTRW2;
03473             break;
03474           case 3:
03475             *iopc = INTRN_PEXTRW3;
03476             break;
03477           default:
03478             Fail_FmtAssertion ("Invalid imm value %d to pextrw", val);
03479         }
03480         TY_IDX arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(t_list)));
03481         TYPE_ID arg_mtype  = TY_mtype(arg_ty_idx);
03482         arg0     = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
03483                                   arg_ty_idx, WN_PARM_BY_VALUE);
03484         wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, MTYPE_U4, MTYPE_V,
03485                                       *iopc, 1, &arg0);
03486         break;
03487       }
03488     case IX86_BUILTIN_PINSRW:
03489       {
03490         Is_True (TREE_CODE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t_list)))) == INTEGER_CST, ("Immediate value required by pinsrw"));
03491         UINT val = Get_Integer_Value (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t_list))));
03492         switch (val)
03493         {
03494           case 0:
03495             *iopc = INTRN_PINSRW0;
03496             break;
03497           case 1:
03498             *iopc = INTRN_PINSRW1;
03499             break;
03500           case 2:
03501             *iopc = INTRN_PINSRW2;
03502             break;
03503           case 3:
03504             *iopc = INTRN_PINSRW3;
03505             break;
03506           default:
03507             Fail_FmtAssertion ("Invalid imm value %d to pinsrw", val);
03508                                                                                 
03509         }
03510         WN * args[2];
03511         for (int c=0; c<2; c++)
03512         {
03513             TY_IDX arg_ty_idx = Get_TY (TREE_TYPE (TREE_VALUE (t_list)));
03514             TYPE_ID arg_mtype = TY_mtype (arg_ty_idx);
03515             args[c] = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
03516                                         arg_ty_idx, WN_PARM_BY_VALUE);
03517             t_list = TREE_CHAIN (t_list);
03518             arg0 = arg1;
03519         }
03520                                                                                 
03521         wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, MTYPE_M8I2, MTYPE_V,
03522                                   *iopc, 2, args);
03523         break;
03524       }
03525     case IX86_BUILTIN_PMOVMSKB:
03526       *iopc = INTRN_PMOVMSKB;
03527       break;
03528     case IX86_BUILTIN_ADDPS:
03529       *iopc = INTRN_ADDPS;
03530       break;
03531     case IX86_BUILTIN_SUBPS:
03532       *iopc = INTRN_SUBPS;
03533       break;
03534     case IX86_BUILTIN_MULPS:
03535       *iopc = INTRN_MULPS;
03536       break;
03537     case IX86_BUILTIN_DIVPS:
03538       *iopc = INTRN_DIVPS;
03539       break;
03540     case IX86_BUILTIN_ADDSS:
03541       *iopc = INTRN_ADDSS;
03542       break;
03543     case IX86_BUILTIN_SUBSS:
03544       *iopc = INTRN_SUBSS;
03545       break;
03546     case IX86_BUILTIN_MULSS:
03547       *iopc = INTRN_MULSS;
03548       break;
03549     case IX86_BUILTIN_DIVSS:
03550       *iopc = INTRN_DIVSS;
03551       break;
03552     case IX86_BUILTIN_CMPEQPS:
03553       *iopc = INTRN_CMPEQPS;
03554       break;
03555     case IX86_BUILTIN_CMPLTPS:
03556       *iopc = INTRN_CMPLTPS;
03557       break;
03558     case IX86_BUILTIN_CMPLEPS:
03559       *iopc = INTRN_CMPLEPS;
03560       break;
03561     case IX86_BUILTIN_CMPGTPS:
03562       *iopc = INTRN_CMPGTPS;
03563       break;
03564     case IX86_BUILTIN_CMPGEPS:
03565       *iopc = INTRN_CMPGEPS;
03566       break;
03567     case IX86_BUILTIN_CMPUNORDPS:
03568       *iopc = INTRN_CMPUNORDPS;
03569       break;
03570     case IX86_BUILTIN_CMPNEQPS:
03571       *iopc = INTRN_CMPNEQPS;
03572       break;
03573     case IX86_BUILTIN_CMPNLTPS:
03574       *iopc = INTRN_CMPNLTPS;
03575       break;
03576     case IX86_BUILTIN_CMPNLEPS:
03577       *iopc = INTRN_CMPNLEPS;
03578       break;
03579     case IX86_BUILTIN_CMPNGTPS:
03580       *iopc = INTRN_CMPNGTPS;
03581       break;
03582     case IX86_BUILTIN_CMPNGEPS:
03583       *iopc = INTRN_CMPNGEPS;
03584       break;
03585     case IX86_BUILTIN_CMPORDPS:
03586       *iopc = INTRN_CMPORDPS;
03587       break;
03588     case IX86_BUILTIN_CMPEQSS:
03589       *iopc = INTRN_CMPEQSS;
03590       break;
03591     case IX86_BUILTIN_CMPLTSS:
03592       *iopc = INTRN_CMPLTSS;
03593       break;
03594     case IX86_BUILTIN_CMPLESS:
03595       *iopc = INTRN_CMPLESS;
03596       break;
03597     case IX86_BUILTIN_CMPUNORDSS:
03598       *iopc = INTRN_CMPUNORDSS;
03599       break;
03600     case IX86_BUILTIN_CMPNEQSS:
03601       *iopc = INTRN_CMPNEQSS;
03602       break;
03603     case IX86_BUILTIN_CMPNLTSS:
03604       *iopc = INTRN_CMPNLTSS;
03605       break;
03606     case IX86_BUILTIN_CMPNLESS:
03607       *iopc = INTRN_CMPNLESS;
03608       break;
03609     case IX86_BUILTIN_CMPORDSS:
03610       *iopc = INTRN_CMPORDSS;
03611       break;
03612     case IX86_BUILTIN_MAXPS:
03613       *iopc = INTRN_MAXPS;
03614       break;
03615     case IX86_BUILTIN_MAXSS:
03616       *iopc = INTRN_MAXSS;
03617       break;
03618     case IX86_BUILTIN_MINPS:
03619       *iopc = INTRN_MINPS;
03620       break;
03621     case IX86_BUILTIN_MINSS:
03622       *iopc = INTRN_MINSS;
03623       break;
03624     case IX86_BUILTIN_ANDPS:
03625       *iopc = INTRN_ANDPS;
03626       break;
03627     case IX86_BUILTIN_ANDNPS:
03628       *iopc = INTRN_ANDNPS;
03629       break;
03630     case IX86_BUILTIN_ORPS:
03631       *iopc = INTRN_ORPS;
03632       break;
03633     case IX86_BUILTIN_XORPS:
03634       *iopc = INTRN_XORPS;
03635       break;
03636     case IX86_BUILTIN_MOVSS:
03637       *iopc = INTRN_MOVSS;
03638       break;
03639     case IX86_BUILTIN_MOVHLPS:
03640       *iopc = INTRN_MOVHLPS;
03641       break;
03642     case IX86_BUILTIN_MOVLHPS:
03643       *iopc = INTRN_MOVLHPS;
03644       break;
03645     case IX86_BUILTIN_UNPCKHPS:
03646       *iopc = INTRN_UNPCKHPS;
03647       break;
03648     case IX86_BUILTIN_UNPCKLPS:
03649       *iopc = INTRN_UNPCKLPS;
03650       break;
03651     case IX86_BUILTIN_RCPPS:
03652       *iopc = INTRN_RCPPS;
03653       break;
03654     case IX86_BUILTIN_RSQRTPS:
03655       *iopc = INTRN_RSQRTPS;
03656       break;
03657     case IX86_BUILTIN_SQRTPS:
03658       *iopc = INTRN_SQRTPS;
03659       break;
03660     case IX86_BUILTIN_RCPSS:
03661       *iopc = INTRN_RCPSS;
03662       break;
03663     case IX86_BUILTIN_RSQRTSS:
03664       *iopc = INTRN_RSQRTSS;
03665       break;
03666     case IX86_BUILTIN_SQRTSS:
03667       *iopc = INTRN_SQRTSS;
03668       break;
03669     case IX86_BUILTIN_SHUFPS:
03670       *iopc = INTRN_SHUFPS;
03671       break;
03672     case IX86_BUILTIN_EMMS:
03673       *iopc = INTRN_EMMS;
03674       *intrinsic_op = FALSE;
03675       break;
03676     case IX86_BUILTIN_LOADAPS:
03677       *iopc = INTRN_LOADAPS;
03678       break;
03679     case IX86_BUILTIN_STOREAPS:
03680       *iopc = INTRN_STOREAPS;
03681       *intrinsic_op = FALSE;
03682       break;
03683     case IX86_BUILTIN_PXOR128:
03684       wn = WN_Bxor (res_type, arg0, arg1);
03685       *intrinsic_op = FALSE;
03686       break;
03687     case IX86_BUILTIN_PSLLDQI128:
03688       *iopc = INTRN_PSLLDQ;
03689       break;
03690     case IX86_BUILTIN_PSRLDQI128:
03691       *iopc = INTRN_PSRLDQ;
03692       break;
03693     case IX86_BUILTIN_PSLLW128:
03694       *iopc = INTRN_PSLLW;
03695       break;
03696     case IX86_BUILTIN_PSLLD128:
03697       *iopc = INTRN_PSLLD;
03698       break;
03699     case IX86_BUILTIN_PSLLQ128:
03700       *iopc = INTRN_PSLLQ;
03701       break;
03702     case IX86_BUILTIN_PSRLW128:
03703       *iopc = INTRN_PSRLW;
03704       break;
03705     case IX86_BUILTIN_PSRLD128:
03706       *iopc = INTRN_PSRLD;
03707       break;
03708     case IX86_BUILTIN_PSRLQ128:
03709       *iopc = INTRN_PSRLQ;
03710       break;
03711     case IX86_BUILTIN_PSRAW128:
03712       *iopc = INTRN_PSRAW;
03713       break;
03714     case IX86_BUILTIN_PSRAD128:
03715       *iopc = INTRN_PSRAD;
03716       break;
03717     case IX86_BUILTIN_PSRAWI128:
03718       *iopc = INTRN_PSRAW;
03719       break;
03720     case IX86_BUILTIN_PSRADI128:
03721       *iopc = INTRN_PSRAD;
03722       break;
03723     case IX86_BUILTIN_PSLLWI128:
03724       *iopc = INTRN_PSLLW;
03725       break;
03726     case IX86_BUILTIN_PSLLDI128:
03727       *iopc = INTRN_PSLLD;
03728       break;
03729     case IX86_BUILTIN_PSLLQI128:
03730       *iopc = INTRN_PSLLQ;
03731       break;
03732     case IX86_BUILTIN_PSRLWI128:
03733       *iopc = INTRN_PSRLW;
03734       break;
03735     case IX86_BUILTIN_PSRLDI128:
03736       *iopc = INTRN_PSRLD;
03737       break;
03738     case IX86_BUILTIN_PSRLQI128:
03739       *iopc = INTRN_PSRLQ;
03740       break;
03741     case IX86_BUILTIN_MOVNTDQ:
03742       *iopc = INTRN_MOVNTDQ;
03743       *intrinsic_op = FALSE;
03744       break;
03745     case IX86_BUILTIN_LOADD:
03746       *iopc = INTRN_LOADD;
03747       break;
03748     case IX86_BUILTIN_MOVNTPS:
03749       *iopc = INTRN_MOVNTPS;
03750       *intrinsic_op = FALSE;
03751       break;
03752     case IX86_BUILTIN_SSE_ZERO:
03753       *iopc = INTRN_SSE_ZERO;
03754       *intrinsic_op = FALSE;
03755       break;
03756     case IX86_BUILTIN_CLRTI:
03757       *iopc = INTRN_CLRTI;
03758       *intrinsic_op = FALSE;
03759       break;
03760     case IX86_BUILTIN_PSHUFD:
03761       *iopc = INTRN_PSHUFD;
03762       break;
03763     case IX86_BUILTIN_LOADSS:
03764       *iopc = INTRN_LOADSS;
03765       break;
03766     case IX86_BUILTIN_DIVPD:
03767       wn = WN_Div (res_type, arg0, arg1);
03768       *intrinsic_op = FALSE;
03769       break;
03770     case IX86_BUILTIN_MULPD:
03771       wn = WN_Mpy (res_type, arg0, arg1);
03772       *intrinsic_op = FALSE;
03773       break;
03774     case IX86_BUILTIN_SQRTPD:
03775       wn = WN_Sqrt (res_type, arg0);
03776       *intrinsic_op = FALSE;
03777       break;
03778     case IX86_BUILTIN_MINPD:
03779       wn = WN_Binary (OPR_MIN, res_type, arg0, arg1);
03780       *intrinsic_op = FALSE;
03781       break;
03782     case IX86_BUILTIN_MAXPD:
03783       wn = WN_Binary (OPR_MAX, res_type, arg0, arg1);
03784       *intrinsic_op = FALSE;
03785       break;
03786     case IX86_BUILTIN_SHUFPD:
03787       *iopc = INTRN_SHUFPD;
03788       break;
03789     case IX86_BUILTIN_XORPD:
03790       *iopc = INTRN_XORPD;
03791       break;
03792     case IX86_BUILTIN_ANDPD:
03793       *iopc = INTRN_ANDPD;
03794       break;
03795     case IX86_BUILTIN_ORPD:
03796       *iopc = INTRN_ORPD;
03797       break;
03798     case IX86_BUILTIN_STORELPD:
03799       *iopc = INTRN_STORELPD;
03800       *intrinsic_op = FALSE;
03801       break;
03802     case IX86_BUILTIN_STOREHPD:
03803       *iopc = INTRN_STOREHPD;
03804       *intrinsic_op = FALSE;
03805       break;
03806     case IX86_BUILTIN_LOADLPD:
03807       *iopc = INTRN_LOADLPD;
03808       break;
03809     case IX86_BUILTIN_LOADHPD:
03810       *iopc = INTRN_LOADHPD;
03811       break;
03812     case IX86_BUILTIN_UNPCKLPD:
03813       *iopc = INTRN_UNPCKLPD;
03814       break;
03815     case IX86_BUILTIN_UNPCKHPD:
03816       *iopc = INTRN_UNPCKHPD;
03817       break;
03818     case IX86_BUILTIN_LFENCE:
03819       *iopc = INTRN_LFENCE;
03820       *intrinsic_op = FALSE;
03821       break;
03822     case IX86_BUILTIN_MFENCE:
03823       *iopc = INTRN_MFENCE;
03824       *intrinsic_op = FALSE;
03825       break;
03826     case IX86_BUILTIN_SFENCE:
03827       *iopc = INTRN_SFENCE;
03828       *intrinsic_op = FALSE;
03829       break;
03830     case IX86_BUILTIN_PSHUFW:
03831       *iopc = INTRN_PSHUFW;
03832       break;
03833     case IX86_BUILTIN_LOADDQA:
03834       *iopc = INTRN_LOADDQA;
03835       break;
03836     case IX86_BUILTIN_LOADDQU:
03837       *iopc = INTRN_LOADDQU;
03838       break;
03839     case IX86_BUILTIN_STOREDQA:
03840       *iopc = INTRN_STOREDQA;
03841       *intrinsic_op = FALSE;
03842       break;
03843     case IX86_BUILTIN_STOREDQU:
03844       *iopc = INTRN_STOREDQU;
03845       *intrinsic_op = FALSE;
03846       break;
03847     case IX86_BUILTIN_MOVNTI:
03848       *iopc = INTRN_MOVNTI;
03849       *intrinsic_op = FALSE;
03850       break;
03851                                                                                 
03852     default:
03853       if (Opt_Level > 0)
03854       { // Don't assert in front-end. If used, backend will assert.
03855         *iopc = INTRN_UNIMP_PURE;
03856         if (res_type == MTYPE_V)
03857         {
03858           *iopc = INTRN_UNIMP;
03859           *intrinsic_op = FALSE;
03860         }
03861       }
03862       else
03863       {
03864         *intrinsic_op = FALSE;
03865         // For simplicity, generate a U8 constant, and then use a cvt
03866         // if necessary. If void result type, generate a placeholder eval.
03867         wn = WN_Intconst (MTYPE_U8, 0);
03868         if (res_type != MTYPE_U8 && res_type != MTYPE_V)
03869           wn = WN_Cvt (MTYPE_U8, res_type, wn);
03870       }
03871       break;
03872   }
03873                                                                                 
03874   // The following instructions expect both arguments as FP (xmm), but
03875   // the 2nd argument type for the corresponding builtin is INT, so we
03876   // need to insert a CVT here.
03877   switch (ins_code)
03878   {
03879     case IX86_BUILTIN_PSRAWI128:
03880     case IX86_BUILTIN_PSRADI128:
03881     case IX86_BUILTIN_PSLLWI128:
03882     case IX86_BUILTIN_PSLLDI128:
03883     case IX86_BUILTIN_PSLLQI128:
03884     case IX86_BUILTIN_PSRLWI128:
03885     case IX86_BUILTIN_PSRLDI128:
03886     case IX86_BUILTIN_PSRLQI128:
03887       Is_True (wn == NULL, ("WFE_target_builtins: null WN expected"));
03888       WN * args[2];
03889       //for (int c=0; c<2; c++)
03890       {
03891         // 1st argument
03892         TY_IDX arg_ty_idx = Get_TY (TREE_TYPE (TREE_VALUE (t_list)));
03893         TYPE_ID arg_mtype = TY_mtype (arg_ty_idx);
03894         args[0] = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
03895                                  arg_ty_idx, WN_PARM_BY_VALUE);
03896                                                                                 
03897         // 2nd argument
03898         arg1 = WN_Cvt (WN_rtype(arg1), MTYPE_V16I8, arg1);
03899         arg_ty_idx = MTYPE_TO_TY_array[WN_rtype (arg1)];
03900         arg_mtype = WN_rtype (arg1);
03901         args[1] = WN_CreateParm (Mtype_comparison (arg_mtype), arg1,
03902                                  arg_ty_idx, WN_PARM_BY_VALUE);
03903       }
03904                                                                                 
03905       wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, res_type, MTYPE_V,
03906                                 *iopc, 2, args);
03907       break;
03908   }
03909                                                                                 
03910   return wn;
03911 }
03912 #endif // TARG_X8664
03913 
03914 #ifdef TARG_SL
03915 BOOL 
03916 Has_LDA_Node(WN* tree) {
03917   BOOL has_lda = FALSE;
03918   for(INT i = 0; i < WN_kid_count(tree); i++) {
03919     has_lda |= Has_LDA_Node(WN_kid(tree, i));
03920     if(has_lda)
03921       break;         
03922   }
03923   if( WN_operator(tree) == OPR_LDA) {
03924     return TRUE;
03925   }
03926   return has_lda;
03927 }
03928 
03929 BOOL 
03930 Mark_LDA_Vbuf_Offset(WN* tree, INTRINSIC iopc ) {
03931 
03932   BOOL has_v1buf_lda = FALSE; 
03933   static vector < WN* > processed; 
03934 
03935   if(find(processed.begin(), processed.end(), tree) != processed.end()) 
03936     return has_v1buf_lda;
03937 
03938   for(INT i = 0; i < WN_kid_count(tree); i++) {
03939     has_v1buf_lda |= Mark_LDA_Vbuf_Offset(WN_kid(tree, i), iopc);
03940   }
03941 
03942   if(WN_operator(tree) == OPR_LDA) {
03943     if( ST_in_vbuf(WN_st(tree)) && iopc == INTRN_VBUF_OFFSET) {
03944       WN_Set_is_internal_mem_ofst(tree);
03945       Set_ST_is_vbuf_ofst(WN_st(tree));
03946       if(ST_in_v1buf(WN_st(tree))) 
03947         has_v1buf_lda = TRUE;
03948     }     
03949     else if(ST_in_sbuf(WN_st(tree)) && iopc == INTRN_SBUF_OFFSET) {
03950       WN_Set_is_internal_mem_ofst(tree);
03951       Set_ST_is_sbuf_ofst(WN_st(tree));
03952     }     
03953   }
03954 
03955   processed.push_back(tree); 
03956 
03957   return has_v1buf_lda; 
03958 }
03959 
03960 
03961 BOOL 
03962 May_Include_Vbuf_Offset(INTRINSIC iopc, WN* call) {
03963   switch(iopc) {
03964     case INTRN_C2_LD_V:
03965     case INTRN_C2_ST_V:
03966     case INTRN_C2_ST_G2V:
03967     case INTRN_C2_ST_G:
03968       return Has_LDA_Node(WN_kid0(WN_kid1(call)));
03969     case INTRN_C2_LD_V2G:
03970     case INTRN_C2_LD_G:
03971       return Has_LDA_Node(WN_kid0(WN_kid0(call)));
03972     default:
03973       return FALSE;
03974   }
03975 }
03976 #endif 
03977 
03978 /* expand gnu expr tree into symtab & whirl */
03979 WN *
03980 WFE_Expand_Expr (tree exp, 
03981      bool need_result,
03982      TY_IDX nop_ty_idx, 
03983      TY_IDX component_ty_idx, 
03984      INT64 component_offset,
03985      UINT16 field_id,
03986      bool is_bit_field,
03987      bool is_aggr_init_via_ctor
03988 #ifdef KEY
03989      , WN *target_wn
03990 #endif
03991      )
03992 {
03993   FmtAssert(exp != NULL_TREE, ("WFE_Expand_Expr: null argument"));
03994   enum tree_code code = TREE_CODE (exp);
03995   WN *wn, *wn0, *wn1, *wn2;
03996   ST *st;
03997   TY_IDX ty_idx;
03998   TY_IDX desc_ty_idx;
03999   tree arg0, arg1, arg2;
04000 #ifdef KEY
04001   static BOOL must_not_throw = FALSE;
04002 #endif
04003 
04004   wn = NULL;
04005 
04006 #ifdef WFE_DEBUG
04007   fprintf (stderr,
04008            "{( WFE_Expand_Expr: %s\n", Operator_From_Tree [code].name); // ")}"
04009 #endif /* WFE_DEBUG */
04010 
04011   switch (code)
04012     {
04013     // leaves
04014     case ADDR_EXPR:
04015       wn = WFE_Address_Of(TREE_OPERAND(exp, 0));
04016       break;
04017       
04018     /*FDESC_EXPR:
04019      *Operand0 is a function constant; result is part N of a function 
04020      *descriptor of type ptr_mode. 
04021      *So we should get function constant and exprand it.
04022      */
04023     case FDESC_EXPR:
04024       {
04025   tree exp_operand = TREE_OPERAND(exp, 0);
04026   FmtAssert(TREE_CODE(exp_operand) == FUNCTION_DECL,("Unexpected Tree Code!!"));
04027   st = Get_ST (exp_operand);
04028   ty_idx = ST_type (st);
04029   wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
04030       }
04031       break;
04032       
04033     case FUNCTION_DECL:
04034       {
04035    st = Get_ST (exp);
04036    ty_idx = ST_type (st);
04037    wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
04038       }
04039       break;
04040 
04041     case TREE_LIST: 
04042       {
04043   tree stmt;
04044   for (stmt = TREE_PURPOSE(exp); stmt; stmt = TREE_CHAIN(stmt))
04045     WFE_Expand_Stmt (stmt);
04046   wn = WFE_Expand_Expr (TREE_VALUE(exp));
04047       }
04048       break;
04049 
04050     case DECL_STMT:
04051       {
04052         tree decl = DECL_STMT_DECL(exp);
04053   WFE_Expand_Decl (decl);
04054   wn = WFE_Expand_Expr (decl);
04055       }
04056       break;
04057 
04058     case BIND_EXPR:
04059 #ifdef GPLUSPLUS_FE
04060       DevWarn ("Encountered BIND_EXPR at line %d", lineno);
04061       // ignore the first operand as it ia a list of temporary variables
04062       wn = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
04063       break;
04064 #else
04065       {
04066         INT32    i;
04067         WN      *block;
04068         TYPE_ID  mtype;
04069         tree     t;
04070 
04071   DevWarn ("Encountered BIND_EXPR at line %d", lineno);
04072 
04073         for (i = wfe_bind_expr_stack_last; i >= 0; --i) {
04074 
04075           if (wfe_bind_expr_stack [i].rtl_expr == TREE_OPERAND (exp, 1)) {
04076 
04077             block = wfe_bind_expr_stack [i].block;
04078             t     = wfe_bind_expr_stack [i].rtl_expr;
04079             wfe_bind_expr_stack [i] = wfe_bind_expr_stack [wfe_bind_expr_stack_last];
04080             --wfe_bind_expr_stack_last;
04081             break;
04082           }
04083         }
04084 
04085         FmtAssert (i >= 0,
04086                    ("BIND_EXPR: did not find tree"));
04087   ty_idx = Get_TY (TREE_TYPE(t));
04088         mtype  = TY_mtype (ty_idx);
04089   if (mtype == MTYPE_V) {
04090     WFE_Stmt_Append (block, Get_Srcpos ());
04091           break;
04092   }
04093   else {
04094     wn0 = block;
04095     wn1 = WN_COPY_Tree (WN_last (wn0));
04096     WN_DELETE_FromBlock (wn0, WN_last (wn0));
04097     WFE_Stmt_Append (wn0, Get_Srcpos ());
04098     if (nop_ty_idx == 0 && component_ty_idx == 0) {
04099       wn = WN_kid0 (wn1);
04100             break;
04101     }
04102           if (WN_operator (WN_kid0 (wn1)) == OPR_LDID)
04103             st = WN_st (WN_kid0 (wn1));
04104           else {
04105             st = Gen_Temp_Symbol (ty_idx, "__bind_expr");
04106 #ifdef KEY
04107         WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
04108 #endif
04109             WFE_Set_ST_Addr_Saved (WN_kid0 (wn1));
04110             wn0 = WN_Stid (mtype, 0, st, ty_idx, WN_kid0 (wn1));
04111             WFE_Stmt_Append (wn0, Get_Srcpos ());
04112           }
04113   }
04114       }
04115       /*FALLTHRU*/
04116 #endif /* GPLUSPLUS_FE */
04117 
04118     case TARGET_EXPR:
04119       {
04120   tree opnd0 = TREE_OPERAND(exp, 0);
04121   st = NULL;
04122   TY_IDX ty;
04123   TYPE_ID mtype;
04124 #ifdef KEY
04125   // If we are supposed to put the result in target_wn, then give the
04126   // init target the same ST as target_wn.
04127   if (target_wn != NULL) {
04128     if (WN_operator(target_wn) == OPR_LDA) {
04129       FmtAssert(TREE_CODE(opnd0) != INDIRECT_REF,
04130           ("WFE_Expand_Expr: write target mismtach"));
04131       set_DECL_ST(opnd0, WN_st(target_wn));
04132     } else if (WN_operator(target_wn) == OPR_LDID) {
04133       // Change the target into an INDIRECT_REF only if we have not done
04134       // so.
04135       if (TREE_CODE(opnd0) == VAR_DECL) {
04136         tree ptr_var = build_decl(VAR_DECL, NULL_TREE,
04137           build_pointer_type(TREE_TYPE(opnd0)));
04138         TREE_SET_CODE(opnd0, INDIRECT_REF);
04139         TREE_OPERAND(opnd0, 0) = ptr_var;
04140         set_DECL_ST(ptr_var, WN_st(target_wn));
04141       }
04142     }
04143   }
04144 
04145   // We might have changed the VAR_DECL to an INDIRECT_REF, in which case
04146   // use the referenced symbol instead of creating a new one.
04147   if (TREE_CODE(opnd0) != INDIRECT_REF)
04148 #endif
04149   {
04150   st    = Get_ST (TREE_OPERAND(exp, 0));
04151   ty    = ST_type(st);
04152   mtype = TY_mtype (ty);
04153   }
04154   /*
04155    * Usually operand 1 of the target_expr will be an aggr_init_expr
04156    * for which AGGR_INIT_VIA_CTOR_P holds.  Such a node has the
04157    * annoying property that its first argument is not the expected
04158    * argument to the constructor call.  Instead the argument whose
04159    * address should be passed to the constructor appears as 
04160    * operand 2.  The value in operand 2, however, is not always
04161    * right:  it is the original temporary var_decl from the
04162    * target_expr.  What we really want is the current operand 0
04163    * of the target_expr, which may have been changed (see INIT_EXPR).
04164    * This is really ugly, but we can't help it because at the
04165    * expression level we need to stay compatible with the current
04166    * rtl generation.
04167    * So we're going to replace the first argument of the aggr_init_expr
04168    * with the var_decl from operand 0 of the target_expr, and pass
04169    * is_aggr_init_via_ctor to WFE_Expand_Expr, so it can be dealt
04170    * with by the AGGR_INIT_EXPR/CALL_EXPR code.
04171    *
04172    * If a target expression is initialized by a target expression,
04173    * it ought not to have an associated cleanup, so we clear the
04174    * cleanup in this case.
04175    */
04176   tree t = TREE_OPERAND(exp, 1);
04177 #ifdef KEY
04178   if (t == NULL_TREE) {
04179     t = TREE_OPERAND(exp, 3);
04180     FmtAssert(t != NULL_TREE,
04181         ("WFE_Expand_Expr: no initializer found for TARGET_EXPR"));
04182   }
04183 #endif
04184   if (TREE_CODE(t) == TARGET_EXPR)
04185     TREE_OPERAND(t, 2) = 0;
04186   if (TREE_CODE(t) == AGGR_INIT_EXPR && AGGR_INIT_VIA_CTOR_P(t)) {
04187     tree args = TREE_OPERAND(t, 1);
04188     TREE_VALUE(args) = TREE_OPERAND(exp, 0);
04189     WFE_Expand_Expr (t, false, 0, 0, 0, 0, false, true);
04190   }
04191   else {
04192 #ifdef KEY
04193     // If opnd 0 of the TARGET_EXPR is an INDIRECT_REF, then tell
04194     // WFE_Expand_Expr to put the result in the area addressed by the
04195     // INDIRECT_REF.
04196           // OSP_397, initializing member of a class having copy-constructor
04197           // This fix is done by Pathscale. Thanks
04198           // If opnd0 is not DECL, then generate the addr of opnd 0
04199           // Otherwise, get the ST and get the addr of the st
04200           if (TREE_CODE(opnd0) == INDIRECT_REF) {
04201             if (TREE_CODE_CLASS(TREE_CODE(TREE_OPERAND(opnd0,0))) != 'd') {
04202               WN * target_wn = WFE_Address_Of (opnd0);
04203               WFE_Expand_Expr (t, TRUE /* for return_in_mem */,
04204                                0, 0, 0, 0, FALSE, FALSE, target_wn);
04205             }
04206             else {
04207         ST *st = Get_ST(TREE_OPERAND(opnd0, 0));
04208         WN *ldid_wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type(st));
04209         WN *result_wn = WFE_Expand_Expr (t, TRUE, 0, 0, 0, 0, FALSE, FALSE,
04210                                                ldid_wn);
04211         // If the result of expanding t is not an indirect reference to the
04212         // result area we want, then it means t has not copied the value
04213         // into the result area.  Do the copy.
04214         if (result_wn &&
04215                   !(WN_operator(result_wn) == OPR_ILOAD &&
04216         WN_operator(WN_kid0(result_wn)) == OPR_LDID &&
04217         WN_st(WN_kid0(result_wn)) == st)) {
04218           WFE_Stmt_Append(WN_Istore(WN_rtype(result_wn), 0, ST_type(st),
04219                                           WN_CopyNode(ldid_wn), result_wn),
04220                                 Get_Srcpos());
04221         }
04222             }
04223     }
04224     // If the initializer returns the object in memory, then make sure
04225     // the type doesn't require a copy constructor, since such types
04226     // sometimes require one.
04227     //
04228     // Note when one stmt like "bool_expr ? Default Constructor : throw 0;"
04229     // the TY_return_in_mem(Get_TY(TREE_TYPE(t)) return 0, so add another
04230     // condition for this case.
04231     else if (TY_return_in_mem(Get_TY(TREE_TYPE(t))) || 
04232        ((TY_mtype (Get_TY(TREE_TYPE(t))) == MTYPE_M) &&
04233         (TREE_CODE(t) == COND_EXPR))) {
04234       if (TREE_CODE(t) == VAR_DECL ||
04235     TREE_CODE(t) == PARM_DECL) {
04236         // The initializer is a var or parm.  We need to insert copy.
04237         // First make sure type has no copy constructor.
04238         WN *rhs_wn = WFE_Expand_Expr (t);
04239         tree type = TREE_TYPE(TREE_OPERAND(exp, 0));
04240         Is_True(!WFE_has_copy_constructor(type),
04241           ("WFE_Expand_Expr: type require copy constructor"));
04242         WFE_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty, rhs_wn),
04243             Get_Srcpos());
04244       } else {
04245         // The initializer is an expression.  Try to expand it directly
04246         // into the target.
04247         WN *target_wn = WN_Lda (Pointer_Mtype, 0, st, 0);
04248         WN *result_wn = WFE_Expand_Expr (t, TRUE, 0, 0, 0, 0, FALSE,
04249                  FALSE, target_wn);
04250         // If expanding t did not write the result into the target as a
04251         // side effect, then create the copy.
04252         if (result_wn) {
04253     // There may be more cases where we need to store the result.
04254     // Need to find a better way to catch them all.
04255     if (WN_operator(result_wn) == OPR_ILOAD) {
04256       WFE_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty,
04257           result_wn), Get_Srcpos());
04258     } else if (WN_operator(result_wn) == OPR_CSELECT) {
04259       WN *wn = WN_CreateEval(result_wn);
04260       WFE_Stmt_Append(wn, Get_Srcpos());
04261     }
04262         }
04263       }
04264     } else {
04265       // Bug 7862: Set addr_saved flag if the initializer is an LDA.
04266       WN * init = WFE_Expand_Expr (t);
04267       if (WN_operator (init) == OPR_LDA)
04268         WFE_Set_ST_Addr_Saved (init);
04269       WFE_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty, init),
04270           Get_Srcpos());
04271     }
04272 #else
04273     WFE_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty,
04274                  WFE_Expand_Expr (t)),
04275         Get_Srcpos());
04276 #endif
04277   }
04278         if (TREE_OPERAND(exp, 2) 
04279 #ifdef KEY
04280 // We should not be emitting all cleanups
04281   && TREE_LANG_FLAG_7 (exp)
04282 #endif
04283   )
04284 #ifdef KEY
04285           Push_Temp_Cleanup(TREE_OPERAND(exp, 2), true, CLEANUP_EH_ONLY (exp));
04286 #else
04287           Push_Temp_Cleanup(TREE_OPERAND(exp, 2), true);
04288 #endif
04289 
04290 #ifdef KEY
04291   // If the target area was supplied by the caller, then return an ILOAD
04292   // of the target pointer.
04293         // OSP_397, fix by Pathscale.
04294         // If the opnd0 is a DECL, then get the ST and load from the st
04295         // Otherwise, expand opnd 0
04296         if (TREE_CODE(opnd0) == INDIRECT_REF) {
04297           if (TREE_CODE_CLASS(TREE_CODE(TREE_OPERAND(opnd0,0))) == 'd') {
04298             ST *st = Get_ST(TREE_OPERAND(opnd0, 0));
04299             TY_IDX ty_idx = Get_TY (TREE_TYPE(exp));
04300             WN *ldid_wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type(st));
04301             wn = WN_Iload(TY_mtype(ty_idx), 0, ty_idx, ldid_wn);
04302             break;
04303           }
04304           else {
04305             wn = WFE_Expand_Expr(opnd0);
04306       break;
04307           }
04308         }
04309 #endif
04310       }
04311 
04312     case CONSTRUCTOR:
04313 #ifdef KEY
04314       // In general, if the result is not needed and EXP has no side effects,
04315       // then there is no need to expand EXP, regardless of what EXP is.  This
04316       // is what gcc's expand_expr does.  However, doing so breaks the WHIRL
04317       // front-end, so limit this to CONSTRUCTOR for now.
04318       if (!need_result &&
04319     !TREE_SIDE_EFFECTS(exp)) {
04320   return NULL;
04321       }
04322 #endif
04323 
04324     case PARM_DECL: // for formal parms
04325     case VAR_DECL:
04326       {
04327   UINT xtra_BE_ofst = 0;  // only needed for big-endian target
04328         PREG_NUM preg_num = 0;
04329   desc_ty_idx = component_ty_idx;
04330   TY_IDX hi_ty_idx = Get_TY (TREE_TYPE(exp));
04331   if (desc_ty_idx == 0)
04332     desc_ty_idx = hi_ty_idx;
04333 
04334   if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
04335     ty_idx = desc_ty_idx;
04336   else {
04337     ty_idx = nop_ty_idx;
04338     if (ty_idx == 0) 
04339       ty_idx = desc_ty_idx;
04340   }
04341 
04342   UINT cvtl_size = 0; // if non-zero, need to generate CVTL with this size
04343   if (! is_bit_field) {
04344     if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
04345       if (Target_Byte_Sex == BIG_ENDIAN)
04346         xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
04347       cvtl_size = TY_size(ty_idx) * 8;
04348       ty_idx = desc_ty_idx;
04349     }
04350   }
04351   else {
04352     if (TY_size(desc_ty_idx) > TY_size(ty_idx)) 
04353       ty_idx = desc_ty_idx;
04354   }
04355 
04356         TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
04357         TYPE_ID desc = TY_mtype(desc_ty_idx);
04358         if (MTYPE_is_integral(desc)) {
04359           if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
04360             if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
04361     is_bit_field)
04362               rtype = Mtype_TransferSign(desc, rtype);
04363             else desc = Mtype_TransferSign(rtype, desc);
04364           }
04365         }
04366 
04367   if (TREE_THIS_VOLATILE(exp))
04368     Set_TY_is_volatile(ty_idx);
04369 
04370   if (code == PARM_DECL || code == VAR_DECL) {
04371     st = Get_ST (exp);
04372           if (ST_assigned_to_dedicated_preg (st))
04373       Set_TY_is_volatile(ty_idx);
04374         }
04375   else
04376   if (code == CONSTRUCTOR) {
04377     DevWarn ("Encountered CONSTRUCTOR at line %d", lineno);
04378     st = WFE_Generate_Temp_For_Initialized_Aggregate (exp, "");
04379   }
04380 
04381   Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
04382     ("WFE_Expand_Expr: field id for bit-field exceeds limit"));
04383 
04384 #ifdef TARG_X8664
04385         // The source may have different types of casting between same-sized
04386         // vector types, and between same-sized vector-nonvector types.
04387         if (MTYPE_is_vector (rtype) || MTYPE_is_vector (desc))
04388           desc = rtype;
04389 #endif
04390 
04391   wn = WN_CreateLdid (OPR_LDID, rtype,
04392           is_bit_field ? MTYPE_BS : desc,
04393           ST_ofst(st)+component_offset+xtra_BE_ofst+preg_num, st,
04394           field_id != 0 ? hi_ty_idx : ty_idx, field_id);
04395   if (cvtl_size != 0)
04396     wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
04397       }
04398       break;
04399 
04400     case CONST_DECL:
04401         wn = WFE_Expand_Expr(DECL_INITIAL(exp), need_result);
04402   break;
04403 
04404     case INTEGER_CST:
04405       {
04406   ty_idx = Get_TY (TREE_TYPE(exp));
04407   TYPE_ID mtyp = TY_mtype(ty_idx);
04408   mtyp = (mtyp == MTYPE_V) ? MTYPE_I4 : Widen_Mtype(mtyp);
04409   wn = WN_Intconst(mtyp, Get_Integer_Value(exp));
04410       }
04411       break;
04412 
04413     case PTRMEM_CST:
04414       {
04415   wn = WFE_Expand_Expr(cplus_expand_constant (exp),
04416            need_result, nop_ty_idx, component_ty_idx,
04417            component_offset, field_id);
04418       }
04419       break;
04420 
04421 #ifdef KEY  // Use the code from kgccfe, which is newer and can handle
04422     // i386.
04423     case REAL_CST:
04424       {
04425   TCON tcon;
04426   ty_idx = Get_TY (TREE_TYPE(exp));
04427 #if (defined(TARG_IA32) || defined(TARG_X8664)) && !defined(REAL_ARITHMETIC)
04428   tcon = Host_To_Targ_Float (TY_mtype (ty_idx), TREE_REAL_CST(exp));
04429 #else
04430   REAL_VALUE_TYPE real = TREE_REAL_CST(exp);
04431 #ifndef TARG_IA64
04432   int rval;
04433 
04434   long rbuf [4];
04435 #ifdef KEY
04436   INT32 rbuf_w[4]; // this is needed when long is 64-bit
04437   INT32 i;
04438 #endif
04439 #endif
04440   switch (TY_mtype (ty_idx)) {
04441 #ifdef TARG_IA64
04442     case MTYPE_F4:
04443       tcon = Host_To_Targ_Float_4 (MTYPE_F4,
04444     WFE_Convert_Internal_Real_to_IEEE_Single(real));
04445       break;
04446 
04447     case MTYPE_F8:
04448       tcon = Host_To_Targ_Float (MTYPE_F8,
04449     WFE_Convert_Internal_Real_to_IEEE_Double(real));
04450       break;
04451 
04452           case MTYPE_F10:
04453       tcon = Host_To_Targ_Float_10 (MTYPE_F10,
04454     WFE_Convert_Internal_Real_to_IEEE_Double_Extended(real));
04455             break;
04456 
04457     case MTYPE_FQ:
04458       tcon = Host_To_Targ_Quad (WFE_Convert_Internal_Real_to_IEEE_Double_Extended(real));
04459       break;      
04460 
04461 #else
04462     case MTYPE_F4:
04463       REAL_VALUE_TO_TARGET_SINGLE (real, rval);
04464       tcon = Host_To_Targ_Float_4 (MTYPE_F4, *(float *) &rval);
04465       break;
04466     case MTYPE_F8:
04467       REAL_VALUE_TO_TARGET_DOUBLE (real, rbuf);
04468 #ifdef KEY
04469       WFE_Convert_To_Host_Order(rbuf);
04470       for (i = 0; i < 4; i++)
04471         rbuf_w[i] = rbuf[i];
04472       tcon = Host_To_Targ_Float (MTYPE_F8, *(double *) &rbuf_w);
04473 #else
04474       tcon = Host_To_Targ_Float (MTYPE_F8, *(double *) &rbuf);
04475 #endif
04476       break;
04477 #if defined(TARG_IA32) || defined(TARG_X8664) 
04478     case MTYPE_FQ:
04479       REAL_VALUE_TO_TARGET_LONG_DOUBLE (real, rbuf);
04480       for (i = 0; i < 4; i++)
04481         rbuf_w[i] = rbuf[i];
04482       tcon = Host_To_Targ_Quad (*(long double *) &rbuf_w);
04483       break;      
04484 #endif /* TARG_IA32 */
04485 #endif
04486     default:
04487       FmtAssert(FALSE, ("WFE_Expand_Expr unexpected float size"));
04488       break;
04489   }
04490 #endif
04491   st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04492   wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
04493       }
04494       break;
04495 
04496     case COMPLEX_CST:
04497       {
04498   TCON tcon;
04499   ty_idx = Get_TY (TREE_TYPE(exp));
04500 #if (defined(TARG_IA32) || defined(TARG_X8664)) && !defined(REAL_ARITHMETIC)
04501         tcon = Host_To_Targ_Complex (TY_mtype (ty_idx),
04502              TREE_REAL_CST(TREE_REALPART(exp)),
04503              TREE_REAL_CST(TREE_IMAGPART(exp)));
04504 #else
04505 #ifdef TARG_IA64
04506   REAL_VALUE_TYPE real = TREE_REAL_CST(TREE_REALPART(exp));
04507   REAL_VALUE_TYPE imag = TREE_REAL_CST(TREE_IMAGPART(exp));
04508 
04509   switch (TY_mtype (ty_idx)) {
04510     case MTYPE_C4:
04511       tcon = Host_To_Targ_Complex_4 (MTYPE_C4,
04512     WFE_Convert_Internal_Real_to_IEEE_Single(real),
04513     WFE_Convert_Internal_Real_to_IEEE_Single(imag));
04514       break;
04515 
04516     case MTYPE_C8:
04517       tcon = Host_To_Targ_Complex (MTYPE_C8,
04518     WFE_Convert_Internal_Real_to_IEEE_Double(real),
04519     WFE_Convert_Internal_Real_to_IEEE_Double(imag));
04520       break;
04521 
04522     case MTYPE_C10:
04523       tcon = Host_To_Targ_Complex_10 (MTYPE_C10,
04524     WFE_Convert_Internal_Real_to_IEEE_Double_Extended(real),
04525     WFE_Convert_Internal_Real_to_IEEE_Double_Extended(imag));
04526       break;
04527 
04528     case MTYPE_CQ:
04529       tcon = Host_To_Targ_Complex_Quad (
04530     WFE_Convert_Internal_Real_to_IEEE_Double_Extended(real),
04531     WFE_Convert_Internal_Real_to_IEEE_Double_Extended(imag));
04532       break;
04533 #else
04534 
04535   REAL_VALUE_TYPE real = TREE_REAL_CST(TREE_REALPART(exp));
04536   REAL_VALUE_TYPE imag = TREE_REAL_CST(TREE_IMAGPART(exp));
04537         int rval;
04538   int ival;
04539   long rbuf [4];
04540   long ibuf [4];
04541 #ifdef KEY
04542   INT32 rbuf_w [4]; // this is needed when long is 64-bit
04543   INT32 ibuf_w [4]; // this is needed when long is 64-bit
04544   INT32 i;
04545 #endif 
04546   switch (TY_mtype (ty_idx)) {
04547     case MTYPE_C4:
04548       REAL_VALUE_TO_TARGET_SINGLE (real, rval);
04549       REAL_VALUE_TO_TARGET_SINGLE (imag, ival);
04550       tcon = Host_To_Targ_Complex_4 (MTYPE_C4,
04551              *(float *) &rval,
04552              *(float *) &ival);
04553       break;
04554     case MTYPE_C8:
04555       REAL_VALUE_TO_TARGET_DOUBLE (real, rbuf);
04556       REAL_VALUE_TO_TARGET_DOUBLE (imag, ibuf);
04557 #ifdef KEY
04558       WFE_Convert_To_Host_Order(rbuf);
04559       WFE_Convert_To_Host_Order(ibuf);
04560       for (i = 0; i < 4; i++) {
04561         rbuf_w[i] = rbuf[i];
04562         ibuf_w[i] = ibuf[i];
04563       }
04564       tcon = Host_To_Targ_Complex (MTYPE_C8,
04565            *(double *) &rbuf_w,
04566            *(double *) &ibuf_w);
04567 #else
04568       tcon = Host_To_Targ_Complex (MTYPE_C8,
04569            *(double *) &rbuf,
04570            *(double *) &ibuf);
04571 #endif
04572       break;
04573 #ifdef KEY
04574   case MTYPE_CQ:
04575       REAL_VALUE_TO_TARGET_LONG_DOUBLE (real, rbuf);
04576       REAL_VALUE_TO_TARGET_LONG_DOUBLE (imag, ibuf);
04577       WFE_Convert_To_Host_Order(rbuf);
04578       WFE_Convert_To_Host_Order(ibuf);
04579       for (i = 0; i < 4; i++) {
04580         rbuf_w[i] = rbuf[i];
04581         ibuf_w[i] = ibuf[i];
04582       }
04583       tcon = Host_To_Targ_Complex_Quad( *(long double *) &rbuf_w,
04584                 *(long double *) &ibuf_w );
04585     break;
04586 #endif
04587 #endif
04588     default:
04589       FmtAssert(FALSE, ("WFE_Expand_Expr unexpected float size"));
04590       break;
04591   }
04592 #endif
04593   st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04594   wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
04595       }
04596       break;
04597 
04598 #else // KEY
04599 
04600     case REAL_CST:
04601       {
04602   TCON tcon;
04603   ty_idx = Get_TY (TREE_TYPE(exp));
04604   tcon = Host_To_Targ_Float (TY_mtype (ty_idx), TREE_REAL_CST(exp));
04605   st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04606   wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
04607       }
04608       break;
04609 
04610     case COMPLEX_CST:
04611       {
04612   TCON tcon;
04613   ty_idx = Get_TY (TREE_TYPE(exp));
04614   tcon = Host_To_Targ_Complex (TY_mtype (ty_idx),
04615              TREE_REAL_CST(TREE_REALPART(exp)),
04616              TREE_REAL_CST(TREE_IMAGPART(exp)));
04617   st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04618   wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
04619       }
04620       break;
04621 #endif  // KEY
04622 
04623     // this should occur only if string is a statement expression
04624     case STRING_CST:
04625       {
04626   TCON tcon;
04627   tcon = Host_To_Targ_String (MTYPE_STRING,
04628             const_cast<char*>TREE_STRING_POINTER(exp),
04629             TREE_STRING_LENGTH(exp));
04630   ty_idx = Get_TY(TREE_TYPE(exp));
04631   st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04632   wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
04633   TREE_STRING_ST (exp) = st;
04634       }
04635       break;
04636 
04637     // unary ops
04638     case BIT_NOT_EXPR:
04639     case ABS_EXPR:
04640     case NEGATE_EXPR:
04641     case REALPART_EXPR:
04642     case IMAGPART_EXPR:
04643       {
04644         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
04645         wn  = WN_Unary (Operator_From_Tree [code].opr,
04646                         Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(exp)))), wn0);
04647 #ifdef KEY // bug 2648
04648         TYPE_ID mtyp = TY_mtype(Get_TY(TREE_TYPE(exp)));
04649         if (mtyp != WN_rtype(wn))
04650           wn = WN_CreateCvtl (OPR_CVTL, WN_rtype(wn), MTYPE_V,
04651                               MTYPE_size_min(mtyp), wn);
04652 #endif
04653       }
04654       break;
04655 
04656     case TRUTH_NOT_EXPR:
04657       wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
04658       wn1 = WN_Intconst (MTYPE_I4, 0);
04659       wn  = WN_Relational (OPR_EQ, MTYPE_I4, wn0, wn1);
04660       break;
04661 
04662     case CONJ_EXPR:
04663       {
04664   ty_idx = Get_TY (TREE_TYPE(exp));
04665         TYPE_ID complex_mtype = TY_mtype(ty_idx);
04666         TYPE_ID float_mtype   = Mtype_complex_to_real (complex_mtype);
04667         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
04668   if (WN_has_side_effects (wn0)) {
04669     ST       *preg_st;
04670     PREG_NUM  preg;
04671     preg_st = MTYPE_To_PREG(complex_mtype);
04672     preg    = Create_Preg (complex_mtype, NULL);
04673     wn0     = WN_Stid (complex_mtype, preg, preg_st, ty_idx, wn0);
04674     WFE_Stmt_Append (wn0, Get_Srcpos());
04675     wn0 = WN_Ldid (complex_mtype, preg, preg_st, ty_idx);
04676   }
04677 #ifdef KEY
04678   // Fix bug 603
04679         wn = WN_Binary (OPR_COMPLEX, complex_mtype,
04680       WN_Unary (OPR_REALPART, float_mtype, wn0),
04681       WN_Unary (OPR_NEG, float_mtype,
04682           WN_Unary (OPR_IMAGPART, float_mtype, wn0)));
04683 #else
04684         wn = WN_Binary (OPR_COMPLEX, complex_mtype,
04685       WN_Unary (OPR_REALPART, float_mtype, wn0),
04686       WN_Unary (OPR_NEG, float_mtype,
04687           WN_Unary (OPR_REALPART, float_mtype, wn0)));
04688 #endif
04689       }
04690       break;
04691 
04692     case NOP_EXPR:
04693       {
04694   ty_idx = Get_TY (TREE_TYPE(exp));
04695         TYPE_ID mtyp = TY_mtype(ty_idx);
04696   // do not pass struct type down because will cause rtype of MTYPE_M
04697         wn = WFE_Expand_Expr (TREE_OPERAND (exp, 0), TRUE, 
04698             (mtyp == MTYPE_M) ? 0 : ty_idx,
04699              component_ty_idx, component_offset,
04700              field_id, is_bit_field
04701 #ifdef KEY
04702              , FALSE, target_wn
04703 #endif
04704              );
04705   if (mtyp == MTYPE_V) 
04706     break;
04707   if (mtyp == MTYPE_M) 
04708     break;
04709   if (MTYPE_is_integral(mtyp) && MTYPE_is_integral(WN_rtype(wn))) {
04710     // For 32-bit to 64-bit conversion, make the result have the same
04711     // sign as the source.  Fix bug 480.
04712     if (MTYPE_size_min(mtyp) == 64 &&
04713         MTYPE_size_min(WN_rtype(wn)) == 32 &&
04714         MTYPE_is_signed(mtyp) != MTYPE_is_signed(WN_rtype(wn))) {
04715       mtyp = MTYPE_complement(mtyp);
04716     }
04717 
04718     if (MTYPE_size_min(mtyp) < MTYPE_size_min(WN_rtype(wn))) {
04719       if (MTYPE_size_min(mtyp) != 32)
04720         wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp), MTYPE_V,
04721                MTYPE_size_min(mtyp), wn);
04722       else wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
04723     }
04724     else {
04725       TY_IDX ty_idx0 = Get_TY(TREE_TYPE(TREE_OPERAND (exp, 0)));
04726       TYPE_ID mtyp0 = TY_mtype(ty_idx0);
04727 
04728       if (MTYPE_size_min(mtyp) > MTYPE_size_min(mtyp0) &&
04729     ! Has_Subsumed_Cvtl(WN_operator(wn)))
04730         wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp0), MTYPE_V,
04731          MTYPE_size_min(mtyp0), wn);
04732 
04733       if (MTYPE_size_min(mtyp) > MTYPE_size_min(WN_rtype(wn)))
04734         wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
04735       else { // same size
04736         if (mtyp != WN_rtype(wn)) 
04737           wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
04738       }
04739     }
04740   }
04741   else {
04742     if (mtyp != WN_rtype(wn)) 
04743       wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
04744   }
04745       }
04746       break;
04747 
04748     case COMPONENT_REF:
04749       {
04750   INT64 ofst;
04751   arg0 = TREE_OPERAND (exp, 0);
04752   arg1 = TREE_OPERAND (exp, 1);
04753   // If this is an indirect of a nop_expr, we may need to fix the
04754   // type of the nop_expr:
04755   (void) Get_TY(TREE_TYPE(arg0));
04756    
04757   if (component_ty_idx == 0)
04758     ty_idx = Get_TY (TREE_TYPE(exp));
04759   else ty_idx = component_ty_idx;
04760   if (DECL_BIT_FIELD(arg1)) 
04761     is_bit_field = TRUE;
04762 
04763   if (! is_bit_field && 
04764       component_ty_idx == 0) {  // only for top-level COMPONENT_REF
04765           // if size does not agree with ty_idx, fix ty_idx
04766           tree sizenode = DECL_SIZE(arg1);
04767           if (
04768 #ifdef KEY
04769               sizenode && // bug 11726, in absence of size expression
04770 #endif
04771               TREE_CODE(sizenode) == INTEGER_CST) {
04772       TYPE_ID c_mtyp = TY_mtype(ty_idx);
04773       INT32 bsize = Get_Integer_Value(sizenode);
04774       if (MTYPE_size_min(c_mtyp) > bsize) {
04775         FmtAssert(MTYPE_is_integral(c_mtyp), 
04776           ("COMPONENT_REF: integer type expected at inconsistent field size"));
04777         c_mtyp = Mtype_AlignmentClass(bsize >> 3, MTYPE_type_class(c_mtyp));
04778         ty_idx = MTYPE_To_TY(c_mtyp);
04779       }
04780     }
04781         }
04782 
04783   if (! is_bit_field)
04784     ofst = (BITSPERBYTE * Get_Integer_Value(DECL_FIELD_OFFSET(arg1)) +
04785               Get_Integer_Value(DECL_FIELD_BIT_OFFSET(arg1)))
04786             / BITSPERBYTE;
04787   else ofst = 0;
04788 #ifdef KEY
04789   FmtAssert (DECL_FIELD_ID(arg1) != 0,
04790                    ("WFE_Expand_Expr: DECL_FIELD_ID used but not set"));
04791 
04792   // If arg0 is a CALL_EXPR that returns a ptr-to-member-function, then
04793   // call WFE_Expand_Ptr_To_Member_Func_Call_Expr to expand it.
04794   // Otherwise, call WFE_Expand_Expr to do regular expansion.
04795   // Bug 3400, 3427.
04796   if (WFE_Call_Returns_Ptr_To_Member_Func(arg0)) {
04797     tree field0 = TYPE_FIELDS(TREE_TYPE(arg0));
04798     // Get_TY(TREE_TYPE(field0)) is valid only if
04799     // WFE_Call_Returns_Ptr_To_Member_Func(arg0)) is TRUE.  Bug 6022.
04800     TYPE_ID desc = TY_mtype(Get_TY(TREE_TYPE(field0)));
04801     wn = WFE_Expand_Ptr_To_Member_Func_Call_Expr (arg0, nop_ty_idx,
04802       Pointer_Mtype, desc, component_offset,
04803       field_id + DECL_FIELD_ID(arg1));
04804   } else
04805 #endif
04806         wn = WFE_Expand_Expr (arg0, TRUE, nop_ty_idx, ty_idx, ofst+component_offset,
04807             field_id + DECL_FIELD_ID(arg1), is_bit_field);
04808 
04809 #ifdef KEY
04810   // For code such as (p->a = q->a).b, the gnu tree is:
04811   //   component_ref
04812   //     modify_expr
04813   //       indirect_ref
04814   //       indirect_ref
04815   // WFE_Expand_Expr will call WFE_Lhs_Of_Modify_Expr to expand the
04816   // modify_expr.  WFE_Lhs_Of_Modify_Expr will return an iload
04817   // corresponding to p->a.  Since we want p->a.b, recreate the iload
04818   // here.  Bug 3122 and 3210
04819   //
04820   // bug fix for OSP_118
04821   //
04822   if (TREE_CODE(arg0) == MODIFY_EXPR || TREE_CODE(arg0) == NON_LVALUE_EXPR) {
04823     TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
04824     TYPE_ID desc = TY_mtype(ty_idx);
04825     if (WN_operator(wn) == OPR_ILOAD) {
04826 #ifdef PATHSCALE_MERGE
04827             wn = WN_CreateIload(OPR_ILOAD, rtype, desc,
04828               WN_offset(wn) + ofst + component_offset, ty_idx,
04829               WN_load_addr_ty(wn), WN_kid0(wn),
04830               WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
04831 #else
04832             wn = WN_CreateIload(OPR_ILOAD, rtype, desc,
04833               ofst + component_offset, ty_idx,
04834               Make_Pointer_Type (ty_idx, FALSE), WN_kid0(wn),
04835               field_id + DECL_FIELD_ID(arg1));
04836 #endif
04837     } 
04838     else if (WN_operator(wn) == OPR_LDID) {
04839       WN_set_rtype(wn, rtype);
04840       WN_set_desc(wn, desc);
04841       WN_offset(wn) = WN_offset(wn)+ofst+component_offset;
04842       WN_set_ty(wn, ty_idx);
04843       // bug fix for OSP_158 
04844       // if (TY_kind(ty_idx) == KIND_SCALAR)
04845       if (TY_kind(ty_idx) != KIND_STRUCT)
04846         WN_set_field_id (wn, 0);
04847       else
04848 #ifdef PATHSCALE_MERGE
04849         WN_set_field_id(wn, WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
04850 #else
04851         WN_set_field_id(wn, field_id + DECL_FIELD_ID(arg1));
04852 #endif
04853     } 
04854   } 
04855   // bug 6122
04856   // Handle code like (x == 1 ? p->a : p->b).c
04857   else if (TREE_CODE(arg0) == COND_EXPR &&
04858      WN_operator(wn) == OPR_CSELECT &&
04859      WN_rtype(wn) == MTYPE_M)
04860   {
04861     // kid1 and kid2 must be type M and must be of the same struct type
04862     Is_True (WN_rtype (WN_kid1(wn)) == MTYPE_M, ("Unexpected type"));
04863     // code adapted from vho
04864     TY_IDX temp_ty_idx = WN_ty (WN_kid1 (wn));
04865     // Get the struct type corresponding to the field
04866     if (WN_field_id (WN_kid1 (wn)))
04867       temp_ty_idx = get_field_type (temp_ty_idx,
04868                                     WN_field_id (WN_kid1 (wn)));
04869     // Store into temp symbol
04870     ST * temp = Gen_Temp_Symbol (temp_ty_idx, ".mcselect_store");
04871     wn = WN_Stid (MTYPE_M, 0, temp, temp_ty_idx, wn);
04872     WFE_Stmt_Append (wn, Get_Srcpos());
04873     // Load correct field from temp symbol
04874     wn = WN_Ldid (TY_mtype (ty_idx), ofst + component_offset,
04875                   temp, temp_ty_idx, field_id + DECL_FIELD_ID(arg1));
04876   }
04877 #endif
04878       }
04879       break;
04880 
04881     case INDIRECT_REF:
04882       {
04883   UINT xtra_BE_ofst = 0;  // only needed for big-endian target
04884         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
04885 
04886   TY_IDX hi_ty_idx = Get_TY(TREE_TYPE(exp));
04887 
04888   desc_ty_idx = component_ty_idx;
04889   if (desc_ty_idx == 0)
04890     desc_ty_idx = hi_ty_idx;
04891 
04892         if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
04893     ty_idx = desc_ty_idx;
04894   else {
04895     ty_idx = nop_ty_idx;
04896     if (ty_idx == 0) 
04897       ty_idx = desc_ty_idx;
04898   }
04899 
04900   if (! is_bit_field) {
04901     if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
04902       if (Target_Byte_Sex == BIG_ENDIAN)
04903         xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
04904       desc_ty_idx = ty_idx;
04905     }
04906   }
04907   else {
04908     if (TY_size(desc_ty_idx) > TY_size(ty_idx)) 
04909       ty_idx = desc_ty_idx;
04910   }
04911 
04912   TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
04913   TYPE_ID desc = TY_mtype(desc_ty_idx);
04914   if (MTYPE_is_integral(desc)) {
04915     if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
04916       if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
04917     is_bit_field)
04918         rtype = Mtype_TransferSign(desc, rtype);
04919       else desc = Mtype_TransferSign(rtype, desc);
04920     }
04921   }
04922 
04923   if (TREE_THIS_VOLATILE(exp))
04924     Set_TY_is_volatile(hi_ty_idx);
04925 
04926   Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
04927     ("WFE_Expand_Expr: field id for bit-field exceeds limit"));
04928 
04929         if (!WFE_Keep_Zero_Length_Structs &&
04930             rtype == MTYPE_M              &&
04931             TY_size (hi_ty_idx) == 0) {
04932     if (WN_has_side_effects (wn0)) {
04933       wn = WN_CreateEval (wn0);
04934       WFE_Stmt_Append (wn, Get_Srcpos());
04935     }
04936     wn = NULL;
04937         }
04938         else {
04939     // special case indexing into a constant string
04940     if (WN_operator (wn0) == OPR_LDA          &&
04941         ST_class (WN_st (wn0)) == CLASS_CONST &&
04942         is_bit_field == FALSE                 &&
04943         field_id == 0) {
04944             st = WN_st (wn0);
04945       TCON tcon = Tcon_Table [ST_tcon (st)];
04946       if (TCON_ty (tcon) == MTYPE_STRING &&
04947                 TY_size (Be_Type_Tbl (desc)) == 1) {
04948         mUINT32 len = Targ_String_Length (tcon);
04949         mUINT64 offset = component_offset + xtra_BE_ofst + WN_offset (wn0);
04950         if (offset <= len    &&
04951       desc == MTYPE_U1 &&
04952       (rtype == MTYPE_U4 || rtype == MTYPE_U8)) {
04953     unsigned char *cp = (unsigned char *) Targ_String_Address (tcon);
04954     unsigned long long val = cp [offset];
04955     wn = WN_Intconst (rtype, val);
04956     break;
04957         }
04958         else
04959         if (offset <= len    &&
04960       desc == MTYPE_I1 &&
04961       (rtype == MTYPE_I4 || rtype == MTYPE_I8)) {
04962     signed char *cp = (signed char *) Targ_String_Address (tcon);
04963     signed long long val = cp [offset];
04964     wn = WN_Intconst (rtype, val);
04965     break;
04966         }
04967       }
04968     }
04969     if (need_result)
04970       wn = WN_CreateIload(OPR_ILOAD, rtype,
04971         is_bit_field ? MTYPE_BS : desc, 
04972         component_offset+xtra_BE_ofst,
04973         field_id != 0 ? hi_ty_idx : ty_idx, 
04974         Make_Pointer_Type (hi_ty_idx, FALSE),
04975         wn0, field_id);
04976     else
04977     if (WN_has_side_effects (wn0))
04978       wn = wn0;
04979   }
04980       }
04981       break;
04982 
04983     case CONVERT_EXPR:
04984     case FLOAT_EXPR:
04985       {
04986         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
04987   ty_idx = Get_TY (TREE_TYPE(exp));
04988   TYPE_ID mtyp = TY_mtype(ty_idx);
04989   if (mtyp == MTYPE_V)
04990     wn = wn0;
04991   else {
04992     mtyp = Widen_Mtype(TY_mtype(ty_idx));
04993     if (mtyp == WN_rtype(wn0) || mtyp == MTYPE_V)
04994       wn = wn0;
04995     else {
04996 #ifdef KEY // prevent zero extension when converting to 64-bit address type
04997       if (TREE_CODE(TREE_TYPE(exp)) == POINTER_TYPE &&
04998     MTYPE_byte_size(FE_Pointer_Type_To_Mtype()) == 8) {
04999         if (WN_operator(wn0) == OPR_CVT && WN_desc(wn0) == MTYPE_U4) {
05000     WN_set_desc(wn0, MTYPE_I4);
05001     wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05002         }
05003         else if (MTYPE_byte_size(WN_rtype(wn0) == 4))
05004     wn = WN_Cvt(MTYPE_I4, mtyp, wn0);
05005         else wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05006       }
05007       else
05008 #endif
05009       wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05010       // The following opcodes are not valid for MIPS
05011       if (WN_opcode(wn) == OPC_I4U4CVT ||
05012           WN_opcode(wn) == OPC_U4I4CVT ||
05013           WN_opcode(wn) == OPC_I8U8CVT ||
05014           WN_opcode(wn) == OPC_U8I8CVT) {
05015         wn = WN_kid0 (wn);
05016       }
05017     }
05018   }
05019       }
05020       break;
05021 
05022     case FIX_TRUNC_EXPR:
05023       {
05024         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05025   ty_idx = Get_TY (TREE_TYPE(exp));
05026          TYPE_ID mtype = Widen_Mtype(TY_mtype(ty_idx));
05027          if(WN_operator(wn0) == OPR_CVT &&
05028       MTYPE_is_integral(WN_desc(wn0)) &&
05029       MTYPE_is_float(WN_rtype(wn0))){
05030            wn1 = WN_kid0(wn0);
05031            TYPE_ID kid_type = WN_rtype(wn1);
05032            if(mtype == kid_type){
05033              wn = wn1;
05034            }
05035            else{
05036              wn = WN_Cvt(WN_rtype(wn1), mtype, wn1);
05037            }
05038          }
05039          else
05040            wn = WN_Trunc(WN_rtype(wn0), mtype, wn0);
05041 
05042       }
05043       break;
05044 
05045 #ifdef GPLUSPLUS_FE
05046     case EXPR_STMT:
05047       {
05048 #ifdef KEY
05049         wn = WFE_Expand_Expr (EXPR_STMT_EXPR(exp), false, nop_ty_idx,
05050           component_ty_idx, component_offset, field_id,
05051           is_bit_field, is_aggr_init_via_ctor);
05052 #else
05053   wn = WFE_Expand_Expr (EXPR_STMT_EXPR(exp), false);
05054 #endif
05055       }
05056       break;
05057 
05058     case STMT_EXPR:
05059       {
05060 #ifdef KEY
05061   bool write_to_target_wn = TRUE;
05062 
05063   // If we need to store the result in target_wn, then give result the
05064   // same ST as the ST in target_wn.  To do this, first find the
05065   // STMT_EXPR's result, which is returned by the last EXPR_STMT in the
05066   // COMPOUND_STMT.  Based on code in gnu/c-common.c:c_expand_expr.
05067   if (target_wn != NULL
05068       && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
05069       && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT) {
05070     tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
05071     tree last = TREE_CHAIN (expr);
05072 
05073     while (TREE_CHAIN (last)) {
05074       expr = last;
05075       last = TREE_CHAIN (last);
05076     }
05077 
05078     if (TREE_CODE (last) == SCOPE_STMT
05079         && TREE_CODE (expr) == EXPR_STMT) {
05080       if (TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL) {
05081         // If the last expression is a variable, then the variable is the
05082         // returned value.
05083         tree var_decl = EXPR_STMT_EXPR (expr);
05084         ST *st = DECL_ST (var_decl);
05085         if (st == NULL) {
05086     // Give the returned var_decl the same ST indicated by
05087     // target_wn.
05088     if (WN_operator(target_wn) == OPR_LDA) {
05089       set_DECL_ST(var_decl, WN_st(target_wn));
05090     } else if (WN_operator(target_wn) == OPR_LDID) {
05091       // target_wn is an ldid of the fake first parm.  Change the
05092       // stmt_expr's var_decl to be an indirect_ref of the fake
05093       // parm.
05094       tree ptr_var =
05095         build_decl(VAR_DECL, NULL_TREE,
05096              build_pointer_type(TREE_TYPE(var_decl)));
05097       TREE_SET_CODE(var_decl, INDIRECT_REF);
05098       TREE_OPERAND(var_decl, 0) = ptr_var;
05099       set_DECL_ST(ptr_var, WN_st(target_wn));
05100     } else {
05101       FmtAssert(FALSE,
05102        ("WFE_Expand_Expr: unexpected operator in target_wn"));
05103     }
05104         } else {
05105     // The var_decl already has a ST assigned.  This should be the
05106     // same ST as the target_wn.
05107     FmtAssert(st == WN_st(target_wn),
05108         ("WFE_Expand_Expr: STs are different"));
05109         }
05110         // Don't need target_wn anymore since the returned var_decl
05111         // already has the target ST.
05112         write_to_target_wn = FALSE;
05113 
05114       } else if (TREE_CODE (EXPR_STMT_EXPR (expr)) == INDIRECT_REF) {
05115         // The indirect_ref must have been a var_decl that was changed by
05116         // kg++fe to an indirect_ref.  This means we are already writing
05117         // to the target location.
05118         write_to_target_wn = FALSE;
05119       }
05120     }
05121   }
05122   wn = WFE_Expand_Expr (TREE_OPERAND (exp, 0), need_result, nop_ty_idx,
05123             component_ty_idx, component_offset, field_id,
05124             is_bit_field, is_aggr_init_via_ctor,
05125             write_to_target_wn ? target_wn : NULL);
05126 #else
05127         wn = WFE_Expand_Expr (TREE_OPERAND (exp, 0), need_result);
05128 #endif
05129       }
05130       break;
05131 
05132 #ifndef KEY
05133     case SUBOBJECT:
05134       break;
05135 #endif // !KEY
05136 
05137     case CLEANUP_POINT_EXPR: 
05138       {
05139         Push_Temp_Cleanup(exp, false);
05140         wn = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05141         WN * cleanup_block = WN_CreateBlock ();
05142         WFE_Stmt_Push (cleanup_block, wfe_stmk_temp_cleanup, Get_Srcpos ());
05143         Do_Temp_Cleanups(exp);
05144         WFE_Stmt_Pop (wfe_stmk_temp_cleanup);
05145   if (wn && WN_has_side_effects (wn) && WN_first (cleanup_block)) {
05146     DevWarn("CLEANUP_POINT_EXPR: expressson has side effects");
05147     ty_idx = Get_TY (TREE_TYPE(exp));
05148     st = Gen_Temp_Symbol (ty_idx, "__cleanup_point_expr");
05149 #ifdef KEY
05150       WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
05151 #endif
05152     TYPE_ID mtype = TY_mtype (ty_idx);
05153     WFE_Set_ST_Addr_Saved (wn);
05154     wn = WN_Stid (mtype, 0, st, ty_idx, wn);
05155     WFE_Stmt_Append (wn, Get_Srcpos ());
05156     wn = WN_Ldid (mtype, 0, st, ty_idx);
05157   }
05158   WFE_Stmt_Append (cleanup_block, Get_Srcpos ());
05159       }
05160       break;
05161 
05162     case THROW_EXPR:
05163       WFE_One_Stmt (TREE_OPERAND (exp, 0));
05164       Call_Throw();
05165       break;
05166 
05167     case TRY_CATCH_EXPR:
05168       DevWarn ("Encountered TRY_CATCH_EXPR at line %d:  ignored", lineno);
05169       break;
05170 
05171     case COMPOUND_STMT:
05172       {
05173   tree t = COMPOUND_BODY(exp);
05174   tree last_expr_stmt = 0;
05175   wn = NULL;
05176   while (t) {
05177     if (TREE_CODE(t) == EXPR_STMT)
05178       last_expr_stmt = t;
05179     t = TREE_CHAIN(t);
05180   }
05181 
05182   t = COMPOUND_BODY(exp);
05183 
05184   while (t != last_expr_stmt) {
05185     WFE_Expand_Stmt (t, target_wn);
05186     t = TREE_CHAIN(t);
05187   }
05188 
05189   if (t) {
05190 #ifdef KEY
05191     wn =  WFE_Expand_Expr(t, need_result, nop_ty_idx, component_ty_idx,
05192         component_offset, field_id, is_bit_field,
05193         is_aggr_init_via_ctor, target_wn);
05194 #else
05195     wn =  WFE_Expand_Expr(t, need_result);
05196 #endif
05197     t = TREE_CHAIN(t);
05198   }
05199 
05200   while (t) {
05201     WFE_Expand_Stmt(t, target_wn);
05202     t = TREE_CHAIN(t);
05203   }
05204 
05205       }
05206       break;
05207 
05208     case EMPTY_CLASS_EXPR:
05209       DevWarn ("Encountered EMPTY_CLASS_EXPR at line %d\n", lineno);
05210       ty_idx = Get_TY (TREE_TYPE(exp));
05211       st = Gen_Temp_Symbol (ty_idx, "__empty_class_expr");
05212 #ifdef KEY
05213       WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
05214 #endif
05215       wn = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
05216       break;
05217 #endif /* GLPUSPLUFE */
05218 
05219     // binary ops
05220     case PLUS_EXPR:
05221     case MINUS_EXPR:
05222     case MULT_EXPR:
05223     case MAX_EXPR:
05224     case MIN_EXPR:
05225     case LSHIFT_EXPR:
05226     case BIT_AND_EXPR:
05227     case BIT_IOR_EXPR:
05228     case BIT_XOR_EXPR:
05229     case TRUNC_DIV_EXPR:
05230     case TRUNC_MOD_EXPR:
05231     case RDIV_EXPR:
05232     case EXACT_DIV_EXPR:
05233     case TRUTH_AND_EXPR:
05234     case TRUTH_OR_EXPR:
05235     case TRUTH_XOR_EXPR:
05236     case COMPLEX_EXPR:
05237     case CEIL_DIV_EXPR:
05238       {
05239 #ifdef KEY
05240   TYPE_ID etype = TY_mtype(Get_TY(TREE_TYPE(exp)));
05241         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05242         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05243         wn  = WN_Binary (Operator_From_Tree [code].opr,
05244                          Widen_Mtype(etype), wn0, wn1);
05245 
05246 #if defined(TARG_SL)
05247         if(WN_operator(wn) == OPR_ADD &&
05248           (WN_operator(WN_kid0(wn)) == OPR_LDA ||
05249            WN_operator(WN_kid(wn, 1)) == OPR_LDA)) {
05250 
05251            if(WN_operator(WN_kid0(wn)) == OPR_LDA && WN_has_sym(WN_kid0(wn))) {
05252              ST* vbuf_sym = WN_st(WN_kid0(wn));
05253              if(ST_in_v2buf(vbuf_sym) || ST_in_v4buf(vbuf_sym)) {
05254                if(WN_operator(WN_kid1(wn)) == OPR_MPY) {
05255                  WN* tmp = WN_Intconst(MTYPE_U4,  ST_in_v2buf(vbuf_sym) ? 2 : 4); 
05256                  WN_Set_vbuf_ofst_adjusted(tmp);
05257                  WN* new_wn = WN_Binary(OPR_MPY, MTYPE_I4, WN_kid1(wn), tmp);
05258                  WN_Set_vbuf_ofst_adjusted(new_wn);
05259                  WN_kid1(wn) = new_wn;
05260                }
05261              }
05262            }
05263         }
05264 #endif // TARG_SL 
05265   
05266   // bug 2649, 5503
05267   if ((MTYPE_is_integral(etype)) &&
05268       (Widen_Mtype(etype) != etype) &&
05269       (TY_size (Get_TY(TREE_TYPE(exp))) < 32) &&
05270        (code == PLUS_EXPR || code == MINUS_EXPR || 
05271        code == MULT_EXPR || code == LSHIFT_EXPR || 
05272        code == BIT_XOR_EXPR || code == BIT_IOR_EXPR))
05273     wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(etype), MTYPE_V,
05274                        TY_size (Get_TY(TREE_TYPE(exp))) * 8, wn);
05275 #else
05276         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05277         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05278         wn  = WN_Binary (Operator_From_Tree [code].opr,
05279                          Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(exp)))), wn0, wn1);
05280 #endif
05281       }
05282       break;
05283 
05284     case LROTATE_EXPR:
05285       {
05286   ty_idx = Get_TY(TREE_TYPE(exp));
05287   TYPE_ID mtype = TY_mtype (ty_idx);
05288         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05289         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05290   wn1 = WN_Binary (OPR_SUB, Widen_Mtype (mtype),
05291        WN_Intconst (Widen_Mtype (mtype),
05292               TY_size (ty_idx) * 8),
05293        wn1);
05294   wn  = WN_Rrotate (TY_mtype(Get_TY(TREE_TYPE(exp))), wn0, wn1);
05295       }
05296       break;
05297 
05298     case RROTATE_EXPR:
05299       {
05300         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05301         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05302   wn  = WN_Rrotate (TY_mtype(Get_TY(TREE_TYPE(exp))), wn0, wn1);
05303       }
05304       break;
05305 
05306     case RSHIFT_EXPR:
05307       {
05308   TYPE_ID mtyp = Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(exp))));
05309         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05310         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05311         wn  = WN_Binary (MTYPE_signed(mtyp) ? OPR_ASHR : OPR_LSHR,
05312                          mtyp, wn0, wn1);
05313       }
05314       break;
05315 
05316     case TRUTH_ANDIF_EXPR:
05317     case TRUTH_ORIF_EXPR:
05318       {
05319 #ifdef KEY
05320   // bug 2651: evaluate the 1st operand unconditionally
05321         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05322 
05323   // Evaluate the second condition.  Add guard variable to the cleanup if
05324   // there is cleanup.
05325         WFE_Guard_Var_Push();
05326         wn1 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 1),
05327                Boolean_type);
05328         tree guard_var = WFE_Guard_Var_Pop();
05329   if (guard_var != NULL_TREE) {
05330     WFE_add_guard_var(guard_var, wn1);
05331   }
05332 #else
05333         wn0 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 0),
05334                Boolean_type);
05335         wn1 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 1),
05336                Boolean_type);
05337 #endif
05338         wn  = WN_Binary (Operator_From_Tree [code].opr,
05339                          Boolean_type, wn0, wn1);
05340         if (Boolean_type != MTYPE_B &&
05341       Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(exp)))) != Boolean_type)
05342     wn = WN_Cvt (Boolean_type, Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(exp)))), wn);
05343       }
05344       break;
05345 
05346     case LT_EXPR:
05347     case LE_EXPR:
05348     case GT_EXPR:
05349     case GE_EXPR:
05350     case EQ_EXPR:
05351     case NE_EXPR:
05352       {
05353         wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05354         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1));
05355 
05356   // check if conversion is needed
05357   ty_idx = Get_TY (TREE_TYPE(exp));
05358         TYPE_ID mtyp = TY_mtype(ty_idx);
05359   TY_IDX ty_idx0 = Get_TY(TREE_TYPE(TREE_OPERAND (exp, 0)));
05360   TYPE_ID mtyp0 = TY_mtype(ty_idx0);
05361   TY_IDX ty_idx1 = Get_TY(TREE_TYPE(TREE_OPERAND (exp, 1)));
05362   TYPE_ID mtyp1 = TY_mtype(ty_idx1);
05363 
05364   if (MTYPE_size_min(mtyp1) > MTYPE_size_min(mtyp0) &&
05365       ! Has_Subsumed_Cvtl(WN_operator(wn0)))
05366     wn0 = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp0), MTYPE_V,
05367             MTYPE_size_min(mtyp0), wn0);
05368   if (MTYPE_size_min(mtyp0) > MTYPE_size_min(mtyp1) &&
05369       ! Has_Subsumed_Cvtl(WN_operator(wn1)))
05370     wn1 = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp1), MTYPE_V,
05371             MTYPE_size_min(mtyp1), wn1);
05372 
05373         wn  = WN_Relational (Operator_From_Tree [code].opr,
05374            Widen_Mtype(TY_mtype(Get_TY(TREE_TYPE(TREE_OPERAND(exp, 0))))),
05375            wn0, wn1);
05376 #if defined(TARG_SL)
05377 // don't add conversion for float, it will cause to compiler to generate instruction dmtc1 
05378         if ((Widen_Mtype(mtyp0) != Boolean_type ) && !MTYPE_float(mtyp0))
05379           wn = WN_Cvt( Boolean_type, Widen_Mtype(mtyp0), wn);
05380 #endif 
05381       }
05382       break;
05383 
05384     case COND_EXPR:
05385       {
05386         TY_IDX ty_idx1 = Get_TY (TREE_TYPE(TREE_OPERAND (exp, 1)));
05387         TY_IDX ty_idx2 = Get_TY (TREE_TYPE(TREE_OPERAND (exp, 2)));
05388   ty_idx = Get_TY (TREE_TYPE(exp));
05389   if(ty_idx != ty_idx1 && TY_mtype(ty_idx1) != MTYPE_V)
05390     DevWarn("The type of COND_EXPR and its first kid mismatch!");
05391   if(ty_idx != ty_idx2 && TY_mtype(ty_idx2) != MTYPE_V)
05392     DevWarn("The type of COND_EXPR and its second kid mismatch!"); 
05393 #ifdef KEY // bug 2645
05394   wn0 = WFE_Expand_Expr (TREE_OPERAND (exp, 0));
05395 #else
05396   wn0 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 0),
05397                Boolean_type);
05398 #endif
05399   // Due to a bug of handling ternary operators(i.e, COND_EXPR) in the GCC 3.3 front end,
05400   // WFE_Expand_Expr convert the ternary operator to an if/else statement.
05401   // 
05402   if (TY_mtype (ty_idx)  == MTYPE_V ||
05403             TY_mtype (ty_idx1) == MTYPE_V ||
05404             TY_mtype (ty_idx2) == MTYPE_V) {
05405     WN *then_block = WN_CreateBlock ();
05406     WN *else_block = WN_CreateBlock ();
05407     WN *if_stmt    = WN_CreateIf (wn0, then_block, else_block);
05408     WFE_Stmt_Append (if_stmt, Get_Srcpos());
05409     WFE_Stmt_Push (then_block, wfe_stmk_if_then, Get_Srcpos());
05410     wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1), FALSE);
05411     if (wn1) {
05412       wn1 = WN_CreateEval (wn1);
05413       WFE_Stmt_Append (wn1, Get_Srcpos());
05414     }
05415     WFE_Stmt_Pop (wfe_stmk_if_then);
05416     WFE_Stmt_Push (else_block, wfe_stmk_if_else, Get_Srcpos());
05417     wn2 = WFE_Expand_Expr (TREE_OPERAND (exp, 2), FALSE);
05418     if (wn2) {
05419       wn2 = WN_CreateEval (wn2);
05420       WFE_Stmt_Append (wn2, Get_Srcpos());
05421     }
05422     WFE_Stmt_Pop (wfe_stmk_if_else);
05423         }
05424   else {
05425 #ifdef KEY
05426     // Prepare a guard variable for each part of the conditional, in case
05427     // the conditional has a cleanup that is executed after the whole
05428     // conditional expression is evaluated.  The guard variable ensures
05429     // that a cleanup is executed only if its part of the conditional is
05430     // executed.
05431     WFE_Guard_Var_Push();
05432     if(ty_idx != ty_idx1 &&
05433        Ty_Table[ty_idx].kind == KIND_POINTER &&
05434        Ty_Table[ty_idx1].kind == KIND_STRUCT) {
05435       wn1 = WFE_Address_Of (TREE_OPERAND (exp, 1));
05436     }
05437     else{
05438       wn1 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 1),
05439                    TY_mtype (ty_idx),
05440                    target_wn);
05441     }
05442     
05443     tree guard_var1 = WFE_Guard_Var_Pop();
05444 
05445     WFE_Guard_Var_Push();
05446     if(ty_idx != ty_idx2 &&
05447        Ty_Table[ty_idx].kind == KIND_POINTER &&
05448        Ty_Table[ty_idx2].kind == KIND_STRUCT) {
05449       wn2 = WFE_Address_Of (TREE_OPERAND (exp, 2));
05450     }
05451     else{
05452       wn2 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 2),
05453                    TY_mtype (ty_idx),
05454                    target_wn);
05455     }
05456     tree guard_var2 = WFE_Guard_Var_Pop();
05457 
05458     // Add guard variables if they are needed.
05459     if (guard_var1 != NULL_TREE) {
05460       WFE_add_guard_var(guard_var1, wn1);
05461     }
05462     if (guard_var2 != NULL_TREE) {
05463       WFE_add_guard_var(guard_var2, wn2);
05464     }
05465 #else
05466     wn1 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 1),
05467                  TY_mtype (ty_idx));
05468     wn2 = WFE_Expand_Expr_With_Sequence_Point (TREE_OPERAND (exp, 2),
05469                  TY_mtype (ty_idx));
05470 #endif
05471     wn  = WN_CreateExp3 (OPR_CSELECT, Mtype_comparison (TY_mtype (ty_idx)),
05472          MTYPE_V, wn0, wn1, wn2);
05473     Set_PU_has_very_high_whirl (Get_Current_PU ());
05474         }
05475 
05476         // bug fix for OSP_229
05477   // 
05478   FmtAssert ((wn != 0 || 
05479        TY_mtype(ty_idx) == MTYPE_V ||
05480                    TY_mtype(ty_idx1) == MTYPE_V || 
05481        TY_mtype(ty_idx2) == MTYPE_V),
05482       ("WFE_Expand_Expr: NULL WHIRL tree for %s", 
05483        Operator_From_Tree [code].name));
05484       }
05485       break;
05486 
05487     case INIT_EXPR:
05488 #ifdef KEY
05489       // Put the result in the write target if there is a write target.
05490       if (target_wn != NULL &&
05491     (TREE_CODE(TREE_OPERAND(exp, 0)) == VAR_DECL ||
05492      TREE_CODE(TREE_OPERAND(exp, 0)) == RESULT_DECL ||
05493      TREE_CODE(TREE_OPERAND(exp, 0)) == PARM_DECL)) {
05494   if (WN_operator(target_wn) == OPR_LDA) {
05495     // target_wn is a LDA of a ST.  Give the result the same ST.
05496     set_DECL_ST(TREE_OPERAND(exp, 0), WN_st(target_wn));
05497   } else if (WN_operator(target_wn) == OPR_LDID) {
05498     // target_wn is a LDID of a ST, where ST points to the target
05499     // location.  This only happens if ST is the fake first parm.  To
05500     // have the INIT_EXPR write to the target area, change node X into an
05501     // indirect ref of the ST, where X is the original target of the
05502     // init_expr (var_decl/result_decl/parm_decl).  This will make all
05503     // tree nodes that point to X now point to the indirect ref.
05504     tree opnd0 = TREE_OPERAND(exp, 0);
05505     tree ptr_var = build_decl(VAR_DECL, NULL_TREE,
05506             build_pointer_type(TREE_TYPE(opnd0)));
05507     TREE_SET_CODE(opnd0, INDIRECT_REF);
05508     TREE_OPERAND(opnd0, 0) = ptr_var;
05509     set_DECL_ST(ptr_var, WN_st(target_wn));
05510   }
05511       }
05512 
05513 #ifdef NEW_INITIALIZER
05514       {
05515         tree opnd0 = TREE_OPERAND(exp, 0);
05516         tree opnd1 = TREE_OPERAND(exp, 1);
05517         if( TREE_CODE(opnd0) == INDIRECT_REF &&
05518             TREE_CODE(opnd1) == CONSTRUCTOR ) {
05519           WN* target = WFE_Address_Of(opnd0);
05520           ST* copy_st = WFE_Generate_Initialized_Aggregate(target, opnd1);
05521           ST* orig_st = WN_st(target);
05522           if ( ST_st_idx(copy_st) != ST_st_idx(orig_st) ) {
05523             // If the returned ST is not the original one,
05524             //   it means we create a new temp ST for initialization
05525             // One case is on x8664, the returned struct is converted into 
05526             //   the first FORMAL.
05527             // When initialize the FORMAL, we need to use a temp st.
05528             //   we copy the new ST into target here
05529             TY_IDX copy_ty = ST_type(copy_st);
05530             WN* ldid = WN_Ldid(TY_mtype(copy_ty), 0, copy_st, copy_ty);
05531             if ( WN_operator(target) == OPR_LDA ) {
05532               WFE_Stmt_Append(
05533                          WN_Stid (TY_mtype(copy_ty), WN_lda_offset(target),
05534                                   orig_st, ST_type(orig_st), ldid),
05535                          Get_Srcpos() );
05536             }
05537             else if ( WN_operator(target) == OPR_LDID ) {
05538               WFE_Stmt_Append(
05539                          WN_Istore(TY_mtype(copy_ty), 0,
05540                                    ST_type(orig_st), target, ldid),
05541                          Get_Srcpos() );
05542             }
05543             else {
05544               FmtAssert(FALSE, ("Bad operator for target, not LDA/LDID"));
05545             }
05546           }
05547           break;
05548         }
05549       }
05550 #endif
05551 
05552       // fall through
05553 #endif
05554     case MODIFY_EXPR:
05555       /*
05556        * When operand 1 of an init_expr or modify_expr is a target_expr,
05557        * then the temporary in the target_expr needs to be replaced by
05558        * operand 1 of the init_expr or modify_expr and the cleanup
05559        * (operand 2) of the target_expr needs to be zeroed out, since
05560        * no temporary will be generated so none should be destroyed.
05561        */
05562 #ifdef KEY
05563        // Don't replace the temporary in the target_expr by the first operand
05564        // of the init_expr as the above comment says.  This is because we no
05565        // longer generate the MLDID-MSTID that copies the target_expr's
05566        // initialization result into the target_expr's init target (the
05567        // target_expr's temporary).  (Using MLDID-MSTID is incorrect when there
05568        // is a copy constructor.)  In the new scheme, the target_expr's
05569        // initializer writes directly into the target_expr's init target.
05570        // Doing the transformation in the above comment breaks this.  For
05571        // example:
05572        //
05573        //   init
05574        //     var_decl y  (node 1)
05575        //     target_expr
05576        //       var_decl x  (target_expr's init target, node 2)
05577        //       compound_expr (target_expr's initializer)
05578        //         call_expr
05579        //           addr_expr
05580        //           tree_list
05581        //             addr_expr  (arg 0)
05582        //               var_decl x
05583        //         var_decl x  (compound_expr returns x)
05584        //
05585        // After node 2 is replaced by node 1, the target_expr's init target
05586        // becomes y.  However, the target_expr's initializer still writes to x.
05587        // Without a MLDID-MSTID to copy x to y, the code is now incorrect.
05588        //
05589        // The solution is instead of replacing node 2 with node 1, we give both
05590        // x and y the same ST.  This follows the intention that x is just an
05591        // alias for y.
05592        //
05593        // The init's target can be an indirect ref.  (This occurs when we
05594        // changed the init target from a var_decl/result_decl/parm_decl to an
05595        // indirect ref based on a target_wn that is a LDID of a fake arg0 ST.)
05596        // In this case, replace the target_expr's var_decl x with the indirect
05597        // ref.  Change:
05598        //
05599        //   init
05600        //     indirect_ref    (node 1)
05601        //       var_decl y
05602        //     target_expr
05603        //       var_decl x    (node 2)
05604        //       initializer
05605        //
05606        // to:
05607        //
05608        //   init
05609        //     indirect_ref    (node 1)
05610        //       var_decl y
05611        //     target_expr
05612        //       indirect_ref  (node 2)
05613        //         var_decl y
05614        //       initializer
05615        //
05616        // After the transformation, target_expr's init target remains to be
05617        // node 2, but node 2 is renamed to be an indirect_ref node.  This will
05618        // cause all references inside the target_expr's initializer to
05619        // reference the location pointed to by the indirect_ref.
05620 
05621        // Handle case where initializer is a nop_expr (bug 3045):
05622        //   init
05623        //     indirect_ref
05624        //       var_decl y
05625        //     nop_expr
05626        //       target_expr
05627        //         var_decl x
05628        //         initializer
05629        //
05630        // Handle by expanding the nop_expr into the target location pointed to
05631        // by y.  Do this by setting target_wn to y before calling
05632        // WFE_Expand_Expr.  (This case was discovered after the scheme to
05633        // modify the init tree (described above) was implemented.  It seems the
05634        // correct approach is to simply set target_wn and then call
05635        // WFE_Expand_Expr to expand directly into target_wn, without modifying
05636        // the init tree.  Change to this scheme if more problems show up.)
05637        //
05638        // As below, only check for indirect_ref if the indirect_ref is created
05639        // by kg++fe to access through the fake arg0, in order to avoid
05640        // (indirect_ref (nop (var_decl))) which is generated by g++.
05641       {
05642   tree init_expr_opnd0 = TREE_OPERAND(exp, 0);
05643   if (TREE_CODE(TREE_OPERAND(exp, 1)) == NOP_EXPR &&
05644       TREE_CODE(TREE_OPERAND(TREE_OPERAND(exp, 1), 0)) == TARGET_EXPR &&
05645       TREE_CODE(init_expr_opnd0) == INDIRECT_REF &&
05646       TREE_CODE(TREE_OPERAND(init_expr_opnd0, 0)) == VAR_DECL) {
05647     tree t = TREE_OPERAND(exp, 1);
05648     ST *st = Get_ST(TREE_OPERAND(init_expr_opnd0, 0));
05649     WN *target_wn = WN_Ldid(Pointer_Mtype, 0, st, ST_type(st));
05650     wn = WFE_Expand_Expr(t, TRUE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
05651     break;
05652   }
05653       }
05654 #endif
05655       {
05656   tree t = NULL;
05657         if (TREE_CODE(TREE_OPERAND(exp, 1)) == TARGET_EXPR) {
05658     t = TREE_OPERAND(exp, 1);
05659     TREE_OPERAND(t, 2) = NULL_TREE;
05660         }
05661 #ifdef KEY
05662         // Handle case where initializer is (nop (target ...)).  Bug 7792.
05663         else if (TREE_CODE(TREE_OPERAND(exp, 1)) == NOP_EXPR &&
05664                  TREE_CODE(TREE_OPERAND(TREE_OPERAND(exp, 1), 0))
05665        == TARGET_EXPR) {
05666     t = TREE_OPERAND(TREE_OPERAND(exp, 1), 0);
05667     TREE_OPERAND(t, 2) = NULL_TREE;
05668         }
05669 #endif
05670 
05671         if (t != NULL) {
05672 #ifdef KEY
05673     // Only check for indirect_ref if the indirect_ref is created by
05674     // kg++fe to access through the fake arg0, in order to avoid
05675     // (indirect_ref (nop (var_decl))) which is generated by g++.
05676     tree init_expr_opnd0 = TREE_OPERAND(exp, 0);
05677           tree initializer = NULL;
05678     if (TREE_CODE(init_expr_opnd0) == INDIRECT_REF &&
05679         TREE_CODE(TREE_OPERAND(init_expr_opnd0, 0)) == VAR_DECL) {
05680       tree target_expr_opnd0 = TREE_OPERAND(t, 0);
05681       tree ptr_var =
05682         build_decl(VAR_DECL, NULL_TREE,
05683              TREE_TYPE(TREE_OPERAND(init_expr_opnd0, 0)));
05684       TREE_SET_CODE(target_expr_opnd0, INDIRECT_REF);
05685       TREE_OPERAND(target_expr_opnd0, 0) = ptr_var;
05686       set_DECL_ST(ptr_var, DECL_ST(TREE_OPERAND(init_expr_opnd0, 0)));
05687       wn = WFE_Expand_Expr(t);
05688       break;
05689     }
05690 #ifdef PATHSCALE_MERGE
05691     // The above is no longer true. INDIRECT_REFs generated by g++
05692     // are also handled here for bug 12788. Handle:
05693     //   init
05694     //     indirect_ref
05695     //       nop_expr
05696     //         var_decl y
05697     //     target_expr
05698     //       var_decl x
05699     //       initializer
05700     else if (TREE_CODE(init_expr_opnd0) == INDIRECT_REF &&
05701              TREE_CODE(TREE_OPERAND(init_expr_opnd0, 0)) == NOP_EXPR &&
05702              TREE_CODE(TREE_OPERAND(TREE_OPERAND(init_expr_opnd0,0),0))
05703                                                == VAR_DECL) {
05704       tree target_expr_opnd0 = TREE_OPERAND(t, 0);
05705       tree target_var = TREE_OPERAND(TREE_OPERAND(init_expr_opnd0, 0), 0);
05706       tree ptr_var =
05707         build_decl(VAR_DECL, NULL_TREE, TREE_TYPE(target_var));
05708       TREE_SET_CODE(target_expr_opnd0, INDIRECT_REF);
05709       TREE_OPERAND(target_expr_opnd0, 0) = ptr_var;
05710       set_DECL_ST(ptr_var, DECL_ST(target_var));
05711       wn = WFE_Expand_Expr(t);
05712       break;
05713     }
05714 #endif // PATHSCALE_MERGE
05715 #endif
05716     if (TREE_CODE(TREE_OPERAND(exp, 0)) == VAR_DECL    ||
05717         TREE_CODE(TREE_OPERAND(exp, 0)) == RESULT_DECL ||
05718         TREE_CODE(TREE_OPERAND(exp, 0)) == PARM_DECL) {
05719 #ifdef KEY
05720       ST *st = Get_ST(TREE_OPERAND(exp, 0));
05721       set_DECL_ST(TREE_OPERAND(t, 0), st);
05722 #else
05723       TREE_OPERAND(t, 0) = TREE_OPERAND(exp, 0);
05724 #endif
05725       wn = WFE_Expand_Expr(t);
05726       break;
05727     }
05728           // OSP_397, initializing a class member having copy-constructor
05729           // fixed by Pathscale
05730           // Bug 13261: Handle INDIRECT_REF generated by g++, when its
05731           // operand is not a decl.
05732           else if (TREE_CODE(init_expr_opnd0) == INDIRECT_REF &&
05733                    ((initializer = TREE_OPERAND(t,1)) ||
05734                     (initializer = TREE_OPERAND(t,3))) &&
05735                    (TREE_CODE(initializer) == CALL_EXPR ||
05736                     TREE_CODE(initializer) == AGGR_INIT_EXPR)) {
05737             TREE_OPERAND(t,0) = init_expr_opnd0;
05738             wn = WFE_Expand_Expr(t);
05739             break;
05740           }
05741     DevWarn ("INIT_EXPR/MODIFY_EXPR kid1 is TARGET_EXPR, kid0 is %s\n",
05742        Operator_From_Tree [TREE_CODE(TREE_OPERAND(exp, 0))].name);
05743         }
05744       }
05745 
05746     case PREDECREMENT_EXPR:
05747     case PREINCREMENT_EXPR:
05748     case POSTDECREMENT_EXPR:
05749     case POSTINCREMENT_EXPR:
05750       {
05751   if (TREE_CODE(TREE_OPERAND(exp, 1)) == ERROR_MARK)
05752       break;
05753 #ifdef KEY
05754   // If TREE_OPERAND(exp, 1) is a CALL_EXPR that returns a
05755   // ptr-to-member-function, then call
05756   // WFE_Expand_Ptr_To_Member_Func_Call_Expr to expand it.  Otherwise,
05757   // call WFE_Expand_Expr to do regular expansion.  Bug 4737.
05758   tree exp_opnd1 = TREE_OPERAND(exp, 1);
05759   if (WFE_Call_Returns_Ptr_To_Member_Func(exp_opnd1)) {
05760     TYPE_ID desc = TY_mtype(Get_TY(TREE_TYPE(exp_opnd1)));
05761     wn1 = WFE_Expand_Ptr_To_Member_Func_Call_Expr(exp_opnd1, 0,
05762                    Widen_Mtype(desc), desc);
05763         } else
05764 #endif
05765         wn1 = WFE_Expand_Expr (TREE_OPERAND (exp, 1)); // r.h.s.
05766 
05767 #ifdef TARG_SL
05768   wn  = WFE_Lhs_Of_Modify_Expr(code, TREE_OPERAND (exp, 0), TREE_OPERAND(exp,1), need_result, 
05769 #else
05770   wn  = WFE_Lhs_Of_Modify_Expr(code, TREE_OPERAND (exp, 0), need_result, 
05771 #endif
05772              0, 0, 0, FALSE, wn1, 0, FALSE, FALSE);
05773       }
05774       break;
05775 
05776     // ternary ops
05777 
05778     case BIT_FIELD_REF:
05779       {
05780         wn = WFE_Expand_Expr (TREE_OPERAND (exp, 0), TRUE, nop_ty_idx, 
05781             component_ty_idx, component_offset,
05782             field_id, FALSE);
05783   ty_idx = Get_TY (TREE_TYPE(exp));
05784   TYPE_ID rtype = TY_mtype(ty_idx);
05785   UINT siz = TY_size(ty_idx);
05786   TYPE_ID desc;
05787   if (siz <= 8) {
05788     if (MTYPE_signed(rtype))
05789       desc = Mtype_AlignmentClass(siz, MTYPE_CLASS_INTEGER);
05790     else desc = Mtype_AlignmentClass(siz, MTYPE_CLASS_UNSIGNED_INTEGER);
05791     rtype = Widen_Mtype(desc);
05792   }
05793   else desc = rtype;
05794 #ifdef KEY
05795   // bug 3074
05796         while (1) {
05797         if ((WN_operator(wn) == OPR_CVT)
05798             && (desc == rtype)
05799 #ifdef TARG_SL
05800             /* for SL, we need to use ldub and etc to support
05801              * byte load, and we dont want to expand desc
05802              */
05803             && WN_operator(WN_kid0(wn)) != OPR_LDA
05804             && WN_operator(WN_kid0(wn)) != OPR_LDID
05805             && WN_operator(WN_kid0(wn)) != OPR_LDBITS
05806 #endif
05807         )
05808             { // We do not need the CVT
05809                 WN * del = wn;
05810                 wn = WN_kid0 (wn);
05811                 WN_Delete (del);
05812             }
05813         else break;
05814         }
05815 #endif // KEY
05816   WN_set_rtype(wn, rtype);
05817   if (WN_desc(wn) != MTYPE_V)
05818     WN_set_desc(wn, desc);
05819   INT bofst = Get_Integer_Value(TREE_OPERAND(exp, 2));
05820   INT bsiz =Get_Integer_Value(TREE_OPERAND(exp, 1));
05821   if ((bsiz & 7) == 0 &&  // field size multiple of bytes
05822       MTYPE_size_min(desc) % bsiz == 0 && // accessed loc multiple of bsiz
05823       bofst % bsiz == 0) {    // bofst multiple of bsiz
05824     // not really a bit-field extraction!
05825     if (WN_desc(wn) != MTYPE_V)
05826       if (MTYPE_signed(rtype))
05827         WN_set_desc(wn, Mtype_AlignmentClass(bsiz >> 3, MTYPE_CLASS_INTEGER));
05828       else WN_set_desc(wn, Mtype_AlignmentClass(bsiz >> 3, MTYPE_CLASS_UNSIGNED_INTEGER));
05829     WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
05830   } else {
05831 #ifdef KEY
05832           // bofst is ofst in bits from the base of the object.
05833           // Convert it to ofst from the beginning of the field, and update
05834           // the load offset using the proper alignment
05835           // The change is needed when we come here with bofst > base_type_size
05836           mUINT16 base_type_size = MTYPE_bit_size (desc);
05837           WN_load_offset(wn) += (bofst / base_type_size) * MTYPE_byte_size (desc);
05838           bofst = bofst % base_type_size;
05839 #endif
05840     if (WN_operator(wn) == OPR_LDID)
05841       WN_set_operator(wn, OPR_LDBITS);
05842     else WN_set_operator(wn, OPR_ILDBITS);
05843     WN_set_bit_offset_size(wn, bofst, bsiz);
05844 #ifdef KEY
05845     TY_IDX ty = MTYPE_To_TY (WN_desc(wn));
05846     WN_set_ty (wn, ty);
05847     if (WN_operator(wn) == OPR_ILDBITS)
05848       WN_set_load_addr_ty(wn, Make_Pointer_Type(ty));  // Bug 12394
05849     break;
05850 #endif
05851   }
05852   if (MTYPE_byte_size (WN_desc(wn)) != TY_size(WN_ty(wn)))
05853     // the container is smaller than the entire struct
05854 #ifdef KEY
05855   {
05856     TY_IDX ty = MTYPE_To_TY (WN_desc(wn));
05857     if ((TY_kind(Ty_Table[WN_ty(wn)]) == KIND_STRUCT)
05858               && (TY_kind(Ty_Table[ty]) != KIND_STRUCT))
05859   // if struct is being changed to a non-struct, the field-id
05860   // does not hold any more.
05861     WN_set_field_id (wn, 0);
05862     WN_set_ty (wn, ty);
05863     if (WN_operator(wn) == OPR_ILOAD || WN_operator(wn) == OPR_ILDBITS)
05864       WN_set_load_addr_ty(wn, Make_Pointer_Type(ty));
05865   }
05866 #else
05867     WN_set_ty (wn, MTYPE_To_TY (WN_desc(wn)));
05868 #endif
05869       }
05870       break;
05871 
05872     // n-ary ops
05873 
05874     case ARRAY_REF:
05875       {
05876   UINT xtra_BE_ofst = 0;  // only needed for big-endian target
05877   TY_IDX elem_ty_idx;
05878   // generate the WHIRL array node
05879         wn0 = WFE_Array_Expr(exp, &elem_ty_idx, 0, 0, 0);
05880 
05881   // generate the iload node
05882   TY_IDX hi_ty_idx = Get_TY (TREE_TYPE(exp));
05883   desc_ty_idx = component_ty_idx;
05884   if (desc_ty_idx == 0)
05885           desc_ty_idx = hi_ty_idx;
05886 
05887         if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
05888     ty_idx = desc_ty_idx;
05889   else {
05890     ty_idx = nop_ty_idx;
05891     if (ty_idx == 0) 
05892       ty_idx = desc_ty_idx;
05893   }
05894 
05895   if (! is_bit_field) {
05896     if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
05897       if (Target_Byte_Sex == BIG_ENDIAN)
05898         xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
05899       desc_ty_idx = ty_idx;
05900     }
05901   }
05902         else {
05903           if (TY_size(desc_ty_idx) > TY_size(ty_idx))
05904             ty_idx = desc_ty_idx;
05905         }
05906 
05907         TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
05908         TYPE_ID desc = TY_mtype(desc_ty_idx);
05909         if (MTYPE_is_integral(desc)) {
05910           if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
05911             if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
05912     is_bit_field)
05913               rtype = Mtype_TransferSign(desc, rtype);
05914             else desc = Mtype_TransferSign(rtype, desc);
05915           }
05916         }
05917 
05918   Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
05919     ("WFE_Expand_Expr: field id for bit-field exceeds limit"));
05920   wn = WN_CreateIload(OPR_ILOAD, rtype,
05921           is_bit_field ? MTYPE_BS : desc, 
05922           component_offset+xtra_BE_ofst,
05923           field_id != 0 ? hi_ty_idx : ty_idx,
05924           Make_Pointer_Type(elem_ty_idx, FALSE),
05925           wn0, field_id);
05926       }
05927 #if defined(TARG_SL)
05928      // following code is used to set if iload is a v1buf iload
05929      // set corresponding flag for automatic expand v1buf ld/st
05930      // in whirl2ops.cxx 
05931     if(Mark_LDA_Vbuf_Offset(wn, INTRN_VBUF_OFFSET)) 
05932       WN_Set_is_internal_mem_ofst(wn);
05933 
05934     // following code used to handle assignment from one vbuf array value to 
05935     // another vbuf array value;
05936     // __v2buf array[2][3][16];
05937     // __v2buf array2[3][4][16];
05938     // array[0][1][2] = array2[2][3][4]
05939     //
05940     wn = Adjust_Vbuf_Array_Ofst(wn);
05941 #endif       // TARG_SL
05942 
05943       break;
05944 
05945     case AGGR_INIT_EXPR:
05946     case CALL_EXPR:
05947       {
05948   INTRINSIC iopc = INTRINSIC_NONE;
05949   tree arglist = TREE_OPERAND (exp, 1);
05950         TYPE_ID ret_mtype;
05951         WN *call_wn;
05952         WN *arg_wn;
05953   TY_IDX  arg_ty_idx;
05954         TYPE_ID arg_mtype;
05955         INT num_args = 0;
05956   INT num_handlers = 0;
05957         INT i;
05958   tree list;
05959   arg0 = TREE_OPERAND (exp, 0);
05960   enum tree_code code0 = TREE_CODE (arg0);
05961   // KEY:  true if type must be returned in mem
05962   BOOL return_in_mem = FALSE;
05963 #ifdef KEY
05964   ST *ret_st = NULL;    // return symbol
05965 #endif
05966   for (list = TREE_OPERAND (exp, 1); list; list = TREE_CHAIN (list)) {
05967           arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
05968           if (!WFE_Keep_Zero_Length_Structs    &&
05969               TY_mtype (arg_ty_idx) == MTYPE_M &&
05970               TY_size (arg_ty_idx) == 0) {
05971             // zero length struct parameter
05972           }
05973           else
05974             num_args++;
05975         }
05976         ty_idx = Get_TY(TREE_TYPE(exp));
05977         if (need_result) {
05978           if (!WFE_Keep_Zero_Length_Structs  &&
05979               TY_mtype (ty_idx) == MTYPE_M   &&
05980               TY_size (ty_idx) == 0) {
05981             // zero length struct return
05982             ret_mtype = MTYPE_V;
05983           }
05984           else
05985             ret_mtype = TY_mtype (ty_idx);
05986 #ifdef KEY
05987     // If the type must be returned in memory, create a symbol and pass
05988     // its address as the first param.
05989           if (TY_return_in_mem (ty_idx)) {
05990       ret_mtype = MTYPE_V;
05991       return_in_mem = TRUE;
05992             num_args++;   // first param is address of return symbol
05993     }
05994 #endif
05995         }
05996         else
05997           ret_mtype = MTYPE_V;
05998         st = NULL;
05999         if (code0 == ADDR_EXPR                  &&
06000             TREE_CODE (TREE_OPERAND (arg0, 0))) {
06001     tree func = TREE_OPERAND (arg0, 0);
06002     BOOL intrinsic_op = FALSE;
06003           BOOL whirl_generated = FALSE;
06004 
06005 #ifdef KEY
06006     // bug 8251: If we forcibly change the return type, we should
06007     // generate a CVT.
06008     TYPE_ID cvt_to = MTYPE_UNKNOWN;
06009 
06010     if (DECL_ASSEMBLER_NAME(func))
06011       TREE_SYMBOL_REFERENCED_BY_WHIRL(DECL_ASSEMBLER_NAME(func)) = 1;
06012 #endif
06013           
06014     if (DECL_BUILT_IN (func)) {
06015       if (DECL_BUILT_IN_CLASS (func) != BUILT_IN_MD) {
06016 
06017             switch (DECL_FUNCTION_CODE (func)) {
06018 
06019         case END_BUILTINS:
06020     break;
06021 
06022         case BUILT_IN_STDARG_START:
06023 #ifdef KEY
06024         case BUILT_IN_VA_START:
06025 #endif
06026         {
06027 #ifdef TARG_X8664
06028     if( TARGET_64BIT ){
06029       iopc = INTRN_VA_START;
06030       break;
06031     }
06032 #endif
06033     arg1 = TREE_VALUE (arglist);
06034     arg2 = TREE_VALUE (TREE_CHAIN (arglist));
06035     WN *arg_wn = WFE_Expand_Expr (arg1);
06036     TY_IDX arg_ty_idx = Get_TY (TREE_TYPE (arg1));
06037     while (TREE_CODE (arg2) == NOP_EXPR
06038            || TREE_CODE (arg2) == CONVERT_EXPR
06039            || TREE_CODE (arg2) == NON_LVALUE_EXPR
06040            || TREE_CODE (arg2) == INDIRECT_REF)
06041       arg2 = TREE_OPERAND (arg2, 0);
06042     ST *st2 = Get_ST (arg2);
06043 #if defined(TARG_X8664) || defined(TARG_SL) || defined(TARG_MIPS)
06044     const int align = PARM_BOUNDARY / BITS_PER_UNIT;
06045     wn = WN_Lda (Pointer_Mtype, 
06046                              ((TY_size (ST_type (st2)) + align-1) & (-align)),
06047                              st2);
06048 #else
06049     wn = WN_Lda (Pointer_Mtype, 
06050                              ((TY_size (ST_type (st2)) + 7) & (-8)),
06051                              st2);
06052 #endif
06053     if (WN_operator (arg_wn) == OPR_LDA) {
06054       wn = WN_Stid (Pointer_Mtype, WN_offset (arg_wn),
06055               WN_st (arg_wn), arg_ty_idx, wn);
06056     }
06057     else {
06058       wn = WN_CreateIstore (OPR_ISTORE, MTYPE_V,
06059                 Pointer_Mtype, 0, arg_ty_idx,
06060                 wn, arg_wn, 0);
06061     }
06062 
06063     WFE_Stmt_Append (wn, Get_Srcpos());
06064     whirl_generated = TRUE;
06065     wn = NULL;
06066     break;
06067         }
06068 
06069         case BUILT_IN_VA_COPY:
06070         {
06071     arg1 = TREE_VALUE (arglist);
06072     arg2 = TREE_VALUE (TREE_CHAIN (arglist));
06073                 TY_IDX arg_ty_idx = Get_TY (TREE_TYPE (arg1));
06074 
06075 
06076 #ifdef KEY
06077     /* Under -m32, convert a __builtin_va_copy to an assignment if the
06078        type of va_list is not array.
06079        Also, the original code seems to only work for -m64, like other
06080        va_XYZ code; under -m32, the source address is wrong.  (bug#2601)
06081        (But even under -m64, the using of memcpy is unnecessary.)
06082      */
06083 #if defined(TARG_X8664) || defined(TARG_SL) || defined(TARG_MIPS)
06084     if( !TARGET_64BIT )
06085 #endif
06086                 {
06087       FmtAssert( TREE_CODE(arglist) != ARRAY_TYPE,
06088            ("unexpected array type for intrinsic 'va_copy'") );
06089       WN* addr = WFE_Expand_Expr( arg1 );
06090       WN* value = WFE_Expand_Expr( arg2 );
06091       wn = WN_CreateIstore( OPR_ISTORE, MTYPE_V, Pointer_Mtype,
06092           0, arg_ty_idx, value, addr, 0 );
06093 
06094       WFE_Stmt_Append( wn, Get_Srcpos() );
06095       whirl_generated = TRUE;
06096       wn = NULL;
06097       break;
06098     }
06099 #endif // KEY
06100 
06101     WN *dst  = WN_CreateParm (Pointer_Mtype, WFE_Expand_Expr (arg1),
06102             arg_ty_idx, WN_PARM_BY_VALUE);
06103     WN *src  = WN_CreateParm (Pointer_Mtype, WFE_Expand_Expr (arg2),
06104             arg_ty_idx, WN_PARM_BY_VALUE);
06105     WN *size = WN_CreateParm (MTYPE_I4,
06106             WN_Intconst(MTYPE_I4,TY_size(TY_pointed(arg_ty_idx))),
06107             Be_Type_Tbl(MTYPE_I4), WN_PARM_BY_VALUE);
06108     wn = WN_Create (OPR_INTRINSIC_CALL, ret_mtype, MTYPE_V, 3);
06109     WN_intrinsic (wn) = INTRN_MEMCPY;
06110     WN_kid0 (wn) = dst;
06111     WN_kid1 (wn) = src;
06112     WN_kid2 (wn) = size;
06113     WFE_Stmt_Append (wn, Get_Srcpos());
06114     whirl_generated = TRUE;
06115     wn = NULL;
06116     break;
06117         }
06118 
06119         case BUILT_IN_VA_END:
06120         {
06121     arg1 = TREE_VALUE (arglist);
06122     wn = WN_CreateEval ( WFE_Expand_Expr (arg1) );
06123     WFE_Stmt_Append (wn, Get_Srcpos());
06124     whirl_generated = TRUE;
06125     wn = NULL;
06126     break;
06127         }
06128 
06129         case BUILT_IN_NEXT_ARG:
06130         {
06131                 tree last_parm = tree_last 
06132            (DECL_ARGUMENTS (Current_Function_Decl()));
06133     while (TREE_CODE (last_parm) == NOP_EXPR
06134            || TREE_CODE (last_parm) == CONVERT_EXPR
06135            || TREE_CODE (last_parm) == NON_LVALUE_EXPR
06136            || TREE_CODE (last_parm) == INDIRECT_REF)
06137       last_parm = TREE_OPERAND (last_parm, 0);
06138     ST *st = Get_ST (last_parm);
06139     arg_wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
06140     wn = WN_Binary (OPR_ADD, Pointer_Mtype, arg_wn,
06141         WN_Intconst (Pointer_Mtype,
06142                Parameter_Size(ST_size(st))));
06143                 whirl_generated = TRUE;
06144     break;
06145         }
06146 
06147               case BUILT_IN_ALLOCA:
06148     Set_PU_has_alloca (Get_Current_PU ());
06149     Set_PU_has_user_alloca (Get_Current_PU ());
06150                 arg_wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06151           wn = WN_CreateAlloca (arg_wn);
06152                 whirl_generated = TRUE;
06153                 break;
06154 
06155               case BUILT_IN_MEMCPY:
06156     iopc = INTRN_MEMCPY;
06157                 break;
06158 
06159               case BUILT_IN_MEMCMP:
06160     iopc = INTRN_MEMCMP;
06161                 break;
06162 
06163               case BUILT_IN_MEMSET:
06164     iopc = INTRN_MEMSET;
06165                 break;
06166 
06167               case BUILT_IN_STRCPY:
06168     iopc = INTRN_STRCPY;
06169                 break;
06170 
06171               case BUILT_IN_STRCMP:
06172 #ifdef GPLUSPLUS_FE
06173     iopc = INTRN_STRCMP;
06174 #else
06175     if (arglist == 0
06176         /* Arg could be non-pointer if user redeclared this fcn wrong.  */
06177         || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
06178         || TREE_CHAIN (arglist) == 0
06179         || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
06180       break;
06181     else {
06182       arg1 = TREE_VALUE (arglist);
06183       arg2 = TREE_VALUE (TREE_CHAIN (arglist));
06184       tree len1 = c_strlen (arg1);
06185       if (len1) {
06186         tree len2 = c_strlen (arg2);
06187         if (len2) {
06188           char *ptr1 = get_string_pointer (WFE_Expand_Expr (arg1));
06189           char *ptr2 = get_string_pointer (WFE_Expand_Expr (arg2));
06190           if (ptr1 && ptr2) {
06191       wn = WN_Intconst (MTYPE_I4,
06192             strcmp (ptr1, ptr2));
06193       whirl_generated = TRUE;
06194       break;
06195           }
06196         }
06197       }
06198       iopc = INTRN_STRCMP;
06199 //      intrinsic_op = TRUE;
06200     }
06201 #endif /* GPLUSPLUS_FE */
06202                 break;
06203 
06204               case BUILT_IN_STRLEN:
06205 #ifdef GPLUSPLUS_FE
06206     iopc = INTRN_STRLEN;
06207 #else
06208     if (arglist == 0
06209     /* Arg could be non-pointer if user redeclared this fcn wrong.  */
06210        || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
06211       break;
06212     else {
06213       tree src = TREE_VALUE (arglist);
06214       tree len = c_strlen (src);
06215       if (len) {
06216         wn = WFE_Expand_Expr (len);
06217         whirl_generated = TRUE;
06218       }
06219       else {
06220         iopc = INTRN_STRLEN;
06221 //        intrinsic_op = TRUE;
06222       }
06223     }
06224 #endif /* GPLUSPLUS_FE */
06225                 break;
06226 
06227 #ifdef KEY
06228       case BUILT_IN_FLOOR:
06229         arg_wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06230 #if defined TARG_MIPS
06231         iopc = INTRN_FLOOR;
06232         intrinsic_op = TRUE;
06233 #else
06234         wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype , MTYPE_F8, arg_wn);
06235               whirl_generated = TRUE;
06236 #endif        
06237         break;
06238 
06239       case BUILT_IN_FLOORF: 
06240               arg_wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06241 #if defined TARG_MIPS
06242         iopc = INTRN_FLOORF;
06243         intrinsic_op = TRUE;
06244 #else
06245         wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_F4, arg_wn);
06246               whirl_generated = TRUE;
06247 #endif        
06248         break;
06249 
06250 #ifndef TARG_MIPS
06251             case BUILT_IN_FLOORL:
06252               arg_wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06253 #ifdef TARG_IA64
06254         wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_F10, arg_wn);
06255 #else
06256         wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_FQ, arg_wn);
06257 #endif // TARG_IA64       
06258         whirl_generated = TRUE;
06259               break;
06260 #endif // ! TARG_MIPS
06261 #endif // KEY
06262 
06263 #ifdef KEY
06264         case BUILT_IN_SQRT:
06265     if( flag_errno_math ){
06266       break;
06267     }
06268 #else
06269               case BUILT_IN_FSQRT:
06270 #endif
06271                 arg_wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06272                 wn = WN_CreateExp1 (OPR_SQRT, ret_mtype, MTYPE_V, arg_wn);
06273                 whirl_generated = TRUE;
06274                 break;
06275 
06276               case BUILT_IN_SIN:
06277     intrinsic_op = TRUE;
06278 #ifdef TARG_X8664
06279                 if (!Force_IEEE_Comparisons)
06280                 {
06281                   iopc = INTRN_SINL;
06282       if (ret_mtype != MTYPE_FQ)
06283       {
06284         // generate a cvt to 'cvt_to'
06285         cvt_to = ret_mtype;
06286         ret_mtype = MTYPE_FQ;
06287       }
06288                   break;
06289                 }
06290 #endif
06291 #ifdef KEY
06292                 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06293 #endif
06294          if (ret_mtype == MTYPE_F4) iopc = INTRN_F4SIN;
06295                 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8SIN;
06296                 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'sin'");
06297                 break;
06298 
06299               case BUILT_IN_COS:
06300     intrinsic_op = TRUE;
06301 #ifdef TARG_X8664
06302                 if (!Force_IEEE_Comparisons)
06303                 {
06304                   iopc = INTRN_COSL;
06305       if (ret_mtype != MTYPE_FQ)
06306       {
06307         // generate a cvt to 'cvt_to'
06308         cvt_to = ret_mtype;
06309         ret_mtype = MTYPE_FQ;
06310       }
06311                   break;
06312                 }
06313 #endif
06314 #ifdef KEY
06315                 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06316 #endif
06317          if (ret_mtype == MTYPE_F4) iopc = INTRN_F4COS;
06318                 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8COS;
06319                 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'cos'");
06320                 break;
06321 
06322 #ifdef KEY
06323               case BUILT_IN_EXP:
06324         case BUILT_IN_EXPF:
06325     // bug 3390
06326     // If return type is void, generate an intrinsic assuming
06327     // double (so if it is without side-effects, optimizer can 
06328     // remove it)
06329     if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06330 
06331                 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4EXP;
06332                 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8EXP;
06333                 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'exp'");
06334     intrinsic_op = TRUE;
06335                 break;
06336 
06337       case BUILT_IN_POW:
06338 
06339                 // Bug 8195: If for whatever reason the pow(3) call is unused,
06340                 // need_result will be false. Then, the value that this very
06341                 // function assigns to ret_mtype for pow(3) is MTYPE_V. So,
06342                 // just like we handle BUILT_IN_EXP above, we need to reassign
06343                 // ret_mtype to MTYPE_F8.
06344 
06345                 // Note that since pow[lf](3) are not builtin's (unlike the way
06346                 // exp[lf]?(3)'s are), we only permit ret_mtype MTYPE_F8 here.
06347 
06348                 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06349 
06350           FmtAssert(ret_mtype == MTYPE_F8, 
06351         ("unexpected mtype for intrinsic 'pow'"));
06352     iopc = INTRN_F8EXPEXPR;
06353     intrinsic_op = TRUE;
06354     break;
06355 #endif // KEY
06356 
06357               case BUILT_IN_CONSTANT_P:
06358               {
06359                 tree arg = TREE_VALUE (TREE_OPERAND (exp, 1));
06360                 STRIP_NOPS (arg);
06361                 if (really_constant_p (arg)
06362                     || (TREE_CODE (arg) == ADDR_EXPR
06363                         && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
06364     {
06365                   wn = WN_Intconst (MTYPE_I4, 1);
06366       whirl_generated = TRUE; // KEY
06367     }
06368 #ifdef KEY
06369 // If not yet compile-time constant, let the backend decide if it is 
06370 // a constant
06371     else
06372     {
06373       iopc = INTRN_CONSTANT_P;
06374                   if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_I4;
06375       intrinsic_op = TRUE;
06376     }
06377 #else
06378 
06379                 else
06380                   wn = WN_Intconst (MTYPE_I4, 0);
06381 //                wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06382                 whirl_generated = TRUE;
06383 #endif // KEY
06384                 break;
06385               }
06386 #if 0
06387               case BUILT_IN_LOCK_TEST_AND_SET:
06388                 wn = emit_builtin_lock_test_and_set (exp, num_args-2);
06389                 whirl_generated = TRUE;
06390                 break;
06391 
06392               case BUILT_IN_LOCK_RELEASE:
06393                 emit_builtin_lock_release (exp, num_args-1);
06394                 whirl_generated = TRUE;
06395                 break;
06396 
06397               case BUILT_IN_COMPARE_AND_SWAP:
06398                 wn = emit_builtin_compare_and_swap (exp, num_args-3);
06399                 whirl_generated = TRUE;
06400                 break;
06401 
06402               case BUILT_IN_SYNCHRONIZE:
06403                 emit_builtin_synchronize (exp, num_args);
06404                 whirl_generated = TRUE;
06405                 break;
06406 #endif
06407 
06408               case BUILT_IN_RETURN_ADDRESS:
06409                 i = Get_Integer_Value (TREE_VALUE (TREE_OPERAND (exp, 1)));
06410     if (i > 0) {
06411       // currently don't handle levels > 0,
06412       // which requires iterating thru call-stack
06413       // and finding $ra in fixed place.
06414       warning("non-zero levels not supported for builtin_return_address");
06415       wn = WN_Intconst(Pointer_Mtype, 0);
06416     }
06417     else {
06418       st = WFE_Get_Return_Address_ST (i);
06419       wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type (st));
06420     }
06421                 whirl_generated = TRUE;
06422     break;
06423 
06424 #ifdef KEY
06425               case BUILT_IN_EXTRACT_RETURN_ADDR:
06426     list = TREE_OPERAND (exp, 1);
06427     wn   = WFE_Expand_Expr (TREE_VALUE (list));
06428                 wn = WN_Binary (OPR_BAND, Pointer_Mtype, wn, 
06429         WN_Intconst(Pointer_Mtype, -2));
06430                 whirl_generated = TRUE;
06431     break;
06432 
06433               case BUILT_IN_FRAME_ADDRESS:
06434     Set_PU_has_alloca(Get_Current_PU());
06435     iopc = MTYPE_byte_size(Pointer_Mtype) == 4 ?
06436          INTRN_U4READFRAMEPOINTER : INTRN_U4READFRAMEPOINTER;
06437     intrinsic_op = TRUE;
06438     break;
06439         case BUILT_IN_APPLY_ARGS:
06440     Set_PU_has_alloca(Get_Current_PU());
06441     iopc = INTRN_APPLY_ARGS;
06442     break;  
06443         case BUILT_IN_APPLY:
06444     {
06445       WN *load_wn, *sp_addr;
06446 
06447       Set_PU_has_alloca(Get_Current_PU());
06448 
06449       iopc = INTRN_APPLY;
06450       call_wn = WN_Create (OPR_INTRINSIC_CALL, ret_mtype, MTYPE_V, 
06451                num_args);
06452       WN_intrinsic (call_wn) = iopc;
06453       WN_Set_Linenum (call_wn, Get_Srcpos());
06454       WN_Set_Call_Default_Flags (call_wn);
06455       i = 0;
06456       BOOL generate_mload = FALSE;
06457       WN *kid1 = NULL;
06458       WN *kid2 = NULL;
06459       for (list = TREE_OPERAND (exp, 1);
06460            list;
06461            list = TREE_CHAIN (list)) {
06462         arg_wn     = WFE_Expand_Expr (TREE_VALUE (list));
06463         if (i == 1)
06464           kid1 = arg_wn;
06465         if (i == 2 && 
06466       WN_operator(arg_wn) != OPR_INTCONST) {
06467           generate_mload = TRUE;
06468           kid2 = arg_wn;
06469         } else if (i == 2)
06470           kid2 = arg_wn;
06471         arg_ty_idx = Get_TY(TREE_TYPE(TREE_VALUE(list)));
06472         arg_mtype  = TY_mtype(arg_ty_idx);
06473         arg_wn = WN_CreateParm (Mtype_comparison (arg_mtype), 
06474               arg_wn,
06475               arg_ty_idx, WN_PARM_BY_VALUE);
06476         WN_kid (call_wn, i++) = arg_wn;
06477       }
06478 
06479       // Store SP & Alloca
06480       TY_IDX ty_idx = 
06481         Make_Pointer_Type (Be_Type_Tbl (MTYPE_V), FALSE);
06482       ST* alloca_st_0 = 
06483         Gen_Temp_Symbol (ty_idx, 
06484              "__builtin_apply_alloca0");
06485       WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL,
06486                    alloca_st_0);
06487       WN *alloca_0 = 
06488         WN_CreateAlloca (WN_CreateIntconst (OPC_I4INTCONST, 0));
06489       WN *alloca_kid0 = alloca_0;
06490       alloca_kid0 = 
06491         WN_Stid (Pointer_Mtype, 
06492            0, alloca_st_0, ty_idx, alloca_kid0);
06493       WFE_Stmt_Append (alloca_kid0, Get_Srcpos());
06494       ST *alloca_st_1 = 
06495         Gen_Temp_Symbol (ty_idx, 
06496              "__builtin_apply_alloca1");
06497       WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL,
06498                      alloca_st_1);
06499       WN *alloca_1 = WN_CreateAlloca (kid2);
06500       WN *alloca_kid1 = alloca_1;
06501       alloca_kid1 = WN_Stid (Pointer_Mtype, 
06502            0, alloca_st_1, ty_idx, alloca_kid1);
06503       WFE_Stmt_Append (alloca_kid1, Get_Srcpos());
06504 
06505       // The src is actually in 0(kid1)
06506       kid1 = 
06507         WN_CreateIload (OPR_ILOAD, MTYPE_I4, MTYPE_I4, 0,
06508             MTYPE_To_TY(MTYPE_I4), 
06509             Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)), 
06510             kid1, 0);
06511       load_wn = 
06512         WN_CreateMload (0, 
06513             Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)), 
06514             kid1, kid2);
06515       sp_addr = WN_LdidPreg(MTYPE_U4, 29); // $sp
06516       WFE_Stmt_Append(WN_CreateMstore (0, 
06517             Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)), 
06518                load_wn,
06519                sp_addr,
06520                kid2),
06521           Get_Srcpos());
06522 
06523       WFE_Stmt_Append (call_wn, Get_Srcpos());
06524 
06525       call_wn = WN_Create (OPR_ICALL, ret_mtype, MTYPE_V, 1);
06526       WN_kid(call_wn, 0) = 
06527         WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06528       WN_set_ty (call_wn, TY_pointed(Get_TY(
06529           TREE_TYPE (TREE_VALUE(TREE_OPERAND (exp, 1))))));
06530       WFE_Stmt_Append (call_wn, Get_Srcpos());    
06531 
06532       TY_IDX tyi;
06533       TY& ty = New_TY(tyi);
06534       TY_Init(ty, 16, KIND_STRUCT, MTYPE_M,
06535         Save_Str("__apply"));
06536       Set_TY_align(tyi, 8);
06537       ST *tmpst = New_ST(CURRENT_SYMTAB);
06538       ST_Init(tmpst, TY_name_idx(ty),
06539         CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, tyi);
06540       Set_ST_is_temp_var(tmpst);
06541       WN *load, *store;
06542       load = WN_LdidPreg(MTYPE_I8, 2); // $v0
06543       store = WN_Stid(MTYPE_I8, 
06544           (WN_OFFSET)0, tmpst, Spill_Int_Type, load);
06545       WFE_Stmt_Append (store, Get_Srcpos());    
06546       load = WN_LdidPreg(MTYPE_F8, 32); //$f0
06547       store = WN_Stid(MTYPE_F8, 
06548           (WN_OFFSET)8, tmpst, Spill_Int_Type, load);
06549       WFE_Stmt_Append (store, Get_Srcpos());    
06550       wn = WN_Lda (Pointer_Mtype, 0, tmpst, 
06551              Make_Pointer_Type (ST_type(tmpst), FALSE));
06552 
06553       // Dealloca/Restore SP
06554       WN *dealloca_wn = WN_CreateDealloca (2);
06555       WN_kid0 (dealloca_wn) = 
06556         WN_Ldid (Pointer_Mtype, 
06557            0, alloca_st_0, ST_type (alloca_st_0));
06558       WN_kid1 (dealloca_wn) = 
06559         WN_Ldid (Pointer_Mtype, 
06560            0, alloca_st_1, ST_type (alloca_st_1));
06561       WFE_Stmt_Append (dealloca_wn, Get_Srcpos());    
06562       
06563       whirl_generated = TRUE;
06564       break;
06565     }
06566         case BUILT_IN_RETURN:
06567     Set_PU_has_alloca(Get_Current_PU());
06568     iopc = INTRN_RETURN;
06569     break;  
06570 
06571                 // Implement built-in versions of the ISO C99 floating point
06572                 // comparison macros (that avoid raising exceptions for
06573                 // unordered operands)
06574               case BUILT_IN_ISGREATER:
06575                 iopc = INTRN_ISGREATER;
06576                 intrinsic_op = TRUE;
06577                 break;
06578               case BUILT_IN_ISGREATEREQUAL:
06579                 iopc = INTRN_ISGREATEREQUAL;
06580                 intrinsic_op = TRUE;
06581                 break;
06582               case BUILT_IN_ISLESS:
06583                 iopc = INTRN_ISLESS;
06584                 intrinsic_op = TRUE;
06585                 break;
06586               case BUILT_IN_ISLESSEQUAL:
06587                 iopc = INTRN_ISLESSEQUAL;
06588                 intrinsic_op = TRUE;
06589                 break;
06590               case BUILT_IN_ISLESSGREATER:
06591                 iopc = INTRN_ISLESSGREATER;
06592                 intrinsic_op = TRUE;
06593                 break;
06594               case BUILT_IN_ISUNORDERED:
06595                 iopc = INTRN_ISUNORDERED;
06596                 intrinsic_op = TRUE;
06597                 break;
06598 
06599         case BUILT_IN_EXPECT:
06600 #ifdef KEY
06601                 iopc = INTRN_EXPECT;
06602                 intrinsic_op = TRUE;
06603                 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_I4; // bug 12344
06604 #else
06605                 wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06606                 whirl_generated = TRUE;
06607 #endif
06608           break;
06609 
06610               case BUILT_IN_FFS:
06611                 iopc = INTRN_I4FFS;
06612                 intrinsic_op = TRUE;
06613                 if (ret_mtype == MTYPE_V)
06614                   ret_mtype = MTYPE_I4;
06615                 break;
06616 
06617         case BUILT_IN_EXTEND_POINTER:
06618     wn = WFE_Expand_Expr (TREE_VALUE (TREE_OPERAND (exp, 1)));
06619     whirl_generated = TRUE;
06620           break;
06621   
06622         case BUILT_IN_POPCOUNT:
06623         case BUILT_IN_POPCOUNTL:
06624         case BUILT_IN_POPCOUNTLL:
06625           iopc = INTRN_POPCOUNT;
06626     intrinsic_op = TRUE;
06627     break;
06628   
06629         case BUILT_IN_CTZ:
06630         case BUILT_IN_CTZL:
06631         case BUILT_IN_CTZLL:
06632           iopc = INTRN_CTZ;
06633     intrinsic_op = TRUE;
06634     break;
06635 
06636         case BUILT_IN_TRAP:
06637     call_wn = WN_Create (OPR_CALL, MTYPE_V, MTYPE_V, 0);
06638     st = Get_ST (TREE_OPERAND (arg0, 0));
06639     Set_ST_name_idx (st, Save_Str ("abort"));
06640     WN_st_idx (call_wn) = ST_st_idx (st);
06641     WN_Set_Linenum (call_wn, Get_Srcpos());
06642     WN_Set_Call_Default_Flags (call_wn);
06643     WFE_Stmt_Append (call_wn, Get_Srcpos());
06644     whirl_generated = TRUE;
06645     break;
06646 
06647         case BUILT_IN_PREFETCH:
06648           {
06649       // prefetch address
06650       tree pf_arg = TREE_OPERAND (exp, 1);
06651       WN * pf_addr = WFE_Expand_Expr (TREE_VALUE (pf_arg));
06652       // Note 2nd/3rd argument optional
06653       // read/write access
06654       pf_arg = TREE_CHAIN (pf_arg);
06655       UINT32 pf_flag = 0;
06656       int access = 0;
06657       if (pf_arg && TREE_CODE (TREE_VALUE (pf_arg)) == INTEGER_CST)
06658         access = Get_Integer_Value (TREE_VALUE (pf_arg));
06659       if (access == 0)
06660         PF_SET_READ (pf_flag);
06661       else // should be 1 (write access)
06662         PF_SET_WRITE (pf_flag);
06663       // Ignore 3rd argument which gives a measure of temporal
06664       // locality. LNO does analyze the temporal locality, but
06665       // not sure what is a good way to encode it in PREFETCH.
06666       PF_SET_MANUAL (pf_flag); // manual prefetch
06667       WFE_Stmt_Append (WN_CreatePrefetch (0, pf_flag, pf_addr),
06668                        Get_Srcpos());
06669       whirl_generated = TRUE;
06670     }
06671     break;
06672 #endif
06673 
06674 #ifdef TARG_X8664
06675               case BUILT_IN_COSF:
06676               case BUILT_IN_COSL:
06677                 if (!Force_IEEE_Comparisons)
06678                 {
06679                   iopc = INTRN_COSL;
06680                   intrinsic_op = TRUE;
06681       if (ret_mtype != MTYPE_FQ)
06682       {
06683         // generate a cvt to 'cvt_to'
06684         cvt_to = ret_mtype;
06685         ret_mtype = MTYPE_FQ;
06686       }
06687                 }
06688                 break;
06689                                                                                 
06690               case BUILT_IN_SINF:
06691               case BUILT_IN_SINL:
06692                 if (!Force_IEEE_Comparisons)
06693                 {
06694                   iopc = INTRN_SINL;
06695                   intrinsic_op = TRUE;
06696       if (ret_mtype != MTYPE_FQ)
06697       {
06698         // generate a cvt to 'cvt_to'
06699         cvt_to = ret_mtype;
06700         ret_mtype = MTYPE_FQ;
06701       }
06702                 }
06703                 break;
06704 #endif // TARG_X8664
06705 
06706 #ifdef KEY
06707 #if !defined(TARG_SL)
06708               case BUILT_IN_TAN:
06709                 // return type should only be F8 for tan
06710                 if (ret_mtype == MTYPE_F8)
06711                 {
06712                   iopc = INTRN_TAN;
06713                   intrinsic_op = TRUE;
06714                 }
06715                 break;
06716 #endif
06717 #endif
06718 #if defined(TARG_SL)
06719            case BUILT_IN_PERIPHERAL_RW_BEGIN:
06720              iopc = INTRN_PERIPHERAL_RW_BEGIN; 
06721              break;
06722            case BUILT_IN_PERIPHERAL_RW_END:
06723              iopc = INTRN_PERIPHERAL_RW_END; 
06724              break;
06725       case BUILT_IN_VBUF_OFFSET:
06726         iopc = INTRN_VBUF_OFFSET;
06727         intrinsic_op = TRUE;
06728         break;
06729       case BUILT_IN_VBUF_ABSOLUTE:
06730         iopc = INTRN_VBUF_ABSOLUTE;
06731         intrinsic_op = TRUE;
06732         break;
06733       case BUILT_IN_SBUF_OFFSET:
06734         iopc = INTRN_SBUF_OFFSET;
06735         intrinsic_op = TRUE;
06736         break;
06737            case  BUILT_IN_CVT64_HIGH:
06738                 iopc = INTRN_CVT64_HIGH;
06739                 intrinsic_op = TRUE;
06740                 break;
06741            case BUILT_IN_CVT64_LOW:
06742                 iopc = INTRN_CVT64_LOW;
06743                 intrinsic_op = TRUE;
06744                 break;
06745            case BUILT_IN_CVT32:
06746                 iopc = INTRN_CVT32;
06747                 intrinsic_op = TRUE;
06748                 break;
06749            case  BUILT_IN_LONGLONG_CVT64_HIGH:
06750                 iopc = INTRN_LONGLONG_CVT64_HIGH;
06751                 intrinsic_op = TRUE;
06752                 break;
06753            case BUILT_IN_LONGLONG_CVT64_LOW:
06754                 iopc = INTRN_LONGLONG_CVT64_LOW;
06755                 intrinsic_op = TRUE;
06756                 break;
06757            case BUILT_IN_C3_INIT_ACC:
06758                 iopc = INTRN_C3_INIT_ACC;
06759                 break;
06760            case BUILT_IN_C3_SAVE_ACC:
06761                 iopc = INTRN_C3_SAVE_ACC;
06762                 break;
06763            case BUILT_IN_C3_INIT_ADDR:
06764                 iopc = INTRN_C3_INIT_ADDR;
06765                 break;
06766            case BUILT_IN_C3_SAVE_ADDR:
06767                 iopc = INTRN_C3_SAVE_ADDR;
06768                 break;
06769            case BUILT_IN_C3_INIT_DACC:
06770                 iopc = INTRN_C3_INIT_DACC;
06771                 break;
06772            case BUILT_IN_C3_SAVE_DACC:
06773                 iopc = INTRN_C3_SAVE_DACC;
06774                 break;
06775            case BUILT_IN_C3_MVFS:
06776                 iopc = INTRN_C3_MVFS;
06777                 intrinsic_op = TRUE;
06778                 break;
06779            case BUILT_IN_SET_ADDR:
06780                 iopc = INTRN_C3_SET_ADDR;
06781                 break;
06782            case BUILT_IN_SET_CIRCBUF:
06783                 iopc = INTRN_C3_SET_CIRCBUF;
06784                 break;
06785            case BUILT_IN_C3AADDA:
06786                 iopc = INTRN_C3AADDA;
06787                 intrinsic_op = TRUE;
06788                 break;
06789            case BUILT_IN_C3BITR:
06790                 iopc = INTRN_C3BITR;
06791                 intrinsic_op = TRUE;
06792                 break;
06793            case BUILT_IN_C3CS:
06794                 iopc = INTRN_C3CS;
06795                 intrinsic_op = TRUE;
06796                 break;
06797            case BUILT_IN_C3DADD:
06798                 iopc = INTRN_C3DADD;
06799                 intrinsic_op = TRUE;
06800                 break;
06801            case BUILT_IN_C3DMAC:
06802                 iopc = INTRN_C3DMAC;
06803                 intrinsic_op = TRUE;
06804                 break;
06805            case BUILT_IN_C3DMACA:
06806                 iopc = INTRN_C3DMAC_A;
06807                 intrinsic_op = TRUE;
06808                 break;
06809            case BUILT_IN_C3DMULA:
06810                 iopc = INTRN_C3DMULA;
06811                 intrinsic_op = TRUE;
06812                 break;
06813            case BUILT_IN_C3DMULAA:
06814                 iopc = INTRN_C3DMULA_A;
06815                 intrinsic_op = TRUE;
06816                 break;
06817            case BUILT_IN_C3DSHLLI:
06818                 iopc = INTRN_C3DSHLL_I;
06819                 intrinsic_op = TRUE;
06820                 break;
06821            case BUILT_IN_C3FFE:
06822                 iopc = INTRN_C3FFE;
06823                 break;
06824            case BUILT_IN_C3LD:
06825                 iopc = INTRN_C3LD;
06826                 intrinsic_op = TRUE;
06827                 break;
06828            case BUILT_IN_C3ST:
06829                 iopc = INTRN_C3ST;
06830                 break;
06831            case BUILT_IN_C3LEAD:
06832                 iopc = INTRN_C3LEAD;
06833                 intrinsic_op = TRUE;
06834                 break;
06835            case BUILT_IN_C3MAC:
06836                 iopc = INTRN_C3MAC;
06837                 intrinsic_op = TRUE;
06838                 break;
06839            case BUILT_IN_C3MACA:
06840                 iopc = INTRN_C3MAC_A;
06841                 intrinsic_op = TRUE;
06842                 break;
06843            case BUILT_IN_C3MACAR:
06844                 iopc = INTRN_C3MAC_AR;
06845                 intrinsic_op = TRUE;
06846                 break;
06847            case BUILT_IN_C3MACI:
06848                 iopc = INTRN_C3MAC_I;
06849                 intrinsic_op = TRUE;
06850                 break;
06851            case BUILT_IN_C3MULA:
06852                 iopc = INTRN_C3MULA;
06853                 intrinsic_op = TRUE;
06854                 break;
06855            case BUILT_IN_C3MULAA:
06856                 iopc =