00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #define __STDC_LIMIT_MACROS
00042 #include <stdint.h>
00043 #include "defs.h"
00044 #include "glob.h"
00045 #include "config.h"
00046 #include "wn.h"
00047 #include "wn_util.h"
00048
00049 #include "gnu_config.h"
00050 #include "gnu/system.h"
00051
00052 #include "srcpos.h"
00053 #include "gnu/flags.h"
00054 #include "gnu/tree.h"
00055 #include "insn-config.h"
00056 #include "ir_reader.h"
00057 #include "tree_symtab.h"
00058 #include "wfe_misc.h"
00059 #include "wfe_expr.h"
00060 #include "wfe_stmt.h"
00061 #include "targ_sim.h"
00062 #ifdef KEY
00063 #include "const.h"
00064 extern "C" void check_gnu_errors (INT *, INT *);
00065 #endif
00066 #include <ctype.h>
00067
00068 extern "C" int decode_reg_name (char*);
00069
00070 #define ENLARGE(x) (x + (x >> 1))
00071
00072 static BOOL *if_else_info_stack;
00073 static INT32 if_else_info_i;
00074 static INT32 if_else_info_max;
00075
00076 enum LOOP_CONTINUE_INFO {
00077 CONTINUE_NONE,
00078 CONTINUE_ELSEWHERE,
00079 CONTINUE_HERE,
00080 CONTINUE_ELSEWHERE_HERE,
00081 CONTINUE_HERE_ELSEWHERE
00082 };
00083
00084 typedef struct loop_info_t {
00085 struct nesting *whichloop;
00086 LOOP_CONTINUE_INFO continue_info;
00087 LABEL_IDX continue_label_idx;
00088 LABEL_IDX exit_label_idx;
00089 BOOL exit_loop_if_false;
00090 BOOL continue_here;
00091 } LOOP_INFO;
00092
00093 static LOOP_INFO *loop_info_stack;
00094 static INT32 loop_info_i;
00095 static INT32 loop_info_max;
00096
00097 typedef struct case_info_t {
00098 INT64 case_lower_bound_value;
00099 INT64 case_upper_bound_value;
00100 LABEL_IDX case_label_idx;
00101 } CASE_INFO;
00102
00103 typedef struct switch_info_t {
00104 WN *index;
00105 TYPE_ID index_mtype;
00106 INT32 start_case_index;
00107 LABEL_IDX default_label_idx;
00108 LABEL_IDX exit_label_idx;
00109 } SWITCH_INFO;
00110
00111 static CASE_INFO *case_info_stack;
00112 static INT32 case_info_i;
00113 static INT32 case_info_max;
00114
00115 static SWITCH_INFO *switch_info_stack;
00116 static INT32 switch_info_i;
00117 static INT32 switch_info_max;
00118
00119 typedef struct label_info_t {
00120 LABEL_IDX label_idx;
00121 unsigned char symtab_idx;
00122 unsigned char defined;
00123 } LABEL_INFO;
00124
00125 static LABEL_INFO *undefined_labels_stack;
00126 static INT32 undefined_labels_i;
00127 static INT32 undefined_labels_max;
00128
00129 void
00130 WFE_Stmt_Init (void)
00131 {
00132 if_else_info_max = 32;
00133 if_else_info_i = -1;
00134 if_else_info_stack = (BOOL *) malloc (sizeof (BOOL) * if_else_info_max);
00135 loop_info_max = 32;
00136 loop_info_i = -1;
00137 loop_info_stack = (LOOP_INFO *) malloc (sizeof (LOOP_INFO) * loop_info_max);
00138 switch_info_max = 32;
00139 switch_info_i = -1;
00140 switch_info_stack = (SWITCH_INFO *) malloc (sizeof (SWITCH_INFO) * switch_info_max);
00141 case_info_max = 32;
00142 case_info_i = -1;
00143 case_info_stack = (CASE_INFO *) malloc (sizeof (CASE_INFO) * case_info_max);
00144 undefined_labels_max = 32;
00145 undefined_labels_i = -1;
00146 undefined_labels_stack = (LABEL_INFO *) malloc (sizeof (LABEL_INFO) * undefined_labels_max);
00147 }
00148
00149 void
00150 WFE_Expand_Start_Cond (tree cond, int exitflag)
00151 {
00152 WN* if_stmt;
00153 WN* test;
00154 WN* then_block;
00155 WN* else_block;
00156
00157 if (++if_else_info_i == if_else_info_max) {
00158
00159 if_else_info_max = ENLARGE(if_else_info_max);
00160 if_else_info_stack = (BOOL *) realloc (if_else_info_stack,
00161 if_else_info_max * sizeof (BOOL));
00162 }
00163
00164 if_else_info_stack [if_else_info_i] = FALSE;
00165 test = WFE_Expand_Expr_With_Sequence_Point (cond, Boolean_type);
00166 then_block = WN_CreateBlock ();
00167 else_block = WN_CreateBlock ();
00168 if_stmt = WN_CreateIf (test, then_block, else_block);
00169 WFE_Stmt_Append (if_stmt, Get_Srcpos());
00170 WFE_Stmt_Push (else_block, wfe_stmk_if_else, Get_Srcpos());
00171 WFE_Stmt_Push (then_block, wfe_stmk_if_then, Get_Srcpos());
00172 }
00173
00174 void
00175 WFE_Expand_Start_Else (void)
00176 {
00177 FmtAssert (if_else_info_i >= 0,
00178 ("WFE_Expand_Start_Else: no ifs"));
00179 if_else_info_stack [if_else_info_i] = TRUE;
00180 WFE_Stmt_Pop (wfe_stmk_if_then);
00181 }
00182
00183 void
00184 WFE_Expand_End_Cond (void)
00185 {
00186 FmtAssert (if_else_info_i >= 0,
00187 ("WFE_Expand_End_Cond: no ifs"));
00188 if (if_else_info_stack [if_else_info_i] == FALSE)
00189 WFE_Stmt_Pop (wfe_stmk_if_then);
00190 WFE_Stmt_Pop (wfe_stmk_if_else);
00191 --if_else_info_i;
00192 }
00193
00194 void
00195 WFE_Expand_Start_Loop (int exitflag, struct nesting *whichloop)
00196 {
00197 WN* while_body;
00198
00199 if (++loop_info_i == loop_info_max) {
00200
00201 loop_info_max = ENLARGE(loop_info_max);
00202 loop_info_stack = (LOOP_INFO *) realloc (loop_info_stack,
00203 loop_info_max * sizeof (LOOP_INFO));
00204 }
00205
00206 loop_info_stack [loop_info_i].whichloop = whichloop;
00207 loop_info_stack [loop_info_i].continue_info = CONTINUE_NONE;
00208 loop_info_stack [loop_info_i].continue_label_idx = 0;
00209 loop_info_stack [loop_info_i].exit_label_idx = 0;
00210 loop_info_stack [loop_info_i].exit_loop_if_false = FALSE;
00211 loop_info_stack [loop_info_i].continue_here = FALSE;
00212
00213 while_body = WN_CreateBlock ();
00214 WFE_Stmt_Push (while_body, wfe_stmk_while_body, Get_Srcpos());
00215 }
00216
00217 void
00218 WFE_Expand_Start_Loop_Continue_Elsewhere (int exitflag, struct nesting *whichloop)
00219 {
00220 FmtAssert (loop_info_i >= 0,
00221 ("WFE_Expand_Start_Loop_Continue_Elsewhere: no loops"));
00222 FmtAssert (loop_info_stack [loop_info_i].whichloop == whichloop,
00223 ("WFE_Expand_Start_Loop_Continue_Elsewhere: loop mismatch"));
00224 if (loop_info_stack [loop_info_i].continue_info == CONTINUE_NONE)
00225 loop_info_stack [loop_info_i].continue_info = CONTINUE_ELSEWHERE;
00226 else
00227 if (loop_info_stack [loop_info_i].continue_info == CONTINUE_HERE)
00228 loop_info_stack [loop_info_i].continue_info = CONTINUE_HERE_ELSEWHERE;
00229 else
00230 Fail_FmtAssertion ("WFE_Expand_Start_Loop_Continue_Elsewhere: unexpected state");
00231 #ifndef TARG_NVISA // only create label if needed
00232 LABEL_IDX continue_label_idx;
00233 New_LABEL (CURRENT_SYMTAB, continue_label_idx);
00234 loop_info_stack [loop_info_i].continue_label_idx = continue_label_idx;
00235 #endif
00236 }
00237
00238 void
00239 WFE_Expand_Loop_Continue_Here (void)
00240 {
00241 FmtAssert (loop_info_i >= 0,
00242 ("WFE_Expand_Loop_Continue_Here: no loops"));
00243 if (loop_info_stack [loop_info_i].continue_info == CONTINUE_NONE)
00244 loop_info_stack [loop_info_i].continue_info = CONTINUE_HERE;
00245 else
00246 if (loop_info_stack [loop_info_i].continue_info == CONTINUE_ELSEWHERE)
00247 loop_info_stack [loop_info_i].continue_info = CONTINUE_ELSEWHERE_HERE;
00248 else
00249 Fail_FmtAssertion ("WFE_Expand_Loop_Continue_Here: unexpected state");
00250
00251 #ifdef TARG_NVISA
00252
00253
00254 if (loop_info_stack [loop_info_i].continue_label_idx)
00255 #endif
00256 WFE_Stmt_Append (
00257 WN_CreateLabel ((ST_IDX) 0,
00258 loop_info_stack [loop_info_i].continue_label_idx,
00259 0, NULL),
00260 Get_Srcpos());
00261 loop_info_stack [loop_info_i].continue_here = TRUE;
00262 }
00263
00264 void
00265 WFE_Expand_End_Loop (void)
00266 {
00267 LABEL_IDX exit_label_idx;
00268 FmtAssert (loop_info_i >= 0,
00269 ("WFE_Expand_End_Loop: no loops"));
00270 if (!loop_info_stack [loop_info_i].exit_loop_if_false) {
00271 WN *while_body;
00272 WN *while_stmt;
00273 WN *test = WN_Intconst (MTYPE_I4, 1);
00274 while_body = WFE_Stmt_Pop (wfe_stmk_while_body);
00275 switch (loop_info_stack [loop_info_i].continue_info) {
00276 case CONTINUE_NONE:
00277 case CONTINUE_ELSEWHERE:
00278 while_stmt = WN_CreateWhileDo (test, while_body);
00279 break;
00280 case CONTINUE_ELSEWHERE_HERE:
00281 while_stmt = WN_CreateDoWhile (test, while_body);
00282 break;
00283 default:
00284 Fail_FmtAssertion ("WFE_Expand_Exit_Loop_If_False: unexpected state");
00285 break;
00286 }
00287 WFE_Stmt_Append (while_stmt, Get_Srcpos());
00288 WFE_Stmt_Push (while_body, wfe_stmk_while_body, Get_Srcpos());
00289 }
00290 if (loop_info_stack [loop_info_i].continue_label_idx &&
00291 loop_info_stack [loop_info_i].continue_here == FALSE) {
00292 WFE_Stmt_Append (
00293 WN_CreateLabel ((ST_IDX) 0,
00294 loop_info_stack [loop_info_i].continue_label_idx,
00295 0, NULL),
00296 Get_Srcpos());
00297 }
00298 WFE_Stmt_Pop (wfe_stmk_while_body);
00299 exit_label_idx = loop_info_stack [loop_info_i].exit_label_idx;
00300 if (exit_label_idx) {
00301 WFE_Stmt_Append (
00302 WN_CreateLabel ((ST_IDX) 0, exit_label_idx, 0, NULL),
00303 Get_Srcpos());
00304 }
00305 --loop_info_i;
00306 }
00307
00308 void
00309 WFE_Expand_Continue_Loop (struct nesting *whichloop)
00310 {
00311 FmtAssert (loop_info_i >= 0,
00312 ("WFE_Expand_Continue_Loop: no loops"));
00313 LABEL_IDX continue_label_idx = loop_info_stack [loop_info_i].continue_label_idx;
00314
00315 if (continue_label_idx == 0) {
00316 New_LABEL (CURRENT_SYMTAB, continue_label_idx);
00317 loop_info_stack [loop_info_i].continue_label_idx = continue_label_idx;
00318 }
00319
00320 WN* wn = WN_CreateGoto ((ST_IDX) NULL, continue_label_idx);
00321 WFE_Stmt_Append (wn, Get_Srcpos());
00322 }
00323
00324 void
00325 WFE_Expand_Exit_Loop (struct nesting *whichloop)
00326 {
00327 Fail_FmtAssertion ("WFE_Expand_Exit_Loop: unexpected state");
00328 }
00329
00330 void
00331 WFE_Expand_Exit_Loop_If_False (struct nesting *whichloop, tree cond)
00332 {
00333 WN* while_stmt;
00334 WN* test;
00335 WN* while_body;
00336
00337 FmtAssert (loop_info_i >= 0,
00338 ("WFE_Expand_Exit_Loop_If_False: no loops"));
00339 FmtAssert (loop_info_stack [loop_info_i].whichloop == whichloop,
00340 ("WFE_Expand_Exit_Loop_If_False: loop mismatch"));
00341 loop_info_stack [loop_info_i].exit_loop_if_false = TRUE;
00342 #ifdef KEY
00343 if (cond)
00344 test = WFE_Expand_Expr_With_Sequence_Point (cond, Boolean_type);
00345 else
00346 test = WN_Intconst (Boolean_type, 1);
00347 #else
00348 test = WFE_Expand_Expr_With_Sequence_Point (cond, Boolean_type);
00349 #endif // KEY
00350 while_body = WFE_Stmt_Pop (wfe_stmk_while_body);
00351 switch (loop_info_stack [loop_info_i].continue_info) {
00352 case CONTINUE_NONE:
00353 case CONTINUE_ELSEWHERE:
00354 while_stmt = WN_CreateWhileDo (test, while_body);
00355 break;
00356 case CONTINUE_ELSEWHERE_HERE:
00357 while_stmt = WN_CreateDoWhile (test, while_body);
00358 break;
00359 default:
00360 Fail_FmtAssertion ("WFE_Expand_Exit_Loop_If_False: unexpected state");
00361 break;
00362 }
00363 WFE_Stmt_Append (while_stmt, Get_Srcpos());
00364 WFE_Stmt_Push (while_body, wfe_stmk_while_body, Get_Srcpos());
00365 }
00366
00367 void
00368 WFE_Expand_Start_Case (int exit_flag, tree expr, tree type, char *printname)
00369 {
00370 TYPE_ID index_mtype = Mtype_comparison (TY_mtype (Get_TY (TREE_TYPE (expr))));
00371 WN *switch_block = WN_CreateBlock ();
00372 WN *index = WFE_Expand_Expr_With_Sequence_Point (expr, index_mtype);
00373
00374 #ifdef KEY
00375
00376
00377
00378 ST *save_expr_st = Gen_Temp_Symbol (MTYPE_TO_TY_array[index_mtype], "_switch_index");
00379 WN *stid = WN_Stid (index_mtype, 0, save_expr_st, MTYPE_TO_TY_array[index_mtype], index);
00380 WFE_Stmt_Append(stid, Get_Srcpos());
00381 index = WN_Ldid(index_mtype, 0, save_expr_st, MTYPE_TO_TY_array[index_mtype]);
00382 #endif
00383
00384 WFE_Stmt_Push (switch_block, wfe_stmk_switch, Get_Srcpos());
00385 if (++switch_info_i == switch_info_max) {
00386
00387 switch_info_max = ENLARGE(switch_info_max);
00388 switch_info_stack = (SWITCH_INFO *) realloc (switch_info_stack,
00389 switch_info_max * sizeof (SWITCH_INFO));
00390 }
00391 switch_info_stack [switch_info_i].index = index;
00392 switch_info_stack [switch_info_i].index_mtype = index_mtype;
00393 switch_info_stack [switch_info_i].start_case_index = case_info_i + 1;
00394 switch_info_stack [switch_info_i].default_label_idx = 0;
00395 switch_info_stack [switch_info_i].exit_label_idx = 0;
00396 }
00397
00398 void
00399 WFE_Expand_Start_Case_Dummy (void)
00400 {
00401 }
00402
00403 void
00404 WFE_Add_Case_Node (tree low, tree high, tree label)
00405 {
00406 WN *wn;
00407 LABEL_IDX case_label_idx;
00408 WN *lower_bound = WFE_Expand_Expr (low);
00409 WN *upper_bound = WFE_Expand_Expr (high);
00410 if (WN_const_val (lower_bound) != WN_const_val (upper_bound))
00411 DevWarn ("ecncountered case range at line %d", lineno);
00412 if (++case_info_i == case_info_max) {
00413
00414 case_info_max = ENLARGE(case_info_max);
00415 case_info_stack = (CASE_INFO *) realloc (case_info_stack,
00416 case_info_max * sizeof (CASE_INFO));
00417 }
00418 case_info_stack [case_info_i].case_lower_bound_value = WN_const_val (lower_bound);
00419 case_info_stack [case_info_i].case_upper_bound_value = WN_const_val (upper_bound);
00420 #ifdef KEY
00421 if (label->decl.sgi_u1.label_idx != (LABEL_IDX) 0)
00422 case_label_idx = label->decl.sgi_u1.label_idx;
00423 else {
00424 #endif
00425 FmtAssert (label->decl.sgi_u1.label_idx == (LABEL_IDX) 0,
00426 ("WFE_Add_Case_Node: label already defined"));
00427 #ifdef KEY
00428 }
00429 #endif
00430 #ifdef PATHSCALE_MERGE
00431
00432
00433 New_LABEL (CURRENT_SYMTAB, case_label_idx);
00434 #endif
00435 label->decl.sgi_u1.label_idx = case_label_idx;
00436 label->decl.label_defined = TRUE;
00437 case_info_stack [case_info_i].case_label_idx = case_label_idx;
00438 wn = WN_CreateLabel ((ST_IDX) 0, case_label_idx, 0, NULL);
00439 WFE_Stmt_Append (wn, Get_Srcpos ());
00440 }
00441
00442 void
00443 WFE_Emit_Case_Nodes (void)
00444 {
00445 }
00446
00447 void
00448 WFE_Expand_End_Case_Dummy (void)
00449 {
00450 }
00451
00452 #ifdef PATHSCALE_MERGE
00453
00454 static WN* WN_CreateIfForCaseGotoRange(
00455 ST_IDX value, TYPE_ID value_ty,
00456 INT64 case_lb, INT64 case_ub, INT32 case_label)
00457 {
00458 TY_IDX ty = MTYPE_To_TY(value_ty);
00459 WN* wn_lb = WN_Intconst(value_ty, case_lb);
00460 WN* wn_ub = WN_Intconst(value_ty, case_ub);
00461 WN* wn_lv = WN_Ldid(value_ty, 0, value, ty, 0);
00462 WN* wn_uv = WN_Ldid(value_ty, 0, value, ty, 0);
00463 WN* cmp_l = WN_CreateExp2(OPR_GE, MTYPE_I4, value_ty, wn_lv, wn_lb);
00464 WN* cmp_u = WN_CreateExp2(OPR_LE, MTYPE_I4, value_ty, wn_uv, wn_ub);
00465 WN* cond = WN_CreateExp2(OPR_LAND, MTYPE_I4, MTYPE_V, cmp_l, cmp_u);
00466 WN* wn_goto = WN_CreateGoto(case_label);
00467 WN* then_blk = WN_CreateBlock();
00468 WN* else_blk = WN_CreateBlock();
00469 WN_INSERT_BlockLast(then_blk, wn_goto);
00470 return WN_CreateIf(cond, then_blk, else_blk);
00471 }
00472 #endif
00473
00474 void
00475 WFE_Expand_End_Case (tree orig_index)
00476 {
00477 INT32 i;
00478 INT32 n;
00479 WN *switch_wn;
00480 WN *switch_block;
00481 WN *case_block;
00482 WN *case_entry;
00483 WN *def_goto;
00484 WN *wn;
00485 #ifdef PATHSCALE_MERGE
00486
00487
00488 ST *value_st = NULL;
00489 WN *value_stid = NULL;
00490 WN *if_block = NULL;
00491 char st_name[32];
00492 const int CASE_VALUE_THRESHOLD = 512;
00493 #endif
00494 TYPE_ID index_mtype = switch_info_stack [switch_info_i].index_mtype;
00495
00496 n = case_info_i - switch_info_stack [switch_info_i].start_case_index + 1;
00497 if (switch_info_stack [switch_info_i].exit_label_idx == 0) {
00498 New_LABEL (CURRENT_SYMTAB, switch_info_stack [switch_info_i].exit_label_idx);
00499 }
00500 if (switch_info_stack [switch_info_i].default_label_idx)
00501 def_goto = WN_CreateGoto (switch_info_stack [switch_info_i].default_label_idx);
00502 else
00503 def_goto = WN_CreateGoto (switch_info_stack [switch_info_i].exit_label_idx);
00504 case_block = WN_CreateBlock ();
00505 for (i = switch_info_stack [switch_info_i].start_case_index;
00506 i <= case_info_i;
00507 i++) {
00508 LABEL_IDX case_label_idx = case_info_stack [i].case_label_idx;
00509 if (case_info_stack [i].case_lower_bound_value ==
00510 case_info_stack [i].case_upper_bound_value) {
00511
00512 INT64 case_value = case_info_stack [i].case_lower_bound_value;
00513 case_entry = WN_CreateCasegoto (case_value, case_label_idx);
00514 WN_INSERT_BlockLast (case_block, case_entry);
00515 }
00516 else {
00517 #ifdef PATHSCALE_MERGE
00518
00519 UINT64 range;
00520 if (MTYPE_is_signed (index_mtype))
00521 range = (INT64)case_info_stack [i].case_upper_bound_value -
00522 (INT64)case_info_stack [i].case_lower_bound_value;
00523 else
00524 range = (UINT64)case_info_stack [i].case_upper_bound_value -
00525 (UINT64)case_info_stack [i].case_lower_bound_value;
00526 if ( range > CASE_VALUE_THRESHOLD ) {
00527
00528 WN *if_stmt;
00529 if ( value_st == NULL ) {
00530 Is_True(value_stid == NULL, ("Convert Multi CaseGoto to if: value_stid is not NULL"));
00531 Is_True(if_block == NULL, ("Convert Multi CaseGoto to if: if_block is not NULL"));
00532
00533 value_st = New_ST();
00534 sprintf(st_name, "__tmp_switch_value_%d", switch_info_i);
00535 ST_Init(value_st, Save_Str(st_name),
00536 CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, MTYPE_To_TY(index_mtype));
00537 value_stid = WN_Stid(index_mtype,
00538 0, value_st, MTYPE_To_TY(index_mtype),
00539 switch_info_stack [switch_info_i].index, 0);
00540 if_block = WN_CreateBlock();
00541 }
00542
00543 Is_True( value_st != NULL, ("Convert Multi CaseGoto to if: value_st is NULL"));
00544 Is_True( value_stid != NULL, ("Convert Multi CaseGoto to if: value_stid is NULL"));
00545 Is_True( if_block != NULL, ("Convert Multi CaseGoto to if: if_block is NULL"));
00546 if_stmt = WN_CreateIfForCaseGotoRange(ST_st_idx(value_st), index_mtype,
00547 case_info_stack [i].case_lower_bound_value,
00548 case_info_stack [i].case_upper_bound_value,
00549 case_label_idx);
00550 WN_INSERT_BlockLast(if_block, if_stmt);
00551 }
00552 else {
00553 if (MTYPE_is_signed (index_mtype)) {
00554 INT64 case_value;
00555 for (case_value = case_info_stack [i].case_lower_bound_value;
00556 case_value <= case_info_stack [i].case_upper_bound_value;
00557 case_value++) {
00558
00559 case_entry = WN_CreateCasegoto (case_value, case_label_idx);
00560 WN_INSERT_BlockLast (case_block, case_entry);
00561 }
00562 }
00563 else {
00564 UINT64 case_value;
00565 for (case_value = (UINT64) case_info_stack [i].case_lower_bound_value;
00566 case_value <= (UINT64) case_info_stack [i].case_upper_bound_value;
00567 case_value++) {
00568
00569 case_entry = WN_CreateCasegoto (case_value, case_label_idx);
00570 WN_INSERT_BlockLast (case_block, case_entry);
00571 }
00572 }
00573 }
00574 }
00575 }
00576
00577
00578 switch_block = WFE_Stmt_Pop (wfe_stmk_switch);
00579 if ( value_stid != NULL ) {
00580 WN *value_ldid = WN_CreateLdid(OPR_LDID, index_mtype, index_mtype,
00581 0, ST_st_idx(value_st),
00582 MTYPE_To_TY(index_mtype),0);
00583 switch_wn = WN_CreateSwitch (n,
00584 value_ldid,
00585 case_block,
00586 def_goto,
00587 switch_info_stack [switch_info_i].exit_label_idx);
00588 WFE_Stmt_Append (value_stid, WN_Get_Linenum(switch_block));
00589 WFE_Stmt_Append (if_block, WN_Get_Linenum(switch_block));
00590 }
00591 else {
00592 switch_wn = WN_CreateSwitch (n,
00593 switch_info_stack [switch_info_i].index,
00594 case_block,
00595 def_goto,
00596 switch_info_stack [switch_info_i].exit_label_idx);
00597 }
00598
00599 #endif
00600 #ifndef KEY
00601 WFE_Stmt_Append (switch_wn, Get_Srcpos ());
00602 WFE_Stmt_Append (switch_block, Get_Srcpos ());
00603 #else
00604
00605
00606 WFE_Stmt_Append (switch_wn, WN_Get_Linenum(switch_block));
00607 WFE_Stmt_Append (switch_block, WN_Get_Linenum(switch_block));
00608 #endif
00609 wn = WN_CreateLabel ((ST_IDX) 0,
00610 switch_info_stack [switch_info_i].exit_label_idx,
00611 0, NULL);
00612 WFE_Stmt_Append (wn, Get_Srcpos ());
00613 case_info_i = switch_info_stack [switch_info_i].start_case_index - 1;
00614 --switch_info_i;
00615 }
00616
00617 void
00618 WFE_Record_Switch_Default_Label (tree label)
00619 {
00620 LABEL_IDX default_label_idx;
00621 WN *wn;
00622
00623 #ifdef KEY
00624
00625
00626 if (label->decl.sgi_u1.label_idx != (LABEL_IDX) 0)
00627 default_label_idx = label->decl.sgi_u1.label_idx;
00628 else
00629 #else
00630 FmtAssert (label->decl.sgi_u1.label_idx == (LABEL_IDX) 0,
00631 ("WFE_Record_Switch_Default_Label: label already defined"));
00632 #endif
00633 New_LABEL (CURRENT_SYMTAB, default_label_idx);
00634 label->decl.sgi_u1.label_idx = default_label_idx;
00635 label->decl.label_defined = TRUE;
00636 switch_info_stack [switch_info_i].default_label_idx = default_label_idx;
00637 wn = WN_CreateLabel ((ST_IDX) 0, default_label_idx, 0, NULL);
00638 WFE_Stmt_Append (wn, Get_Srcpos ());
00639 }
00640
00641 void
00642 WFE_Expand_Exit_Something (struct nesting *n,
00643 struct nesting *cond_stack,
00644 struct nesting *loop_stack,
00645 struct nesting *case_stack,
00646 LABEL_IDX *label_idx)
00647 {
00648 LABEL_IDX exit_label_idx = *label_idx;
00649 WN *wn;
00650 if (n == case_stack) {
00651 if (exit_label_idx == 0) {
00652 New_LABEL (CURRENT_SYMTAB, exit_label_idx);
00653 *label_idx = exit_label_idx;
00654 switch_info_stack [switch_info_i].exit_label_idx = exit_label_idx;
00655 }
00656 wn = WN_CreateGoto (exit_label_idx);
00657 WFE_Stmt_Append (wn, Get_Srcpos ());
00658 }
00659 else
00660 if (n == loop_stack) {
00661 if (n == loop_info_stack [loop_info_i].whichloop) {
00662 if (exit_label_idx == 0) {
00663 New_LABEL (CURRENT_SYMTAB, exit_label_idx);
00664 *label_idx = exit_label_idx;
00665 loop_info_stack [loop_info_i].exit_label_idx = exit_label_idx;
00666 }
00667 wn = WN_CreateGoto (exit_label_idx);
00668 WFE_Stmt_Append (wn, Get_Srcpos ());
00669 }
00670 }
00671 }
00672
00673 LABEL_IDX
00674 WFE_Get_LABEL (tree label, int def)
00675 {
00676 LABEL_IDX label_idx = label->decl.sgi_u1.label_idx;
00677 LABEL_IDX symtab_idx = label->decl.symtab_idx;
00678
00679 if (label_idx == 0) {
00680 LABEL_Init (New_LABEL (CURRENT_SYMTAB, label_idx), 0, LKIND_DEFAULT);
00681 label->decl.sgi_u1.label_idx = label_idx;
00682 label->decl.symtab_idx = CURRENT_SYMTAB;
00683 if (!def) {
00684 if (++undefined_labels_i == undefined_labels_max) {
00685 undefined_labels_max = ENLARGE(undefined_labels_max);
00686 undefined_labels_stack =
00687 (LABEL_INFO *) realloc (undefined_labels_stack,
00688 undefined_labels_max * sizeof (LABEL_INFO));
00689 }
00690 undefined_labels_stack [undefined_labels_i].label_idx = label_idx;
00691 undefined_labels_stack [undefined_labels_i].symtab_idx = CURRENT_SYMTAB;
00692 undefined_labels_stack [undefined_labels_i].defined = FALSE;
00693 }
00694 }
00695 else {
00696 if (def) {
00697 for (int i = undefined_labels_i; i >= 0; --i) {
00698 if (undefined_labels_stack [i].label_idx == label_idx &&
00699 undefined_labels_stack [i].symtab_idx == CURRENT_SYMTAB) {
00700 undefined_labels_stack [i].defined = TRUE;
00701 break;
00702 }
00703 }
00704 }
00705
00706
00707
00708
00709
00710
00711
00712 }
00713
00714 return label_idx;
00715 }
00716
00717 void
00718 WFE_Declare_Nonlocal_Label (tree label)
00719 {
00720 LABEL_IDX label_idx = WFE_Get_LABEL (label, FALSE);
00721 Set_LABEL_target_of_goto_outer_block (label_idx);
00722 }
00723
00724 void
00725 WFE_Expand_Label (tree label)
00726 {
00727 LABEL_IDX label_idx = WFE_Get_LABEL (label, TRUE);
00728 label->decl.symtab_idx = CURRENT_SYMTAB;
00729
00730 if (!label->decl.label_defined) {
00731 WN *wn;
00732 label->decl.label_defined = TRUE;
00733 wn = WN_CreateLabel ((ST_IDX) 0, label_idx, 0, NULL);
00734 WFE_Stmt_Append (wn, Get_Srcpos ());
00735 }
00736 }
00737
00738 void
00739 WFE_Expand_Goto (tree label)
00740 {
00741 WN *wn;
00742 LABEL_IDX label_idx = WFE_Get_LABEL (label, FALSE);
00743 if ((CURRENT_SYMTAB > GLOBAL_SYMTAB + 1) &&
00744 (label->decl.symtab_idx < CURRENT_SYMTAB))
00745 wn = WN_CreateGotoOuterBlock (label_idx, label->decl.symtab_idx);
00746 else
00747 wn = WN_CreateGoto ((ST_IDX) NULL, label_idx);
00748 WFE_Stmt_Append (wn, Get_Srcpos());
00749 }
00750
00751 void
00752 WFE_Expand_Computed_Goto (tree exp)
00753 {
00754 DevWarn ("encountered indirect jump at line %d\n", lineno);
00755 Set_PU_no_inline (Get_Current_PU ());
00756 WN *addr = WFE_Expand_Expr (exp);
00757 WN *wn = WN_CreateAgoto (addr);
00758 WFE_Stmt_Append (wn, Get_Srcpos());
00759 }
00760
00761 void
00762 WFE_Expand_Return (tree retval)
00763 {
00764 WN *wn;
00765
00766 if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE) {
00767 if (retval) {
00768 (void) WFE_Expand_Expr_With_Sequence_Point (retval, MTYPE_V);
00769 }
00770 wn = WN_CreateReturn ();
00771 }
00772 else {
00773 WN *rhs_wn;
00774 TY_IDX ret_ty_idx = Get_TY(TREE_TYPE(TREE_TYPE(current_function_decl)));
00775 rhs_wn = WFE_Expand_Expr_With_Sequence_Point (
00776 TREE_OPERAND (retval, 1),
00777 TY_mtype (ret_ty_idx));
00778 if (!WFE_Keep_Zero_Length_Structs &&
00779 TY_mtype (ret_ty_idx) == MTYPE_M &&
00780 TY_size (ret_ty_idx) == 0) {
00781
00782 if (WN_has_side_effects (rhs_wn)) {
00783 rhs_wn = WN_CreateEval (rhs_wn);
00784 WFE_Stmt_Append(rhs_wn, Get_Srcpos());
00785 }
00786 wn = WN_CreateReturn ();
00787 }
00788 else {
00789 if (WN_opcode (rhs_wn) == OPC_MMLDID &&
00790 WN_offset (rhs_wn) == 0 &&
00791 WN_field_id (rhs_wn) == 0 &&
00792 TY_align (ret_ty_idx) < MTYPE_align_best(Spill_Int_Mtype)) {
00793 ST *st = WN_st (rhs_wn);
00794 TY_IDX ty_idx = ST_type (st);
00795 #ifdef PATHSCALE_MERGE
00796
00797
00798
00799
00800
00801
00802
00803
00804 if (ty_idx == ret_ty_idx && ST_sclass(st) != SCLASS_EXTERN) {
00805 #endif
00806 Set_TY_align (ty_idx, MTYPE_align_best(Spill_Int_Mtype));
00807 Set_ST_type (st, ty_idx);
00808 }
00809 }
00810 WFE_Set_ST_Addr_Saved (rhs_wn);
00811 if (DECL_WIDEN_RETVAL(current_function_decl)) {
00812 TYPE_ID old_rtype = WN_rtype(rhs_wn);
00813 TYPE_ID new_rtype = MTYPE_is_signed (old_rtype) ? MTYPE_I8 : MTYPE_U8;
00814 rhs_wn = WN_Cvt (old_rtype, new_rtype, rhs_wn);
00815 wn = WN_CreateReturn_Val(OPR_RETURN_VAL, new_rtype, MTYPE_V, rhs_wn);
00816 }
00817 else
00818 wn = WN_CreateReturn_Val(OPR_RETURN_VAL, TY_mtype(ret_ty_idx), MTYPE_V, rhs_wn);
00819 }
00820 }
00821
00822 WFE_Stmt_Append(wn, Get_Srcpos());
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832 static WN *
00833 idname_from_regnum (int gcc_reg)
00834 {
00835 if (gcc_reg < 0) {
00836 DevWarn("unrecognized register name in asm");
00837 return NULL;
00838 }
00839 else {
00840 extern PREG_NUM Map_Reg_To_Preg [];
00841 PREG_NUM preg = Map_Reg_To_Preg [gcc_reg];
00842 if (preg < 0) {
00843 DevWarn("couldn't map asm regname to preg");
00844 return NULL;
00845 }
00846 ST *st;
00847 if (Preg_Offset_Is_Int(preg))
00848 st = Int_Preg;
00849 else if (Preg_Offset_Is_Float(preg))
00850 st = Float_Preg;
00851 #ifdef TARG_IA64
00852
00853 else if (Preg_Offset_Is_Branch(preg))
00854 st = Branch_Preg;
00855 #endif
00856 #ifdef TARG_X8664
00857 else if (Preg_Offset_Is_X87(preg))
00858 st = X87_Preg;
00859 #endif
00860 else
00861 FmtAssert (FALSE, ("unexpected preg %d", preg));
00862 return WN_CreateIdname((WN_OFFSET) preg, st);
00863 }
00864 }
00865
00866 char *
00867 remove_plus_modifier(char *s)
00868 {
00869 #define MAX_NON_PLUS_CONSTRAINT_CHARS 7
00870 static char out[MAX_NON_PLUS_CONSTRAINT_CHARS + 1];
00871 int i = 0;
00872 while (i <= MAX_NON_PLUS_CONSTRAINT_CHARS)
00873 {
00874 while (*s == '+')
00875 {
00876 ++s;
00877 }
00878 out[i++] = *s;
00879 if (*s == '\0')
00880 {
00881 return out;
00882 }
00883 else
00884 {
00885 ++s;
00886 }
00887 }
00888 Fail_FmtAssertion("Constraint string too long");
00889
00890 }
00891
00892 BOOL
00893 constraint_supported (const char *s)
00894 {
00895 while (*s != 0) {
00896 if (*s != 'r' &&
00897 *s != 'f' &&
00898 *s != 'm' &&
00899 *s != '+' &&
00900 *s != ',' &&
00901 *s != '=' &&
00902 (*s < '0' ||
00903 *s > '9')) {
00904 return FALSE;
00905 }
00906 ++s;
00907 }
00908 return TRUE;
00909 }
00910
00911 ST *
00912 st_of_new_temp_for_expr(const WN *expr)
00913 {
00914 static unsigned int temp_count = 0;
00915
00916 static char temp_name[64];
00917
00918 sprintf(temp_name, "asm.by.address.temp_%u", temp_count++);
00919
00920 ST *retval = New_ST(CURRENT_SYMTAB);
00921
00922 ST_Init (retval,
00923 Save_Str (temp_name),
00924 CLASS_VAR,
00925 SCLASS_AUTO,
00926 EXPORT_LOCAL,
00927 MTYPE_To_TY(WN_rtype(expr)));
00928 return retval;
00929 }
00930
00931
00932
00933
00934 static char *operand_constraint_array[MAX_RECOG_OPERANDS];
00935
00936 static BOOL
00937 constraint_by_address (const char *s)
00938 {
00939 #ifndef TARG_X8664
00940 if (strchr (s, 'm')) {
00941 #else
00942 if (strchr (s, 'm') || strchr (s, 'g')) {
00943 #endif
00944 return TRUE;
00945 }
00946 else if (isdigit(*s)) {
00947 return constraint_by_address (operand_constraint_array[*s - '0']);
00948 }
00949 else {
00950 return FALSE;
00951 }
00952 }
00953
00954 #ifdef KEY
00955
00956 static void
00957 update_opnd_num(int *opnd_num_map, char *constraint_string)
00958 {
00959 char *p;
00960
00961 for (p = constraint_string; *p != '\0'; p++) {
00962 if (*p >= '0' &&
00963 *p <= '9') {
00964 unsigned int old_opnd_num = *p - '0';
00965 unsigned int new_opnd_num = opnd_num_map[old_opnd_num];
00966 Is_True(new_opnd_num >= 0 && new_opnd_num <= old_opnd_num,
00967 ("update_opnd_num: bad opnd numbers map"));
00968 *p = new_opnd_num + '0';
00969 }
00970 }
00971 }
00972 #endif
00973
00974 static WN *
00975 add_offset(WN_OFFSET ofst,
00976 WN *address)
00977 {
00978 return WN_Binary(OPR_ADD, Pointer_Mtype,
00979 WN_Intconst(MTYPE_I8, ofst),
00980 address);
00981 }
00982
00983 static WN *
00984 address_of (const WN *wn)
00985 {
00986 if (WN_operator(wn) == OPR_ILOAD ||
00987 WN_operator(wn) == OPR_MLOAD) {
00988 return add_offset(WN_offset(wn), WN_kid0(wn));
00989 }
00990 else if ((WN_operator(wn) == OPR_LDID) &&
00991 (ST_sclass(WN_st(wn)) != SCLASS_REG)) {
00992 return WN_Lda (Pointer_Mtype,
00993 WN_offset(wn),
00994 WN_st(wn),
00995 (UINT) 0);
00996 }
00997
00998 return NULL;
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 PREG_NUM asm_neg_preg = -2;
01018
01019 void
01020 Wfe_Expand_Asm_Operands (tree string,
01021 tree outputs,
01022 tree inputs,
01023 tree clobbers,
01024 int vol,
01025 const char *filename,
01026 int line)
01027 {
01028
01029
01030
01031
01032
01033
01034
01035
01036 int ninputs = list_length (inputs);
01037
01038 tree tail;
01039 char *constraint_string;
01040
01041 #ifdef KEY
01042
01043
01044
01045
01046
01047
01048
01049
01050 int opnd_num_map[MAX_RECOG_OPERANDS];
01051 #endif
01052
01053
01054
01055 int i = 0;
01056
01057 for (tail = outputs; tail; tail = TREE_CHAIN (tail)) {
01058 #ifdef KEY
01059
01060 opnd_num_map[i] = i;
01061
01062
01063
01064 constraint_string =
01065 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01066 #endif
01067 operand_constraint_array[i] = constraint_string;
01068 ++i;
01069 }
01070 #ifdef KEY
01071 opnd_num_map[i] = -1;
01072 #endif
01073
01074 FmtAssert(i < MAX_RECOG_OPERANDS, ("Too many asm operands"));
01075 for ( ; i < MAX_RECOG_OPERANDS; ++i) {
01076 operand_constraint_array[i] = NULL;
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 for (tail = outputs;
01093 tail;
01094 tail = TREE_CHAIN (tail))
01095 {
01096 #ifdef KEY
01097
01098
01099 constraint_string =
01100 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01101 #endif
01102
01103 if (strchr (constraint_string, '+') ||
01104 constraint_by_address (constraint_string))
01105 {
01106 ++ninputs;
01107 }
01108 if (flag_bad_asm_constraint_kills_stmt &&
01109 !constraint_supported (constraint_string)) {
01110 DevWarn ("Unrecognized constraint %s; "
01111 "asm statement at line %d discarded",
01112 constraint_string, lineno);
01113 return;
01114 }
01115 }
01116
01117 WN *asm_wn = WN_CreateAsm_Stmt (ninputs + 2,
01118 const_cast<char*>TREE_STRING_POINTER (string));
01119
01120 WN *clobber_block = WN_CreateBlock ();
01121
01122 WN_kid0(asm_wn) = clobber_block;
01123
01124 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
01125 {
01126 char *clobber_string =
01127 const_cast<char*>TREE_STRING_POINTER (TREE_VALUE (tail));
01128
01129 WN *clobber_pragma = NULL;
01130
01131 int gcc_reg = decode_reg_name(clobber_string);
01132 if (gcc_reg == -3)
01133 WN_Set_Asm_Clobbers_Cc(asm_wn);
01134 else if (gcc_reg == -4)
01135 WN_Set_Asm_Clobbers_Mem(asm_wn);
01136 else {
01137 WN *clobbered_idname = idname_from_regnum (gcc_reg);
01138
01139 if (clobbered_idname) {
01140
01141
01142
01143 ST *clobber_st = New_ST(CURRENT_SYMTAB);
01144 ST_Init(clobber_st,
01145 Str_To_Index (Save_Str (clobber_string),
01146 Current_Strtab),
01147 CLASS_NAME,
01148 SCLASS_UNKNOWN,
01149 EXPORT_LOCAL,
01150 (TY_IDX) 0);
01151
01152 clobber_pragma = WN_CreateXpragma (WN_PRAGMA_ASM_CLOBBER,
01153 ST_st_idx(clobber_st),
01154 1);
01155 WN_kid0 (clobber_pragma) = clobbered_idname;
01156 }
01157 else {
01158
01159
01160
01161
01162 ST *clobber_st = New_ST(CURRENT_SYMTAB);
01163 ST_Init(clobber_st,
01164 Str_To_Index (Save_Str (clobber_string),
01165 Current_Strtab),
01166 CLASS_NAME,
01167 SCLASS_UNKNOWN,
01168 EXPORT_LOCAL,
01169 (TY_IDX) 0);
01170
01171 clobber_pragma = WN_CreatePragma (WN_PRAGMA_ASM_CLOBBER,
01172 ST_st_idx(clobber_st),
01173 (INT32) 0,
01174 (INT32) 0);
01175
01176 WN_Set_Asm_Volatile (asm_wn);
01177 }
01178 }
01179
01180 if (clobber_pragma != NULL)
01181 WN_INSERT_BlockAfter (clobber_block,
01182 WN_last (clobber_block),
01183 clobber_pragma);
01184 }
01185
01186 WN *output_constraint_block = WN_CreateBlock ();
01187
01188 WN_kid1(asm_wn) = output_constraint_block;
01189
01190 i = 2;
01191
01192
01193
01194
01195 UINT32 opnd_num = 0;
01196
01197 for (tail = outputs;
01198 tail;
01199 tail = TREE_CHAIN (tail))
01200 {
01201 #ifdef KEY
01202
01203
01204 constraint_string =
01205 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01206 #endif
01207
01208 if (constraint_by_address(constraint_string)) {
01209
01210
01211 WN *lhs_rvalue = WFE_Expand_Expr(TREE_OPERAND(tail, 0));
01212 WN *addr_of_lvalue = address_of(lhs_rvalue);
01213 FmtAssert(addr_of_lvalue != NULL,
01214 ("WFE_Expand_Asm_Operands: output operand must be lvalue"));
01215 WN_kid (asm_wn, i) =
01216 WN_CreateAsm_Input (constraint_string, opnd_num, addr_of_lvalue);
01217 ++i;
01218 #ifdef KEY
01219
01220
01221 for (int j = opnd_num + 1; opnd_num_map[j] != -1; j++) {
01222 opnd_num_map[j]--;
01223 }
01224 #endif
01225 }
01226 ++opnd_num;
01227 }
01228
01229 for (tail = inputs;
01230 tail;
01231 tail = TREE_CHAIN (tail))
01232 {
01233 if (TREE_PURPOSE (tail) == NULL_TREE)
01234 {
01235 Fail_FmtAssertion ("hard register `%s' listed as "
01236 "input operand to `asm'",
01237 TREE_STRING_POINTER (TREE_VALUE (tail)) );
01238 return;
01239 }
01240
01241 #ifdef KEY
01242
01243
01244 constraint_string =
01245 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01246 #endif
01247
01248 if (flag_bad_asm_constraint_kills_stmt &&
01249 !constraint_supported (constraint_string)) {
01250 DevWarn ("Unrecognized constraint %s; "
01251 "asm statement at line %d discarded",
01252 constraint_string, lineno);
01253 return;
01254 }
01255
01256 WN *input_rvalue = WFE_Expand_Expr (TREE_VALUE (tail));
01257
01258 if (constraint_by_address(constraint_string)) {
01259 WN *addr_of_rvalue = address_of(input_rvalue);
01260 if (addr_of_rvalue != NULL) {
01261
01262
01263 input_rvalue = addr_of_rvalue;
01264 }
01265 else {
01266
01267
01268 ST *temp_st = st_of_new_temp_for_expr(input_rvalue);
01269 WN *store_wn = WN_Stid(WN_rtype(input_rvalue),
01270 (WN_OFFSET) 0,
01271 temp_st,
01272
01273
01274
01275
01276
01277 MTYPE_To_TY(WN_rtype(input_rvalue)),
01278 input_rvalue);
01279 WFE_Stmt_Append (store_wn, Get_Srcpos ());
01280 input_rvalue = WN_Lda (Pointer_Mtype,
01281 (WN_OFFSET) 0,
01282 temp_st,
01283 (UINT) 0);
01284 }
01285 }
01286
01287 #ifndef TARG_NVISA // ptx f is for 32bit float
01288 #ifdef PATHSCALE_MERGE
01289
01290
01291
01292
01293
01294
01295 if (*constraint_string == 'f') {
01296 TYPE_ID rtype = (input_rvalue != NULL ? WN_rtype(input_rvalue) : MTYPE_F8);
01297 Is_True(MTYPE_bit_size(rtype) >= 64, ("bit size must equal or greater than 64"));
01298 if (WN_rtype(input_rvalue) == MTYPE_U8 || WN_rtype(input_rvalue) == MTYPE_I8) {
01299 input_rvalue = WN_CreateExp1(OPR_CVT, MTYPE_F8, WN_rtype(input_rvalue), input_rvalue);
01300 }
01301 }
01302 #endif
01303 #endif
01304 #ifdef KEY
01305
01306 update_opnd_num(opnd_num_map, constraint_string);
01307 #endif
01308
01309 WN_kid (asm_wn, i) =
01310 WN_CreateAsm_Input (constraint_string, opnd_num, input_rvalue);
01311 ++i;
01312 ++opnd_num;
01313 }
01314
01315
01316 WFE_Stmt_Append (asm_wn, Get_Srcpos ());
01317
01318
01319
01320 opnd_num = 0;
01321 #ifdef KEY
01322
01323
01324
01325
01326
01327
01328 INT nonmem_opnd_num = 0;
01329 #endif
01330 for (tail = outputs;
01331 tail;
01332 tail = TREE_CHAIN (tail), ++opnd_num)
01333 {
01334 #ifdef KEY
01335
01336
01337 constraint_string =
01338 const_cast<char*>TREE_STRING_POINTER (TREE_OPERAND (TREE_PURPOSE (tail), 0));
01339 #endif
01340
01341 if (!constraint_by_address(constraint_string)) {
01342
01343
01344 BOOL plus_modifier = (strchr (constraint_string, '+') != NULL);
01345
01346 char input_opnd_constraint[8];
01347 tree output = TREE_VALUE(tail);
01348
01349 #ifdef KEY // otherwise, WFE_Lhs_Of_Modify_Expr can't handle NOP_EXPR
01350 STRIP_NOPS(output);
01351 while (TREE_CODE (output) == NOP_EXPR
01352 || TREE_CODE (output) == CONVERT_EXPR
01353 || TREE_CODE (output) == FLOAT_EXPR
01354 || TREE_CODE (output) == FIX_TRUNC_EXPR
01355 || TREE_CODE (output) == FIX_FLOOR_EXPR
01356 || TREE_CODE (output) == FIX_ROUND_EXPR
01357 || TREE_CODE (output) == FIX_CEIL_EXPR)
01358 output = TREE_OPERAND (output, 0);
01359 #endif
01360 #ifdef PATHSCALE_MERGE
01361
01362
01363 if (strchr (constraint_string, 'f') != NULL) {
01364 TY_IDX hi_ty_idx = Get_TY(TREE_TYPE(output));
01365
01366 TYPE_ID rtype = TY_mtype(hi_ty_idx);
01367 #ifdef TARG_NVISA
01368
01369 if (rtype == MTYPE_U4 || rtype == MTYPE_I4) {
01370 Set_TY_mtype(hi_ty_idx, MTYPE_F4);
01371 }
01372 #else
01373 Is_True(MTYPE_bit_size(rtype) >= 64, ("bit size must equal or greater than 64"));
01374 #endif
01375 if (rtype == MTYPE_U8 || rtype == MTYPE_I8) {
01376 Set_TY_mtype(hi_ty_idx, MTYPE_F8);
01377 }
01378 }
01379
01380 #endif
01381 if (plus_modifier)
01382 {
01383
01384 constraint_string = remove_plus_modifier(constraint_string);
01385
01386
01387
01388 #ifdef KEY
01389 sprintf(input_opnd_constraint, "%d", nonmem_opnd_num);
01390 #else
01391 sprintf(input_opnd_constraint, "%d", opnd_num);
01392 #endif
01393 }
01394 #ifdef KEY
01395 nonmem_opnd_num ++;
01396 #endif
01397
01398 WN *output_rvalue_wn = WFE_Lhs_Of_Modify_Expr (MODIFY_EXPR,
01399 output,
01400 #ifdef TARG_SL
01401 NULL,
01402 #endif
01403 plus_modifier,
01404 (TY_IDX) 0,
01405 (INT64) 0,
01406 (UINT32) 0,
01407 FALSE,
01408 NULL,
01409 asm_neg_preg,
01410 FALSE,
01411 FALSE);
01412
01413 if (plus_modifier)
01414 {
01415 WN_kid (asm_wn, i) =
01416 WN_CreateAsm_Input (input_opnd_constraint,
01417 opnd_num,
01418 output_rvalue_wn);
01419 ++i;
01420 }
01421
01422
01423
01424
01425 TYPE_ID desc = TY_mtype (Get_TY (TREE_TYPE (TREE_VALUE (tail))));
01426 #ifdef PATHSCALE_MERGE
01427
01428
01429 if (strchr (constraint_string, 'f') != NULL) {
01430 #ifdef TARG_NVISA
01431
01432 if (MTYPE_bit_size(desc) == 32)
01433 desc = MTYPE_F4;
01434 else
01435 desc = MTYPE_F8;
01436 #else
01437 Is_True(MTYPE_bit_size(desc) >= 64, ("bit size must equal or greater than 64"));
01438 #endif
01439 desc = MTYPE_F8;
01440 }
01441 #endif
01442 ST *preg_st = MTYPE_To_PREG(desc);
01443
01444 ST *constraint_st = New_ST(CURRENT_SYMTAB);
01445 ST_Init(constraint_st,
01446 Str_To_Index (Save_Str (constraint_string),
01447 Current_Strtab),
01448 CLASS_NAME,
01449 SCLASS_UNKNOWN,
01450 EXPORT_LOCAL,
01451 (TY_IDX) 0);
01452
01453 WN *constraint_pragma =
01454 WN_CreatePragma (WN_PRAGMA_ASM_CONSTRAINT,
01455 (ST_IDX) ST_st_idx(preg_st),
01456 (INT32) ST_st_idx(constraint_st),
01457 asm_neg_preg,
01458 opnd_num);
01459
01460 WN_INSERT_BlockAfter (output_constraint_block,
01461 WN_last (output_constraint_block),
01462 constraint_pragma);
01463 --asm_neg_preg;
01464 }
01465 }
01466
01467 if (vol)
01468 {
01469 WN_Set_Asm_Volatile (asm_wn);
01470 }
01471 }
01472
01473
01474
01475 void
01476 WFE_Check_Undefined_Labels (void)
01477 {
01478 INT32 i;
01479 #ifdef KEY // bug 6152
01480 INT error_count, sorry_count;
01481
01482 check_gnu_errors (&error_count, &sorry_count);
01483 if (error_count || sorry_count)
01484 {
01485 undefined_labels_i = 0;
01486 return;
01487 }
01488 #endif
01489
01490 for (i = undefined_labels_i; i >= 0; --i) {
01491 LABEL_IDX label_idx = undefined_labels_stack [undefined_labels_i].label_idx;
01492 SYMTAB_IDX symtab_idx = undefined_labels_stack [undefined_labels_i].symtab_idx;
01493
01494 if (symtab_idx < CURRENT_SYMTAB)
01495 break;
01496 FmtAssert (undefined_labels_stack [undefined_labels_i].defined,
01497 ("label not defined within current function scope"));
01498 }
01499 undefined_labels_i = i;
01500 }
01501 #ifdef KEY
01502
01503
01504 int
01505 WFE_Emit_Side_Effects_Pending (tree* node)
01506 {
01507 if ( TREE_CODE(*node) == POSTINCREMENT_EXPR ||
01508 TREE_CODE(*node) == POSTDECREMENT_EXPR )
01509 WFE_One_Stmt(*node);
01510
01511 return 0;
01512 }
01513
01514 int
01515 WFE_Null_ST_References (tree* node)
01516 {
01517 if ( TREE_CODE (*node) == VAR_DECL )
01518 {
01519 #ifdef PATHSCALE_MERGE
01520
01521 if(DECL_ST (*node)==NULL)
01522 return 0;
01523 #endif
01524 #if defined(TARG_SL)
01525 if (DECL_ST (*node)) {
01526 #endif
01527 ST_SCLASS sc = ST_sclass (DECL_ST (*node));
01528
01529
01530 if ( sc != SCLASS_DGLOBAL &&
01531 sc != SCLASS_EXTERN &&
01532 sc != SCLASS_FSTATIC &&
01533 sc != SCLASS_UGLOBAL &&
01534 sc != SCLASS_COMMON )
01535 DECL_ST(*node) = NULL;
01536 }
01537 #if defined(TARG_SL)
01538 }
01539 #endif
01540
01541 return 0;
01542 }
01543
01544
01545 void
01546 WFE_Start_Do_Loop (struct nesting * whichloop)
01547 {
01548 if (++loop_info_i == loop_info_max) {
01549
01550 loop_info_max = ENLARGE(loop_info_max);
01551 loop_info_stack = (LOOP_INFO *) realloc (loop_info_stack,
01552 loop_info_max * sizeof (LOOP_INFO));
01553 }
01554
01555 loop_info_stack [loop_info_i].whichloop = whichloop;
01556 loop_info_stack [loop_info_i].continue_info = CONTINUE_NONE;
01557 loop_info_stack [loop_info_i].continue_label_idx = 0;
01558 loop_info_stack [loop_info_i].exit_label_idx = 0;
01559 loop_info_stack [loop_info_i].exit_loop_if_false = FALSE;
01560 loop_info_stack [loop_info_i].continue_here = FALSE;
01561
01562 LABEL_IDX continue_label_idx;
01563 New_LABEL (CURRENT_SYMTAB, continue_label_idx);
01564 loop_info_stack [loop_info_i].continue_label_idx = continue_label_idx;
01565
01566 }
01567
01568
01569 void
01570 WFE_End_Do_Loop (struct nesting * whichloop)
01571 {
01572 FmtAssert (loop_info_i >= 0, ("WFE_End_Do_Loop: no loops"));
01573 FmtAssert (loop_info_stack [loop_info_i].whichloop == whichloop,
01574 ("WFE_End_Do_Loop: loop mismatch"));
01575
01576 WFE_Stmt_Append (
01577 WN_CreateLabel ((ST_IDX) 0,
01578 loop_info_stack [loop_info_i].continue_label_idx,
01579 0, NULL), Get_Srcpos());
01580
01581 }
01582
01583
01584 void
01585 WFE_Terminate_Do_Loop (struct nesting * whichloop)
01586 {
01587 FmtAssert (loop_info_i >= 0, ("WFE_Terminate_Do_Loop: no loops"));
01588 FmtAssert (loop_info_stack [loop_info_i].whichloop == whichloop,
01589 ("WFE_Terminate_Do_Loop: loop mismatch"));
01590
01591
01592 if (loop_info_stack [loop_info_i].exit_label_idx)
01593 WFE_Stmt_Append (
01594 WN_CreateLabel ((ST_IDX) 0,
01595 loop_info_stack [loop_info_i].exit_label_idx,
01596 0, NULL), Get_Srcpos());
01597 --loop_info_i;
01598 }
01599
01600
01601
01602
01603
01604 void
01605 WFE_Expand_Pragma (tree exp)
01606 {
01607 switch (exp->omp.choice)
01608 {
01609 case options_dir:
01610 {
01611 TCON tcon;
01612 exp = (tree) exp->omp.omp_clause_list;
01613 tcon = Host_To_Targ_String (MTYPE_STRING,
01614 const_cast<char*>TREE_STRING_POINTER(exp),
01615 TREE_STRING_LENGTH(exp) - 1 );
01616 TY_IDX ty_idx = Get_TY(TREE_TYPE(exp));
01617 ST * st = New_Const_Sym (Enter_tcon (tcon), ty_idx);
01618 TREE_STRING_ST (exp) = st;
01619 WN * wn = WN_CreatePragma (WN_PRAGMA_OPTIONS, st, 0, 0);
01620 WN * func_wn = WFE_Find_Stmt_In_Stack (wfe_stmk_func_entry);
01621 WN_INSERT_BlockLast (WN_func_pragmas(func_wn), wn);
01622 break;
01623 }
01624 case exec_freq_dir:
01625 {
01626 MIPS_FREQUENCY_HINT freq_hint;
01627 Is_True (TREE_CODE ((tree) exp->omp.omp_clause_list) == STRING_CST,
01628 ("Expected string constant with mips_frequency_hint"));
01629 const char * hint = TREE_STRING_POINTER ((tree) exp->omp.omp_clause_list);
01630
01631 if (!strcmp (hint, "never")) freq_hint = FREQUENCY_HINT_NEVER;
01632 else if (!strcmp (hint, "init")) freq_hint = FREQUENCY_HINT_INIT;
01633 else if (!strcmp (hint, "frequent")) freq_hint = FREQUENCY_HINT_FREQUENT;
01634 else
01635 break;
01636
01637 WN * wn = WN_CreatePragma (WN_PRAGMA_MIPS_FREQUENCY_HINT, (ST*)NULL, freq_hint, 0);
01638 WFE_Stmt_Append (wn, Get_Srcpos());
01639 break;
01640 }
01641 case unroll_dir:
01642 {
01643 UINT32 num;
01644 exp = (tree) exp->omp.omp_clause_list;
01645 if (exp) {
01646 FmtAssert(TREE_CODE(exp) == INTEGER_CST, ("unroll arg not an integer constant?"));
01647 num = Get_Integer_Value(exp);
01648 }
01649 else {
01650
01651 num = UINT32_MAX;
01652 }
01653 WN * wn = WN_CreatePragma (WN_PRAGMA_UNROLL, (ST*)NULL, num, 0);
01654 WFE_Stmt_Append (wn, Get_Srcpos());
01655 break;
01656 }
01657 }
01658 }
01659 #endif
01660
01661 void
01662 WFE_Expand_Freq_Hint (tree exp) {
01663
01664 tree hint_opnd = TREE_OPERAND(exp, 0);
01665 Is_True (TREE_CODE (hint_opnd) == STRING_CST,
01666 ("the first operand of FREQ_HINT_STMT should be STRING_CST"));
01667
01668 MIPS_FREQUENCY_HINT hint_id;
01669 const char* hint_name = TREE_STRING_POINTER (hint_opnd);
01670
01671 if (!strcmp (hint_name, "never")) {
01672 hint_id = FREQUENCY_HINT_NEVER;
01673 } else if (!strcmp (hint_name, "init")) {
01674 hint_id = FREQUENCY_HINT_INIT;
01675 } else if (!strcmp (hint_name, "frequent")) {
01676 hint_id = FREQUENCY_HINT_FREQUENT;
01677 } else {
01678 Is_True (FALSE, ("unrecognized frequency hint '%s'", hint_name));
01679 }
01680
01681 WN* wn = WN_CreatePragma (WN_PRAGMA_MIPS_FREQUENCY_HINT, (ST*)NULL, hint_id, 0);
01682 WFE_Stmt_Append (wn, Get_Srcpos());
01683 }
01684