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