00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "defs.h"
00028 #include "glob.h"
00029 #include "config.h"
00030 #include "wn.h"
00031 #include "wn_util.h"
00032
00033 extern "C" {
00034 #include "gnu_config.h"
00035 }
00036 #include "gnu/system.h"
00037
00038 #include "srcpos.h"
00039 #include "gnu/machmode.h"
00040 extern "C" {
00041 #include "gnu/system.h"
00042 #include "gnu/tree.h"
00043 #include "cp-tree.h"
00044 #include "gnu/output.h"
00045 }
00046 #include "gnu/flags.h"
00047 #undef TARGET_PENTIUM // hack around macro definition in gnu
00048 #include "insn-config.h"
00049 #include "wfe_misc.h"
00050 #include "wfe_dst.h"
00051 #include "ir_reader.h"
00052 #include "wfe_expr.h"
00053 #include "wfe_stmt.h"
00054 #include "wfe_pragma.h"
00055 #include "wfe_decl.h"
00056 #include "tree_symtab.h"
00057 #include "targ_sim.h"
00058 #include <ctype.h>
00059 #include "tree_cmp.h"
00060
00061 #ifdef KEY
00062 #include "wn.h"
00063 #include "const.h"
00064 int make_symbols_weak = FALSE;
00065 bool in_cleanup = FALSE;
00066 #endif // KEY
00067
00068 extern "C" void error (const char *, ...);
00069
00070
00071
00072 char *WFE_Tree_Node_Name (tree op);
00073
00074 #define ENLARGE(x) (x + (x >> 1))
00075
00076 static BOOL *if_else_info_stack;
00077 static INT32 if_else_info_i;
00078 static INT32 if_else_info_max;
00079
00080 typedef struct case_info_t {
00081 INT64 case_lower_bound_value;
00082 INT64 case_upper_bound_value;
00083 LABEL_IDX case_label_idx;
00084 } CASE_INFO;
00085
00086 static CASE_INFO *case_info_stack;
00087 static INT32 case_info_i;
00088 static INT32 case_info_max;
00089
00090
00091 typedef struct switch_info_t {
00092 WN *index;
00093 INT32 start_case_index;
00094 LABEL_IDX default_label_idx;
00095 } SWITCH_INFO;
00096
00097 static SWITCH_INFO *switch_info_stack;
00098 static INT32 switch_info_i;
00099 static INT32 switch_info_max;
00100
00101 typedef struct break_continue_info_t {
00102 int tree_code;
00103 LABEL_IDX break_label_idx;
00104 LABEL_IDX continue_label_idx;
00105 tree scope;
00106 } BREAK_CONTINUE_INFO;
00107
00108 static BREAK_CONTINUE_INFO *break_continue_info_stack;
00109 static INT32 break_continue_info_i;
00110 static INT32 break_continue_info_max;
00111
00112 typedef struct label_info_t {
00113 LABEL_IDX label_idx;
00114 unsigned char symtab_idx;
00115 unsigned char defined;
00116 } LABEL_INFO;
00117
00118 static LABEL_INFO *undefined_labels_stack;
00119 static INT32 undefined_labels_i;
00120 static INT32 undefined_labels_max;
00121
00122 typedef struct scope_cleanup_info_t {
00123 tree stmt;
00124 LABEL_IDX label_idx;
00125 #ifdef KEY
00126 LABEL_IDX cmp_idx;
00127 bool cleanup_eh_only;
00128 struct vla_ {
00129 bool has_alloca;
00130 ST * alloca_st;
00131 vector<ST*> * alloca_sts_vector;
00132 } vla;
00133 #endif // KEY
00134 } SCOPE_CLEANUP_INFO;
00135
00136 static SCOPE_CLEANUP_INFO *scope_cleanup_stack;
00137 static INT32 scope_cleanup_i;
00138 static INT32 scope_cleanup_max;
00139
00140 static tree *scope_stack;
00141 static INT32 scope_i;
00142 static INT32 scope_max;
00143
00144 typedef struct temp_cleanup_info_t {
00145 tree expr;
00146 LABEL_IDX label_idx;
00147 #ifdef KEY
00148 bool cleanup_eh_only;
00149 #endif
00150 } TEMP_CLEANUP_INFO;
00151
00152 static TEMP_CLEANUP_INFO *temp_cleanup_stack;
00153 static INT32 temp_cleanup_i;
00154 static INT32 temp_cleanup_max;
00155
00156 #ifdef KEY
00157 #include <vector>
00158 #include <algorithm>
00159 #include <functional>
00160 #include <list>
00161 #include <stack>
00162 typedef struct handler_info_t {
00163 tree handler;
00164 vector<tree> *cleanups;
00165 vector<SCOPE_CLEANUP_INFO> *scope;
00166 vector<TEMP_CLEANUP_INFO> *temp_cleanup;
00167 vector<BREAK_CONTINUE_INFO> *break_continue;
00168 vector<ST_IDX> *handler_list;
00169 vector<ST_IDX> *eh_spec;
00170 LABEL_IDX label_idx;
00171
00172
00173
00174 LABEL_IDX cmp_idx[2];
00175 LABEL_IDX goto_idx;
00176 LABEL_IDX cleanups_idx;
00177 bool outermost;
00178 } HANDLER_INFO;
00179
00180 std::stack<HANDLER_INFO> handler_stack;
00181 #else
00182 typedef struct handler_info_t {
00183 tree handler;
00184 LABEL_IDX label_idx;
00185 } HANDLER_INFO;
00186 #endif // KEY
00187
00188 static HANDLER_INFO *handler_info_stack;
00189 static INT32 handler_info_i;
00190 static INT32 handler_info_max;
00191
00192 typedef struct eh_cleanup_info {
00193 tree cleanup;
00194 LABEL_IDX label_idx;
00195 LABEL_IDX goto_idx;
00196 } EH_CLEANUP_INFO;
00197
00198 static EH_CLEANUP_INFO *eh_cleanup_stack;
00199 static INT32 eh_cleanup_i;
00200 static INT32 eh_cleanup_max;
00201
00202 #ifdef KEY
00203
00204 bool processing_handler = false;
00205 bool try_block_seen;
00206 typedef struct eh_cleanup_entry {
00207 tree tryhandler;
00208 vector<tree> *cleanups;
00209 LABEL_IDX pad;
00210 LABEL_IDX start;
00211 LABEL_IDX goto_idx;
00212 } EH_CLEANUP_ENTRY;
00213
00214 static std::list<EH_CLEANUP_ENTRY> cleanup_list_for_eh;
00215
00216 class TYPE_FILTER_ENTRY {
00217 public:
00218 ST_IDX st;
00219 int filter;
00220 friend bool operator== (const TYPE_FILTER_ENTRY&, const TYPE_FILTER_ENTRY&);
00221 };
00222
00223 inline bool operator==(const TYPE_FILTER_ENTRY& x, const TYPE_FILTER_ENTRY& y)
00224 {
00225 return x.st == y.st;
00226 }
00227
00228 static vector<TYPE_FILTER_ENTRY> type_filter_vector;
00229 struct cmp_types :
00230 public std::binary_function<const TYPE_FILTER_ENTRY,
00231 const TYPE_FILTER_ENTRY, bool>
00232 {
00233 bool operator () (const TYPE_FILTER_ENTRY &e1,
00234 const TYPE_FILTER_ENTRY &e2)
00235 {
00236 return (e1.st < e2.st);
00237 }
00238 };
00239 static vector<ST_IDX> eh_spec_vector;
00240
00241 static vector<ST_IDX> eh_spec_func_end;
00242 static int current_eh_spec_ofst=1;
00243 static void Do_Cleanups_For_EH (void);
00244 static INITV_IDX lookup_handlers (vector<tree> * =0);
00245 static void Generate_unwind_resume (void);
00246
00247 static void WFE_fixup_target_expr (tree retval);
00248
00249
00250 LABEL_IDX WFE_unusable_label_idx;
00251
00252
00253 LABEL_IDX WFE_last_label_idx;
00254 #endif // KEY
00255
00256 static INT32 scope_number;
00257
00258 static TY_IDX
00259 Type_For_Function_Returning_Void (void)
00260 {
00261 static TY_IDX result = 0;
00262 if (result == 0) {
00263 TY &ty = New_TY (result);
00264 TY_Init (ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, 0);
00265 TYLIST_IDX tylist_idx;
00266 Set_TYLIST_type (New_TYLIST (tylist_idx), Void_Type);
00267 Set_TY_tylist (ty, tylist_idx);
00268 #ifdef KEY
00269 Set_TYLIST_type (New_TYLIST (tylist_idx), 0);
00270 #endif
00271 }
00272
00273 return result;
00274 }
00275
00276 static ST *
00277 Function_ST_For_String (const char * s)
00278 {
00279 ST * st = New_ST (GLOBAL_SYMTAB);
00280 PU_IDX pu_idx;
00281 PU & pu = New_PU (pu_idx);
00282 PU_Init (pu, Type_For_Function_Returning_Void (), GLOBAL_SYMTAB + 1);
00283 ST_Init (st, Save_Str(s),
00284 CLASS_FUNC, SCLASS_EXTERN, EXPORT_PREEMPTIBLE, TY_IDX(pu_idx));
00285 return st;
00286 }
00287
00288 #ifdef KEY
00289 static void
00290 Emit_Cleanup(tree cleanup)
00291 {
00292 int saved_make_symbols_weak;
00293
00294 saved_make_symbols_weak = make_symbols_weak;
00295 make_symbols_weak = TRUE;
00296 if (TREE_CODE(cleanup) == IF_STMT) {
00297
00298
00299
00300 FmtAssert(THEN_CLAUSE(cleanup) != NULL_TREE,
00301 ("Do_Temp_Cleanups: then clause should be non-null"));
00302 FmtAssert(ELSE_CLAUSE(cleanup) == NULL_TREE,
00303 ("Do_Temp_Cleanups: else clause should be null"));
00304 WN *test = WFE_Expand_Expr_With_Sequence_Point (IF_COND(cleanup),
00305 Boolean_type);
00306 WN *then_block = WN_CreateBlock();
00307 WN *else_block = WN_CreateBlock();
00308 WN *if_stmt = WN_CreateIf (test, then_block, else_block);
00309 WFE_Stmt_Append (if_stmt, Get_Srcpos());
00310 WFE_Stmt_Push (then_block, wfe_stmk_if_then, Get_Srcpos());
00311 tree then_clause = THEN_CLAUSE(cleanup);
00312 if (TREE_CODE(then_clause) == EXPR_WITH_FILE_LOCATION)
00313 then_clause = EXPR_WFL_NODE(then_clause);
00314 else if (TREE_CODE(then_clause) == CLEANUP_STMT)
00315 then_clause = CLEANUP_EXPR(then_clause);
00316 WFE_One_Stmt_Cleanup(then_clause);
00317 WFE_Stmt_Pop(wfe_stmk_if_then);
00318 } else {
00319 if (TREE_CODE(cleanup) == EXPR_WITH_FILE_LOCATION)
00320 cleanup = EXPR_WFL_NODE(cleanup);
00321 else if (TREE_CODE(cleanup) == CLEANUP_STMT)
00322 cleanup = CLEANUP_EXPR(cleanup);
00323 WFE_One_Stmt_Cleanup (cleanup);
00324 }
00325 make_symbols_weak = saved_make_symbols_weak;
00326 }
00327 #endif
00328
00329 static void
00330 #ifdef KEY
00331 Push_Scope_Cleanup (tree t, bool eh_only=false)
00332 #else
00333 Push_Scope_Cleanup (tree t)
00334 #endif
00335 {
00336
00337 if (scope_cleanup_i == -1 && TREE_CODE(t) == CLEANUP_STMT)
00338 return;
00339
00340 if (++scope_cleanup_i == scope_cleanup_max) {
00341 scope_cleanup_max = ENLARGE (scope_cleanup_max);
00342 scope_cleanup_stack =
00343 (SCOPE_CLEANUP_INFO *) realloc (scope_cleanup_stack,
00344 scope_cleanup_max * sizeof (SCOPE_CLEANUP_INFO));
00345 }
00346
00347 scope_cleanup_stack [scope_cleanup_i].stmt = t;
00348 if (TREE_CODE(t) == CLEANUP_STMT)
00349 New_LABEL (CURRENT_SYMTAB,
00350 scope_cleanup_stack [scope_cleanup_i].label_idx);
00351 else
00352 scope_cleanup_stack [scope_cleanup_i].label_idx = 0;
00353 #ifdef KEY
00354 if (TREE_CODE(t) == TRY_BLOCK)
00355 New_LABEL (CURRENT_SYMTAB,
00356 scope_cleanup_stack [scope_cleanup_i].cmp_idx);
00357 else
00358 scope_cleanup_stack [scope_cleanup_i].cmp_idx = 0;
00359 scope_cleanup_stack [scope_cleanup_i].cleanup_eh_only = eh_only;
00360 scope_cleanup_stack [scope_cleanup_i].vla.has_alloca = FALSE;
00361 scope_cleanup_stack [scope_cleanup_i].vla.alloca_st = NULL;
00362 scope_cleanup_stack [scope_cleanup_i].vla.alloca_sts_vector =
00363 new vector<ST*>();
00364 #endif // KEY
00365 }
00366
00367 #ifdef KEY
00368 static void
00369 Push_Handler_Info (tree handler, vector<tree> *v,
00370 vector<SCOPE_CLEANUP_INFO> *scope, vector<TEMP_CLEANUP_INFO> *temp,
00371 vector<BREAK_CONTINUE_INFO> *break_continue,
00372 vector<ST_IDX> *handler_list, vector<ST_IDX> *eh_spec,
00373 LABEL_IDX label_idx, bool outermost, LABEL_IDX cmp_idx[],
00374 LABEL_IDX goto_idx)
00375 {
00376 if (++handler_info_i == handler_info_max) {
00377 handler_info_max = ENLARGE (handler_info_max);
00378 handler_info_stack =
00379 (HANDLER_INFO *) realloc (handler_info_stack,
00380 handler_info_max * sizeof (HANDLER_INFO));
00381 }
00382
00383 handler_info_stack [handler_info_i].handler = handler;
00384 handler_info_stack [handler_info_i].cleanups = v;
00385 handler_info_stack [handler_info_i].scope = scope;
00386 handler_info_stack [handler_info_i].temp_cleanup = temp;
00387 handler_info_stack [handler_info_i].break_continue = break_continue;
00388 handler_info_stack [handler_info_i].handler_list = handler_list;
00389 handler_info_stack [handler_info_i].eh_spec = eh_spec;
00390 handler_info_stack [handler_info_i].label_idx = label_idx;
00391 handler_info_stack [handler_info_i].cmp_idx[0] = cmp_idx[0];
00392 handler_info_stack [handler_info_i].cmp_idx[1] = cmp_idx[1];
00393 New_LABEL (CURRENT_SYMTAB, handler_info_stack [handler_info_i].cleanups_idx);
00394 handler_info_stack [handler_info_i].goto_idx = goto_idx;
00395 handler_info_stack [handler_info_i].outermost = outermost;
00396 }
00397 #else
00398 static void
00399 Push_Handler_Info (tree handler, LABEL_IDX label_idx)
00400 {
00401 if (++handler_info_i == handler_info_max) {
00402 handler_info_max = ENLARGE (handler_info_max);
00403 handler_info_stack =
00404 (HANDLER_INFO *) realloc (handler_info_stack,
00405 handler_info_max * sizeof (HANDLER_INFO));
00406 }
00407
00408 handler_info_stack [handler_info_i].handler = handler;
00409 handler_info_stack [handler_info_i].label_idx = label_idx;
00410 }
00411 #endif // KEY
00412
00413 static void
00414 Push_EH_Cleanup (tree cleanup, LABEL_IDX label_idx, LABEL_IDX goto_idx)
00415 {
00416 if (++eh_cleanup_i == eh_cleanup_max) {
00417 eh_cleanup_max = ENLARGE (eh_cleanup_max);
00418 eh_cleanup_stack =
00419 (EH_CLEANUP_INFO *) realloc (eh_cleanup_stack,
00420 eh_cleanup_max * sizeof (EH_CLEANUP_INFO));
00421 }
00422
00423 eh_cleanup_stack[eh_cleanup_i].cleanup = cleanup;
00424 eh_cleanup_stack[eh_cleanup_i].label_idx = label_idx;
00425 eh_cleanup_stack[eh_cleanup_i].goto_idx = goto_idx;
00426 }
00427
00428 static void WFE_Expand_Handlers_Or_Cleanup (const HANDLER_INFO&);
00429
00430
00431 void
00432 Do_Handlers (void)
00433 {
00434 #ifdef KEY
00435 int saved_make_symbols_weak = make_symbols_weak;
00436 make_symbols_weak = TRUE;
00437
00438 if (key_exceptions) processing_handler = true;
00439 #endif
00440 while (handler_info_i != -1) {
00441 #ifndef KEY
00442 LABEL_IDX start_handlers;
00443 New_LABEL (CURRENT_SYMTAB, start_handlers);
00444 Set_LABEL_addr_saved (start_handlers);
00445 WFE_Stmt_Append (WN_CreateLabel ((ST_IDX) 0, start_handlers, 0, NULL),
00446 Get_Srcpos());
00447 #else
00448 LABEL_IDX start_handlers = handler_info_stack[handler_info_i].cmp_idx[1];
00449
00450
00451 if (start_handlers)
00452 {
00453 Is_True (LABEL_kind (Label_Table[start_handlers]) ==
00454 LKIND_BEGIN_HANDLER, ("Wrong label kind, expecting handler_begin"));
00455 WN * cmp_wn = WN_CreateLabel ((ST_IDX) 0, start_handlers, 0, NULL);
00456 WN_Set_Label_Is_Handler_Begin (cmp_wn);
00457 WFE_Stmt_Append (cmp_wn, Get_Srcpos());
00458 }
00459 WN * actual_cmp = WN_CreateLabel ((ST_IDX) 0,
00460 handler_info_stack[handler_info_i].cmp_idx[0], 0, NULL);
00461 WFE_Stmt_Append (actual_cmp, Get_Srcpos());
00462 #endif // !KEY
00463
00464 #ifdef KEY
00465 handler_stack.push (handler_info_stack[handler_info_i]);
00466 #endif
00467 --handler_info_i;
00468 WFE_Expand_Handlers_Or_Cleanup (handler_info_stack[handler_info_i+1]);
00469 #ifdef KEY
00470 handler_stack.pop();
00471 #endif
00472 }
00473 #ifdef KEY
00474 processing_handler = false;
00475 Do_Cleanups_For_EH();
00476 if (key_exceptions)
00477 FmtAssert (cleanup_list_for_eh.empty(), ("EH Cleanup list not completely processed"));
00478
00479 make_symbols_weak = saved_make_symbols_weak;
00480 #endif
00481 }
00482
00483 static void Call_Rethrow (void);
00484 #ifndef KEY
00485 static void Call_Terminate (void);
00486 #endif // !KEY
00487
00488 void
00489 Do_EH_Cleanups (void)
00490 {
00491 #ifndef KEY
00492 for (int i = 0; i <= eh_cleanup_i; ++i) {
00493 WFE_Stmt_Append (
00494 WN_CreateLabel ((ST_IDX) 0, eh_cleanup_stack [i].label_idx,
00495 0, NULL),
00496 Get_Srcpos());
00497 tree cleanup = eh_cleanup_stack [i].cleanup;
00498 WFE_One_Stmt (CLEANUP_EXPR(eh_cleanup_stack [i].cleanup));
00499 LABEL_IDX goto_idx = eh_cleanup_stack [i].goto_idx;
00500 if (goto_idx)
00501 WFE_Stmt_Append (
00502 WN_CreateGoto ((ST_IDX) 0, goto_idx), Get_Srcpos());
00503 else
00504 Call_Rethrow();
00505 }
00506 Call_Terminate();
00507 #endif
00508 eh_cleanup_i = -1;
00509 }
00510
00511 #ifdef KEY
00512 ST *
00513 Get_eh_spec_ST (void)
00514 {
00515 FmtAssert (!eh_spec_func_end.empty(),("Empty Type Filter Table"));
00516
00517 ARB_HANDLE arb = New_ARB();
00518 int eh_spec_size = eh_spec_func_end.size();
00519 ARB_Init (arb, 0, eh_spec_size-1, sizeof(ST_IDX));
00520 Set_ARB_flags (arb, ARB_flags(arb) | ARB_FIRST_DIMEN | ARB_LAST_DIMEN);
00521 STR_IDX str = Save_Str ("__EH_SPEC_TABLE__");
00522 TY_IDX ty;
00523 TY_Init (New_TY(ty), eh_spec_size*sizeof(ST_IDX), KIND_ARRAY, MTYPE_UNKNOWN, str);
00524 Set_TY_arb (ty, arb);
00525 Set_TY_etype (ty, MTYPE_TO_TY_array[MTYPE_U4]);
00526 ST * etable = New_ST (CURRENT_SYMTAB);
00527 ST_Init (etable, str, CLASS_VAR, SCLASS_EH_REGION_SUPP, EXPORT_LOCAL, ty);
00528 Set_ST_is_initialized (*etable);
00529 Set_ST_one_per_pu (etable);
00530 return etable;
00531 }
00532
00533 ST *
00534 Get_typeinfo_ST (void)
00535 {
00536 FmtAssert (!type_filter_vector.empty(),("Empty Type Filter Table"));
00537
00538 ARB_HANDLE arb = New_ARB();
00539 ARB_Init (arb, 0, type_filter_vector.size()-1, sizeof(TYPE_FILTER_ENTRY));
00540 Set_ARB_flags (arb, ARB_flags(arb) | ARB_FIRST_DIMEN | ARB_LAST_DIMEN);
00541 STR_IDX str = Save_Str ("__TYPEINFO_TABLE__");
00542 FLD_HANDLE fld1 = New_FLD ();
00543 FLD_Init (fld1, Save_Str ("st"),
00544 MTYPE_TO_TY_array[MTYPE_U4], 0);
00545 FLD_HANDLE fld2 = New_FLD ();
00546 FLD_Init (fld2, Save_Str ("filter"),
00547 MTYPE_TO_TY_array[MTYPE_U4], 4);
00548 Set_FLD_flags (fld2, FLD_LAST_FIELD);
00549
00550 TY_IDX struct_ty;
00551 TY_Init (New_TY(struct_ty), sizeof(TYPE_FILTER_ENTRY), KIND_STRUCT,
00552 MTYPE_M, Save_Str ("__TYPEINFO_ENTRY__"));
00553 Set_TY_fld (struct_ty, fld1);
00554 TY_IDX ty;
00555 TY_Init (New_TY(ty), type_filter_vector.size()*sizeof(TYPE_FILTER_ENTRY), KIND_ARRAY, MTYPE_M, str);
00556 Set_TY_arb (ty, arb);
00557 Set_TY_etype (ty, struct_ty);
00558 ST * etable = New_ST (CURRENT_SYMTAB);
00559 ST_Init (etable, str, CLASS_VAR, SCLASS_EH_REGION_SUPP, EXPORT_LOCAL, ty);
00560 Set_ST_is_initialized (*etable);
00561 Set_ST_one_per_pu (etable);
00562 return etable;
00563 }
00564
00565 void
00566 Do_EH_Tables (void)
00567 {
00568 INITV_IDX blk, start;
00569 INITO_IDX id;
00570
00571 for (int i=0; i<type_filter_vector.size(); ++i)
00572 {
00573 INITV_IDX st = New_INITV();
00574
00575
00576
00577
00578 if (type_filter_vector[i].st)
00579 INITV_Set_VAL (Initv_Table[st],
00580 Enter_tcon (Host_To_Targ (MTYPE_U4,
00581 type_filter_vector[i].st)), 1);
00582 else
00583 INITV_Set_ZERO (Initv_Table[st], MTYPE_U4, 1);
00584
00585 INITV_IDX filter = New_INITV();
00586 INITV_Set_VAL (Initv_Table[filter],
00587 Enter_tcon (Host_To_Targ (MTYPE_U4,
00588 type_filter_vector[i].filter)), 1);
00589 Set_INITV_next (st, filter);
00590
00591 if (i == 0)
00592 {
00593 blk = start = New_INITV();
00594 INITV_Init_Block (blk, st);
00595 }
00596 else
00597 {
00598 INITV_IDX next_blk = New_INITV();
00599 INITV_Init_Block (next_blk, st);
00600 Set_INITV_next (blk, next_blk);
00601 blk = next_blk;
00602 }
00603 if (i == (type_filter_vector.size()-1))
00604 {
00605 ST * typeinfo = Get_typeinfo_ST ();
00606 id = New_INITO (ST_st_idx(typeinfo), start);
00607
00608
00609 INITV_IDX index = INITV_next (INITV_next (INITO_val (
00610 PU_misc_info (Get_Current_PU()))));
00611
00612
00613 INITV_IDX bkup = INITV_next (index);
00614 INITV_Set_VAL (Initv_Table[index],
00615 Enter_tcon (Host_To_Targ (MTYPE_U4, id)), 1);
00616 Set_INITV_next (index, bkup);
00617 }
00618 }
00619 type_filter_vector.clear();
00620
00621 INITV_IDX prev_st = 0;
00622 for (int i=0; i<eh_spec_func_end.size(); ++i)
00623 {
00624 INITV_IDX st = New_INITV();
00625 FmtAssert (eh_spec_func_end[i] >= 0, ("Invalid eh-spec entry in front-end"));
00626 if (eh_spec_func_end[i])
00627 INITV_Set_VAL (Initv_Table[st], Enter_tcon (
00628 Host_To_Targ (MTYPE_U4, eh_spec_func_end[i])), 1);
00629 else
00630 INITV_Set_ZERO (Initv_Table[st], MTYPE_U4, 1);
00631
00632 if (prev_st == 0)
00633 {
00634 start = New_INITV();
00635 INITV_Init_Block (start, st);
00636 }
00637 else
00638 Set_INITV_next (prev_st, st);
00639 prev_st = st;
00640 }
00641 if (!eh_spec_func_end.empty())
00642 {
00643 ST * eh_spec = Get_eh_spec_ST ();
00644 id = New_INITO (ST_st_idx(eh_spec), start);
00645 INITV_IDX index = INITV_next (INITV_next (INITV_next (
00646 INITO_val (PU_misc_info (Get_Current_PU())))));
00647
00648
00649 INITV_IDX bkup = INITV_next (index);
00650 INITV_Set_VAL (Initv_Table[index],
00651 Enter_tcon (Host_To_Targ (MTYPE_U4, id)), 1);
00652 Set_INITV_next (index, bkup);
00653 }
00654 eh_spec_func_end.clear();
00655 current_eh_spec_ofst = 1;
00656 }
00657
00658
00659
00660
00661
00662 static void
00663 Do_Cleanups_For_EH (void)
00664 {
00665 for (std::list<EH_CLEANUP_ENTRY>::iterator i = cleanup_list_for_eh.begin();
00666 i != cleanup_list_for_eh.end(); ++i) {
00667 EH_CLEANUP_ENTRY e = *i;
00668
00669 WN *pad_wn = WN_CreateLabel ((ST_IDX) 0, e.pad, 0, NULL);
00670 WN_Set_Label_Is_Handler_Begin (pad_wn);
00671 WFE_Stmt_Append (pad_wn, Get_Srcpos());
00672
00673 WFE_Stmt_Append (WN_CreateLabel ((ST_IDX) 0, e.start, 0, NULL),
00674 Get_Srcpos());
00675
00676 for (vector<tree>::iterator j=e.cleanups->begin();
00677 j!=e.cleanups->end();++j)
00678 {
00679 tree cleanup = *j;
00680 Emit_Cleanup(cleanup);
00681 }
00682 if (e.goto_idx)
00683 WFE_Stmt_Append (WN_CreateGoto ((ST_IDX) 0, e.goto_idx), Get_Srcpos());
00684 else
00685 Generate_unwind_resume();
00686 }
00687 cleanup_list_for_eh.clear();
00688 }
00689 #endif // KEY
00690
00691 static void
00692 Pop_Scope_And_Do_Cleanups (void)
00693 {
00694 Is_True(scope_cleanup_i != -1,
00695 ("Pop_Scope_And_Do_Cleanups: scope_cleanup-stack is empty"));
00696
00697 while (true) {
00698 tree t = scope_cleanup_stack [scope_cleanup_i].stmt;
00699 if (TREE_CODE(t) != CLEANUP_STMT) {
00700 if (TREE_CODE(t) == SCOPE_STMT)
00701 {
00702 #ifdef KEY
00703
00704 if (scope_cleanup_stack[scope_cleanup_i].vla.has_alloca)
00705 WFE_Dealloca (scope_cleanup_stack[scope_cleanup_i].vla.alloca_st,
00706 scope_cleanup_stack[scope_cleanup_i].vla.alloca_sts_vector);
00707 #endif
00708 --scope_cleanup_i;
00709 }
00710 break;
00711 }
00712 Is_True(scope_cleanup_i != -1,
00713 ("Pop_Scope_And_Do_Cleanups: no scope_stmt on stack"));
00714 #ifdef KEY
00715 if (scope_cleanup_stack[scope_cleanup_i].cleanup_eh_only)
00716 {
00717 --scope_cleanup_i;
00718 continue;
00719 }
00720 #endif
00721 INT j = scope_cleanup_i - 1;
00722 LABEL_IDX goto_idx = 0;
00723 #ifdef KEY
00724 while (j != -1 && (TREE_CODE(scope_cleanup_stack [j].stmt) != CLEANUP_STMT
00725 || scope_cleanup_stack[j].cleanup_eh_only)) {
00726 #else
00727 while (j != -1 && TREE_CODE(scope_cleanup_stack [j].stmt) != CLEANUP_STMT) {
00728 #endif
00729 if (TREE_CODE(scope_cleanup_stack [j].stmt) == TRY_BLOCK)
00730 break;
00731 --j;
00732 }
00733 if (j != -1 && TREE_CODE(scope_cleanup_stack [j].stmt) == CLEANUP_STMT)
00734 goto_idx = scope_cleanup_stack [j].label_idx;
00735 Push_EH_Cleanup (t,
00736 scope_cleanup_stack [scope_cleanup_i] .label_idx,
00737 goto_idx);
00738 --scope_cleanup_i;
00739 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [scope_cleanup_i+1].stmt));
00740 }
00741 }
00742
00743 static void
00744 Push_Scope (tree t)
00745 {
00746 if (++scope_i == scope_max) {
00747 scope_max = ENLARGE (scope_max);
00748 scope_stack =
00749 (tree *) realloc (scope_stack,
00750 scope_max * sizeof (tree));
00751 }
00752 scope_stack[scope_i] = t;
00753 }
00754
00755 #ifdef KEY
00756
00757 void
00758 Push_Top_Level_Scope (tree t)
00759 {
00760 PARENT_SCOPE (t) = 0;
00761 Push_Scope (t);
00762 }
00763
00764
00765 void Pop_Top_Level_Scope (void)
00766 {
00767 --scope_i;
00768 }
00769 #endif
00770
00771 void
00772 Push_Temp_Cleanup (tree t, bool is_cleanup
00773 #ifdef KEY
00774 , bool cleanup_eh_only
00775 #endif
00776 )
00777 {
00778 #ifdef KEY
00779
00780 tree guard_var = WFE_Get_Guard_Var();
00781 if (guard_var != NULL_TREE) {
00782 t = build_stmt((tree_code) IF_STMT,
00783 c_common_truthvalue_conversion(guard_var),
00784 t, NULL_TREE);
00785 }
00786 #endif
00787
00788 if (++temp_cleanup_i == temp_cleanup_max) {
00789 temp_cleanup_max = ENLARGE (temp_cleanup_max);
00790 temp_cleanup_stack =
00791 (TEMP_CLEANUP_INFO *) realloc (temp_cleanup_stack,
00792 temp_cleanup_max *
00793 sizeof (TEMP_CLEANUP_INFO));
00794 }
00795
00796 temp_cleanup_stack [temp_cleanup_i].expr = t;
00797 if (is_cleanup)
00798 New_LABEL (CURRENT_SYMTAB, temp_cleanup_stack [temp_cleanup_i].label_idx);
00799 else
00800 temp_cleanup_stack [temp_cleanup_i].label_idx = 0;
00801 #ifdef KEY
00802 temp_cleanup_stack [temp_cleanup_i].cleanup_eh_only = cleanup_eh_only;
00803 #endif
00804 }
00805
00806
00807
00808 static bool
00809 cleanup_matches (tree candidate, tree target)
00810 {
00811 if (candidate == target)
00812 return TRUE;
00813
00814
00815 if (TREE_CODE(candidate) == IF_STMT &&
00816 THEN_CLAUSE(candidate) == target)
00817 return TRUE;
00818
00819 return FALSE;
00820 }
00821
00822
00823 bool
00824 Is_Cleanup_Only (void)
00825 {
00826 return temp_cleanup_stack[temp_cleanup_i].cleanup_eh_only;
00827 }
00828
00829 void
00830 Do_Temp_Cleanups (tree t)
00831 {
00832 Is_True(temp_cleanup_i != -1, ("Do_Temp_Cleanups: stack empty"));
00833 #ifdef KEY
00834 while (!cleanup_matches(temp_cleanup_stack[temp_cleanup_i].expr, t))
00835 #else
00836 while (temp_cleanup_stack[temp_cleanup_i].expr != t)
00837 #endif
00838 {
00839 #ifdef KEY
00840 if (temp_cleanup_stack[temp_cleanup_i].cleanup_eh_only) {
00841
00842
00843 --temp_cleanup_i;
00844 continue;
00845 }
00846 #endif
00847 LABEL_IDX goto_idx = 0;
00848 INT j = temp_cleanup_i - 1;
00849 tree cleanup = temp_cleanup_stack [temp_cleanup_i].expr;
00850 #ifdef KEY
00851 while (j != -1 && (temp_cleanup_stack [j].label_idx == 0 ||
00852 temp_cleanup_stack[j].cleanup_eh_only))
00853 #else
00854 while (j != -1 && temp_cleanup_stack [j].label_idx == 0)
00855 #endif
00856 --j;
00857 if (j != -1)
00858 goto_idx = temp_cleanup_stack [j].label_idx;
00859 Push_EH_Cleanup (cleanup,
00860 temp_cleanup_stack [temp_cleanup_i].label_idx,
00861 goto_idx);
00862 #ifdef KEY
00863 Emit_Cleanup(cleanup);
00864 #else
00865 WFE_One_Stmt (cleanup);
00866 #endif
00867 --temp_cleanup_i;
00868 }
00869 --temp_cleanup_i;
00870
00871 #ifdef KEY
00872 if (key_exceptions && processing_handler &&
00873 !cleanup_matches(temp_cleanup_stack[temp_cleanup_i+1].expr, t))
00874 {
00875 HANDLER_INFO hi = handler_stack.top();
00876 if (hi.temp_cleanup)
00877 {
00878 int n = hi.temp_cleanup->size()-1;
00879 while (!cleanup_matches((*hi.temp_cleanup)[n].expr, t)) {
00880 LABEL_IDX goto_idx = 0;
00881 INT j = n - 1;
00882 tree cleanup = (*hi.temp_cleanup) [n].expr;
00883 while (j != -1 && (*hi.temp_cleanup) [j].label_idx == 0) --j;
00884 if (j != -1)
00885 goto_idx = (*hi.temp_cleanup) [j].label_idx;
00886 Push_EH_Cleanup (cleanup, (*hi.temp_cleanup) [n].label_idx, goto_idx);
00887 Emit_Cleanup(cleanup);
00888 --n;
00889 }
00890 }
00891 }
00892 #endif // KEY
00893 }
00894
00895 static void
00896 WFE_Record_Loop_Switch (int tree_code)
00897 {
00898 INT32 i;
00899 Is_True(tree_code == DO_STMT ||
00900 tree_code == FOR_STMT ||
00901 tree_code == WHILE_STMT ||
00902 tree_code == SWITCH_STMT,
00903 ("WFE_Record_Loop_Switch: unexpected tree_code"));
00904
00905 if (++break_continue_info_i == break_continue_info_max) {
00906 break_continue_info_max = ENLARGE (break_continue_info_max);
00907 break_continue_info_stack =
00908 (BREAK_CONTINUE_INFO *) realloc (break_continue_info_stack,
00909 break_continue_info_max *
00910 sizeof (BREAK_CONTINUE_INFO));
00911 }
00912
00913 break_continue_info_stack
00914 [break_continue_info_i].tree_code = tree_code;
00915 break_continue_info_stack
00916 [break_continue_info_i].break_label_idx = 0;
00917 break_continue_info_stack
00918 [break_continue_info_i].continue_label_idx = 0;
00919 if (scope_cleanup_i == -1)
00920 break_continue_info_stack
00921 [break_continue_info_i].scope = NULL_TREE;
00922 else {
00923 for (i = scope_cleanup_i;
00924 TREE_CODE(scope_cleanup_stack[i].stmt) == CLEANUP_STMT;
00925 --i);
00926 Is_True (i != -1 &&
00927 (TREE_CODE(scope_cleanup_stack[i].stmt) == SCOPE_STMT ||
00928 TREE_CODE(scope_cleanup_stack[i].stmt) == TRY_BLOCK),
00929 ("WFE_Record_Loop_Switch: no scope_stmt on stack"));
00930 break_continue_info_stack
00931 [break_continue_info_i].scope = scope_cleanup_stack[i].stmt;
00932 }
00933 }
00934
00935 static void
00936 WFE_Expand_Case (tree low, tree high)
00937 {
00938 WN *wn;
00939 WN *lower_bound;
00940 WN *upper_bound;
00941 LABEL_IDX case_label_idx;
00942
00943 if (high != NULL_TREE)
00944 DevWarn("encountered case range");
00945
00946 if (low == NULL_TREE) {
00947 if (switch_info_stack [switch_info_i].default_label_idx != 0)
00948 error ("duplicate default label");
00949 else {
00950 New_LABEL (CURRENT_SYMTAB, case_label_idx);
00951 switch_info_stack [switch_info_i].default_label_idx = case_label_idx;
00952 }
00953 }
00954
00955 else {
00956 if (TREE_CODE(low) == VAR_DECL)
00957 low = DECL_INITIAL(low);
00958 if (high != NULL_TREE && TREE_CODE(high) == VAR_DECL)
00959 high = DECL_INITIAL(high);
00960 lower_bound = WFE_Expand_Expr (low);
00961 upper_bound = (high == NULL_TREE) ? lower_bound
00962 : WFE_Expand_Expr(high);
00963 if (++case_info_i == case_info_max) {
00964 case_info_max = ENLARGE(case_info_max);
00965 case_info_stack = (CASE_INFO *) realloc (case_info_stack,
00966 case_info_max * sizeof (CASE_INFO));
00967 }
00968
00969 case_info_stack
00970 [case_info_i].case_lower_bound_value =
00971 (low == NULL_TREE) ? 0 : WN_const_val (lower_bound);
00972 case_info_stack
00973 [case_info_i].case_upper_bound_value =
00974 (high == NULL_TREE) ? WN_const_val (lower_bound)
00975 : WN_const_val (upper_bound);
00976 for (int i = switch_info_stack [switch_info_i].start_case_index;
00977 i < case_info_i; ++i)
00978 if (WN_const_val(lower_bound) ==
00979 case_info_stack [i].case_lower_bound_value)
00980 error ("duplicate case");
00981 New_LABEL (CURRENT_SYMTAB, case_label_idx);
00982 case_info_stack [case_info_i].case_label_idx = case_label_idx;
00983 }
00984
00985 wn = WN_CreateLabel ((ST_IDX) 0, case_label_idx, 0, NULL);
00986 WFE_Stmt_Append (wn, Get_Srcpos ());
00987 }
00988
00989 static void
00990 WFE_Declare_Nonlocal_Label (tree label)
00991 {
00992 WFE_Get_LABEL (label, FALSE);
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002 static WN *
01003 idname_from_regnum (int gcc_reg)
01004 {
01005 if (gcc_reg < 0) {
01006 DevWarn("unrecognized register name in asm");
01007 return NULL;
01008 }
01009 else {
01010 extern PREG_NUM Map_Reg_To_Preg [];
01011 PREG_NUM preg = Map_Reg_To_Preg [gcc_reg];
01012 if (preg < 0) {
01013 DevWarn("couldn't map asm regname to preg");
01014 return NULL;
01015 }
01016 ST *st;
01017 if (Preg_Offset_Is_Int(preg))
01018 st = Int_Preg;
01019 else if (Preg_Offset_Is_Float(preg))
01020 st = Float_Preg;
01021 #ifdef TARG_X8664
01022 else if (Preg_Offset_Is_X87(preg))
01023 st = X87_Preg;
01024 #endif
01025 else
01026 FmtAssert (FALSE, ("unexpected preg %d", preg));
01027 return WN_CreateIdname((WN_OFFSET) preg, st);
01028 }
01029 }
01030
01031 char *
01032 remove_plus_modifier(char *s)
01033 {
01034 #define MAX_NON_PLUS_CONSTRAINT_CHARS 7
01035 static char out[MAX_NON_PLUS_CONSTRAINT_CHARS + 1];
01036 int i = 0;
01037 while (i <= MAX_NON_PLUS_CONSTRAINT_CHARS)
01038 {
01039 while (*s == '+')
01040 {
01041 ++s;
01042 }
01043 out[i++] = *s;
01044 if (*s == '\0')
01045 {
01046 return out;
01047 }
01048 else
01049 {
01050 ++s;
01051 }
01052 }
01053 Fail_FmtAssertion("Constraint string too long");
01054
01055 }
01056
01057 BOOL
01058 constraint_supported (const char *s)
01059 {
01060 while (*s != 0) {
01061 if (*s != 'r' &&
01062 *s != 'f' &&
01063 *s != 'm' &&
01064 *s != '+' &&
01065 *s != ',' &&
01066 *s != '=' &&
01067 (*s < '0' ||
01068 *s > '9')) {
01069 return FALSE;
01070 }
01071 ++s;
01072 }
01073 return TRUE;
01074 }
01075
01076 ST *
01077 st_of_new_temp_for_expr(const WN *expr)
01078 {
01079 static unsigned int temp_count = 0;
01080
01081 static char temp_name[64];
01082
01083 sprintf(temp_name, "asm.by.address.temp_%u", temp_count++);
01084
01085 ST *retval = New_ST(CURRENT_SYMTAB);
01086
01087 ST_Init (retval,
01088 Save_Str (temp_name),
01089 CLASS_VAR,
01090 SCLASS_AUTO,
01091 EXPORT_LOCAL,
01092 MTYPE_To_TY(WN_rtype(expr)));
01093 return retval;
01094 }
01095
01096
01097
01098
01099 static char *operand_constraint_array[MAX_RECOG_OPERANDS];
01100
01101 static BOOL
01102 constraint_by_address (const char *s)
01103 {
01104 #ifndef TARG_X8664
01105 if (strchr (s, 'm')) {
01106 #else
01107 if (strchr (s, 'm') || strchr (s, 'g')) {
01108 #endif
01109 return TRUE;
01110 }
01111 else if (isdigit(*s)) {
01112 return constraint_by_address (operand_constraint_array[*s - '0']);
01113 }
01114 else {
01115 return FALSE;
01116 }
01117 }
01118
01119 #ifdef KEY
01120
01121 static void
01122 update_opnd_num(int *opnd_num_map, char *constraint_string)
01123 {
01124 char *p;
01125
01126 for (p = constraint_string; *p != '\0'; p++) {
01127 if (*p >= '0' &&
01128 *p <= '9') {
01129 unsigned int old_opnd_num = *p - '0';
01130 unsigned int new_opnd_num = opnd_num_map[old_opnd_num];
01131 Is_True(new_opnd_num >= 0 && new_opnd_num <= old_opnd_num,
01132 ("update_opnd_num: bad opnd numbers map"));
01133 *p = new_opnd_num + '0';
01134 }
01135 }
01136 }
01137 #endif
01138
01139 static WN *
01140 add_offset(WN_OFFSET ofst,
01141 WN *address)
01142 {
01143 return WN_Binary(OPR_ADD, Pointer_Mtype,
01144 WN_Intconst(MTYPE_I8, ofst),
01145 address);
01146 }
01147
01148 static WN *
01149 address_of (const WN *wn)
01150 {
01151 if (WN_operator(wn) == OPR_ILOAD ||
01152 WN_operator(wn) == OPR_MLOAD) {
01153 return add_offset(WN_offset(wn), WN_kid0(wn));
01154 }
01155 else if ((WN_operator(wn) == OPR_LDID) &&
01156 (ST_sclass(WN_st(wn)) != SCLASS_REG)) {
01157 return WN_Lda (Pointer_Mtype,
01158 WN_offset(wn),
01159 WN_st(wn),
01160 (UINT) 0);
01161 }
01162
01163 return NULL;
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 static PREG_NUM asm_neg_preg = -2;
01183
01184 void
01185 Wfe_Expand_Asm_Operands (tree string,
01186 tree outputs,
01187 tree inputs,
01188 tree clobbers,
01189 int vol,
01190 char *filename,
01191 int line)
01192 {
01193
01194
01195
01196
01197
01198
01199
01200
01201 int ninputs = list_length (inputs);
01202
01203 tree tail;
01204 char *constraint_string;
01205
01206 #ifdef KEY
01207
01208
01209
01210
01211
01212
01213
01214
01215 int opnd_num_map[MAX_RECOG_OPERANDS];
01216 #endif
01217
01218
01219
01220 int i = 0;
01221
01222 for (tail = outputs; tail; tail = TREE_CHAIN (tail)) {
01223 #ifdef KEY
01224
01225 opnd_num_map[i] = i;
01226
01227
01228
01229 constraint_string =
01230 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01231 #else
01232 constraint_string = TREE_STRING_POINTER (TREE_PURPOSE (tail));
01233 #endif
01234 operand_constraint_array[i] = constraint_string;
01235 ++i;
01236 }
01237 #ifdef KEY
01238 opnd_num_map[i] = -1;
01239 #endif
01240
01241 FmtAssert(i < MAX_RECOG_OPERANDS, ("Too many asm operands"));
01242 for ( ; i < MAX_RECOG_OPERANDS; ++i) {
01243 operand_constraint_array[i] = NULL;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 for (tail = outputs;
01260 tail;
01261 tail = TREE_CHAIN (tail))
01262 {
01263 #ifdef KEY
01264
01265
01266 constraint_string =
01267 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01268 #else
01269 constraint_string = TREE_STRING_POINTER (TREE_PURPOSE (tail));
01270 #endif
01271
01272 if (strchr (constraint_string, '+') ||
01273 constraint_by_address (constraint_string))
01274 {
01275 ++ninputs;
01276 }
01277 if (flag_bad_asm_constraint_kills_stmt &&
01278 !constraint_supported (constraint_string)) {
01279 DevWarn ("Unrecognized constraint %s; "
01280 "asm statement at line %d discarded",
01281 constraint_string, lineno);
01282 return;
01283 }
01284 }
01285
01286 WN *asm_wn = WN_CreateAsm_Stmt (ninputs + 2,
01287 const_cast<char*>TREE_STRING_POINTER (string));
01288
01289 WN *clobber_block = WN_CreateBlock ();
01290
01291 WN_kid0(asm_wn) = clobber_block;
01292
01293 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
01294 {
01295 char *clobber_string =
01296 const_cast<char *>TREE_STRING_POINTER (TREE_VALUE (tail));
01297
01298 WN *clobber_pragma = NULL;
01299
01300 int gcc_reg = decode_reg_name(clobber_string);
01301 if (gcc_reg == -3)
01302 WN_Set_Asm_Clobbers_Cc(asm_wn);
01303 else if (gcc_reg == -4)
01304 WN_Set_Asm_Clobbers_Mem(asm_wn);
01305 else {
01306 WN *clobbered_idname = idname_from_regnum (gcc_reg);
01307
01308 if (clobbered_idname) {
01309
01310
01311
01312 ST *clobber_st = New_ST(CURRENT_SYMTAB);
01313 ST_Init(clobber_st,
01314 Str_To_Index (Save_Str (clobber_string),
01315 Current_Strtab),
01316 CLASS_NAME,
01317 SCLASS_UNKNOWN,
01318 EXPORT_LOCAL,
01319 (TY_IDX) 0);
01320
01321 clobber_pragma = WN_CreateXpragma (WN_PRAGMA_ASM_CLOBBER,
01322 ST_st_idx(clobber_st),
01323 1);
01324 WN_kid0 (clobber_pragma) = clobbered_idname;
01325 }
01326 else {
01327
01328
01329
01330
01331 ST *clobber_st = New_ST(CURRENT_SYMTAB);
01332 ST_Init(clobber_st,
01333 Str_To_Index (Save_Str (clobber_string),
01334 Current_Strtab),
01335 CLASS_NAME,
01336 SCLASS_UNKNOWN,
01337 EXPORT_LOCAL,
01338 (TY_IDX) 0);
01339
01340 clobber_pragma = WN_CreatePragma (WN_PRAGMA_ASM_CLOBBER,
01341 ST_st_idx(clobber_st),
01342 (INT32) 0,
01343 (INT32) 0);
01344
01345 WN_Set_Asm_Volatile (asm_wn);
01346 }
01347 }
01348
01349 if (clobber_pragma != NULL)
01350 WN_INSERT_BlockAfter (clobber_block,
01351 WN_last (clobber_block),
01352 clobber_pragma);
01353 }
01354
01355 WN *output_constraint_block = WN_CreateBlock ();
01356
01357 WN_kid1(asm_wn) = output_constraint_block;
01358
01359 i = 2;
01360
01361
01362
01363
01364 UINT32 opnd_num = 0;
01365
01366 for (tail = outputs;
01367 tail;
01368 tail = TREE_CHAIN (tail))
01369 {
01370 #ifdef KEY
01371
01372
01373 constraint_string =
01374 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01375 #else
01376 constraint_string = TREE_STRING_POINTER (TREE_PURPOSE (tail));
01377 #endif
01378
01379 if (constraint_by_address(constraint_string)) {
01380
01381
01382 WN *lhs_rvalue = WFE_Expand_Expr(TREE_OPERAND(tail, 0));
01383 WN *addr_of_lvalue = address_of(lhs_rvalue);
01384 FmtAssert(addr_of_lvalue != NULL,
01385 ("WFE_Expand_Asm_Operands: output operand must be lvalue"));
01386 WN_kid (asm_wn, i) =
01387 WN_CreateAsm_Input (constraint_string, opnd_num, addr_of_lvalue);
01388 ++i;
01389 #ifdef KEY
01390
01391
01392 for (int j = opnd_num + 1; opnd_num_map[j] != -1; j++) {
01393 opnd_num_map[j]--;
01394 }
01395 #endif
01396 }
01397 ++opnd_num;
01398 }
01399
01400 for (tail = inputs;
01401 tail;
01402 tail = TREE_CHAIN (tail))
01403 {
01404 if (TREE_PURPOSE (tail) == NULL_TREE)
01405 {
01406 Fail_FmtAssertion ("hard register `%s' listed as "
01407 "input operand to `asm'",
01408 TREE_STRING_POINTER (TREE_VALUE (tail)) );
01409 return;
01410 }
01411
01412 #ifdef KEY
01413
01414
01415 constraint_string =
01416 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01417 #else
01418 constraint_string = TREE_STRING_POINTER (TREE_PURPOSE (tail));
01419 #endif
01420
01421 if (flag_bad_asm_constraint_kills_stmt &&
01422 !constraint_supported (constraint_string)) {
01423 DevWarn ("Unrecognized constraint %s; "
01424 "asm statement at line %d discarded",
01425 constraint_string, lineno);
01426 return;
01427 }
01428
01429 WN *input_rvalue = WFE_Expand_Expr (TREE_VALUE (tail));
01430
01431 if (constraint_by_address(constraint_string)) {
01432 WN *addr_of_rvalue = address_of(input_rvalue);
01433 if (addr_of_rvalue != NULL) {
01434
01435
01436 input_rvalue = addr_of_rvalue;
01437 }
01438 else {
01439
01440
01441 ST *temp_st = st_of_new_temp_for_expr(input_rvalue);
01442 WN *store_wn = WN_Stid(WN_rtype(input_rvalue),
01443 (WN_OFFSET) 0,
01444 temp_st,
01445
01446
01447
01448
01449
01450 MTYPE_To_TY(WN_rtype(input_rvalue)),
01451 input_rvalue);
01452 WFE_Stmt_Append (store_wn, Get_Srcpos ());
01453 input_rvalue = WN_Lda (Pointer_Mtype,
01454 (WN_OFFSET) 0,
01455 temp_st,
01456 (UINT) 0);
01457 }
01458 }
01459
01460 #ifdef KEY
01461
01462 update_opnd_num(opnd_num_map, constraint_string);
01463 #endif
01464
01465 WN_kid (asm_wn, i) =
01466 WN_CreateAsm_Input (constraint_string, opnd_num, input_rvalue);
01467 ++i;
01468 ++opnd_num;
01469 }
01470
01471
01472 WFE_Stmt_Append (asm_wn, Get_Srcpos ());
01473
01474
01475
01476 opnd_num = 0;
01477 #ifdef KEY
01478
01479
01480
01481
01482
01483
01484 INT nonmem_opnd_num = 0;
01485 #endif
01486 for (tail = outputs;
01487 tail;
01488 tail = TREE_CHAIN (tail), ++opnd_num)
01489 {
01490 #ifdef KEY
01491
01492
01493 constraint_string =
01494 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01495 #else
01496 constraint_string = TREE_STRING_POINTER (TREE_PURPOSE (tail));
01497 #endif
01498
01499 if (!constraint_by_address(constraint_string)) {
01500
01501
01502 BOOL plus_modifier = (strchr (constraint_string, '+') != NULL);
01503
01504 char input_opnd_constraint[8];
01505
01506 if (plus_modifier)
01507 {
01508
01509 constraint_string = remove_plus_modifier(constraint_string);
01510
01511
01512
01513 #ifdef KEY
01514 sprintf(input_opnd_constraint, "%d", nonmem_opnd_num);
01515 #else
01516 sprintf(input_opnd_constraint, "%d", opnd_num);
01517 #endif
01518 }
01519 #ifdef KEY
01520 nonmem_opnd_num ++;
01521 #endif
01522
01523 WN *output_rvalue_wn = WFE_Lhs_Of_Modify_Expr (MODIFY_EXPR,
01524 TREE_VALUE (tail),
01525 #ifdef TARG_SL
01526 NULL,
01527 #endif
01528 plus_modifier,
01529 (TY_IDX) 0,
01530 (INT64) 0,
01531 (UINT32) 0,
01532 FALSE,
01533 NULL,
01534 asm_neg_preg,
01535 FALSE,
01536 FALSE);
01537
01538 if (plus_modifier)
01539 {
01540 WN_kid (asm_wn, i) =
01541 WN_CreateAsm_Input (input_opnd_constraint,
01542 opnd_num,
01543 output_rvalue_wn);
01544 ++i;
01545 }
01546
01547
01548
01549
01550 TYPE_ID desc = TY_mtype (Get_TY (TREE_TYPE (TREE_VALUE (tail))));
01551 ST *preg_st = MTYPE_To_PREG(desc);
01552
01553 ST *constraint_st = New_ST(CURRENT_SYMTAB);
01554 ST_Init(constraint_st,
01555 Str_To_Index (Save_Str (constraint_string),
01556 Current_Strtab),
01557 CLASS_NAME,
01558 SCLASS_UNKNOWN,
01559 EXPORT_LOCAL,
01560 (TY_IDX) 0);
01561
01562 WN *constraint_pragma =
01563 WN_CreatePragma (WN_PRAGMA_ASM_CONSTRAINT,
01564 (ST_IDX) ST_st_idx(preg_st),
01565 (INT32) ST_st_idx(constraint_st),
01566 asm_neg_preg,
01567 opnd_num);
01568
01569 WN_INSERT_BlockAfter (output_constraint_block,
01570 WN_last (output_constraint_block),
01571 constraint_pragma);
01572 --asm_neg_preg;
01573 }
01574 }
01575
01576 if (vol)
01577 {
01578 WN_Set_Asm_Volatile (asm_wn);
01579 }
01580 }
01581
01582 LABEL_IDX
01583 WFE_Get_LABEL (tree label, int def)
01584 {
01585 LABEL_IDX label_idx = DECL_LABEL_IDX(label);
01586 SYMTAB_IDX symtab_idx = DECL_SYMTAB_IDX(label);
01587
01588 if (label_idx == 0
01589 #ifdef KEY
01590
01591 || label_idx <= WFE_unusable_label_idx
01592 #endif
01593 ) {
01594 New_LABEL (CURRENT_SYMTAB, label_idx);
01595 DECL_LABEL_IDX(label) = label_idx;
01596 DECL_SYMTAB_IDX(label) = CURRENT_SYMTAB;
01597 #ifdef KEY
01598 WFE_last_label_idx = label_idx;
01599
01600 DECL_LABEL_DEFINED(label) = FALSE;
01601 #endif
01602 if (!def) {
01603 if (++undefined_labels_i == undefined_labels_max) {
01604 undefined_labels_max = ENLARGE(undefined_labels_max);
01605 undefined_labels_stack =
01606 (LABEL_INFO *) realloc (undefined_labels_stack,
01607 undefined_labels_max * sizeof (LABEL_INFO));
01608 }
01609 undefined_labels_stack [undefined_labels_i].label_idx = label_idx;
01610 undefined_labels_stack [undefined_labels_i].symtab_idx = CURRENT_SYMTAB;
01611 undefined_labels_stack [undefined_labels_i].defined = FALSE;
01612 }
01613 }
01614 else {
01615 if (def) {
01616 for (int i = undefined_labels_i; i >= 0; --i) {
01617 if (undefined_labels_stack [i].label_idx == label_idx &&
01618 undefined_labels_stack [i].symtab_idx == CURRENT_SYMTAB) {
01619 undefined_labels_stack [i].defined = TRUE;
01620 break;
01621 }
01622 }
01623 }
01624
01625
01626
01627
01628
01629
01630
01631 }
01632
01633 return label_idx;
01634 }
01635
01636 void
01637 WFE_Check_Undefined_Labels (void)
01638 {
01639 INT32 i;
01640 for (i = undefined_labels_i; i >= 0; --i) {
01641 LABEL_IDX label_idx = undefined_labels_stack [undefined_labels_i].label_idx;
01642 SYMTAB_IDX symtab_idx = undefined_labels_stack [undefined_labels_i].symtab_idx;
01643
01644 if (symtab_idx < CURRENT_SYMTAB)
01645 break;
01646 FmtAssert (undefined_labels_stack [undefined_labels_i].defined,
01647 ("label not defined within current function scope"));
01648 }
01649 undefined_labels_i = i;
01650 }
01651
01652
01653 void
01654 WFE_Stmt_Init (void)
01655 {
01656 if_else_info_max = 32;
01657 if_else_info_i = -1;
01658 if_else_info_stack =
01659 (BOOL *) malloc (sizeof (BOOL) * if_else_info_max);
01660
01661 case_info_max = 32;
01662 case_info_i = -1;
01663 case_info_stack =
01664 (CASE_INFO *) malloc (sizeof (CASE_INFO) * case_info_max);
01665
01666 switch_info_max = 32;
01667 switch_info_i = -1;
01668 switch_info_stack =
01669 (SWITCH_INFO *) malloc (sizeof (SWITCH_INFO) * switch_info_max);
01670
01671 break_continue_info_max = 32;
01672 break_continue_info_i = -1;
01673 break_continue_info_stack =
01674 (BREAK_CONTINUE_INFO *) malloc (sizeof (BREAK_CONTINUE_INFO) *
01675 break_continue_info_max);
01676
01677 undefined_labels_max = 32;
01678 undefined_labels_i = -1;
01679 undefined_labels_stack =
01680 (LABEL_INFO *) malloc (sizeof (LABEL_INFO) * undefined_labels_max);
01681
01682 scope_cleanup_max = 32;
01683 scope_cleanup_i = -1;
01684 scope_cleanup_stack =
01685 (SCOPE_CLEANUP_INFO *) malloc (sizeof (SCOPE_CLEANUP_INFO) *
01686 scope_cleanup_max);
01687
01688 scope_max = 32;
01689 scope_i = -1;
01690 scope_stack =
01691 (tree *) malloc (sizeof (tree) * scope_max);
01692
01693 temp_cleanup_max = 32;
01694 temp_cleanup_i = -1;
01695 temp_cleanup_stack =
01696 (TEMP_CLEANUP_INFO *) malloc (sizeof (TEMP_CLEANUP_INFO) *
01697 temp_cleanup_max);
01698
01699 handler_info_max = 32;
01700 handler_info_i = -1;
01701 handler_info_stack =
01702 (HANDLER_INFO *) malloc (sizeof(HANDLER_INFO) * handler_info_max);
01703
01704 eh_cleanup_max = 32;
01705 eh_cleanup_i = -1;
01706 eh_cleanup_stack =
01707 (EH_CLEANUP_INFO *) malloc (sizeof (EH_CLEANUP_INFO) * eh_cleanup_max);
01708
01709 scope_number = 0;
01710 }
01711
01712 #ifdef KEY
01713
01714 static void
01715 Cleanup_To_Scope_From_Handler(tree scope)
01716 {
01717 INT32 i = scope_cleanup_i;
01718 INT32 j = -1;
01719 Is_True(i != -1, ("Cleanup_To_Scope_From_Handler: scope_cleanup_stack empty"));
01720 while ((i != -1) && (scope_cleanup_stack [i].stmt != scope)) {
01721 if (TREE_CODE(scope_cleanup_stack [i].stmt) == SCOPE_STMT)
01722 j = i;
01723 --i;
01724 }
01725
01726 bool found_target_scope = false;
01727 if (i != -1) found_target_scope = true;
01728
01729 if (j != -1) {
01730 i = scope_cleanup_i;
01731 while (i != j) {
01732 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT &&
01733 !scope_cleanup_stack[i].cleanup_eh_only)
01734 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
01735 --i;
01736 }
01737 }
01738 if (found_target_scope) return;
01739
01740 FmtAssert (processing_handler, ("Invalid scope"));
01741
01742 HANDLER_INFO hi = handler_stack.top();
01743 FmtAssert (hi.scope, ("No scope information available"));
01744 i = hi.scope->size()-1;
01745 j = -1;
01746 Is_True(i != 0, ("Cleanup_To_Scope_From_Handler: scope_cleanup_stack empty"));
01747
01748 while ((*hi.scope)[i].stmt != scope) {
01749 if (TREE_CODE((*hi.scope)[i].stmt) == SCOPE_STMT)
01750 j = i;
01751 --i;
01752 }
01753 if (j != -1) {
01754 i = hi.scope->size()-1;
01755 while (i != j) {
01756 if (TREE_CODE((*hi.scope)[i].stmt) == CLEANUP_STMT &&
01757 !(*hi.scope)[i].cleanup_eh_only)
01758 WFE_One_Stmt_Cleanup (CLEANUP_EXPR((*hi.scope)[i].stmt));
01759 --i;
01760 }
01761 }
01762 }
01763 #endif // KEY
01764
01765 static void
01766 Cleanup_To_Scope(tree scope)
01767 {
01768 INT32 i = scope_cleanup_i;
01769 INT32 j = -1;
01770 Is_True(i != -1, ("Cleanup_To_Scope: scope_cleanup_stack empty"));
01771 while (scope_cleanup_stack [i].stmt != scope) {
01772 if (TREE_CODE(scope_cleanup_stack [i].stmt) == SCOPE_STMT)
01773 j = i;
01774 --i;
01775 }
01776
01777 if (j != -1) {
01778 i = scope_cleanup_i;
01779 while (i != j) {
01780 #ifdef KEY
01781 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT &&
01782 !scope_cleanup_stack[i].cleanup_eh_only)
01783 #else
01784 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT)
01785 #endif
01786 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
01787 --i;
01788 }
01789 }
01790 }
01791
01792 #ifdef KEY
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805 static void
01806 WFE_Expand_Break (void)
01807 {
01808 INT32 i = break_continue_info_i;
01809 LABEL_IDX label_idx;
01810 tree scope;
01811 WN * wn;
01812
01813 HANDLER_INFO hi;
01814 if (processing_handler)
01815 hi = handler_stack.top();
01816 if (i == -1)
01817 {
01818 FmtAssert (processing_handler && hi.break_continue, ("No break/continue info"));
01819 label_idx = (*hi.break_continue)[hi.break_continue->size()-1].break_label_idx;
01820 scope = (*hi.break_continue)[hi.break_continue->size()-1].scope;
01821 }
01822 else
01823 {
01824 label_idx = break_continue_info_stack[i].break_label_idx;
01825 scope = break_continue_info_stack[i].scope;
01826 }
01827
01828 if (label_idx == 0) {
01829
01830
01831 New_LABEL (CURRENT_SYMTAB, label_idx);
01832 break_continue_info_stack [i].break_label_idx = label_idx;
01833 }
01834
01835 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
01836
01837 if (scope)
01838 {
01839 if (key_exceptions && processing_handler)
01840 Cleanup_To_Scope_From_Handler (scope);
01841 else
01842 Cleanup_To_Scope (scope);
01843 }
01844
01845 WFE_Stmt_Append (wn, Get_Srcpos());
01846 }
01847 #else
01848 static void
01849 WFE_Expand_Break (void)
01850 {
01851 INT32 i = break_continue_info_i;
01852 LABEL_IDX label_idx = break_continue_info_stack[i].break_label_idx;
01853 tree scope = break_continue_info_stack[i].scope;
01854 WN * wn;
01855
01856 if (label_idx == 0) {
01857 New_LABEL (CURRENT_SYMTAB, label_idx);
01858 break_continue_info_stack [i].break_label_idx = label_idx;
01859 }
01860
01861 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
01862
01863 if (scope)
01864 Cleanup_To_Scope (scope);
01865
01866 WFE_Stmt_Append (wn, Get_Srcpos());
01867 }
01868
01869 #endif // KEY
01870
01871 #ifdef KEY
01872 static void
01873 WFE_Expand_Continue (void)
01874 {
01875 INT32 i = break_continue_info_i;
01876 LABEL_IDX label_idx=0;
01877 tree scope;
01878
01879 HANDLER_INFO hi;
01880 if (processing_handler)
01881 hi = handler_stack.top();
01882 if (i == -1)
01883 {
01884 FmtAssert (processing_handler, ("WFE_Expand_Continue: No break/continue info"));
01885 scope = (*hi.break_continue)[hi.break_continue->size()-1].scope;
01886 }
01887 else scope = break_continue_info_stack [i].scope;
01888 WN * wn;
01889
01890
01891 if (i != -1) {
01892 while (break_continue_info_stack [i].tree_code == SWITCH_STMT) --i;
01893 if (i != -1) {
01894 label_idx = break_continue_info_stack [i].continue_label_idx;
01895 if (label_idx == 0) {
01896
01897
01898 New_LABEL (CURRENT_SYMTAB, label_idx);
01899 break_continue_info_stack [i].continue_label_idx = label_idx;
01900 }
01901 }
01902 }
01903
01904 if (key_exceptions && processing_handler && !label_idx)
01905 {
01906 INT32 j = hi.break_continue->size()-1;
01907 while ((*hi.break_continue)[j].tree_code == SWITCH_STMT) --j;
01908 FmtAssert (j != -1, ("Error with 'continue' in handler"));
01909 label_idx = (*hi.break_continue)[j].continue_label_idx;
01910 FmtAssert (label_idx,("WFE_Expand_Goto: No label to goto"));
01911 }
01912
01913 if (scope)
01914 {
01915 if (key_exceptions && processing_handler)
01916 Cleanup_To_Scope_From_Handler (scope);
01917 else
01918 Cleanup_To_Scope (scope);
01919 }
01920
01921 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
01922 WFE_Stmt_Append (wn, Get_Srcpos());
01923 }
01924 #else
01925 static void
01926 WFE_Expand_Continue (void)
01927 {
01928 INT32 i = break_continue_info_i;
01929 LABEL_IDX label_idx;
01930 tree scope = break_continue_info_stack [i].scope;
01931 WN * wn;
01932
01933
01934 while (break_continue_info_stack [i].tree_code == SWITCH_STMT) --i;
01935 label_idx = break_continue_info_stack [i].continue_label_idx;
01936 if (label_idx == 0) {
01937 New_LABEL (CURRENT_SYMTAB, label_idx);
01938 break_continue_info_stack [i].continue_label_idx = label_idx;
01939 }
01940
01941 if (scope)
01942 Cleanup_To_Scope (scope);
01943
01944 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
01945 WFE_Stmt_Append (wn, Get_Srcpos());
01946 }
01947 #endif // KEY
01948
01949 static void
01950 WFE_Expand_Loop (tree stmt)
01951 {
01952 tree cond, body, incr = NULL_TREE, init = NULL_TREE;
01953
01954 WN * loop_stmt;
01955 WN * loop_test;
01956 WN * loop_block;
01957 WN * loop_body;
01958
01959 WFE_Record_Loop_Switch (TREE_CODE(stmt));
01960
01961 switch (TREE_CODE(stmt)) {
01962 case WHILE_STMT:
01963 cond = WHILE_COND(stmt);
01964 body = WHILE_BODY(stmt);
01965 break;
01966
01967 case DO_STMT:
01968 cond = DO_COND(stmt);
01969 body = DO_BODY(stmt);
01970 break;
01971
01972 case FOR_STMT:
01973 incr = FOR_EXPR(stmt);
01974 cond = FOR_COND(stmt);
01975 body = FOR_BODY(stmt);
01976 for (init = FOR_INIT_STMT(stmt); init; init = TREE_CHAIN(init))
01977 WFE_Expand_Stmt(init);
01978 break;
01979
01980 default:
01981 Is_True(FALSE, ("WFE_Expand_Loop: unexpected TREE_CODE"));
01982 break;
01983 }
01984
01985 #ifdef KEY
01986
01987 if (!cond) {
01988 loop_test = WN_Intconst (Boolean_type, 1);
01989 }
01990 else
01991 #endif // KEY
01992 if (TREE_CODE(cond) == TREE_LIST &&
01993 TREE_VALUE(cond) == NULL) {
01994
01995 tree stmt;
01996 WN *cond_block;
01997 cond_block = WN_CreateBlock ();
01998 WFE_Stmt_Push (cond_block, wfe_stmk_while_cond, Get_Srcpos());
01999 for (stmt = TREE_PURPOSE(cond); stmt; stmt = TREE_CHAIN(stmt))
02000 WFE_Expand_Stmt (stmt);
02001 WFE_Stmt_Pop (wfe_stmk_while_cond);
02002 loop_test = WN_Intconst (Boolean_type, 1);
02003 if (WN_first (cond_block)) {
02004 loop_test = WN_CreateComma (OPR_COMMA, Boolean_type, MTYPE_V,
02005 cond_block, loop_test);
02006 }
02007 else
02008 WN_Delete (cond_block);
02009 }
02010
02011 else
02012 loop_test = WFE_Expand_Expr_With_Sequence_Point (cond, Boolean_type);
02013
02014 loop_body = WN_CreateBlock ();
02015
02016 if (TREE_CODE(stmt) == WHILE_STMT ||
02017 TREE_CODE(stmt) == FOR_STMT)
02018 loop_stmt = WN_CreateWhileDo (loop_test, loop_body);
02019 else
02020 loop_stmt = WN_CreateDoWhile (loop_test, loop_body);
02021
02022 WFE_Stmt_Append (loop_stmt, Get_Srcpos());
02023
02024 if (body) {
02025 WFE_Stmt_Push (loop_body, wfe_stmk_while_body, Get_Srcpos());
02026 while (body) {
02027 WFE_Expand_Stmt (body);
02028 body = TREE_CHAIN(body);
02029 }
02030
02031 if (break_continue_info_stack
02032 [break_continue_info_i].continue_label_idx) {
02033 WFE_Stmt_Append (
02034 WN_CreateLabel ((ST_IDX) 0,
02035 break_continue_info_stack
02036 [break_continue_info_i].continue_label_idx,
02037 0, NULL),
02038 Get_Srcpos());
02039 }
02040 #ifdef KEY // bug 3265
02041 if (incr) {
02042 Push_Temp_Cleanup(incr, false);
02043 WFE_One_Stmt(incr);
02044 Do_Temp_Cleanups(incr);
02045 }
02046 #else
02047 if (incr)
02048 WFE_One_Stmt(incr);
02049 #endif
02050
02051 WFE_Stmt_Pop (wfe_stmk_while_body);
02052 }
02053
02054 if (break_continue_info_stack [break_continue_info_i].break_label_idx) {
02055 WFE_Stmt_Append (
02056 WN_CreateLabel ((ST_IDX) 0,
02057 break_continue_info_stack
02058 [break_continue_info_i].break_label_idx,
02059 0, NULL),
02060 Get_Srcpos());
02061 }
02062
02063 --break_continue_info_i;
02064 }
02065
02066 #ifndef KEY
02067 void
02068 WFE_Expand_Goto (tree label)
02069 {
02070 WN *wn;
02071 LABEL_IDX label_idx = WFE_Get_LABEL (label, FALSE);
02072 if ((CURRENT_SYMTAB > GLOBAL_SYMTAB + 1) &&
02073 (DECL_SYMTAB_IDX(label) < CURRENT_SYMTAB))
02074 wn = WN_CreateGotoOuterBlock (label_idx, DECL_SYMTAB_IDX(label));
02075 else {
02076 tree scope = LABEL_SCOPE(label);
02077 if (scope != NULL_TREE && scope_cleanup_i != -1) {
02078 INT32 scope_number = SCOPE_NUMBER(scope);
02079 INT32 i = scope_cleanup_i;
02080 INT32 j = -1;
02081 while (i != -1) {
02082 if (TREE_CODE(scope_cleanup_stack [i].stmt) == SCOPE_STMT)
02083 if (SCOPE_NUMBER(scope_cleanup_stack [i].stmt) >= scope_number)
02084 break;
02085 j = i;
02086 --i;
02087 }
02088 if (j != -1) {
02089 i = scope_cleanup_i;
02090 while (i != j) {
02091 if (TREE_CODE(scope_cleanup_stack[i].stmt) == CLEANUP_STMT)
02092 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
02093 --i;
02094 }
02095 }
02096 }
02097
02098 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
02099 }
02100
02101 WFE_Stmt_Append (wn, Get_Srcpos());
02102 }
02103 #else
02104 void
02105 WFE_Expand_Goto (tree label)
02106 {
02107 WN *wn;
02108 bool in_handler=false;
02109 vector<tree>::reverse_iterator ci, li;
02110 LABEL_IDX label_idx = WFE_Get_LABEL (label, FALSE);
02111 if ((CURRENT_SYMTAB > GLOBAL_SYMTAB + 1) &&
02112 (DECL_SYMTAB_IDX(label) < CURRENT_SYMTAB))
02113 wn = WN_CreateGotoOuterBlock (label_idx, DECL_SYMTAB_IDX(label));
02114 else {
02115 tree scope = LABEL_SCOPE(label);
02116 if (scope != NULL_TREE && scope_cleanup_i != -1) {
02117 vector<tree> Label_scope_nest;
02118 while (scope) {
02119 Label_scope_nest.push_back (scope);
02120 scope = PARENT_SCOPE (scope);
02121 }
02122 INT32 i = scope_cleanup_i;
02123 while (i != -1) {
02124 if (TREE_CODE(scope_cleanup_stack [i].stmt) == SCOPE_STMT)
02125 break;
02126 --i;
02127 }
02128 vector<tree> Current_scope_nest;
02129 if (i != -1) {
02130 scope = scope_cleanup_stack[i].stmt;
02131 while (scope) {
02132 Current_scope_nest.push_back (scope);
02133 scope = PARENT_SCOPE (scope);
02134 }
02135 }
02136
02137 li=Label_scope_nest.rbegin();
02138 ci=Current_scope_nest.rbegin();
02139 for (; li!=Label_scope_nest.rend(), ci!=Current_scope_nest.rend();
02140 ++li, ++ci)
02141 if (*li != *ci) break;
02142 if (ci!=Current_scope_nest.rend())
02143 {
02144 i = scope_cleanup_i;
02145 Is_True(i != -1, ("WFE_Expand_Goto: scope_cleanup_stack empty"));
02146 while ((i >= 0) && (scope_cleanup_stack [i].stmt != *ci))
02147 {
02148 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT &&
02149 !scope_cleanup_stack[i].cleanup_eh_only)
02150 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
02151 --i;
02152 }
02153 if (i == -1)
02154 in_handler = true;
02155 }
02156 }
02157
02158 if (in_handler && (!key_exceptions || !processing_handler))
02159 DevWarn ("Goto in exception handler but exceptions not enabled?");
02160
02161
02162
02163 if (in_handler && processing_handler && key_exceptions)
02164 {
02165 HANDLER_INFO hi = handler_stack.top();
02166
02167 INT32 i = hi.scope->size()-1;
02168 Is_True(i != -1, ("WFE_Expand_Goto: scope_cleanup_stack empty inside handler"));
02169 while ((i >= 0) && ((*hi.scope) [i].stmt != *ci)) {
02170 if (TREE_CODE((*hi.scope) [i].stmt) == CLEANUP_STMT &&
02171 !(*hi.scope) [i].cleanup_eh_only)
02172 WFE_One_Stmt_Cleanup (CLEANUP_EXPR((*hi.scope) [i].stmt));
02173 --i;
02174 }
02175 }
02176
02177 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
02178 }
02179
02180 WFE_Stmt_Append (wn, Get_Srcpos());
02181 }
02182 #endif
02183
02184 static void
02185 WFE_Expand_Computed_Goto (tree exp)
02186 {
02187 DevWarn ("encountered indirect jump");
02188 WN *addr = WFE_Expand_Expr (exp);
02189 WN *wn = WN_CreateAgoto (addr);
02190 WFE_Stmt_Append (wn, Get_Srcpos());
02191 }
02192
02193 #ifndef KEY
02194 static
02195 #endif
02196 void
02197 WFE_Expand_If (tree stmt)
02198 {
02199 WN * if_stmt;
02200 WN * test;
02201 WN * then_block;
02202 WN * else_block;
02203
02204 test = WFE_Expand_Expr_With_Sequence_Point (IF_COND(stmt),
02205 Boolean_type);
02206 then_block = WN_CreateBlock ();
02207 else_block = WN_CreateBlock ();
02208 if_stmt = WN_CreateIf (test, then_block, else_block);
02209 WFE_Stmt_Append (if_stmt, Get_Srcpos ());
02210 if (THEN_CLAUSE(stmt)) {
02211 WFE_Stmt_Push (then_block, wfe_stmk_if_then, Get_Srcpos ());
02212 for (tree t = THEN_CLAUSE(stmt); t; t = TREE_CHAIN(t))
02213 WFE_Expand_Stmt (t);
02214 WFE_Stmt_Pop (wfe_stmk_if_then);
02215 }
02216 if (ELSE_CLAUSE(stmt)) {
02217 WFE_Stmt_Push (else_block, wfe_stmk_if_else, Get_Srcpos());
02218 for (tree t = ELSE_CLAUSE(stmt); t; t = TREE_CHAIN(t))
02219 WFE_Expand_Stmt (t);
02220 WFE_Stmt_Pop (wfe_stmk_if_else);
02221 }
02222 }
02223
02224 void
02225 WFE_Expand_Label (tree label)
02226 {
02227 LABEL_IDX label_idx = WFE_Get_LABEL (label, TRUE);
02228 DECL_SYMTAB_IDX(label) = CURRENT_SYMTAB;
02229
02230 if (!DECL_LABEL_DEFINED(label)) {
02231 WN *wn;
02232 DECL_LABEL_DEFINED(label) = TRUE;
02233 wn = WN_CreateLabel ((ST_IDX) 0, label_idx, 0, NULL);
02234 WFE_Stmt_Append (wn, Get_Srcpos ());
02235 }
02236 }
02237
02238 #ifdef KEY
02239 extern void WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_ID, ST *);
02240 #endif // KEY
02241
02242 void
02243 WFE_Expand_Return (tree stmt, tree retval)
02244 {
02245 WN *wn;
02246
02247 if (retval == NULL_TREE) {
02248 Do_Temp_Cleanups (stmt);
02249 int i = scope_cleanup_i;
02250 while (i != -1) {
02251 #ifdef KEY
02252 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT &&
02253 !scope_cleanup_stack[i].cleanup_eh_only)
02254 #else
02255 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT)
02256 #endif
02257 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
02258 --i;
02259 }
02260 #ifdef KEY
02261 if (key_exceptions && processing_handler) {
02262 HANDLER_INFO hi = handler_stack.top();
02263 FmtAssert (hi.scope, ("NULL scope"));
02264 int j = hi.scope->size()-1;
02265 while (j != -1) {
02266 if (TREE_CODE((*hi.scope)[j].stmt) == CLEANUP_STMT &&
02267 !(*hi.scope)[j].cleanup_eh_only)
02268 WFE_One_Stmt_Cleanup (CLEANUP_EXPR((*hi.scope) [j].stmt));
02269 --j;
02270 }
02271 }
02272 #endif
02273 wn = WN_CreateReturn ();
02274 }
02275 else {
02276 WN *rhs_wn;
02277 TY_IDX ret_ty_idx = Get_TY(TREE_TYPE(TREE_TYPE(Current_Function_Decl())));
02278
02279 #ifdef KEY
02280 bool copied_return_value = FALSE;
02281 #ifdef PATHSCALE_MERGE
02282 bool need_iload_via_fake_parm = FALSE;
02283 WN *target_wn = NULL;
02284 #endif
02285
02286
02287
02288
02289 if (TY_return_in_mem(ret_ty_idx)) {
02290 FmtAssert (TY_mtype (ret_ty_idx) == MTYPE_M,
02291 ("WFE_Expand_Return: return_in_mem type is not MTYPE_M"));
02292
02293 tree t = retval;
02294 while (TREE_CODE(t) == NOP_EXPR) {
02295 t = TREE_OPERAND(t, 0);
02296 }
02297 if (TREE_CODE(t) == TARGET_EXPR) {
02298 WFE_fixup_target_expr(t);
02299 copied_return_value = TRUE;
02300 #ifdef PATHSCALE_MERGE
02301 } else if (TREE_CODE(t) == CALL_EXPR) {
02302
02303
02304
02305 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
02306 ST *st = WN_st(first_formal);
02307 target_wn = WN_Ldid(Pointer_Mtype, 0, st, ST_type(st));
02308 copied_return_value = TRUE;
02309 need_iload_via_fake_parm = TRUE;
02310 #endif
02311 }
02312 }
02313 #endif
02314
02315 rhs_wn = WFE_Expand_Expr_With_Sequence_Point (
02316 retval,
02317 TY_mtype (ret_ty_idx)
02318 #ifdef PATHSCALE_MERGE
02319 , target_wn
02320 #endif
02321 );
02322 #ifdef PATHSCALE_MERGE
02323
02324
02325
02326 if (rhs_wn == NULL) {
02327 Is_True(need_iload_via_fake_parm == TRUE,
02328 ("WFE_Expand_Return: unexpected rhs_wn NULL"));
02329 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
02330 ST *st = WN_st(first_formal);
02331 TY_IDX ty_idx = Get_TY(TREE_TYPE(retval));
02332 WN *ldid_wn = WN_Ldid(Pointer_Mtype, 0, st, ST_type(st));
02333 rhs_wn = WN_Iload(TY_mtype(ty_idx), 0, ty_idx, ldid_wn);
02334 }
02335 #endif
02336
02337 WN * cleanup_block = WN_CreateBlock ();
02338 WFE_Stmt_Push (cleanup_block, wfe_stmk_temp_cleanup, Get_Srcpos ());
02339 Do_Temp_Cleanups (stmt);
02340 int i = scope_cleanup_i;
02341 while (i != -1) {
02342 #ifdef KEY
02343 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT &&
02344 !scope_cleanup_stack[i].cleanup_eh_only)
02345 #else
02346 if (TREE_CODE(scope_cleanup_stack [i].stmt) == CLEANUP_STMT)
02347 #endif
02348 WFE_One_Stmt_Cleanup (CLEANUP_EXPR(scope_cleanup_stack [i].stmt));
02349 --i;
02350 }
02351 #ifdef KEY
02352 if (key_exceptions && processing_handler) {
02353 HANDLER_INFO hi = handler_stack.top();
02354 FmtAssert (hi.scope, ("NULL scope"));
02355 int j = hi.scope->size()-1;
02356 while (j != -1) {
02357 if (TREE_CODE((*hi.scope)[j].stmt) == CLEANUP_STMT &&
02358 !(*hi.scope)[j].cleanup_eh_only)
02359 WFE_One_Stmt_Cleanup (CLEANUP_EXPR((*hi.scope) [j].stmt));
02360 --j;
02361 }
02362 }
02363 #endif
02364 WFE_Stmt_Pop (wfe_stmk_temp_cleanup);
02365
02366 if (WN_first (cleanup_block)) {
02367
02368 if (TREE_CODE(retval) == TARGET_EXPR ||
02369 TREE_CODE(retval) == COMPOUND_EXPR) {
02370
02371 WN * insertee = WN_kid0 (rhs_wn);
02372 if (((WN_operator (rhs_wn) != OPR_COMMA) ||
02373 (WN_has_side_effects (WN_kid1 (rhs_wn))))
02374 #ifdef KEY
02375
02376
02377 && (TREE_CODE(retval) == TARGET_EXPR)
02378 #endif
02379 ) {
02380
02381 Fail_FmtAssertion ("WFE_Expand_Return: TARGET_EXPR with cleanup");
02382 }
02383 WN_INSERT_BlockAfter (insertee, WN_last (insertee), cleanup_block);
02384 }
02385 else {
02386 #ifndef KEY // bug 3265
02387 if (WN_has_side_effects (rhs_wn)) {
02388 DevWarn ("WFE_Expand_Return: cleanup block and expressson has side effects");
02389 #endif
02390 ST *ret_st = Gen_Temp_Symbol (ret_ty_idx, "__return_val");
02391 #ifdef KEY
02392 WFE_add_pragma_to_enclosing_regions (WN_PRAGMA_LOCAL, ret_st);
02393 #endif
02394 TYPE_ID ret_mtype = TY_mtype (ret_ty_idx);
02395 WFE_Set_ST_Addr_Saved (rhs_wn);
02396 wn = WN_Stid (ret_mtype, 0, ret_st, ret_ty_idx, rhs_wn);
02397 WFE_Stmt_Append (wn, Get_Srcpos ());
02398 rhs_wn = WN_Ldid (ret_mtype, 0, ret_st, ret_ty_idx);
02399 #ifndef KEY
02400 }
02401 #endif
02402 WFE_Stmt_Append (cleanup_block, Get_Srcpos ());
02403 }
02404 }
02405
02406 if ((!WFE_Keep_Zero_Length_Structs &&
02407 TY_mtype (ret_ty_idx) == MTYPE_M &&
02408 TY_size (ret_ty_idx) == 0)
02409 #ifdef KEY
02410
02411
02412 || copied_return_value
02413 #endif
02414 ) {
02415
02416 if (WN_has_side_effects (rhs_wn)) {
02417 rhs_wn = WN_CreateEval (rhs_wn);
02418 WFE_Stmt_Append(rhs_wn, Get_Srcpos());
02419 }
02420 wn = WN_CreateReturn ();
02421 }
02422 #ifdef KEY
02423 else if (TY_return_in_mem(ret_ty_idx)) {
02424
02425
02426
02427 FmtAssert (TY_mtype (ret_ty_idx) == MTYPE_M,
02428 ("WFE_Expand_Return: return_in_mem type is not MTYPE_M"));
02429
02430 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
02431 TY_IDX tidx = ST_type(WN_st(first_formal));
02432 FmtAssert (MTYPE_is_pointer(TY_mtype(tidx)),
02433 ("WFE_Expand_Return: fake param is not a pointer"));
02434 WN *dest_addr = WN_CreateLdid(OPR_LDID, TY_mtype(Ty_Table[tidx]),
02435 TY_mtype(Ty_Table[tidx]),
02436 WN_idname_offset(first_formal),
02437 WN_st(first_formal), tidx);
02438
02439 tree return_type = TREE_TYPE(TREE_TYPE(Current_Function_Decl()));
02440 Is_True(!WFE_has_copy_constructor(return_type),
02441 ("WFE_Expand_Return: return type has copy constructor"));
02442
02443 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, MTYPE_M, 0, tidx, rhs_wn,
02444 dest_addr, 0);
02445 WFE_Stmt_Append(wn, Get_Srcpos());
02446
02447 wn = WN_CreateReturn ();
02448 }
02449 #endif
02450 else {
02451 WFE_Set_ST_Addr_Saved (rhs_wn);
02452 wn = WN_CreateReturn_Val(OPR_RETURN_VAL, WN_rtype(rhs_wn), MTYPE_V, rhs_wn);
02453 }
02454 }
02455
02456 WFE_Stmt_Append(wn, Get_Srcpos());
02457 }
02458
02459
02460 void
02461 Mark_Scopes_And_Labels (tree stmt)
02462 {
02463 if (!stmt) return;
02464
02465 switch (TREE_CODE(stmt)) {
02466 case COMPOUND_STMT: {
02467 tree t;
02468 for (t = COMPOUND_BODY(stmt); t; t = TREE_CHAIN(t))
02469 Mark_Scopes_And_Labels (t);
02470 break;
02471 }
02472
02473 case DO_STMT:
02474 #ifdef KEY
02475 {
02476 tree body = WHILE_BODY(stmt);
02477 while (body) {
02478 Mark_Scopes_And_Labels (body);
02479 body = TREE_CHAIN(body);
02480 }
02481 break;
02482 }
02483 #else
02484 Mark_Scopes_And_Labels (DO_BODY(stmt));
02485 break;
02486 #endif
02487
02488 case FOR_STMT: {
02489 tree init = FOR_INIT_STMT(stmt);
02490 tree cond = FOR_COND(stmt);
02491 tree body = FOR_BODY(stmt);
02492 while (init) {
02493 Mark_Scopes_And_Labels (init);
02494 init = TREE_CHAIN(init);
02495 }
02496 #ifdef KEY
02497
02498 if (cond && (TREE_CODE(cond) == TREE_LIST))
02499 #else
02500 if (TREE_CODE(cond) == TREE_LIST)
02501 #endif // KEY
02502 Mark_Scopes_And_Labels(cond);
02503 while (body) {
02504 Mark_Scopes_And_Labels (body);
02505 body = TREE_CHAIN(body);
02506 }
02507 break;
02508 }
02509
02510 case IF_STMT:
02511 Mark_Scopes_And_Labels (IF_COND(stmt));
02512 Mark_Scopes_And_Labels (THEN_CLAUSE(stmt));
02513 Mark_Scopes_And_Labels (ELSE_CLAUSE(stmt));
02514 break;
02515
02516 case LABEL_STMT:
02517 if (scope_i == -1)
02518 LABEL_SCOPE(LABEL_STMT_LABEL(stmt)) = NULL_TREE;
02519 else
02520 LABEL_SCOPE(LABEL_STMT_LABEL(stmt)) = scope_stack [scope_i];
02521 break;
02522
02523 case SCOPE_STMT:
02524 if (SCOPE_BEGIN_P(stmt)) {
02525 #ifdef KEY
02526 if (scope_i != -1)
02527 PARENT_SCOPE(stmt) = scope_stack[scope_i];
02528 else
02529 PARENT_SCOPE(stmt) = 0;
02530 #endif
02531 Push_Scope(stmt);
02532 }
02533 else {
02534 SCOPE_NUMBER(scope_stack [scope_i]) = ++scope_number;
02535 --scope_i;
02536 }
02537 break;
02538
02539 case SWITCH_STMT:
02540 Mark_Scopes_And_Labels (SWITCH_COND(stmt));
02541 Mark_Scopes_And_Labels (SWITCH_BODY(stmt));
02542 break;
02543
02544 case TREE_LIST:
02545 for (tree t = TREE_PURPOSE(stmt); stmt; stmt = TREE_CHAIN(stmt))
02546 Mark_Scopes_And_Labels(t);
02547 break;
02548
02549 case TRY_BLOCK: {
02550 tree handler;
02551 Mark_Scopes_And_Labels (TRY_STMTS(stmt));
02552 for (handler = TRY_HANDLERS(stmt);
02553 handler;
02554 handler = TREE_CHAIN(handler))
02555 for (tree t = HANDLER_BODY(handler); t; t = TREE_CHAIN(t))
02556 Mark_Scopes_And_Labels (t);
02557 break;
02558 }
02559
02560 case WHILE_STMT:
02561 #ifdef KEY
02562 {
02563 Mark_Scopes_And_Labels (WHILE_COND(stmt));
02564 tree body = WHILE_BODY(stmt);
02565 while (body) {
02566 Mark_Scopes_And_Labels (body);
02567 body = TREE_CHAIN(body);
02568 }
02569 break;
02570 }
02571 #else
02572 Mark_Scopes_And_Labels (WHILE_COND(stmt));
02573 Mark_Scopes_And_Labels (WHILE_BODY(stmt));
02574 break;
02575 #endif
02576
02577 default:
02578 break;
02579 }
02580 }
02581
02582 static void
02583 WFE_Expand_Start_Case (tree selector)
02584 {
02585 #ifdef KEY
02586 TYPE_ID index_mtype;
02587 if (TREE_CODE (selector) == TREE_LIST)
02588 index_mtype = Mtype_comparison (
02589 TY_mtype (Get_TY (TREE_TYPE (TREE_VALUE(selector)))));
02590 else
02591 index_mtype = Mtype_comparison (
02592 TY_mtype (Get_TY (TREE_TYPE (selector))));
02593 #else
02594 TYPE_ID index_mtype = Mtype_comparison (
02595 TY_mtype (Get_TY (TREE_TYPE (TREE_VALUE(selector)))));
02596 #endif // KEY
02597
02598 WN *switch_block = WN_CreateBlock ();
02599 WN *index;
02600 index = WFE_Expand_Expr_With_Sequence_Point (selector, index_mtype);
02601 WFE_Stmt_Push (switch_block, wfe_stmk_switch, Get_Srcpos());
02602 if (++switch_info_i == switch_info_max) {
02603 switch_info_max = ENLARGE(switch_info_max);
02604 switch_info_stack = (SWITCH_INFO *) realloc (switch_info_stack,
02605 switch_info_max * sizeof (SWITCH_INFO));
02606 }
02607 switch_info_stack [switch_info_i].index = index;
02608 switch_info_stack [switch_info_i].start_case_index = case_info_i + 1;
02609 switch_info_stack [switch_info_i].default_label_idx = 0;
02610 WFE_Record_Loop_Switch (SWITCH_STMT);
02611 }
02612
02613 static void
02614 WFE_Expand_End_Case (void)
02615 {
02616 INT32 i;
02617 INT32 n;
02618 WN *switch_wn;
02619 WN *switch_block;
02620 WN *case_block;
02621 WN *case_entry;
02622 WN *def_goto;
02623 WN *wn;
02624 LABEL_IDX exit_label_idx;
02625
02626 n = case_info_i - switch_info_stack [switch_info_i].start_case_index + 1;
02627 if (break_continue_info_stack [break_continue_info_i].break_label_idx)
02628 exit_label_idx = break_continue_info_stack [break_continue_info_i].break_label_idx;
02629 else
02630 New_LABEL (CURRENT_SYMTAB, exit_label_idx);
02631 if (switch_info_stack [switch_info_i].default_label_idx)
02632 def_goto = WN_CreateGoto (switch_info_stack [switch_info_i].default_label_idx);
02633 else
02634 def_goto = WN_CreateGoto (exit_label_idx);
02635 case_block = WN_CreateBlock ();
02636 for (i = switch_info_stack [switch_info_i].start_case_index;
02637 i <= case_info_i;
02638 i++) {
02639 INT64 case_value;
02640 LABEL_IDX case_label_idx = case_info_stack [i].case_label_idx;
02641 for (case_value = case_info_stack [i].case_lower_bound_value;
02642 case_value <= case_info_stack [i].case_upper_bound_value;
02643 case_value++) {
02644 case_entry = WN_CreateCasegoto (case_value, case_label_idx);
02645 WN_INSERT_BlockLast (case_block, case_entry);
02646 #ifdef KEY // bug 2814. TODO: Port the switch-related code from kgccfe.
02647 if (case_value == case_info_stack[i].case_upper_bound_value)
02648 break;
02649 #endif
02650 }
02651 }
02652 switch_wn = WN_CreateSwitch (n,
02653 switch_info_stack [switch_info_i].index,
02654 case_block,
02655 def_goto,
02656 exit_label_idx);
02657 switch_block = WFE_Stmt_Pop (wfe_stmk_switch);
02658 WFE_Stmt_Append (switch_wn, Get_Srcpos ());
02659 WFE_Stmt_Append (switch_block, Get_Srcpos ());
02660 wn = WN_CreateLabel ((ST_IDX) 0, exit_label_idx, 0, NULL);
02661 WFE_Stmt_Append (wn, Get_Srcpos ());
02662 case_info_i = switch_info_stack [switch_info_i].start_case_index - 1;
02663 --switch_info_i;
02664 }
02665
02666 static void
02667 WFE_Expand_Switch (tree stmt)
02668 {
02669 WFE_Expand_Start_Case (SWITCH_COND(stmt));
02670 WFE_Expand_Stmt (SWITCH_BODY(stmt));
02671 WFE_Expand_End_Case ();
02672 --break_continue_info_i;
02673 }
02674
02675 static void
02676 Set_Handler_Labels (tree stmt)
02677 {
02678 for (tree handler = TRY_HANDLERS(stmt);
02679 handler;
02680 handler = TREE_CHAIN (handler)) {
02681 LABEL_IDX handler_label;
02682 New_LABEL (CURRENT_SYMTAB, handler_label);
02683 HANDLER_LABEL(handler) = handler_label;
02684 }
02685 }
02686
02687 INT
02688 Current_Handler_Count()
02689 {
02690 #ifndef ADD_HANDLER_INFO
02691 return 0;
02692 #endif
02693 if (temp_cleanup_i != -1) {
02694 for (int i = temp_cleanup_i; i != -1; --i) {
02695 if (temp_cleanup_stack [i].label_idx != 0)
02696 return 1;
02697 }
02698 }
02699
02700 for (int i = scope_cleanup_i; i != -1; --i) {
02701 tree t = scope_cleanup_stack [i].stmt;
02702 if (TREE_CODE(t) == CLEANUP_STMT)
02703 return 1;
02704 INT result = 0;
02705 if (TREE_CODE(t) == TRY_BLOCK) {
02706 for (tree handler = TRY_HANDLERS(t);
02707 handler;
02708 handler = TREE_CHAIN(handler))
02709 ++result;
02710 return result;
02711 }
02712 }
02713
02714 return 0;
02715 }
02716
02717 static ST_IDX
02718 Tid_For_Handler (tree handler)
02719 {
02720 tree t = HANDLER_BODY (handler);
02721 while (TREE_CODE(t) != COMPOUND_STMT)
02722 t = TREE_CHAIN(t);
02723 t = COMPOUND_BODY(t);
02724 #if 0
02725 while (TREE_CODE(t) != START_CATCH_STMT)
02726 t = TREE_CHAIN(t);
02727 #endif
02728 t = TREE_TYPE(t);
02729 return t ? ST_st_idx(Get_ST (TREE_OPERAND(t, 0))) : 0;
02730 }
02731
02732 #ifdef ADD_HANDLER_INFO
02733 void
02734 Add_Handler_Info (WN * call_wn, INT i, INT num_handlers)
02735 {
02736 if (temp_cleanup_i != -1) {
02737 for (int i = temp_cleanup_i; i != -1; --i)
02738 if (temp_cleanup_stack [i].label_idx != 0) {
02739 WN_kid (call_wn, i++) =
02740 WN_CreateHandlerInfo (0,
02741 temp_cleanup_stack[temp_cleanup_i].label_idx);
02742 return;
02743
02744 }
02745 }
02746
02747 int j = scope_cleanup_i;
02748 while (TREE_CODE(scope_cleanup_stack [j].stmt) == SCOPE_STMT)
02749 --j;
02750 tree t = scope_cleanup_stack [j].stmt;
02751 if (TREE_CODE(t) == TRY_BLOCK && TREE_CODE(TRY_HANDLERS(t)) == HANDLER) {
02752 for (tree handler = TRY_HANDLERS(t);
02753 handler;
02754 handler = TREE_CHAIN(handler))
02755 WN_kid (call_wn, i++) =
02756 WN_CreateHandlerInfo (Tid_For_Handler (handler),
02757 HANDLER_LABEL (handler));
02758 return;
02759 }
02760
02761 WN_kid (call_wn, i++) =
02762 WN_CreateHandlerInfo (0, scope_cleanup_stack [j].label_idx);
02763 }
02764 #endif
02765
02766 #ifdef KEY
02767
02768 static tree
02769 Get_typeinfo_var (tree t)
02770 {
02771 tree ti_var = 0;
02772 if (CLASS_TYPE_P(t))
02773 ti_var = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (t));
02774 else
02775 ti_var = IDENTIFIER_GLOBAL_VALUE (mangle_typeinfo_for_type(t));
02776 FmtAssert (ti_var, ("Typeinfo of handler unavailable"));
02777 if (DECL_ASSEMBLER_NAME_SET_P (ti_var) &&
02778 TREE_NOT_EMITTED_BY_GXX (ti_var) &&
02779 !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (ti_var)))
02780 {
02781
02782 TREE_NOT_EMITTED_BY_GXX (ti_var) = 0;
02783 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (ti_var)) = 1;
02784 gxx_emits_typeinfos (ti_var);
02785 }
02786 return ti_var;
02787 }
02788
02789
02790
02791 static INITV_IDX
02792 Create_handler_list (int scope_index)
02793 {
02794 INITV_IDX type_st, prev_type_st=0, start=0;
02795
02796 FmtAssert (TREE_CODE(scope_cleanup_stack[scope_index].stmt) == TRY_BLOCK,
02797 ("EH Error"));
02798 for (int i=scope_index; i>=0; i--)
02799 {
02800 tree t = scope_cleanup_stack[i].stmt;
02801 if ((TREE_CODE(t) != TRY_BLOCK) || CLEANUP_P(t)) continue;
02802
02803 tree h = TRY_HANDLERS (t);
02804 if (key_exceptions)
02805 {
02806 FmtAssert (h, ("Create_handler_list: Null handlers"));
02807 FmtAssert (TREE_CODE(h) == HANDLER, ("Create_handler_list: TREE_CODE HANDLER expected"));
02808 }
02809 while (h)
02810 {
02811 type_st = New_INITV();
02812 tree type = HANDLER_TYPE(h);
02813
02814 ST_IDX st = 0;
02815 if (type) st = ST_st_idx (Get_ST (Get_typeinfo_var(type)));
02816 INITV_Set_VAL (Initv_Table[type_st], Enter_tcon (Host_To_Targ (MTYPE_U4, st)), 1);
02817
02818 h = TREE_CHAIN(h);
02819 if (prev_type_st) Set_INITV_next (prev_type_st, type_st);
02820 else start = type_st;
02821 prev_type_st = type_st;
02822 }
02823 }
02824 if (processing_handler)
02825 {
02826 INITV_IDX next = lookup_handlers();
02827 if (prev_type_st) Set_INITV_next (prev_type_st, next);
02828 else start = next;
02829 }
02830 return start;
02831 }
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851 static INITV_IDX
02852 lookup_handlers (vector<tree> *cleanups)
02853 {
02854 HANDLER_INFO hi = handler_stack.top();
02855 vector<ST_IDX> * h = hi.handler_list;
02856 INITV_IDX type_st, prev_type_st=0, start=0;
02857 for (vector<ST_IDX>::iterator i = h->begin(); i != h->end(); ++i)
02858 {
02859 type_st = New_INITV();
02860 ST_IDX st = *i;
02861 INITV_Set_VAL (Initv_Table[type_st], Enter_tcon (Host_To_Targ (MTYPE_U4, st)), 1);
02862
02863 if (prev_type_st) Set_INITV_next (prev_type_st, type_st);
02864 else start = type_st;
02865 prev_type_st = type_st;
02866 }
02867 if (!start)
02868 {
02869 start = New_INITV();
02870 INITV_Set_ZERO (Initv_Table[start], MTYPE_U4, 1);
02871 }
02872 if (cleanups)
02873 {
02874 vector<tree> * temp = hi.cleanups;
02875 for (vector<tree>::iterator j = temp->begin(); j != temp->end(); ++j)
02876 cleanups->push_back (*j);
02877 }
02878 return start;
02879 }
02880
02881 LABEL_IDX
02882 New_eh_cleanup_entry (tree t, vector<tree> *v, LABEL_IDX goto_idx)
02883 {
02884 EH_CLEANUP_ENTRY e;
02885
02886 e.tryhandler = t;
02887 e.cleanups = v;
02888 e.goto_idx = goto_idx;
02889 LABEL_IDX pad;
02890 New_LABEL (CURRENT_SYMTAB, pad);
02891 Label_Table[pad].kind = LKIND_BEGIN_HANDLER;
02892 e.pad = pad;
02893 New_LABEL (CURRENT_SYMTAB, e.start);
02894 cleanup_list_for_eh.push_back (e);
02895 return pad;
02896 }
02897
02898
02899
02900
02901 static void
02902 append_eh_filter (INITV_IDX& iv)
02903 {
02904 INITV_IDX tmp = iv;
02905 while (tmp && INITV_next (tmp))
02906 tmp = INITV_next (tmp);
02907
02908 INITV_IDX eh_filter = New_INITV();
02909 INITV_Set_VAL (Initv_Table[eh_filter], Enter_tcon (Host_To_Targ (MTYPE_I4, -current_eh_spec_ofst)), 1);
02910 if (tmp) Set_INITV_next (tmp, eh_filter);
02911 else iv = eh_filter;
02912 }
02913
02914 static void
02915 append_catch_all (INITV_IDX& iv)
02916 {
02917 INITV_IDX tmp = iv;
02918 while (tmp && INITV_next (tmp))
02919 tmp = INITV_next (tmp);
02920
02921 INITV_IDX catch_all = New_INITV();
02922 INITV_Set_VAL (Initv_Table[catch_all], Enter_tcon (Host_To_Targ (MTYPE_U4, 0)), 1);
02923 if (tmp) Set_INITV_next (tmp, catch_all);
02924 else iv = catch_all;
02925 }
02926
02927
02928
02929 static bool
02930 optimize_cleanups (vector<tree> * current, vector<tree> * prev)
02931 {
02932 if (prev->size() >= current->size())
02933 return false;
02934 reverse (current->begin(), current->end());
02935 reverse (prev->begin(), prev->end());
02936 vector<tree>::iterator c = current->begin();
02937 for (vector<tree>::iterator p = prev->begin(); p != prev->end(); ++p, ++c)
02938 if (*p != *c)
02939 return false;
02940
02941
02942 reverse (current->begin(), current->end());
02943 reverse (prev->begin(), prev->end());
02944 for (int i=0; i<prev->size(); ++i)
02945 current->pop_back();
02946 return true;
02947 }
02948
02949 static bool manual_unwinding_needed (void);
02950
02951 LABEL_IDX
02952 lookup_cleanups (INITV_IDX& iv)
02953 {
02954 tree t=0;
02955 iv = 0;
02956 vector<tree> *cleanups = new vector<tree>();
02957
02958 if (scope_cleanup_i == -1)
02959 {
02960 iv = New_INITV();
02961 INITV_Set_ZERO (Initv_Table[iv], MTYPE_U4, 1);
02962 return 0;
02963 }
02964 tree temp_cleanup=0;
02965 for (int i=temp_cleanup_i; i>=0; --i)
02966 {
02967 TEMP_CLEANUP_INFO t = temp_cleanup_stack[i];
02968 if (t.label_idx && t.cleanup_eh_only)
02969 {
02970
02971 temp_cleanup = temp_cleanup_stack[i].expr;
02972 break;
02973 }
02974 }
02975 int scope_index;
02976 LABEL_IDX goto_idx=0;
02977 for (scope_index=scope_cleanup_i; scope_index>=0; scope_index--)
02978 {
02979 t = scope_cleanup_stack[scope_index].stmt;
02980 if (TREE_CODE(t) == CLEANUP_STMT)
02981 cleanups->push_back (t);
02982 if (TREE_CODE(t) == TRY_BLOCK)
02983 if (CLEANUP_P(t)) cleanups->push_back (TRY_HANDLERS(t));
02984 else break;
02985 if (temp_cleanup && (cleanups->size() == 1))
02986 {
02987 cleanups->push_back (temp_cleanup);
02988 temp_cleanup = 0;
02989 }
02990 }
02991 if (temp_cleanup)
02992 cleanups->push_back (temp_cleanup);
02993 tree h = 0;
02994 if (TREE_CODE(t) == TRY_BLOCK)
02995 {
02996 h = TRY_HANDLERS (t);
02997 iv = Create_handler_list (scope_index);
02998 goto_idx = scope_cleanup_stack[scope_index].cmp_idx;
02999 }
03000 else
03001 {
03002 if (processing_handler)
03003 {
03004 iv = lookup_handlers (cleanups);
03005 goto_idx = handler_stack.top().goto_idx;
03006 }
03007 else if (cleanups->empty() && eh_spec_vector.empty())
03008 {
03009 iv = New_INITV();
03010 INITV_Set_ZERO (Initv_Table[iv], MTYPE_U4, 1);
03011 return 0;
03012 }
03013 }
03014 if (!try_block_seen && manual_unwinding_needed())
03015 Set_PU_needs_manual_unwinding (Get_Current_PU());
03016
03017
03018 bool catch_all_appended = false;
03019 if (PU_needs_manual_unwinding (Get_Current_PU()))
03020 {
03021 append_catch_all (iv);
03022 catch_all_appended = true;
03023 }
03024 if (processing_handler)
03025 {
03026 vector<ST_IDX> * eh_spec = handler_stack.top().eh_spec;
03027 FmtAssert (eh_spec, ("Invalid eh_spec inside handler"));
03028 if (!eh_spec->empty())
03029 {
03030 if (!catch_all_appended)
03031 append_catch_all (iv);
03032 append_eh_filter (iv);
03033 }
03034 }
03035 else if (!eh_spec_vector.empty())
03036 {
03037 if (!catch_all_appended)
03038 append_catch_all (iv);
03039 append_eh_filter (iv);
03040 }
03041 if (!iv)
03042 {
03043 iv = New_INITV();
03044 INITV_Set_ZERO (Initv_Table[iv], MTYPE_U4, 1);
03045 }
03046 if (cleanup_list_for_eh.empty())
03047 {
03048 return New_eh_cleanup_entry (h, cleanups, goto_idx);
03049 }
03050 else
03051 {
03052 EH_CLEANUP_ENTRY e = cleanup_list_for_eh.back();
03053
03054
03055 if (h == 0 && e.tryhandler == 0 && !processing_handler &&
03056 cleanups->size() != e.cleanups->size())
03057 {
03058 if (optimize_cleanups (cleanups, e.cleanups))
03059 return New_eh_cleanup_entry (h, cleanups, e.start);
03060 }
03061
03062 if ((h != e.tryhandler) ||
03063 (cleanups->size() != e.cleanups->size()))
03064 return New_eh_cleanup_entry (h, cleanups, goto_idx);
03065
03066 for (int j=0; j<cleanups->size(); ++j)
03067 if ((*cleanups)[j] != (*(e.cleanups))[j])
03068 return New_eh_cleanup_entry (h, cleanups, goto_idx);
03069 return e.pad;
03070 }
03071 }
03072
03073
03074
03075 static void
03076 Get_handler_list (vector<ST_IDX> *handler_list)
03077 {
03078 FmtAssert (TREE_CODE(scope_cleanup_stack[scope_cleanup_i+1].stmt) ==
03079 TRY_BLOCK, ("EH Error"));
03080 for (int i=scope_cleanup_i; i>=0; i--)
03081 {
03082 tree t = scope_cleanup_stack[i].stmt;
03083 if ((TREE_CODE(t) != TRY_BLOCK) || CLEANUP_P(t)) continue;
03084
03085 tree h = TRY_HANDLERS (t);
03086 if (key_exceptions)
03087 {
03088 FmtAssert (h, ("Get_handler_list: Null handlers"));
03089 FmtAssert (TREE_CODE(h) == HANDLER, ("Get_handler_list: TREE_CODE HANDLER expected"));
03090 }
03091 while (h)
03092 {
03093 tree type = HANDLER_TYPE(h);
03094 ST_IDX st = 0;
03095 if (type)
03096 st = ST_st_idx (Get_ST (Get_typeinfo_var(type)));
03097 handler_list->push_back (st);
03098 h = TREE_CHAIN (h);
03099 }
03100 }
03101 if (processing_handler)
03102 {
03103 HANDLER_INFO hi = handler_stack.top();
03104 for (vector<ST_IDX>::iterator i = hi.handler_list->begin();
03105 i != hi.handler_list->end(); ++i)
03106 handler_list->push_back (*i);
03107 }
03108 }
03109
03110 static bool
03111 Get_Cleanup_Info (vector<tree> *cleanups, LABEL_IDX *goto_idx)
03112 {
03113 FmtAssert (TREE_CODE(scope_cleanup_stack[scope_cleanup_i+1].stmt)==TRY_BLOCK,
03114 ("EH Processing Error"));
03115
03116 for (int i=scope_cleanup_i; i>=0; i--)
03117 {
03118 tree t = scope_cleanup_stack[i].stmt;
03119 if (TREE_CODE(t) == CLEANUP_STMT)
03120 cleanups->push_back (t);
03121 if (TREE_CODE(t) == TRY_BLOCK)
03122 {
03123 *goto_idx = scope_cleanup_stack[i].cmp_idx;
03124 return false;
03125 }
03126 }
03127 if (!processing_handler)
03128 {
03129 *goto_idx = 0;
03130 return true;
03131 }
03132 HANDLER_INFO hi = handler_stack.top();
03133 if (hi.handler_list->empty())
03134 {
03135 *goto_idx = 0;
03136 return true;
03137 }
03138 else
03139 {
03140 *goto_idx = hi.cleanups_idx;
03141 return false;
03142 }
03143 }
03144
03145
03146 static vector<SCOPE_CLEANUP_INFO> *
03147 Get_Scope_Info (void)
03148 {
03149 vector<SCOPE_CLEANUP_INFO> *scope = new vector<SCOPE_CLEANUP_INFO>();
03150 if (processing_handler)
03151 {
03152 HANDLER_INFO hi = handler_stack.top();
03153 if (hi.scope)
03154 for (vector<SCOPE_CLEANUP_INFO>::iterator i = hi.scope->begin();
03155 i != hi.scope->end(); ++i)
03156 scope->push_back (*i);
03157 }
03158 FmtAssert (TREE_CODE(scope_cleanup_stack[scope_cleanup_i].stmt)
03159 == TRY_BLOCK, ("Scope Error in Get_Scope_Info"));
03160 for (int i=0; i<scope_cleanup_i; ++i)
03161 scope->push_back(scope_cleanup_stack[i]);
03162 return scope;
03163 }
03164
03165 static vector<TEMP_CLEANUP_INFO> *
03166 Get_Temp_Cleanup_Info (void)
03167 {
03168 vector<TEMP_CLEANUP_INFO> *temp = new vector<TEMP_CLEANUP_INFO>();
03169 if (processing_handler)
03170 {
03171 HANDLER_INFO hi = handler_stack.top();
03172 if (hi.temp_cleanup)
03173 for (vector<TEMP_CLEANUP_INFO>::iterator i = hi.temp_cleanup->begin();
03174 i != hi.temp_cleanup->end(); ++i)
03175 temp->push_back (*i);
03176 }
03177 FmtAssert (TREE_CODE(temp_cleanup_stack[temp_cleanup_i].expr)
03178 == TRY_BLOCK, ("Scope Error"));
03179 for (int i=0; i<temp_cleanup_i; ++i)
03180 temp->push_back(temp_cleanup_stack[i]);
03181 return temp;
03182 }
03183
03184 void check_for_loop_label (void)
03185 {
03186 int i = break_continue_info_i;
03187
03188 if (i != -1) {
03189 if (!break_continue_info_stack[i].break_label_idx)
03190 New_LABEL (CURRENT_SYMTAB, break_continue_info_stack[i].break_label_idx);
03191
03192 while (break_continue_info_stack [i].tree_code == SWITCH_STMT) --i;
03193 if (i != -1) {
03194 LABEL_IDX label_idx = break_continue_info_stack [i].continue_label_idx;
03195 if (label_idx == 0) {
03196 New_LABEL (CURRENT_SYMTAB, label_idx);
03197 break_continue_info_stack [i].continue_label_idx = label_idx;
03198 }
03199 }
03200 }
03201 }
03202
03203 static vector<BREAK_CONTINUE_INFO> *
03204 Get_Break_Continue_Info (void)
03205 {
03206 vector<BREAK_CONTINUE_INFO> *info = new vector<BREAK_CONTINUE_INFO>();
03207
03208 check_for_loop_label ();
03209 if (processing_handler)
03210 {
03211 HANDLER_INFO hi = handler_stack.top();
03212 if (hi.break_continue)
03213 for (vector<BREAK_CONTINUE_INFO>::iterator i = hi.break_continue->begin();
03214 i != hi.break_continue->end(); ++i)
03215 info->push_back (*i);
03216 }
03217 FmtAssert (TREE_CODE(scope_cleanup_stack[scope_cleanup_i].stmt)
03218 == TRY_BLOCK, ("Scope Error in Get_Break_Continue_Info"));
03219 for (int i=0; i<=break_continue_info_i; ++i)
03220 info->push_back(break_continue_info_stack[i]);
03221 return info;
03222 }
03223
03224 static bool
03225 manual_unwinding_needed (void)
03226 {
03227 FmtAssert (!processing_handler, ("Cannot be called from inside handler"));
03228
03229 if (!eh_spec_vector.empty()) return true;
03230 bool cleanups_seen = false;
03231 for (int i=scope_cleanup_i; i>=0; i--)
03232 {
03233 tree t = scope_cleanup_stack[i].stmt;
03234 if (TREE_CODE(t) == CLEANUP_STMT)
03235 {
03236 cleanups_seen = true;
03237 break;
03238 }
03239 if (TREE_CODE(t) == TRY_BLOCK)
03240 Fail_FmtAssertion ("manual_unwinding_needed: Cannot reach here");
03241 }
03242 return cleanups_seen;
03243 }
03244
03245 static void
03246 Get_eh_spec (vector<ST_IDX> *in)
03247 {
03248 vector<ST_IDX> * eh_spec;
03249 if (processing_handler)
03250 eh_spec = handler_stack.top().eh_spec;
03251 else
03252 eh_spec = &eh_spec_vector;
03253 FmtAssert (eh_spec, ("Invalid eh_spec"));
03254 for (int i=0; i<eh_spec->size(); ++i)
03255 in->push_back ((*eh_spec)[i]);
03256 }
03257 #endif // KEY
03258
03259 static void
03260 WFE_Expand_Try (tree stmt)
03261 {
03262 LABEL_IDX end_label_idx;
03263 WN * end_label_wn;
03264
03265
03266
03267
03268
03269
03270 if (TRY_STMTS(stmt) == NULL_TREE)
03271 return;
03272
03273 #ifdef KEY
03274 if (!try_block_seen)
03275 {
03276 if (manual_unwinding_needed())
03277 Set_PU_needs_manual_unwinding (Get_Current_PU());
03278 try_block_seen = true;
03279 }
03280 #endif
03281
03282
03283 Set_Handler_Labels(stmt);
03284
03285
03286 if (!opt_regions)
03287 Push_Scope_Cleanup (stmt);
03288
03289 #ifdef KEY
03290
03291 #if 0
03292 vector<TEMP_CLEANUP_INFO> *temp_cleanup = Get_Temp_Cleanup_Info ();
03293 #else
03294 vector<TEMP_CLEANUP_INFO> *temp_cleanup = 0;
03295 #endif
03296 int handler_count=0;
03297 WN * region_body;
03298 if (key_exceptions)
03299 {
03300 region_body = WN_CreateBlock();
03301 WFE_Stmt_Push (region_body, wfe_stmk_region_body, Get_Srcpos());
03302
03303
03304 if (opt_regions)
03305 Push_Scope_Cleanup (stmt);
03306 handler_count = cleanup_list_for_eh.size();
03307 }
03308 vector<SCOPE_CLEANUP_INFO> *scope_cleanup = Get_Scope_Info ();
03309 vector<BREAK_CONTINUE_INFO> *break_continue = Get_Break_Continue_Info ();
03310 #endif // KEY
03311
03312
03313
03314 for (tree s = TRY_STMTS(stmt); s; s = TREE_CHAIN(s))
03315 WFE_Expand_Stmt(s);
03316
03317 if (!opt_regions)
03318 --scope_cleanup_i;
03319
03320 #ifdef KEY
03321 LABEL_IDX start = 0;
03322 if (key_exceptions)
03323 {
03324 WFE_Stmt_Pop (wfe_stmk_region_body);
03325
03326 if (opt_regions)
03327 --scope_cleanup_i;
03328 WN * region_pragmas = WN_CreateBlock();
03329 FmtAssert (cleanup_list_for_eh.size() >= handler_count, ("Cleanups cannot be removed here"));
03330 LABEL_IDX cmp_idx = scope_cleanup_stack[scope_cleanup_i+1].cmp_idx;
03331 if (cleanup_list_for_eh.size() > handler_count)
03332 {
03333 std::list<EH_CLEANUP_ENTRY>::iterator iter = cleanup_list_for_eh.begin();
03334 for (int incr=0; incr<handler_count; ++incr)
03335 ++iter;
03336 for (; iter != cleanup_list_for_eh.end(); ++iter)
03337 {
03338 EH_CLEANUP_ENTRY entry = *iter;
03339 WN_INSERT_BlockLast (region_pragmas, WN_CreateGoto (entry.pad));
03340 }
03341 }
03342 else
03343 {
03344
03345
03346
03347
03348
03349 New_LABEL (CURRENT_SYMTAB, start);
03350 Set_LABEL_KIND (Label_Table[start], LKIND_BEGIN_HANDLER);
03351 WN_INSERT_BlockLast (region_pragmas, WN_CreateGoto (start));
03352 }
03353
03354
03355
03356 TY_IDX ty = MTYPE_TO_TY_array[MTYPE_U4];
03357 ST * ereg = Gen_Temp_Named_Symbol (ty, "try_label", CLASS_VAR,
03358 SCLASS_EH_REGION_SUPP);
03359 Set_ST_is_initialized (*ereg);
03360 Set_ST_is_not_used (*ereg);
03361 INITV_IDX try_label = New_INITV();
03362 INITV_Init_Label (try_label, cmp_idx, 1);
03363 INITO_IDX ereg_supp = New_INITO (ST_st_idx(ereg), try_label);
03364 WFE_Stmt_Append (WN_CreateRegion (REGION_KIND_TRY, region_body,
03365 region_pragmas, WN_CreateBlock(), New_Region_Id(), ereg_supp),
03366 Get_Srcpos());
03367 Set_PU_has_region (Get_Current_PU());
03368
03369
03370
03371
03372
03373 UINT inito_size;
03374 TY_IDX tyi;
03375 TY& zty = New_TY(tyi);
03376 inito_size = Get_INITO_Size (ereg_supp);
03377 TY_Init (zty, inito_size, KIND_STRUCT, MTYPE_M,
03378 ereg -> u1.name_idx);
03379 Set_TY_align (tyi, 4);
03380 ST_Init (ereg, TY_name_idx(zty),CLASS_VAR, SCLASS_EH_REGION_SUPP, EXPORT_LOCAL, tyi);
03381 Set_ST_is_initialized (ereg);
03382 Set_ST_is_not_used (ereg);
03383 }
03384 vector<tree> *cleanups = new vector<tree>();
03385 LABEL_IDX cmp_idxs[2];
03386 cmp_idxs[0] = scope_cleanup_stack[scope_cleanup_i+1].cmp_idx;
03387 cmp_idxs[1] = start;
03388 LABEL_IDX goto_idx=0;
03389 bool outermost = 0;
03390 if (key_exceptions) outermost = Get_Cleanup_Info (cleanups, &goto_idx);
03391 vector<ST_IDX> *handler_list = new vector<ST_IDX>();
03392 vector<ST_IDX> * eh_spec_list = NULL;
03393 if (key_exceptions)
03394 {
03395 Get_handler_list (handler_list);
03396 eh_spec_list = new vector<ST_IDX>();
03397 Get_eh_spec (eh_spec_list);
03398 }
03399 #endif // KEY
03400
03401
03402
03403 New_LABEL (CURRENT_SYMTAB, end_label_idx);
03404
03405
03406
03407 #ifdef KEY
03408 Push_Handler_Info (TRY_HANDLERS(stmt), cleanups, scope_cleanup, temp_cleanup,
03409 break_continue, handler_list, eh_spec_list, end_label_idx, outermost,
03410 cmp_idxs, goto_idx);
03411 #else
03412 Push_Handler_Info (TRY_HANDLERS(stmt), end_label_idx);
03413 #endif // KEY
03414
03415
03416
03417 end_label_wn = WN_CreateLabel ((ST_IDX) 0, end_label_idx, 0, NULL);
03418 WFE_Stmt_Append (end_label_wn, Get_Srcpos());
03419 }
03420
03421 #ifdef KEY
03422 static int
03423 sizeof_eh_spec (tree t)
03424 {
03425 int i=1;
03426 for (; t; t = TREE_CHAIN(t), i++) ;
03427 return i;
03428 }
03429 #endif
03430
03431 static void
03432 WFE_Expand_EH_Spec (tree stmt)
03433 {
03434
03435
03436
03437
03438
03439 #ifdef KEY
03440 int bkup = current_eh_spec_ofst;
03441 int initial_size = eh_spec_vector.size();
03442 if (key_exceptions)
03443 {
03444
03445
03446
03447
03448
03449 tree eh_spec = EH_SPEC_RAISES (stmt);
03450 current_eh_spec_ofst = initial_size+1;
03451 if (eh_spec_vector.empty())
03452 eh_spec_vector.reserve (sizeof_eh_spec (eh_spec));
03453 for (; eh_spec; eh_spec = TREE_CHAIN (eh_spec))
03454 {
03455 ST_IDX type_st = ST_st_idx (Get_ST (
03456 Get_typeinfo_var(TREE_VALUE(eh_spec))));
03457 eh_spec_vector.push_back (type_st);
03458 eh_spec_func_end.push_back (type_st);
03459
03460 TYPE_FILTER_ENTRY e;
03461 e.st = type_st;
03462 e.filter = 0;
03463 vector<TYPE_FILTER_ENTRY>::iterator f = find(type_filter_vector.begin(), type_filter_vector.end(), e);
03464 if (f == type_filter_vector.end())
03465 {
03466 e.filter = type_filter_vector.size()+1;
03467 type_filter_vector.push_back (e);
03468 }
03469 }
03470 eh_spec_vector.push_back (0);
03471 eh_spec_func_end.push_back (0);
03472 }
03473 #endif
03474 #ifdef KEY
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484 tree eh_spec_stmt;
03485 for (eh_spec_stmt = EH_SPEC_STMTS (stmt); eh_spec_stmt != NULL; eh_spec_stmt = TREE_CHAIN(eh_spec_stmt))
03486 WFE_Expand_Stmt (eh_spec_stmt);
03487 #else
03488 WFE_Expand_Stmt (EH_SPEC_STMTS (stmt));
03489 #endif
03490 #ifdef KEY
03491 if (key_exceptions)
03492 {
03493 if (!initial_size) eh_spec_vector.clear();
03494 else
03495 {
03496 int current_size = eh_spec_vector.size();
03497 for (int i=initial_size; i<current_size; ++i)
03498 eh_spec_vector.pop_back();
03499 }
03500 }
03501 current_eh_spec_ofst = bkup;
03502 #endif
03503 }
03504
03505 static void
03506 Call_Named_Function (ST * st)
03507 {
03508 WN * call_wn = WN_Create (OPR_CALL, MTYPE_V, MTYPE_V, 0);
03509 WN_st_idx (call_wn) = ST_st_idx (st);
03510 WFE_Stmt_Append (call_wn, Get_Srcpos());
03511 }
03512
03513 void
03514 Call_Throw (void)
03515 {
03516 #if 0
03517 static ST * st = NULL;
03518 if (st == NULL) {
03519 st = Function_ST_For_String("__throw");
03520 }
03521 Call_Named_Function (st);
03522 #endif
03523 }
03524
03525 void
03526 Call_Rethrow (void)
03527 {
03528 #if 0
03529 static ST * st = NULL;
03530 if (st == NULL) {
03531 st = Function_ST_For_String ("__rethrow");
03532 }
03533 Call_Named_Function (st);
03534 #endif
03535 }
03536
03537 void Call_Terminate (void)
03538 {
03539 #ifdef KEY
03540 static ST * st = NULL;
03541 if (st == NULL) {
03542 st = Function_ST_For_String ("_ZSt9terminatev");
03543 }
03544 Call_Named_Function (st);
03545 #else
03546 #if 0
03547 static ST * st = NULL;
03548 if (st == NULL) {
03549 st = Function_ST_For_String ("terminate__Fv");
03550 }
03551 Call_Named_Function (st);
03552 #endif
03553 #endif // KEY
03554 }
03555
03556 #ifdef KEY
03557 static void Generate_filter_cmp (int filter, LABEL_IDX goto_idx);
03558 static WN *
03559 Generate_cxa_call_unexpected (void)
03560 {
03561 ST_IDX exc_ptr_param = TCON_uval (INITV_tc_val (INITO_val (PU_misc_info (Get_Current_PU()))));
03562 ST exc_st = St_Table[exc_ptr_param];
03563 WN* parm_node = WN_Ldid (Pointer_Mtype, 0, &exc_st, ST_type (exc_st));
03564
03565 TY_IDX idx;
03566 TY &ptr_ty = New_TY (idx);
03567 TY_Init (ptr_ty, Pointer_Size, KIND_POINTER, Pointer_Mtype,
03568 Save_Str ("anon_ptr."));
03569
03570 ptr_ty.Set_pointed (ST_type(exc_st));
03571
03572 WN * arg0 = WN_CreateParm (Pointer_Mtype, parm_node, idx, WN_PARM_BY_VALUE);
03573
03574 ST * st = Function_ST_For_String("__cxa_call_unexpected");
03575 WN * call_wn = WN_Create (OPR_CALL, Pointer_Mtype, MTYPE_V, 1);
03576 WN_kid0 (call_wn) = arg0;
03577 WN_st_idx (call_wn) = ST_st_idx (st);
03578 return call_wn;
03579 }
03580
03581 static void
03582 Generate_unwind_resume (void)
03583 {
03584 ST_IDX exc_ptr_param = TCON_uval (INITV_tc_val (INITO_val (PU_misc_info (Get_Current_PU()))));
03585 ST exc_st = St_Table[exc_ptr_param];
03586 WN* parm_node = WN_Ldid (Pointer_Mtype, 0, &exc_st, ST_type (exc_st));
03587
03588 TY_IDX idx;
03589 TY &ptr_ty = New_TY (idx);
03590 TY_Init (ptr_ty, Pointer_Size, KIND_POINTER, Pointer_Mtype,
03591 Save_Str ("anon_ptr."));
03592
03593 ptr_ty.Set_pointed (ST_type(exc_st));
03594
03595 WN * arg0 = WN_CreateParm (Pointer_Mtype, parm_node, idx, WN_PARM_BY_VALUE);
03596
03597 ST * st = Function_ST_For_String("_Unwind_Resume");
03598 WN * call_wn = WN_Create (OPR_CALL, Pointer_Mtype, MTYPE_V, 1);
03599 WN_kid0 (call_wn) = arg0;
03600 WN_st_idx (call_wn) = ST_st_idx (st);
03601 WN_Set_Call_Never_Return (call_wn);
03602
03603
03604
03605 WN *call_unexpected;
03606 LABEL_IDX goto_unexpected;
03607 if (!eh_spec_func_end.empty())
03608 {
03609
03610
03611 New_LABEL (CURRENT_SYMTAB, goto_unexpected);
03612 Generate_filter_cmp (-1, goto_unexpected);
03613 call_unexpected = Generate_cxa_call_unexpected ();
03614 }
03615
03616 if (key_exceptions)
03617 WFE_Stmt_Push (WN_CreateBlock(), wfe_stmk_region_body, Get_Srcpos());
03618 WFE_Stmt_Append (call_wn, Get_Srcpos());
03619 if (key_exceptions)
03620 Setup_EH_Region (1 );
03621
03622
03623 if (!eh_spec_func_end.empty())
03624 {
03625 WFE_Stmt_Append (WN_CreateLabel ((ST_IDX) 0, goto_unexpected, 0, NULL),
03626 Get_Srcpos());
03627 if (key_exceptions)
03628 WFE_Stmt_Push (WN_CreateBlock(), wfe_stmk_region_body, Get_Srcpos());
03629 WFE_Stmt_Append (call_unexpected, Get_Srcpos());
03630 if (key_exceptions)
03631 Setup_EH_Region (1 );
03632 }
03633 }
03634
03635 static void
03636 Generate_filter_cmp (int filter, LABEL_IDX goto_idx)
03637 {
03638 ST_IDX filter_param = TCON_uval (INITV_tc_val (INITV_next (INITO_val (PU_misc_info (Get_Current_PU())))));
03639 const TYPE_ID mtype = TARGET_64BIT ? MTYPE_U8 : MTYPE_U4;
03640
03641 WN * wn_ldid = WN_Ldid (mtype, 0, &St_Table[filter_param],
03642 MTYPE_TO_TY_array[mtype]);
03643 WN * goto_wn = WN_CreateGoto (goto_idx);
03644 WN_next (goto_wn) = WN_prev (goto_wn) = NULL;
03645
03646 WN * if_then = WN_CreateBlock ();
03647 WN_first (if_then) = WN_last (if_then) = goto_wn;
03648
03649 WN * if_else = WN_CreateBlock ();
03650 WN * cmp_value = WN_Intconst (mtype, filter);
03651 WN * cond = WN_Create (OPR_EQ, WN_rtype (wn_ldid), mtype, 2);
03652 WN_kid0 (cond) = wn_ldid;
03653 WN_kid1 (cond) = cmp_value;
03654
03655 WN * if_blk = WN_CreateIf (cond, if_then, if_else);
03656
03657 WFE_Stmt_Append (if_blk, Get_Srcpos());
03658 }
03659 #endif // KEY
03660
03661
03662
03663
03664 static void
03665 WFE_Expand_Handlers_Or_Cleanup (const HANDLER_INFO &handler_info)
03666 {
03667 tree t = handler_info.handler;
03668 vector<tree> *cleanups = handler_info.cleanups;
03669 LABEL_IDX label_idx = handler_info.label_idx;
03670 LABEL_IDX goto_idx = handler_info.goto_idx;
03671 LABEL_IDX cleanups_idx = handler_info.cleanups_idx;
03672 bool outermost = handler_info.outermost;
03673 #ifndef KEY
03674 WFE_Stmt_Append (
03675 WN_CreateLabel ((ST_IDX) 0, HANDLER_LABEL(t), 0, NULL),
03676 Get_Srcpos());
03677 #endif // !KEY
03678
03679 if (TREE_CODE(t) == HANDLER) {
03680
03681 #ifdef KEY
03682 if (key_exceptions)
03683 {
03684 tree t_copy = t;
03685 while (t_copy)
03686 {
03687 tree type = HANDLER_TYPE(t_copy);
03688 ST_IDX sym = 0;
03689 if (type) sym = ST_st_idx (Get_ST (Get_typeinfo_var(type)));
03690 TYPE_FILTER_ENTRY e;
03691 e.st = sym;
03692 e.filter = 0;
03693 vector<TYPE_FILTER_ENTRY>::iterator f = find(type_filter_vector.begin(), type_filter_vector.end(), e);
03694 if (f == type_filter_vector.end())
03695 {
03696 e.filter = type_filter_vector.size()+1;
03697 type_filter_vector.push_back (e);
03698 if (e.st)
03699 Generate_filter_cmp (e.filter, HANDLER_LABEL(t_copy));
03700 else
03701 WFE_Stmt_Append (WN_CreateGoto ((ST_IDX) NULL,
03702 HANDLER_LABEL(t_copy)), Get_Srcpos());
03703 #if 0
03704
03705
03706 sort (type_filter_vector.begin(), type_filter_vector.end(),
03707 cmp_types());
03708 #endif
03709 }
03710 else
03711 {
03712 if (e.st)
03713 Generate_filter_cmp ((*f).filter, HANDLER_LABEL(t_copy));
03714 else
03715 WFE_Stmt_Append (WN_CreateGoto ((ST_IDX) NULL,
03716 HANDLER_LABEL(t_copy)), Get_Srcpos());
03717 }
03718 t_copy = TREE_CHAIN(t_copy);
03719 }
03720
03721 WFE_Stmt_Append (
03722 WN_CreateLabel ((ST_IDX) 0, cleanups_idx, 0, NULL), Get_Srcpos());
03723
03724
03725 in_cleanup = TRUE;
03726 for (vector<tree>::iterator j=cleanups->begin();
03727 j!=cleanups->end(); ++j)
03728 WFE_One_Stmt_Cleanup (CLEANUP_EXPR (*j));
03729
03730 in_cleanup = FALSE;
03731
03732 if (outermost)
03733 {
03734 FmtAssert (goto_idx == 0, ("Goto label should be 0"));
03735 Generate_unwind_resume ();
03736 }
03737 else
03738 WFE_Stmt_Append (WN_CreateGoto ((ST_IDX) NULL, goto_idx), Get_Srcpos());
03739 }
03740 #endif // KEY
03741 while (t) {
03742 #ifdef KEY
03743
03744
03745 WFE_Stmt_Append (
03746 WN_CreateLabel ((ST_IDX) 0, HANDLER_LABEL(t), 0, NULL), Get_Srcpos());
03747 #endif
03748 tree body = HANDLER_BODY(t);
03749 for (; body; body = TREE_CHAIN(body))
03750 WFE_Expand_Stmt (body);
03751 WFE_Stmt_Append (WN_CreateGoto ((ST_IDX) NULL, label_idx),
03752 Get_Srcpos());
03753 t = TREE_CHAIN(t);
03754 }
03755 } else {
03756
03757
03758
03759 #if 0
03760
03761
03762 WFE_One_Stmt (t);
03763 Call_Rethrow();
03764 #endif
03765 }
03766 }
03767
03768 #ifdef KEY
03769 #include "omp_directive.h"
03770 static void
03771 WFE_Expand_Omp (tree stmt)
03772 {
03773 switch (stmt->omp.choice)
03774 {
03775 case parallel_dir_b:
03776 expand_start_parallel ((struct parallel_clause_list *) stmt->omp.omp_clause_list);
03777 break;
03778 case parallel_dir_e:
03779 expand_end_parallel ();
03780 break;
03781 case for_dir_b:
03782 expand_start_for ((struct for_clause_list *) stmt->omp.omp_clause_list);
03783 break;
03784 case for_dir_e:
03785 expand_end_for ();
03786 break;
03787 case sections_cons_b:
03788 expand_start_sections ((struct sections_clause_list *) stmt->omp.omp_clause_list);
03789 break;
03790 case sections_cons_e:
03791 expand_end_sections ();
03792 break;
03793 case section_cons_b:
03794 expand_start_section ();
03795 break;
03796 case section_cons_e:
03797 expand_end_section ();
03798 break;
03799 case single_cons_b:
03800 expand_start_single ((struct single_clause_list *) stmt->omp.omp_clause_list); break;
03801 case single_cons_e:
03802 expand_end_single ();
03803 break;
03804 case par_for_cons_b:
03805 expand_start_parallel_for ((struct parallel_for_clause_list *) stmt->omp.omp_clause_list);
03806 break;
03807 case par_for_cons_e:
03808 expand_end_parallel_for ();
03809 break;
03810 case par_sctn_cons_b:
03811 expand_start_parallel_sections ((struct parallel_sections_clause_list *) stmt->omp.omp_clause_list);
03812 break;
03813 case par_sctn_cons_e:
03814 expand_end_parallel_sections ();
03815 break;
03816 case master_cons_b:
03817 expand_start_master ();
03818 break;
03819 case master_cons_e:
03820 expand_end_master ();
03821 break;
03822 case critical_cons_b:
03823 expand_start_critical ((tree) stmt->omp.omp_clause_list);
03824 break;
03825 case critical_cons_e:
03826 expand_end_critical ();
03827 break;
03828 case barrier_dir:
03829 expand_barrier ();
03830 break;
03831 case flush_dir:
03832 expand_flush ((tree) stmt->omp.omp_clause_list);
03833 break;
03834 case atomic_cons_b:
03835 expand_start_atomic ();
03836 break;
03837 case atomic_cons_e:
03838 expand_end_atomic ();
03839 break;
03840 case ordered_cons_b:
03841 expand_start_ordered ();
03842 break;
03843 case ordered_cons_e:
03844 expand_end_ordered ();
03845 break;
03846 case thdprv_dir:
03847 expand_threadprivate ((tree) stmt->omp.omp_clause_list);
03848 break;
03849 case options_dir:
03850 case exec_freq_dir:
03851 WFE_Expand_Pragma (stmt);
03852 break;
03853
03854 #ifdef TARG_SL // fork_joint
03855 case sl2_sections_cons_b:
03856 case sl2_minor_sections_cons_b:
03857 expand_start_sl2_sections (stmt->omp.choice == sl2_minor_sections_cons_b);
03858 break;
03859 case sl2_sections_cons_e:
03860 expand_end_sl2_sections ();
03861 break;
03862 case sl2_section_cons_b:
03863 case sl2_minor_section_cons_b:
03864 expand_start_sl2_section (stmt->omp.choice == sl2_minor_section_cons_b);
03865 break;
03866 case sl2_section_cons_e:
03867 case sl2_minor_section_cons_e:
03868 expand_end_sl2_section ();
03869 break;
03870 #endif
03871
03872
03873 default:
03874 Fail_FmtAssertion ("Unexpected stmt node");
03875 }
03876 }
03877
03878 void
03879 WFE_Expand_DO (tree stmt)
03880 {
03881 tree init, incr, cond, body;
03882
03883 WFE_Record_Loop_Switch (TREE_CODE (stmt));
03884
03885 init = FOR_INIT_STMT (stmt);
03886 incr = FOR_EXPR(stmt);
03887 cond = FOR_COND(stmt);
03888 body = FOR_BODY(stmt);
03889 #if 0
03890 for (init = FOR_INIT_STMT(stmt); init; init = TREE_CHAIN(init))
03891 WFE_Expand_Stmt(init);
03892 #endif
03893 expand_start_do_loop (init, cond, incr);
03894 while (body)
03895 {
03896 WFE_Expand_Stmt (body);
03897 body = TREE_CHAIN(body);
03898 }
03899
03900
03901 if (break_continue_info_stack [break_continue_info_i].continue_label_idx)
03902 {
03903 WFE_Stmt_Append (
03904 WN_CreateLabel ((ST_IDX) 0,
03905 break_continue_info_stack
03906 [break_continue_info_i].continue_label_idx,
03907 0, NULL),
03908 Get_Srcpos());
03909 }
03910
03911
03912 expand_end_do_loop ();
03913
03914
03915 if (break_continue_info_stack [break_continue_info_i].break_label_idx)
03916 {
03917 WFE_Stmt_Append (
03918 WN_CreateLabel ((ST_IDX) 0,
03919 break_continue_info_stack
03920 [break_continue_info_i].break_label_idx,
03921 0, NULL),
03922 Get_Srcpos());
03923 }
03924 --break_continue_info_i;
03925 }
03926 #endif // KEY
03927
03928 void
03929 WFE_Expand_Stmt(tree stmt, WN* target_wn)
03930 {
03931 #ifdef WFE_DEBUG
03932 fprintf (stderr,
03933 "{( WFE_Expand_Expr: %s\n", WFE_Tree_Node_Name (stmt));
03934 #endif
03935
03936 #ifdef KEY
03937 #if 0
03938
03939
03940 if (opt_regions && Check_For_Call_Region ())
03941 Did_Not_Terminate_Region = FALSE;
03942 #endif
03943 #endif
03944
03945 if (TREE_CODE(stmt) == LABEL_DECL)
03946 lineno = DECL_SOURCE_LINE(stmt);
03947 else
03948 if (TREE_CODE(stmt) != CASE_LABEL)
03949 lineno = STMT_LINENO(stmt);
03950
03951 if (STMT_IS_FULL_EXPR_P(stmt))
03952 Push_Temp_Cleanup (stmt, false);
03953
03954 switch (TREE_CODE(stmt)) {
03955 case ASM_STMT:
03956 Wfe_Expand_Asm_Operands (ASM_STRING (stmt),
03957 ASM_OUTPUTS (stmt),
03958 ASM_INPUTS (stmt),
03959 ASM_CLOBBERS (stmt),
03960 ASM_VOLATILE_P(stmt),
03961 NULL,
03962 0);
03963 break;
03964
03965 case BREAK_STMT:
03966 WFE_Expand_Break ();
03967 break;
03968
03969 case CASE_LABEL:
03970 WFE_Expand_Case (CASE_LOW(stmt), CASE_HIGH(stmt));
03971 break;
03972
03973 case CLEANUP_STMT:
03974 #ifdef KEY
03975 if (opt_regions && Check_For_Call_Region ())
03976 Did_Not_Terminate_Region = FALSE;
03977 if (!CLEANUP_EH_ONLY(stmt))
03978 Push_Scope_Cleanup (stmt);
03979 else Push_Scope_Cleanup (stmt, true );
03980 #else
03981 Push_Scope_Cleanup (stmt);
03982 #endif
03983 break;
03984
03985 case COMPOUND_STMT: {
03986 tree t;
03987 for (t = COMPOUND_BODY(stmt);
03988 t != NULL;
03989 t = TREE_CHAIN(t))
03990 WFE_Expand_Stmt (t, target_wn);
03991 break;
03992 }
03993
03994 case CONTINUE_STMT:
03995 WFE_Expand_Continue ();
03996 break;
03997
03998 case DECL_STMT:
03999 #ifdef KEY
04000
04001
04002
04003
04004
04005 if (TREE_CODE(DECL_STMT_DECL(stmt)) == INDIRECT_REF) {
04006 if (named_ret_obj_initializer) {
04007 WFE_Expand_Expr(named_ret_obj_initializer);
04008 }
04009 break;
04010 }
04011 #endif
04012 WFE_Expand_Decl (DECL_STMT_DECL (stmt));
04013 break;
04014
04015 case DO_STMT:
04016 WFE_Expand_Loop (stmt);
04017 break;
04018
04019 case EXPR_STMT:
04020 WFE_One_Stmt (EXPR_STMT_EXPR(stmt), target_wn);
04021 break;
04022
04023 case FOR_STMT:
04024 #ifdef KEY
04025 if (TREE_ADDRESSABLE (stmt))
04026 WFE_Expand_DO (stmt);
04027 else
04028 #endif
04029 WFE_Expand_Loop (stmt);
04030 break;
04031
04032 case GOTO_STMT: {
04033 tree dest = GOTO_DESTINATION(stmt);
04034 if (TREE_CODE(dest) == LABEL_DECL)
04035 WFE_Expand_Goto (dest);
04036 else
04037 WFE_Expand_Computed_Goto(dest);
04038 break;
04039 }
04040
04041 case IF_STMT:
04042 WFE_Expand_If (stmt);
04043 break;
04044
04045 case LABEL_STMT:
04046 WFE_Expand_Label (LABEL_STMT_LABEL(stmt));
04047 break;
04048
04049 case RETURN_STMT: {
04050 #ifdef KEY
04051 if (opt_regions && Check_For_Call_Region ())
04052 Did_Not_Terminate_Region = FALSE;
04053 tree t = RETURN_STMT_EXPR(stmt);
04054 #else
04055 tree t = RETURN_EXPR(stmt);
04056 #endif // KEY
04057 if (t && TREE_CODE(t) == INIT_EXPR) {
04058 Is_True(TREE_CODE(TREE_OPERAND(t, 0)) == RESULT_DECL,
04059 ("WFE_Expand_Stmt: expected RESULT_DECL"));
04060 tree t1 = TREE_OPERAND(t, 1);
04061 if (TREE_CODE(t1) == TARGET_EXPR)
04062 TREE_OPERAND(t1, 2) = 0;
04063 WFE_Expand_Return (stmt, t1);
04064 }
04065 else
04066 WFE_Expand_Return(stmt, t);
04067 return;
04068 }
04069
04070 case SCOPE_STMT:
04071 #ifdef KEY
04072 if (opt_regions && Check_For_Call_Region ())
04073 Did_Not_Terminate_Region = FALSE;
04074 #endif
04075 if (SCOPE_BEGIN_P(stmt))
04076 Push_Scope_Cleanup (stmt);
04077 else
04078 Pop_Scope_And_Do_Cleanups ();
04079 break;
04080
04081 #ifndef KEY
04082 case SUBOBJECT:
04083 break;
04084 #endif // !KEY
04085
04086 case SWITCH_STMT:
04087 WFE_Expand_Switch (stmt);
04088 break;
04089
04090 case TRY_BLOCK:
04091 #ifdef KEY
04092
04093 if (opt_regions && Check_For_Call_Region ())
04094 Did_Not_Terminate_Region = FALSE;
04095 #endif
04096 WFE_Expand_Try (stmt);
04097 break;
04098
04099 case WHILE_STMT:
04100 WFE_Expand_Loop (stmt);
04101 break;
04102
04103 #ifndef KEY
04104 case CTOR_STMT:
04105 DevWarn("Encountered CTOR_STMT (%s). Ignoring.",
04106 (CTOR_BEGIN_P(stmt) ? "begin" : "end"));
04107 break;
04108 #endif // !KEY
04109
04110 case FILE_STMT:
04111
04112 input_filename = FILE_STMT_FILENAME (stmt);
04113 #ifdef KEY //bug 10632,8895: File changed. Don't worry lineno
04114 WFE_Set_Line_And_File (lineno, input_filename);
04115 #endif
04116 break;
04117
04118 case EH_SPEC_BLOCK:
04119 WFE_Expand_EH_Spec (stmt);
04120 break;
04121
04122 case USING_STMT:
04123 break;
04124
04125 #ifdef KEY
04126 case OMP_MARKER_STMT:
04127 WFE_Expand_Omp (stmt);
04128 break;
04129 #endif // KEY
04130
04131 default:
04132 Is_True(FALSE,
04133 ("WFE_Expand_Stmt: Unexpected statement node %s", WFE_Tree_Node_Name (stmt)));
04134 break;
04135 }
04136
04137 if (STMT_IS_FULL_EXPR_P(stmt))
04138 Do_Temp_Cleanups (stmt);
04139
04140 #ifdef WFE_DEBUG
04141 fprintf (stderr,
04142 ")} WFE_Expand_Expr: %s\n", WFE_Tree_Node_Name (stmt));
04143 #endif
04144
04145 }
04146
04147 #ifdef KEY
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177 static void
04178 WFE_fixup_target_expr (tree retval)
04179 {
04180 tree decl = TREE_OPERAND(retval, 0);
04181 FmtAssert(TREE_CODE(decl) == VAR_DECL,
04182 ("WFE_fixup_target_expr: VAR_DECL not found in TARGET_EXPR"));
04183
04184
04185 WN *first_formal = WN_formal(Current_Entry_WN(), 0);
04186
04187
04188
04189 tree ptr_var = build_decl(VAR_DECL, NULL_TREE,
04190 build_pointer_type(TREE_TYPE(retval)));
04191 TREE_SET_CODE(decl, INDIRECT_REF);
04192 TREE_OPERAND(decl, 0) = ptr_var;
04193 set_DECL_ST(ptr_var, WN_st(first_formal));
04194 }
04195
04196
04197 bool
04198 WFE_has_copy_constructor (tree type)
04199 {
04200 if (CLASS_TYPE_P(type) &&
04201 CLASSTYPE_COPY_CONSTRUCTOR(type) != NULL)
04202 return TRUE;
04203
04204 return FALSE;
04205 }
04206
04207 bool
04208
04209
04210 Set_Current_Scope_Has_Alloca (INT & idx)
04211 {
04212 int i = scope_cleanup_i;
04213 while (i != -1)
04214 {
04215 if (TREE_CODE (scope_cleanup_stack[i].stmt) == SCOPE_STMT)
04216 break;
04217 i--;
04218 }
04219 Is_True (i != -1, ("No scope stmt available"));
04220
04221 idx = i;
04222 if (scope_cleanup_stack[i].vla.has_alloca) return TRUE;
04223 scope_cleanup_stack[i].vla.has_alloca = TRUE;
04224 return FALSE;
04225 }
04226
04227
04228 void
04229 Set_Current_Scope_Alloca_St (ST * st, int idx)
04230 {
04231 Is_True (TREE_CODE (scope_cleanup_stack[idx].stmt) == SCOPE_STMT,
04232 ("Unexpected tree code"));
04233 scope_cleanup_stack[idx].vla.alloca_st = st;
04234 }
04235
04236
04237 void
04238 Add_Current_Scope_Alloca_St (ST * st, int idx)
04239 {
04240 Is_True (TREE_CODE (scope_cleanup_stack[idx].stmt) == SCOPE_STMT,
04241 ("Unexpected tree code"));
04242 scope_cleanup_stack[idx].vla.alloca_sts_vector->push_back (st);
04243 }
04244
04245
04246
04247
04248
04249 void
04250 WFE_Expand_Pragma (tree exp)
04251 {
04252 switch (exp->omp.choice)
04253 {
04254 case options_dir:
04255 {
04256 TCON tcon;
04257 exp = (tree) exp->omp.omp_clause_list;
04258 tcon = Host_To_Targ_String (MTYPE_STRING,
04259 const_cast<char*>TREE_STRING_POINTER(exp),
04260 TREE_STRING_LENGTH(exp) - 1 );
04261 TY_IDX ty_idx = Get_TY(TREE_TYPE(exp));
04262 ST * st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
04263 TREE_STRING_ST (exp) = st;
04264 WN * wn = WN_CreatePragma (WN_PRAGMA_OPTIONS, st, 0, 0);
04265 WN * func_wn = WFE_Find_Stmt_In_Stack (wfe_stmk_func_entry);
04266 WN_INSERT_BlockLast (WN_func_pragmas(func_wn), wn);
04267 break;
04268 }
04269 case exec_freq_dir:
04270 {
04271 MIPS_FREQUENCY_HINT freq_hint;
04272 Is_True (TREE_CODE ((tree) exp->omp.omp_clause_list) == STRING_CST,
04273 ("Expected string constant with mips_frequency_hint"));
04274 const char * hint = TREE_STRING_POINTER ((tree) exp->omp.omp_clause_list);
04275 if (!strcmp (hint, "never")) freq_hint = FREQUENCY_HINT_NEVER;
04276 else if (!strcmp (hint, "init")) freq_hint = FREQUENCY_HINT_INIT;
04277 else if (!strcmp (hint, "frequent")) freq_hint = FREQUENCY_HINT_FREQUENT;
04278 else
04279 break;
04280
04281 WN * wn = WN_CreatePragma (WN_PRAGMA_MIPS_FREQUENCY_HINT, (ST*)NULL, freq_hint, 0);
04282 WFE_Stmt_Append (wn, Get_Srcpos());
04283 break;
04284 }
04285 }
04286 }
04287 #endif