00001
00002
00003
00004
00005
00006
00007
00008
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00032
00033 extern "C"{
00034 #include "gspin-wgen-interface.h"
00035 }
00036 #if defined(BUILD_OS_DARWIN)
00037 #include <limits.h>
00038 #else
00039 #include <values.h>
00040 #endif
00041 #include "defs.h"
00042 #include "glob.h"
00043 #include "config.h"
00044 #ifdef TARG_X8664
00045 #include "config_opt.h"
00046 #endif
00047 #include "wn.h"
00048 #include "wn_util.h"
00049 #include "targ_sim.h"
00050 #include "const.h"
00051 #include "intrn_info.h"
00052 #include "c_int_model.h"
00053
00054 #include "ir_reader.h"
00055 #include "wgen_misc.h"
00056 #include "wgen_dst.h"
00057 #include "wgen_spin_symbol.h"
00058 #include "wgen_decl.h"
00059 #include "wgen_expr.h"
00060 #include "wgen_stmt.h"
00061 #include "wgen_tracing.h"
00062 #ifdef FE_GNU_4_2_0
00063 #include "omp_types.h"
00064 #include "wgen_omp_directives.h"
00065 #endif
00066
00067 #define BITS_PER_UNIT 8
00068
00069 extern void WGEN_Expand_Return(gs_t, gs_t);
00070
00071 LABEL_IDX loop_expr_exit_label = 0;
00072
00073 gs_t enclosing_cleanup_point_expr = NULL;
00074
00075 #include <ext/hash_map>
00076
00077 namespace {
00078
00079 using __gnu_cxx::hash_map;
00080
00081 struct ptrhash {
00082 size_t operator()(void* p) const { return reinterpret_cast<size_t>(p); }
00083 };
00084
00085 hash_map<gs_t, BOOL, ptrhash> referenced_by_whirl_map;
00086 }
00087
00088 BOOL& REFERENCED_BY_WHIRL(gs_t t) { return referenced_by_whirl_map[t]; }
00089
00090 struct operator_from_tree_t {
00091 gs_code_t tree_code;
00092 OPERATOR opr;
00093 } Operator_From_Tree [] = {
00094
00095
00096 DOT, OPERATOR_UNKNOWN,
00097
00098
00099 EMPTY, OPERATOR_UNKNOWN,
00100 CONS, OPERATOR_UNKNOWN,
00101
00102
00103
00104 IB_INT, OPERATOR_UNKNOWN,
00105 IB_UNSIGNED, OPERATOR_UNKNOWN,
00106 IB_LONG_LONG, OPERATOR_UNKNOWN,
00107 IB_LONG, OPERATOR_UNKNOWN,
00108 IB_LONG_DOUBLE, OPERATOR_UNKNOWN,
00109 IB_UNSIGNED_LONG, OPERATOR_UNKNOWN,
00110 IB_UNSIGNED_LONG_LONG, OPERATOR_UNKNOWN,
00111 IB_CHAR, OPERATOR_UNKNOWN,
00112 IB_STRING, OPERATOR_UNKNOWN,
00113 IB_FLOAT, OPERATOR_UNKNOWN,
00114 IB_DOUBLE, OPERATOR_UNKNOWN,
00115 IB_BOOL, OPERATOR_UNKNOWN,
00116 IB_BIT_VECTOR, OPERATOR_UNKNOWN,
00117
00118 GS_TCC, OPERATOR_UNKNOWN,
00119 GSBI, OPERATOR_UNKNOWN,
00120 GSBI_CLASS, OPERATOR_UNKNOWN,
00121
00122
00123
00124 GS_ABS_EXPR, OPR_ABS,
00125 GS_ADDR_EXPR, OPERATOR_UNKNOWN,
00126 GS_ALIGNOF_EXPR, OPERATOR_UNKNOWN,
00127 GS_ALIGN_INDIRECT_REF, OPERATOR_UNKNOWN,
00128 GS_ARRAY_RANGE_REF, OPERATOR_UNKNOWN,
00129 GS_ARRAY_REF, OPERATOR_UNKNOWN,
00130 GS_ARRAY_TYPE, OPERATOR_UNKNOWN,
00131 GS_ARROW_EXPR, OPERATOR_UNKNOWN,
00132 GS_ASM_EXPR, OPERATOR_UNKNOWN,
00133 GS_ASSIGN_STMT, OPERATOR_UNKNOWN,
00134 GS_BIND_EXPR, OPERATOR_UNKNOWN,
00135 GS_BIT_AND_EXPR, OPR_BAND,
00136 GS_BIT_FIELD_REF, OPERATOR_UNKNOWN,
00137 GS_BIT_IOR_EXPR, OPR_BIOR,
00138 GS_BIT_NOT_EXPR, OPR_BNOT,
00139 GS_BIT_XOR_EXPR, OPR_BXOR,
00140 GS_BLOCK, OPERATOR_UNKNOWN,
00141 GS_BOOLEAN_TYPE, OPERATOR_UNKNOWN,
00142 GS_BREAK_STMT, OPERATOR_UNKNOWN,
00143 GS_CALL_EXPR, OPERATOR_UNKNOWN,
00144 GS_CASE_LABEL_EXPR, OPERATOR_UNKNOWN,
00145 GS_CATCH_EXPR, OPERATOR_UNKNOWN,
00146 GS_CEIL_DIV_EXPR, OPR_DIV,
00147 GS_CEIL_MOD_EXPR, OPR_DIV,
00148 GS_CHAR_TYPE, OPERATOR_UNKNOWN,
00149 GS_CLEANUP, OPERATOR_UNKNOWN,
00150 GS_CLEANUP_POINT_EXPR, OPERATOR_UNKNOWN,
00151 GS_COMPLEX_CST, OPERATOR_UNKNOWN,
00152 GS_COMPLEX_EXPR, OPR_PAIR,
00153 GS_COMPLEX_TYPE, OPERATOR_UNKNOWN,
00154 GS_COMPONENT_REF, OPERATOR_UNKNOWN,
00155 GS_COMPOUND_EXPR, OPERATOR_UNKNOWN,
00156 GS_COMPOUND_LITERAL_EXPR, OPERATOR_UNKNOWN,
00157 GS_COND_EXPR, OPERATOR_UNKNOWN,
00158 GS_CONJ_EXPR, OPERATOR_UNKNOWN,
00159 GS_CONSTRUCTOR, OPERATOR_UNKNOWN,
00160 GS_CONST_DECL, OPERATOR_UNKNOWN,
00161 GS_CONTINUE_STMT, OPERATOR_UNKNOWN,
00162 GS_CONVERT_EXPR, OPERATOR_UNKNOWN,
00163 GS_DECL_EXPR, OPERATOR_UNKNOWN,
00164 GS_DO_STMT, OPERATOR_UNKNOWN,
00165 GS_EH_FILTER_EXPR, OPERATOR_UNKNOWN,
00166 GS_ENUMERAL_TYPE, OPERATOR_UNKNOWN,
00167 GS_EQ_EXPR, OPR_EQ,
00168 GS_ERROR_MARK, OPERATOR_UNKNOWN,
00169 GS_EXACT_DIV_EXPR, OPR_DIV,
00170 GS_EXC_PTR_EXPR, OPERATOR_UNKNOWN,
00171 GS_EXIT_EXPR, OPERATOR_UNKNOWN,
00172 GS_EXPR_STMT, OPERATOR_UNKNOWN,
00173 GS_FDESC_EXPR, OPERATOR_UNKNOWN,
00174 GS_FIELD_DECL, OPERATOR_UNKNOWN,
00175 GS_FILE_TYPE, OPERATOR_UNKNOWN,
00176 GS_FILTER_EXPR, OPERATOR_UNKNOWN,
00177 GS_FIX_CEIL_EXPR, OPERATOR_UNKNOWN,
00178 GS_FIX_FLOOR_EXPR, OPERATOR_UNKNOWN,
00179 GS_FIX_ROUND_EXPR, OPERATOR_UNKNOWN,
00180 GS_FIX_TRUNC_EXPR, OPERATOR_UNKNOWN,
00181 GS_FLOAT_EXPR, OPERATOR_UNKNOWN,
00182 GS_FLOOR_DIV_EXPR, OPERATOR_UNKNOWN,
00183 GS_FLOOR_MOD_EXPR, OPERATOR_UNKNOWN,
00184 GS_FOR_STMT, OPERATOR_UNKNOWN,
00185 GS_FUNCTION_DECL, OPERATOR_UNKNOWN,
00186 GS_FUNCTION_TYPE, OPERATOR_UNKNOWN,
00187 GS_GE_EXPR, OPR_GE,
00188 GS_GOTO_EXPR, OPERATOR_UNKNOWN,
00189 GS_GT_EXPR, OPR_GT,
00190 GS_IDENTIFIER_NODE, OPERATOR_UNKNOWN,
00191 GS_IMAGPART_EXPR, OPR_SECONDPART,
00192 GS_INDIRECT_REF, OPERATOR_UNKNOWN,
00193 GS_INIT_EXPR, OPERATOR_UNKNOWN,
00194 GS_INTEGER_CST, OPERATOR_UNKNOWN,
00195 GS_INTEGER_TYPE, OPERATOR_UNKNOWN,
00196 GS_LABEL_DECL, OPERATOR_UNKNOWN,
00197 GS_LABEL_EXPR, OPERATOR_UNKNOWN,
00198 GS_LANG_TYPE, OPERATOR_UNKNOWN,
00199 GS_LE_EXPR, OPR_LE,
00200 GS_LOOP_EXPR, OPERATOR_UNKNOWN,
00201 GS_LROTATE_EXPR, OPR_RROTATE,
00202 GS_LSHIFT_EXPR, OPR_SHL,
00203 GS_LTGT_EXPR, OPERATOR_UNKNOWN,
00204 GS_LT_EXPR, OPR_LT,
00205 GS_MAX_EXPR, OPR_MAX,
00206 GS_METHOD_TYPE, OPERATOR_UNKNOWN,
00207 GS_MINUS_EXPR, OPR_SUB,
00208 GS_MIN_EXPR, OPR_MIN,
00209 GS_MISALIGNED_INDIRECT_REF, OPERATOR_UNKNOWN,
00210 GS_MODIFY_EXPR, OPERATOR_UNKNOWN,
00211 GS_MULT_EXPR, OPR_MPY,
00212 GS_NAMESPACE_DECL, OPERATOR_UNKNOWN,
00213 GS_NEGATE_EXPR, OPR_NEG,
00214 GS_NE_EXPR, OPR_NE,
00215 GS_NON_LVALUE_EXPR, OPERATOR_UNKNOWN,
00216 GS_NOP_EXPR, OPERATOR_UNKNOWN,
00217 GS_OBJ_TYPE_REF, OPERATOR_UNKNOWN,
00218 GS_OFFSET_TYPE, OPERATOR_UNKNOWN,
00219 #ifdef FE_GNU_4_2_0
00220 GS_OMP_ATOMIC, OPERATOR_UNKNOWN,
00221 GS_OMP_CLAUSE, OPERATOR_UNKNOWN,
00222 GS_OMP_CRITICAL, OPERATOR_UNKNOWN,
00223 GS_OMP_FOR, OPERATOR_UNKNOWN,
00224 GS_OMP_MASTER, OPERATOR_UNKNOWN,
00225 GS_OMP_ORDERED, OPERATOR_UNKNOWN,
00226 GS_OMP_PARALLEL, OPERATOR_UNKNOWN,
00227 GS_OMP_SECTION, OPERATOR_UNKNOWN,
00228 GS_OMP_SECTIONS, OPERATOR_UNKNOWN,
00229 GS_OMP_SINGLE, OPERATOR_UNKNOWN,
00230 #endif
00231 GS_ORDERED_EXPR, OPERATOR_UNKNOWN,
00232 GS_PARM_DECL, OPERATOR_UNKNOWN,
00233 GS_PHI_NODE, OPERATOR_UNKNOWN,
00234 GS_PLACEHOLDER_EXPR, OPERATOR_UNKNOWN,
00235 GS_PLUS_EXPR, OPR_ADD,
00236 GS_POINTER_TYPE, OPERATOR_UNKNOWN,
00237 GS_POLYNOMIAL_CHREC, OPERATOR_UNKNOWN,
00238 GS_POSTDECREMENT_EXPR, OPR_SUB,
00239 GS_POSTINCREMENT_EXPR, OPR_ADD,
00240 GS_PREDECREMENT_EXPR, OPR_SUB,
00241 GS_PREINCREMENT_EXPR, OPR_ADD,
00242 GS_PROGRAM, OPERATOR_UNKNOWN,
00243 GS_QUAL_UNION_TYPE, OPERATOR_UNKNOWN,
00244 GS_RANGE_EXPR, OPERATOR_UNKNOWN,
00245 GS_RDIV_EXPR, OPR_DIV,
00246 GS_REALIGN_LOAD_EXPR, OPERATOR_UNKNOWN,
00247 GS_REALPART_EXPR, OPR_FIRSTPART,
00248 GS_REAL_CST, OPERATOR_UNKNOWN,
00249 GS_REAL_TYPE, OPERATOR_UNKNOWN,
00250 GS_RECORD_TYPE, OPERATOR_UNKNOWN,
00251 GS_REFERENCE_TYPE, OPERATOR_UNKNOWN,
00252 GS_RESULT_DECL, OPERATOR_UNKNOWN,
00253 GS_RESX_EXPR, OPERATOR_UNKNOWN,
00254 GS_RETURN_EXPR, OPERATOR_UNKNOWN,
00255 GS_ROUND_DIV_EXPR, OPERATOR_UNKNOWN,
00256 GS_ROUND_MOD_EXPR, OPERATOR_UNKNOWN,
00257 GS_RROTATE_EXPR, OPR_RROTATE,
00258 GS_RSHIFT_EXPR, OPERATOR_UNKNOWN,
00259 GS_SAVE_EXPR, OPERATOR_UNKNOWN,
00260 GS_SCEV_KNOWN, OPERATOR_UNKNOWN,
00261 GS_SCEV_NOT_KNOWN, OPERATOR_UNKNOWN,
00262 GS_SCOPE, OPERATOR_UNKNOWN,
00263 GS_SCOPE_STMT, OPERATOR_UNKNOWN,
00264 GS_SIZEOF_EXPR, OPERATOR_UNKNOWN,
00265 GS_SSA_NAME, OPERATOR_UNKNOWN,
00266 GS_STATEMENT_LIST, OPERATOR_UNKNOWN,
00267 GS_STMT_EXPR, OPERATOR_UNKNOWN,
00268 GS_STRING_CST, OPERATOR_UNKNOWN,
00269 GS_SWITCH_EXPR, OPERATOR_UNKNOWN,
00270 GS_SWITCH_STMT, OPERATOR_UNKNOWN,
00271 GS_TARGET_EXPR, OPERATOR_UNKNOWN,
00272 GS_TRANSLATION_UNIT_DECL, OPERATOR_UNKNOWN,
00273 GS_TREE_BINFO, OPERATOR_UNKNOWN,
00274 GS_TREE_LIST, OPERATOR_UNKNOWN,
00275 GS_TREE_VEC, OPERATOR_UNKNOWN,
00276 GS_TRUNC_DIV_EXPR, OPR_DIV,
00277 GS_TRUNC_MOD_EXPR, OPR_REM,
00278 GS_TRUTH_ANDIF_EXPR, OPR_CAND,
00279 GS_TRUTH_AND_EXPR, OPR_BAND,
00280 GS_TRUTH_NOT_EXPR, OPR_LNOT,
00281 GS_TRUTH_ORIF_EXPR, OPR_CIOR,
00282 GS_TRUTH_OR_EXPR, OPR_BIOR,
00283 GS_TRUTH_XOR_EXPR, OPR_BXOR,
00284 GS_TRY_BLOCK, OPERATOR_UNKNOWN,
00285 GS_TRY_CATCH_EXPR, OPERATOR_UNKNOWN,
00286 GS_TRY_FINALLY_EXPR, OPERATOR_UNKNOWN,
00287 GS_TYPE_DECL, OPERATOR_UNKNOWN,
00288 GS_UNEQ_EXPR, OPERATOR_UNKNOWN,
00289 GS_UNGE_EXPR, OPERATOR_UNKNOWN,
00290 GS_UNGT_EXPR, OPERATOR_UNKNOWN,
00291 GS_UNION_TYPE, OPERATOR_UNKNOWN,
00292 GS_UNLE_EXPR, OPERATOR_UNKNOWN,
00293 GS_UNLT_EXPR, OPERATOR_UNKNOWN,
00294 GS_UNORDERED_EXPR, OPERATOR_UNKNOWN,
00295 GS_VALUE_HANDLE, OPERATOR_UNKNOWN,
00296 GS_VAR_DECL, OPERATOR_UNKNOWN,
00297 GS_VA_ARG_EXPR, OPERATOR_UNKNOWN,
00298 GS_VECTOR_CST, OPERATOR_UNKNOWN,
00299 GS_VECTOR_TYPE, OPERATOR_UNKNOWN,
00300 GS_VEC_COND_EXPR, OPERATOR_UNKNOWN,
00301 GS_VIEW_CONVERT_EXPR, OPERATOR_UNKNOWN,
00302 GS_VOID_TYPE, OPERATOR_UNKNOWN,
00303 GS_WHILE_STMT, OPERATOR_UNKNOWN,
00304 GS_WITH_CLEANUP_EXPR, OPERATOR_UNKNOWN,
00305 GS_WITH_SIZE_EXPR, OPERATOR_UNKNOWN,
00306
00307 GS_AGGR_INIT_EXPR, OPERATOR_UNKNOWN,
00308 GS_BASELINK, OPERATOR_UNKNOWN,
00309 GS_BOUND_TEMPLATE_TEMPLATE_PARM, OPERATOR_UNKNOWN,
00310 GS_CAST_EXPR, OPERATOR_UNKNOWN,
00311 GS_CONST_CAST_EXPR, OPERATOR_UNKNOWN,
00312 GS_CLEANUP_STMT, OPERATOR_UNKNOWN,
00313 GS_CTOR_INITIALIZER, OPERATOR_UNKNOWN,
00314 GS_DELETE_EXPR, OPERATOR_UNKNOWN,
00315 GS_DEFAULT_ARG, OPERATOR_UNKNOWN,
00316 GS_DYNAMIC_CAST_EXPR, OPERATOR_UNKNOWN,
00317 GS_DOTSTAR_EXPR, OPERATOR_UNKNOWN,
00318 GS_EMPTY_CLASS_EXPR, OPERATOR_UNKNOWN,
00319 GS_EH_SPEC_BLOCK, OPERATOR_UNKNOWN,
00320 GS_HANDLER, OPERATOR_UNKNOWN,
00321 GS_IF_STMT, OPERATOR_UNKNOWN,
00322 GS_MEMBER_REF, OPERATOR_UNKNOWN,
00323 GS_MODOP_EXPR, OPERATOR_UNKNOWN,
00324 GS_MUST_NOT_THROW_EXPR, OPERATOR_UNKNOWN,
00325 GS_NEW_EXPR, OPERATOR_UNKNOWN,
00326 GS_NON_DEPENDENT_EXPR, OPERATOR_UNKNOWN,
00327 GS_OFFSET_REF, OPERATOR_UNKNOWN,
00328 GS_OFFSETOF_EXPR, OPERATOR_UNKNOWN,
00329 GS_OVERLOAD, OPERATOR_UNKNOWN,
00330 GS_PTRMEM_CST, OPERATOR_UNKNOWN,
00331 GS_PSEUDO_DTOR_EXPR, OPERATOR_UNKNOWN,
00332 GS_REINTERPRET_CAST_EXPR, OPERATOR_UNKNOWN,
00333 GS_SCOPE_REF, OPERATOR_UNKNOWN,
00334 GS_STATIC_CAST_EXPR, OPERATOR_UNKNOWN,
00335 GS_TAG_DEFN, OPERATOR_UNKNOWN,
00336 GS_TEMPLATE_DECL, OPERATOR_UNKNOWN,
00337 GS_TEMPLATE_ID_EXPR, OPERATOR_UNKNOWN,
00338 GS_TEMPLATE_PARM_INDEX, OPERATOR_UNKNOWN,
00339 GS_TEMPLATE_TYPE_PARM, OPERATOR_UNKNOWN,
00340 GS_THROW_EXPR, OPERATOR_UNKNOWN,
00341 GS_TINST_LEVEL, OPERATOR_UNKNOWN,
00342 GS_TYPEOF_TYPE, OPERATOR_UNKNOWN,
00343 GS_TYPENAME_TYPE, OPERATOR_UNKNOWN,
00344 GS_TYPE_EXPR, OPERATOR_UNKNOWN,
00345 GS_TYPEID_EXPR, OPERATOR_UNKNOWN,
00346 GS_USING_DECL, OPERATOR_UNKNOWN,
00347 GS_USING_STMT, OPERATOR_UNKNOWN,
00348 GS_UNBOUND_CLASS_TEMPLATE, OPERATOR_UNKNOWN,
00349 GS_VEC_DELETE_EXPR, OPERATOR_UNKNOWN,
00350 GS_VEC_NEW_EXPR, OPERATOR_UNKNOWN,
00351 GS_TEMPLATE_TEMPLATE_PARM, OPERATOR_UNKNOWN,
00352 };
00353
00354 #ifdef FE_GNU_4_2_0
00355 extern OPERATOR
00356 Operator_From_Tree_node (gs_code_t code) {
00357 return Operator_From_Tree[code].opr;
00358 }
00359 #endif
00360
00361 #ifdef TARG_SL
00362
00363
00364
00365 typedef enum EXTEND_PARM_POS {
00366 P0,
00367 P1,
00368 P2,
00369 P3,
00370 P4,
00371 P0_P2,
00372 P1_P3,
00373 P2_P4,
00374 P3_P4,
00375 }EXTEND_PARM_POS;
00376
00377 typedef struct intrinsicop_attr_extended {
00378 INTRINSIC id;
00379 BOOL need_extend;
00380 int extend_kid;
00381 EXTEND_PARM_POS pos;
00382 INTRINSIC aux_id;
00383 } INTRN_ATTR_EXTEND;
00384
00385 #define INTRN_EATTR_LAST 13
00386 static INTRN_ATTR_EXTEND intrn_eattr[INTRN_EATTR_LAST] = {
00387 INTRN_C3DMAC_A, TRUE, 2, P2_P4, INTRN_C3_PTR,
00388 INTRN_C3DMULA_A, TRUE, 1, P2, INTRN_C3_PTR,
00389 INTRN_C3LD, TRUE, 1, P0, INTRN_C3_PTR,
00390 INTRN_C3ST, TRUE, 1, P1, INTRN_C3_PTR,
00391 INTRN_C3MAC_A, TRUE, 2, P2_P4, INTRN_C3_PTR,
00392 INTRN_C3MAC_AR, TRUE, 1, P3, INTRN_C3_PTR,
00393 INTRN_C3MULA_A, TRUE, 1, P2_P4, INTRN_C3_PTR,
00394 INTRN_C3MULA_AR, TRUE, 1, P3, INTRN_C3_PTR,
00395 INTRN_C3SAADD_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00396 INTRN_C3SAADDH_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00397 INTRN_C3SADDA_A, TRUE, 1, P2, INTRN_C3_PTR,
00398 INTRN_C3SAMULH_A, TRUE, 2, P0_P2, INTRN_C3_PTR,
00399 INTRN_C3_SET_CIRCBUF, FALSE, 2, P3_P4, INTRN_C3_PTR,
00400 };
00401
00402 static BOOL intrinsic_op_need_extend (INTRINSIC id) {
00403 INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00404 int i=0;
00405 while (p && (i<INTRN_EATTR_LAST)) {
00406 if (p->id == id ) {
00407 return p->need_extend;
00408 }
00409 i++;
00410 p++;
00411 }
00412 return FALSE;
00413 }
00414
00415 static BOOL intrinsic_need_deref (INTRINSIC id) {
00416 INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00417 int i=0;
00418 while (p && (i<INTRN_EATTR_LAST)) {
00419 if (p->id == id ) {
00420 return TRUE;
00421 }
00422 i++;
00423 p++;
00424 }
00425 return FALSE;
00426 }
00427
00428 static INTRN_ATTR_EXTEND *Get_intrinsic_op_Eattr (INTRINSIC id) {
00429 INTRN_ATTR_EXTEND *p = &intrn_eattr[0];
00430 int i =0;
00431 while (p && (i<INTRN_EATTR_LAST)) {
00432 if (p->id == id ) {
00433 return p;
00434 }
00435 p++;
00436 i++;
00437 }
00438 return NULL;
00439 }
00440
00441 static void WN_Set_Deref_If_Needed(WN *wn) {
00442 INTRINSIC intrn=WN_intrinsic(wn);
00443 if (intrinsic_need_deref(intrn)) {
00444 INTRN_ATTR_EXTEND *p=Get_intrinsic_op_Eattr(intrn);
00445
00446 switch (p->pos) {
00447 case P0:
00448 WN_Set_Parm_Dereference(WN_kid(wn,0)); break;
00449 case P1:
00450 WN_Set_Parm_Dereference(WN_kid(wn,1)); break;
00451 case P2:
00452 WN_Set_Parm_Dereference(WN_kid(wn,2)); break;
00453 case P3:
00454 WN_Set_Parm_Dereference(WN_kid(wn,3)); break;
00455 case P4:
00456 WN_Set_Parm_Dereference(WN_kid(wn,4)); break;
00457 case P0_P2:
00458 WN_Set_Parm_Dereference(WN_kid(wn,0)); WN_Set_Parm_Dereference(WN_kid(wn,2)); break;
00459 case P1_P3:
00460 WN_Set_Parm_Dereference(WN_kid(wn,1)); WN_Set_Parm_Dereference(WN_kid(wn,3)); break;
00461 case P2_P4:
00462 WN_Set_Parm_Dereference(WN_kid(wn,2)); WN_Set_Parm_Dereference(WN_kid(wn,4)); break;
00463 case P3_P4:
00464 WN_Set_Parm_Dereference(WN_kid(wn,3)); WN_Set_Parm_Dereference(WN_kid(wn,4)); break;
00465 default:
00466 Is_True(0, ("intrinsic has no extended attribution"));
00467 }
00468 }
00469 return;
00470 }
00471
00472 static int intrinsic_op_extend_kid (int index) {
00473 return intrn_eattr[index].extend_kid;
00474 }
00475
00476 static EXTEND_PARM_POS intrinsic_op_parm_pos (int index) {
00477 return intrn_eattr[index].pos;
00478 }
00479
00480 BOOL WN_Need_Append_Intrinsic(WN *rhs) {
00481 OPERATOR opr=WN_operator(rhs);
00482 if (opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL) {
00483 INTRINSIC inid = WN_intrinsic(rhs);
00484 if (intrinsic_op_need_extend(inid)) {
00485 return TRUE;
00486 }
00487 } else if (opr == OPR_CVTL) {
00488 WN *tmp = WN_kid0(rhs);
00489 OPERATOR kid_opr=WN_operator(tmp);
00490 if (kid_opr == OPR_INTRINSIC_OP || kid_opr == OPR_INTRINSIC_CALL) {
00491 INTRINSIC inid = WN_intrinsic(tmp);
00492 if (intrinsic_op_need_extend(inid)) {
00493 return TRUE;
00494 }
00495 }
00496 }
00497 return FALSE;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507 void WFE_Stmt_Append_Extend_Intrinsic(WN *wn, WN *master_variable, SRCPOS src) {
00508 WN *kid1s[5];
00509 WN *op1;
00510 int aux_kid = -1;
00511 int extend_num = -1;
00512 int pos[5]= {-1, -1, -1, -1, -1};
00513 WN *tmp_wn;
00514 INTRN_ATTR_EXTEND *p;
00515
00516 if (WN_kid0(master_variable) && WN_operator(master_variable) == OPR_CVT) {
00517 master_variable = WN_kid0(master_variable);
00518 }
00519 if (WN_operator(WN_kid0(wn)) == OPR_INTRINSIC_OP) {
00520 p = Get_intrinsic_op_Eattr(WN_intrinsic(WN_kid0(wn)));
00521 tmp_wn = wn;
00522 } else if (WN_operator(WN_kid0(wn)) == OPR_CVTL && WN_operator(WN_kid0(WN_kid0(wn))) == OPR_INTRINSIC_OP ) {
00523 p = Get_intrinsic_op_Eattr(WN_intrinsic(WN_kid0(WN_kid0(wn))));
00524 tmp_wn = WN_kid0(wn);
00525 } else if (WN_operator(wn) == OPR_INTRINSIC_CALL) {
00526 p = Get_intrinsic_op_Eattr(WN_intrinsic(wn));
00527 tmp_wn = wn;
00528 }
00529 if (p) {
00530 extend_num = p->extend_kid;
00531 switch (p->aux_id) {
00532 case INTRN_C3_PTR: aux_kid = 2; break;
00533 default:
00534 Is_True(0, ("unsupport internal intrinsic op"));
00535 }
00536 switch (p->pos) {
00537 case P0:
00538 pos[0] = 0; break;
00539 case P1:
00540 pos[0] = 1; break;
00541 case P2:
00542 pos[0] = 2; break;
00543 case P3:
00544 pos[0] = 3; break;
00545 case P0_P2:
00546 pos[0] = 0; pos[1] = 2; break;
00547 case P1_P3:
00548 pos[0] = 1; pos[1] = 3; break;
00549 case P2_P4:
00550 pos[0] = 2; pos[1] = 4; break;
00551 case P3_P4:
00552 pos[0] = 3; pos[1] = 4; break;
00553 default:
00554 Is_True(0, ("intrinsic has no extended attribution"));
00555 }
00556 } else {
00557 Is_True(0, ("intrinsic has no extended attribution"));
00558 }
00559 if (WN_operator(master_variable) == OPR_INTCONST) {
00560
00561 Is_True(WN_opcode(master_variable) == OPC_I4INTCONST,("should be 32-bit immediate"));
00562 master_variable = WN_CreateParm(MTYPE_I4, master_variable, Be_Type_Tbl(MTYPE_I4), WN_PARM_BY_VALUE);
00563 } else {
00564 TY_IDX ti2 = WN_ty(master_variable);
00565 TYPE_ID tm2 = TY_mtype(ti2);
00566 master_variable = WN_CreateParm (Mtype_comparison (tm2), master_variable,
00567 ti2, WN_PARM_BY_VALUE);
00568 }
00569 kid1s[0]= master_variable;
00570 for (int i =0; i < extend_num; i++) {
00571 WN *op1;
00572 if (WN_operator(wn) == OPR_INTRINSIC_CALL) {
00573 op1 = WN_kid0(WN_kid(tmp_wn, pos[i]));
00574 } else {
00575 op1 = WN_kid0(WN_kid(WN_kid0(tmp_wn), pos[i]));
00576 }
00577 ST *st1;
00578 if (WN_has_sym(op1)) {
00579 st1 = WN_st(op1);
00580 } else {
00581
00582 continue;
00583 }
00584 TY_IDX ti1 = WN_ty(op1);
00585 TYPE_ID tm1 = TY_mtype(ti1);
00586 op1 = WN_CreateParm (Mtype_comparison (tm1), op1,
00587 ti1, WN_PARM_BY_VALUE);
00588 kid1s[1]= op1;
00589 WN *app1 = WN_Create_Intrinsic(OPR_INTRINSIC_OP,TY_mtype(ST_type(st1)), MTYPE_V, p->aux_id, aux_kid, kid1s);
00590 WN *stmt1 = WN_Stid(TY_mtype(ST_type(st1)), ST_ofst(st1), st1, ST_type(st1), app1, 0);
00591 WGEN_Stmt_Append(stmt1, src);
00592 }
00593 }
00594 #endif
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static bool WGEN_Call_Returns_Ptr_To_Member_Func (gs_t exp);
00615
00616 static WN *WGEN_Expand_Ptr_To_Member_Func_Call_Expr (gs_t exp,
00617 TY_IDX nop_ty_idx, TYPE_ID rtype, TYPE_ID desc,
00618 WN_OFFSET offset = 0, UINT field_id = 0);
00619
00620
00621
00622 void
00623 WGEN_Convert_To_Host_Order (long *buf)
00624 {
00625 if (!Same_Byte_Sex)
00626 {
00627 int t = buf[0];
00628 buf[0] = buf[1];
00629 buf[1] = t;
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 static void
00645 WGEN_add_guard_var (gs_t guard_var, WN *value_wn, BOOL need_comma = TRUE)
00646 {
00647 WN *stid, *comma;
00648
00649
00650 WN *zero_wn = WN_Intconst(MTYPE_I4, 0);
00651 stid = WN_Stid(MTYPE_I4, 0, Get_ST(guard_var), MTYPE_To_TY(MTYPE_I4),
00652 zero_wn, 0);
00653 WGEN_Stmt_Append(stid, Get_Srcpos());
00654
00655
00656
00657 WN *one_wn = WN_Intconst(MTYPE_I4, 1);
00658 stid = WN_Stid(MTYPE_I4, 0, Get_ST(guard_var), MTYPE_To_TY(MTYPE_I4),
00659 one_wn, 0);
00660 if (need_comma) {
00661 if (WN_operator(value_wn) == OPR_COMMA) {
00662 comma = value_wn;
00663 } else if (WN_operator(WN_kid0(value_wn)) == OPR_COMMA) {
00664 comma = WN_kid0(value_wn);
00665 } else {
00666
00667 WN *wn0 = WN_CreateBlock();
00668 WN *wn1 = WN_kid0(value_wn);
00669 WN_Set_Linenum (wn0, Get_Srcpos());
00670 comma = WN_CreateComma (OPR_COMMA, WN_rtype(wn1), MTYPE_V, wn0, wn1);
00671 WN_kid0(value_wn) = comma;
00672 }
00673 WN *wn = WN_kid0(comma);
00674 FmtAssert(WN_operator(wn) == OPR_BLOCK,
00675 ("WGEN_add_guard_var: unexpected WN operator"));
00676 WN_INSERT_BlockFirst(wn, stid);
00677 }
00678 else WN_INSERT_BlockFirst(value_wn, stid);
00679 }
00680
00681
00682
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
00700
00701
00702 inline UINT64 Parameter_Size(UINT64 sz)
00703 {
00704 # if WORDS_BIG_ENDIAN
00705 return sz;
00706 # else
00707 INT UNITS_PER_WORD = TARGET_64BIT ? 8 : 4;
00708 return (sz + UNITS_PER_WORD - 1) & ~(UNITS_PER_WORD - 1);
00709 # endif
00710 }
00711
00712 TYPE_ID
00713 Widen_Mtype (TYPE_ID t)
00714 {
00715 if (MTYPE_is_m(t))
00716 return t;
00717 if (MTYPE_is_void(t) || t == MTYPE_BS) {
00718 Fail_FmtAssertion ("Widen_Mtype: for MTYPE_V or MTYPE_BS");
00719 return t;
00720 }
00721 if (MTYPE_byte_size(t) >= 4)
00722 return t;
00723 return Mtype_TransferSize(MTYPE_I4, t);
00724 }
00725
00726
00727
00728 void
00729 WGEN_Set_ST_Addr_Saved (WN *wn)
00730 {
00731 OPERATOR Operator;
00732 ST *st;
00733
00734 Operator = WN_operator (wn);
00735
00736 switch ( Operator ) {
00737
00738 case OPR_LDA:
00739 case OPR_LDMA:
00740
00741 st = WN_st (wn);
00742
00743 if (ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_FUNC)
00744 Set_ST_addr_saved (st);
00745 break;
00746
00747 case OPR_ARRAY:
00748
00749 WGEN_Set_ST_Addr_Saved (WN_kid0 (wn));
00750 break;
00751
00752 case OPR_LDID:
00753
00754 st = WN_st (wn);
00755 if (ST_pt_to_unique_mem (st))
00756 Clear_ST_pt_to_unique_mem (st);
00757 break;
00758
00759 case OPR_CONST:
00760 case OPR_ILOAD:
00761 case OPR_MLOAD:
00762 case OPR_INTCONST:
00763 case OPR_INTRINSIC_OP:
00764 case OPR_CALL:
00765 case OPR_EQ:
00766 case OPR_NE:
00767 case OPR_GT:
00768 case OPR_GE:
00769 case OPR_LT:
00770 case OPR_LE:
00771 case OPR_ALLOCA:
00772 break;
00773
00774 case OPR_EVAL:
00775 case OPR_TAS:
00776 case OPR_CVT:
00777 case OPR_CVTL:
00778 case OPR_NEG:
00779 case OPR_ABS:
00780 case OPR_SQRT:
00781 case OPR_REALPART:
00782 case OPR_IMAGPART:
00783 case OPR_PAREN:
00784 case OPR_RND:
00785 case OPR_TRUNC:
00786 case OPR_CEIL:
00787 case OPR_FLOOR:
00788 case OPR_BNOT:
00789 case OPR_LNOT:
00790 case OPR_LOWPART:
00791 case OPR_HIGHPART:
00792 case OPR_MINPART:
00793 case OPR_MAXPART:
00794 case OPR_RECIP:
00795 case OPR_RSQRT:
00796 case OPR_PARM:
00797 case OPR_EXTRACT_BITS:
00798
00799 WGEN_Set_ST_Addr_Saved (WN_kid0(wn));
00800 break;
00801
00802 case OPR_CSELECT:
00803
00804 WGEN_Set_ST_Addr_Saved (WN_kid1(wn));
00805 WGEN_Set_ST_Addr_Saved (WN_kid2(wn));
00806 break;
00807
00808 case OPR_SELECT:
00809 case OPR_ADD:
00810 case OPR_SUB:
00811 case OPR_MPY:
00812 case OPR_DIV:
00813 case OPR_MOD:
00814 case OPR_REM:
00815 case OPR_DIVREM:
00816 case OPR_MAX:
00817 case OPR_MIN:
00818 case OPR_MINMAX:
00819 case OPR_BAND:
00820 case OPR_BIOR:
00821 case OPR_BXOR:
00822 case OPR_BNOR:
00823 case OPR_LAND:
00824 case OPR_LIOR:
00825 case OPR_SHL:
00826 case OPR_ASHR:
00827 case OPR_LSHR:
00828 case OPR_COMPLEX:
00829 case OPR_HIGHMPY:
00830 case OPR_RROTATE:
00831 case OPR_COMPOSE_BITS:
00832
00833 WGEN_Set_ST_Addr_Saved (WN_kid0(wn));
00834 WGEN_Set_ST_Addr_Saved (WN_kid1(wn));
00835 break;
00836
00837 case OPR_CAND:
00838 case OPR_CIOR:
00839
00840 break;
00841
00842 case OPR_COMMA:
00843
00844 WGEN_Set_ST_Addr_Saved (WN_kid1(wn));
00845 break;
00846
00847 case OPR_RCOMMA:
00848
00849 WGEN_Set_ST_Addr_Saved (WN_kid0(wn));
00850 break;
00851
00852 default:
00853
00854 DevWarn ("WGEN_Set_ST_Addr_Saved not implemented");
00855 }
00856 }
00857
00858
00859 typedef struct wgen_save_expr_t {
00860 gs_t exp;
00861 ST *st;
00862 #ifdef KEY
00863 INT32 level;
00864 #endif
00865 } WGEN_SAVE_EXPR;
00866
00867 WGEN_SAVE_EXPR *wgen_save_expr_stack = NULL;
00868 INT32 wgen_save_expr_stack_last = -1;
00869 INT32 wgen_save_expr_stack_max = 0;
00870
00871 #ifdef KEY
00872 INT32 wgen_save_expr_level;
00873 INT32 wgen_last_save_expr_level;
00874 #endif
00875
00876 static WN*
00877 WGEN_Save_Expr (gs_t save_exp,
00878 bool need_result,
00879 TY_IDX nop_ty_idx,
00880 TY_IDX component_ty_idx,
00881 INT64 component_offset,
00882 UINT16 field_id)
00883 {
00884 INT32 i;
00885 gs_t exp = gs_tree_operand (save_exp, 0);
00886 TY_IDX ty_idx = Get_TY (gs_tree_type (exp));
00887 TYPE_ID mtype = TY_mtype (ty_idx);
00888 ST *st;
00889 WN *wn;
00890 bool found = false;
00891
00892 for (i = wgen_save_expr_stack_last; i >= 0; i--) {
00893 #ifndef KEY
00894 if (wgen_save_expr_stack [i].exp == exp) {
00895 #else
00896 if (wgen_save_expr_stack [i].exp == save_exp &&
00897 wgen_save_expr_stack [i].level == wgen_save_expr_level) {
00898 #endif
00899 st = wgen_save_expr_stack [i].st;
00900 FmtAssert (st != 0,
00901 ("WGEN_Save_Expr: st not yet assigned"));
00902 found = true;
00903 break;
00904 }
00905 }
00906
00907 if (!found) {
00908 i = ++wgen_save_expr_stack_last;
00909 if (i == wgen_save_expr_stack_max) {
00910 if (wgen_save_expr_stack == NULL) {
00911 wgen_save_expr_stack_max = 32;
00912 wgen_save_expr_stack =
00913 (WGEN_SAVE_EXPR *) malloc (wgen_save_expr_stack_max *
00914 sizeof (WGEN_SAVE_EXPR));
00915 }
00916 else {
00917 wgen_save_expr_stack_max = wgen_save_expr_stack_max +
00918 (wgen_save_expr_stack_max >> 1);
00919 wgen_save_expr_stack =
00920 (WGEN_SAVE_EXPR *) realloc (wgen_save_expr_stack,
00921 wgen_save_expr_stack_max *
00922 sizeof (WGEN_SAVE_EXPR));
00923 }
00924 }
00925 #ifndef KEY
00926 wgen_save_expr_stack [i].exp = exp;
00927 #else
00928 wgen_save_expr_stack [i].exp = save_exp;
00929 wgen_save_expr_stack [i].level = wgen_save_expr_level;
00930 #endif
00931 wgen_save_expr_stack [i].st = 0;
00932 #ifdef KEY
00933
00934
00935
00936 if (WGEN_Call_Returns_Ptr_To_Member_Func(exp)) {
00937 TYPE_ID desc = TY_mtype(Get_TY(gs_tree_type(exp)));
00938 wn = WGEN_Expand_Ptr_To_Member_Func_Call_Expr(exp, nop_ty_idx,
00939 Widen_Mtype(desc), desc);
00940 } else
00941 #endif
00942 wn = WGEN_Expand_Expr (exp);
00943
00944 st = Gen_Temp_Symbol (ty_idx, "__save_expr");
00945 #ifdef FE_GNU_4_2_0
00946 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
00947 #endif
00948 WGEN_Set_ST_Addr_Saved (wn);
00949 wn = WN_Stid (mtype, 0, st, ty_idx, wn);
00950 WGEN_Stmt_Append (wn, Get_Srcpos());
00951 wgen_save_expr_stack [i].st = st;
00952 }
00953
00954 if (component_ty_idx == 0)
00955 wn = WN_Ldid (mtype, 0, st, ty_idx);
00956 else {
00957 TYPE_ID desc = TY_mtype(component_ty_idx);
00958 TYPE_ID rtype = Widen_Mtype(desc);
00959 wn = WN_CreateLdid(OPR_LDID, rtype, desc, component_offset, st,
00960 field_id? ty_idx : component_ty_idx, field_id);
00961 }
00962 return wn;
00963 }
00964
00965 static WN *
00966 WGEN_Expand_Math_Errno_Sqrt(gs_t exp, TY_IDX ty_idx, TYPE_ID ret_mtype)
00967 {
00968 WN *arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
00969 ST *arg_st = Gen_Temp_Symbol(ty_idx, "__sqrt_arg");
00970 #ifdef FE_GNU_4_2_0
00971 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_st);
00972 #endif
00973 WN *stmt = WN_Stid(ret_mtype, 0, arg_st, ty_idx, arg_wn);
00974 WGEN_Stmt_Append(stmt, Get_Srcpos());
00975
00976 arg_wn = WN_Ldid(ret_mtype, 0, arg_st, ty_idx);
00977 WN *wn = WN_CreateExp1 (OPR_SQRT, ret_mtype, MTYPE_V, arg_wn);
00978
00979 ST *res_st = Gen_Temp_Symbol(ty_idx, "__save_sqrt");
00980 #ifdef FE_GNU_4_2_0
00981 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, res_st);
00982 #endif
00983 stmt = WN_Stid(ret_mtype, 0, res_st, ty_idx, wn);
00984 WGEN_Stmt_Append(stmt, Get_Srcpos());
00985
00986 wn = WN_Ldid(ret_mtype, 0, res_st, ty_idx);
00987 WN *wn0 = WN_Ldid(ret_mtype, 0, res_st, ty_idx);
00988 WN *then_block = WN_CreateBlock();
00989 WN *else_block = WN_CreateBlock();
00990 WN *if_stmt = WN_CreateIf( WN_Relational(OPR_NE, ret_mtype, wn, wn0),
00991 then_block, else_block);
00992 WGEN_Stmt_Append(if_stmt, Get_Srcpos());
00993
00994 WGEN_Stmt_Push (then_block, wgen_stmk_if_then, Get_Srcpos());
00995
00996
00997 gs_t arg0 = gs_tree_operand(exp, 0);
00998 WN *call_wn = WN_Create(OPR_CALL, ret_mtype, MTYPE_V, 1);
00999 ST *st2 = DECL_ST2(gs_tree_operand(arg0, 0));
01000 if (Opt_Level > 0 && st2) {
01001 WN_st_idx (call_wn) = ST_st_idx (st2);
01002 }
01003 else {
01004 ST *st = Get_ST (gs_tree_operand (arg0, 0));
01005 WN_st_idx (call_wn) = ST_st_idx (st);
01006 }
01007 arg_wn = WN_Ldid(ret_mtype, 0, arg_st, ty_idx);
01008 arg_wn = WN_CreateParm(ret_mtype, arg_wn, ty_idx, WN_PARM_BY_VALUE);
01009 WN_kid(call_wn, 0) = arg_wn;
01010 WGEN_Stmt_Append(call_wn, Get_Srcpos());
01011
01012 wn = WN_Ldid (ret_mtype, -1, Return_Val_Preg, ty_idx);
01013 stmt = WN_Stid(ret_mtype, 0, res_st, ty_idx, wn);
01014 WGEN_Stmt_Append(stmt, Get_Srcpos());
01015
01016 WGEN_Stmt_Pop(wgen_stmk_if_then);
01017
01018 return WN_Ldid(ret_mtype, 0, res_st, ty_idx);
01019 }
01020
01021
01022
01023
01024
01025
01026 static WN *
01027 WGEN_Array_Expr(gs_t exp,
01028 TY_IDX *ty_idx,
01029 TY_IDX component_ty_idx,
01030 INT64 component_offset,
01031 UINT32 field_id)
01032 {
01033 WN *wn;
01034 gs_code_t code = gs_tree_code (exp);
01035 if (code == GS_COMPONENT_REF) {
01036 TY_IDX ty_idx0;
01037 gs_t arg0 = gs_tree_operand(exp, 0);
01038 gs_t arg1 = gs_tree_operand(exp, 1);
01039 if (component_ty_idx == 0)
01040 ty_idx0 = Get_TY(gs_tree_type(exp));
01041 else ty_idx0 = component_ty_idx;
01042 #ifdef KEY // bug 10728
01043 if (gs_tree_this_volatile(exp))
01044 Set_TY_is_volatile(ty_idx0);
01045 #endif
01046 Is_True(! gs_decl_bit_field(arg1),
01047 ("WGEN_Array_Expr: address arithmetic cannot use bitfield addresses"));
01048 INT64 ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
01049 gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
01050 / BITSPERBYTE;
01051 #ifdef KEY
01052
01053
01054
01055
01056 if ( gs_tree_code(arg0) == GS_MODIFY_EXPR ) {
01057 WGEN_Expand_Expr(arg0);
01058 gs_t lhs = gs_tree_operand(arg0, 0);
01059 Is_True( lhs != NULL && gs_tree_code(lhs) == GS_VAR_DECL,
01060 ("Unsupported lhs for `(p=q).x[n]'"));
01061 arg0 = lhs;
01062 }
01063 #endif
01064
01065 #ifdef KEY // bug 9725: If the field is an array of struct, it is considered
01066
01067 return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
01068 DECL_FIELD_ID(arg1));
01069 #else
01070 return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
01071 field_id + DECL_FIELD_ID(arg1));
01072 #endif
01073 }
01074 #ifdef KEY
01075 else if (code == GS_VAR_DECL && gs_decl_value_expr(exp)) {
01076 return WGEN_Array_Expr(gs_decl_value_expr(exp),
01077 ty_idx, component_ty_idx, component_offset,
01078 field_id);
01079 }
01080 #endif
01081 else if (code == GS_VAR_DECL || code == GS_PARM_DECL
01082 #ifdef KEY
01083 || code == GS_RESULT_DECL
01084 #endif
01085 ) {
01086 ST *st = Get_ST (exp);
01087 ST *base_st = ST_base (st);
01088
01089
01090 if (st != base_st) {
01091 FmtAssert (component_ty_idx == 0,
01092 ("Variable Length Arrays within struct not currently implemented"));
01093 wn = WN_Ldid (Pointer_Mtype, 0, base_st, ST_type (base_st));
01094 }
01095 else
01096 wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01097 if (component_ty_idx == 0)
01098 *ty_idx = ST_type(st);
01099 else {
01100 *ty_idx = component_ty_idx;
01101 if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01102 Set_TY_align(*ty_idx, TY_align(ST_type(st)));
01103 }
01104 Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01105 ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01106 return wn;
01107 }
01108 else if (code == GS_CONSTRUCTOR) {
01109 ST *st = WGEN_Generate_Temp_For_Initialized_Aggregate (exp, "");
01110 wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01111 if (component_ty_idx == 0)
01112 *ty_idx = ST_type(st);
01113 else *ty_idx = component_ty_idx;
01114 Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01115 ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01116 return wn;
01117 }
01118 else if (code == GS_STRING_CST) {
01119 wn = WGEN_Expand_Expr(exp);
01120 *ty_idx = ST_type (TREE_STRING_ST (exp));
01121 return wn;
01122 }
01123 else if (code == GS_INDIRECT_REF) {
01124 wn = WGEN_Expand_Expr(gs_tree_operand (exp, 0));
01125 if (component_ty_idx == 0)
01126 *ty_idx = Get_TY (gs_tree_type(exp));
01127 else {
01128 *ty_idx = component_ty_idx;
01129 INT node_align = gs_type_align(gs_tree_type(exp)) / BITSPERBYTE;
01130 if (node_align < TY_align(component_ty_idx))
01131 Set_TY_align(*ty_idx, node_align);
01132 }
01133 if (component_offset != 0) {
01134 WN *wn0 = WN_Intconst(MTYPE_I4, component_offset);
01135 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn, wn0);
01136 }
01137 return wn;
01138 }
01139 else if (code == GS_CALL_EXPR) {
01140 wn = WGEN_Expand_Expr(exp);
01141 FmtAssert (WN_opcode (wn) == OPC_MCOMMA,
01142 ("opcode other than OPC_MCOMMA for call underneath ARRAY_REF"));
01143 WGEN_Stmt_Append (WN_kid0 (wn), Get_Srcpos ());
01144 ST *st = WN_st (WN_kid1 (wn));
01145 WN_Delete (WN_kid1 (wn));
01146 WN_Delete (wn);
01147 wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01148 if (component_ty_idx == 0)
01149 *ty_idx = ST_type(st);
01150 else {
01151 *ty_idx = component_ty_idx;
01152 if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01153 Set_TY_align(*ty_idx, TY_align(ST_type(st)));
01154 }
01155 Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01156 ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01157 return wn;
01158 }
01159 else if (code == GS_ARRAY_REF) {
01160 WN *wn0, *wn1, *wn2;
01161 TY_IDX ty_idx0;
01162 #ifdef KEY // Bug 5831.
01163 wn0 = WGEN_Array_Expr(gs_tree_operand (exp, 0), &ty_idx0, 0,
01164 component_offset, field_id);
01165 #else
01166 wn0 = WGEN_Array_Expr(gs_tree_operand (exp, 0), &ty_idx0, component_ty_idx,
01167 component_offset, field_id);
01168 #endif
01169 Is_True(TY_kind(ty_idx0) == KIND_ARRAY,
01170 ("WGEN_Array_Expr: arg 0 of ARRAY_REF not of type KIND_ARRAY"));
01171 ARB_HANDLE arb = TY_arb(ty_idx0);
01172 if (ARB_dimension(arb) == 1 &&
01173 ARB_first_dimen(arb) && ARB_last_dimen(arb) &&
01174 ARB_const_lbnd(arb)) {
01175 if (ARB_const_ubnd(arb))
01176 wn1 = WN_Intconst(MTYPE_I4, ARB_ubnd_val(arb) - ARB_lbnd_val(arb) + 1);
01177 #ifdef KEY
01178
01179 else if (ARB_ubnd_var(arb)) {
01180 ST *ubnd_st = &St_Table[ARB_ubnd_var(arb)];
01181 wn1 = WN_Binary(OPR_SUB, MTYPE_I4,
01182 WN_Ldid(MTYPE_I4, 0, ubnd_st, ST_type(ubnd_st)),
01183 WN_Intconst(MTYPE_I4, ARB_lbnd_val(arb) - 1));
01184 }
01185 #endif
01186 else
01187 wn1 = WN_Intconst(MTYPE_I4, 0);
01188 wn2 = WGEN_Expand_Expr (gs_tree_operand (exp, 1));
01189 #ifdef TARG_X8664 // bug 11705
01190 if (WN_operator(wn2) == OPR_SUB)
01191 WN_set_rtype(wn2, Mtype_TransferSign(MTYPE_I4, WN_rtype(wn2)));
01192 #endif
01193 #ifdef KEY // bug 14871, OSP_455
01194 if (TARGET_64BIT && OPCODE_is_load(WN_opcode(wn2)))
01195 WN_set_rtype(wn2, Mtype_TransferSize(MTYPE_U8, WN_rtype(wn2)));
01196 #endif
01197 #ifdef KEY
01198
01199
01200 if (gs_tree_code(gs_tree_operand(exp, 0)) == GS_ARRAY_REF) {
01201 Is_True(WN_operator(wn0) == OPR_ARRAY,
01202 ("WGEN_Array_Expr: ARRAY_REF not translated to OPR_ARRAY"));
01203 int old_kid_count = WN_kid_count(wn0);
01204 int new_kid_count = old_kid_count + 2;
01205 wn = WN_Create(OPR_ARRAY, Pointer_Mtype, MTYPE_V, new_kid_count);
01206 for (int kid = 0; kid < (old_kid_count >> 1); kid++) {
01207 WN_kid(wn, kid + 1) = WN_kid(wn0, kid + 1);
01208 WN_kid(wn, (new_kid_count >> 1) + kid + 1) =
01209 WN_kid(wn0, (old_kid_count >> 1) + kid + 1);
01210 }
01211 WN_kid(wn, 0) = WN_kid(wn0, 0);
01212 WN_kid(wn, new_kid_count >> 1) = wn1;
01213 WN_kid(wn, new_kid_count - 1) = wn2;
01214 WN_Delete(wn0);
01215 } else
01216 #endif
01217 wn = WN_Ternary(OPR_ARRAY, Pointer_Mtype, wn0, wn1, wn2);
01218
01219 WN_element_size(wn) = TY_size(Get_TY (gs_tree_type(exp)));
01220 }
01221 else Is_True(FALSE,
01222 ("WGEN_Array_Expr: only const-bounds 1-dimension arrays handled now"));
01223 if (component_ty_idx == 0) {
01224 *ty_idx = TY_etype(ty_idx0);
01225 if (TY_align(ty_idx0) < TY_align(*ty_idx))
01226 Set_TY_align(*ty_idx, TY_align(ty_idx0));
01227 #ifdef KEY // bug 10728
01228 if (gs_tree_this_volatile(exp))
01229 Set_TY_is_volatile(*ty_idx);
01230 #endif
01231 }
01232 else *ty_idx = component_ty_idx;
01233 return wn;
01234 }
01235 #ifdef KEY
01236 else if (code == GS_COMPOUND_LITERAL_EXPR) {
01237 gs_t arg0 = gs_decl_initial (gs_tree_operand (gs_tree_operand (exp, 0), 0));
01238 ST *st = WGEN_Generate_Temp_For_Initialized_Aggregate (arg0, "");
01239 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
01240 *ty_idx = component_ty_idx == 0 ? ST_type(st) : component_ty_idx;
01241 return wn;
01242 }
01243 else if (code == GS_TARGET_EXPR) {
01244 wn = WGEN_Expand_Expr(exp);
01245 Is_True(WN_operator(wn) == OPR_LDID,
01246 ("WGEN_Array_Expr: OPR_LDID not found"));
01247 ST *st = WN_st(wn);
01248 wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
01249 if (component_ty_idx == 0)
01250 *ty_idx = ST_type(st);
01251 else {
01252 *ty_idx = component_ty_idx;
01253 if (TY_align(ST_type(st)) < TY_align(component_ty_idx))
01254 Set_TY_align(*ty_idx, TY_align(ST_type(st)));
01255 }
01256 Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
01257 ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
01258 return wn;
01259 }
01260 #endif
01261 else if (code == GS_COMPOUND_EXPR) {
01262 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), FALSE);
01263 if (wn && WN_has_side_effects(wn)) {
01264 wn = WN_CreateEval (wn);
01265 WGEN_Stmt_Append (wn, Get_Srcpos ());
01266 }
01267 return WGEN_Array_Expr(gs_tree_operand(exp, 1), ty_idx, component_ty_idx,
01268 component_offset, field_id);
01269 }
01270 else if (code == GS_COND_EXPR) {
01271 WN *wn1, *wn2;
01272 wn = WGEN_Expand_Expr(gs_tree_operand(exp, 0));
01273 wn1 = WGEN_Array_Expr(gs_tree_operand(exp, 1), ty_idx, component_ty_idx,
01274 component_offset, field_id);
01275 wn2 = WGEN_Array_Expr(gs_tree_operand(exp, 2), ty_idx, component_ty_idx,
01276 component_offset, field_id);
01277 Set_PU_has_very_high_whirl(Get_Current_PU());
01278 return WN_CreateExp3(OPR_CSELECT, WN_rtype(wn1), MTYPE_V, wn, wn1, wn2);
01279 }
01280 else {
01281 Is_True(FALSE,
01282 ("WGEN_Array_Expr: unsupported node for base of ARRAY_REF"));
01283 return NULL;
01284 }
01285 }
01286
01287 #if 0
01288
01289
01290
01291
01292
01293
01294
01295
01296 void
01297 WGEN_fixup_result_decl (gs_t exp)
01298 {
01299 Is_True (gs_tree_code(exp) == GS_RESULT_DECL,
01300 ("WGEN_fixup_result_decl: expected result_decl node"));
01301
01302
01303
01304
01305 gs_t ptr_var = gs_build_decl (GS_RESULT_DECL,
01306 gs_build_pointer_type(gs_tree_type(exp)));
01307
01308 _gs_code(exp, GS_INDIRECT_REF);
01309 gs_set_tree_operand (exp, 0, ptr_var);
01310
01311
01312 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
01313 set_DECL_ST (ptr_var, WN_st(first_formal));
01314 }
01315 #endif
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330 WN *
01331 WGEN_Lhs_Of_Modify_Expr(gs_code_t assign_code,
01332 gs_t lhs,
01333 WN* lhs_retval,
01334 bool need_result,
01335 TY_IDX component_ty_idx,
01336 INT64 component_offset,
01337 UINT32 field_id,
01338 bool is_bit_field,
01339 WN *rhs_wn,
01340 PREG_NUM rhs_preg_num,
01341 bool is_realpart,
01342 bool is_imagpart)
01343 {
01344 WN *wn = NULL;
01345 ST *st;
01346 bool result_in_temp = FALSE;
01347 ST *result_preg_st;
01348 PREG_NUM result_preg;
01349 PREG_NUM lhs_preg_num = 0;
01350 gs_code_t code = gs_tree_code (lhs);
01351 BOOL volt = FALSE;
01352 #ifdef TARG_SL
01353 BOOL need_append = FALSE;
01354 #endif
01355
01356 if (rhs_wn != NULL) {
01357 WGEN_Set_ST_Addr_Saved (rhs_wn);
01358 #ifdef TARG_SL
01359 need_append = WN_Need_Append_Intrinsic(rhs_wn);
01360 #endif
01361 }
01362
01363 TRACE_EXPAND_GS(lhs);
01364 switch (code) {
01365 case GS_COMPONENT_REF:
01366 {
01367 INT64 ofst;
01368 TY_IDX ty_idx0;
01369
01370 gs_t arg0 = gs_tree_operand(lhs, 0);
01371 gs_t arg1 = gs_tree_operand(lhs, 1);
01372 #ifdef GPLUSPLUS_FE
01373
01374
01375 (void) Get_TY (gs_tree_type (arg0));
01376 #endif
01377 if (component_ty_idx == 0)
01378 ty_idx0 = Get_TY(gs_tree_type(lhs));
01379 else ty_idx0 = component_ty_idx;
01380 if (gs_decl_bit_field(arg1))
01381 is_bit_field = TRUE;
01382 if (! is_bit_field)
01383 ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
01384 gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
01385 / BITSPERBYTE;
01386 else ofst = 0;
01387 #ifdef KEY // bug 10422: check if the field is volatile, arg1 is FIELD_DECL
01388 if (gs_tree_this_volatile(arg1)) {
01389 Set_TY_is_volatile(ty_idx0);
01390 volt = TRUE;
01391 }
01392 #if 1 // wgen bug 10470
01393 else {
01394 Clear_TY_is_volatile(ty_idx0);
01395 volt = FALSE;
01396 }
01397 #endif
01398 #endif
01399 #ifdef KEY
01400 FmtAssert (DECL_FIELD_ID(arg1) != 0,
01401 ("WGEN_Lhs_Of_Modify_Expr: DECL_FIELD_ID used but not set"));
01402 #endif
01403 wn = WGEN_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0,
01404 ofst+component_offset,
01405 field_id + DECL_FIELD_ID(arg1), is_bit_field,
01406 rhs_wn, rhs_preg_num, is_realpart,
01407 is_imagpart);
01408 }
01409 return wn;
01410
01411 case GS_REALPART_EXPR:
01412 {
01413 gs_t arg0 = gs_tree_operand(lhs, 0);
01414 TY_IDX ty_idx0 = Get_TY(gs_tree_type(arg0));
01415 wn = WGEN_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0,
01416 component_offset, field_id, is_bit_field,
01417 rhs_wn, rhs_preg_num, TRUE, FALSE);
01418 }
01419 return wn;
01420
01421 case GS_IMAGPART_EXPR:
01422 {
01423 gs_t arg0 = gs_tree_operand(lhs, 0);
01424 TY_IDX ty_idx0 = Get_TY(gs_tree_type(arg0));
01425 wn = WGEN_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0,
01426 component_offset, field_id, is_bit_field,
01427 rhs_wn, rhs_preg_num, FALSE, TRUE);
01428 }
01429 return wn;
01430
01431 #ifdef KEY
01432 case GS_TARGET_EXPR:
01433 {
01434 WN *wn = WGEN_Expand_Expr(lhs);
01435 Is_True(WN_operator(wn) == OPR_LDID,
01436 ("WGEN_Lhs_Of_Modify_Expr: wrong operator from TARGET_EXPR"));
01437 st = WN_st(wn);
01438 }
01439
01440 #endif
01441
01442 case GS_PARM_DECL:
01443 case GS_VAR_DECL:
01444 case GS_RESULT_DECL:
01445 {
01446 #if 0 // def KEY
01447
01448
01449 if (code == GS_RESULT_DECL &&
01450 TY_return_in_mem(Get_TY
01451 (gs_tree_type
01452 (gs_tree_type(Current_Function_Decl()) ) ) ) )
01453 {
01454 WGEN_fixup_result_decl (lhs);
01455 wn = WGEN_Lhs_Of_Modify_Expr (assign_code, lhs, NULL, need_result,
01456 component_ty_idx, component_offset,
01457 field_id, is_bit_field, rhs_wn,
01458 rhs_preg_num, is_realpart, is_imagpart);
01459 break;
01460 }
01461 #endif
01462 TY_IDX hi_ty_idx = Get_TY(gs_tree_type(lhs));
01463 if (gs_tree_this_volatile(lhs)) {
01464 Set_TY_is_volatile(hi_ty_idx);
01465 volt = TRUE;
01466 }
01467 #if 1 // wgen bug 10470
01468 else {
01469 Clear_TY_is_volatile(hi_ty_idx);
01470 volt = FALSE;
01471 }
01472 #endif
01473 TY_IDX desc_ty_idx = component_ty_idx;
01474 if (desc_ty_idx == 0)
01475 desc_ty_idx = hi_ty_idx;
01476 if (TY_is_volatile(desc_ty_idx)) {
01477 Clear_TY_is_volatile(desc_ty_idx);
01478 volt = TRUE;
01479 }
01480
01481 #ifdef KEY
01482 if (code != GS_TARGET_EXPR) {
01483 gs_t actual_decl = NULL;
01484 if (code == GS_VAR_DECL && (actual_decl = gs_decl_value_expr(lhs))) {
01485
01486 TY_IDX ty_idx0 = Get_TY (gs_tree_type (actual_decl));
01487 return WGEN_Lhs_Of_Modify_Expr(assign_code, actual_decl, NULL,
01488 need_result, ty_idx0,
01489 component_offset, field_id,
01490 is_bit_field, rhs_wn, rhs_preg_num,
01491 FALSE, FALSE);
01492 }
01493
01494 st = Get_ST (lhs);
01495 }
01496 #else
01497 st = Get_ST (lhs);
01498 #endif
01499
01500 if (ST_assigned_to_dedicated_preg (st)) {
01501 Set_TY_is_volatile(hi_ty_idx);
01502 volt = TRUE;
01503 }
01504 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
01505 ("WGEN_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
01506
01507 TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
01508 TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
01509
01510 if (rhs_wn == NULL) {
01511
01512
01513
01514
01515
01516 if (rtype == MTYPE_M && desc == MTYPE_M) {
01517 #ifndef KEY
01518 FmtAssert(TY_size(desc_ty_idx) == MTYPE_byte_size(Def_Int_Mtype),
01519 ("Size of ASM struct opnd must be equal to register size"));
01520 desc = rtype = Def_Int_Mtype;
01521 desc_ty_idx = hi_ty_idx = MTYPE_To_TY(Def_Int_Mtype);
01522 #else
01523
01524
01525
01526 if (rtype == MTYPE_M && desc == MTYPE_M) {
01527 if (TY_size(desc_ty_idx) == MTYPE_byte_size(Def_Int_Mtype)) {
01528 desc = rtype = Def_Int_Mtype;
01529 desc_ty_idx = hi_ty_idx = MTYPE_To_TY(Def_Int_Mtype);
01530 } else {
01531 desc = rtype = MTYPE_I4;
01532 desc_ty_idx = hi_ty_idx = MTYPE_To_TY(MTYPE_I4);
01533 }
01534 }
01535 #endif
01536 }
01537 ST *rhs_st = MTYPE_To_PREG(desc);
01538 rhs_wn = WN_CreateLdid (OPR_LDID, rtype,
01539 desc, rhs_preg_num, rhs_st,
01540 desc_ty_idx, 0);
01541 }
01542 else {
01543 WN *result_wn;
01544 if (assign_code == GS_MODIFY_EXPR) {
01545 if (is_realpart)
01546 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01547 rhs_wn,
01548 WN_Unary(OPR_IMAGPART,
01549 Mtype_complex_to_real (rtype),
01550 WN_CreateLdid(OPR_LDID, rtype, desc,
01551 ST_ofst(st) + component_offset,
01552 st, hi_ty_idx, field_id)));
01553 else
01554 if (is_imagpart)
01555 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01556 WN_Unary(OPR_REALPART,
01557 Mtype_complex_to_real (rtype),
01558 WN_CreateLdid(OPR_LDID, rtype, desc,
01559 ST_ofst(st) + component_offset,
01560 st, hi_ty_idx, field_id)),
01561 rhs_wn);
01562 }
01563 else {
01564 if (is_realpart)
01565 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01566 rhs_wn,
01567 WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
01568 else
01569 if (is_imagpart)
01570 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01571 WN_Floatconst (Mtype_complex_to_real (rtype), 0.0),
01572 rhs_wn);
01573 }
01574
01575 if (assign_code == GS_PREINCREMENT_EXPR ||
01576 assign_code == GS_PREDECREMENT_EXPR) {
01577 wn = WN_CreateLdid (OPR_LDID, rtype, desc,
01578 ST_ofst(st) + component_offset,
01579 st, hi_ty_idx, field_id);
01580 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01581 rtype, wn, rhs_wn);
01582 result_wn = rhs_wn;
01583 }
01584 else if (assign_code == GS_POSTINCREMENT_EXPR ||
01585 assign_code == GS_POSTDECREMENT_EXPR) {
01586 result_wn = WN_CreateLdid (OPR_LDID, rtype, desc,
01587 ST_ofst(st) + component_offset,
01588 st, hi_ty_idx, field_id);
01589 }
01590 else result_wn = rhs_wn;
01591
01592
01593 if (need_result && rtype != MTYPE_M &&
01594 (volt ||
01595 assign_code == GS_POSTINCREMENT_EXPR ||
01596 assign_code == GS_POSTDECREMENT_EXPR)) {
01597 result_in_temp = TRUE;
01598 result_preg_st = MTYPE_To_PREG(rtype);
01599 result_preg = Create_Preg(rtype, NULL);
01600 wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
01601 result_wn, 0);
01602 WGEN_Stmt_Append (wn, Get_Srcpos());
01603 result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
01604 0);
01605 }
01606
01607 if (assign_code == GS_POSTINCREMENT_EXPR ||
01608 assign_code == GS_POSTDECREMENT_EXPR) {
01609 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01610 rtype, result_wn, rhs_wn);
01611 }
01612 else rhs_wn = result_wn;
01613
01614
01615 }
01616
01617
01618 if (!WGEN_Keep_Zero_Length_Structs &&
01619 desc == MTYPE_M &&
01620 TY_size (hi_ty_idx) == 0) {
01621
01622 }
01623 else {
01624 #ifdef KEY // bug 10422: check if the field is volatile
01625 if (volt)
01626 Set_TY_is_volatile(hi_ty_idx);
01627 #endif
01628 wn = WN_Stid (desc, ST_ofst(st) + component_offset + lhs_preg_num, st,
01629 hi_ty_idx, rhs_wn, field_id);
01630 WGEN_Stmt_Append(wn, Get_Srcpos());
01631 #if defined(TARG_SL)
01632 if (need_append) {
01633 WN *ldid_wn;
01634 if (! result_in_temp)
01635 ldid_wn = WN_CreateLdid(OPR_LDID, rtype, desc,
01636 ST_ofst(st) + component_offset, st, hi_ty_idx,
01637 field_id);
01638 else
01639 ldid_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01640
01641 WFE_Stmt_Append_Extend_Intrinsic(wn, ldid_wn, Get_Srcpos());
01642 }
01643 #endif
01644 }
01645 if (need_result) {
01646 if (! result_in_temp)
01647 wn = WN_CreateLdid(OPR_LDID, rtype, desc,
01648 ST_ofst(st) + component_offset, st, hi_ty_idx,
01649 field_id);
01650 else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01651 if (is_realpart)
01652 wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
01653 else
01654 if (is_imagpart)
01655 wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
01656 }
01657 else wn = NULL;
01658 }
01659 break;
01660
01661 case GS_INDIRECT_REF:
01662 {
01663 TY_IDX hi_ty_idx = Get_TY(gs_tree_type(lhs));
01664 if (gs_tree_this_volatile(lhs)) {
01665 Set_TY_is_volatile(hi_ty_idx);
01666 volt = TRUE;
01667 }
01668 gs_t op = gs_tree_operand(lhs, 0);
01669 WN *addr_wn = NULL;
01670 TY_IDX desc_ty_idx = component_ty_idx;
01671 if (desc_ty_idx == 0)
01672 desc_ty_idx = hi_ty_idx;
01673 if (TY_is_volatile(desc_ty_idx)) {
01674 Clear_TY_is_volatile(desc_ty_idx);
01675 volt = TRUE;
01676 }
01677 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
01678 ("WGEN_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
01679
01680 if ( gs_tree_code(op) == GS_CALL_EXPR && lhs_retval != NULL ) {
01681
01682
01683
01684
01685
01686 addr_wn = lhs_retval;
01687 FmtAssert(WN_operator(addr_wn) == OPR_LDID,
01688 ("Bad Operator for INDIRECT_REF-->CALL_EXPR. LDID expected."));
01689 }
01690 else {
01691
01692 addr_wn = WGEN_Expand_Expr (gs_tree_operand (lhs, 0));
01693 if (WN_has_side_effects(addr_wn) &&
01694 (need_result ||
01695 assign_code == GS_PREINCREMENT_EXPR ||
01696 assign_code == GS_PREDECREMENT_EXPR ||
01697 assign_code == GS_POSTINCREMENT_EXPR ||
01698 assign_code == GS_POSTDECREMENT_EXPR)) {
01699 ST *preg_st;
01700 PREG_NUM preg;
01701 TY_IDX address_ty_idx = Get_TY (gs_tree_type (gs_tree_operand (lhs, 0)));
01702 #ifdef KEY
01703
01704 if (TY_is_volatile(address_ty_idx)) {
01705 Clear_TY_is_volatile(address_ty_idx);
01706 volt = TRUE;
01707 }
01708 #endif
01709 preg_st = MTYPE_To_PREG(Pointer_Mtype);
01710 preg = Create_Preg (Pointer_Mtype, NULL);
01711 wn = WN_Stid (Pointer_Mtype, preg, preg_st, address_ty_idx, addr_wn);
01712 WGEN_Set_ST_Addr_Saved (addr_wn);
01713 #ifdef KEY
01714
01715
01716 WN *body = WGEN_Stmt_Top();
01717 if (body &&
01718 WN_last(body) &&
01719 WN_operator(WN_last(body)) == OPR_ASM_STMT) {
01720 WGEN_Stmt_Prepend_Last (wn, Get_Srcpos());
01721 } else
01722 #endif
01723 WGEN_Stmt_Append (wn, Get_Srcpos());
01724 addr_wn = WN_Ldid (Pointer_Mtype, preg, preg_st, address_ty_idx);
01725 }
01726 }
01727
01728 TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
01729 TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
01730
01731 if (rhs_wn == NULL) {
01732
01733
01734
01735 ST *rhs_st;
01736
01737
01738 rhs_st = MTYPE_To_PREG(desc);
01739
01740 rhs_wn = WN_CreateLdid (OPR_LDID, rtype, desc, rhs_preg_num, rhs_st,
01741 desc_ty_idx, 0);
01742 #ifdef KEY
01743
01744
01745 if (MTYPE_byte_size(desc) < 4) {
01746
01747 rhs_wn = WN_CreateCvtl(!MTYPE_signed(desc) ? OPC_U4CVTL : OPC_I4CVTL,
01748 MTYPE_bit_size(desc),
01749 rhs_wn);
01750
01751 }
01752 #endif
01753 }
01754 else {
01755 WN *result_wn;
01756
01757 if (assign_code == GS_MODIFY_EXPR) {
01758 if (is_realpart)
01759 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01760 rhs_wn,
01761 WN_Unary(OPR_IMAGPART,
01762 Mtype_complex_to_real (rtype),
01763 WN_CreateIload(OPR_ILOAD, rtype, desc,
01764 component_offset,
01765 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01766 Make_Pointer_Type(hi_ty_idx, FALSE),
01767 WN_COPY_Tree (addr_wn),
01768 field_id)));
01769 else
01770 if (is_imagpart)
01771 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01772 WN_Unary(OPR_REALPART,
01773 Mtype_complex_to_real (rtype),
01774 WN_CreateIload(OPR_ILOAD, rtype, desc,
01775 component_offset,
01776 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01777 Make_Pointer_Type(hi_ty_idx, FALSE),
01778 WN_COPY_Tree (addr_wn),
01779 field_id)),
01780 rhs_wn);
01781 }
01782 else {
01783 if (is_realpart)
01784 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01785 rhs_wn,
01786 WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
01787 else
01788 if (is_imagpart)
01789 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01790 WN_Floatconst(Mtype_complex_to_real(rtype), 0.0),
01791 rhs_wn);
01792 }
01793
01794 if (assign_code == GS_PREINCREMENT_EXPR ||
01795 assign_code == GS_PREDECREMENT_EXPR) {
01796 wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
01797 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01798 Make_Pointer_Type(hi_ty_idx, FALSE),
01799 WN_COPY_Tree (addr_wn),
01800 field_id);
01801 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01802 rtype, wn, rhs_wn);
01803 result_wn = rhs_wn;
01804 }
01805 else if (assign_code == GS_POSTINCREMENT_EXPR ||
01806 assign_code == GS_POSTDECREMENT_EXPR) {
01807 result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
01808 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01809 Make_Pointer_Type(hi_ty_idx, FALSE),
01810 WN_COPY_Tree (addr_wn),
01811 field_id);
01812 }
01813 else result_wn = rhs_wn;
01814
01815
01816 if (need_result && rtype != MTYPE_M &&
01817 (volt ||
01818 assign_code == GS_POSTINCREMENT_EXPR ||
01819 assign_code == GS_POSTDECREMENT_EXPR)) {
01820 result_in_temp = TRUE;
01821 result_preg_st = MTYPE_To_PREG(rtype);
01822 result_preg = Create_Preg(rtype, NULL);
01823 wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
01824 result_wn, 0);
01825 WGEN_Stmt_Append (wn, Get_Srcpos());;
01826 result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
01827 0);
01828 }
01829
01830 if (assign_code == GS_POSTINCREMENT_EXPR ||
01831 assign_code == GS_POSTDECREMENT_EXPR) {
01832 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
01833 rtype, result_wn, rhs_wn);
01834 }
01835 else rhs_wn = result_wn;
01836
01837
01838 }
01839
01840
01841 if (!WGEN_Keep_Zero_Length_Structs &&
01842 desc == MTYPE_M &&
01843 TY_size (hi_ty_idx) == 0) {
01844
01845 if (WN_has_side_effects (addr_wn)) {
01846 wn = WN_CreateEval (addr_wn);
01847 WGEN_Stmt_Append (wn, Get_Srcpos());
01848 }
01849 wn = NULL;
01850 }
01851 else {
01852 #ifdef KEY
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867 gs_t addr = gs_tree_operand(lhs, 0);
01868 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
01869 if (TY_return_in_mem(hi_ty_idx) &&
01870 field_id == 0 &&
01871
01872
01873
01874 first_formal != NULL && (WN_operator(first_formal) != OPR_BLOCK) &&
01875 gs_tree_code(addr) == GS_VAR_DECL &&
01876 DECL_ST(addr) == WN_st(first_formal)) {
01877 FmtAssert(TY_mtype(hi_ty_idx) == MTYPE_M,
01878 ("WGEN_Lhs_Of_Modify_Expr: return_in_mem type not MTYPE_M"));
01879 gs_t ptr_type = gs_tree_type(gs_tree_operand(lhs, 0));
01880 gs_t type = gs_tree_type(ptr_type);
01881 FmtAssert(gs_tree_code(ptr_type) == GS_POINTER_TYPE,
01882 ("WGEN_Lhs_Of_Modify_Expr: INDIRECT_REF opnd0 is not POINTER_TYPE"));
01883 FmtAssert(component_offset == 0,
01884 ("WGEN_Lhs_Of_Modify_Expr: component_offset nonzero"));
01885 TY_IDX tidx = Get_TY(ptr_type);
01886
01887 FmtAssert(!WGEN_has_copy_constructor(type),
01888 ("WGEN_Lhs_Of_Modify_Expr: object needs copy constructor"));
01889 }
01890 #endif
01891 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset,
01892 Make_Pointer_Type (hi_ty_idx, FALSE),
01893 rhs_wn, addr_wn, field_id);
01894 WGEN_Stmt_Append(wn, Get_Srcpos());
01895 #if defined(TARG_SL)
01896 if (need_append) {
01897 WN *ldid_wn;
01898 if (! result_in_temp)
01899 ldid_wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
01900 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01901 Make_Pointer_Type (hi_ty_idx, FALSE),
01902 WN_COPY_Tree (addr_wn),
01903 field_id);
01904 else
01905 ldid_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01906
01907 WFE_Stmt_Append_Extend_Intrinsic(wn, ldid_wn, Get_Srcpos());
01908 }
01909 #endif
01910 if (need_result) {
01911 if (! result_in_temp)
01912 wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
01913 field_id != 0 ? hi_ty_idx : desc_ty_idx,
01914 Make_Pointer_Type (hi_ty_idx, FALSE),
01915 WN_COPY_Tree (addr_wn),
01916 field_id);
01917 else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
01918 if (is_realpart)
01919 wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
01920 else
01921 if (is_imagpart)
01922 wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
01923 }
01924 else wn = NULL;
01925 }
01926 }
01927 break;
01928
01929 case GS_ARRAY_REF:
01930 {
01931 TY_IDX elem_ty_idx;
01932
01933 WN *addr_wn = WGEN_Array_Expr(lhs, &elem_ty_idx, 0, 0, 0);
01934 if (TY_is_volatile(elem_ty_idx))
01935 volt = TRUE;
01936 TY_IDX desc_ty_idx = component_ty_idx;
01937 if (desc_ty_idx == 0)
01938 desc_ty_idx = Get_TY (gs_tree_type(lhs));
01939 if (TY_is_volatile(desc_ty_idx)) {
01940 Clear_TY_is_volatile(desc_ty_idx);
01941 volt = TRUE;
01942 }
01943 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
01944 ("WGEN_Lhs_Of_Modify_Expr: field id for bit-field exceeds limit"));
01945 if (WN_has_side_effects(addr_wn) &&
01946 (need_result ||
01947 assign_code == GS_PREINCREMENT_EXPR ||
01948 assign_code == GS_PREDECREMENT_EXPR ||
01949 assign_code == GS_POSTINCREMENT_EXPR ||
01950 assign_code == GS_POSTDECREMENT_EXPR)) {
01951 ST *preg_st;
01952 PREG_NUM preg;
01953 TY_IDX address_ty_idx = Make_Pointer_Type(elem_ty_idx, FALSE);
01954 preg_st = MTYPE_To_PREG(Pointer_Mtype);
01955 preg = Create_Preg (Pointer_Mtype, NULL);
01956 wn = WN_Stid (Pointer_Mtype, preg, preg_st, address_ty_idx, addr_wn);
01957 WGEN_Set_ST_Addr_Saved (addr_wn);
01958 WGEN_Stmt_Append (wn, Get_Srcpos());
01959 addr_wn = WN_Ldid (Pointer_Mtype, preg, preg_st, address_ty_idx);
01960 }
01961
01962 TYPE_ID rtype = Widen_Mtype(TY_mtype(desc_ty_idx));
01963 TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
01964
01965 if (rhs_wn == NULL) {
01966
01967
01968
01969 ST *rhs_st;
01970
01971
01972 rhs_st = MTYPE_To_PREG(desc);
01973 rhs_wn = WN_CreateLdid (OPR_LDID, rtype, desc, rhs_preg_num, rhs_st,
01974 desc_ty_idx, 0);
01975 }
01976 else {
01977 WN *result_wn;
01978
01979 if (assign_code == GS_MODIFY_EXPR) {
01980 if (is_realpart)
01981 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01982 rhs_wn,
01983 WN_Unary(OPR_IMAGPART,
01984 Mtype_complex_to_real (rtype),
01985 WN_CreateIload(OPR_ILOAD, rtype, desc,
01986 component_offset,
01987 field_id != 0 ? elem_ty_idx : desc_ty_idx,
01988 Make_Pointer_Type(elem_ty_idx, FALSE),
01989 WN_COPY_Tree (addr_wn),
01990 field_id)));
01991 else
01992 if (is_imagpart)
01993 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
01994 WN_Unary(OPR_REALPART,
01995 Mtype_complex_to_real (rtype),
01996 WN_CreateIload(OPR_ILOAD, rtype, desc,
01997 component_offset,
01998 field_id != 0 ? elem_ty_idx : desc_ty_idx,
01999 Make_Pointer_Type(elem_ty_idx, FALSE),
02000 WN_COPY_Tree (addr_wn),
02001 field_id)),
02002 rhs_wn);
02003 }
02004 else {
02005 if (is_realpart)
02006 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02007 rhs_wn,
02008 WN_Floatconst (Mtype_complex_to_real (rtype), 0.0));
02009 else
02010 if (is_imagpart)
02011 rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
02012 WN_Floatconst(Mtype_complex_to_real(rtype), 0.0),
02013 rhs_wn);
02014 }
02015
02016 if (assign_code == GS_PREINCREMENT_EXPR ||
02017 assign_code == GS_PREDECREMENT_EXPR) {
02018 wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02019 field_id != 0 ? elem_ty_idx : desc_ty_idx,
02020 Make_Pointer_Type(elem_ty_idx, FALSE),
02021 WN_COPY_Tree (addr_wn),
02022 field_id);
02023 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
02024 rtype, wn, rhs_wn);
02025 result_wn = rhs_wn;
02026 }
02027 else if (assign_code == GS_POSTINCREMENT_EXPR ||
02028 assign_code == GS_POSTDECREMENT_EXPR) {
02029 result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02030 field_id != 0 ? elem_ty_idx : desc_ty_idx,
02031 Make_Pointer_Type(elem_ty_idx, FALSE),
02032 WN_COPY_Tree (addr_wn),
02033 field_id);
02034 }
02035 else result_wn = rhs_wn;
02036
02037
02038 if (need_result && rtype != MTYPE_M &&
02039 (volt ||
02040 assign_code == GS_POSTINCREMENT_EXPR ||
02041 assign_code == GS_POSTDECREMENT_EXPR)) {
02042 result_in_temp = TRUE;
02043 result_preg_st = MTYPE_To_PREG(rtype);
02044 result_preg = Create_Preg(rtype, NULL);
02045 wn = WN_Stid(rtype, result_preg, result_preg_st, desc_ty_idx,
02046 result_wn, 0);
02047 WGEN_Stmt_Append (wn, Get_Srcpos());;
02048 result_wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx,
02049 0);
02050 }
02051
02052 if (assign_code == GS_POSTINCREMENT_EXPR ||
02053 assign_code == GS_POSTDECREMENT_EXPR) {
02054 rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
02055 rtype, result_wn, rhs_wn);
02056 }
02057 else rhs_wn = result_wn;
02058
02059
02060 }
02061
02062
02063 if (!WGEN_Keep_Zero_Length_Structs &&
02064 desc == MTYPE_M &&
02065 TY_size (elem_ty_idx) == 0) {
02066
02067 if (WN_has_side_effects (addr_wn)) {
02068 wn = WN_CreateEval (addr_wn);
02069 WGEN_Stmt_Append (wn, Get_Srcpos());
02070 }
02071 wn = NULL;
02072 }
02073 else {
02074 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset,
02075 Make_Pointer_Type(elem_ty_idx, FALSE), rhs_wn,
02076 addr_wn, field_id);
02077 WGEN_Stmt_Append(wn, Get_Srcpos());
02078 #ifdef TARG_SL
02079 if (need_append) {
02080 WN *iload;
02081 if (!result_in_temp)
02082 iload = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02083 field_id != 0 ? elem_ty_idx : desc_ty_idx,
02084 Make_Pointer_Type (elem_ty_idx, FALSE),
02085 WN_COPY_Tree (addr_wn),
02086 field_id);
02087 else
02088 iload = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
02089 WFE_Stmt_Append_Extend_Intrinsic(wn, iload, Get_Srcpos());
02090 }
02091 #endif
02092 if (need_result) {
02093 if (! result_in_temp)
02094 wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
02095 field_id != 0 ? elem_ty_idx : desc_ty_idx,
02096 Make_Pointer_Type (elem_ty_idx, FALSE),
02097 WN_COPY_Tree (addr_wn),
02098 field_id);
02099 else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
02100 if (is_realpart)
02101 wn = WN_Unary (OPR_REALPART, Mtype_complex_to_real (rtype), wn);
02102 else
02103 if (is_imagpart)
02104 wn = WN_Unary (OPR_IMAGPART, Mtype_complex_to_real (rtype), wn);
02105 }
02106 else wn = NULL;
02107 }
02108 }
02109 break;
02110 #ifdef KEY // bug 10073
02111 case GS_MIN_EXPR:
02112 case GS_MAX_EXPR:
02113 {
02114 gs_t arg0 = gs_tree_operand(lhs, 0);
02115 gs_t arg1 = gs_tree_operand(lhs, 1);
02116
02117 WN *then_block = WN_CreateBlock ();
02118 WN *else_block = WN_CreateBlock ();
02119
02120 WGEN_Stmt_Push (then_block, wgen_stmk_if_then, Get_Srcpos());
02121 WN * wn1 = WGEN_Lhs_Of_Modify_Expr (assign_code, arg0, NULL, TRUE,
02122 component_ty_idx, component_offset,
02123 field_id, is_bit_field,
02124 rhs_wn, rhs_preg_num, is_realpart,
02125 is_imagpart);
02126 WGEN_Stmt_Pop (wgen_stmk_if_then);
02127
02128 WGEN_Stmt_Push (else_block, wgen_stmk_if_else, Get_Srcpos());
02129 WN * wn2 = WGEN_Lhs_Of_Modify_Expr (assign_code, arg1, NULL, TRUE,
02130 component_ty_idx, component_offset,
02131 field_id, is_bit_field,
02132 rhs_wn, rhs_preg_num, is_realpart,
02133 is_imagpart);
02134 WGEN_Stmt_Pop (wgen_stmk_if_else);
02135
02136 Is_True (wn1 && wn2,
02137 ("WGEN_Lhs_Of_Modify_Expr: null operands of MIN/MAX_EXPR?"));
02138 WN * wn0 = WN_Relational (code == GS_MIN_EXPR ? OPR_LE : OPR_GE,
02139 Widen_Mtype(TY_mtype(Get_TY(gs_tree_type(lhs)))),
02140 wn1, wn2);
02141 WN *if_stmt = WN_CreateIf (wn0, then_block, else_block);
02142 WGEN_Stmt_Append (if_stmt, Get_Srcpos());
02143 }
02144 break;
02145 #endif
02146
02147 case GS_COMPOUND_LITERAL_EXPR:
02148 {
02149 #ifdef KEY // bug 14372
02150 TY_IDX hi_ty_idx = Get_TY(gs_tree_type(lhs));
02151 #endif
02152 gs_t var = gs_decl_initial(gs_tree_operand(gs_tree_operand (lhs, 0), 0));
02153 st = WGEN_Generate_Temp_For_Initialized_Aggregate(var, "");
02154
02155
02156
02157 ST *copy = New_ST(CURRENT_SYMTAB);
02158 ST_Init(copy, Save_Str(".cpfrominit"), CLASS_VAR, SCLASS_AUTO,
02159 EXPORT_LOCAL, ST_type(st));
02160 WN *init_wn = WN_CreateLdid(OPR_LDID, MTYPE_M, MTYPE_M, 0, st,
02161 ST_type(st));
02162 WGEN_Stmt_Append( WN_CreateStid(OPR_STID, MTYPE_V, MTYPE_M,
02163 0, copy, ST_type(copy), init_wn),
02164 Get_Srcpos());
02165
02166 TY_IDX desc_ty_idx = component_ty_idx;
02167 TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
02168 if (desc == MTYPE_UNKNOWN)
02169 desc = WN_rtype(rhs_wn);
02170 #ifdef KEY // bug 14372
02171 wn = WN_Stid (desc, ST_ofst(copy) + component_offset, copy,
02172 hi_ty_idx, rhs_wn, field_id);
02173 #else
02174 if (desc_ty_idx == 0)
02175 desc_ty_idx = MTYPE_TO_TY_array[desc];
02176
02177 wn = WN_Stid (desc, ST_ofst(copy) + component_offset, copy,
02178 desc_ty_idx, rhs_wn, field_id);
02179 #endif
02180 WGEN_Stmt_Append(wn, Get_Srcpos());
02181 if (need_result)
02182 wn = WN_CreateLdid(OPR_LDID, desc, desc,
02183 ST_ofst(copy) + component_offset, copy,
02184 ST_type(copy));
02185 else
02186 wn = NULL;
02187 }
02188 break;
02189
02190 #ifdef KEY
02191 case GS_FILTER_EXPR:
02192
02193 DevWarn("NYI: FILTER_EXPR");
02194 wn = NULL;
02195 break;
02196
02197 case GS_EXC_PTR_EXPR:
02198
02199 DevWarn("NYI: EXC_PTR_EXPR");
02200 wn = NULL;
02201 break;
02202 #endif
02203
02204 default:
02205 Fail_FmtAssertion ("WGEN_Lhs_Of_Modify_Expr: unhandled tree node in LHS of MODIFY_EXPR");
02206 }
02207
02208 return wn;
02209 }
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236 WN*
02237 WGEN_Expand_Expr_With_Sequence_Point (gs_t exp, TYPE_ID mtype, WN* target_wn)
02238 {
02239 WN *wn;
02240
02241 if (mtype == MTYPE_V)
02242 #ifdef KEY
02243 wn = WGEN_Expand_Expr (exp, FALSE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
02244 #else
02245 wn = WGEN_Expand_Expr (exp, FALSE);
02246 #endif
02247
02248 else {
02249
02250 WN *comma_block = WN_CreateBlock ();
02251
02252 WGEN_Stmt_Push (comma_block, wgen_stmk_comma, Get_Srcpos ());
02253 #ifdef KEY
02254 wn = WGEN_Expand_Expr (exp, TRUE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
02255 #else
02256 wn = WGEN_Expand_Expr (exp);
02257 #endif
02258
02259
02260 if (gs_tree_type (exp) == gs_boolean_type_node()) {
02261 if (WN_operator (wn) == OPR_LDID ||
02262 WN_operator (wn) == OPR_ILOAD) {
02263 WN *zero = WN_Intconst (WN_rtype (wn), 0);
02264 wn = WN_Relational (OPR_NE, MTYPE_I4, wn, zero);
02265 }
02266 }
02267
02268 WGEN_Stmt_Pop (wgen_stmk_comma);
02269 if (WN_first (comma_block)) {
02270 if (wn)
02271 wn = WN_CreateComma (OPR_COMMA, Mtype_comparison (mtype), MTYPE_V,
02272 comma_block, wn);
02273 else
02274 WGEN_Stmt_Append (comma_block, Get_Srcpos());
02275 }
02276 else
02277 WN_Delete (comma_block);
02278 }
02279
02280 return wn;
02281 }
02282
02283 static void
02284 emit_barrier (bool type, gs_t list, INT32 k)
02285 {
02286 INT32 i;
02287 WN *wn = WN_CreateBarrier (type, k);
02288
02289 for (i = 0; i < k; i++) {
02290 gs_t exp = gs_tree_value (list);
02291 ST *st = Get_ST (exp);
02292 WN_kid (wn, i) = WN_Lda (Pointer_Mtype, 0, st,
02293 Make_Pointer_Type (ST_type (st), FALSE));
02294 list = gs_tree_chain (list);
02295 }
02296
02297 WGEN_Stmt_Append (wn, Get_Srcpos());
02298 }
02299
02300 static WN *
02301 emit_builtin_lock_test_and_set (gs_t exp, INT32 k)
02302 {
02303 WN *wn;
02304 WN *arg_wn;
02305 WN *ikids [2];
02306 TYPE_ID obj_mtype;
02307 TY_IDX arg_ty_idx;
02308 TYPE_ID arg_mtype;
02309 gs_t list = gs_tree_operand (exp, 1);
02310 OPCODE opc;
02311 INTRINSIC iopc;
02312
02313 obj_mtype = TY_mtype (TY_pointed (Get_TY(gs_tree_type(gs_tree_value(list)))));
02314 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02315 arg_mtype = TY_mtype (arg_ty_idx);
02316 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02317 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02318 ikids [0] = arg_wn;
02319 list = gs_tree_chain (list);
02320 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02321 arg_mtype = TY_mtype (arg_ty_idx);
02322 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02323 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02324 ikids [1] = arg_wn;
02325 list = gs_tree_chain (list);
02326
02327 if (obj_mtype == MTYPE_I4) {
02328 opc = OPC_I4INTRINSIC_CALL;
02329 iopc = INTRN_LOCK_TEST_AND_SET_I4;
02330 }
02331 else
02332 if (obj_mtype == MTYPE_U4) {
02333 opc = OPC_U4INTRINSIC_CALL;
02334 iopc = INTRN_LOCK_TEST_AND_SET_I4;
02335 }
02336 else
02337 if (obj_mtype == MTYPE_I8) {
02338 opc = OPC_I8INTRINSIC_CALL;
02339 iopc = INTRN_LOCK_TEST_AND_SET_I8;
02340 }
02341 else
02342 if (obj_mtype == MTYPE_U8) {
02343 opc = OPC_U8INTRINSIC_CALL;
02344 iopc = INTRN_LOCK_TEST_AND_SET_I8;
02345 }
02346 else {
02347 Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02348 opc = OPCODE_UNKNOWN;
02349 iopc = INTRINSIC_NONE;
02350 }
02351
02352 wn = WN_Create_Intrinsic (opc, iopc, 2, ikids);
02353 WGEN_Stmt_Append (wn, Get_Srcpos());
02354
02355 ST *preg_st = MTYPE_To_PREG(obj_mtype);
02356 TY_IDX preg_ty_idx = Be_Type_Tbl(obj_mtype);
02357 PREG_NUM preg = Create_Preg (obj_mtype, NULL);
02358
02359 wn = WN_Ldid (obj_mtype, -1, Return_Val_Preg, preg_ty_idx);
02360 wn = WN_Stid (obj_mtype, preg, preg_st, preg_ty_idx, wn),
02361 WGEN_Stmt_Append (wn, Get_Srcpos());
02362
02363 emit_barrier (FALSE, list, k);
02364
02365 wn = WN_Ldid (obj_mtype, preg, preg_st, preg_ty_idx);
02366
02367 return wn;
02368 }
02369
02370 static void
02371 emit_builtin_lock_release (gs_t exp, INT32 k)
02372 {
02373 WN *wn;
02374 WN *arg_wn;
02375 WN *ikids [1];
02376 TYPE_ID obj_mtype;
02377 TY_IDX arg_ty_idx;
02378 TYPE_ID arg_mtype;
02379 gs_t list = gs_tree_operand (exp, 1);
02380 OPCODE opc;
02381 INTRINSIC iopc;
02382
02383 obj_mtype = TY_mtype (TY_pointed (Get_TY(gs_tree_type(gs_tree_value(list)))));
02384 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02385 arg_mtype = TY_mtype (arg_ty_idx);
02386 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02387 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02388 ikids [0] = arg_wn;
02389 list = gs_tree_chain (list);
02390
02391 emit_barrier (TRUE, list, k);
02392
02393 opc = OPC_VINTRINSIC_CALL;
02394 if (obj_mtype == MTYPE_I4)
02395 iopc = INTRN_LOCK_RELEASE_I4;
02396 else
02397 if (obj_mtype == MTYPE_U4)
02398 iopc = INTRN_LOCK_RELEASE_I4;
02399 else
02400 if (obj_mtype == MTYPE_I8)
02401 iopc = INTRN_LOCK_RELEASE_I8;
02402 else
02403 if (obj_mtype == MTYPE_U8)
02404 iopc = INTRN_LOCK_RELEASE_I8;
02405 else {
02406 Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02407 opc = OPCODE_UNKNOWN;
02408 iopc = INTRINSIC_NONE;
02409 }
02410
02411 wn = WN_Create_Intrinsic (opc, iopc, 1, ikids);
02412 WGEN_Stmt_Append (wn, Get_Srcpos());
02413 }
02414
02415 static WN *
02416 emit_builtin_compare_and_swap (gs_t exp, INT32 k)
02417 {
02418 WN *wn;
02419 WN *arg_wn;
02420 WN *ikids [3];
02421 TYPE_ID obj_mtype;
02422 TY_IDX arg_ty_idx;
02423 TYPE_ID arg_mtype;
02424 gs_t list = gs_tree_operand (exp, 1);
02425 OPCODE opc;
02426 INTRINSIC iopc;
02427
02428 obj_mtype = TY_mtype (TY_pointed (Get_TY(gs_tree_type(gs_tree_value(list)))));
02429 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02430 arg_mtype = TY_mtype (arg_ty_idx);
02431 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02432 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02433 ikids [0] = arg_wn;
02434 list = gs_tree_chain (list);
02435 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02436 arg_mtype = TY_mtype (arg_ty_idx);
02437 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02438 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02439 ikids [1] = arg_wn;
02440 list = gs_tree_chain (list);
02441 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02442 arg_mtype = TY_mtype (arg_ty_idx);
02443 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02444 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02445 ikids [2] = arg_wn;
02446 list = gs_tree_chain (list);
02447
02448 emit_barrier (TRUE, list, k);
02449
02450 opc = OPC_I4INTRINSIC_CALL;
02451 if (obj_mtype == MTYPE_I4)
02452 iopc = INTRN_COMPARE_AND_SWAP_I4;
02453 else
02454 if (obj_mtype == MTYPE_U4)
02455 iopc = INTRN_COMPARE_AND_SWAP_I4;
02456 else
02457 if (obj_mtype == MTYPE_I8)
02458 iopc = INTRN_COMPARE_AND_SWAP_I8;
02459 else
02460 if (obj_mtype == MTYPE_U8)
02461 iopc = INTRN_COMPARE_AND_SWAP_I8;
02462 else {
02463 Fail_FmtAssertion ("unknown object type in __builtin_lock_test_and_set");
02464 opc = OPCODE_UNKNOWN;
02465 iopc = INTRINSIC_NONE;
02466 }
02467
02468 wn = WN_Create_Intrinsic (opc, iopc, 3, ikids);
02469 WGEN_Stmt_Append (wn, Get_Srcpos());
02470
02471 ST *preg_st = MTYPE_To_PREG(MTYPE_I4);
02472 TY_IDX preg_ty_idx = Be_Type_Tbl(MTYPE_I4);
02473 PREG_NUM preg = Create_Preg (MTYPE_I4, NULL);
02474
02475 wn = WN_Ldid (MTYPE_I4, -1, Return_Val_Preg, preg_ty_idx);
02476 wn = WN_Stid (MTYPE_I4, preg, preg_st, preg_ty_idx, wn),
02477 WGEN_Stmt_Append (wn, Get_Srcpos());
02478
02479 emit_barrier (FALSE, list, k);
02480
02481 wn = WN_Ldid (MTYPE_I4, preg, preg_st, preg_ty_idx);
02482
02483 return wn;
02484 }
02485
02486
02487
02488
02489
02490
02491
02492 static WN *
02493 emit_builtin_sync_fetch_op (INTRINSIC iopc, gs_t exp, INT32 k)
02494 {
02495 WN *wn;
02496 WN *arg_wn;
02497 WN *ikids [2];
02498 TYPE_ID obj_mtype;
02499 TY_IDX arg_ty_idx;
02500 TYPE_ID arg_mtype;
02501 gs_t list = gs_tree_operand (exp, 1);
02502 OPCODE opc;
02503
02504 obj_mtype = TY_mtype (TY_pointed (Get_TY(gs_tree_type(gs_tree_value(list)))));
02505 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02506 arg_mtype = TY_mtype (arg_ty_idx);
02507 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02508 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02509 ikids [0] = arg_wn;
02510 list = gs_tree_chain (list);
02511 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
02512 arg_mtype = TY_mtype (arg_ty_idx);
02513 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
02514 arg_wn = WN_CreateParm (arg_mtype, arg_wn, arg_ty_idx, WN_PARM_BY_VALUE);
02515 ikids [1] = arg_wn;
02516 list = gs_tree_chain (list);
02517
02518 Is_True( (obj_mtype == MTYPE_I4 || obj_mtype == MTYPE_U4 ||
02519 obj_mtype == MTYPE_I8 || obj_mtype == MTYPE_U8),
02520 ("Unsupported object type in emit_builtin_sync_fetch_op") );
02521
02522 emit_barrier (TRUE, list, k);
02523
02524 opc = OPCODE_make_op(OPR_INTRINSIC_CALL, obj_mtype, MTYPE_V);
02525 wn = WN_Create_Intrinsic (opc, iopc, 2, ikids);
02526 WGEN_Stmt_Append (wn, Get_Srcpos());
02527
02528 ST *preg_st = MTYPE_To_PREG(obj_mtype);
02529 TY_IDX preg_ty_idx = Be_Type_Tbl(obj_mtype);
02530 PREG_NUM preg = Create_Preg (obj_mtype, NULL);
02531
02532 wn = WN_Ldid (obj_mtype, -1, Return_Val_Preg, preg_ty_idx);
02533 wn = WN_Stid (obj_mtype, preg, preg_st, preg_ty_idx, wn),
02534 WGEN_Stmt_Append (wn, Get_Srcpos());
02535
02536 emit_barrier (FALSE, list, k);
02537
02538 wn = WN_Ldid (obj_mtype, preg, preg_st, preg_ty_idx);
02539
02540 return wn;
02541 }
02542
02543 static void
02544 emit_builtin_synchronize (gs_t exp, INT32 k)
02545 {
02546 WN *wn;
02547 gs_t list = gs_tree_operand (exp, 1);
02548 emit_barrier (TRUE, list, k);
02549 wn = WN_Create_Intrinsic (OPC_VINTRINSIC_CALL, INTRN_SYNCHRONIZE, 0, NULL);
02550 WGEN_Stmt_Append (wn, Get_Srcpos());
02551 emit_barrier (FALSE, list, k);
02552 }
02553
02554 static char *
02555 get_string_pointer (WN *wn)
02556 {
02557 char *ptr = NULL;
02558
02559 if (WN_operator (wn) == OPR_LDA) {
02560 ST *st = WN_st (wn);
02561 if (ST_class (st) == CLASS_CONST) {
02562 TCON tcon = Tcon_Table [ST_tcon (st)];
02563 if (TCON_ty (tcon) == MTYPE_STRING)
02564 ptr = ((char *) Targ_String_Address (tcon)) + WN_offset (wn);
02565 }
02566 }
02567
02568 return ptr;
02569 }
02570
02571
02572
02573 WN*
02574 WGEN_Address_Of(gs_t arg0)
02575 {
02576 gs_code_t code0 = gs_tree_code (arg0);
02577 ST *st = 0;
02578 WN* wn = 0;
02579 WN* wn0;
02580 WN* wn1;
02581 TY_IDX ty_idx;
02582
02583 switch (code0) {
02584 #ifdef KEY
02585 case GS_RESULT_DECL:
02586 #if 0
02587
02588
02589 if (TY_return_in_mem(Get_TY
02590 (gs_tree_type
02591 (gs_tree_type(Current_Function_Decl()) ) ) ) )
02592 {
02593 WGEN_fixup_result_decl (arg0);
02594 wn = WGEN_Address_Of (arg0);
02595 break;
02596 }
02597
02598 #endif
02599 #endif
02600 case GS_VAR_DECL:
02601 case GS_PARM_DECL:
02602 case GS_FUNCTION_DECL:
02603 {
02604 st = Get_ST (arg0);
02605 ty_idx = ST_type (st);
02606 #ifdef KEY
02607
02608
02609 if (code0 == GS_VAR_DECL) {
02610 if (gs_decl_initial(arg0) &&
02611 (gs_decl_virtual_p(arg0) ||
02612 ( gs_decl_tinfo_p(arg0) &&
02613
02614 gs_tree_code(gs_decl_initial(arg0)) != GS_STRING_CST)) &&
02615 !gs_decl_external(arg0)) {
02616 gs_t init = gs_decl_initial(arg0);
02617 if (gs_tree_code(init) != GS_ERROR_MARK) {
02618 FmtAssert (gs_tree_code(init) == GS_CONSTRUCTOR,
02619 ("Unexpected initializer for virtual table"));
02620 WGEN_Initialize_Decl(arg0);
02621 }
02622 }
02623 }
02624
02625 if (code0 == GS_VAR_DECL && gs_decl_value_expr(arg0)) {
02626 wn = WGEN_Address_Of (gs_decl_value_expr(arg0));
02627 break;
02628 }
02629 #endif
02630
02631 if (code0 == GS_VAR_DECL &&
02632 st != ST_base(st)) {
02633 FmtAssert (ST_ofst (st) == 0,
02634 ("Variable Length Arrays within struct not currently implemented"));
02635 wn = WN_Ldid (Pointer_Mtype, 0, ST_base(st), ST_type(ST_base(st)));
02636 }
02637 else
02638 if (!WGEN_Keep_Zero_Length_Structs &&
02639 code0 == GS_PARM_DECL &&
02640 TY_mtype (ty_idx) == MTYPE_M &&
02641 TY_size (ty_idx) == 0) {
02642
02643 DevWarn ("taking address of zero length struct %s at line %d",
02644 ST_name (st), lineno);
02645 wn = WN_Intconst (Pointer_Mtype, 0);
02646 }
02647 else
02648 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02649
02650 #ifdef KEY
02651 if (code0 == GS_FUNCTION_DECL) {
02652 PU &pu = Pu_Table[ST_pu(st)];
02653 if (PU_is_nested_func(pu))
02654 Set_PU_need_trampoline(pu);
02655 }
02656 #endif
02657 }
02658 break;
02659
02660 case GS_INDIRECT_REF:
02661 wn = WGEN_Expand_Expr (gs_tree_operand(arg0, 0));
02662 break;
02663
02664 case GS_STRING_CST:
02665 {
02666 TCON tcon;
02667 tcon = Host_To_Targ_String (MTYPE_STRING,
02668 const_cast<char*>(gs_tree_string_pointer(arg0)),
02669 gs_tree_string_length(arg0));
02670 ty_idx = Get_TY(gs_tree_type(arg0));
02671 st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
02672 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02673 TREE_STRING_ST (arg0) = st;
02674 }
02675 break;
02676
02677 case GS_CONSTRUCTOR:
02678 {
02679 st = WGEN_Generate_Temp_For_Initialized_Aggregate (arg0, "");
02680 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02681 }
02682 break;
02683
02684 case GS_LABEL_DECL:
02685 {
02686 DevWarn ("taking address of a label at line %d", lineno);
02687 LABEL_IDX label_idx = WGEN_Get_LABEL (arg0, FALSE);
02688 #if 0
02689 FmtAssert (arg0->decl.symtab_idx == CURRENT_SYMTAB,
02690 ("line %d: taking address of a label not defined in current function currently not implemented", lineno));
02691 #endif
02692 wn = WN_LdaLabel (Pointer_Mtype, label_idx);
02693 Set_LABEL_addr_saved (label_idx);
02694 #ifdef KEY
02695
02696
02697
02698
02699 if ( ST_export (Get_Current_PU_ST()) != EXPORT_LOCAL)
02700 #endif
02701 Set_PU_no_inline (Get_Current_PU ());
02702 }
02703 break;
02704
02705 case GS_TARGET_EXPR:
02706 {
02707 WGEN_Expand_Expr (arg0);
02708 st = Get_ST (gs_tree_operand(arg0, 0));
02709 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02710 }
02711 break;
02712
02713 case GS_COMPOUND_EXPR:
02714 {
02715 #ifdef KEY
02716 wn = WGEN_Expand_Expr(arg0);
02717 if (WN_operator(wn) == OPR_CSELECT) {
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729 int i;
02730 ST *st1 = NULL, *st2 = NULL;
02731 for (i = 0; i < 2; i++) {
02732 WN *kid = (i == 0) ? WN_kid1(wn) : WN_kid2(wn);
02733 WN *comma_kid1;
02734 ST **st_ptr = (i == 0) ? &st1 : &st2;
02735 switch (WN_operator(kid)) {
02736 case OPR_LDID:
02737 *st_ptr = WN_st(kid);
02738 break;
02739 case OPR_COMMA:
02740 comma_kid1 = WN_kid1(kid);
02741 Is_True(WN_operator(comma_kid1) == OPR_LDID,
02742 ("WGEN_Address_Of: kid1 of COMMA is not LDID"));
02743 *st_ptr = WN_st(comma_kid1);
02744 break;
02745 default:
02746 FmtAssert(FALSE, ("WGEN_Address_Of: CSELECT kid NYI"));
02747 }
02748 }
02749 Is_True((st1 != NULL) && (st1 == st2),
02750 ("WGEN_Address_Of: CSELECT kids returns different STs"));
02751 st = st1;
02752 } else
02753 st = WN_st(wn);
02754 #else
02755 st = WN_st (WGEN_Expand_Expr (arg0));
02756 #endif
02757 wn = WN_Lda (Pointer_Mtype, ST_ofst (st), st);
02758 }
02759 break;
02760
02761 case GS_NOP_EXPR:
02762 {
02763 wn = WGEN_Address_Of(gs_tree_operand(arg0, 0));
02764 }
02765 break;
02766
02767 case GS_MIN_EXPR:
02768 case GS_MAX_EXPR:
02769 {
02770
02771 gs_t op0 = gs_tree_operand(arg0, 0);
02772 gs_t op1 = gs_tree_operand(arg0, 1);
02773 WN* a = WGEN_Expand_Expr(op0);
02774 WN* b = WGEN_Expand_Expr(op1);
02775 FmtAssert(!WN_has_side_effects(a) && !WN_has_side_effects(b),
02776 ("Addr of MIN/MAX_EXPR with side effects not yet supported"));
02777
02778 #if 0 // GCC's same_type_p is not duplicated in wgen because it is too
02779
02780 FmtAssert(gs_same_type_p(gs_tree_type(op0), gs_tree_type(op1)),
02781 ("Types of MIN/MAX_EXPR operands differ"));
02782 #endif
02783 TY_IDX ptr_ty = Make_Pointer_Type (Get_TY(gs_tree_type(op0)), FALSE);
02784 TYPE_ID ptr_mtype = TY_mtype(ptr_ty);
02785 TY_IDX arg_ty = Get_TY(gs_tree_type(gs_tree_operand(arg0, 0)));
02786 TYPE_ID arg_mtype = TY_mtype(arg_ty);
02787
02788 WN* aptr = WGEN_Address_Of(op0);
02789 WN* bptr = WGEN_Address_Of(op1);
02790 wn = WN_Select(Widen_Mtype(ptr_mtype),
02791 WN_Relational(code0 == GS_MIN_EXPR ? OPR_LT : OPR_GT,
02792 Widen_Mtype(arg_mtype),
02793 a, b),
02794 aptr, bptr);
02795 Set_PU_has_very_high_whirl (Get_Current_PU ());
02796 }
02797 break;
02798
02799 case GS_COMPONENT_REF:
02800 {
02801 wn = WGEN_Expand_Expr (arg0);
02802 ty_idx = Get_TY(gs_tree_type(arg0));
02803 WN *comma = NULL;
02804 if (WN_operator(wn) == OPR_COMMA) {
02805 comma = wn;
02806 wn = WN_kid1(wn);
02807 }
02808 if (WN_operator (wn) == OPR_LDID) {
02809 WN_set_operator (wn, OPR_LDA);
02810 WN_set_rtype(wn, Pointer_Mtype);
02811 WN_set_desc (wn, MTYPE_V);
02812 WN_set_ty (wn, Make_Pointer_Type(WN_ty(wn)));
02813 }
02814 else
02815 if (WN_operator (wn) == OPR_ILOAD) {
02816 wn0 = WN_kid0 (wn);
02817 wn1 = WN_Intconst (Pointer_Mtype, WN_offset (wn));
02818 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn0, wn1);
02819 }
02820 else
02821 Fail_FmtAssertion ("WGEN_Address_Of has unhandled %s",
02822 gs_code_name(code0));
02823 if (comma) {
02824 WN_set_rtype(comma, WN_rtype(wn));
02825 wn = comma;
02826 }
02827 }
02828 break;
02829
02830 #ifdef KEY // bug 3228
02831 case GS_ARRAY_REF:
02832 wn = WGEN_Expand_Expr (arg0);
02833 if (WN_operator(wn) == OPR_ILOAD)
02834 wn = WN_kid0(wn);
02835 ty_idx = Get_TY(gs_tree_type(arg0));
02836 break;
02837 #endif
02838
02839 #ifdef KEY
02840 case GS_COMPOUND_LITERAL_EXPR:
02841 {
02842 arg0 = gs_decl_initial (gs_tree_operand (gs_tree_operand (arg0, 0), 0));
02843 st = WGEN_Generate_Temp_For_Initialized_Aggregate (arg0, "");
02844
02845 if (CURRENT_SYMTAB == GLOBAL_SYMTAB)
02846 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02847 else {
02848
02849
02850 ST *copy = New_ST(CURRENT_SYMTAB);
02851 ST_Init(copy, Save_Str(".cpfrominit"), CLASS_VAR, SCLASS_AUTO,
02852 EXPORT_LOCAL, ST_type(st));
02853 WN *init_wn = WN_CreateLdid(OPR_LDID, MTYPE_M, MTYPE_M, 0, st,
02854 ST_type(st));
02855 WGEN_Stmt_Append( WN_CreateStid(OPR_STID, MTYPE_V, MTYPE_M,
02856 0, copy, ST_type(copy), init_wn),
02857 Get_Srcpos());
02858
02859 wn = WN_Lda (Pointer_Mtype, ST_ofst(copy), copy);
02860 }
02861 }
02862 break;
02863
02864
02865 case GS_SAVE_EXPR:
02866 {
02867 st = WN_st (WGEN_Expand_Expr (arg0));
02868 wn = WN_Lda (Pointer_Mtype, ST_ofst (st), st);
02869 }
02870 break;
02871
02872
02873 case GS_REALPART_EXPR:
02874 {
02875 wn = WGEN_Expand_Expr (gs_tree_operand (arg0, 0));
02876 if (WN_operator (wn) == OPR_ILOAD)
02877 wn = WN_kid0 (wn);
02878 else if (WN_operator (wn) == OPR_LDID)
02879 wn = WN_Lda (Pointer_Mtype, WN_offset(wn), WN_st(wn));
02880 else Fail_FmtAssertion ("WGEN_Address_Of: NYI for REALPART_EXPR");
02881 }
02882 break;
02883
02884 case GS_IMAGPART_EXPR:
02885 {
02886 wn = WGEN_Expand_Expr (gs_tree_operand (arg0, 0));
02887 if (WN_operator (wn) == OPR_ILOAD)
02888 {
02889 wn0 = WN_kid0 (wn);
02890 TYPE_ID imag_mtype;
02891 switch (WN_rtype (wn))
02892 {
02893 case MTYPE_C4:
02894 imag_mtype = MTYPE_F4;
02895 break;
02896 case MTYPE_C8:
02897 imag_mtype = MTYPE_F8;
02898 break;
02899 #ifdef TARG_IA64
02900 case MTYPE_C10:
02901 imag_mtype = MTYPE_F10;
02902 break;
02903 #else
02904 case MTYPE_CQ:
02905 imag_mtype = MTYPE_FQ;
02906 break;
02907 #endif
02908 default:
02909 Fail_FmtAssertion ("WGEN_Address_Of: Unexpected rtype in IMAGPART_EXPR");
02910 }
02911 INT ofst;
02912 if (imag_mtype == MTYPE_FQ)
02913 {
02914 #ifdef TARG_X8664
02915 if (Is_Target_32bit()) ofst = 12; else
02916 #endif // TARG_X8664
02917 ofst = 16;
02918 }
02919 else ofst = MTYPE_byte_size (imag_mtype);
02920
02921 wn1 = WN_Intconst (Pointer_Mtype, ofst);
02922 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn0, wn1);
02923 }
02924 else if (WN_operator (wn) == OPR_LDID)
02925 wn = WN_Lda (Pointer_Mtype,
02926 WN_offset(wn) + MTYPE_byte_size(WN_rtype(wn)) / 2,
02927 WN_st(wn));
02928 else Fail_FmtAssertion ("WGEN_Address_Of: NYI for IMAGPART_EXPR");
02929 }
02930 break;
02931
02932 case GS_BASELINK:
02933 wn = WGEN_Address_Of (gs_baselink_functions (arg0));
02934 break;
02935
02936 case GS_CONST_DECL:
02937 st = WGEN_Generate_Temp_For_Initialized_Aggregate
02938 (gs_decl_initial (arg0), "");
02939 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
02940 break;
02941 #endif
02942
02943 default:
02944 {
02945 Fail_FmtAssertion ("WGEN_Address_Of: Unexpected operand %s",
02946 gs_code_name(code0));
02947 }
02948 break;
02949 }
02950
02951 FmtAssert(wn != 0, ("WGEN_Address_Of: null WHIRL tree for %s",
02952 gs_code_name(code0)));
02953 return wn;
02954 }
02955
02956 #ifdef TARG_X8664
02957
02958
02959
02960
02961
02962 static WN *WGEN_x8664_va_arg(WN *ap_wn, BOOL isfloat, TY_IDX ty_idx, BOOL twice)
02963 {
02964
02965 WN *wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4),
02966 WN_CopyNode(ap_wn));
02967 WN *wn1 = WN_Intconst(MTYPE_I4, (!isfloat ? 48 : 176) - (twice ? 8 : 0));
02968 WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
02969 LABEL_IDX lab1;
02970 New_LABEL (CURRENT_SYMTAB, lab1);
02971 WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
02972 wn = WN_CreateTruebr(lab1, wn);
02973 WGEN_Stmt_Append (wn, Get_Srcpos ());
02974
02975 ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
02976 #ifdef FE_GNU_4_2_0
02977 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
02978 #endif
02979
02980 wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4),
02981 WN_CopyNode(ap_wn));
02982 wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype),
02983 WN_CopyNode(ap_wn));
02984 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
02985 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
02986 WGEN_Stmt_Append (wn, Get_Srcpos ());
02987
02988
02989 wn0 = WN_Iload(MTYPE_I4, !isfloat ? 0 : 4, MTYPE_To_TY(MTYPE_I4),
02990 WN_CopyNode(ap_wn));
02991 wn1 = WN_Intconst(MTYPE_I4, (!isfloat ? 8 : 16) * ((INT)twice+1));
02992 wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
02993 wn = WN_Istore(MTYPE_I4, !isfloat ? 0 : 4,
02994 Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
02995 WN_CopyNode(ap_wn), wn);
02996 WGEN_Stmt_Append (wn, Get_Srcpos ());
02997
02998
02999 LABEL_IDX lab2;
03000 New_LABEL (CURRENT_SYMTAB, lab2);
03001 WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03002 wn = WN_CreateGoto(lab2);
03003 WGEN_Stmt_Append (wn, Get_Srcpos ());
03004
03005 WGEN_Stmt_Append (lab1_wn, Get_Srcpos ());
03006
03007
03008 wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx),
03009 WN_CopyNode(ap_wn));
03010 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03011 WGEN_Stmt_Append (wn, Get_Srcpos ());
03012
03013
03014 wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype),
03015 WN_CopyNode(ap_wn));
03016 wn1 = WN_Intconst(MTYPE_U8, twice ? 16 : 8);
03017 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03018 wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03019 WN_CopyNode(ap_wn), wn);
03020 WGEN_Stmt_Append (wn, Get_Srcpos ());
03021
03022 WGEN_Stmt_Append (lab2_wn, Get_Srcpos ());
03023
03024 return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03025 }
03026
03027
03028
03029
03030
03031
03032 static WN *WGEN_x8664_va_arg_2_mixed(WN *ap_wn, BOOL isfloat0, BOOL isfloat1,
03033 TY_IDX ty_idx)
03034 {
03035
03036 WN *wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03037 WN *wn1 = WN_Intconst(MTYPE_I4, 48);
03038 WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03039 LABEL_IDX lab1;
03040 New_LABEL (CURRENT_SYMTAB, lab1);
03041 WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
03042 wn = WN_CreateTruebr(lab1, wn);
03043 WGEN_Stmt_Append (wn, Get_Srcpos ());
03044
03045 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03046 wn1 = WN_Intconst(MTYPE_I4, 176);
03047 wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03048 wn = WN_CreateTruebr(lab1, wn);
03049 WGEN_Stmt_Append (wn, Get_Srcpos ());
03050
03051
03052 ST *struct_temp_st = Gen_Temp_Symbol(ty_idx, ".va_arg_struct");
03053 #ifdef FE_GNU_4_2_0
03054 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, struct_temp_st);
03055 #endif
03056
03057
03058
03059 wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03060 wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype),
03061 WN_CopyNode(ap_wn));
03062 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03063 wn = WN_Iload(MTYPE_I8, 0, MTYPE_To_TY(MTYPE_I8), wn);
03064 wn = WN_Stid(MTYPE_I8, isfloat0 ? 8 : 0, struct_temp_st,
03065 MTYPE_To_TY(MTYPE_I8), wn);
03066 WGEN_Stmt_Append (wn, Get_Srcpos ());
03067
03068
03069 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03070 wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype),
03071 WN_CopyNode(ap_wn));
03072 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03073 wn = WN_Iload(MTYPE_F8, 0, MTYPE_To_TY(MTYPE_F8), wn);
03074 wn = WN_Stid(MTYPE_F8, isfloat0 ? 0 : 8, struct_temp_st,
03075 MTYPE_To_TY(MTYPE_F8), wn);
03076 WGEN_Stmt_Append (wn, Get_Srcpos ());
03077
03078
03079 wn0 = WN_Iload(MTYPE_I4, 0, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03080 wn1 = WN_Intconst(MTYPE_I4, 8);
03081 wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03082 wn = WN_Istore(MTYPE_I4, 0, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
03083 WN_CopyNode(ap_wn), wn);
03084 WGEN_Stmt_Append (wn, Get_Srcpos ());
03085
03086 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03087 wn1 = WN_Intconst(MTYPE_I4, 16);
03088 wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03089 wn = WN_Istore(MTYPE_I4, 4, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
03090 WN_CopyNode(ap_wn), wn);
03091 WGEN_Stmt_Append (wn, Get_Srcpos ());
03092
03093
03094 ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
03095 #ifdef FE_GNU_4_2_0
03096 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
03097 #endif
03098 wn = WN_Lda(Pointer_Mtype, 0, struct_temp_st, 0);
03099 Set_ST_addr_saved(struct_temp_st);
03100 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
03101 WGEN_Stmt_Append (wn, Get_Srcpos ());
03102
03103
03104 LABEL_IDX lab2;
03105 New_LABEL (CURRENT_SYMTAB, lab2);
03106 WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03107 wn = WN_CreateGoto(lab2);
03108 WGEN_Stmt_Append (wn, Get_Srcpos ());
03109
03110 WGEN_Stmt_Append (lab1_wn, Get_Srcpos ());
03111
03112
03113 wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx),
03114 WN_CopyNode(ap_wn));
03115 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03116 WGEN_Stmt_Append (wn, Get_Srcpos ());
03117
03118
03119 wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype),
03120 WN_CopyNode(ap_wn));
03121 wn1 = WN_Intconst(MTYPE_U8, 16);
03122 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03123 wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03124 WN_CopyNode(ap_wn), wn);
03125 WGEN_Stmt_Append (wn, Get_Srcpos ());
03126
03127 WGEN_Stmt_Append (lab2_wn, Get_Srcpos ());
03128
03129 return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03130 }
03131
03132
03133
03134
03135
03136
03137 static WN *WGEN_x8664_va_arg_2_float(WN *ap_wn, TY_IDX ty_idx)
03138 {
03139 LABEL_IDX lab1;
03140 New_LABEL (CURRENT_SYMTAB, lab1);
03141 WN *lab1_wn = WN_CreateLabel ((ST_IDX) 0, lab1, 0, NULL);
03142
03143 WN *wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03144 WN *wn1 = WN_Intconst(MTYPE_I4, 160);
03145 WN *wn = WN_Relational(OPR_GE, MTYPE_I4, wn0, wn1);
03146 wn = WN_CreateTruebr(lab1, wn);
03147 WGEN_Stmt_Append (wn, Get_Srcpos ());
03148
03149
03150 ST *struct_temp_st = Gen_Temp_Symbol(ty_idx, ".va_arg_struct");
03151 #ifdef FE_GNU_4_2_0
03152 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, struct_temp_st);
03153 #endif
03154
03155
03156
03157 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03158 wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype),
03159 WN_CopyNode(ap_wn));
03160 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03161 wn = WN_Iload(MTYPE_F8, 0, MTYPE_To_TY(MTYPE_F8), wn);
03162 wn = WN_Stid(MTYPE_F8, 0, struct_temp_st, MTYPE_To_TY(MTYPE_F8), wn);
03163 WGEN_Stmt_Append (wn, Get_Srcpos ());
03164
03165
03166 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03167 wn1 = WN_Iload(Pointer_Mtype, 16, MTYPE_To_TY(Pointer_Mtype),
03168 WN_CopyNode(ap_wn));
03169 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03170 wn = WN_Iload(MTYPE_F8, 16, MTYPE_To_TY(MTYPE_F8), wn);
03171 wn = WN_Stid(MTYPE_F8, 8, struct_temp_st, MTYPE_To_TY(MTYPE_F8), wn);
03172 WGEN_Stmt_Append (wn, Get_Srcpos ());
03173
03174
03175 wn0 = WN_Iload(MTYPE_I4, 4, MTYPE_To_TY(MTYPE_I4), WN_CopyNode(ap_wn));
03176 wn1 = WN_Intconst(MTYPE_I4, 32);
03177 wn = WN_Binary(OPR_ADD, MTYPE_I4, wn0, wn1);
03178 wn = WN_Istore(MTYPE_I4, 4, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
03179 WN_CopyNode(ap_wn), wn);
03180 WGEN_Stmt_Append (wn, Get_Srcpos ());
03181
03182
03183 ST *arg_temp_st = Gen_Temp_Symbol(Make_Pointer_Type(ty_idx), ".va_arg");
03184 #ifdef FE_GNU_4_2_0
03185 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, arg_temp_st);
03186 #endif
03187 wn = WN_Lda(Pointer_Mtype, 0, struct_temp_st, 0);
03188 Set_ST_addr_saved(struct_temp_st);
03189 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn);
03190 WGEN_Stmt_Append (wn, Get_Srcpos ());
03191
03192
03193 LABEL_IDX lab2;
03194 New_LABEL (CURRENT_SYMTAB, lab2);
03195 WN *lab2_wn = WN_CreateLabel ((ST_IDX) 0, lab2, 0, NULL);
03196 wn = WN_CreateGoto(lab2);
03197 WGEN_Stmt_Append (wn, Get_Srcpos ());
03198
03199 WGEN_Stmt_Append (lab1_wn, Get_Srcpos ());
03200
03201
03202 wn0 = WN_Iload(Pointer_Mtype, 8, Make_Pointer_Type(ty_idx),
03203 WN_CopyNode(ap_wn));
03204 wn = WN_Stid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx), wn0);
03205 WGEN_Stmt_Append (wn, Get_Srcpos ());
03206
03207
03208 wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype),
03209 WN_CopyNode(ap_wn));
03210 wn1 = WN_Intconst(MTYPE_U8, 16);
03211 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
03212 wn = WN_Istore(Pointer_Mtype, 8,Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
03213 WN_CopyNode(ap_wn), wn);
03214 WGEN_Stmt_Append (wn, Get_Srcpos ());
03215
03216 WGEN_Stmt_Append (lab2_wn, Get_Srcpos ());
03217
03218 return WN_Ldid(Pointer_Mtype, 0, arg_temp_st, Make_Pointer_Type(ty_idx));
03219 }
03220 #endif
03221
03222 static bool inside_eh_region = false;
03223
03224 void
03225 Setup_EH_Region (bool for_unwinding)
03226 {
03227 WN * region_body;
03228
03229 if (for_unwinding)
03230 region_body = WGEN_Stmt_Pop (wgen_stmk_region_body);
03231 else
03232 {
03233 region_body = WGEN_Stmt_Pop (wgen_stmk_call_region_body);
03234 inside_eh_region = false;
03235 }
03236 INITV_IDX iv;
03237 LABEL_IDX pad = 0;
03238
03239 if (!for_unwinding) pad = lookup_cleanups (iv);
03240 else
03241 {
03242 iv = New_INITV();
03243 INITV_Set_ZERO (Initv_Table[iv], MTYPE_U4, 1);
03244 }
03245
03246 INITV_IDX initv_label = New_INITV();
03247 if (pad)
03248 INITV_Init_Label (initv_label, pad, 1);
03249 else
03250 INITV_Set_ZERO (Initv_Table[initv_label], MTYPE_U4, 1);
03251 INITV_IDX blk = New_INITV();
03252 INITV_Init_Block (blk, initv_label);
03253
03254 Set_INITV_next (initv_label, iv);
03255
03256 TY_IDX ty = MTYPE_TO_TY_array[MTYPE_U4];
03257 ST * ereg = Gen_Temp_Named_Symbol (ty, "dummy1", CLASS_VAR,
03258 SCLASS_EH_REGION_SUPP);
03259 Set_ST_is_initialized (*ereg);
03260 Set_ST_is_not_used (*ereg);
03261 INITO_IDX ereg_supp = New_INITO (ST_st_idx(ereg), blk);
03262
03263 WGEN_Stmt_Append (WN_CreateRegion (REGION_KIND_EH, region_body,
03264 WN_CreateBlock(), WN_CreateBlock(), New_Region_Id(), ereg_supp), Get_Srcpos());
03265 Set_PU_has_region (Get_Current_PU());
03266 Set_PU_has_exc_scopes (Get_Current_PU());
03267
03268 #ifdef TARG_IA64
03269
03270
03271
03272
03273 TY_IDX tyi;
03274 TY& zty = New_TY (tyi);
03275 UINT inito_size = Get_INITO_Size(ereg_supp);
03276 TY_Init (zty, inito_size, KIND_STRUCT, MTYPE_M,ereg->u1.name_idx);
03277 Set_TY_align (tyi, 4);
03278 ST_Init (ereg, TY_name_idx (zty),
03279 CLASS_VAR, SCLASS_EH_REGION_SUPP, EXPORT_LOCAL, tyi);
03280 Set_ST_is_initialized (ereg);
03281 #endif
03282 }
03283
03284 static TY_IDX
03285 get_field_type (TY_IDX struct_type, UINT field_id)
03286 {
03287 Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
03288 UINT cur_field_id = 0;
03289 FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
03290 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
03291 field_id, struct_type));
03292 return FLD_type (fld);
03293 }
03294
03295 #ifdef TARG_X8664
03296
03297 static WN *
03298 WGEN_target_builtins (gs_t exp, INTRINSIC * iopc, BOOL * intrinsic_op)
03299 {
03300 WN * wn = NULL;
03301
03302
03303 *intrinsic_op = TRUE;
03304
03305 gs_t func = gs_tree_operand (gs_tree_operand (exp, 0), 0);
03306 Is_True (gs_tree_code (func) == GS_FUNCTION_DECL && gs_decl_built_in (func) &&
03307 gs_decl_built_in_class(func) == GSBI_CLASS_BUILT_IN_MD,
03308 ("Invalid tree node"));
03309
03310 unsigned int ins_code = gs_decl_function_code (func);
03311 TYPE_ID res_type = TY_mtype(Get_TY(gs_tree_type(exp)));
03312 gs_t t_list = gs_tree_operand (exp, 1);
03313 WN * arg0 = NULL, * arg1 = NULL;
03314 if (t_list)
03315 {
03316
03317 arg0 = WGEN_Expand_Expr (gs_tree_value (t_list));
03318 if (gs_tree_chain (t_list))
03319 arg1 = WGEN_Expand_Expr (gs_tree_value (gs_tree_chain (t_list)));
03320 }
03321
03322 switch (ins_code)
03323 {
03324
03325 case GSBI_IX86_BUILTIN_PADDB:
03326 case GSBI_IX86_BUILTIN_PADDW:
03327 case GSBI_IX86_BUILTIN_PADDD:
03328 case GSBI_IX86_BUILTIN_PADDQ:
03329 case GSBI_IX86_BUILTIN_ADDPD:
03330 case GSBI_IX86_BUILTIN_PADDB128:
03331 case GSBI_IX86_BUILTIN_PADDQ128:
03332 wn = WN_Add (res_type, arg0, arg1);
03333 *intrinsic_op = FALSE;
03334 break;
03335 case GSBI_IX86_BUILTIN_PSUBB:
03336 case GSBI_IX86_BUILTIN_PSUBW:
03337 case GSBI_IX86_BUILTIN_PSUBD:
03338 case GSBI_IX86_BUILTIN_PSUBQ:
03339 case GSBI_IX86_BUILTIN_SUBPD:
03340 case GSBI_IX86_BUILTIN_PSUBB128:
03341 case GSBI_IX86_BUILTIN_PSUBW128:
03342 case GSBI_IX86_BUILTIN_PSUBD128:
03343 case GSBI_IX86_BUILTIN_PSUBQ128:
03344 wn = WN_Sub (res_type, arg0, arg1);
03345 *intrinsic_op = FALSE;
03346 break;
03347 #if 0
03348 case GSBI_IX86_BUILTIN_PAND:
03349 if (MTYPE_is_mmx_vector(res_type))
03350 goto unsupported;
03351 wn = WN_Band (res_type, arg0, arg1);
03352 *intrinsic_op = FALSE;
03353 break;
03354 case GSBI_IX86_BUILTIN_PANDN:
03355 if (MTYPE_is_mmx_vector(res_type))
03356 goto unsupported;
03357 wn = WN_Band (res_type, WN_Bnot (res_type, arg0), arg1);
03358 *intrinsic_op = FALSE;
03359 break;
03360 case GSBI_IX86_BUILTIN_POR:
03361 if (MTYPE_is_mmx_vector(res_type))
03362 goto unsupported;
03363 wn = WN_Bior (res_type, arg0, arg1);
03364 *intrinsic_op = FALSE;
03365 break;
03366 case GSBI_IX86_BUILTIN_PXOR:
03367 if (MTYPE_is_mmx_vector(res_type))
03368 goto unsupported;
03369 wn = WN_Bxor (res_type, arg0, arg1);
03370 *intrinsic_op = FALSE;
03371 break;
03372 #endif
03373 case GSBI_IX86_BUILTIN_PSLLQ:
03374 if (MTYPE_is_mmx_vector(res_type))
03375 goto unsupported;
03376 wn = WN_Shl (res_type, arg0, arg1);
03377 *intrinsic_op = FALSE;
03378 break;
03379 case GSBI_IX86_BUILTIN_PSRLQ:
03380 if (MTYPE_is_mmx_vector(res_type))
03381 goto unsupported;
03382 wn = WN_Lshr (res_type, arg0, arg1);
03383 *intrinsic_op = FALSE;
03384 break;
03385
03386
03387 case GSBI_IX86_BUILTIN_PADDSB:
03388 *iopc = INTRN_PADDSB;
03389 break;
03390 case GSBI_IX86_BUILTIN_PADDSW:
03391 *iopc = INTRN_PADDSW;
03392 break;
03393 case GSBI_IX86_BUILTIN_PADDD128:
03394 *iopc = INTRN_PADDD128;
03395 break;
03396 case GSBI_IX86_BUILTIN_PADDW128:
03397 *iopc = INTRN_PADDW128;
03398 break;
03399 case GSBI_IX86_BUILTIN_PSUBSB:
03400 *iopc = INTRN_PSUBSB;
03401 break;
03402 case GSBI_IX86_BUILTIN_PSUBSW:
03403 *iopc = INTRN_PSUBSW;
03404 break;
03405 case GSBI_IX86_BUILTIN_PADDUSB:
03406 *iopc = INTRN_PADDUSB;
03407 break;
03408 case GSBI_IX86_BUILTIN_PADDUSW:
03409 *iopc = INTRN_PADDUSW;
03410 break;
03411 case GSBI_IX86_BUILTIN_PSUBUSB:
03412 case GSBI_IX86_BUILTIN_PSUBUSB128:
03413 *iopc = INTRN_PSUBUSB;
03414 break;
03415 case GSBI_IX86_BUILTIN_PSUBUSW:
03416 case GSBI_IX86_BUILTIN_PSUBUSW128:
03417 *iopc = INTRN_PSUBUSW;
03418 break;
03419 case GSBI_IX86_BUILTIN_PMULLW:
03420 *iopc = INTRN_PMULLW;
03421 break;
03422 case GSBI_IX86_BUILTIN_PMULHW:
03423 case GSBI_IX86_BUILTIN_PMULHW128:
03424 *iopc = INTRN_PMULHW;
03425 break;
03426 case GSBI_IX86_BUILTIN_PCMPEQB:
03427 *iopc = INTRN_PCMPEQB;
03428 break;
03429 case GSBI_IX86_BUILTIN_PCMPEQW:
03430 case GSBI_IX86_BUILTIN_PCMPEQW128:
03431 *iopc = INTRN_PCMPEQW;
03432 break;
03433 case GSBI_IX86_BUILTIN_PCMPEQD:
03434 *iopc = INTRN_PCMPEQD;
03435 break;
03436 case GSBI_IX86_BUILTIN_PCMPGTB:
03437 *iopc = INTRN_PCMPGTB;
03438 break;
03439 case GSBI_IX86_BUILTIN_PCMPGTW:
03440 *iopc = INTRN_PCMPGTW;
03441 break;
03442 case GSBI_IX86_BUILTIN_PCMPGTD:
03443 *iopc = INTRN_PCMPGTD;
03444 break;
03445 case GSBI_IX86_BUILTIN_PUNPCKHBW:
03446 *iopc = INTRN_PUNPCKHBW;
03447 break;
03448 case GSBI_IX86_BUILTIN_PUNPCKHWD:
03449 *iopc = INTRN_PUNPCKHWD;
03450 break;
03451 case GSBI_IX86_BUILTIN_PUNPCKHDQ:
03452 *iopc = INTRN_PUNPCKHDQ;
03453 break;
03454 case GSBI_IX86_BUILTIN_PUNPCKLBW:
03455 case GSBI_IX86_BUILTIN_PUNPCKLBW128:
03456 *iopc = INTRN_PUNPCKLBW;
03457 break;
03458 case GSBI_IX86_BUILTIN_PUNPCKLWD:
03459 *iopc = INTRN_PUNPCKLWD;
03460 break;
03461 case GSBI_IX86_BUILTIN_PUNPCKLDQ:
03462 *iopc = INTRN_PUNPCKLDQ;
03463 break;
03464 case GSBI_IX86_BUILTIN_PACKSSWB:
03465 *iopc = INTRN_PACKSSWB;
03466 break;
03467 case GSBI_IX86_BUILTIN_PACKSSDW:
03468 case GSBI_IX86_BUILTIN_PACKSSDW128:
03469 *iopc = INTRN_PACKSSDW;
03470 break;
03471 case GSBI_IX86_BUILTIN_PACKUSWB:
03472 case GSBI_IX86_BUILTIN_PACKUSWB128:
03473 *iopc = INTRN_PACKUSWB;
03474 break;
03475 case GSBI_IX86_BUILTIN_PMULHUW:
03476 *iopc = INTRN_PMULHUW;
03477 break;
03478 case GSBI_IX86_BUILTIN_PAVGB:
03479 *iopc = INTRN_PAVGB;
03480 break;
03481 case GSBI_IX86_BUILTIN_PAVGW:
03482 *iopc = INTRN_PAVGW;
03483 break;
03484 case GSBI_IX86_BUILTIN_PSADBW:
03485 *iopc = INTRN_PSADBW;
03486 break;
03487 case GSBI_IX86_BUILTIN_PMAXUB:
03488 *iopc = INTRN_PMAXUB;
03489 break;
03490 case GSBI_IX86_BUILTIN_PMAXSW:
03491 *iopc = INTRN_PMAXSW;
03492 break;
03493 case GSBI_IX86_BUILTIN_PMINUB:
03494 *iopc = INTRN_PMINUB;
03495 break;
03496 case GSBI_IX86_BUILTIN_PMINSW:
03497 *iopc = INTRN_PMINSW;
03498 break;
03499 #if 0 // wgen TODO
03500 case GSBI_IX86_BUILTIN_PEXTRW:
03501 {
03502 Is_True (gs_tree_code (gs_tree_value (gs_tree_chain (t_list))) == GS_INTEGER_CST,
03503 ("Immediate value required by pextrw"));
03504 UINT val = gs_get_integer_value(gs_tree_value (gs_tree_chain (t_list)));
03505 switch (val)
03506 {
03507 case 0:
03508 *iopc = INTRN_PEXTRW0;
03509 break;
03510 case 1:
03511 *iopc = INTRN_PEXTRW1;
03512 break;
03513 case 2:
03514 *iopc = INTRN_PEXTRW2;
03515 break;
03516 case 3:
03517 *iopc = INTRN_PEXTRW3;
03518 break;
03519 default:
03520 Fail_FmtAssertion ("Invalid imm value %d to pextrw", val);
03521 }
03522 TY_IDX arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(t_list)));
03523 TYPE_ID arg_mtype = TY_mtype(arg_ty_idx);
03524 arg0 = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
03525 arg_ty_idx, WN_PARM_BY_VALUE);
03526 wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, MTYPE_U4, MTYPE_V,
03527 *iopc, 1, &arg0);
03528 break;
03529 }
03530 case GSBI_IX86_BUILTIN_PINSRW:
03531 {
03532 Is_True (gs_tree_code (gs_tree_value (gs_tree_chain (gs_tree_chain (t_list)))) == GS_INTEGER_CST, ("Immediate value required by pinsrw"));
03533 UINT val = gs_get_integer_value(gs_tree_value (gs_tree_chain (gs_tree_chain (t_list))));
03534 switch (val)
03535 {
03536 case 0:
03537 *iopc = INTRN_PINSRW0;
03538 break;
03539 case 1:
03540 *iopc = INTRN_PINSRW1;
03541 break;
03542 case 2:
03543 *iopc = INTRN_PINSRW2;
03544 break;
03545 case 3:
03546 *iopc = INTRN_PINSRW3;
03547 break;
03548 default:
03549 Fail_FmtAssertion ("Invalid imm value %d to pinsrw", val);
03550
03551 }
03552 WN * args[2];
03553 for (int c=0; c<2; c++)
03554 {
03555 TY_IDX arg_ty_idx = Get_TY (gs_tree_type (gs_tree_value (t_list)));
03556 TYPE_ID arg_mtype = TY_mtype (arg_ty_idx);
03557 args[c] = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
03558 arg_ty_idx, WN_PARM_BY_VALUE);
03559 t_list = gs_tree_chain (t_list);
03560 arg0 = arg1;
03561 }
03562
03563 wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, MTYPE_M8I2, MTYPE_V,
03564 *iopc, 2, args);
03565 break;
03566 }
03567 #endif
03568 case GSBI_IX86_BUILTIN_PMOVMSKB:
03569 *iopc = INTRN_PMOVMSKB;
03570 break;
03571 case GSBI_IX86_BUILTIN_PMOVMSKB128:
03572 *iopc = INTRN_PMOVMSKB128;
03573 break;
03574 case GSBI_IX86_BUILTIN_ADDPS:
03575 *iopc = INTRN_ADDPS;
03576 break;
03577 case GSBI_IX86_BUILTIN_SUBPS:
03578 *iopc = INTRN_SUBPS;
03579 break;
03580 case GSBI_IX86_BUILTIN_MULPS:
03581 *iopc = INTRN_MULPS;
03582 break;
03583 case GSBI_IX86_BUILTIN_DIVPS:
03584 *iopc = INTRN_DIVPS;
03585 break;
03586 case GSBI_IX86_BUILTIN_ADDSS:
03587 *iopc = INTRN_ADDSS;
03588 break;
03589 case GSBI_IX86_BUILTIN_SUBSS:
03590 *iopc = INTRN_SUBSS;
03591 break;
03592 case GSBI_IX86_BUILTIN_MULSS:
03593 *iopc = INTRN_MULSS;
03594 break;
03595 case GSBI_IX86_BUILTIN_DIVSS:
03596 *iopc = INTRN_DIVSS;
03597 break;
03598 case GSBI_IX86_BUILTIN_CMPEQPS:
03599 *iopc = INTRN_CMPEQPS;
03600 break;
03601 case GSBI_IX86_BUILTIN_CMPLTPS:
03602 *iopc = INTRN_CMPLTPS;
03603 break;
03604 case GSBI_IX86_BUILTIN_CMPLEPS:
03605 *iopc = INTRN_CMPLEPS;
03606 break;
03607 case GSBI_IX86_BUILTIN_CMPGTPS:
03608 *iopc = INTRN_CMPGTPS;
03609 break;
03610 case GSBI_IX86_BUILTIN_CMPGEPS:
03611 *iopc = INTRN_CMPGEPS;
03612 break;
03613 case GSBI_IX86_BUILTIN_CMPUNORDPS:
03614 *iopc = INTRN_CMPUNORDPS;
03615 break;
03616 case GSBI_IX86_BUILTIN_CMPNEQPS:
03617 *iopc = INTRN_CMPNEQPS;
03618 break;
03619 case GSBI_IX86_BUILTIN_CMPNLTPS:
03620 *iopc = INTRN_CMPNLTPS;
03621 break;
03622 case GSBI_IX86_BUILTIN_CMPNLEPS:
03623 *iopc = INTRN_CMPNLEPS;
03624 break;
03625 case GSBI_IX86_BUILTIN_CMPNGTPS:
03626 *iopc = INTRN_CMPNGTPS;
03627 break;
03628 case GSBI_IX86_BUILTIN_CMPNGEPS:
03629 *iopc = INTRN_CMPNGEPS;
03630 break;
03631 case GSBI_IX86_BUILTIN_CMPORDPS:
03632 *iopc = INTRN_CMPORDPS;
03633 break;
03634 case GSBI_IX86_BUILTIN_CMPEQSS:
03635 *iopc = INTRN_CMPEQSS;
03636 break;
03637 case GSBI_IX86_BUILTIN_CMPLTSS:
03638 *iopc = INTRN_CMPLTSS;
03639 break;
03640 case GSBI_IX86_BUILTIN_CMPLESS:
03641 *iopc = INTRN_CMPLESS;
03642 break;
03643 case GSBI_IX86_BUILTIN_CMPUNORDSS:
03644 *iopc = INTRN_CMPUNORDSS;
03645 break;
03646 case GSBI_IX86_BUILTIN_CMPNEQSS:
03647 *iopc = INTRN_CMPNEQSS;
03648 break;
03649 case GSBI_IX86_BUILTIN_CMPNLTSS:
03650 *iopc = INTRN_CMPNLTSS;
03651 break;
03652 case GSBI_IX86_BUILTIN_CMPNLESS:
03653 *iopc = INTRN_CMPNLESS;
03654 break;
03655 case GSBI_IX86_BUILTIN_CMPORDSS:
03656 *iopc = INTRN_CMPORDSS;
03657 break;
03658 case GSBI_IX86_BUILTIN_MAXPS:
03659 *iopc = INTRN_MAXPS;
03660 break;
03661 case GSBI_IX86_BUILTIN_MAXSS:
03662 *iopc = INTRN_MAXSS;
03663 break;
03664 case GSBI_IX86_BUILTIN_MINPS:
03665 *iopc = INTRN_MINPS;
03666 break;
03667 case GSBI_IX86_BUILTIN_MINSS:
03668 *iopc = INTRN_MINSS;
03669 break;
03670 case GSBI_IX86_BUILTIN_ANDPS:
03671 *iopc = INTRN_ANDPS;
03672 break;
03673 case GSBI_IX86_BUILTIN_ANDNPS:
03674 *iopc = INTRN_ANDNPS;
03675 break;
03676 case GSBI_IX86_BUILTIN_ORPS:
03677 *iopc = INTRN_ORPS;
03678 break;
03679 case GSBI_IX86_BUILTIN_XORPS:
03680 *iopc = INTRN_XORPS;
03681 break;
03682 case GSBI_IX86_BUILTIN_MOVSS:
03683 *iopc = INTRN_MOVSS;
03684 break;
03685 case GSBI_IX86_BUILTIN_MOVSD:
03686 *iopc = INTRN_MOVSD;
03687 break;
03688 case GSBI_IX86_BUILTIN_MOVHLPS:
03689 *iopc = INTRN_MOVHLPS;
03690 break;
03691 case GSBI_IX86_BUILTIN_MOVLHPS:
03692 *iopc = INTRN_MOVLHPS;
03693 break;
03694 case GSBI_IX86_BUILTIN_UNPCKHPS:
03695 *iopc = INTRN_UNPCKHPS;
03696 break;
03697 case GSBI_IX86_BUILTIN_UNPCKLPS:
03698 *iopc = INTRN_UNPCKLPS;
03699 break;
03700 case GSBI_IX86_BUILTIN_RCPPS:
03701 *iopc = INTRN_RCPPS;
03702 break;
03703 case GSBI_IX86_BUILTIN_RSQRTPS:
03704 *iopc = INTRN_RSQRTPS;
03705 break;
03706 case GSBI_IX86_BUILTIN_SQRTPS:
03707 *iopc = INTRN_SQRTPS;
03708 break;
03709 case GSBI_IX86_BUILTIN_RCPSS:
03710 *iopc = INTRN_RCPSS;
03711 break;
03712 case GSBI_IX86_BUILTIN_RSQRTSS:
03713 *iopc = INTRN_RSQRTSS;
03714 break;
03715 case GSBI_IX86_BUILTIN_SQRTSS:
03716 *iopc = INTRN_SQRTSS;
03717 break;
03718 case GSBI_IX86_BUILTIN_SHUFPS:
03719 *iopc = INTRN_SHUFPS;
03720 break;
03721 case GSBI_IX86_BUILTIN_EMMS:
03722 *iopc = INTRN_EMMS;
03723 *intrinsic_op = FALSE;
03724 break;
03725 #if 0 // wgen TODO
03726 case GSBI_IX86_BUILTIN_LOADAPS:
03727 *iopc = INTRN_LOADAPS;
03728 break;
03729 case GSBI_IX86_BUILTIN_STOREAPS:
03730 *iopc = INTRN_STOREAPS;
03731 *intrinsic_op = FALSE;
03732 break;
03733 #endif
03734 case GSBI_IX86_BUILTIN_PXOR128:
03735 wn = WN_Bxor (res_type, arg0, arg1);
03736 *intrinsic_op = FALSE;
03737 break;
03738 case GSBI_IX86_BUILTIN_PSLLDQI128:
03739 *iopc = INTRN_PSLLDQ;
03740 break;
03741 case GSBI_IX86_BUILTIN_PSRLDQI128:
03742 *iopc = INTRN_PSRLDQ;
03743 break;
03744 case GSBI_IX86_BUILTIN_PSLLW128:
03745 *iopc = INTRN_PSLLW;
03746 break;
03747 case GSBI_IX86_BUILTIN_PSLLD128:
03748 *iopc = INTRN_PSLLD;
03749 break;
03750 case GSBI_IX86_BUILTIN_PSLLQ128:
03751 *iopc = INTRN_PSLLQ;
03752 break;
03753 case GSBI_IX86_BUILTIN_PSRLW128:
03754 *iopc = INTRN_PSRLW;
03755 break;
03756 case GSBI_IX86_BUILTIN_PSRLD128:
03757 *iopc = INTRN_PSRLD;
03758 break;
03759 case GSBI_IX86_BUILTIN_PSRLQ128:
03760 *iopc = INTRN_PSRLQ;
03761 break;
03762 case GSBI_IX86_BUILTIN_PSRAW128:
03763 *iopc = INTRN_PSRAW;
03764 break;
03765 case GSBI_IX86_BUILTIN_PSRAD128:
03766 *iopc = INTRN_PSRAD;
03767 break;
03768 case GSBI_IX86_BUILTIN_PSRAWI128:
03769 *iopc = INTRN_PSRAW;
03770 break;
03771 case GSBI_IX86_BUILTIN_PSRADI128:
03772 *iopc = INTRN_PSRAD;
03773 break;
03774 case GSBI_IX86_BUILTIN_PSLLWI128:
03775 *iopc = INTRN_PSLLW;
03776 break;
03777 case GSBI_IX86_BUILTIN_PSLLDI128:
03778 *iopc = INTRN_PSLLD;
03779 break;
03780 case GSBI_IX86_BUILTIN_PSLLQI128:
03781 *iopc = INTRN_PSLLQ;
03782 break;
03783 case GSBI_IX86_BUILTIN_PSRLWI128:
03784 *iopc = INTRN_PSRLW;
03785 break;
03786 case GSBI_IX86_BUILTIN_PSRLDI128:
03787 *iopc = INTRN_PSRLD;
03788 break;
03789 case GSBI_IX86_BUILTIN_PSRLQI128:
03790 *iopc = INTRN_PSRLQ;
03791 break;
03792 case GSBI_IX86_BUILTIN_MOVNTDQ:
03793 *iopc = INTRN_MOVNTDQ;
03794 *intrinsic_op = FALSE;
03795 break;
03796 #if 0 // wgen TODO
03797 case GSBI_IX86_BUILTIN_LOADD:
03798 *iopc = INTRN_LOADD;
03799 break;
03800 #endif
03801 case GSBI_IX86_BUILTIN_MOVNTPS:
03802 *iopc = INTRN_MOVNTPS;
03803 *intrinsic_op = FALSE;
03804 break;
03805 #if 0 // wgen TODO
03806 case GSBI_IX86_BUILTIN_SSE_ZERO:
03807 *iopc = INTRN_SSE_ZERO;
03808 *intrinsic_op = FALSE;
03809 break;
03810 case GSBI_IX86_BUILTIN_CLRTI:
03811 *iopc = INTRN_CLRTI;
03812 *intrinsic_op = FALSE;
03813 break;
03814 #endif
03815 case GSBI_IX86_BUILTIN_PSHUFD:
03816 *iopc = INTRN_PSHUFD;
03817 break;
03818 #if 0 // wgen TODO
03819 case GSBI_IX86_BUILTIN_LOADSS:
03820 *iopc = INTRN_LOADSS;
03821 break;
03822 #endif
03823 case GSBI_IX86_BUILTIN_DIVPD:
03824 wn = WN_Div (res_type, arg0, arg1);
03825 *intrinsic_op = FALSE;
03826 break;
03827 case GSBI_IX86_BUILTIN_MULPD:
03828 wn = WN_Mpy (res_type, arg0, arg1);
03829 *intrinsic_op = FALSE;
03830 break;
03831 case GSBI_IX86_BUILTIN_SQRTPD:
03832 wn = WN_Sqrt (res_type, arg0);
03833 *intrinsic_op = FALSE;
03834 break;
03835 case GSBI_IX86_BUILTIN_MINPD:
03836 wn = WN_Binary (OPR_MIN, res_type, arg0, arg1);
03837 *intrinsic_op = FALSE;
03838 break;
03839 case GSBI_IX86_BUILTIN_MAXPD:
03840 wn = WN_Binary (OPR_MAX, res_type, arg0, arg1);
03841 *intrinsic_op = FALSE;
03842 break;
03843 case GSBI_IX86_BUILTIN_SHUFPD:
03844 *iopc = INTRN_SHUFPD;
03845 break;
03846 case GSBI_IX86_BUILTIN_XORPD:
03847 *iopc = INTRN_XORPD;
03848 break;
03849 case GSBI_IX86_BUILTIN_ANDPD:
03850 *iopc = INTRN_ANDPD;
03851 break;
03852 case GSBI_IX86_BUILTIN_ORPD:
03853 *iopc = INTRN_ORPD;
03854 break;
03855 #if 0 // wgen TODO
03856 case GSBI_IX86_BUILTIN_STORELPD:
03857 *iopc = INTRN_STORELPD;
03858 *intrinsic_op = FALSE;
03859 break;
03860 case GSBI_IX86_BUILTIN_STOREHPD:
03861 *iopc = INTRN_STOREHPD;
03862 *intrinsic_op = FALSE;
03863 break;
03864 #endif
03865 case GSBI_IX86_BUILTIN_LOADLPD:
03866 *iopc = INTRN_LOADLPD;
03867 break;
03868 case GSBI_IX86_BUILTIN_LOADHPD:
03869 *iopc = INTRN_LOADHPD;
03870 break;
03871 case GSBI_IX86_BUILTIN_UNPCKLPD:
03872 *iopc = INTRN_UNPCKLPD;
03873 break;
03874 case GSBI_IX86_BUILTIN_UNPCKHPD:
03875 *iopc = INTRN_UNPCKHPD;
03876 break;
03877 case GSBI_IX86_BUILTIN_LFENCE:
03878 *iopc = INTRN_LFENCE;
03879 *intrinsic_op = FALSE;
03880 break;
03881 case GSBI_IX86_BUILTIN_MFENCE:
03882 *iopc = INTRN_MFENCE;
03883 *intrinsic_op = FALSE;
03884 break;
03885 case GSBI_IX86_BUILTIN_SFENCE:
03886 *iopc = INTRN_SFENCE;
03887 *intrinsic_op = FALSE;
03888 break;
03889 case GSBI_IX86_BUILTIN_PSHUFW:
03890 *iopc = INTRN_PSHUFW;
03891 break;
03892 #if 0 // wgen TODO
03893 case GSBI_IX86_BUILTIN_LOADDQA:
03894 *iopc = INTRN_LOADDQA;
03895 break;
03896 #endif
03897 case GSBI_IX86_BUILTIN_LOADDQU:
03898 *iopc = INTRN_LOADDQU;
03899 break;
03900 #if 0 // wgen TODO
03901 case GSBI_IX86_BUILTIN_STOREDQA:
03902 *iopc = INTRN_STOREDQA;
03903 *intrinsic_op = FALSE;
03904 break;
03905 #endif
03906 case GSBI_IX86_BUILTIN_STOREDQU:
03907 *iopc = INTRN_STOREDQU;
03908 *intrinsic_op = FALSE;
03909 break;
03910 case GSBI_IX86_BUILTIN_VEC_INIT_V2SI:
03911 *iopc = INTRN_VEC_INIT_V2SI;
03912 break;
03913 case GSBI_IX86_BUILTIN_VEC_EXT_V2SI:
03914 *iopc = INTRN_VEC_EXT_V2SI;
03915 break;
03916 case GSBI_IX86_BUILTIN_VEC_EXT_V4SI:
03917 *iopc = INTRN_VEC_EXT_V2SI;
03918 break;
03919 case GSBI_IX86_BUILTIN_VEC_EXT_V2DI:
03920 *iopc = INTRN_VEC_EXT_V2SI;
03921 break;
03922 case GSBI_IX86_BUILTIN_VEC_EXT_V2DF:
03923 wn = WN_Tas(MTYPE_F8, MTYPE_To_TY(MTYPE_V16F8), arg0);
03924 *intrinsic_op = FALSE;
03925 break;
03926 case GSBI_IX86_BUILTIN_VEC_EXT_V4SF:
03927 wn = WN_Tas(MTYPE_F4, MTYPE_To_TY(MTYPE_V16F4), arg0);
03928 *intrinsic_op = FALSE;
03929 break;
03930 case GSBI_IX86_BUILTIN_PMADDWD:
03931 case GSBI_IX86_BUILTIN_PMADDWD128:
03932 *iopc = INTRN_PMADDWD;
03933 break;
03934 case GSBI_IX86_BUILTIN_PSLLW:
03935 *iopc = INTRN_PSLLW_MMX;
03936 break;
03937 case GSBI_IX86_BUILTIN_PSLLD:
03938 *iopc = INTRN_PSLLD_MMX;
03939 break;
03940 case GSBI_IX86_BUILTIN_PSRLW:
03941 *iopc = INTRN_PSRLW_MMX;
03942 break;
03943 case GSBI_IX86_BUILTIN_PSRLD:
03944 *iopc = INTRN_PSRLD_MMX;
03945 break;
03946 case GSBI_IX86_BUILTIN_PSRAW:
03947 *iopc = INTRN_PSRAW_MMX;
03948 break;
03949 case GSBI_IX86_BUILTIN_PSRAD:
03950 *iopc = INTRN_PSRAD_MMX;
03951 break;
03952 case GSBI_IX86_BUILTIN_PAND:
03953 *iopc = INTRN_PAND_MMX;
03954 break;
03955 case GSBI_IX86_BUILTIN_PANDN:
03956 *iopc = INTRN_PANDN_MMX;
03957 break;
03958 case GSBI_IX86_BUILTIN_PXOR:
03959 *iopc = INTRN_PXOR_MMX;
03960 break;
03961 case GSBI_IX86_BUILTIN_POR:
03962 *iopc = INTRN_POR_MMX;
03963 break;
03964 case GSBI_IX86_BUILTIN_VEC_INIT_V4HI: {
03965 WN *arg[4];
03966 gs_t t_node = t_list;
03967 INT i;
03968 for (i = 0; i < 4; i++, t_node = gs_tree_chain(t_node)) {
03969 arg[i] = WGEN_Expand_Expr(gs_tree_value(t_node));
03970 arg[i] = WN_CreateCvtl(OPC_U8CVTL, 16, arg[i]);
03971 }
03972 wn = arg[3];
03973 for (i = 2; i >= 0; i--) {
03974 wn = WN_Shl(MTYPE_U8, wn, WN_Intconst(MTYPE_U8, 16));
03975 wn = WN_Bior(MTYPE_U8, wn, arg[i]);
03976 }
03977 *intrinsic_op = FALSE;
03978 break;
03979 }
03980 case GSBI_IX86_BUILTIN_VEC_INIT_V8QI: {
03981 WN *arg[8];
03982 gs_t t_node = t_list;
03983 INT i;
03984 for (i = 0; i < 8; i++, t_node = gs_tree_chain(t_node)) {
03985 arg[i] = WGEN_Expand_Expr(gs_tree_value(t_node));
03986 arg[i] = WN_CreateCvtl(OPC_U8CVTL, 8, arg[i]);
03987 }
03988 wn = arg[7];
03989 for (i = 6; i >= 0; i--) {
03990 wn = WN_Shl(MTYPE_U8, wn, WN_Intconst(MTYPE_U8, 8));
03991 wn = WN_Bior(MTYPE_U8, wn, arg[i]);
03992 }
03993 *intrinsic_op = FALSE;
03994 break;
03995 }
03996 case GSBI_IX86_BUILTIN_COMIEQSS:
03997 case GSBI_IX86_BUILTIN_UCOMIEQSS:
03998 *iopc = INTRN_COMIEQSS;
03999 break;
04000 case GSBI_IX86_BUILTIN_COMILTSS:
04001 case GSBI_IX86_BUILTIN_UCOMILTSS:
04002 *iopc = INTRN_COMILTSS;
04003 break;
04004 case GSBI_IX86_BUILTIN_COMILESS:
04005 case GSBI_IX86_BUILTIN_UCOMILESS:
04006 *iopc = INTRN_COMILESS;
04007 break;
04008 case GSBI_IX86_BUILTIN_COMIGTSS:
04009 case GSBI_IX86_BUILTIN_UCOMIGTSS:
04010 *iopc = INTRN_COMIGTSS;
04011 break;
04012 case GSBI_IX86_BUILTIN_COMIGESS:
04013 case GSBI_IX86_BUILTIN_UCOMIGESS:
04014 *iopc = INTRN_COMIGESS;
04015 break;
04016 case GSBI_IX86_BUILTIN_COMINEQSS:
04017 case GSBI_IX86_BUILTIN_UCOMINEQSS:
04018 *iopc = INTRN_COMINEQSS;
04019 break;
04020 case GSBI_IX86_BUILTIN_COMIEQSD:
04021 case GSBI_IX86_BUILTIN_UCOMIEQSD:
04022 *iopc = INTRN_COMIEQSD;
04023 break;
04024 case GSBI_IX86_BUILTIN_COMILTSD:
04025 case GSBI_IX86_BUILTIN_UCOMILTSD:
04026 *iopc = INTRN_COMILTSD;
04027 break;
04028 case GSBI_IX86_BUILTIN_COMILESD:
04029 case GSBI_IX86_BUILTIN_UCOMILESD:
04030 *iopc = INTRN_COMILESD;
04031 break;
04032 case GSBI_IX86_BUILTIN_COMIGTSD:
04033 case GSBI_IX86_BUILTIN_UCOMIGTSD:
04034 *iopc = INTRN_COMIGTSD;
04035 break;
04036 case GSBI_IX86_BUILTIN_COMIGESD:
04037 case GSBI_IX86_BUILTIN_UCOMIGESD:
04038 *iopc = INTRN_COMIGESD;
04039 break;
04040 case GSBI_IX86_BUILTIN_COMINEQSD:
04041 case GSBI_IX86_BUILTIN_UCOMINEQSD:
04042 *iopc = INTRN_COMINEQSD;
04043 break;
04044 case GSBI_IX86_BUILTIN_CVTPI2PS:
04045 *iopc = INTRN_CVTPI2PS;
04046 break;
04047 case GSBI_IX86_BUILTIN_CVTPS2PI:
04048 *iopc = INTRN_CVTPS2PI;
04049 break;
04050 case GSBI_IX86_BUILTIN_CVTSI2SS:
04051 *iopc = INTRN_CVTSI2SS;
04052 break;
04053 case GSBI_IX86_BUILTIN_CVTSI642SS:
04054 *iopc = INTRN_CVTSI642SS;
04055 break;
04056 case GSBI_IX86_BUILTIN_CVTSS2SI:
04057 *iopc = INTRN_CVTSS2SI;
04058 break;
04059 case GSBI_IX86_BUILTIN_CVTSS2SI64:
04060 *iopc = INTRN_CVTSS2SI64;
04061 break;
04062 case GSBI_IX86_BUILTIN_CVTTPS2PI:
04063 *iopc = INTRN_CVTTPS2PI;
04064 break;
04065 case GSBI_IX86_BUILTIN_CVTTSS2SI:
04066 *iopc = INTRN_CVTTSS2SI;
04067 break;
04068 case GSBI_IX86_BUILTIN_CVTTSS2SI64:
04069 *iopc = INTRN_CVTTSS2SI64;
04070 break;
04071 case GSBI_IX86_BUILTIN_CVTDQ2PD:
04072 *iopc = INTRN_CVTDQ2PD;
04073 break;
04074 case GSBI_IX86_BUILTIN_CVTDQ2PS:
04075 *iopc = INTRN_CVTDQ2PS;
04076 break;
04077 case GSBI_IX86_BUILTIN_CVTPD2DQ:
04078 *iopc = INTRN_CVTPD2DQ;
04079 break;
04080 case GSBI_IX86_BUILTIN_CVTPD2PI:
04081 *iopc = INTRN_CVTPD2PI;
04082 break;
04083 case GSBI_IX86_BUILTIN_CVTPD2PS:
04084 *iopc = INTRN_CVTPD2PS;
04085 break;
04086 case GSBI_IX86_BUILTIN_CVTTPD2DQ:
04087 *iopc = INTRN_CVTTPD2DQ;
04088 break;
04089 case GSBI_IX86_BUILTIN_CVTTPD2PI:
04090 *iopc = INTRN_CVTTPD2PI;
04091 break;
04092 case GSBI_IX86_BUILTIN_CVTPI2PD:
04093 *iopc = INTRN_CVTPI2PD;
04094 break;
04095 case GSBI_IX86_BUILTIN_CVTSI2SD:
04096 *iopc = INTRN_CVTSI2SD;
04097 break;
04098 case GSBI_IX86_BUILTIN_CVTSI642SD:
04099 *iopc = INTRN_CVTSI642SD;
04100 break;
04101 case GSBI_IX86_BUILTIN_CVTSD2SI:
04102 *iopc = INTRN_CVTSD2SI;
04103 break;
04104 case GSBI_IX86_BUILTIN_CVTSD2SI64:
04105 *iopc = INTRN_CVTSD2SI64;
04106 break;
04107 case GSBI_IX86_BUILTIN_CVTSD2SS:
04108 *iopc = INTRN_CVTSD2SS;
04109 break;
04110 case GSBI_IX86_BUILTIN_CVTSS2SD:
04111 *iopc = INTRN_CVTSS2SD;
04112 break;
04113 case GSBI_IX86_BUILTIN_CVTTSD2SI:
04114 *iopc = INTRN_CVTTSD2SI;
04115 break;
04116 case GSBI_IX86_BUILTIN_CVTTSD2SI64:
04117 *iopc = INTRN_CVTTSD2SI64;
04118 break;
04119 case GSBI_IX86_BUILTIN_CVTPS2DQ:
04120 *iopc = INTRN_CVTPS2DQ;
04121 break;
04122 case GSBI_IX86_BUILTIN_CVTPS2PD:
04123 *iopc = INTRN_CVTPS2PD;
04124 break;
04125 case GSBI_IX86_BUILTIN_CVTTPS2DQ:
04126 *iopc = INTRN_CVTTPS2DQ;
04127 break;
04128 case GSBI_IX86_BUILTIN_LOADUPS:
04129 *iopc = INTRN_LOADUPS;
04130 break;
04131 case GSBI_IX86_BUILTIN_STOREUPS:
04132 *iopc = INTRN_STOREUPS;
04133 *intrinsic_op = FALSE;
04134 break;
04135 case GSBI_IX86_BUILTIN_LOADUPD:
04136 *iopc = INTRN_LOADUPD;
04137 break;
04138 case GSBI_IX86_BUILTIN_STOREUPD:
04139 *iopc = INTRN_STOREUPD;
04140 *intrinsic_op = FALSE;
04141 break;
04142 case GSBI_IX86_BUILTIN_LOADHPS:
04143 *iopc = INTRN_LOADHPS;
04144 break;
04145 case GSBI_IX86_BUILTIN_STOREHPS:
04146 *iopc = INTRN_STOREHPS;
04147 *intrinsic_op = FALSE;
04148 break;
04149 case GSBI_IX86_BUILTIN_LOADLPS:
04150 *iopc = INTRN_LOADLPS;
04151 break;
04152 case GSBI_IX86_BUILTIN_STORELPS:
04153 *iopc = INTRN_STORELPS;
04154 *intrinsic_op = FALSE;
04155 break;
04156 case GSBI_IX86_BUILTIN_MOVMSKPS:
04157 *iopc = INTRN_MOVMSKPS;
04158 break;
04159 case GSBI_IX86_BUILTIN_MOVMSKPD:
04160 *iopc = INTRN_MOVMSKPD;
04161 break;
04162 case GSBI_IX86_BUILTIN_MASKMOVDQU:
04163 *iopc = INTRN_MASKMOVDQU;
04164 *intrinsic_op = FALSE;
04165 break;
04166 case GSBI_IX86_BUILTIN_MASKMOVQ:
04167 *iopc = INTRN_MASKMOVQ;
04168 *intrinsic_op = FALSE;
04169 break;
04170 case GSBI_IX86_BUILTIN_MOVNTPD:
04171 *iopc = INTRN_MOVNTPD;
04172 *intrinsic_op = FALSE;
04173 break;
04174 case GSBI_IX86_BUILTIN_MOVNTI:
04175 *iopc = INTRN_MOVNTI;
04176 *intrinsic_op = FALSE;
04177 break;
04178 case GSBI_IX86_BUILTIN_MOVNTQ:
04179 *iopc = INTRN_MOVNTQ;
04180 *intrinsic_op = FALSE;
04181 break;
04182 case GSBI_IX86_BUILTIN_STMXCSR:
04183 *iopc = INTRN_STMXCSR;
04184 *intrinsic_op = FALSE;
04185 break;
04186 case GSBI_IX86_BUILTIN_LDMXCSR:
04187 *iopc = INTRN_LDMXCSR;
04188 *intrinsic_op = FALSE;
04189 break;
04190 case GSBI_IX86_BUILTIN_PSHUFLW:
04191 *iopc = INTRN_PSHUFLW;
04192 break;
04193 case GSBI_IX86_BUILTIN_PSHUFHW:
04194 *iopc = INTRN_PSHUFHW;
04195 break;
04196 case GSBI_IX86_BUILTIN_MOVNTSS:
04197 *iopc = INTRN_MOVNTSS;
04198 *intrinsic_op = FALSE;
04199 break;
04200 case GSBI_IX86_BUILTIN_MOVNTSD:
04201 *iopc = INTRN_MOVNTSD;
04202 *intrinsic_op = FALSE;
04203 break;
04204 case GSBI_IX86_BUILTIN_EXTRQI:
04205 *iopc = INTRN_EXTRQ;
04206 break;
04207 case GSBI_IX86_BUILTIN_EXTRQ:
04208 *iopc = INTRN_EXTRQ;
04209 break;
04210 case GSBI_IX86_BUILTIN_INSERTQI:
04211 *iopc = INTRN_INSERTQI;
04212 break;
04213 case GSBI_IX86_BUILTIN_INSERTQ:
04214 *iopc = INTRN_INSERTQ;
04215 break;
04216 default:
04217 unsupported:
04218 if (Opt_Level > 0)
04219 {
04220 *iopc = INTRN_UNIMP_PURE;
04221 if (res_type == MTYPE_V)
04222 {
04223 *iopc = INTRN_UNIMP;
04224 *intrinsic_op = FALSE;
04225 }
04226 }
04227 else
04228 {
04229 *intrinsic_op = FALSE;
04230
04231
04232 wn = WN_Intconst (MTYPE_U8, 0);
04233 if (res_type != MTYPE_U8 && res_type != MTYPE_V)
04234 wn = WN_Cvt (MTYPE_U8, res_type, wn);
04235 }
04236 break;
04237 }
04238
04239
04240
04241
04242 switch (ins_code)
04243 {
04244 case GSBI_IX86_BUILTIN_PSRAWI128:
04245 case GSBI_IX86_BUILTIN_PSRADI128:
04246 case GSBI_IX86_BUILTIN_PSLLWI128:
04247 case GSBI_IX86_BUILTIN_PSLLDI128:
04248 case GSBI_IX86_BUILTIN_PSLLQI128:
04249 case GSBI_IX86_BUILTIN_PSRLWI128:
04250 case GSBI_IX86_BUILTIN_PSRLDI128:
04251 case GSBI_IX86_BUILTIN_PSRLQI128:
04252 Is_True (wn == NULL, ("WGEN_target_builtins: null WN expected"));
04253 WN * args[2];
04254
04255 {
04256
04257 TY_IDX arg_ty_idx = Get_TY (gs_tree_type (gs_tree_value (t_list)));
04258 TYPE_ID arg_mtype = TY_mtype (arg_ty_idx);
04259 args[0] = WN_CreateParm (Mtype_comparison (arg_mtype), arg0,
04260 arg_ty_idx, WN_PARM_BY_VALUE);
04261
04262
04263 arg1 = WN_Cvt (WN_rtype(arg1), MTYPE_V16I8, arg1);
04264 arg_ty_idx = MTYPE_TO_TY_array[WN_rtype (arg1)];
04265 arg_mtype = WN_rtype (arg1);
04266 args[1] = WN_CreateParm (Mtype_comparison (arg_mtype), arg1,
04267 arg_ty_idx, WN_PARM_BY_VALUE);
04268 }
04269
04270 wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, res_type, MTYPE_V,
04271 *iopc, 2, args);
04272 break;
04273 }
04274
04275 return wn;
04276 }
04277 #endif // TARG_X8664
04278
04279
04280 gs_t first_in_compound_expr(gs_t node)
04281 {
04282 gs_t first = gs_tree_operand(node, 0);
04283 while (gs_tree_code(first) == GS_COMPOUND_EXPR)
04284 first = gs_tree_operand(first, 0);
04285 return first;
04286 }
04287
04288 #ifdef KEY
04289 extern BOOL processing_function_prototype;
04290
04291 #ifdef FE_GNU_4_2_0
04292 static inline BOOL
04293 expr_is_final_value (gs_t expr)
04294 {
04295 if (expr == NULL )
04296 return FALSE;
04297
04298 switch (gs_tree_code (expr))
04299 {
04300 case GS_BIND_EXPR:
04301 case GS_CLEANUP_POINT_EXPR:
04302 case GS_TRY_FINALLY_EXPR:
04303 case GS_TRY_CATCH_EXPR:
04304 case GS_STATEMENT_LIST:
04305 case GS_COMPOUND_EXPR:
04306 return FALSE;
04307 default:
04308 return TRUE;
04309 }
04310 }
04311
04312
04313 static WN *
04314 get_wrapper_value (gs_t stmt)
04315 {
04316 Is_True (gs_tree_code(stmt) == GS_BIND_EXPR,
04317 ("get_wrapper_value() only accepts BIND_EXPR"));
04318
04319 gs_t type = gs_tree_type (stmt);
04320 gs_t temp = NULL;
04321 if (type && gs_tree_code (type) != GS_VOID_TYPE)
04322 {
04323 gs_t p;
04324
04325
04326 for (p = stmt; p; )
04327 {
04328 switch (gs_tree_code (p))
04329 {
04330 case GS_BIND_EXPR:
04331 if (expr_is_final_value (gs_bind_expr_body (p)))
04332 {
04333 temp = gs_build_decl (GS_VAR_DECL, type);
04334 gs_t s = gs_build_2 (GS_TCC_EXPRESSION, GS_INIT_EXPR, temp,
04335 gs_bind_expr_body(p));
04336 gs_set_operand(p, GS_BIND_EXPR_BODY, s);
04337 goto out;
04338 }
04339 else
04340 p = gs_bind_expr_body (p);
04341 break;
04342
04343 case GS_CLEANUP_POINT_EXPR:
04344 case GS_TRY_FINALLY_EXPR:
04345 case GS_TRY_CATCH_EXPR:
04346 if (expr_is_final_value (gs_tree_operand (p, 0)))
04347 {
04348 temp = gs_build_decl (GS_VAR_DECL, type);
04349 gs_t s = gs_build_2 (GS_TCC_EXPRESSION, GS_INIT_EXPR, temp,
04350 gs_tree_operand(p, 0));
04351 gs_set_tree_operand(p, 0, s);
04352 goto out;
04353 }
04354 else
04355 p = gs_tree_operand (p, 0);
04356 break;
04357
04358 case GS_STATEMENT_LIST:
04359 {
04360 gs_t stmt_list = gs_statement_list_elts(p);
04361 for (gs_t list = stmt_list; gs_code(list) != EMPTY;
04362 list = gs_operand(list, 1))
04363 {
04364 if (gs_code (gs_operand(list, 1)) == EMPTY )
04365 {
04366 p = gs_operand(list, 0);
04367 if (expr_is_final_value (p))
04368 {
04369 temp = gs_build_decl (GS_VAR_DECL, type);
04370 p = gs_build_2 (GS_TCC_EXPRESSION, GS_INIT_EXPR, temp, p);
04371 gs_set_operand(list, 0, p);
04372 goto out;
04373 }
04374 break;
04375 }
04376 }
04377 }
04378 break;
04379
04380 case GS_COMPOUND_EXPR:
04381 {
04382 gs_t e = p;
04383 for (; gs_tree_code (p) == GS_COMPOUND_EXPR; p = gs_tree_operand (p, 1))
04384 e = p;
04385 if (expr_is_final_value (p))
04386 {
04387 temp = gs_build_decl (GS_VAR_DECL, type);
04388 p = gs_build_2 (GS_TCC_EXPRESSION, GS_INIT_EXPR, temp, p);
04389 gs_set_tree_operand(e, 1, p);
04390 goto out;
04391 }
04392 }
04393 break;
04394
04395 default:
04396
04397 Is_True (FALSE, ("get_wrapper_value() should not reach here"));
04398 }
04399 }
04400
04401 out:
04402
04403 if (!temp)
04404 return NULL;
04405
04406 ST * s = Get_ST(temp);
04407 TY_IDX ty_idx = ST_type(s);
04408 return WN_Ldid(TY_mtype(ty_idx), 0, s, ty_idx);
04409 }
04410
04411 return NULL;
04412 }
04413 #endif // FE_GNU_4_2_0
04414 #endif // KEY
04415
04416 WN *
04417 WGEN_Expand_Expr (gs_t exp,
04418 bool need_result,
04419 TY_IDX nop_ty_idx,
04420 TY_IDX component_ty_idx,
04421 INT64 component_offset,
04422 UINT32 field_id ,
04423 bool is_bit_field,
04424 bool is_aggr_init_via_ctor,
04425 WN *target_wn)
04426 {
04427 gs_code_t code = gs_tree_code(exp);
04428 WN *wn0, *wn1, *wn2, *wn;
04429 ST *st;
04430 TY_IDX ty_idx;
04431 TY_IDX desc_ty_idx;
04432 gs_t arg0, arg1, arg2;
04433 #ifdef KEY
04434 static BOOL must_not_throw = FALSE;
04435 #endif
04436 gs_code_t tmp_code;
04437
04438 wn = NULL;
04439
04440 TRACE_EXPAND_GS(exp);
04441 switch(code)
04442 {
04443
04444 case GS_ADDR_EXPR:
04445 wn = WGEN_Address_Of(gs_tree_operand(exp, 0));
04446 break;
04447
04448
04449
04450
04451
04452
04453 #ifdef TARG_IA64
04454 case GS_FDESC_EXPR:
04455 {
04456 gs_t exp_operand = gs_tree_operand (exp, 0);
04457 FmtAssert( gs_tree_code(exp_operand) == GS_FUNCTION_DECL,("Unexpected Tree Code!!"));
04458 st = Get_ST (exp_operand);
04459 ty_idx = ST_type (st);
04460 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
04461 }
04462 break;
04463 #endif
04464
04465 case GS_FUNCTION_DECL:
04466 {
04467 st = Get_ST (exp);
04468 ty_idx = ST_type (st);
04469 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
04470 }
04471 break;
04472
04473 case GS_TREE_LIST:
04474 {
04475 gs_t stmt;
04476 for (stmt = gs_tree_purpose(exp); stmt; stmt = gs_tree_chain(stmt))
04477 WGEN_Expand_Stmt (stmt);
04478 wn = WGEN_Expand_Expr (gs_tree_value(exp));
04479 }
04480 break;
04481
04482 case GS_DECL_EXPR:
04483 {
04484 gs_t decl = gs_decl_expr_decl(exp);
04485 WGEN_Expand_Decl (decl, TRUE);
04486 wn = WGEN_Expand_Expr (decl);
04487 }
04488 break;
04489
04490 case GS_BIND_EXPR:
04491 {
04492 gs_t body;
04493
04494 Register_Cleanup(exp);
04495 body = gs_bind_expr_body(exp);
04496 #ifdef FE_GNU_4_2_0
04497
04498 wn = get_wrapper_value(exp);
04499 #endif
04500 if (gs_tree_code(body) != GS_STATEMENT_LIST)
04501 WGEN_Expand_Stmt(body);
04502 else {
04503 gs_t stmt_list = gs_statement_list_elts(body);
04504 gs_t list;
04505 for (list = stmt_list; gs_code(list) != EMPTY;
04506 list = gs_operand(list, 1)) {
04507 gs_t stmt = gs_operand(list, 0);
04508 WGEN_Expand_Stmt(stmt);
04509 }
04510 }
04511 Unregister_Cleanup();
04512 }
04513 break;
04514
04515 case GS_TARGET_EXPR:
04516 {
04517 gs_t opnd0 = gs_tree_operand(exp, 0);
04518 st = NULL;
04519 TY_IDX ty;
04520 TYPE_ID mtype;
04521 #ifdef KEY
04522
04523
04524 if (target_wn != NULL) {
04525 if (WN_operator(target_wn) == OPR_LDA) {
04526 FmtAssert(gs_tree_code(opnd0) != GS_INDIRECT_REF,
04527 ("WGEN_Expand_Expr: write target mismtach"));
04528 set_DECL_ST(opnd0, WN_st(target_wn));
04529 } else if (WN_operator(target_wn) == OPR_LDID) {
04530
04531
04532 if (gs_tree_code(opnd0) == GS_VAR_DECL) {
04533 gs_t ptr_var = gs_build_decl(GS_VAR_DECL,
04534 gs_build_pointer_type(gs_tree_type(opnd0)));
04535 _gs_code(opnd0, GS_INDIRECT_REF);
04536 gs_set_tree_operand(opnd0, 0, ptr_var);
04537 set_DECL_ST(ptr_var, WN_st(target_wn));
04538 }
04539 }
04540 }
04541
04542
04543
04544
04545 if (gs_tree_code(opnd0) != GS_INDIRECT_REF &&
04546 gs_tree_code(opnd0) != GS_COMPONENT_REF &&
04547 gs_tree_code(opnd0) != GS_ARRAY_REF)
04548 #endif
04549 {
04550 st = Get_ST (gs_tree_operand(exp, 0));
04551 ty = ST_type(st);
04552 mtype = TY_mtype (ty);
04553 }
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576 gs_t t = gs_tree_operand(exp, 1);
04577 #ifdef KEY
04578 if (t == NULL) {
04579 t = gs_tree_operand(exp, 3);
04580 FmtAssert(t != NULL,
04581 ("WGEN_Expand_Expr: no initializer found for TARGET_EXPR"));
04582 }
04583 #endif
04584 if (gs_tree_code(t) == GS_TARGET_EXPR)
04585 gs_set_tree_operand(t, 2, 0);
04586 if (gs_tree_code(t) == GS_AGGR_INIT_EXPR && gs_aggr_init_via_ctor_p(t)) {
04587 gs_t args = gs_tree_operand(t, 1);
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600 gs_set_tree_value(args, gs_tree_operand(exp, 0));
04601 WGEN_Expand_Expr (t, false, 0, 0, 0, 0, false, true);
04602 }
04603 else
04604 {
04605 #ifdef KEY
04606 gs_t ret_type = NULL;
04607 if (gs_tree_code(t) == GS_AGGR_INIT_EXPR)
04608 {
04609 ret_type = gs_tree_type
04610 (gs_tree_type
04611 (gs_tree_type(gs_tree_operand(t, 0))));
04612 }
04613
04614
04615
04616 if (gs_tree_code(opnd0) == GS_INDIRECT_REF) {
04617 gs_t var = opnd0;
04618 if (gs_tree_code(gs_tree_operand(var, 0)) == GS_NON_LVALUE_EXPR ||
04619 gs_tree_code(gs_tree_operand(var, 0)) == GS_NOP_EXPR)
04620 var = gs_tree_operand(var, 0);
04621 ST *st = Get_ST(gs_tree_operand(var, 0));
04622 WN *ldid_wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type(st));
04623 WN *result_wn = WGEN_Expand_Expr (t, TRUE, 0, 0, 0, 0, FALSE, FALSE,
04624 ldid_wn);
04625
04626
04627
04628 if (result_wn &&
04629 !(WN_operator(result_wn) == OPR_ILOAD &&
04630 WN_operator(WN_kid0(result_wn)) == OPR_LDID &&
04631 WN_st(WN_kid0(result_wn)) == st)) {
04632 WGEN_Stmt_Append(WN_Istore(WN_rtype(result_wn), 0, ST_type(st),
04633 WN_CopyNode(ldid_wn), result_wn),
04634 Get_Srcpos());
04635 }
04636 }
04637
04638 else if (gs_tree_code(t) == GS_AGGR_INIT_EXPR &&
04639 gs_tree_code(opnd0) == GS_COMPONENT_REF) {
04640 WN *target_wn = WGEN_Address_Of(opnd0);
04641 WN *result_wn = WGEN_Expand_Expr (t, TRUE ,
04642 0, 0, 0, 0, FALSE, FALSE, target_wn);
04643
04644 FmtAssert(result_wn == NULL,
04645 ("result_wn should be NULL for the result is passed as param."));
04646 }
04647
04648
04649
04650
04651 else if (TY_return_in_mem(Get_TY(gs_tree_type(t))) ||
04652 (gs_tree_code(t) == GS_AGGR_INIT_EXPR &&
04653 TY_return_in_mem(Get_TY(ret_type)))) {
04654 gs_code_t code = gs_tree_code(t);
04655 if (code == GS_VAR_DECL ||
04656 code == GS_PARM_DECL) {
04657
04658
04659 WN *rhs_wn = WGEN_Expand_Expr (t);
04660 gs_t type = gs_tree_type(gs_tree_operand(exp, 0));
04661 Is_True(!WGEN_has_copy_constructor(type),
04662 ("WGEN_Expand_Expr: type require copy constructor"));
04663 WGEN_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty, rhs_wn),
04664 Get_Srcpos());
04665 } else {
04666
04667
04668 WN *target_wn = WN_Lda (Pointer_Mtype, 0, st, 0);
04669 WN *result_wn = WGEN_Expand_Expr (t, TRUE, 0, 0, 0, 0, FALSE,
04670 FALSE, target_wn);
04671
04672
04673 if (result_wn) {
04674
04675
04676 if (WN_operator(result_wn) == OPR_ILOAD ||
04677 WN_operator(result_wn) == OPR_LDID) {
04678 WGEN_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty,
04679 result_wn), Get_Srcpos());
04680 } else if (WN_operator(result_wn) == OPR_CSELECT) {
04681 WN *wn = WN_CreateEval(result_wn);
04682 WGEN_Stmt_Append(wn, Get_Srcpos());
04683 }
04684 }
04685 }
04686 } else {
04687
04688 WN * init = WGEN_Expand_Expr (t, TRUE);
04689 if (init != NULL) {
04690 if (WN_operator (init) == OPR_LDA)
04691 WGEN_Set_ST_Addr_Saved (init);
04692 WGEN_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty, init),
04693 Get_Srcpos());
04694 }
04695 }
04696 #else
04697 WGEN_Stmt_Append(WN_Stid (mtype, ST_ofst(st), st, ty,
04698 WGEN_Expand_Expr (t)),
04699 Get_Srcpos());
04700 #endif
04701 }
04702 if (gs_tree_operand(exp, 2)
04703 #ifdef KEY
04704
04705 && gs_emit_target_expr_cleanup(exp)
04706 #endif
04707 )
04708 #ifdef KEY
04709 Push_Temp_Cleanup(gs_tree_operand(exp, 2), true, gs_cleanup_eh_only (exp));
04710 #else
04711 Push_Temp_Cleanup(gs_tree_operand(exp, 2), true);
04712 #endif
04713
04714 #ifdef KEY
04715
04716
04717 if (gs_tree_code(opnd0) == GS_INDIRECT_REF) {
04718
04719
04720
04721
04722
04723
04724 if (gs_tree_code(gs_tree_operand(opnd0, 0)) == GS_NOP_EXPR ||
04725 gs_tree_code(gs_tree_operand(opnd0, 0)) == GS_NON_LVALUE_EXPR)
04726 opnd0 = gs_tree_operand(opnd0, 0);
04727 ST *st = Get_ST(gs_tree_operand(opnd0, 0));
04728 TY_IDX ty_idx = Get_TY (gs_tree_type(exp));
04729 WN *ldid_wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type(st));
04730 wn = WN_Iload(TY_mtype(ty_idx), 0, ty_idx, ldid_wn);
04731 break;
04732 }
04733 else if (gs_tree_code(opnd0) == GS_COMPONENT_REF ||
04734 gs_tree_code(opnd0) == GS_ARRAY_REF) {
04735 wn = WGEN_Expand_Expr(opnd0);
04736 break;
04737 }
04738 #endif
04739 }
04740
04741 case GS_CONSTRUCTOR:
04742 #ifdef KEY
04743
04744
04745
04746
04747 if (!need_result &&
04748 !gs_tree_side_effects(exp)) {
04749 return NULL;
04750 }
04751 #endif
04752
04753
04754 case GS_PARM_DECL:
04755 case GS_VAR_DECL:
04756 case GS_RESULT_DECL:
04757 {
04758 UINT xtra_BE_ofst = 0;
04759 PREG_NUM preg_num = 0;
04760 desc_ty_idx = component_ty_idx;
04761 TY_IDX hi_ty_idx = Get_TY (gs_tree_type(exp));
04762 if (desc_ty_idx == 0)
04763 desc_ty_idx = hi_ty_idx;
04764
04765 if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
04766 ty_idx = desc_ty_idx;
04767 else {
04768 ty_idx = nop_ty_idx;
04769 if (ty_idx == 0)
04770 ty_idx = desc_ty_idx;
04771 }
04772
04773 UINT cvtl_size = 0;
04774 if (! is_bit_field) {
04775 if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
04776 if (Target_Byte_Sex == BIG_ENDIAN)
04777 xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
04778 cvtl_size = TY_size(ty_idx) * 8;
04779 ty_idx = desc_ty_idx;
04780 }
04781 }
04782 else {
04783 if (TY_size(desc_ty_idx) > TY_size(ty_idx))
04784 ty_idx = desc_ty_idx;
04785 }
04786
04787 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
04788 TYPE_ID desc = TY_mtype(desc_ty_idx);
04789 if (MTYPE_is_integral(desc)) {
04790 if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
04791 if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
04792 is_bit_field)
04793 rtype = Mtype_TransferSign(desc, rtype);
04794 else desc = Mtype_TransferSign(rtype, desc);
04795 }
04796 }
04797
04798 if (gs_tree_this_volatile(exp))
04799 Set_TY_is_volatile(ty_idx);
04800 #if 1 // wgen bug 10470
04801 else Clear_TY_is_volatile(ty_idx);
04802 #endif
04803
04804 #ifdef KEY
04805 if (code == GS_VAR_DECL && gs_decl_value_expr(exp)) {
04806 wn = WGEN_Expand_Expr (gs_decl_value_expr(exp),
04807 need_result, nop_ty_idx, component_ty_idx,
04808 component_offset, field_id, is_bit_field);
04809 if (cvtl_size != 0)
04810 wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
04811 break;
04812 }
04813 #endif
04814
04815 if (code == GS_PARM_DECL ||
04816 code == GS_VAR_DECL ||
04817 code == GS_RESULT_DECL) {
04818 st = Get_ST (exp);
04819 if (ST_assigned_to_dedicated_preg (st))
04820 Set_TY_is_volatile(ty_idx);
04821 }
04822 else
04823 if (code == GS_CONSTRUCTOR) {
04824 DevWarn ("Encountered CONSTRUCTOR at line %d", lineno);
04825 st = WGEN_Generate_Temp_For_Initialized_Aggregate (exp, "");
04826 }
04827
04828 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
04829 ("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
04830 wn = WN_CreateLdid (OPR_LDID, rtype,
04831 is_bit_field ? MTYPE_BS : desc,
04832 ST_ofst(st)+component_offset+xtra_BE_ofst+preg_num, st,
04833 field_id != 0 ? hi_ty_idx : ty_idx, field_id);
04834 if (cvtl_size != 0)
04835 wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
04836 }
04837 break;
04838
04839 case GS_COMPOUND_LITERAL_EXPR:
04840 {
04841 gs_t oper = gs_tree_operand (gs_tree_operand (exp, 0), 0);
04842 if (gs_tree_code (gs_decl_initial (oper)) == GS_CONSTRUCTOR)
04843 exp = gs_decl_initial (oper);
04844 else
04845 exp = oper;
04846
04847 desc_ty_idx = component_ty_idx;
04848 TY_IDX hi_ty_idx = Get_TY (gs_tree_type(exp));
04849 if (desc_ty_idx == 0)
04850 desc_ty_idx = hi_ty_idx;
04851
04852 if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
04853 ty_idx = desc_ty_idx;
04854 else {
04855 ty_idx = nop_ty_idx;
04856 if (ty_idx == 0)
04857 ty_idx = desc_ty_idx;
04858 }
04859
04860 UINT cvtl_size = 0;
04861 if (! is_bit_field) {
04862 if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
04863 cvtl_size = TY_size(ty_idx) * 8;
04864 ty_idx = desc_ty_idx;
04865 }
04866 }
04867 else {
04868 if (TY_size(desc_ty_idx) > TY_size(ty_idx))
04869 ty_idx = desc_ty_idx;
04870 }
04871
04872 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
04873 TYPE_ID desc = TY_mtype(desc_ty_idx);
04874 if (MTYPE_is_integral(desc)) {
04875 if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
04876 if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
04877 is_bit_field)
04878 rtype = Mtype_TransferSign(desc, rtype);
04879 else desc = Mtype_TransferSign(rtype, desc);
04880 }
04881 }
04882
04883 if (gs_tree_this_volatile(exp))
04884 Set_TY_is_volatile(ty_idx);
04885
04886 if (gs_tree_code(exp) == GS_CONSTRUCTOR)
04887 st = WGEN_Generate_Temp_For_Initialized_Aggregate (exp, "");
04888 else {
04889 WGEN_Initialize_Decl (exp);
04890 st = Get_ST (exp);
04891 if (ST_assigned_to_dedicated_preg (st))
04892 Set_TY_is_volatile (ty_idx);
04893 }
04894 wn = WN_CreateLdid (OPR_LDID, rtype,
04895 is_bit_field ? MTYPE_BS : desc,
04896 ST_ofst(st)+component_offset, st,
04897 field_id != 0 ? hi_ty_idx : ty_idx, field_id);
04898 if (cvtl_size != 0)
04899 wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
04900 }
04901 break;
04902
04903 case GS_CONST_DECL:
04904 wn = WGEN_Expand_Expr(gs_decl_initial(exp), need_result);
04905 break;
04906
04907 case GS_INTEGER_CST:
04908 {
04909 ty_idx = Get_TY (gs_tree_type(exp));
04910 TYPE_ID mtyp = TY_mtype(ty_idx);
04911 mtyp = (mtyp == MTYPE_V || mtyp == MTYPE_M) ? MTYPE_I4 : Widen_Mtype(mtyp);
04912 wn = WN_Intconst(mtyp, gs_get_integer_value(exp));
04913 }
04914 break;
04915
04916 case GS_PTRMEM_CST:
04917 wn = WGEN_Expand_Expr(gs_expanded_ptrmem_cst(exp), need_result,
04918 nop_ty_idx, component_ty_idx, component_offset,
04919 field_id);
04920 break;
04921
04922 case GS_EMPTY_CLASS_EXPR:
04923 ty_idx = Get_TY (gs_tree_type(exp));
04924 st = Gen_Temp_Symbol (ty_idx, "__empty_class_expr");
04925 #if 0 // wgen TODO
04926 WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
04927 #endif
04928 wn = WN_Ldid (TY_mtype (ty_idx), 0, st, ty_idx);
04929 break;
04930
04931 case GS_REAL_CST:
04932 {
04933 TCON tcon;
04934 ty_idx = Get_TY (gs_tree_type(exp));
04935 switch (TY_size(ty_idx)) {
04936 case 4:
04937 tcon = Host_To_Targ_Float_4(MTYPE_F4, gs_tree_real_cst_f(exp));
04938 break;
04939 case 8:
04940 tcon = Host_To_Targ_Float(MTYPE_F8, gs_tree_real_cst_d(exp));
04941 break;
04942 #ifdef TARG_IA64
04943 case 12:
04944 case 16:
04945 tcon = Host_To_Targ_Float_10(MTYPE_F10, gs_tree_real_cst_ld(exp));
04946 break;
04947 #else
04948 case 12:
04949 case 16:
04950 tcon = Host_To_Targ_Quad(gs_tree_real_cst_ld(exp));
04951 break;
04952 #endif
04953 default:
04954 FmtAssert(FALSE, ("WGEN_Expand_Expr: unexpected size for real constant"));
04955 break;
04956 }
04957 st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04958 wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
04959 }
04960 break;
04961
04962 case GS_COMPLEX_CST:
04963 {
04964 TCON tcon;
04965 ty_idx = Get_TY (gs_tree_type(exp));
04966 #ifdef KEY
04967
04968 if (gs_tree_code(gs_tree_realpart(exp)) != GS_REAL_CST ||
04969 gs_tree_code(gs_tree_imagpart(exp)) != GS_REAL_CST) {
04970 printf("%s does not support complex integer data types "
04971 "(a GNU extension)\n", lang_cplus ? "pathCC" : "pathcc");
04972 exit(2);
04973 }
04974 #endif
04975 switch (TY_size(ty_idx)) {
04976 case 8:
04977 tcon = Host_To_Targ_Complex_4(MTYPE_C4,
04978 gs_tree_real_cst_f(gs_tree_realpart(exp)),
04979 gs_tree_real_cst_f(gs_tree_imagpart(exp)));
04980 break;
04981 case 16:
04982 tcon = Host_To_Targ_Complex(MTYPE_C8,
04983 gs_tree_real_cst_d(gs_tree_realpart(exp)),
04984 gs_tree_real_cst_d(gs_tree_imagpart(exp)));
04985 break;
04986 #ifdef TARG_IA64
04987 case 32:
04988 tcon = Host_To_Targ_Complex_10(MTYPE_C10,
04989 gs_tree_real_cst_ld(gs_tree_realpart(exp)),
04990 gs_tree_real_cst_ld(gs_tree_imagpart(exp)));
04991 break;
04992 #else
04993 case 24:
04994 case 32:
04995 tcon = Host_To_Targ_Complex_Quad(
04996 gs_tree_real_cst_ld(gs_tree_realpart(exp)),
04997 gs_tree_real_cst_ld(gs_tree_imagpart(exp)));
04998 break;
04999 #endif
05000 default:
05001 FmtAssert(FALSE, ("WGEN_Expand_Expr: unexpected size for complex constant"));
05002 break;
05003 }
05004 st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
05005 wn = WN_CreateConst (OPR_CONST, TY_mtype (ty_idx), MTYPE_V, st);
05006 }
05007 break;
05008
05009
05010 case GS_STRING_CST:
05011 {
05012 TCON tcon;
05013 tcon = Host_To_Targ_String (MTYPE_STRING,
05014 const_cast<char*>(gs_tree_string_pointer(exp)),
05015 gs_tree_string_length(exp));
05016 ty_idx = Get_TY(gs_tree_type(exp));
05017 st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
05018 wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
05019 TREE_STRING_ST (exp) = st;
05020 }
05021 break;
05022
05023
05024 case GS_BIT_NOT_EXPR:
05025 case GS_ABS_EXPR:
05026 case GS_NEGATE_EXPR:
05027 case GS_REALPART_EXPR:
05028 case GS_IMAGPART_EXPR:
05029 {
05030 TYPE_ID mtyp = TY_mtype(Get_TY(gs_tree_type(exp)));
05031 #ifdef KEY
05032
05033 if ((code == GS_REALPART_EXPR ||
05034 code == GS_IMAGPART_EXPR) &&
05035 !MTYPE_float(mtyp)) {
05036 printf("%s does not support complex integer data types "
05037 "(a GNU extension)\n", lang_cplus ? "pathCC" : "pathcc");
05038 exit(2);
05039 }
05040 #endif
05041
05042 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05043 wn = WN_Unary (Operator_From_Tree [code].opr, Widen_Mtype(mtyp), wn0);
05044 #ifdef KEY // bug 2648
05045 if (mtyp != WN_rtype(wn))
05046 wn = WN_CreateCvtl (OPR_CVTL, WN_rtype(wn), MTYPE_V,
05047 MTYPE_size_min(mtyp), wn);
05048 #endif
05049 }
05050 break;
05051
05052 case GS_TRUTH_NOT_EXPR:
05053 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05054 wn1 = WN_Intconst (MTYPE_I4, 0);
05055 wn = WN_Relational (OPR_EQ, MTYPE_I4, wn0, wn1);
05056 break;
05057
05058 case GS_CONJ_EXPR:
05059 {
05060 ty_idx = Get_TY (gs_tree_type(exp));
05061 TYPE_ID complex_mtype = TY_mtype(ty_idx);
05062 TYPE_ID float_mtype = Mtype_complex_to_real (complex_mtype);
05063 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05064 if (WN_has_side_effects (wn0)) {
05065 ST *preg_st;
05066 PREG_NUM preg;
05067 preg_st = MTYPE_To_PREG(complex_mtype);
05068 preg = Create_Preg (complex_mtype, NULL);
05069 wn0 = WN_Stid (complex_mtype, preg, preg_st, ty_idx, wn0);
05070 WGEN_Stmt_Append (wn0, Get_Srcpos());
05071 wn0 = WN_Ldid (complex_mtype, preg, preg_st, ty_idx);
05072 }
05073 #ifdef KEY
05074
05075 wn = WN_Binary (OPR_COMPLEX, complex_mtype,
05076 WN_Unary (OPR_REALPART, float_mtype, wn0),
05077 WN_Unary (OPR_NEG, float_mtype,
05078 WN_Unary (OPR_IMAGPART, float_mtype, WN_COPY_Tree(wn0))));
05079 #else
05080 wn = WN_Binary (OPR_COMPLEX, complex_mtype,
05081 WN_Unary (OPR_REALPART, float_mtype, wn0),
05082 WN_Unary (OPR_NEG, float_mtype,
05083 WN_Unary (OPR_REALPART, float_mtype, WN_COPY_Tree(wn0))));
05084 #endif
05085 }
05086 break;
05087
05088 case GS_NOP_EXPR:
05089 {
05090 ty_idx = Get_TY (gs_tree_type(exp));
05091 TYPE_ID mtyp = TY_mtype(ty_idx);
05092
05093 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), TRUE,
05094 (mtyp == MTYPE_M || mtyp == MTYPE_V) ? 0 : ty_idx,
05095 component_ty_idx, component_offset,
05096 field_id, is_bit_field
05097 #ifdef KEY
05098 , FALSE, target_wn
05099 #endif
05100 );
05101
05102 #ifdef KEY // bug 12548
05103 if (!wn)
05104 break;
05105 #endif
05106 if (mtyp == MTYPE_V)
05107 break;
05108 if (mtyp == MTYPE_M)
05109 break;
05110 if (WN_rtype(wn) == MTYPE_M)
05111 break;
05112 if (MTYPE_is_integral(mtyp) && MTYPE_is_integral(WN_rtype(wn))) {
05113
05114
05115 if (MTYPE_size_min(mtyp) == 64 &&
05116 MTYPE_size_min(WN_rtype(wn)) == 32 &&
05117 MTYPE_is_signed(mtyp) != MTYPE_is_signed(WN_rtype(wn))) {
05118 mtyp = MTYPE_complement(mtyp);
05119 }
05120
05121 if (MTYPE_size_min(mtyp) < MTYPE_size_min(WN_rtype(wn))) {
05122 if (MTYPE_size_min(mtyp) != 32)
05123 wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp), MTYPE_V,
05124 MTYPE_size_min(mtyp), wn);
05125 else wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
05126 }
05127 else {
05128 TY_IDX ty_idx0 = Get_TY(gs_tree_type(gs_tree_operand (exp, 0)));
05129 TYPE_ID mtyp0 = TY_mtype(ty_idx0);
05130
05131 if (MTYPE_size_min(mtyp) > MTYPE_size_min(mtyp0) &&
05132 ! Has_Subsumed_Cvtl(WN_operator(wn)))
05133 wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp0), MTYPE_V,
05134 MTYPE_size_min(mtyp0), wn);
05135
05136 if (MTYPE_size_min(mtyp) > MTYPE_size_min(WN_rtype(wn)))
05137 wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
05138 else {
05139 if (mtyp != WN_rtype(wn))
05140 wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
05141 }
05142 }
05143 }
05144 else {
05145 if (mtyp != WN_rtype(wn))
05146 wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
05147 }
05148 }
05149 break;
05150
05151 case GS_COMPONENT_REF:
05152 {
05153 INT64 ofst;
05154 arg0 = gs_tree_operand (exp, 0);
05155 arg1 = gs_tree_operand (exp, 1);
05156
05157
05158 (void) Get_TY(gs_tree_type(arg0));
05159
05160 if (component_ty_idx == 0)
05161 ty_idx = Get_TY (gs_tree_type(exp));
05162 else ty_idx = component_ty_idx;
05163 if (gs_decl_bit_field(arg1))
05164 is_bit_field = TRUE;
05165
05166 if (! is_bit_field &&
05167 component_ty_idx == 0) {
05168
05169 gs_t sizenode = gs_decl_size(arg1);
05170 if (
05171 #ifdef KEY
05172 sizenode &&
05173 #endif
05174 gs_tree_code(sizenode) == GS_INTEGER_CST) {
05175 TYPE_ID c_mtyp = TY_mtype(ty_idx);
05176 INT32 bsize = gs_get_integer_value(sizenode);
05177 if (MTYPE_size_min(c_mtyp) > bsize) {
05178 FmtAssert(MTYPE_is_integral(c_mtyp),
05179 ("COMPONENT_REF: integer type expected at inconsistent field size"));
05180 c_mtyp = Mtype_AlignmentClass(bsize >> 3, MTYPE_type_class(c_mtyp));
05181 ty_idx = MTYPE_To_TY(c_mtyp);
05182 }
05183 }
05184 }
05185
05186 if (! is_bit_field)
05187 ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
05188 gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
05189 / BITSPERBYTE;
05190 else ofst = 0;
05191 #ifdef KEY
05192 FmtAssert (DECL_FIELD_ID(arg1) != 0,
05193 ("WGEN_Expand_Expr: DECL_FIELD_ID used but not set"));
05194
05195
05196
05197
05198
05199 if (WGEN_Call_Returns_Ptr_To_Member_Func(arg0)) {
05200 gs_t field0 = gs_type_fields(gs_tree_type(arg0));
05201
05202
05203 TYPE_ID desc = TY_mtype(Get_TY(gs_tree_type(field0)));
05204 wn = WGEN_Expand_Ptr_To_Member_Func_Call_Expr (arg0, nop_ty_idx,
05205 Pointer_Mtype, desc, component_offset,
05206 field_id + DECL_FIELD_ID(arg1));
05207 } else
05208 #endif
05209 wn = WGEN_Expand_Expr (arg0, TRUE, nop_ty_idx, ty_idx, ofst+component_offset,
05210 field_id + DECL_FIELD_ID(arg1), is_bit_field);
05211
05212 #ifdef KEY
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222 if (gs_tree_code(arg0) == GS_MODIFY_EXPR) {
05223 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
05224 TYPE_ID desc = TY_mtype(ty_idx);
05225 if (WN_operator(wn) == OPR_ILOAD) {
05226 wn = WN_CreateIload(OPR_ILOAD, rtype, desc,
05227 WN_offset(wn) + ofst + component_offset, ty_idx,
05228 WN_load_addr_ty(wn), WN_kid0(wn),
05229 WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
05230 }
05231 else if (WN_operator(wn) == OPR_LDID) {
05232 WN_set_rtype(wn, rtype);
05233 WN_set_desc(wn, desc);
05234 WN_offset(wn) = WN_offset(wn)+ofst+component_offset;
05235 WN_set_field_id(wn, WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
05236 }
05237 }
05238
05239
05240 else if (gs_tree_code(arg0) == GS_COND_EXPR &&
05241 WN_operator(wn) == OPR_CSELECT &&
05242 WN_rtype(wn) == MTYPE_M)
05243 {
05244
05245 Is_True (WN_rtype (WN_kid1(wn)) == MTYPE_M, ("Unexpected type"));
05246
05247 TY_IDX temp_ty_idx = WN_ty (WN_kid1 (wn));
05248
05249 if (WN_field_id (WN_kid1 (wn)))
05250 temp_ty_idx = get_field_type (temp_ty_idx,
05251 WN_field_id (WN_kid1 (wn)));
05252
05253 ST * temp = Gen_Temp_Symbol (temp_ty_idx, ".mcselect_store");
05254 wn = WN_Stid (MTYPE_M, 0, temp, temp_ty_idx, wn);
05255 WGEN_Stmt_Append (wn, Get_Srcpos());
05256
05257 wn = WN_Ldid (TY_mtype (ty_idx), ofst + component_offset,
05258 temp, temp_ty_idx, field_id + DECL_FIELD_ID(arg1));
05259 }
05260 #endif
05261 }
05262 break;
05263
05264 case GS_INDIRECT_REF:
05265 {
05266 UINT xtra_BE_ofst = 0;
05267 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05268
05269 TY_IDX hi_ty_idx;
05270 if (gs_tree_code(gs_tree_type(exp)) == GS_VOID_TYPE)
05271 hi_ty_idx = MTYPE_To_TY(MTYPE_I4);
05272 else hi_ty_idx = Get_TY(gs_tree_type(exp));
05273
05274 desc_ty_idx = component_ty_idx;
05275 if (desc_ty_idx == 0)
05276 desc_ty_idx = hi_ty_idx;
05277
05278 if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
05279 ty_idx = desc_ty_idx;
05280 else {
05281 ty_idx = nop_ty_idx;
05282 if (ty_idx == 0)
05283 ty_idx = desc_ty_idx;
05284 }
05285
05286 if (! is_bit_field) {
05287 if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
05288 if (Target_Byte_Sex == BIG_ENDIAN)
05289 xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
05290 desc_ty_idx = ty_idx;
05291 }
05292 }
05293 else {
05294 if (TY_size(desc_ty_idx) > TY_size(ty_idx))
05295 ty_idx = desc_ty_idx;
05296 }
05297
05298 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
05299 TYPE_ID desc = TY_mtype(desc_ty_idx);
05300 if (MTYPE_is_integral(desc)) {
05301 if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
05302 if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
05303 is_bit_field)
05304 rtype = Mtype_TransferSign(desc, rtype);
05305 else desc = Mtype_TransferSign(rtype, desc);
05306 }
05307 }
05308
05309 if (gs_tree_this_volatile(exp))
05310 Set_TY_is_volatile(hi_ty_idx);
05311
05312 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
05313 ("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
05314
05315 #ifdef KEY // bug 12548
05316 if (!wn0)
05317 break;
05318 #endif
05319
05320 if (!WGEN_Keep_Zero_Length_Structs &&
05321 rtype == MTYPE_M &&
05322 TY_size (hi_ty_idx) == 0) {
05323 if (WN_has_side_effects (wn0)) {
05324 wn = WN_CreateEval (wn0);
05325 WGEN_Stmt_Append (wn, Get_Srcpos());
05326 }
05327 wn = NULL;
05328 }
05329 else {
05330
05331 if (WN_operator (wn0) == OPR_LDA &&
05332 ST_class (WN_st (wn0)) == CLASS_CONST &&
05333 is_bit_field == FALSE &&
05334 field_id == 0) {
05335 st = WN_st (wn0);
05336 TCON tcon = Tcon_Table [ST_tcon (st)];
05337 if (TCON_ty (tcon) == MTYPE_STRING &&
05338 TY_size (Be_Type_Tbl (desc)) == 1) {
05339 mUINT32 len = Targ_String_Length (tcon);
05340 mUINT64 offset = component_offset + xtra_BE_ofst + WN_offset (wn0);
05341 if (offset <= len &&
05342 desc == MTYPE_U1 &&
05343 (rtype == MTYPE_U4 || rtype == MTYPE_U8)) {
05344 unsigned char *cp = (unsigned char *) Targ_String_Address (tcon);
05345 unsigned long long val = cp [offset];
05346 wn = WN_Intconst (rtype, val);
05347 break;
05348 }
05349 else
05350 if (offset <= len &&
05351 desc == MTYPE_I1 &&
05352 (rtype == MTYPE_I4 || rtype == MTYPE_I8)) {
05353 signed char *cp = (signed char *) Targ_String_Address (tcon);
05354 signed long long val = cp [offset];
05355 wn = WN_Intconst (rtype, val);
05356 break;
05357 }
05358 }
05359 }
05360
05361 if (need_result)
05362 wn = WN_CreateIload(OPR_ILOAD, rtype,
05363 is_bit_field ? MTYPE_BS : desc,
05364 component_offset+xtra_BE_ofst,
05365 field_id != 0 ? hi_ty_idx : ty_idx,
05366 Make_Pointer_Type (hi_ty_idx, FALSE),
05367 wn0, field_id);
05368 else
05369 if (WN_has_side_effects (wn0))
05370 wn = wn0;
05371 }
05372 }
05373 break;
05374
05375 case GS_CONVERT_EXPR:
05376 case GS_FLOAT_EXPR:
05377 {
05378 #ifndef KEY // bug 10967
05379 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05380 #endif
05381 ty_idx = Get_TY (gs_tree_type(exp));
05382 TYPE_ID mtyp = TY_mtype(ty_idx);
05383 #ifdef KEY
05384
05385
05386
05387
05388
05389
05390 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0),
05391 need_result || (mtyp != MTYPE_V));
05392 #endif
05393 if (mtyp == MTYPE_V)
05394 wn = wn0;
05395 else if (MTYPE_byte_size(mtyp) < 4 && MTYPE_is_integral(WN_rtype(wn0)))
05396 wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp), MTYPE_V,
05397 MTYPE_size_min(mtyp), wn0);
05398 else {
05399 mtyp = Widen_Mtype(TY_mtype(ty_idx));
05400 if (mtyp == WN_rtype(wn0) || mtyp == MTYPE_V)
05401 wn = wn0;
05402 else {
05403 #ifdef KEY // prevent zero extension when converting to 64-bit address type
05404 if (gs_tree_code(gs_tree_type(exp)) == GS_POINTER_TYPE &&
05405 MTYPE_byte_size(FE_Pointer_Type_To_Mtype()) == 8) {
05406 if (WN_operator(wn0) == OPR_CVT && WN_desc(wn0) == MTYPE_U4) {
05407 WN_set_desc(wn0, MTYPE_I4);
05408 wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05409 }
05410 else if (MTYPE_byte_size(WN_rtype(wn0) == 4))
05411 wn = WN_Cvt(MTYPE_I4, mtyp, wn0);
05412 else wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05413 }
05414
05415 else if (MTYPE_signed(WN_rtype(wn0)) != MTYPE_signed(mtyp) &&
05416 MTYPE_bit_size(WN_rtype(wn0)) > MTYPE_bit_size(mtyp)) {
05417 wn = WN_Cvt(Mtype_TransferSign(mtyp, WN_rtype(wn0)), mtyp, wn0);
05418 }
05419 else
05420 #endif
05421 wn = WN_Cvt(WN_rtype(wn0), mtyp, wn0);
05422
05423 if (WN_opcode(wn) == OPC_I4U4CVT ||
05424 WN_opcode(wn) == OPC_U4I4CVT ||
05425 WN_opcode(wn) == OPC_I8U8CVT ||
05426 WN_opcode(wn) == OPC_U8I8CVT) {
05427 wn = WN_kid0 (wn);
05428 }
05429 }
05430 }
05431 }
05432 break;
05433
05434 case GS_FIX_TRUNC_EXPR:
05435 {
05436 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05437 ty_idx = Get_TY (gs_tree_type(exp));
05438 TYPE_ID mtyp = Widen_Mtype(TY_mtype(ty_idx));
05439 wn = WN_Trunc(WN_rtype(wn0), mtyp, wn0);
05440 }
05441 break;
05442
05443 case GS_EXPR_STMT:
05444 {
05445 #ifdef KEY
05446
05447 wn = WGEN_Expand_Expr (gs_expr_stmt_expr(exp), need_result, nop_ty_idx,
05448 component_ty_idx, component_offset, field_id,
05449 is_bit_field, is_aggr_init_via_ctor);
05450 #else
05451 wn = WGEN_Expand_Expr (gs_expr_stmt_expr(exp), false);
05452 #endif
05453 }
05454 break;
05455
05456 case GS_STMT_EXPR:
05457 {
05458 #ifdef KEY
05459 bool write_to_target_wn = TRUE;
05460
05461
05462
05463
05464
05465 if (target_wn != NULL
05466 && gs_tree_code (gs_stmt_expr_stmt (exp)) == GS_COMPOUND_EXPR
05467 && gs_tree_code (first_in_compound_expr (gs_stmt_expr_stmt (exp))) == GS_SCOPE_STMT) {
05468 gs_t expr = gs_tree_operand (gs_stmt_expr_stmt (exp), 0);
05469 gs_t last = gs_tree_operand (gs_stmt_expr_stmt (exp), 1);
05470
05471 while (gs_tree_code (expr) == GS_COMPOUND_EXPR) {
05472 expr = gs_tree_operand (expr, 1);
05473 }
05474
05475 if (gs_tree_code (last) == GS_SCOPE_STMT
05476 && gs_tree_code (expr) == GS_EXPR_STMT) {
05477 if (gs_tree_code (gs_expr_stmt_expr (expr)) == GS_VAR_DECL) {
05478
05479
05480 gs_t var_decl = gs_expr_stmt_expr (expr);
05481 ST *st = DECL_ST (var_decl);
05482 if (st == NULL) {
05483
05484
05485 if (WN_operator(target_wn) == OPR_LDA) {
05486 set_DECL_ST(var_decl, WN_st(target_wn));
05487 } else if (WN_operator(target_wn) == OPR_LDID) {
05488
05489
05490
05491 gs_t ptr_var =
05492 gs_build_decl(GS_VAR_DECL,
05493 gs_build_pointer_type(gs_tree_type(var_decl)));
05494 _gs_code(var_decl, GS_INDIRECT_REF);
05495 gs_set_tree_operand(var_decl, 0, ptr_var);
05496 set_DECL_ST(ptr_var, WN_st(target_wn));
05497 } else {
05498 FmtAssert(FALSE,
05499 ("WGEN_Expand_Expr: unexpected operator in target_wn"));
05500 }
05501 } else {
05502
05503
05504 FmtAssert(st == WN_st(target_wn),
05505 ("WGEN_Expand_Expr: STs are different"));
05506 }
05507
05508
05509 write_to_target_wn = FALSE;
05510
05511 } else if (gs_tree_code (gs_expr_stmt_expr (expr)) == GS_INDIRECT_REF) {
05512
05513
05514
05515 write_to_target_wn = FALSE;
05516 }
05517 }
05518 }
05519 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), need_result, nop_ty_idx,
05520 component_ty_idx, component_offset, field_id,
05521 is_bit_field, is_aggr_init_via_ctor,
05522 write_to_target_wn ? target_wn : NULL);
05523 #else
05524 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), need_result);
05525 #endif
05526 }
05527 break;
05528
05529 #ifndef KEY
05530 case GS_SUBOBJECT:
05531 break;
05532 #endif // !KEY
05533
05534 case GS_CLEANUP_POINT_EXPR:
05535 {
05536 Push_Temp_Cleanup(exp, false);
05537 #ifdef KEY
05538
05539
05540
05541
05542 BOOL done_cleanups = FALSE;
05543 gs_t old_enclosing_cleanup_point_expr = enclosing_cleanup_point_expr;
05544 enclosing_cleanup_point_expr = exp;
05545
05546
05547 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), need_result);
05548
05549
05550 if (enclosing_cleanup_point_expr == NULL)
05551 done_cleanups = TRUE;
05552 #else
05553 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), FALSE);
05554 #endif
05555 WN * cleanup_block = WN_CreateBlock ();
05556 WGEN_Stmt_Push (cleanup_block, wgen_stmk_temp_cleanup, Get_Srcpos ());
05557 #ifdef KEY
05558 if (!done_cleanups)
05559 #endif
05560 Do_Temp_Cleanups(exp);
05561 WGEN_Stmt_Pop (wgen_stmk_temp_cleanup);
05562 if (wn && WN_has_side_effects (wn) && WN_first (cleanup_block)) {
05563 DevWarn("CLEANUP_POINT_EXPR: expressson has side effects");
05564 #ifdef KEY
05565
05566
05567 ty_idx = MTYPE_TO_TY_array[WN_rtype(wn)];
05568 #else
05569 ty_idx = Get_TY (gs_tree_type(exp));
05570 #endif
05571 st = Gen_Temp_Symbol (ty_idx, "__cleanup_point_expr");
05572 #ifdef FE_GNU_4_2_0
05573 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, st);
05574 #endif
05575 TYPE_ID mtype = TY_mtype (ty_idx);
05576 WGEN_Set_ST_Addr_Saved (wn);
05577 wn = WN_Stid (mtype, 0, st, ty_idx, wn);
05578 WGEN_Stmt_Append (wn, Get_Srcpos ());
05579 wn = WN_Ldid (mtype, 0, st, ty_idx);
05580 }
05581 WGEN_Stmt_Append (cleanup_block, Get_Srcpos ());
05582 #ifdef KEY
05583 enclosing_cleanup_point_expr = old_enclosing_cleanup_point_expr;
05584 #endif
05585 }
05586 break;
05587
05588 case GS_THROW_EXPR:
05589 WGEN_One_Stmt (gs_tree_operand (exp, 0));
05590 break;
05591
05592 case GS_TRY_CATCH_EXPR:
05593 #ifdef KEY
05594
05595
05596
05597 Register_Cleanup (exp);
05598 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), need_result);
05599 Unregister_Cleanup ();
05600 #endif
05601 break;
05602
05603
05604 case GS_PLUS_EXPR:
05605 case GS_MINUS_EXPR:
05606 case GS_MULT_EXPR:
05607 case GS_MAX_EXPR:
05608 case GS_MIN_EXPR:
05609 case GS_LSHIFT_EXPR:
05610 case GS_BIT_AND_EXPR:
05611 case GS_BIT_IOR_EXPR:
05612 case GS_BIT_XOR_EXPR:
05613 case GS_TRUNC_DIV_EXPR:
05614 case GS_TRUNC_MOD_EXPR:
05615 case GS_RDIV_EXPR:
05616 case GS_EXACT_DIV_EXPR:
05617 case GS_TRUTH_AND_EXPR:
05618 case GS_TRUTH_OR_EXPR:
05619 case GS_TRUTH_XOR_EXPR:
05620 case GS_COMPLEX_EXPR:
05621 case GS_CEIL_DIV_EXPR:
05622 {
05623 TYPE_ID etype = TY_mtype(Get_TY(gs_tree_type(exp)));
05624 wn0 = WGEN_Expand_Expr(gs_tree_operand(exp, 0));
05625 wn1 = WGEN_Expand_Expr(gs_tree_operand(exp, 1));
05626 #ifdef KEY // Bug 11875
05627 if (code == GS_COMPLEX_EXPR && !MTYPE_float(WN_rtype(wn0))) {
05628 printf("%s does not support complex integer data types "
05629 "(a GNU extension)\n", lang_cplus ? "pathCC" : "pathcc");
05630 exit(2);
05631 }
05632 #endif
05633
05634
05635 wn = WN_Binary(Operator_From_Tree[code].opr,
05636 Widen_Mtype(etype), wn0, wn1);
05637
05638
05639
05640 if ((MTYPE_is_integral(etype)) &&
05641 (Widen_Mtype(etype) != etype) &&
05642 (TY_size (Get_TY(gs_tree_type(exp))) < 32) &&
05643 (code == GS_PLUS_EXPR || code == GS_MINUS_EXPR ||
05644 code == GS_MULT_EXPR || code == GS_LSHIFT_EXPR ||
05645 code == GS_BIT_XOR_EXPR || code == GS_BIT_IOR_EXPR))
05646 wn = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(etype), MTYPE_V,
05647 TY_size (Get_TY(gs_tree_type(exp))) * 8, wn);
05648 }
05649 break;
05650
05651 case GS_LROTATE_EXPR:
05652 {
05653 ty_idx = Get_TY(gs_tree_type(exp));
05654 TYPE_ID mtype = TY_mtype (ty_idx);
05655 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05656 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1));
05657 wn1 = WN_Binary (OPR_SUB, Widen_Mtype (mtype),
05658 WN_Intconst (Widen_Mtype (mtype),
05659 TY_size (ty_idx) * 8),
05660 wn1);
05661 wn = WN_Rrotate (TY_mtype(Get_TY(gs_tree_type(exp))), wn0, wn1);
05662 }
05663 break;
05664
05665 case GS_RROTATE_EXPR:
05666 {
05667 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05668 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1));
05669 wn = WN_Rrotate (TY_mtype(Get_TY(gs_tree_type(exp))), wn0, wn1);
05670 }
05671 break;
05672
05673 case GS_RSHIFT_EXPR:
05674 {
05675 TYPE_ID mtyp = Widen_Mtype(TY_mtype(Get_TY(gs_tree_type(exp))));
05676 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05677 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1));
05678 wn = WN_Binary (MTYPE_signed(mtyp) ? OPR_ASHR : OPR_LSHR,
05679 mtyp, wn0, wn1);
05680 }
05681 break;
05682
05683 case GS_TRUTH_ANDIF_EXPR:
05684 case GS_TRUTH_ORIF_EXPR:
05685 {
05686
05687 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05688
05689
05690
05691 WGEN_Guard_Var_Push();
05692 wn1 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 1),
05693 Boolean_type);
05694 gs_t guard_var = WGEN_Guard_Var_Pop();
05695 if (guard_var != NULL) {
05696 WGEN_add_guard_var(guard_var, wn1);
05697 }
05698 wn = WN_Binary (Operator_From_Tree [code].opr,
05699 Boolean_type, wn0, wn1);
05700 if (Boolean_type != MTYPE_B &&
05701 Widen_Mtype(TY_mtype(Get_TY(gs_tree_type(exp)))) != Boolean_type)
05702 wn = WN_Cvt (Boolean_type, Widen_Mtype(TY_mtype(Get_TY(gs_tree_type(exp)))), wn);
05703 }
05704 break;
05705
05706 case GS_LT_EXPR:
05707 case GS_LE_EXPR:
05708 case GS_GT_EXPR:
05709 case GS_GE_EXPR:
05710 case GS_EQ_EXPR:
05711 case GS_NE_EXPR:
05712 {
05713 wn0 = WGEN_Expand_Expr(gs_tree_operand(exp, 0));
05714 wn1 = WGEN_Expand_Expr(gs_tree_operand(exp, 1));
05715
05716 ty_idx = Get_TY (gs_tree_type(exp));
05717 TYPE_ID mtyp = TY_mtype(ty_idx);
05718 TY_IDX ty_idx0 = Get_TY(gs_tree_type(gs_tree_operand(exp, 0)));
05719 TYPE_ID mtyp0 = TY_mtype(ty_idx0);
05720 TY_IDX ty_idx1 = Get_TY(gs_tree_type(gs_tree_operand(exp, 1)));
05721 TYPE_ID mtyp1 = TY_mtype(ty_idx1);
05722
05723 if (MTYPE_size_min(mtyp1) > MTYPE_size_min(mtyp0) &&
05724 ! Has_Subsumed_Cvtl(WN_operator(wn0)))
05725 wn0 = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp0), MTYPE_V,
05726 MTYPE_size_min(mtyp0), wn0);
05727 if (MTYPE_size_min(mtyp0) > MTYPE_size_min(mtyp1) &&
05728 ! Has_Subsumed_Cvtl(WN_operator(wn1)))
05729 wn1 = WN_CreateCvtl(OPR_CVTL, Widen_Mtype(mtyp1), MTYPE_V,
05730 MTYPE_size_min(mtyp1), wn1);
05731
05732 #ifdef TARG_IA64
05733 wn = WN_Relational (Operator_From_Tree [code].opr,
05734 Widen_Mtype(mtyp0), wn0, wn1);
05735 #else
05736 wn = WN_CreateExp2(Operator_From_Tree[code].opr, Widen_Mtype(mtyp),
05737 Widen_Mtype(mtyp0), wn0, wn1);
05738 #endif
05739 }
05740 break;
05741
05742 case GS_COND_EXPR:
05743 {
05744 TY_IDX ty_idx1, ty_idx2;
05745 if (gs_tree_has_location(exp) == gs_true)
05746 lineno = gs_expr_lineno(exp);
05747 if (gs_tree_operand(exp, 1) != NULL &&
05748 gs_tree_type(gs_tree_operand(exp, 1)) != NULL)
05749 ty_idx1 = Get_TY (gs_tree_type(gs_tree_operand (exp, 1)));
05750 else ty_idx1 = MTYPE_To_TY(MTYPE_V);
05751 if (gs_tree_operand(exp, 2) != NULL &&
05752 gs_tree_type(gs_tree_operand(exp, 2)) != NULL)
05753 ty_idx2 = Get_TY (gs_tree_type(gs_tree_operand (exp, 2)));
05754 else ty_idx2 = MTYPE_To_TY(MTYPE_V);
05755 if (gs_tree_type(exp) != NULL)
05756 ty_idx = Get_TY (gs_tree_type(exp));
05757 else ty_idx = MTYPE_To_TY(MTYPE_V);
05758 #ifdef KEY // bug 2645
05759 wn0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
05760 #else
05761 wn0 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 0),
05762 Boolean_type);
05763 #endif
05764
05765 FmtAssert( (wn0 != NULL), ("Child 0 of IF can not be NULL!"));
05766
05767 if (TY_mtype (ty_idx) == MTYPE_V ||
05768 TY_mtype (ty_idx1) == MTYPE_V ||
05769 TY_mtype (ty_idx2) == MTYPE_V) {
05770
05771
05772 WN *then_block = WN_CreateBlock ();
05773 WN *else_block = WN_CreateBlock ();
05774 WN *if_stmt = WN_CreateIf (wn0, then_block, else_block);
05775 #ifdef KEY
05776 SRCPOS if_stmt_srcpos = Get_Srcpos();
05777
05778
05779
05780
05781
05782
05783 WGEN_Stmt_Push (then_block, wgen_stmk_if_then, Get_Srcpos());
05784 WGEN_Guard_Var_Push();
05785 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1), FALSE);
05786 gs_t guard_var1 = WGEN_Guard_Var_Pop();
05787 if (wn1) {
05788 wn1 = WN_CreateEval (wn1);
05789 WGEN_Stmt_Append (wn1, Get_Srcpos());
05790 }
05791 WGEN_Stmt_Pop (wgen_stmk_if_then);
05792
05793 if (guard_var1 != NULL) {
05794 WGEN_add_guard_var(guard_var1, then_block, FALSE);
05795 }
05796
05797
05798 if (gs_tree_operand(exp, 2) != NULL) {
05799 WGEN_Stmt_Push (else_block, wgen_stmk_if_else, Get_Srcpos());
05800 WGEN_Guard_Var_Push();
05801 wn2 = WGEN_Expand_Expr (gs_tree_operand (exp, 2), FALSE);
05802 gs_t guard_var2 = WGEN_Guard_Var_Pop();
05803 if (wn2) {
05804 wn2 = WN_CreateEval (wn2);
05805 WGEN_Stmt_Append (wn2, Get_Srcpos());
05806 }
05807 WGEN_Stmt_Pop (wgen_stmk_if_else);
05808
05809 if (guard_var2 != NULL) {
05810 WGEN_add_guard_var(guard_var2, else_block, FALSE);
05811 }
05812 }
05813
05814 WGEN_Stmt_Append (if_stmt, if_stmt_srcpos);
05815 #else
05816 WGEN_Stmt_Append (if_stmt, Get_Srcpos());
05817 WGEN_Stmt_Push (then_block, wgen_stmk_if_then, Get_Srcpos());
05818 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1), FALSE);
05819 if (wn1) {
05820 wn1 = WN_CreateEval (wn1);
05821 WGEN_Stmt_Append (wn1, Get_Srcpos());
05822 }
05823 WGEN_Stmt_Pop (wgen_stmk_if_then);
05824 if (gs_tree_operand(exp, 2) != NULL) {
05825 WGEN_Stmt_Push (else_block, wgen_stmk_if_else, Get_Srcpos());
05826 wn2 = WGEN_Expand_Expr (gs_tree_operand (exp, 2), FALSE);
05827 if (wn2) {
05828 wn2 = WN_CreateEval (wn2);
05829 WGEN_Stmt_Append (wn2, Get_Srcpos());
05830 }
05831 WGEN_Stmt_Pop (wgen_stmk_if_else);
05832 }
05833 #endif
05834 }
05835 else {
05836 #ifdef KEY
05837
05838
05839
05840
05841
05842 WGEN_Guard_Var_Push();
05843 wn1 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 1),
05844 TY_mtype (ty_idx),
05845 target_wn);
05846 gs_t guard_var1 = WGEN_Guard_Var_Pop();
05847
05848 WGEN_Guard_Var_Push();
05849 wn2 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 2),
05850 TY_mtype (ty_idx),
05851 target_wn);
05852 gs_t guard_var2 = WGEN_Guard_Var_Pop();
05853
05854
05855 if (guard_var1 != NULL) {
05856 WGEN_add_guard_var(guard_var1, wn1);
05857 }
05858 if (guard_var2 != NULL) {
05859 WGEN_add_guard_var(guard_var2, wn2);
05860 }
05861 #else
05862 wn1 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 1),
05863 TY_mtype (ty_idx));
05864 wn2 = WGEN_Expand_Expr_With_Sequence_Point (gs_tree_operand (exp, 2),
05865 TY_mtype (ty_idx));
05866 #endif
05867 wn = WN_CreateExp3 (OPR_CSELECT, Mtype_comparison (TY_mtype (ty_idx)),
05868 MTYPE_V, wn0, wn1, wn2);
05869 Set_PU_has_very_high_whirl (Get_Current_PU ());
05870 }
05871 }
05872 break;
05873
05874 case GS_INIT_EXPR:
05875 #ifdef KEY
05876
05877 if (target_wn != NULL &&
05878 ((tmp_code = gs_tree_code(gs_tree_operand(exp, 0))) == GS_VAR_DECL ||
05879 tmp_code == GS_RESULT_DECL ||
05880 tmp_code == GS_PARM_DECL)) {
05881 if (WN_operator(target_wn) == OPR_LDA) {
05882
05883 set_DECL_ST(gs_tree_operand(exp, 0), WN_st(target_wn));
05884 } else if (WN_operator(target_wn) == OPR_LDID) {
05885
05886
05887
05888
05889
05890
05891 gs_t opnd0 = gs_tree_operand(exp, 0);
05892 gs_t ptr_var = gs_build_decl(GS_VAR_DECL,
05893 gs_build_pointer_type(gs_tree_type(opnd0)));
05894 _gs_code(opnd0, GS_INDIRECT_REF);
05895 gs_set_tree_operand(opnd0, 0, ptr_var);
05896 set_DECL_ST(ptr_var, WN_st(target_wn));
05897 }
05898 }
05899
05900 #ifdef NEW_INITIALIZER
05901 {
05902 gs_t opnd0 = gs_tree_operand(exp, 0);
05903 gs_t opnd1 = gs_tree_operand(exp, 1);
05904 if( lang_cplus &&
05905 gs_tree_code(opnd0) == GS_INDIRECT_REF &&
05906 gs_tree_code(opnd1) == GS_CONSTRUCTOR ) {
05907 WN* target = WGEN_Address_Of(opnd0);
05908 ST* copy_st = WGEN_Generate_Initialized_Aggregate(target, opnd1);
05909 ST* orig_st = WN_st(target);
05910 if ( ST_st_idx(copy_st) != ST_st_idx(orig_st) ) {
05911
05912
05913
05914
05915
05916 TY_IDX copy_ty = ST_type(copy_st);
05917 WN* ldid = WN_Ldid(TY_mtype(copy_ty), 0, copy_st, copy_ty);
05918 if ( WN_operator(target) == OPR_LDA ) {
05919 WGEN_Stmt_Append(
05920 WN_Stid (TY_mtype(copy_ty), WN_lda_offset(target),
05921 orig_st, ST_type(orig_st), ldid),
05922 Get_Srcpos() );
05923 }
05924 else if ( WN_operator(target) == OPR_LDID ) {
05925 WGEN_Stmt_Append(
05926 WN_Istore(TY_mtype(copy_ty), 0,
05927 ST_type(orig_st), target, ldid),
05928 Get_Srcpos() );
05929 }
05930 else {
05931 FmtAssert(FALSE, ("Bad operator for target, not LDA/LDID"));
05932 }
05933 }
05934 break;
05935 }
05936 }
05937 #endif
05938
05939
05940 #endif
05941 case GS_MODIFY_EXPR:
05942 if (gs_tree_has_location(exp) == gs_true)
05943 lineno = gs_expr_lineno(exp);
05944
05945
05946
05947
05948
05949
05950
05951 #ifdef KEY
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05982
05983
05984
05985
05986
05987
05988
05989
05990
05991
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039 {
06040
06041 gs_t init_expr_opnd0 = gs_tree_operand(exp, 0);
06042 if ( gs_tree_code(init_expr_opnd0) == GS_INDIRECT_REF ) {
06043 gs_t init_expr_opnd1 = gs_tree_operand(exp, 1);
06044 gs_t var_decl = gs_tree_operand(init_expr_opnd0, 0);
06045 if ( gs_tree_code(var_decl) == GS_NON_LVALUE_EXPR )
06046 var_decl = gs_tree_operand(var_decl, 0);
06047 if ( ( gs_tree_code(init_expr_opnd1) == GS_TARGET_EXPR ||
06048 ( gs_tree_code(init_expr_opnd1) == GS_NOP_EXPR &&
06049 gs_tree_code(gs_tree_operand(init_expr_opnd1, 0)) == GS_TARGET_EXPR ) ) &&
06050 gs_tree_code(var_decl) == GS_VAR_DECL ) {
06051 ST *st = Get_ST(var_decl);
06052 WN *target_wn = WN_Ldid(Pointer_Mtype, 0, st, ST_type(st));
06053 wn = WGEN_Expand_Expr(init_expr_opnd1, TRUE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
06054 break;
06055 }
06056 }
06057 #if 0
06058 gs_t init_expr_opnd0 = gs_tree_operand(exp, 0);
06059 if (gs_tree_code(gs_tree_operand(exp, 1)) == GS_NOP_EXPR &&
06060 gs_tree_code(gs_tree_operand(gs_tree_operand(exp, 1), 0)) == GS_TARGET_EXPR &&
06061 gs_tree_code(init_expr_opnd0) == GS_INDIRECT_REF &&
06062 gs_tree_code(gs_tree_operand(init_expr_opnd0, 0)) == GS_VAR_DECL) {
06063 gs_t t = gs_tree_operand(exp, 1);
06064 ST *st = Get_ST(gs_tree_operand(init_expr_opnd0, 0));
06065 WN *target_wn = WN_Ldid(Pointer_Mtype, 0, st, ST_type(st));
06066 wn = WGEN_Expand_Expr(t, TRUE, 0, 0, 0, 0, FALSE, FALSE, target_wn);
06067 break;
06068 }
06069 #endif
06070 }
06071 #endif
06072 if (lang_cplus)
06073 {
06074 gs_t t = NULL;
06075 if (gs_tree_code(gs_tree_operand(exp, 1)) == GS_TARGET_EXPR) {
06076 t = gs_tree_operand(exp, 1);
06077 gs_set_tree_operand(t, 2, NULL);
06078 }
06079 #ifdef KEY
06080
06081 else if (gs_tree_code(gs_tree_operand(exp, 1)) == GS_NOP_EXPR &&
06082 gs_tree_code(gs_tree_operand(gs_tree_operand(exp, 1), 0))
06083 == GS_TARGET_EXPR) {
06084 t = gs_tree_operand(gs_tree_operand(exp, 1), 0);
06085 gs_set_tree_operand(t, 2, NULL);
06086 }
06087 #endif
06088
06089 if (t != NULL) {
06090 #ifdef KEY
06091
06092
06093
06094
06095
06096
06097
06098 gs_t init_expr_opnd0 = gs_tree_operand(exp, 0);
06099 if (gs_tree_code(init_expr_opnd0) == GS_INDIRECT_REF &&
06100 gs_tree_code(gs_tree_operand(init_expr_opnd0, 0)) == GS_RESULT_DECL) {
06101 gs_t target_expr_opnd0 = gs_tree_operand(t, 0);
06102 gs_t ptr_var =
06103 gs_build_decl(GS_RESULT_DECL,
06104 gs_tree_type(gs_tree_operand(init_expr_opnd0, 0)));
06105 _gs_code(target_expr_opnd0, GS_INDIRECT_REF);
06106 gs_set_tree_operand(target_expr_opnd0, 0, ptr_var);
06107 set_DECL_ST(ptr_var, DECL_ST(gs_tree_operand(init_expr_opnd0, 0)));
06108 wn = WGEN_Expand_Expr(t);
06109 break;
06110 }
06111 gs_t initializer = NULL;
06112 #endif
06113 tmp_code = gs_tree_code(gs_tree_operand(exp, 0));
06114 if (tmp_code == GS_VAR_DECL ||
06115 tmp_code == GS_RESULT_DECL ||
06116 tmp_code == GS_PARM_DECL) {
06117 #ifdef KEY
06118 ST *st = Get_ST(gs_tree_operand(exp, 0));
06119 set_DECL_ST(gs_tree_operand(t, 0), st);
06120 #else
06121 gs_tree_operand(t, 0) = gs_tree_operand(exp, 0);
06122 #endif
06123 wn = WGEN_Expand_Expr(t);
06124 break;
06125 }
06126 #ifdef KEY
06127
06128
06129
06130
06131 else if (gs_tree_code(initializer = gs_tree_operand(t,1)) ==
06132 GS_AGGR_INIT_EXPR
06133 ) {
06134
06135 gs_set_tree_operand(t, 0, gs_tree_operand(exp,0));
06136 wn = WGEN_Expand_Expr(t);
06137 break;
06138 }
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148
06149
06150 else if (code == GS_INIT_EXPR &&
06151 gs_tree_code(gs_tree_operand(exp, 0)) == GS_COMPONENT_REF &&
06152 gs_tree_code(t) == GS_TARGET_EXPR &&
06153 gs_tree_code(gs_tree_operand(t, 1)) == GS_AGGR_INIT_EXPR ) {
06154 gs_set_tree_operand(t, 0, gs_tree_operand(exp,0));
06155 wn = WGEN_Expand_Expr(t);
06156 break;
06157 }
06158 #endif
06159 DevWarn ("INIT_EXPR/MODIFY_EXPR kid1 is TARGET_EXPR, kid0 is %s\n",
06160 gs_code_name(gs_tree_code(gs_tree_operand(exp, 0))));
06161 }
06162
06163 #if 0 // wgen clean-up: we should not need these codes any more, these
06164 are required to process gimplified GNU tree. Also remove
06165 definition of WGEN_Process_Initialization.
06166
06167 gs_t lhs = gs_tree_operand(exp,0);
06168 gs_t rhs = gs_tree_operand(exp,1);
06169
06170
06171
06172
06173
06174 if (!target_wn && gs_tree_code(exp) == GS_MODIFY_EXPR &&
06175 gs_tree_code(rhs) == GS_CALL_EXPR)
06176 {
06177 TY_IDX ty = Get_TY (gs_tree_type(rhs));
06178 if (TY_return_in_mem(ty))
06179 {
06180 if (gs_tree_code(lhs) == GS_VAR_DECL)
06181 {
06182 ST * s = Get_ST(lhs);
06183 target_wn = WN_Lda (Pointer_Mtype, 0, s, 0);
06184 wn = WGEN_Expand_Expr (rhs, TRUE, 0, 0, 0, 0, FALSE,
06185 FALSE, target_wn);
06186 break;
06187 }
06188 }
06189 }
06190
06191
06192
06193
06194
06195 else if (gs_tree_code(exp) == GS_MODIFY_EXPR &&
06196 gs_tree_code(lhs) == GS_VAR_DECL &&
06197 gs_tree_code(rhs) == GS_STRING_CST)
06198 {
06199 WGEN_Process_Initialization (exp);
06200 break;
06201 }
06202 #endif
06203 }
06204
06205
06206 case GS_PREDECREMENT_EXPR:
06207 case GS_PREINCREMENT_EXPR:
06208 case GS_POSTDECREMENT_EXPR:
06209 case GS_POSTINCREMENT_EXPR:
06210 {
06211 if (gs_tree_code(gs_tree_operand(exp, 1)) == GS_ERROR_MARK)
06212 break;
06213 WN* call_return_val = NULL;
06214
06215
06216
06217
06218
06219 gs_t exp_opnd1 = gs_tree_operand(exp, 1);
06220 if (WGEN_Call_Returns_Ptr_To_Member_Func(exp_opnd1)) {
06221 TYPE_ID desc = TY_mtype(Get_TY(gs_tree_type(exp_opnd1)));
06222 wn1 = WGEN_Expand_Ptr_To_Member_Func_Call_Expr(exp_opnd1, 0,
06223 Widen_Mtype(desc), desc);
06224 } else
06225 {
06226 gs_t lhs = gs_tree_operand (exp, 0);
06227 if (gs_tree_code(lhs) == GS_INDIRECT_REF &&
06228 gs_tree_code(gs_tree_operand (lhs, 0)) == GS_CALL_EXPR ) {
06229
06230
06231
06232
06233
06234
06235
06236
06237
06238
06239
06240
06241
06242 WN* call = WGEN_Expand_Expr(gs_tree_operand(lhs, 0));
06243 ST* preg_st;
06244 PREG_NUM preg;
06245 TY_IDX call_ty_idx = Get_TY (gs_tree_type (gs_tree_operand (lhs, 0)));
06246 preg_st = MTYPE_To_PREG(Pointer_Mtype);
06247 preg = Create_Preg (Pointer_Mtype, NULL);
06248 WGEN_Set_ST_Addr_Saved (call);
06249 WN* stid = WN_Stid (Pointer_Mtype, preg, preg_st, call_ty_idx, call);
06250 WGEN_Stmt_Append(stid, Get_Srcpos());
06251 call_return_val = WN_Ldid(Pointer_Mtype, preg, preg_st, call_ty_idx);
06252 }
06253
06254 wn1 = WGEN_Expand_Expr (gs_tree_operand (exp, 1));
06255 }
06256
06257 #ifdef KEY // wgen bugs 10849, 10893, 10908
06258 if (wn1 && WN_operator(wn1) == OPR_INTCONST &&
06259 TY_size(Get_TY(gs_tree_type(gs_tree_operand(exp, 1)))) == 0)
06260 break;
06261 #endif
06262 wn = WGEN_Lhs_Of_Modify_Expr(code, gs_tree_operand (exp, 0), call_return_val, need_result,
06263 0, 0, 0, FALSE, wn1, 0, FALSE, FALSE);
06264 }
06265 break;
06266
06267
06268
06269 case GS_BIT_FIELD_REF:
06270 {
06271 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), TRUE, nop_ty_idx,
06272 component_ty_idx, component_offset,
06273 field_id, FALSE);
06274 ty_idx = Get_TY (gs_tree_type(exp));
06275 TYPE_ID rtype = TY_mtype(ty_idx);
06276 UINT siz = TY_size(ty_idx);
06277 TYPE_ID desc;
06278 if (siz <= 8) {
06279 if (MTYPE_signed(rtype))
06280 desc = Mtype_AlignmentClass(siz, MTYPE_CLASS_INTEGER);
06281 else desc = Mtype_AlignmentClass(siz, MTYPE_CLASS_UNSIGNED_INTEGER);
06282 rtype = Widen_Mtype(desc);
06283 }
06284 else desc = rtype;
06285 #ifdef KEY
06286
06287 while (1) {
06288 if ((WN_operator(wn) == OPR_CVT)
06289 && (desc == rtype))
06290 {
06291 WN * del = wn;
06292 wn = WN_kid0 (wn);
06293 WN_Delete (del);
06294 }
06295 else break;
06296 }
06297 #endif // KEY
06298 WN_set_rtype(wn, rtype);
06299 if (WN_desc(wn) != MTYPE_V)
06300 WN_set_desc(wn, desc);
06301 INT bofst = gs_get_integer_value(gs_tree_operand(exp, 2));
06302 INT bsiz =gs_get_integer_value(gs_tree_operand(exp, 1));
06303 if ((bsiz & 7) == 0 &&
06304 MTYPE_size_min(desc) % bsiz == 0 &&
06305 bofst % bsiz == 0) {
06306
06307 if (WN_desc(wn) != MTYPE_V)
06308 if (MTYPE_signed(rtype))
06309 WN_set_desc(wn, Mtype_AlignmentClass(bsiz >> 3, MTYPE_CLASS_INTEGER));
06310 else WN_set_desc(wn, Mtype_AlignmentClass(bsiz >> 3, MTYPE_CLASS_UNSIGNED_INTEGER));
06311 WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
06312 } else {
06313 #ifdef KEY
06314
06315
06316
06317
06318 mUINT16 base_type_size = MTYPE_bit_size (desc);
06319 WN_load_offset(wn) += (bofst / base_type_size) * MTYPE_byte_size (desc);
06320 bofst = bofst % base_type_size;
06321 #endif
06322 if (WN_operator(wn) == OPR_LDID)
06323 WN_set_operator(wn, OPR_LDBITS);
06324 else WN_set_operator(wn, OPR_ILDBITS);
06325 WN_set_bit_offset_size(wn, bofst, bsiz);
06326 #ifdef KEY
06327 TY_IDX ty = MTYPE_To_TY (WN_desc(wn));
06328 WN_set_ty (wn, ty);
06329 if (WN_operator(wn) == OPR_ILDBITS)
06330 WN_set_load_addr_ty(wn, Make_Pointer_Type(ty));
06331 break;
06332 #endif
06333 }
06334 if (MTYPE_byte_size (WN_desc(wn)) != TY_size(WN_ty(wn)))
06335
06336 #ifdef KEY
06337 {
06338 TY_IDX ty = MTYPE_To_TY (WN_desc(wn));
06339 if ((TY_kind(Ty_Table[WN_ty(wn)]) == KIND_STRUCT)
06340 && (TY_kind(Ty_Table[ty]) != KIND_STRUCT))
06341
06342
06343 WN_set_field_id (wn, 0);
06344 WN_set_ty (wn, ty);
06345
06346 if (WN_operator(wn) == OPR_ILOAD || WN_operator(wn) == OPR_ILDBITS)
06347 WN_set_load_addr_ty(wn, Make_Pointer_Type(ty));
06348 }
06349 #else
06350 WN_set_ty (wn, MTYPE_To_TY (WN_desc(wn)));
06351 #endif
06352 }
06353 break;
06354
06355
06356
06357 case GS_ARRAY_REF:
06358 {
06359 UINT xtra_BE_ofst = 0;
06360 TY_IDX elem_ty_idx;
06361
06362 wn0 = WGEN_Array_Expr(exp, &elem_ty_idx, 0, 0, 0);
06363
06364
06365 TY_IDX hi_ty_idx = Get_TY (gs_tree_type(exp));
06366 #if 1 // wgen bug 10448
06367 if (gs_tree_this_volatile(exp))
06368 Set_TY_is_volatile(hi_ty_idx);
06369 else Clear_TY_is_volatile(hi_ty_idx);
06370 #endif
06371 desc_ty_idx = component_ty_idx;
06372 if (desc_ty_idx == 0)
06373 desc_ty_idx = hi_ty_idx;
06374
06375 if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
06376 ty_idx = desc_ty_idx;
06377 else {
06378 ty_idx = nop_ty_idx;
06379 if (ty_idx == 0)
06380 ty_idx = desc_ty_idx;
06381 }
06382
06383 if (! is_bit_field) {
06384 if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
06385 if (Target_Byte_Sex == BIG_ENDIAN)
06386 xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
06387 desc_ty_idx = ty_idx;
06388 }
06389 }
06390 else {
06391 if (TY_size(desc_ty_idx) > TY_size(ty_idx))
06392 ty_idx = desc_ty_idx;
06393 }
06394
06395 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
06396 TYPE_ID desc = TY_mtype(desc_ty_idx);
06397 if (MTYPE_is_integral(desc)) {
06398 if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
06399 if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
06400 is_bit_field)
06401 rtype = Mtype_TransferSign(desc, rtype);
06402 else desc = Mtype_TransferSign(rtype, desc);
06403 }
06404 }
06405
06406 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
06407 ("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
06408 wn = WN_CreateIload(OPR_ILOAD, rtype,
06409 is_bit_field ? MTYPE_BS : desc,
06410 component_offset+xtra_BE_ofst,
06411 field_id != 0 ? hi_ty_idx : ty_idx,
06412 Make_Pointer_Type(elem_ty_idx, FALSE),
06413 wn0, field_id);
06414 }
06415 break;
06416
06417 case GS_AGGR_INIT_EXPR:
06418 case GS_CALL_EXPR:
06419 {
06420 gs_t arglist = gs_tree_operand (exp, 1);
06421 TYPE_ID ret_mtype;
06422 WN *call_wn;
06423 WN *arg_wn;
06424 TY_IDX arg_ty_idx;
06425 TYPE_ID arg_mtype;
06426 INT num_args = 0;
06427 INT num_handlers = 0;
06428 INT i;
06429 gs_t list;
06430 arg0 = gs_tree_operand (exp, 0);
06431 gs_code_t code0 = gs_tree_code (arg0);
06432
06433 BOOL return_in_mem = FALSE;
06434 #ifdef KEY
06435 ST *ret_st = NULL;
06436 if (gs_tree_code(exp) == GS_AGGR_INIT_EXPR &&
06437 gs_aggr_init_via_ctor_p(exp) &&
06438 !is_aggr_init_via_ctor)
06439 {
06440 Is_True (gs_tree_operand(exp,2),
06441 ("WGEN_Expand_Expr: null slot for AGGR_INIT_EXPR"));
06442
06443 gs_set_tree_value (arglist, gs_tree_operand (exp, 2));
06444
06445 is_aggr_init_via_ctor = true;
06446 }
06447 processing_function_prototype = TRUE;
06448 #endif
06449 for (list = gs_tree_operand (exp, 1); list; list = gs_tree_chain (list)) {
06450 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
06451 if (!WGEN_Keep_Zero_Length_Structs &&
06452 TY_mtype (arg_ty_idx) == MTYPE_M &&
06453 TY_size (arg_ty_idx) == 0) {
06454
06455 }
06456 else
06457 num_args++;
06458 }
06459 #ifdef KEY
06460 processing_function_prototype = FALSE;
06461 if (gs_tree_code(exp) == GS_AGGR_INIT_EXPR)
06462 {
06463
06464 ty_idx = Get_TY(gs_tree_type(gs_tree_type(gs_tree_type(arg0))));
06465 }
06466 else
06467 #endif
06468 ty_idx = Get_TY(gs_tree_type(exp));
06469 #if 1 // wgen bug 10448
06470 if (gs_tree_this_volatile(exp))
06471 Set_TY_is_volatile(ty_idx);
06472 else Clear_TY_is_volatile(ty_idx);
06473 #endif
06474 if (need_result) {
06475 if (!WGEN_Keep_Zero_Length_Structs &&
06476 TY_mtype (ty_idx) == MTYPE_M &&
06477 TY_size (ty_idx) == 0) {
06478
06479 ret_mtype = MTYPE_V;
06480 }
06481 else
06482 ret_mtype = TY_mtype (ty_idx);
06483 #ifdef KEY
06484
06485
06486 if (TY_return_in_mem (ty_idx)) {
06487 ret_mtype = MTYPE_V;
06488 return_in_mem = TRUE;
06489 num_args++;
06490 if (gs_tree_code(exp) == GS_AGGR_INIT_EXPR && !target_wn)
06491 {
06492
06493 gs_t slot = gs_tree_operand(exp,2);
06494 FmtAssert (gs_tree_code(slot) == GS_VAR_DECL,
06495 ("WGEN_Expand_Expr: Expected VAR_DECL for "
06496 "AGGR_INIT_EXPR slot"));
06497 ST * target_st = Get_ST(slot);
06498 target_wn = WN_Lda (Pointer_Mtype, 0, target_st, 0);
06499 }
06500 }
06501 #endif
06502 }
06503 else
06504 ret_mtype = MTYPE_V;
06505 st = NULL;
06506 if (code0 == GS_ADDR_EXPR &&
06507 gs_tree_code (gs_tree_operand (arg0, 0))) {
06508 gs_t func = gs_tree_operand (arg0, 0);
06509 BOOL intrinsic_op = FALSE;
06510 BOOL whirl_generated = FALSE;
06511 INTRINSIC iopc = INTRINSIC_NONE;
06512
06513 #ifdef KEY
06514
06515
06516 TYPE_ID cvt_to = MTYPE_UNKNOWN;
06517
06518 if (gs_decl_assembler_name(func))
06519 REFERENCED_BY_WHIRL(gs_decl_assembler_name(func)) = 1;
06520 #endif
06521
06522 if (gs_decl_built_in (func)) {
06523 if (gs_decl_built_in_class(func) != GSBI_CLASS_BUILT_IN_MD) {
06524
06525 switch (gs_decl_function_code (func)) {
06526
06527 case GSBI_END_BUILTINS:
06528 break;
06529
06530 case GSBI_BUILT_IN_STDARG_START:
06531 #ifdef KEY
06532 case GSBI_BUILT_IN_VA_START:
06533 #endif
06534 {
06535 #ifdef TARG_X8664
06536 if( TARGET_64BIT ){
06537 iopc = INTRN_VA_START;
06538 break;
06539 }
06540 #endif
06541 arg1 = gs_tree_value (arglist);
06542 arg2 = gs_tree_value (gs_tree_chain (arglist));
06543 WN *arg_wn = WGEN_Expand_Expr (arg1);
06544 TY_IDX arg_ty_idx = Get_TY (gs_tree_type (arg1));
06545 while (gs_tree_code(arg2) == GS_NOP_EXPR
06546 || gs_tree_code(arg2) == GS_CONVERT_EXPR
06547 || gs_tree_code(arg2) == GS_NON_LVALUE_EXPR
06548 || gs_tree_code(arg2) == GS_INDIRECT_REF)
06549 arg2 = gs_tree_operand (arg2, 0);
06550 ST *st2 = Get_ST (arg2);
06551 #ifdef TARG_X8664
06552 const int align = TARGET_64BIT ? 8 : 4;
06553 wn = WN_Lda (Pointer_Mtype,
06554 ((TY_size (ST_type (st2)) + align-1) & (-align)),
06555 st2);
06556 #else
06557 wn = WN_Lda (Pointer_Mtype,
06558 ((TY_size (ST_type (st2)) + 7) & (-8)),
06559 st2);
06560 #endif
06561 if (WN_operator (arg_wn) == OPR_LDA) {
06562 wn = WN_Stid (Pointer_Mtype, WN_offset (arg_wn),
06563 WN_st (arg_wn), arg_ty_idx, wn);
06564 }
06565 else {
06566 wn = WN_CreateIstore (OPR_ISTORE, MTYPE_V,
06567 Pointer_Mtype, 0, arg_ty_idx,
06568 wn, arg_wn, 0);
06569 }
06570
06571 WGEN_Stmt_Append (wn, Get_Srcpos());
06572 whirl_generated = TRUE;
06573 wn = NULL;
06574 break;
06575 }
06576
06577 case GSBI_BUILT_IN_VA_COPY:
06578 {
06579 arg1 = gs_tree_value (arglist);
06580 arg2 = gs_tree_value (gs_tree_chain (arglist));
06581 TY_IDX arg_ty_idx = Get_TY (gs_tree_type (arg1));
06582
06583
06584 #ifdef TARG_X8664
06585
06586
06587
06588
06589
06590
06591 if( !TARGET_64BIT ){
06592 FmtAssert( gs_tree_code(arglist) != GS_ARRAY_TYPE,
06593 ("unexpected array type for intrinsic 'va_copy'") );
06594 WN* addr = WGEN_Expand_Expr( arg1 );
06595 WN* value = WGEN_Expand_Expr( arg2 );
06596 wn = WN_CreateIstore( OPR_ISTORE, MTYPE_V, Pointer_Mtype,
06597 0, arg_ty_idx, value, addr, 0 );
06598
06599 WGEN_Stmt_Append( wn, Get_Srcpos() );
06600 whirl_generated = TRUE;
06601 wn = NULL;
06602 break;
06603 }
06604 #endif // TARG_X8664
06605
06606 #ifdef TARG_IA64
06607
06608
06609 FmtAssert( gs_tree_code(arglist) != GS_ARRAY_TYPE,
06610 ("unexpected array type for intrinsic 'va_copy'") );
06611 WN* addr = WGEN_Expand_Expr( arg1 );
06612 WN* value = WGEN_Expand_Expr( arg2 );
06613 wn = WN_CreateIstore( OPR_ISTORE, MTYPE_V, Pointer_Mtype,
06614 0, arg_ty_idx, value, addr, 0 );
06615
06616 WGEN_Stmt_Append( wn, Get_Srcpos() );
06617 whirl_generated = TRUE;
06618 wn = NULL;
06619 break;
06620 #endif
06621
06622 WN *dst = WN_CreateParm (Pointer_Mtype, WGEN_Expand_Expr (arg1),
06623 arg_ty_idx, WN_PARM_BY_VALUE);
06624 WN *src = WN_CreateParm (Pointer_Mtype, WGEN_Expand_Expr (arg2),
06625 arg_ty_idx, WN_PARM_BY_VALUE);
06626 WN *size = WN_CreateParm (MTYPE_I4,
06627 WN_Intconst(MTYPE_I4,TY_size(TY_pointed(arg_ty_idx))),
06628 Be_Type_Tbl(MTYPE_I4), WN_PARM_BY_VALUE);
06629 wn = WN_Create (OPR_INTRINSIC_CALL, ret_mtype, MTYPE_V, 3);
06630 WN_intrinsic (wn) = INTRN_MEMCPY;
06631 WN_kid0 (wn) = dst;
06632 WN_kid1 (wn) = src;
06633 WN_kid2 (wn) = size;
06634 WGEN_Stmt_Append (wn, Get_Srcpos());
06635 whirl_generated = TRUE;
06636 wn = NULL;
06637 break;
06638 }
06639
06640 case GSBI_BUILT_IN_VA_END:
06641 {
06642 arg1 = gs_tree_value (arglist);
06643 wn = WN_CreateEval ( WGEN_Expand_Expr (arg1) );
06644 WGEN_Stmt_Append (wn, Get_Srcpos());
06645 whirl_generated = TRUE;
06646 wn = NULL;
06647 break;
06648 }
06649
06650 case GSBI_BUILT_IN_NEXT_ARG:
06651 {
06652 gs_t last_parm = gs_tree_last
06653 (gs_decl_arguments(Current_Function_Decl()));
06654 gs_code_t last_parm_code = gs_tree_code(last_parm);
06655 while (last_parm_code == GS_NOP_EXPR
06656 || last_parm_code == GS_CONVERT_EXPR
06657 || last_parm_code == GS_NON_LVALUE_EXPR
06658 || last_parm_code == GS_INDIRECT_REF)
06659 last_parm = gs_tree_operand (last_parm, 0);
06660 ST *st = Get_ST (last_parm);
06661 arg_wn = WN_Lda (Pointer_Mtype, ST_ofst(st), st);
06662 wn = WN_Binary (OPR_ADD, Pointer_Mtype, arg_wn,
06663 WN_Intconst (Pointer_Mtype,
06664 Parameter_Size(ST_size(st))));
06665 whirl_generated = TRUE;
06666 break;
06667 }
06668
06669 case GSBI_BUILT_IN_ALLOCA:
06670 Set_PU_has_alloca (Get_Current_PU ());
06671 Set_PU_has_user_alloca (Get_Current_PU ());
06672 arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
06673 wn = WN_CreateAlloca (arg_wn);
06674 whirl_generated = TRUE;
06675 break;
06676
06677 case GSBI_BUILT_IN_MEMCPY:
06678 iopc = INTRN_MEMCPY;
06679 break;
06680
06681 case GSBI_BUILT_IN_MEMCMP:
06682 iopc = INTRN_MEMCMP;
06683 break;
06684
06685 case GSBI_BUILT_IN_MEMSET:
06686 iopc = INTRN_MEMSET;
06687 break;
06688
06689 case GSBI_BUILT_IN_STRCPY:
06690 iopc = INTRN_STRCPY;
06691 break;
06692
06693 case GSBI_BUILT_IN_STRCMP:
06694 #ifdef GPLUSPLUS_FE
06695 iopc = INTRN_STRCMP;
06696 #else
06697 if (arglist == 0
06698
06699 || gs_tree_code (gs_tree_type (gs_tree_value (arglist))) != GS_POINTER_TYPE
06700 || gs_tree_chain (arglist) == 0
06701 || gs_tree_code (gs_tree_type (gs_tree_value (gs_tree_chain (arglist)))) != GS_POINTER_TYPE)
06702 break;
06703 else {
06704 arg1 = gs_tree_value (arglist);
06705 arg2 = gs_tree_value (gs_tree_chain (arglist));
06706 gs_t len1 = c_strlen (arg1);
06707 if (len1) {
06708 gs_t len2 = c_strlen (arg2);
06709 if (len2) {
06710 char *ptr1 = get_string_pointer (WGEN_Expand_Expr (arg1));
06711 char *ptr2 = get_string_pointer (WGEN_Expand_Expr (arg2));
06712 if (ptr1 && ptr2) {
06713 wn = WN_Intconst (MTYPE_I4,
06714 strcmp (ptr1, ptr2));
06715 whirl_generated = TRUE;
06716 break;
06717 }
06718 }
06719 }
06720 iopc = INTRN_STRCMP;
06721
06722 }
06723 #endif
06724 break;
06725
06726 case GSBI_BUILT_IN_STRLEN:
06727 #ifdef GPLUSPLUS_FE
06728 iopc = INTRN_STRLEN;
06729 #else
06730 if (arglist == 0
06731
06732 || gs_tree_code (gs_tree_type (gs_tree_value (arglist))) != GS_POINTER_TYPE)
06733 break;
06734 else {
06735 gs_t src = gs_tree_value (arglist);
06736 gs_t len = c_strlen (src);
06737 if (len) {
06738 wn = WGEN_Expand_Expr (len);
06739 whirl_generated = TRUE;
06740 }
06741 else {
06742 iopc = INTRN_STRLEN;
06743
06744 }
06745 }
06746 #endif
06747 break;
06748
06749 #ifdef KEY
06750 case GSBI_BUILT_IN_FLOOR:
06751 #ifdef FE_GNU_4_2_0
06752 case GSBI_BUILT_IN_LFLOOR:
06753 #endif
06754 {
06755 arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
06756 #if defined TARG_MIPS // bug 12594: call library function for floor
06757 iopc = INTRN_FLOOR;
06758 intrinsic_op = TRUE;
06759 #else
06760 wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_F8, arg_wn);
06761 whirl_generated = TRUE;
06762 #endif
06763 break;
06764 }
06765
06766 case GSBI_BUILT_IN_FLOORF:
06767 #ifdef FE_GNU_4_2_0
06768 case GSBI_BUILT_IN_LFLOORF:
06769 #endif
06770 {
06771 arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
06772 #if defined TARG_MIPS // bug 12594: call library function for floor
06773 iopc = INTRN_FLOORF;
06774 intrinsic_op = TRUE;
06775 #else
06776
06777 wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_F4, arg_wn);
06778 whirl_generated = TRUE;
06779 #endif
06780 break;
06781 }
06782
06783 #ifndef TARG_MIPS // Bug 9071: MIPS needs quad emulation for floor operation
06784 case GSBI_BUILT_IN_FLOORL:
06785 #ifdef FE_GNU_4_2_0
06786 case GSBI_BUILT_IN_LFLOORL:
06787 #endif
06788 arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
06789 #ifdef TARG_IA64
06790 wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_F10, arg_wn);
06791 #else
06792 wn = WN_CreateExp1 (OPR_FLOOR, ret_mtype, MTYPE_FQ, arg_wn);
06793 #endif
06794 whirl_generated = TRUE;
06795 break;
06796 #endif // !TARG_MIPS
06797 #endif
06798
06799 case GSBI_BUILT_IN_SQRT:
06800 case GSBI_BUILT_IN_SQRTF:
06801 #ifndef TARG_MIPS // MIPS needs quad emulation for sqrt operation
06802 case GSBI_BUILT_IN_SQRTL:
06803 #endif
06804 if (! gs_flag_errno_math(program)) {
06805 arg_wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
06806 wn = WN_CreateExp1 (OPR_SQRT, ret_mtype, MTYPE_V, arg_wn);
06807 }
06808 else wn = WGEN_Expand_Math_Errno_Sqrt(exp, ty_idx, ret_mtype);
06809 whirl_generated = TRUE;
06810 break;
06811
06812 #ifdef KEY
06813 case GSBI_BUILT_IN_SINF:
06814 #endif
06815 case GSBI_BUILT_IN_SIN:
06816 intrinsic_op = TRUE;
06817 #ifdef TARG_X8664
06818 if (!Force_IEEE_Comparisons)
06819 {
06820 iopc = INTRN_SINL;
06821 if (ret_mtype != MTYPE_FQ)
06822 {
06823
06824 cvt_to = ret_mtype;
06825 ret_mtype = MTYPE_FQ;
06826 }
06827 break;
06828 }
06829 #endif
06830 #ifdef KEY // bug 11305
06831 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06832 #endif
06833 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4SIN;
06834 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8SIN;
06835 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'sin'");
06836 break;
06837
06838 case GSBI_BUILT_IN_COS:
06839 #ifdef KEY
06840 case GSBI_BUILT_IN_COSF:
06841 #endif
06842 intrinsic_op = TRUE;
06843 #ifdef TARG_X8664
06844 if (!Force_IEEE_Comparisons)
06845 {
06846 iopc = INTRN_COSL;
06847 if (ret_mtype != MTYPE_FQ)
06848 {
06849
06850 cvt_to = ret_mtype;
06851 ret_mtype = MTYPE_FQ;
06852 }
06853 break;
06854 }
06855 #endif
06856 #ifdef KEY // bug 11305
06857 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06858 #endif
06859 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4COS;
06860 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8COS;
06861 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'cos'");
06862 break;
06863
06864 #ifdef KEY
06865 case GSBI_BUILT_IN_ACOS:
06866 case GSBI_BUILT_IN_ACOSF:
06867 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06868 if (! gs_flag_errno_math(program)) {
06869 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4ACOS;
06870 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8ACOS;
06871 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'acos'");
06872 intrinsic_op = TRUE;
06873 }
06874 break;
06875
06876 case GSBI_BUILT_IN_ASIN:
06877 case GSBI_BUILT_IN_ASINF:
06878 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06879 if (! gs_flag_errno_math(program)) {
06880 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4ASIN;
06881 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8ASIN;
06882 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'asin'");
06883 intrinsic_op = TRUE;
06884 }
06885 break;
06886
06887 case GSBI_BUILT_IN_ATAN:
06888 case GSBI_BUILT_IN_ATANF:
06889 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06890 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4ATAN;
06891 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8ATAN;
06892 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'log'");
06893 intrinsic_op = TRUE;
06894 break;
06895
06896 case GSBI_BUILT_IN_LOG10:
06897 case GSBI_BUILT_IN_LOG10F:
06898 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06899 if (! gs_flag_errno_math(program)) {
06900 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4LOG10;
06901 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8LOG10;
06902 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'log10'");
06903 intrinsic_op = TRUE;
06904 }
06905 break;
06906
06907 case GSBI_BUILT_IN_LOG:
06908 case GSBI_BUILT_IN_LOGF:
06909 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06910
06911 if (! gs_flag_errno_math(program)) {
06912 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4LOG;
06913 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8LOG;
06914 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'log'");
06915 intrinsic_op = TRUE;
06916 }
06917 break;
06918
06919 case GSBI_BUILT_IN_EXP:
06920 case GSBI_BUILT_IN_EXPF:
06921
06922
06923
06924
06925 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06926
06927 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4EXP;
06928 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8EXP;
06929 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'exp'");
06930 intrinsic_op = TRUE;
06931 break;
06932
06933 case GSBI_BUILT_IN_POW:
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06944 if (! gs_flag_errno_math(program)) {
06945 FmtAssert(ret_mtype == MTYPE_F8,
06946 ("unexpected mtype for intrinsic 'pow'"));
06947 iopc = INTRN_F8EXPEXPR;
06948 intrinsic_op = TRUE;
06949 }
06950 break;
06951
06952 case GSBI_BUILT_IN_POWI:
06953 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
06954 FmtAssert(ret_mtype == MTYPE_F8,
06955 ("unexpected mtype for intrinsic 'powi'"));
06956 iopc = INTRN_F8F8I4EXPEXPR;
06957 intrinsic_op = TRUE;
06958 break;
06959
06960 case GSBI_BUILT_IN_POWIF:
06961 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F4;
06962 FmtAssert(ret_mtype == MTYPE_F4,
06963 ("unexpected mtype for intrinsic 'powif'"));
06964 intrinsic_op = TRUE;
06965 iopc = INTRN_F4F4I4EXPEXPR;
06966 break;
06967
06968 case GSBI_BUILT_IN_POWIL:
06969 #ifdef TARG_IA64
06970
06971 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F10;
06972 FmtAssert(ret_mtype == MTYPE_F10,
06973 ("unexpected mtype for intrinsic 'powil'"));
06974 #else
06975 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_FQ;
06976 FmtAssert(ret_mtype == MTYPE_FQ,
06977 ("unexpected mtype for intrinsic 'powil'"));
06978 #endif
06979 iopc = INTRN_FQFQI4EXPEXPR;
06980 intrinsic_op = TRUE;
06981 iopc = INTRN_FQFQI4EXPEXPR;
06982 break;
06983 #endif // KEY
06984
06985 case GSBI_BUILT_IN_CONSTANT_P:
06986 {
06987 gs_t arg = gs_tree_value (gs_tree_operand (exp, 1));
06988 arg = gs_strip_nops (arg);
06989 if (gs_really_constant_p (arg)
06990 || (gs_tree_code (arg) == GS_ADDR_EXPR
06991 && gs_tree_code (gs_tree_operand (arg, 0)) == GS_STRING_CST))
06992 {
06993 wn = WN_Intconst (MTYPE_I4, 1);
06994 whirl_generated = TRUE;
06995 }
06996 #ifdef KEY
06997
06998
06999 else
07000 {
07001 iopc = INTRN_CONSTANT_P;
07002 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_I4;
07003 intrinsic_op = TRUE;
07004 }
07005 #else
07006
07007 else
07008 wn = WN_Intconst (MTYPE_I4, 0);
07009
07010 whirl_generated = TRUE;
07011 #endif // KEY
07012 break;
07013 }
07014 #if 0
07015 case BUILT_IN_LOCK_TEST_AND_SET:
07016 wn = emit_builtin_lock_test_and_set (exp, num_args-2);
07017 whirl_generated = TRUE;
07018 break;
07019
07020 case BUILT_IN_LOCK_RELEASE:
07021 emit_builtin_lock_release (exp, num_args-1);
07022 whirl_generated = TRUE;
07023 break;
07024
07025 case BUILT_IN_COMPARE_AND_SWAP:
07026 wn = emit_builtin_compare_and_swap (exp, num_args-3);
07027 whirl_generated = TRUE;
07028 break;
07029 #endif
07030
07031 #ifdef FE_GNU_4_2_0
07032
07033 case GSBI_BUILT_IN_FETCH_AND_ADD_4:
07034 wn = emit_builtin_sync_fetch_op (INTRN_FETCH_AND_ADD_I4, exp, num_args-2);
07035 whirl_generated = TRUE;
07036 break;
07037 case GSBI_BUILT_IN_FETCH_AND_ADD_8:
07038 wn = emit_builtin_sync_fetch_op (INTRN_FETCH_AND_ADD_I8, exp, num_args-2);
07039 whirl_generated = TRUE;
07040 break;
07041
07042 case GSBI_BUILT_IN_ADD_AND_FETCH_4:
07043 wn = emit_builtin_sync_fetch_op (INTRN_ADD_AND_FETCH_I4, exp, num_args-2);
07044 whirl_generated = TRUE;
07045 break;
07046 case GSBI_BUILT_IN_ADD_AND_FETCH_8:
07047 wn = emit_builtin_sync_fetch_op (INTRN_ADD_AND_FETCH_I8, exp, num_args-2);
07048 whirl_generated = TRUE;
07049 break;
07050 #endif
07051
07052 #ifdef FE_GNU_4_2_0
07053 case GSBI_BUILT_IN_SYNCHRONIZE:
07054 emit_builtin_synchronize (exp, num_args);
07055 whirl_generated = TRUE;
07056 break;
07057
07058 case GSBI_BUILT_IN_GOMP_BARRIER:
07059 WGEN_expand_barrier ();
07060 whirl_generated = TRUE;
07061 break;
07062 #endif
07063
07064 case GSBI_BUILT_IN_RETURN_ADDRESS:
07065 i = gs_get_integer_value (gs_tree_value (gs_tree_operand (exp, 1)));
07066 if (i > 0) {
07067
07068
07069
07070 Warning("non-zero levels not supported for builtin_return_address");
07071 wn = WN_Intconst(Pointer_Mtype, 0);
07072 }
07073 else {
07074 st = WGEN_Get_Return_Address_ST (i);
07075 wn = WN_Ldid (Pointer_Mtype, 0, st, ST_type (st));
07076 }
07077 whirl_generated = TRUE;
07078 break;
07079
07080 #ifdef KEY
07081 case GSBI_BUILT_IN_EXTRACT_RETURN_ADDR:
07082 list = gs_tree_operand (exp, 1);
07083 wn = WGEN_Expand_Expr (gs_tree_value (list));
07084 wn = WN_Binary (OPR_BAND, Pointer_Mtype, wn,
07085 WN_Intconst(Pointer_Mtype, -2));
07086 whirl_generated = TRUE;
07087 break;
07088
07089 case GSBI_BUILT_IN_FRAME_ADDRESS:
07090 Set_PU_has_alloca(Get_Current_PU());
07091 iopc = MTYPE_byte_size(Pointer_Mtype) == 4 ?
07092 INTRN_U4READFRAMEPOINTER : INTRN_U8READFRAMEPOINTER;
07093 intrinsic_op = TRUE;
07094 break;
07095 case GSBI_BUILT_IN_APPLY_ARGS:
07096 Set_PU_has_alloca(Get_Current_PU());
07097 iopc = INTRN_APPLY_ARGS;
07098 break;
07099 case GSBI_BUILT_IN_APPLY:
07100 {
07101 WN *load_wn, *sp_addr;
07102
07103 Set_PU_has_alloca(Get_Current_PU());
07104
07105 iopc = INTRN_APPLY;
07106 call_wn = WN_Create (OPR_INTRINSIC_CALL, ret_mtype, MTYPE_V,
07107 num_args);
07108 WN_intrinsic (call_wn) = iopc;
07109 WN_Set_Linenum (call_wn, Get_Srcpos());
07110 WN_Set_Call_Default_Flags (call_wn);
07111 i = 0;
07112 BOOL generate_mload = FALSE;
07113 WN *kid1 = NULL;
07114 WN *kid2 = NULL;
07115 for (list = gs_tree_operand (exp, 1);
07116 list;
07117 list = gs_tree_chain (list)) {
07118 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
07119 if (i == 1)
07120 kid1 = arg_wn;
07121 if (i == 2 &&
07122 WN_operator(arg_wn) != OPR_INTCONST) {
07123 generate_mload = TRUE;
07124 kid2 = arg_wn;
07125 } else if (i == 2)
07126 kid2 = arg_wn;
07127 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
07128 arg_mtype = TY_mtype(arg_ty_idx);
07129 arg_wn = WN_CreateParm (Mtype_comparison (arg_mtype),
07130 arg_wn,
07131 arg_ty_idx, WN_PARM_BY_VALUE);
07132 WN_kid (call_wn, i++) = arg_wn;
07133 }
07134
07135
07136 TY_IDX ty_idx =
07137 Make_Pointer_Type (Be_Type_Tbl (MTYPE_V), FALSE);
07138 ST* alloca_st_0 =
07139 Gen_Temp_Symbol (ty_idx,
07140 "__builtin_apply_alloca0");
07141 #ifdef FE_GNU_4_2_0
07142 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL,
07143 alloca_st_0);
07144 #endif
07145 WN *alloca_0 =
07146 WN_CreateAlloca (WN_CreateIntconst (OPC_I4INTCONST, 0));
07147 WN *alloca_kid0 = alloca_0;
07148 alloca_kid0 =
07149 WN_Stid (Pointer_Mtype,
07150 0, alloca_st_0, ty_idx, alloca_kid0);
07151 WGEN_Stmt_Append (alloca_kid0, Get_Srcpos());
07152 ST *alloca_st_1 =
07153 Gen_Temp_Symbol (ty_idx,
07154 "__builtin_apply_alloca1");
07155 #ifdef FE_GNU_4_2_0
07156 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL,
07157 alloca_st_1);
07158 #endif
07159 WN *alloca_1 = WN_CreateAlloca (kid2);
07160 WN *alloca_kid1 = alloca_1;
07161 alloca_kid1 = WN_Stid (Pointer_Mtype,
07162 0, alloca_st_1, ty_idx, alloca_kid1);
07163 WGEN_Stmt_Append (alloca_kid1, Get_Srcpos());
07164
07165
07166 kid1 =
07167 WN_CreateIload (OPR_ILOAD, MTYPE_I4, MTYPE_I4, 0,
07168 MTYPE_To_TY(MTYPE_I4),
07169 Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)),
07170 kid1, 0);
07171 load_wn =
07172 WN_CreateMload (0,
07173 Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)),
07174 kid1, kid2);
07175 sp_addr = WN_LdidPreg(MTYPE_U4, 29);
07176 WGEN_Stmt_Append(WN_CreateMstore (0,
07177 Make_Pointer_Type(MTYPE_To_TY(MTYPE_U8)),
07178 load_wn,
07179 sp_addr,
07180 kid2),
07181 Get_Srcpos());
07182
07183 WGEN_Stmt_Append (call_wn, Get_Srcpos());
07184
07185 call_wn = WN_Create (OPR_ICALL, ret_mtype, MTYPE_V, 1);
07186 WN_kid(call_wn, 0) =
07187 WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
07188 WN_set_ty (call_wn, TY_pointed(Get_TY(
07189 gs_tree_type (gs_tree_value(gs_tree_operand (exp, 1))))));
07190 WGEN_Stmt_Append (call_wn, Get_Srcpos());
07191
07192 TY_IDX tyi;
07193 TY& ty = New_TY(tyi);
07194 TY_Init(ty, 16, KIND_STRUCT, MTYPE_M,
07195 Save_Str("__apply"));
07196 Set_TY_align(tyi, 8);
07197 ST *tmpst = New_ST(CURRENT_SYMTAB);
07198 ST_Init(tmpst, TY_name_idx(ty),
07199 CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, tyi);
07200 Set_ST_is_temp_var(tmpst);
07201 WN *load, *store;
07202 load = WN_LdidPreg(MTYPE_I8, 2);
07203 store = WN_Stid(MTYPE_I8,
07204 (WN_OFFSET)0, tmpst, Spill_Int_Type, load);
07205 WGEN_Stmt_Append (store, Get_Srcpos());
07206 load = WN_LdidPreg(MTYPE_F8, 32);
07207 store = WN_Stid(MTYPE_F8,
07208 (WN_OFFSET)8, tmpst, Spill_Int_Type, load);
07209 WGEN_Stmt_Append (store, Get_Srcpos());
07210 wn = WN_Lda (Pointer_Mtype, 0, tmpst,
07211 Make_Pointer_Type (ST_type(tmpst), FALSE));
07212
07213
07214 WN *dealloca_wn = WN_CreateDealloca (2);
07215 WN_kid0 (dealloca_wn) =
07216 WN_Ldid (Pointer_Mtype,
07217 0, alloca_st_0, ST_type (alloca_st_0));
07218 WN_kid1 (dealloca_wn) =
07219 WN_Ldid (Pointer_Mtype,
07220 0, alloca_st_1, ST_type (alloca_st_1));
07221 WGEN_Stmt_Append (dealloca_wn, Get_Srcpos());
07222
07223 whirl_generated = TRUE;
07224 break;
07225 }
07226 case GSBI_BUILT_IN_RETURN:
07227 Set_PU_has_alloca(Get_Current_PU());
07228 iopc = INTRN_RETURN;
07229 break;
07230
07231
07232
07233
07234 case GSBI_BUILT_IN_ISGREATER:
07235 iopc = INTRN_ISGREATER;
07236 intrinsic_op = TRUE;
07237 break;
07238 case GSBI_BUILT_IN_ISGREATEREQUAL:
07239 iopc = INTRN_ISGREATEREQUAL;
07240 intrinsic_op = TRUE;
07241 break;
07242 case GSBI_BUILT_IN_ISLESS:
07243 iopc = INTRN_ISLESS;
07244 intrinsic_op = TRUE;
07245 break;
07246 case GSBI_BUILT_IN_ISLESSEQUAL:
07247 iopc = INTRN_ISLESSEQUAL;
07248 intrinsic_op = TRUE;
07249 break;
07250 case GSBI_BUILT_IN_ISLESSGREATER:
07251 iopc = INTRN_ISLESSGREATER;
07252 intrinsic_op = TRUE;
07253 break;
07254 case GSBI_BUILT_IN_ISUNORDERED:
07255 iopc = INTRN_ISUNORDERED;
07256 intrinsic_op = TRUE;
07257 break;
07258
07259 case GSBI_BUILT_IN_EXPECT:
07260 #ifdef KEY
07261 iopc = INTRN_EXPECT;
07262 intrinsic_op = TRUE;
07263 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_I4;
07264 #else
07265 wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
07266 whirl_generated = TRUE;
07267 #endif
07268 break;
07269
07270 case GSBI_BUILT_IN_FFS:
07271 iopc = INTRN_I4FFS;
07272 intrinsic_op = TRUE;
07273 if (ret_mtype == MTYPE_V)
07274 ret_mtype = MTYPE_I4;
07275 break;
07276 #ifndef KEY
07277 case GSBI_BUILT_IN_CTYPE_B_LOC:
07278 iopc = INTRN_CTYPE_B_LOC;
07279 intrinsic_op = TRUE;
07280 break;
07281 case GSBI_BUILT_IN_CTYPE_TOUPPER_LOC:
07282 iopc = INTRN_CTYPE_TOUPPER_LOC;
07283 intrinsic_op = TRUE;
07284 break;
07285
07286 case GSBI_BUILT_IN_CTYPE_TOLOWER_LOC:
07287 iopc = INTRN_CTYPE_TOLOWER_LOC;
07288 intrinsic_op = TRUE;
07289 break;
07290 #endif
07291 case GSBI_BUILT_IN_EXTEND_POINTER:
07292 wn = WGEN_Expand_Expr (gs_tree_value (gs_tree_operand (exp, 1)));
07293 whirl_generated = TRUE;
07294 break;
07295
07296 case GSBI_BUILT_IN_POPCOUNT:
07297 case GSBI_BUILT_IN_POPCOUNTL:
07298 case GSBI_BUILT_IN_POPCOUNTLL:
07299 iopc = INTRN_POPCOUNT;
07300 intrinsic_op = TRUE;
07301 break;
07302
07303 case GSBI_BUILT_IN_PARITY:
07304 case GSBI_BUILT_IN_PARITYL:
07305 case GSBI_BUILT_IN_PARITYLL:
07306 iopc = INTRN_PARITY;
07307 intrinsic_op = TRUE;
07308 break;
07309
07310 #ifdef TARG_MIPS
07311 case GSBI_BUILT_IN_CLZ:
07312 case GSBI_BUILT_IN_CLZL:
07313 case GSBI_BUILT_IN_CLZLL:
07314
07315 iopc = INTRN_CLZ32;
07316 intrinsic_op = TRUE;
07317 break;
07318
07319 case GSBI_BUILT_IN_CTZ:
07320 case GSBI_BUILT_IN_CTZL:
07321 case GSBI_BUILT_IN_CTZLL:
07322
07323 iopc = INTRN_CTZ;
07324 intrinsic_op = TRUE;
07325 break;
07326 #else
07327 case GSBI_BUILT_IN_CLZ:
07328
07329 iopc = INTRN_CLZ32;
07330 intrinsic_op = TRUE;
07331 break;
07332 case GSBI_BUILT_IN_CLZL:
07333
07334 iopc = TARGET_64BIT ? INTRN_CLZ : INTRN_CLZ32;
07335 intrinsic_op = TRUE;
07336 break;
07337 case GSBI_BUILT_IN_CLZLL:
07338 iopc = INTRN_CLZ;
07339 intrinsic_op = TRUE;
07340 break;
07341
07342 case GSBI_BUILT_IN_CTZ:
07343 case GSBI_BUILT_IN_CTZL:
07344 iopc = INTRN_CTZ;
07345 intrinsic_op = TRUE;
07346 break;
07347 case GSBI_BUILT_IN_CTZLL:
07348
07349
07350 iopc = TARGET_64BIT ? INTRN_CTZ : INTRN_CTZ64;
07351 intrinsic_op = TRUE;
07352 break;
07353 #endif
07354 case GSBI_BUILT_IN_TRAP:
07355 call_wn = WN_Create (OPR_CALL, MTYPE_V, MTYPE_V, 0);
07356 st = Get_ST (gs_tree_operand (arg0, 0));
07357 Set_ST_name_idx (st, Save_Str ("abort"));
07358 WN_st_idx (call_wn) = ST_st_idx (st);
07359 WN_Set_Linenum (call_wn, Get_Srcpos());
07360 WN_Set_Call_Default_Flags (call_wn);
07361 WGEN_Stmt_Append (call_wn, Get_Srcpos());
07362 whirl_generated = TRUE;
07363 break;
07364
07365 case GSBI_BUILT_IN_PREFETCH:
07366 {
07367
07368 gs_t pf_arg = gs_tree_operand (exp, 1);
07369 WN * pf_addr = WGEN_Expand_Expr (gs_tree_value (pf_arg));
07370
07371
07372 pf_arg = gs_tree_chain (pf_arg);
07373 UINT32 pf_flag = 0;
07374 int access = 0;
07375 if (pf_arg && gs_tree_code (gs_tree_value (pf_arg)) == GS_INTEGER_CST)
07376 access = gs_get_integer_value (gs_tree_value (pf_arg));
07377 if (access == 0)
07378 PF_SET_READ (pf_flag);
07379 else
07380 PF_SET_WRITE (pf_flag);
07381
07382
07383
07384 PF_SET_MANUAL (pf_flag);
07385 WGEN_Stmt_Append (WN_CreatePrefetch (0, pf_flag, pf_addr),
07386 Get_Srcpos());
07387 whirl_generated = TRUE;
07388 }
07389 break;
07390 #endif
07391
07392 #ifdef TARG_X8664
07393
07394 case GSBI_BUILT_IN_COSL:
07395 if (!Force_IEEE_Comparisons)
07396 {
07397 iopc = INTRN_COSL;
07398 intrinsic_op = TRUE;
07399 if (ret_mtype != MTYPE_FQ)
07400 {
07401
07402 cvt_to = ret_mtype;
07403 ret_mtype = MTYPE_FQ;
07404 }
07405 }
07406 break;
07407
07408
07409 case GSBI_BUILT_IN_SINL:
07410 if (!Force_IEEE_Comparisons)
07411 {
07412 iopc = INTRN_SINL;
07413 intrinsic_op = TRUE;
07414 if (ret_mtype != MTYPE_FQ)
07415 {
07416
07417 cvt_to = ret_mtype;
07418 ret_mtype = MTYPE_FQ;
07419 }
07420 }
07421 break;
07422 #endif // TARG_X8664
07423
07424 #ifdef KEY
07425 case GSBI_BUILT_IN_TAN:
07426 case GSBI_BUILT_IN_TANF:
07427
07428 if (ret_mtype == MTYPE_V) ret_mtype = MTYPE_F8;
07429 if (ret_mtype == MTYPE_F4) iopc = INTRN_F4TAN;
07430 else if (ret_mtype == MTYPE_F8) iopc = INTRN_F8TAN;
07431 else Fail_FmtAssertion ("unexpected mtype for intrinsic 'tan'");
07432 intrinsic_op = TRUE;
07433 break;
07434
07435
07436
07437
07438
07439
07440
07441
07442
07443 #ifdef FE_GNU_4_2_0
07444
07445 case GSBI_BUILT_IN_FETCH_AND_ADD_1:
07446 case GSBI_BUILT_IN_FETCH_AND_ADD_2:
07447 iopc = INTRN_FETCH_AND_ADD_I4;
07448 break;
07449
07450
07451 case GSBI_BUILT_IN_FETCH_AND_SUB_1:
07452 case GSBI_BUILT_IN_FETCH_AND_SUB_2:
07453 case GSBI_BUILT_IN_FETCH_AND_SUB_4:
07454 iopc = INTRN_FETCH_AND_SUB_I4;
07455 break;
07456
07457 case GSBI_BUILT_IN_FETCH_AND_SUB_8:
07458 iopc = INTRN_FETCH_AND_SUB_I8;
07459 break;
07460
07461
07462 case GSBI_BUILT_IN_FETCH_AND_OR_1:
07463 case GSBI_BUILT_IN_FETCH_AND_OR_2:
07464 case GSBI_BUILT_IN_FETCH_AND_OR_4:
07465 iopc = INTRN_FETCH_AND_OR_I4;
07466 break;
07467
07468 case GSBI_BUILT_IN_FETCH_AND_OR_8:
07469 iopc = INTRN_FETCH_AND_OR_I8;
07470 break;
07471
07472
07473 case GSBI_BUILT_IN_FETCH_AND_XOR_1:
07474 case GSBI_BUILT_IN_FETCH_AND_XOR_2:
07475 case GSBI_BUILT_IN_FETCH_AND_XOR_4:
07476 iopc = INTRN_FETCH_AND_XOR_I4;
07477 break;
07478
07479 case GSBI_BUILT_IN_FETCH_AND_XOR_8:
07480 iopc = INTRN_FETCH_AND_XOR_I8;
07481 break;
07482
07483
07484 case GSBI_BUILT_IN_FETCH_AND_AND_1:
07485 case GSBI_BUILT_IN_FETCH_AND_AND_2:
07486 case GSBI_BUILT_IN_FETCH_AND_AND_4:
07487 iopc = INTRN_FETCH_AND_AND_I4;
07488 break;
07489
07490 case GSBI_BUILT_IN_FETCH_AND_AND_8:
07491 iopc = INTRN_FETCH_AND_AND_I8;
07492 break;
07493
07494
07495 case GSBI_BUILT_IN_VAL_COMPARE_AND_SWAP_1:
07496 case GSBI_BUILT_IN_VAL_COMPARE_AND_SWAP_2:
07497 case GSBI_BUILT_IN_VAL_COMPARE_AND_SWAP_4:
07498 iopc = INTRN_COMPARE_AND_SWAP_I4;
07499 break;
07500
07501 case GSBI_BUILT_IN_VAL_COMPARE_AND_SWAP_8:
07502 iopc = INTRN_COMPARE_AND_SWAP_I8;
07503 break;
07504 #endif // FE_GNU_4_2_0
07505 #endif
07506 #ifdef TARG_SL
07507 case GSBI_BUILT_IN_C3AADDA:
07508 iopc = INTRN_C3AADDA;
07509 intrinsic_op = TRUE;
07510 break;
07511 case GSBI_BUILT_IN_C3NEGA:
07512 iopc = INTRN_C3NEGA;
07513 intrinsic_op = TRUE;
07514 break;
07515 case GSBI_BUILT_IN_C3BITR:
07516 iopc = INTRN_C3BITR;
07517 intrinsic_op = TRUE;
07518 break;
07519 case GSBI_BUILT_IN_C3CS:
07520 iopc = INTRN_C3CS;
07521 intrinsic_op = TRUE;
07522 break;
07523 case GSBI_BUILT_IN_C3DADD:
07524 iopc = INTRN_C3DADD;
07525 intrinsic_op = TRUE;
07526 break;
07527 case GSBI_BUILT_IN_C3DMAC:
07528 iopc = INTRN_C3DMAC;
07529 intrinsic_op = TRUE;
07530 break;
07531 case GSBI_BUILT_IN_C3DMACA:
07532 iopc = INTRN_C3DMAC_A;
07533 intrinsic_op = TRUE;
07534 break;
07535 case GSBI_BUILT_IN_C3DMULA:
07536 iopc = INTRN_C3DMULA;
07537 intrinsic_op = TRUE;
07538 break;
07539 case GSBI_BUILT_IN_C3DMULAA:
07540 iopc = INTRN_C3DMULA_A;
07541 intrinsic_op = TRUE;
07542 break;
07543 case GSBI_BUILT_IN_C3DSHLLI:
07544 iopc = INTRN_C3DSHLL_I;
07545 intrinsic_op = TRUE;
07546 break;
07547 case GSBI_BUILT_IN_C3FFE:
07548 iopc = INTRN_C3FFE;
07549 break;
07550 case GSBI_BUILT_IN_C3LD:
07551 iopc = INTRN_C3LD;
07552 intrinsic_op = TRUE;
07553 break;
07554 case GSBI_BUILT_IN_C3ST:
07555 iopc = INTRN_C3ST;
07556 break;
07557 case GSBI_BUILT_IN_C3LEAD:
07558 iopc = INTRN_C3LEAD;
07559 intrinsic_op = TRUE;
07560 break;
07561 case GSBI_BUILT_IN_C3MAC:
07562 iopc = INTRN_C3MAC;
07563 intrinsic_op = TRUE;
07564 break;
07565 case GSBI_BUILT_IN_C3MACA:
07566 iopc = INTRN_C3MAC_A;
07567 intrinsic_op = TRUE;
07568 break;
07569 case GSBI_BUILT_IN_C3MACAR:
07570 iopc = INTRN_C3MAC_AR;
07571 intrinsic_op = TRUE;
07572 break;
07573 case GSBI_BUILT_IN_C3MACI:
07574 iopc = INTRN_C3MAC_I;
07575 intrinsic_op = TRUE;
07576 break;
07577 case GSBI_BUILT_IN_C3MULA:
07578 iopc = INTRN_C3MULA;
07579 intrinsic_op = TRUE;
07580 break;
07581 case GSBI_BUILT_IN_C3MULAA:
07582 iopc = INTRN_C3MULA_A;
07583 intrinsic_op = TRUE;
07584 break;
07585 case GSBI_BUILT_IN_C3MULAAR:
07586 iopc = INTRN_C3MULA_AR;
07587 intrinsic_op = TRUE;
07588 break;
07589 case GSBI_BUILT_IN_C3MULAI:
07590 iopc = INTRN_C3MULA_I;
07591 intrinsic_op = TRUE;
07592 break;
07593 case GSBI_BUILT_IN_C3MULS:
07594 iopc = INTRN_C3MULS;
07595 intrinsic_op = TRUE;
07596 break;
07597 case GSBI_BUILT_IN_C3MULUS:
07598 iopc = INTRN_C3MULUS;
07599 intrinsic_op = TRUE;
07600 break;
07601 case GSBI_BUILT_IN_C3REVB:
07602 iopc = INTRN_C3REVB;
07603 intrinsic_op = TRUE;
07604 break;
07605 case GSBI_BUILT_IN_C3ROUND:
07606 iopc = INTRN_C3ROUND;
07607 intrinsic_op = TRUE;
07608 break;
07609 case GSBI_BUILT_IN_C3SAADDA:
07610 iopc = INTRN_C3SAADD_A;
07611 intrinsic_op = TRUE;
07612 break;
07613 case GSBI_BUILT_IN_C3SAADDHA:
07614 iopc = INTRN_C3SAADDH_A;
07615 intrinsic_op = TRUE;
07616 break;
07617 case GSBI_BUILT_IN_C3SAADDS:
07618 iopc = INTRN_C3SAADDS;
07619 intrinsic_op = TRUE;
07620 break;
07621 case GSBI_BUILT_IN_C3SAADDSH:
07622 iopc = INTRN_C3SAADDSH;
07623 intrinsic_op = TRUE;
07624 break;
07625 case GSBI_BUILT_IN_C3SADDA:
07626 iopc = INTRN_C3SADDA;
07627 intrinsic_op = TRUE;
07628 break;
07629 case GSBI_BUILT_IN_C3SADDAA:
07630 iopc = INTRN_C3SADDA_A;
07631 intrinsic_op = TRUE;
07632 break;
07633 case GSBI_BUILT_IN_C3SAMULHA:
07634 iopc = INTRN_C3SAMULH_A;
07635 intrinsic_op = TRUE;
07636 break;
07637 case GSBI_BUILT_IN_C3SAMULSH:
07638 iopc = INTRN_C3SAMULSH;
07639 intrinsic_op = TRUE;
07640 break;
07641 case GSBI_BUILT_IN_C3SHAV:
07642 iopc = INTRN_C3SHAV;
07643 intrinsic_op = TRUE;
07644 break;
07645 case GSBI_BUILT_IN_C3SHLAFAI:
07646 iopc = INTRN_C3SHLAFA_I;
07647 intrinsic_op = TRUE;
07648 break;
07649 case GSBI_BUILT_IN_C3SHLATAI:
07650 iopc = INTRN_C3SHLATA_I;
07651 intrinsic_op = TRUE;
07652 break;
07653 case GSBI_BUILT_IN_C3SHLAI:
07654 iopc = INTRN_C3SHLA_I;
07655 intrinsic_op = TRUE;
07656 break;
07657 case GSBI_BUILT_IN_C3SUBC:
07658 iopc = INTRN_C3SUBC;
07659 intrinsic_op = TRUE;
07660 break;
07661 case GSBI_BUILT_IN_INIT_HI:
07662 iopc = INTRN_INIT_HI;
07663 break;
07664 case GSBI_BUILT_IN_COPY_HI:
07665 iopc = INTRN_COPY_HI;
07666 intrinsic_op = TRUE;
07667 break;
07668 case GSBI_BUILT_IN_C3_INIT_ACC:
07669 iopc = INTRN_C3_INIT_ACC;
07670 break;
07671 case GSBI_BUILT_IN_C3_SAVE_ACC:
07672 iopc = INTRN_C3_SAVE_ACC;
07673 break;
07674 case GSBI_BUILT_IN_C3_INIT_DACC:
07675 iopc = INTRN_C3_INIT_DACC;
07676 break;
07677 case GSBI_BUILT_IN_C3_SAVE_DACC:
07678 iopc = INTRN_C3_SAVE_DACC;
07679 break;
07680 case GSBI_BUILT_IN_C3_INIT_ADDR:
07681 iopc = INTRN_C3_INIT_ADDR;
07682 break;
07683 case GSBI_BUILT_IN_C3_SAVE_ADDR:
07684 iopc = INTRN_C3_SAVE_ADDR;
07685 break;
07686 case GSBI_BUILT_IN_C3_MVFS:
07687 iopc = INTRN_C3_MVFS;
07688 intrinsic_op = TRUE;
07689 break;
07690 case GSBI_BUILT_IN_SET_ADDR:
07691 iopc = INTRN_C3_SET_ADDR;
07692 break;
07693 case GSBI_BUILT_IN_SET_CIRCBUF:
07694 iopc = INTRN_C3_SET_CIRCBUF;
07695 break;
07696 #endif
07697 default:
07698 DevWarn ("Encountered BUILT_IN: %d at line %d\n",
07699 gs_decl_function_code (func), lineno);
07700 break;
07701 }
07702 }
07703 else
07704 {
07705 #ifdef TARG_X8664
07706 wn = WGEN_target_builtins (exp, &iopc, &intrinsic_op);
07707 if (wn) break;
07708 #else
07709 Fail_FmtAssertion ("Target-specific builtins NYI");
07710 #endif
07711 }
07712 }
07713
07714 if (whirl_generated) {
07715 break;
07716 }
07717
07718 if (intrinsic_op) {
07719 WN *ikids [16];
07720 for (i = 0, list = gs_tree_operand (exp, 1);
07721 list;
07722 i++, list = gs_tree_chain (list)) {
07723 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
07724 #ifdef KEY // bug 11286
07725 if (i == 1 && TARGET_64BIT &&
07726 (gs_decl_function_code(func) == GSBI_BUILT_IN_POWI ||
07727 gs_decl_function_code(func) == GSBI_BUILT_IN_POWIF ||
07728 gs_decl_function_code(func) == GSBI_BUILT_IN_POWIL)) {
07729 arg_wn = WN_Int_Type_Conversion(arg_wn, MTYPE_I8);
07730 arg_ty_idx = MTYPE_To_TY(MTYPE_I8);
07731 arg_mtype = MTYPE_I8;
07732 }
07733 else
07734 #endif
07735 {
07736 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
07737 arg_mtype = TY_mtype(arg_ty_idx);
07738 }
07739 arg_wn = WN_CreateParm (Mtype_comparison (arg_mtype), arg_wn,
07740 arg_ty_idx, WN_PARM_BY_VALUE);
07741 ikids [i] = arg_wn;
07742 }
07743 #if defined(KEY) && defined(TARG_X8664)
07744
07745 switch (INTRN_return_kind(iopc)) {
07746 case IRETURN_M8I1: ret_mtype = MTYPE_M8I1; break;
07747 case IRETURN_M8I2: ret_mtype = MTYPE_M8I2; break;
07748 case IRETURN_M8I4: ret_mtype = MTYPE_M8I4; break;
07749 default: ;
07750 }
07751 #endif
07752 wn = WN_Create_Intrinsic (OPR_INTRINSIC_OP, ret_mtype, MTYPE_V,
07753 iopc, num_args, ikids);
07754 #if defined(TARG_SL)
07755 WN_Set_Deref_If_Needed(wn);
07756 #endif
07757 #ifdef KEY
07758 if (cvt_to != MTYPE_UNKNOWN)
07759 wn = WN_Cvt (ret_mtype, cvt_to, wn);
07760 #endif
07761 break;
07762 }
07763
07764 if (iopc) {
07765 call_wn = WN_Create (OPR_INTRINSIC_CALL, ret_mtype, MTYPE_V, num_args);
07766 WN_intrinsic (call_wn) = iopc;
07767
07768 #ifdef TARG_X8664
07769 if (iopc == INTRN_STMXCSR) {
07770 ST *tmp_st = Gen_Temp_Symbol(MTYPE_To_TY(MTYPE_I4), "__stmxcsr");
07771 arg_wn = WN_Lda(Pointer_Mtype, ST_ofst(tmp_st), tmp_st, 0);
07772 arg_wn = WN_CreateParm(Pointer_Mtype, arg_wn,
07773 Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4), FALSE),
07774 WN_PARM_BY_VALUE);
07775 WN_kid (call_wn, 0) = arg_wn;
07776 WN_set_kid_count(call_wn, 1);
07777 wn0 = WN_CreateBlock ();
07778 WN_INSERT_BlockLast (wn0, call_wn);
07779 wn1 = WN_Ldid(MTYPE_I4, ST_ofst(tmp_st), tmp_st, MTYPE_To_TY(MTYPE_I4));
07780 wn = WN_CreateComma(OPR_COMMA, MTYPE_I4, MTYPE_V, wn0, wn1);
07781 break;
07782 }
07783 #endif
07784 }
07785 else {
07786 num_handlers = Current_Handler_Count();
07787 call_wn = WN_Create (OPR_CALL, ret_mtype, MTYPE_V,
07788 num_args + num_handlers);
07789 ST *st2 = DECL_ST2 (gs_tree_operand (arg0, 0));
07790
07791 if (Opt_Level > 0 && st2) {
07792 WN_st_idx (call_wn) = ST_st_idx (st2);
07793 }
07794 else {
07795 st = Get_ST (gs_tree_operand (arg0, 0));
07796 WN_st_idx (call_wn) = ST_st_idx (st);
07797 }
07798 }
07799 }
07800
07801 else {
07802 WN *wn_kid0, *wn_kid0_kid0;
07803 TY_IDX kid_ty_idx;
07804 UINT32 kid_field_id, kid_cur_fld;
07805 FLD_HANDLE kid_fld_handle;
07806 num_args++;
07807 num_handlers = Current_Handler_Count();
07808 call_wn = WN_Create (OPR_ICALL, ret_mtype, MTYPE_V,
07809 num_args + num_handlers);
07810
07811 wn_kid0 = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
07812 WN_kid(call_wn, num_args-1) = wn_kid0;
07813 WN_set_ty (call_wn, TY_pointed(Get_TY(gs_tree_type (gs_tree_operand (exp, 0)))));
07814
07815
07816
07817
07818
07819
07820
07821
07822
07823
07824
07825
07826
07827
07828
07829 kid_ty_idx = kid_field_id = 0;
07830 #ifdef TARG_IA64
07831
07832 switch (WN_operator(wn_kid0)) {
07833 case OPR_ILOAD :
07834
07835 kid_ty_idx = WN_ty(wn_kid0);
07836 kid_field_id = WN_field_id(wn_kid0);
07837 break;
07838 case OPR_ADD :
07839
07840 wn_kid0_kid0 = WN_kid0(wn_kid0);
07841 if (WN_operator_is(wn_kid0_kid0, OPR_ILOAD)) {
07842 kid_ty_idx = WN_ty(wn_kid0_kid0);
07843 kid_field_id = WN_field_id(wn_kid0_kid0);
07844 }
07845 break;
07846 }
07847 #endif
07848 #ifdef TARG_X8664
07849 if (WN_operator(wn_kid0) == OPR_ILOAD) {
07850 WN *wn_kid0_kid0 = WN_kid0(wn_kid0);
07851 if (WN_operator(wn_kid0_kid0) == OPR_ILOAD) {
07852 kid_ty_idx = WN_ty(wn_kid0_kid0);
07853 kid_field_id = WN_field_id(wn_kid0_kid0);
07854 }
07855 }
07856 #endif
07857
07858 if (kid_ty_idx > 0 && kid_field_id > 0) {
07859
07860
07861 kid_cur_fld = 0;
07862 kid_fld_handle = FLD_get_to_field(kid_ty_idx, kid_field_id, kid_cur_fld);
07863 if (!strncmp (&Str_Table[FLD_name_idx(kid_fld_handle)], "_vptr.", 6))
07864 WN_Set_Call_Is_Virtual(call_wn);
07865 }
07866 }
07867
07868 WN_Set_Linenum (call_wn, Get_Srcpos());
07869 WN_Set_Call_Default_Flags (call_wn);
07870
07871 if (st) {
07872 gs_t func = gs_tree_operand (arg0, 0);
07873 if (gs_decl_inline (func)) {
07874 wgen_invoke_inliner = TRUE;
07875 }
07876 PU& pu_ent = Pu_Table[ST_pu(st)];
07877
07878 if (gs_tree_this_volatile(func)) {
07879 Set_PU_has_attr_noreturn (pu_ent);
07880 }
07881 }
07882
07883 i = 0;
07884 #ifdef KEY
07885
07886
07887
07888
07889
07890
07891 if (return_in_mem) {
07892 FmtAssert (target_wn != NULL,
07893 ("WGEN_Expand_Expr: write target is NULL"));
07894 WN *arg_wn = WN_CreateParm (Pointer_Mtype, target_wn,
07895 Make_Pointer_Type(ty_idx, FALSE),
07896 WN_PARM_BY_VALUE);
07897 WN_kid (call_wn, i++) = arg_wn;
07898 if (WN_operator(target_wn) == OPR_LDA) {
07899 ST *st = WN_st(target_wn);
07900 Set_ST_addr_passed(*st);
07901 }
07902 }
07903 #endif
07904 for (list = gs_tree_operand (exp, 1);
07905 list;
07906 list = gs_tree_chain (list)) {
07907 if (i == 0 && is_aggr_init_via_ctor) {
07908 #ifdef KEY
07909
07910
07911
07912
07913
07914
07915 arg_wn = WGEN_Address_Of(gs_tree_value(list));
07916 #else
07917 ST * st = Get_ST(gs_tree_value(list));
07918 arg_wn = WN_Lda(Pointer_Mtype, ST_ofst(st), st);
07919 #endif
07920 arg_ty_idx = Make_Pointer_Type(Get_TY(gs_tree_type(gs_tree_value(list))));
07921 }
07922 else {
07923 #ifdef KEY
07924 if (gs_tree_code (gs_tree_value (list)) == GS_ADDR_EXPR &&
07925 gs_tree_code (gs_tree_operand (gs_tree_value (list), 0)) == GS_TARGET_EXPR)
07926 {
07927 gs_t targ = gs_tree_operand (gs_tree_value (list), 0);
07928 WN *targ_wn = WGEN_Expand_Expr(targ);
07929 arg_wn = WN_Lda(Pointer_Mtype, 0, WN_st(targ_wn), 0);
07930 arg_ty_idx = Make_Pointer_Type(Get_TY(gs_tree_type(targ)));
07931 }
07932 else
07933 {
07934 #endif // KEY
07935 arg_wn = WGEN_Expand_Expr (gs_tree_value (list));
07936 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_value(list)));
07937 #if 1 // wgen bug 10448
07938 if (gs_tree_this_volatile(gs_tree_value(list)))
07939 Set_TY_is_volatile(arg_ty_idx);
07940 else Clear_TY_is_volatile(arg_ty_idx);
07941 #endif
07942 #ifdef KEY
07943 }
07944 #endif // KEY
07945 #ifdef KEY // bug 11585
07946 if (WN_operator(arg_wn) == OPR_LDA) {
07947 ST *st = WN_st(arg_wn);
07948 Set_ST_addr_passed(*st);
07949 Set_ST_addr_saved(*st);
07950 }
07951 #endif // KEY
07952 }
07953
07954 arg_mtype = TY_mtype(arg_ty_idx);
07955 #if 1 // wgen bug 10846
07956
07957
07958 if (arg_mtype == MTYPE_M) {
07959 arg_mtype = WN_rtype(arg_wn);
07960 }
07961 #endif
07962 arg_wn = WN_CreateParm (Mtype_comparison (arg_mtype), arg_wn,
07963 arg_ty_idx, WN_PARM_BY_VALUE);
07964 WN_kid (call_wn, i++) = arg_wn;
07965 }
07966
07967 #ifdef ADD_HANDLER_INFO
07968 if (num_handlers)
07969 Add_Handler_Info (call_wn, i, num_handlers);
07970 #endif
07971
07972 #ifdef KEY
07973 if (key_exceptions && !gs_tree_nothrow(exp) &&
07974
07975
07976
07977
07978
07979
07980
07981 !(in_cleanup) &&
07982
07983
07984
07985
07986
07987
07988
07989
07990 !must_not_throw)
07991 {
07992 if (!inside_eh_region)
07993 {
07994 WN * region_body = WN_CreateBlock();
07995 inside_eh_region = true;
07996 WGEN_Stmt_Push (region_body, wgen_stmk_call_region_body, Get_Srcpos());
07997 }
07998 } else if (key_exceptions && inside_eh_region && opt_regions)
07999 {
08000
08001
08002
08003 if (Check_For_Call_Region ())
08004 Did_Not_Terminate_Region = FALSE;
08005 }
08006 #endif // KEY
08007
08008 #ifdef TARG_SL
08009 WN_Set_Deref_If_Needed(call_wn);
08010 #endif
08011 if (ret_mtype == MTYPE_V
08012 #ifdef KEY
08013
08014
08015 || return_in_mem
08016 #endif
08017 ) {
08018 WGEN_Stmt_Append (call_wn, Get_Srcpos());
08019 #ifdef TARG_SL
08020
08021 if (WN_Need_Append_Intrinsic(call_wn)) {
08022 WFE_Stmt_Append_Extend_Intrinsic(call_wn, WN_kid0(WN_kid0(call_wn)), Get_Srcpos());
08023 }
08024 #endif
08025 }
08026
08027 else {
08028 wn0 = WN_CreateBlock ();
08029 WN_INSERT_BlockLast (wn0, call_wn);
08030
08031 #ifdef KEY
08032
08033
08034 if (nop_ty_idx && TY_kind(ty_idx) == KIND_POINTER &&
08035 TY_mtype(TY_pointed(ty_idx)) == MTYPE_V)
08036 ty_idx = nop_ty_idx;
08037 #endif
08038 wn1 = WN_Ldid (ret_mtype, -1, Return_Val_Preg, ty_idx);
08039
08040 if (ret_mtype == MTYPE_M) {
08041
08042 TY_IDX ret_ty_idx = ty_idx;
08043 #ifndef KEY
08044
08045
08046 if (Aggregate_Alignment > 0 &&
08047 Aggregate_Alignment > TY_align (ret_ty_idx))
08048 Set_TY_align (ret_ty_idx, Aggregate_Alignment);
08049 #endif // !KEY
08050 if (TY_align (ret_ty_idx) < MTYPE_align_best(Spill_Int_Mtype))
08051 Set_TY_align (ret_ty_idx, MTYPE_align_best(Spill_Int_Mtype));
08052 ST *ret_st = Gen_Temp_Symbol(ret_ty_idx,
08053 st ? Index_To_Str(Save_Str2(".Mreturn.",
08054 ST_name(ST_st_idx(st))))
08055 : ".Mreturn.");
08056 #ifdef FE_GNU_4_2_0
08057 WGEN_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, ret_st);
08058 #endif
08059
08060 if (!return_in_mem) {
08061 wn1 = WN_Stid (ret_mtype, 0, ret_st, ty_idx, wn1);
08062 WN_INSERT_BlockLast (wn0, wn1);
08063 }
08064
08065
08066 UINT xtra_BE_ofst = 0;
08067 desc_ty_idx = component_ty_idx;
08068 if (desc_ty_idx == 0)
08069 desc_ty_idx = Get_TY (gs_tree_type(exp));
08070
08071 if (! MTYPE_is_integral(TY_mtype(desc_ty_idx)))
08072 ty_idx = desc_ty_idx;
08073 else {
08074 ty_idx = nop_ty_idx;
08075 if (ty_idx == 0)
08076 ty_idx = desc_ty_idx;
08077 }
08078
08079 if (! is_bit_field) {
08080 if (TY_size(desc_ty_idx) > TY_size(ty_idx)) {
08081 if (Target_Byte_Sex == BIG_ENDIAN)
08082 xtra_BE_ofst = TY_size(desc_ty_idx) - TY_size(ty_idx);
08083 desc_ty_idx = ty_idx;
08084 }
08085 }
08086 else {
08087 if (TY_size(desc_ty_idx) > TY_size(ty_idx))
08088 ty_idx = desc_ty_idx;
08089 }
08090
08091 TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
08092 TYPE_ID desc = TY_mtype(desc_ty_idx);
08093 if (MTYPE_is_integral(desc)) {
08094 if (MTYPE_signed(rtype) != MTYPE_signed(desc)) {
08095 if (MTYPE_size_min(rtype) > MTYPE_size_min(desc) ||
08096 is_bit_field)
08097 rtype = Mtype_TransferSign(desc, rtype);
08098 else desc = Mtype_TransferSign(rtype, desc);
08099 }
08100 }
08101
08102 Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
08103 ("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
08104
08105 wn1 = WN_CreateLdid(OPR_LDID, rtype,
08106 is_bit_field ? MTYPE_BS : desc,
08107 ST_ofst(ret_st)+component_offset+xtra_BE_ofst,
08108 ret_st,
08109 (field_id != 0 && component_ty_idx != 0) ?
08110 Get_TY (gs_tree_type(exp)) : ty_idx,
08111 field_id);
08112 }
08113
08114 wn = WN_CreateComma (OPR_COMMA, WN_rtype (wn1), MTYPE_V,
08115 wn0, wn1);
08116 }
08117 }
08118 break;
08119
08120 case GS_UNGE_EXPR:
08121 case GS_UNGT_EXPR:
08122 case GS_UNLE_EXPR:
08123 case GS_UNLT_EXPR:
08124 case GS_LTGT_EXPR:
08125 case GS_ORDERED_EXPR:
08126 case GS_UNORDERED_EXPR:
08127 case GS_UNEQ_EXPR:
08128 { WN *ikids[2];
08129 WN *arg_wn;
08130 TY_IDX arg_ty_idx;
08131 TYPE_ID arg_mtype;
08132 INTRINSIC iopc;
08133 BOOL nott = FALSE;
08134
08135 arg_wn = WGEN_Expand_Expr(gs_tree_operand(exp, 0));
08136 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_operand(exp, 0)));
08137 arg_mtype = TY_mtype(arg_ty_idx);
08138 ikids[0] = WN_CreateParm(arg_mtype, arg_wn, arg_ty_idx,
08139 WN_PARM_BY_VALUE);
08140
08141 arg_wn = WGEN_Expand_Expr(gs_tree_operand(exp, 1));
08142 arg_ty_idx = Get_TY(gs_tree_type(gs_tree_operand(exp, 1)));
08143 arg_mtype = TY_mtype(arg_ty_idx);
08144 ikids[1] = WN_CreateParm(arg_mtype, arg_wn, arg_ty_idx,
08145 WN_PARM_BY_VALUE);
08146 switch (code) {
08147 case GS_UNGE_EXPR: iopc = INTRN_ISGREATEREQUAL; break;
08148 case GS_UNGT_EXPR: iopc = INTRN_ISGREATER; break;
08149 case GS_UNLE_EXPR: iopc = INTRN_ISLESSEQUAL; break;
08150 case GS_UNLT_EXPR: iopc = INTRN_ISLESS; break;
08151 case GS_LTGT_EXPR: iopc = INTRN_ISLESSGREATER; break;
08152 case GS_ORDERED_EXPR: iopc = INTRN_ISORDERED; break;
08153 case GS_UNEQ_EXPR:
08154 case GS_UNORDERED_EXPR: iopc = INTRN_ISUNORDERED; break;
08155 }
08156 wn = WN_Create_Intrinsic(OPR_INTRINSIC_OP, Boolean_type, MTYPE_V,
08157 iopc, 2, ikids);
08158 if (code == GS_UNEQ_EXPR) {
08159 WN *eq_wn = WN_Relational(OPR_EQ, arg_mtype,
08160 WN_COPY_Tree(WN_kid0(ikids[0])),
08161 WN_COPY_Tree(WN_kid0(ikids[1])));
08162 wn = WN_Binary (OPR_CIOR, Boolean_type, wn, eq_wn);
08163 }
08164 }
08165 break;
08166
08167 case GS_COMPOUND_EXPR:
08168 {
08169 #ifdef KEY
08170
08171
08172 gs_t opnd1 = gs_tree_operand(exp, 1);
08173 if (gs_tree_code(opnd1) == GS_VAR_DECL &&
08174 target_wn != NULL) {
08175 ST *st = DECL_ST(opnd1);
08176 if (st == NULL) {
08177
08178 FmtAssert(WN_operator(target_wn) == OPR_LDA,
08179 ("WGEN_Expand_Expr: target_wn not LDA"));
08180 set_DECL_ST(opnd1, WN_st(target_wn));
08181 } else {
08182 FmtAssert(st == WN_st(target_wn),
08183 ("WGEN_Expand_Expr: conflicting ST in COMPOUND_EXPR's VAR_DECL"));
08184 }
08185 }
08186 #endif
08187 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), FALSE);
08188 if (wn && WN_has_side_effects(wn)) {
08189 wn = WN_CreateEval (wn);
08190 WGEN_Stmt_Append (wn, Get_Srcpos ());
08191 }
08192 #ifdef KEY
08193
08194 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 1), need_result,
08195 0, 0, 0, 0, FALSE, FALSE, target_wn);
08196 #else
08197 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 1), need_result);
08198 #endif
08199 }
08200 break;
08201
08202 case GS_NON_LVALUE_EXPR:
08203 {
08204 #ifdef KEY
08205
08206 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0), need_result,
08207 nop_ty_idx, component_ty_idx, component_offset,
08208 field_id);
08209 #else
08210 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
08211 #endif
08212 }
08213 break;
08214
08215 case GS_SAVE_EXPR:
08216 {
08217 DevWarn ("Encountered SAVE_EXPR at line %d", lineno);
08218 wn = WGEN_Save_Expr (exp, need_result, nop_ty_idx,
08219 component_ty_idx, component_offset, field_id);
08220 }
08221 break;
08222
08223 case GS_ERROR_MARK:
08224
08225 wn = WN_Intconst(MTYPE_I4, 0);
08226 break;
08227
08228 case GS_LOOP_EXPR:
08229 {
08230 DevWarn ("Encountered LOOP_EXPR at line %d\n", lineno);
08231 LABEL_IDX saved_loop_expr_exit_label = loop_expr_exit_label;
08232 loop_expr_exit_label = 0;
08233 gs_t body = gs_loop_expr_body(exp);
08234 WN *loop_test = WN_Intconst (Boolean_type, 1);
08235 WN *loop_body = WN_CreateBlock ();
08236 if (body) {
08237 WGEN_Stmt_Push (loop_body, wgen_stmk_while_body, Get_Srcpos());
08238 wn = WGEN_Expand_Expr (body);
08239 WGEN_Stmt_Pop (wgen_stmk_while_body);
08240 }
08241 WN *loop_stmt = WN_CreateWhileDo (loop_test, loop_body);
08242 WGEN_Stmt_Append (loop_stmt, Get_Srcpos());
08243 if (loop_expr_exit_label)
08244 WGEN_Stmt_Append (WN_CreateLabel ((ST_IDX) 0, loop_expr_exit_label, 0, NULL),
08245 Get_Srcpos ());
08246 loop_expr_exit_label = saved_loop_expr_exit_label;
08247 }
08248 break;
08249
08250 case GS_EXIT_EXPR:
08251 {
08252 DevWarn ("Encountered EXIT_EXPR at line %d\n", lineno);
08253 WN *test = WGEN_Expand_Expr (gs_tree_operand(exp, 0));
08254 New_LABEL (CURRENT_SYMTAB, loop_expr_exit_label);
08255 WN *stmt = WN_CreateTruebr (loop_expr_exit_label, test);
08256 WGEN_Stmt_Append (stmt, Get_Srcpos ());
08257 }
08258 break;
08259
08260 case GS_VA_ARG_EXPR:
08261 {
08262 #ifdef TARG_X8664
08263 if( TARGET_64BIT ){
08264 gs_t kid0 = gs_tree_operand(exp, 0);
08265 WN *ap_wn;
08266 ap_wn = WGEN_Expand_Expr(kid0);
08267 if (WN_rtype(ap_wn) == MTYPE_M) {
08268 if (OPCODE_is_leaf(WN_opcode(ap_wn)))
08269 ap_wn = WN_Lda(Pointer_Mtype, WN_offset(ap_wn), WN_st(ap_wn), 0);
08270 else {
08271 Is_True(OPCODE_is_load(WN_opcode(ap_wn)),
08272 ("WGEN_Expand_Expr: unexpected VA_ARG_EXPR argument"));
08273 if ( WN_offset(ap_wn) == 0 )
08274 ap_wn = WN_kid0(ap_wn);
08275 else
08276 ap_wn = WN_Add(Pointer_Mtype, WN_kid0(ap_wn), WN_Intconst(Pointer_Mtype, WN_offset(ap_wn)));
08277 }
08278 }
08279 TY_IDX ty_idx = Get_TY (gs_tree_type(exp));
08280 TYPE_ID mtype = Fix_TY_mtype(ty_idx);
08281
08282 if (mtype != MTYPE_FQ && mtype != MTYPE_M && !MTYPE_is_complex(mtype)) {
08283 wn = WGEN_x8664_va_arg(ap_wn, MTYPE_float(mtype), ty_idx, FALSE);
08284 wn = WN_CreateIload(OPR_ILOAD, Widen_Mtype (mtype), mtype, 0,
08285 ty_idx, Make_Pointer_Type(ty_idx), wn);
08286 }
08287 else if (mtype == MTYPE_C4) {
08288 wn = WGEN_x8664_va_arg(ap_wn, MTYPE_float(mtype), ty_idx, FALSE);
08289 wn = WN_CreateIload(OPR_ILOAD, MTYPE_M, MTYPE_M, 0, ty_idx,
08290 Make_Pointer_Type(ty_idx), wn);
08291 }
08292 else {
08293 enum X86_64_PARM_CLASS classes[MAX_CLASSES];
08294 INT n = Classify_Aggregate(ty_idx, classes);
08295 if (n == 0) {
08296
08297 INT delta = ((TY_size(ty_idx) + 7) / 8) * 8;
08298 wn0 = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype),
08299 WN_CopyNode(ap_wn));
08300 wn1 = WN_Intconst(MTYPE_U8, delta);
08301 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
08302 wn = WN_Istore(Pointer_Mtype, 8,
08303 Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)),
08304 WN_CopyNode(ap_wn), wn);
08305 WGEN_Stmt_Append (wn, Get_Srcpos ());
08306
08307 wn = WN_Iload(Pointer_Mtype, 8, MTYPE_To_TY(Pointer_Mtype),
08308 WN_CopyNode(ap_wn));
08309
08310 wn1 = WN_Intconst(MTYPE_I8, -delta);
08311 wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn0, wn1);
08312 }
08313 else if (n == 1) {
08314 wn = WGEN_x8664_va_arg(ap_wn, classes[0] == X86_64_SSE_CLASS,
08315 ty_idx, FALSE);
08316 }
08317 else if (n > 1) {
08318 if (classes[0] == classes[1]) {
08319 if (classes[0] == X86_64_INTEGER_CLASS)
08320 wn = WGEN_x8664_va_arg(ap_wn, classes[0] == X86_64_SSE_CLASS,
08321 ty_idx, TRUE);
08322 else wn = WGEN_x8664_va_arg_2_float(ap_wn, ty_idx);
08323 }
08324 else {
08325 wn = WGEN_x8664_va_arg_2_mixed(ap_wn,
08326 classes[0] == X86_64_SSE_CLASS,
08327 classes[1] == X86_64_SSE_CLASS, ty_idx);
08328 }
08329 }
08330
08331 if( mtype == MTYPE_FQ )
08332 wn = WN_CreateIload(OPR_ILOAD, Widen_Mtype (mtype), mtype, 0,
08333 ty_idx, Make_Pointer_Type(ty_idx), wn);
08334 else
08335 wn = WN_CreateIload(OPR_ILOAD, MTYPE_M, MTYPE_M, 0, ty_idx,
08336 Make_Pointer_Type(ty_idx), wn);
08337 }
08338
08339 break;
08340 }
08341 #endif
08342
08343 INT64 align;
08344 INT64 rounded_size;
08345 gs_t type = gs_tree_type (exp);
08346 TY_IDX ty_idx = Get_TY (type);
08347 TYPE_ID mtype = TY_mtype (ty_idx);
08348
08349
08350 align = TARGET_64BIT ? 8 : 4;
08351 rounded_size = ((TY_size(Get_TY(type)) + align - 1) / align) * align;
08352 #ifdef TARG_MIPS // bug 12916: further align to double-word boundary
08353 rounded_size = ((rounded_size + 7) / 8) * 8;
08354 #endif
08355
08356
08357 WN *ap_load = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
08358 TY_IDX ap_ty_idx = Get_TY (gs_tree_type (gs_tree_operand (exp, 0)));
08359 WN *ap_addr;
08360 TY_IDX ap_addr_ty;
08361 ST *ap_st;
08362 WN_OFFSET ap_offset;
08363 UINT32 ap_field_id = 0;
08364
08365 if (WN_operator(ap_load) == OPR_LDID) {
08366 ap_st = WN_st (ap_load);
08367 ap_offset = WN_offset (ap_load);
08368 }
08369 else
08370 if (WN_operator(ap_load) == OPR_ILOAD) {
08371 ap_st = NULL;
08372 ap_offset = WN_offset (ap_load);
08373 ap_field_id = WN_field_id(ap_load);
08374 ap_addr = WN_COPY_Tree (WN_kid0 (ap_load));
08375 ap_addr_ty = WN_load_addr_ty(ap_load);
08376 if (WN_has_side_effects (ap_addr))
08377 Fail_FmtAssertion ("VA_ARG_EXPR: ap address has side effects");
08378 }
08379 else
08380 Fail_FmtAssertion ("VA_ARG_EXPR: unknown operator for ap");
08381
08382 wn = WN_COPY_Tree(ap_load);
08383
08384 #ifdef TARG_IA64
08385
08386 INT64 ty_align = gs_type_align(type) / BITS_PER_UNIT;
08387 ty_align = ((ty_align + align - 1) / align) * align;
08388
08389
08390 if (ty_align > align) {
08391 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn,
08392 WN_Intconst (Pointer_Mtype, ty_align - 1));
08393 wn = WN_Binary (OPR_BAND, Pointer_Mtype, wn,
08394 WN_Intconst (Pointer_Mtype, -ty_align));
08395 }
08396
08397 if (Target_Byte_Sex == BIG_ENDIAN) {
08398 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn,
08399 WN_Intconst (Pointer_Mtype, 3));
08400 wn = WN_Binary (OPR_BAND, Pointer_Mtype, wn,
08401 WN_Intconst (Pointer_Mtype, -8));
08402 }
08403 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn,
08404 WN_Intconst (Pointer_Mtype, rounded_size));
08405 #else
08406 if (Target_Byte_Sex == BIG_ENDIAN) {
08407 INT64 adj;
08408 adj = gs_n(gs_tree_int_cst_low(gs_type_size(type))) / BITS_PER_UNIT;
08409 if (rounded_size > align)
08410 adj = rounded_size;
08411 wn = WN_Binary (OPR_ADD, Pointer_Mtype, WN_COPY_Tree (ap_load),
08412 WN_Intconst (Pointer_Mtype, 3));
08413 wn = WN_Binary (OPR_BAND, Pointer_Mtype, wn,
08414 WN_Intconst (Pointer_Mtype, -8));
08415 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn,
08416 WN_Intconst (Pointer_Mtype, rounded_size));
08417 } else
08418
08419
08420 #if defined(TARG_SL) && (defined(EMULATE_LONGLONG) || defined(EMULATE_FLOAT_POINT))
08421 if ((mtype == MTYPE_F8) || (mtype == MTYPE_I8) || (mtype == MTYPE_U8)
08422 || (mtype == MTYPE_M && TY_fld(ty_idx).Entry()
08423 && MTYPE_byte_size(TY_mtype(FLD_type(TY_fld(ty_idx))))==8)) {
08424
08425
08426 wn = WN_Binary (OPR_ADD, Pointer_Mtype, WN_COPY_Tree (ap_load),
08427 WN_Intconst (Pointer_Mtype, 8*2-1));
08428
08429 wn = WN_Binary (OPR_LSHR, Pointer_Mtype, wn, WN_Intconst (Pointer_Mtype, 3));
08430 wn = WN_Binary (OPR_SHL, Pointer_Mtype, wn, WN_Intconst (Pointer_Mtype, 3));
08431 if (mtype == MTYPE_M && TY_fld(ty_idx).Entry()
08432 && MTYPE_byte_size(TY_mtype(FLD_type(TY_fld(ty_idx))))==8)
08433 wn = WN_Binary (OPR_ADD, Pointer_Mtype, wn, WN_Intconst (Pointer_Mtype, rounded_size-8));
08434 } else
08435 #endif
08436 {
08437 wn = WN_Binary (OPR_ADD, Pointer_Mtype, WN_COPY_Tree (ap_load),
08438 WN_Intconst (Pointer_Mtype, rounded_size));
08439 }
08440 #ifdef TARG_X8664 // bug 12118: pad since under -m32, vector types are 8-byte aligned
08441 if (MTYPE_is_vector(mtype) && ! TARGET_64BIT) {
08442 wn = WN_Add(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 7));
08443 wn = WN_Div(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 8));
08444 wn = WN_Mpy(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 8));
08445 }
08446 #endif
08447 #ifdef TARG_MIPS // bug 12945: pad since long doubles are 16-byte aligned
08448 if (mtype == MTYPE_FQ) {
08449 wn = WN_Add(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 15));
08450 wn = WN_Div(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 16));
08451 wn = WN_Mpy(Pointer_Mtype, wn, WN_Intconst(Pointer_Mtype, 16));
08452 }
08453 #endif
08454 #endif
08455 if (ap_st)
08456 wn = WN_Stid (Pointer_Mtype, ap_offset, ap_st, ap_ty_idx, wn);
08457 else {
08458 wn = WN_CreateIstore (OPR_ISTORE, MTYPE_V, Pointer_Mtype, ap_offset,
08459 ap_addr_ty, wn, ap_addr, ap_field_id);
08460 }
08461 WGEN_Stmt_Append (wn, Get_Srcpos ());
08462 #ifdef TARG_IA64
08463 wn = WN_CreateIload (OPR_ILOAD, Widen_Mtype (mtype), mtype, -rounded_size,
08464 ty_idx, Make_Pointer_Type (ty_idx, FALSE),
08465 ap_load);
08466 #else
08467 wn = WN_CreateIload (OPR_ILOAD, Widen_Mtype (mtype), mtype, -rounded_size,
08468 ap_ty_idx, Make_Pointer_Type (ap_ty_idx, FALSE),
08469 ap_load);
08470 #endif
08471
08472 #ifdef KEY
08473 if (Target_Byte_Sex != Host_Byte_Sex)
08474 wn = WN_CreateIload (OPR_ILOAD, Widen_Mtype (mtype), mtype,
08475 ((MTYPE_size_min(mtype)==32)?4:0)-rounded_size,
08476 ty_idx, Make_Pointer_Type(ty_idx, FALSE),
08477 ap_load);
08478 else
08479 #endif
08480 wn = WN_CreateIload (OPR_ILOAD, Widen_Mtype (mtype), mtype, -rounded_size,
08481 ty_idx, Make_Pointer_Type(ty_idx, FALSE),
08482 ap_load);
08483 }
08484 break;
08485
08486 case GS_LABEL_DECL:
08487 {
08488 DevWarn ("taking address of a label at line %d", lineno);
08489 LABEL_IDX label_idx = WGEN_Get_LABEL (arg0, FALSE);
08490 #if 0
08491 FmtAssert (arg0->decl.symtab_idx == CURRENT_SYMTAB,
08492 ("line %d: taking address of a label not defined in current function currently not implemented", lineno));
08493 #endif
08494 wn = WN_LdaLabel (Pointer_Mtype, label_idx);
08495 Set_LABEL_addr_saved (label_idx);
08496 Set_PU_no_inline (Get_Current_PU ());
08497 }
08498 break;
08499
08500 #ifdef KEY
08501 case GS_LABEL_EXPR:
08502 {
08503
08504
08505
08506
08507 gs_t type = gs_tree_type(exp);
08508 Is_True ( gs_code(type) == GS_VOID_TYPE, ("Bad expression type for LABEL_EXPR"));
08509 gs_t label = gs_tree_operand(exp, 0);
08510 FmtAssert ( gs_code(label) == GS_LABEL_DECL, ("Bad operand 0 code for LABEL_EXPR"));
08511
08512 LABEL_IDX label_idx = WGEN_Get_LABEL (label, TRUE);
08513 WN* wn1 = WN_CreateLabel ((ST_IDX) 0, label_idx, 0, NULL);
08514 WGEN_Stmt_Append (wn1, Get_Srcpos());
08515 Set_LABEL_addr_saved (label_idx);
08516 Set_PU_no_inline (Get_Current_PU ());
08517 }
08518 break;
08519 #endif
08520
08521 #ifdef KEY
08522 case GS_EXC_PTR_EXPR:
08523 {
08524 if (key_exceptions)
08525 {
08526 ST_IDX exc_ptr_st = Get_exception_pointer_symbol ();
08527 wn = WN_Ldid (Pointer_Mtype, 0, exc_ptr_st, Get_TY(gs_tree_type(exp)));
08528 }
08529 else
08530 {
08531
08532 if (!Dummy_Exc_Ptr_Expr)
08533 Dummy_Exc_Ptr_Expr = Gen_Temp_Symbol (Get_TY(gs_tree_type(exp)),
08534 "__dummy_exc_ptr");
08535 wn = WN_Ldid (Pointer_Mtype, 0, Dummy_Exc_Ptr_Expr, Get_TY(gs_tree_type(exp)));
08536 }
08537 }
08538 break;
08539
08540 case GS_CLEANUP_STMT:
08541 DevWarn ("CLEANUP_STMT not implemented: at line %d\n", lineno);
08542
08543 wn = WN_Intconst(MTYPE_I4, 0);
08544 break;
08545
08546 case GS_MUST_NOT_THROW_EXPR:
08547
08548 must_not_throw = TRUE;
08549 wn = WGEN_Expand_Expr (gs_tree_operand (exp,0));
08550 must_not_throw = FALSE;
08551 break;
08552
08553 case GS_VECTOR_CST:
08554 {
08555 ST * init_st = Gen_Temp_Symbol (Get_TY(gs_tree_type(exp)), "__vec_cst");
08556 #ifdef NEW_INITIALIZER
08557 WN* target = WN_Lda(Pointer_Mtype, 0, init_st, 0);
08558 Traverse_Aggregate_Vector_Const (target, exp, 0, 0);
08559 #else
08560 Traverse_Aggregate_Vector_Const (init_st, exp, 0, 0);
08561 #endif
08562 TY_IDX ty = ST_type (init_st);
08563 TYPE_ID mtype = TY_mtype (ty);
08564 wn = WN_CreateLdid (OPR_LDID, mtype, mtype, 0, init_st, ty, 0);
08565 break;
08566 }
08567
08568
08569 case GS_EH_FILTER_EXPR:
08570 DevWarn ("EH_FILTER_EXPR not yet implemented");
08571 break;
08572
08573 case GS_OBJ_TYPE_REF:
08574
08575 wn = WGEN_Expand_Expr (gs_obj_type_ref_expr (exp), need_result);
08576 break;
08577
08578 case GS_TRY_FINALLY_EXPR:
08579
08580
08581 Register_Cleanup (exp);
08582 WGEN_Expand_Expr (gs_tree_operand (exp,0), need_result);
08583 Unregister_Cleanup ();
08584 WGEN_Expand_Expr (gs_tree_operand (exp,1), need_result);
08585 break;
08586
08587 case GS_FILTER_EXPR:
08588
08589 DevWarn ("NYI: FILTER_EXPR");
08590 wn = WN_Intconst(MTYPE_I4, 0);
08591 break;
08592
08593 case GS_RESX_EXPR:
08594
08595 DevWarn ("NYI: RESX_EXPR");
08596 wn = WN_Intconst(MTYPE_I4, 0);
08597 break;
08598 #endif
08599
08600 case GS_ASM_EXPR:
08601 case GS_GOTO_EXPR:
08602 WGEN_Expand_Stmt(exp);
08603 break;
08604
08605 case GS_STATEMENT_LIST: {
08606 gs_t stmt_list = gs_statement_list_elts(exp);
08607 #ifdef FE_GNU_4_2_0
08608 for (int i=0; i < gs_length(stmt_list); i++)
08609 WGEN_Expand_Stmt(gs_index(stmt_list, i), target_wn);
08610 #else
08611 gs_t list;
08612 for (list = stmt_list; gs_code(list) != EMPTY;
08613 list = gs_operand(list, 1))
08614 WGEN_Expand_Stmt(gs_operand(list, 0), target_wn);
08615 #endif
08616 }
08617 break;
08618
08619 case GS_RETURN_EXPR:
08620 WGEN_Expand_Stmt(exp);
08621 break;
08622
08623 case GS_SWITCH_STMT:
08624 WGEN_Expand_Stmt(exp, target_wn);
08625 break;
08626
08627 #ifdef FE_GNU_4_2_0
08628 case GS_SWITCH_EXPR:
08629 case GS_CASE_LABEL_EXPR:
08630
08631
08632 case GS_OMP_ATOMIC:
08633 case GS_OMP_CRITICAL:
08634 case GS_OMP_FOR:
08635 case GS_OMP_MASTER:
08636 case GS_OMP_ORDERED:
08637 case GS_OMP_PARALLEL:
08638 case GS_OMP_SECTIONS:
08639 case GS_OMP_SINGLE:
08640 WGEN_Expand_Stmt(exp);
08641 break;
08642 #endif
08643
08644 case GS_BREAK_STMT:
08645 case GS_CONTINUE_STMT:
08646 case GS_WHILE_STMT:
08647 case GS_DO_STMT:
08648 case GS_FOR_STMT:
08649 WGEN_Expand_Stmt(exp);
08650 break;
08651
08652 #ifdef KEY
08653 case GS_VIEW_CONVERT_EXPR: {
08654 wn = WGEN_Expand_Expr (gs_tree_operand (exp, 0));
08655 ty_idx = Get_TY (gs_tree_type(exp));
08656 TYPE_ID mtyp = TY_mtype(ty_idx);
08657 if (mtyp == WN_rtype(wn))
08658 break;
08659
08660 if (WN_operator(wn) == OPR_INTCONST && !MTYPE_is_vector(mtyp) ||
08661 WN_operator(wn) == OPR_CONST)
08662 WN_set_rtype(wn, mtyp);
08663 else if (OPERATOR_is_load(WN_operator(wn))) {
08664 WN_set_rtype(wn, mtyp);
08665 WN_set_desc(wn, mtyp);
08666 }
08667 #ifdef TARG_X8664
08668 else if (MTYPE_is_vector(mtyp) && MTYPE_is_vector(WN_rtype(wn)) &&
08669 MTYPE_is_mmx_vector(mtyp) == MTYPE_is_mmx_vector(WN_rtype(wn))) {
08670
08671 }
08672 #endif
08673 else
08674 wn = WN_Cvt(WN_rtype(wn), mtyp, wn);
08675 }
08676 break;
08677
08678 case GS_USING_DECL:
08679
08680 wn = WN_Intconst(MTYPE_I4, 0);
08681 break;
08682 #endif
08683
08684 #ifdef KEY
08685 case GS_IF_STMT:
08686 WGEN_Expand_Stmt(exp, target_wn);
08687 break;
08688 #endif
08689
08690 default:
08691 FmtAssert(FALSE,
08692 ("WGEN_Expand_Expr: not yet implemented %s",
08693 gs_code_name(code)));
08694 break;
08695 }
08696
08697 if (need_result)
08698 FmtAssert (wn != 0 || code == GS_CALL_EXPR || code == GS_BIND_EXPR ||
08699 code == GS_STMT_EXPR ||
08700 code == GS_EXPR_STMT ||
08701 code == GS_COMPOUND_EXPR ||
08702 code == GS_INDIRECT_REF ||
08703 code == GS_COMPONENT_REF ||
08704 code == GS_LOOP_EXPR ||
08705 code == GS_NOP_EXPR ||
08706 code == GS_THROW_EXPR ||
08707 code == GS_AGGR_INIT_EXPR ||
08708 code == GS_STATEMENT_LIST ||
08709 code == GS_CLEANUP_POINT_EXPR ||
08710 ((code == GS_COND_EXPR) &&
08711 (TY_mtype(ty_idx) == MTYPE_V || TY_mtype(ty_idx) == MTYPE_M)),
08712 ("WGEN_Expand_Expr: NULL WHIRL tree for %s",
08713 gs_code_name(code)));
08714
08715 return wn;
08716 }
08717
08718
08719
08720
08721
08722 void
08723 WGEN_One_Stmt_Cleanup (gs_t exp)
08724 {
08725 LABEL_IDX idx = WGEN_unusable_label_idx;
08726 INT32 save_expr_level = wgen_save_expr_level;
08727
08728
08729 WGEN_unusable_label_idx = WGEN_last_label_idx;
08730
08731
08732 wgen_save_expr_level = ++wgen_last_save_expr_level;
08733
08734 WGEN_One_Stmt(exp);
08735 WGEN_unusable_label_idx = idx;
08736 wgen_save_expr_level = save_expr_level;
08737 }
08738
08739
08740 void WGEN_One_Stmt (gs_t exp, WN* target_wn)
08741 {
08742 WN *wn;
08743 wn = WGEN_Expand_Expr_With_Sequence_Point (exp, MTYPE_V, target_wn);
08744 if (wn) {
08745 for (;;) {
08746 if (WN_operator (wn) == OPR_COMMA) {
08747 WN *crwn = wn;
08748 if (WN_operator (WN_kid1 (wn)) == OPR_LDID &&
08749 WN_st (WN_kid1 (wn)) == Return_Val_Preg &&
08750 (WN_operator (WN_last (WN_kid0 (wn))) == OPR_CALL ||
08751 WN_operator (WN_last (WN_kid0 (wn))) == OPR_ICALL)) {
08752 WN_set_rtype (WN_last (WN_kid0 (wn)), MTYPE_V);
08753 WGEN_Stmt_Append (WN_kid0 (wn), Get_Srcpos ());
08754 WN_Delete (crwn);
08755 break;
08756 }
08757 else {
08758 WGEN_Stmt_Append (WN_kid0 (wn), Get_Srcpos ());
08759 wn = WN_kid1 (wn);
08760 WN_Delete (crwn);
08761 }
08762 }
08763 else {
08764 if (WN_has_side_effects (wn)) {
08765 wn = WN_CreateEval (wn);
08766 WGEN_Stmt_Append (wn, Get_Srcpos ());
08767 }
08768 break;
08769 }
08770 }
08771 }
08772 }
08773
08774
08775 void WGEN_Expr_Init()
08776 {
08777 }
08778
08779 char *
08780 WGEN_Tree_Node_Name (gs_t exp)
08781 {
08782 return gs_code_name(gs_tree_code (exp));
08783 }
08784
08785
08786
08787
08788
08789
08790
08791
08792 static bool
08793 WGEN_Call_Returns_Ptr_To_Member_Func (gs_t exp)
08794 {
08795 TY_IDX exp_ty_idx = Get_TY(gs_tree_type(exp));
08796 if (gs_tree_code(exp) == GS_CALL_EXPR &&
08797 gs_type_ptrmemfunc_p(gs_tree_type(exp)) &&
08798 TY_return_in_mem(exp_ty_idx)) {
08799 return TRUE;
08800 }
08801 return FALSE;
08802 }
08803
08804
08805 static WN*
08806 WGEN_Expand_Ptr_To_Member_Func_Call_Expr (gs_t exp, TY_IDX nop_ty_idx,
08807 TYPE_ID rtype, TYPE_ID desc,
08808 WN_OFFSET offset, UINT field_id)
08809 {
08810 TY_IDX exp_ty_idx = Get_TY(gs_tree_type(exp));
08811 WN *wn;
08812 ST *st = New_ST (CURRENT_SYMTAB);
08813
08814 ST_Init(st, Save_Str("__ptr_to_mem_func"), CLASS_VAR, SCLASS_AUTO,
08815 EXPORT_LOCAL, exp_ty_idx);
08816 WN *target_wn = WN_Lda(Pointer_Mtype, ST_ofst(st), st);
08817 WGEN_Expand_Expr(exp, TRUE, nop_ty_idx, exp_ty_idx, 0, 0, FALSE, FALSE,
08818 target_wn);
08819 wn = WN_CreateLdid(OPR_LDID, rtype, desc, ST_ofst(st) + offset,
08820 st, exp_ty_idx, field_id);
08821 return wn;
08822 }