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 #include "config.h"
00029 #include "system.h"
00030 #include "coretypes.h"
00031 #include "tm.h"
00032
00033 #include "rtl.h"
00034 #include "tree.h"
00035 #include "tm_p.h"
00036 #include "flags.h"
00037 #include "except.h"
00038 #include "function.h"
00039 #include "insn-config.h"
00040 #include "expr.h"
00041 #include "libfuncs.h"
00042 #include "hard-reg-set.h"
00043 #include "recog.h"
00044 #include "machmode.h"
00045 #include "toplev.h"
00046 #include "output.h"
00047 #include "ggc.h"
00048 #include "langhooks.h"
00049 #include "predict.h"
00050 #include "optabs.h"
00051 #include "target.h"
00052 #include "regs.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 struct case_node GTY(())
00084 {
00085 struct case_node *left;
00086 struct case_node *right;
00087 struct case_node *parent;
00088 tree low;
00089 tree high;
00090 tree code_label;
00091 };
00092
00093 typedef struct case_node case_node;
00094 typedef struct case_node *case_node_ptr;
00095
00096
00097
00098
00099 static short cost_table_[129];
00100 static int use_cost_table;
00101 static int cost_table_initialized;
00102
00103
00104
00105 #define COST_TABLE(I) cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
00106
00107 static int n_occurrences (int, const char *);
00108 static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
00109 static void expand_nl_goto_receiver (void);
00110 static bool check_operand_nalternatives (tree, tree);
00111 static bool check_unique_operand_names (tree, tree);
00112 static char *resolve_operand_name_1 (char *, tree, tree);
00113 static void expand_null_return_1 (void);
00114 static void expand_value_return (rtx);
00115 static void do_jump_if_equal (rtx, rtx, rtx, int);
00116 static int estimate_case_costs (case_node_ptr);
00117 static bool lshift_cheap_p (void);
00118 static int case_bit_test_cmp (const void *, const void *);
00119 static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, rtx);
00120 static void balance_case_nodes (case_node_ptr *, case_node_ptr);
00121 static int node_has_low_bound (case_node_ptr, tree);
00122 static int node_has_high_bound (case_node_ptr, tree);
00123 static int node_is_bounded (case_node_ptr, tree);
00124 static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
00125 static struct case_node *add_case_node (struct case_node *, tree,
00126 tree, tree, tree);
00127
00128
00129
00130
00131
00132 rtx
00133 label_rtx (tree label)
00134 {
00135 gcc_assert (TREE_CODE (label) == LABEL_DECL);
00136
00137 if (!DECL_RTL_SET_P (label))
00138 {
00139 rtx r = gen_label_rtx ();
00140 SET_DECL_RTL (label, r);
00141 if (FORCED_LABEL (label) || DECL_NONLOCAL (label))
00142 LABEL_PRESERVE_P (r) = 1;
00143 }
00144
00145 return DECL_RTL (label);
00146 }
00147
00148
00149
00150 rtx
00151 force_label_rtx (tree label)
00152 {
00153 rtx ref = label_rtx (label);
00154 tree function = decl_function_context (label);
00155 struct function *p;
00156
00157 gcc_assert (function);
00158
00159 if (function != current_function_decl)
00160 p = find_function_data (function);
00161 else
00162 p = cfun;
00163
00164 p->expr->x_forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref,
00165 p->expr->x_forced_labels);
00166 return ref;
00167 }
00168
00169
00170
00171 void
00172 emit_jump (rtx label)
00173 {
00174 do_pending_stack_adjust ();
00175 emit_jump_insn (gen_jump (label));
00176 emit_barrier ();
00177 }
00178
00179
00180
00181
00182 void
00183 expand_computed_goto (tree exp)
00184 {
00185 rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
00186
00187 x = convert_memory_address (Pmode, x);
00188
00189 do_pending_stack_adjust ();
00190 emit_indirect_jump (x);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 void
00207 expand_label (tree label)
00208 {
00209 rtx label_r = label_rtx (label);
00210
00211 do_pending_stack_adjust ();
00212 emit_label (label_r);
00213 if (DECL_NAME (label))
00214 LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label));
00215
00216 if (DECL_NONLOCAL (label))
00217 {
00218 expand_nl_goto_receiver ();
00219 nonlocal_goto_handler_labels
00220 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
00221 nonlocal_goto_handler_labels);
00222 }
00223
00224 if (FORCED_LABEL (label))
00225 forced_labels = gen_rtx_EXPR_LIST (VOIDmode, label_r, forced_labels);
00226
00227 if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
00228 maybe_set_first_label_num (label_r);
00229 }
00230
00231
00232
00233
00234
00235 void
00236 expand_goto (tree label)
00237 {
00238 #ifdef ENABLE_CHECKING
00239
00240
00241 tree context = decl_function_context (label);
00242 gcc_assert (!context || context == current_function_decl);
00243 #endif
00244
00245 emit_jump (label_rtx (label));
00246 }
00247
00248
00249 static int
00250 n_occurrences (int c, const char *s)
00251 {
00252 int n = 0;
00253 while (*s)
00254 n += (*s++ == c);
00255 return n;
00256 }
00257
00258
00259
00260
00261
00262
00263 static void
00264 expand_asm (tree string, int vol)
00265 {
00266 rtx body;
00267
00268 if (TREE_CODE (string) == ADDR_EXPR)
00269 string = TREE_OPERAND (string, 0);
00270
00271 body = gen_rtx_ASM_INPUT (VOIDmode,
00272 ggc_strdup (TREE_STRING_POINTER (string)));
00273
00274 MEM_VOLATILE_P (body) = vol;
00275
00276 emit_insn (body);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 bool
00293 parse_output_constraint (const char **constraint_p, int operand_num,
00294 int ninputs, int noutputs, bool *allows_mem,
00295 bool *allows_reg, bool *is_inout)
00296 {
00297 const char *constraint = *constraint_p;
00298 const char *p;
00299
00300
00301
00302 *allows_mem = false;
00303 *allows_reg = false;
00304
00305
00306
00307
00308
00309 p = strchr (constraint, '=');
00310 if (!p)
00311 p = strchr (constraint, '+');
00312
00313
00314
00315 if (!p)
00316 {
00317 error ("output operand constraint lacks %<=%>");
00318 return false;
00319 }
00320
00321
00322
00323 *is_inout = (*p == '+');
00324
00325
00326 if (p != constraint || *is_inout)
00327 {
00328 char *buf;
00329 size_t c_len = strlen (constraint);
00330
00331 if (p != constraint)
00332 warning ("output constraint %qc for operand %d "
00333 "is not at the beginning",
00334 *p, operand_num);
00335
00336
00337 buf = alloca (c_len + 1);
00338 strcpy (buf, constraint);
00339
00340 buf[p - constraint] = buf[0];
00341
00342
00343 buf[0] = '=';
00344
00345 *constraint_p = ggc_alloc_string (buf, c_len);
00346 constraint = *constraint_p;
00347 }
00348
00349
00350 for (p = constraint + 1; *p; p += CONSTRAINT_LEN (*p, p))
00351 switch (*p)
00352 {
00353 case '+':
00354 case '=':
00355 error ("operand constraint contains incorrectly positioned "
00356 "%<+%> or %<=%>");
00357 return false;
00358
00359 case '%':
00360 if (operand_num + 1 == ninputs + noutputs)
00361 {
00362 error ("%<%%%> constraint used with last operand");
00363 return false;
00364 }
00365 break;
00366
00367 case 'V': case 'm': case 'o':
00368 *allows_mem = true;
00369 break;
00370
00371 case '?': case '!': case '*': case '&': case '#':
00372 case 'E': case 'F': case 'G': case 'H':
00373 case 's': case 'i': case 'n':
00374 case 'I': case 'J': case 'K': case 'L': case 'M':
00375 case 'N': case 'O': case 'P': case ',':
00376 break;
00377
00378 case '0': case '1': case '2': case '3': case '4':
00379 case '5': case '6': case '7': case '8': case '9':
00380 case '[':
00381 error ("matching constraint not valid in output operand");
00382 return false;
00383
00384 case '<': case '>':
00385
00386
00387
00388 *allows_mem = true;
00389 break;
00390
00391 case 'g': case 'X':
00392 *allows_reg = true;
00393 *allows_mem = true;
00394 break;
00395
00396 case 'p': case 'r':
00397 *allows_reg = true;
00398 break;
00399
00400 default:
00401 if (!ISALPHA (*p))
00402 break;
00403 if (REG_CLASS_FROM_CONSTRAINT (*p, p) != NO_REGS)
00404 *allows_reg = true;
00405 #ifdef EXTRA_CONSTRAINT_STR
00406 else if (EXTRA_ADDRESS_CONSTRAINT (*p, p))
00407 *allows_reg = true;
00408 else if (EXTRA_MEMORY_CONSTRAINT (*p, p))
00409 *allows_mem = true;
00410 else
00411 {
00412
00413
00414
00415 *allows_reg = true;
00416 *allows_mem = true;
00417 }
00418 #endif
00419 break;
00420 }
00421
00422 return true;
00423 }
00424
00425
00426
00427 bool
00428 parse_input_constraint (const char **constraint_p, int input_num,
00429 int ninputs, int noutputs, int ninout,
00430 const char * const * constraints,
00431 bool *allows_mem, bool *allows_reg)
00432 {
00433 const char *constraint = *constraint_p;
00434 const char *orig_constraint = constraint;
00435 size_t c_len = strlen (constraint);
00436 size_t j;
00437 bool saw_match = false;
00438
00439
00440
00441 *allows_mem = false;
00442 *allows_reg = false;
00443
00444
00445
00446 for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j))
00447 switch (constraint[j])
00448 {
00449 case '+': case '=': case '&':
00450 if (constraint == orig_constraint)
00451 {
00452 error ("input operand constraint contains %qc", constraint[j]);
00453 return false;
00454 }
00455 break;
00456
00457 case '%':
00458 if (constraint == orig_constraint
00459 && input_num + 1 == ninputs - ninout)
00460 {
00461 error ("%<%%%> constraint used with last operand");
00462 return false;
00463 }
00464 break;
00465
00466 case 'V': case 'm': case 'o':
00467 *allows_mem = true;
00468 break;
00469
00470 case '<': case '>':
00471 case '?': case '!': case '*': case '#':
00472 case 'E': case 'F': case 'G': case 'H':
00473 case 's': case 'i': case 'n':
00474 case 'I': case 'J': case 'K': case 'L': case 'M':
00475 case 'N': case 'O': case 'P': case ',':
00476 break;
00477
00478
00479
00480
00481
00482
00483 case '0': case '1': case '2': case '3': case '4':
00484 case '5': case '6': case '7': case '8': case '9':
00485 {
00486 char *end;
00487 unsigned long match;
00488
00489 saw_match = true;
00490
00491 match = strtoul (constraint + j, &end, 10);
00492 if (match >= (unsigned long) noutputs)
00493 {
00494 error ("matching constraint references invalid operand number");
00495 return false;
00496 }
00497
00498
00499
00500 if (*end == '\0'
00501 && (j == 0 || (j == 1 && constraint[0] == '%')))
00502 {
00503 constraint = constraints[match];
00504 *constraint_p = constraint;
00505 c_len = strlen (constraint);
00506 j = 0;
00507
00508
00509
00510
00511 break;
00512 }
00513 else
00514 j = end - constraint;
00515
00516 j--;
00517 }
00518
00519
00520 case 'p': case 'r':
00521 *allows_reg = true;
00522 break;
00523
00524 case 'g': case 'X':
00525 *allows_reg = true;
00526 *allows_mem = true;
00527 break;
00528
00529 default:
00530 if (! ISALPHA (constraint[j]))
00531 {
00532 error ("invalid punctuation %qc in constraint", constraint[j]);
00533 return false;
00534 }
00535 if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
00536 != NO_REGS)
00537 *allows_reg = true;
00538 #ifdef EXTRA_CONSTRAINT_STR
00539 else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j], constraint + j))
00540 *allows_reg = true;
00541 else if (EXTRA_MEMORY_CONSTRAINT (constraint[j], constraint + j))
00542 *allows_mem = true;
00543 else
00544 {
00545
00546
00547
00548 *allows_reg = true;
00549 *allows_mem = true;
00550 }
00551 #endif
00552 break;
00553 }
00554
00555 if (saw_match && !*allows_reg)
00556 warning ("matching constraint does not allow a register");
00557
00558 return true;
00559 }
00560
00561
00562
00563
00564
00565 static bool
00566 decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
00567 {
00568
00569
00570 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
00571 && DECL_REGISTER (decl)
00572 && REG_P (DECL_RTL (decl))
00573 && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
00574 {
00575 rtx reg = DECL_RTL (decl);
00576 unsigned int regno;
00577
00578 for (regno = REGNO (reg);
00579 regno < (REGNO (reg)
00580 + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
00581 regno++)
00582 if (TEST_HARD_REG_BIT (clobbered_regs, regno))
00583 {
00584 error ("asm-specifier for variable %qs conflicts with "
00585 "asm clobber list",
00586 IDENTIFIER_POINTER (DECL_NAME (decl)));
00587
00588
00589
00590 DECL_REGISTER (decl) = 0;
00591 return true;
00592 }
00593 }
00594 return false;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static void
00615 expand_asm_operands (tree string, tree outputs, tree inputs,
00616 tree clobbers, int vol, location_t locus)
00617 {
00618 rtvec argvec, constraintvec;
00619 rtx body;
00620 int ninputs = list_length (inputs);
00621 int noutputs = list_length (outputs);
00622 int ninout;
00623 int nclobbers;
00624 HARD_REG_SET clobbered_regs;
00625 int clobber_conflict_found = 0;
00626 tree tail;
00627 tree t;
00628 int i;
00629
00630 rtx *output_rtx = alloca (noutputs * sizeof (rtx));
00631 int *inout_opnum = alloca (noutputs * sizeof (int));
00632 rtx *real_output_rtx = alloca (noutputs * sizeof (rtx));
00633 enum machine_mode *inout_mode
00634 = alloca (noutputs * sizeof (enum machine_mode));
00635 const char **constraints
00636 = alloca ((noutputs + ninputs) * sizeof (const char *));
00637 int old_generating_concat_p = generating_concat_p;
00638
00639
00640 if (noutputs == 0)
00641 vol = 1;
00642
00643 if (! check_operand_nalternatives (outputs, inputs))
00644 return;
00645
00646 string = resolve_asm_operand_names (string, outputs, inputs);
00647
00648
00649 i = 0;
00650 for (t = outputs; t ; t = TREE_CHAIN (t), i++)
00651 constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
00652 for (t = inputs; t ; t = TREE_CHAIN (t), i++)
00653 constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
00654
00655
00656
00657
00658
00659 clobbers = targetm.md_asm_clobbers (clobbers);
00660
00661
00662
00663 nclobbers = 0;
00664 CLEAR_HARD_REG_SET (clobbered_regs);
00665 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
00666 {
00667 const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
00668
00669 i = decode_reg_name (regname);
00670 if (i >= 0 || i == -4)
00671 ++nclobbers;
00672 else if (i == -2)
00673 error ("unknown register name %qs in %<asm%>", regname);
00674
00675
00676 if (i >= 0)
00677 {
00678
00679 if (i == (int) PIC_OFFSET_TABLE_REGNUM)
00680 {
00681 error ("PIC register %qs clobbered in %<asm%>", regname);
00682 return;
00683 }
00684
00685 SET_HARD_REG_BIT (clobbered_regs, i);
00686 }
00687 }
00688
00689
00690
00691
00692 ninout = 0;
00693 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
00694 {
00695 tree val = TREE_VALUE (tail);
00696 tree type = TREE_TYPE (val);
00697 const char *constraint;
00698 bool is_inout;
00699 bool allows_reg;
00700 bool allows_mem;
00701
00702
00703 if (type == error_mark_node)
00704 return;
00705
00706
00707
00708 constraint = constraints[i];
00709 if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
00710 &allows_mem, &allows_reg, &is_inout))
00711 return;
00712
00713 if (! allows_reg
00714 && (allows_mem
00715 || is_inout
00716 || (DECL_P (val)
00717 && REG_P (DECL_RTL (val))
00718 && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
00719 lang_hooks.mark_addressable (val);
00720
00721 if (is_inout)
00722 ninout++;
00723 }
00724
00725 ninputs += ninout;
00726 if (ninputs + noutputs > MAX_RECOG_OPERANDS)
00727 {
00728 error ("more than %d operands in %<asm%>", MAX_RECOG_OPERANDS);
00729 return;
00730 }
00731
00732 for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
00733 {
00734 bool allows_reg, allows_mem;
00735 const char *constraint;
00736
00737
00738
00739 if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
00740 return;
00741
00742 constraint = constraints[i + noutputs];
00743 if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
00744 constraints, &allows_mem, &allows_reg))
00745 return;
00746
00747 if (! allows_reg && allows_mem)
00748 lang_hooks.mark_addressable (TREE_VALUE (tail));
00749 }
00750
00751
00752
00753 ninout = 0;
00754 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
00755 {
00756 tree val = TREE_VALUE (tail);
00757 tree type = TREE_TYPE (val);
00758 bool is_inout;
00759 bool allows_reg;
00760 bool allows_mem;
00761 rtx op;
00762 bool ok;
00763
00764 ok = parse_output_constraint (&constraints[i], i, ninputs,
00765 noutputs, &allows_mem, &allows_reg,
00766 &is_inout);
00767 gcc_assert (ok);
00768
00769
00770
00771
00772
00773
00774 generating_concat_p = 0;
00775
00776 real_output_rtx[i] = NULL_RTX;
00777 if ((TREE_CODE (val) == INDIRECT_REF
00778 && allows_mem)
00779 || (DECL_P (val)
00780 && (allows_mem || REG_P (DECL_RTL (val)))
00781 && ! (REG_P (DECL_RTL (val))
00782 && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
00783 || ! allows_reg
00784 || is_inout)
00785 {
00786 op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
00787 if (MEM_P (op))
00788 op = validize_mem (op);
00789
00790 if (! allows_reg && !MEM_P (op))
00791 error ("output number %d not directly addressable", i);
00792 if ((! allows_mem && MEM_P (op))
00793 || GET_CODE (op) == CONCAT)
00794 {
00795 real_output_rtx[i] = op;
00796 op = gen_reg_rtx (GET_MODE (op));
00797 if (is_inout)
00798 emit_move_insn (op, real_output_rtx[i]);
00799 }
00800 }
00801 else
00802 {
00803 op = assign_temp (type, 0, 0, 1);
00804 op = validize_mem (op);
00805 TREE_VALUE (tail) = make_tree (type, op);
00806 }
00807 output_rtx[i] = op;
00808
00809 generating_concat_p = old_generating_concat_p;
00810
00811 if (is_inout)
00812 {
00813 inout_mode[ninout] = TYPE_MODE (type);
00814 inout_opnum[ninout++] = i;
00815 }
00816
00817 if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
00818 clobber_conflict_found = 1;
00819 }
00820
00821
00822
00823
00824 argvec = rtvec_alloc (ninputs);
00825 constraintvec = rtvec_alloc (ninputs);
00826
00827 body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
00828 : GET_MODE (output_rtx[0])),
00829 ggc_strdup (TREE_STRING_POINTER (string)),
00830 empty_string, 0, argvec, constraintvec,
00831 locus);
00832
00833 MEM_VOLATILE_P (body) = vol;
00834
00835
00836
00837
00838 for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
00839 {
00840 bool allows_reg, allows_mem;
00841 const char *constraint;
00842 tree val, type;
00843 rtx op;
00844 bool ok;
00845
00846 constraint = constraints[i + noutputs];
00847 ok = parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
00848 constraints, &allows_mem, &allows_reg);
00849 gcc_assert (ok);
00850
00851 generating_concat_p = 0;
00852
00853 val = TREE_VALUE (tail);
00854 type = TREE_TYPE (val);
00855 op = expand_expr (val, NULL_RTX, VOIDmode,
00856 (allows_mem && !allows_reg
00857 ? EXPAND_MEMORY : EXPAND_NORMAL));
00858
00859
00860 if (GET_CODE (op) == CONCAT)
00861 op = force_reg (GET_MODE (op), op);
00862 else if (MEM_P (op))
00863 op = validize_mem (op);
00864
00865 if (asm_operand_ok (op, constraint) <= 0)
00866 {
00867 if (allows_reg)
00868 op = force_reg (TYPE_MODE (type), op);
00869 else if (!allows_mem)
00870 warning ("asm operand %d probably doesn%'t match constraints",
00871 i + noutputs);
00872 else if (MEM_P (op))
00873 {
00874
00875
00876
00877 }
00878 else
00879 {
00880 warning ("use of memory input without lvalue in "
00881 "asm operand %d is deprecated", i + noutputs);
00882
00883 if (CONSTANT_P (op))
00884 {
00885 rtx mem = force_const_mem (TYPE_MODE (type), op);
00886 if (mem)
00887 op = validize_mem (mem);
00888 else
00889 op = force_reg (TYPE_MODE (type), op);
00890 }
00891 if (REG_P (op)
00892 || GET_CODE (op) == SUBREG
00893 || GET_CODE (op) == CONCAT)
00894 {
00895 tree qual_type = build_qualified_type (type,
00896 (TYPE_QUALS (type)
00897 | TYPE_QUAL_CONST));
00898 rtx memloc = assign_temp (qual_type, 1, 1, 1);
00899 memloc = validize_mem (memloc);
00900 emit_move_insn (memloc, op);
00901 op = memloc;
00902 }
00903 }
00904 }
00905
00906 generating_concat_p = old_generating_concat_p;
00907 ASM_OPERANDS_INPUT (body, i) = op;
00908
00909 ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
00910 = gen_rtx_ASM_INPUT (TYPE_MODE (type),
00911 ggc_strdup (constraints[i + noutputs]));
00912
00913 if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
00914 clobber_conflict_found = 1;
00915 }
00916
00917
00918
00919
00920 generating_concat_p = 0;
00921
00922
00923 for (i = 0; i < ninout; i++)
00924 {
00925 int j = inout_opnum[i];
00926 char buffer[16];
00927
00928 ASM_OPERANDS_INPUT (body, ninputs - ninout + i)
00929 = output_rtx[j];
00930
00931 sprintf (buffer, "%d", j);
00932 ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
00933 = gen_rtx_ASM_INPUT (inout_mode[i], ggc_strdup (buffer));
00934 }
00935
00936 generating_concat_p = old_generating_concat_p;
00937
00938
00939
00940
00941
00942
00943 if (noutputs == 1 && nclobbers == 0)
00944 {
00945 ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = ggc_strdup (constraints[0]);
00946 emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
00947 }
00948
00949 else if (noutputs == 0 && nclobbers == 0)
00950 {
00951
00952 emit_insn (body);
00953 }
00954
00955 else
00956 {
00957 rtx obody = body;
00958 int num = noutputs;
00959
00960 if (num == 0)
00961 num = 1;
00962
00963 body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
00964
00965
00966 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
00967 {
00968 XVECEXP (body, 0, i)
00969 = gen_rtx_SET (VOIDmode,
00970 output_rtx[i],
00971 gen_rtx_ASM_OPERANDS
00972 (GET_MODE (output_rtx[i]),
00973 ggc_strdup (TREE_STRING_POINTER (string)),
00974 ggc_strdup (constraints[i]),
00975 i, argvec, constraintvec, locus));
00976
00977 MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
00978 }
00979
00980
00981
00982
00983 if (i == 0)
00984 XVECEXP (body, 0, i++) = obody;
00985
00986
00987
00988 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
00989 {
00990 const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
00991 int j = decode_reg_name (regname);
00992 rtx clobbered_reg;
00993
00994 if (j < 0)
00995 {
00996 if (j == -3)
00997 continue;
00998
00999 if (j == -4)
01000 {
01001 XVECEXP (body, 0, i++)
01002 = gen_rtx_CLOBBER (VOIDmode,
01003 gen_rtx_MEM
01004 (BLKmode,
01005 gen_rtx_SCRATCH (VOIDmode)));
01006 continue;
01007 }
01008
01009
01010 continue;
01011 }
01012
01013
01014 clobbered_reg = gen_rtx_REG (QImode, j);
01015
01016
01017
01018
01019 if (!clobber_conflict_found)
01020 {
01021 int opno;
01022
01023
01024
01025 for (opno = 0; opno < noutputs; opno++)
01026 if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
01027 internal_error ("asm clobber conflict with output operand");
01028
01029 for (opno = 0; opno < ninputs - ninout; opno++)
01030 if (reg_overlap_mentioned_p (clobbered_reg,
01031 ASM_OPERANDS_INPUT (obody, opno)))
01032 internal_error ("asm clobber conflict with input operand");
01033 }
01034
01035 XVECEXP (body, 0, i++)
01036 = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
01037 }
01038
01039 emit_insn (body);
01040 }
01041
01042
01043
01044 for (i = 0; i < noutputs; ++i)
01045 if (real_output_rtx[i])
01046 emit_move_insn (real_output_rtx[i], output_rtx[i]);
01047
01048 free_temp_slots ();
01049 }
01050
01051 void
01052 expand_asm_expr (tree exp)
01053 {
01054 int noutputs, i;
01055 tree outputs, tail;
01056 tree *o;
01057
01058 if (ASM_INPUT_P (exp))
01059 {
01060 expand_asm (ASM_STRING (exp), ASM_VOLATILE_P (exp));
01061 return;
01062 }
01063
01064 outputs = ASM_OUTPUTS (exp);
01065 noutputs = list_length (outputs);
01066
01067 o = (tree *) alloca (noutputs * sizeof (tree));
01068
01069
01070 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
01071 o[i] = TREE_VALUE (tail);
01072
01073
01074
01075 expand_asm_operands (ASM_STRING (exp), outputs, ASM_INPUTS (exp),
01076 ASM_CLOBBERS (exp), ASM_VOLATILE_P (exp),
01077 input_location);
01078
01079
01080 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
01081 {
01082 if (o[i] != TREE_VALUE (tail))
01083 {
01084 expand_assignment (o[i], TREE_VALUE (tail));
01085 free_temp_slots ();
01086
01087
01088
01089 TREE_VALUE (tail) = o[i];
01090 }
01091 }
01092 }
01093
01094
01095
01096
01097 static bool
01098 check_operand_nalternatives (tree outputs, tree inputs)
01099 {
01100 if (outputs || inputs)
01101 {
01102 tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
01103 int nalternatives
01104 = n_occurrences (',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
01105 tree next = inputs;
01106
01107 if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
01108 {
01109 error ("too many alternatives in %<asm%>");
01110 return false;
01111 }
01112
01113 tmp = outputs;
01114 while (tmp)
01115 {
01116 const char *constraint
01117 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tmp)));
01118
01119 if (n_occurrences (',', constraint) != nalternatives)
01120 {
01121 error ("operand constraints for %<asm%> differ "
01122 "in number of alternatives");
01123 return false;
01124 }
01125
01126 if (TREE_CHAIN (tmp))
01127 tmp = TREE_CHAIN (tmp);
01128 else
01129 tmp = next, next = 0;
01130 }
01131 }
01132
01133 return true;
01134 }
01135
01136
01137
01138
01139
01140
01141 static bool
01142 check_unique_operand_names (tree outputs, tree inputs)
01143 {
01144 tree i, j;
01145
01146 for (i = outputs; i ; i = TREE_CHAIN (i))
01147 {
01148 tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
01149 if (! i_name)
01150 continue;
01151
01152 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
01153 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01154 goto failure;
01155 }
01156
01157 for (i = inputs; i ; i = TREE_CHAIN (i))
01158 {
01159 tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
01160 if (! i_name)
01161 continue;
01162
01163 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
01164 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01165 goto failure;
01166 for (j = outputs; j ; j = TREE_CHAIN (j))
01167 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01168 goto failure;
01169 }
01170
01171 return true;
01172
01173 failure:
01174 error ("duplicate asm operand name %qs",
01175 TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
01176 return false;
01177 }
01178
01179
01180
01181
01182
01183 tree
01184 resolve_asm_operand_names (tree string, tree outputs, tree inputs)
01185 {
01186 char *buffer;
01187 char *p;
01188 const char *c;
01189 tree t;
01190
01191 check_unique_operand_names (outputs, inputs);
01192
01193
01194
01195 for (t = inputs; t ; t = TREE_CHAIN (t))
01196 {
01197 c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
01198 if (strchr (c, '[') != NULL)
01199 {
01200 p = buffer = xstrdup (c);
01201 while ((p = strchr (p, '[')) != NULL)
01202 p = resolve_operand_name_1 (p, outputs, inputs);
01203 TREE_VALUE (TREE_PURPOSE (t))
01204 = build_string (strlen (buffer), buffer);
01205 free (buffer);
01206 }
01207 }
01208
01209
01210 c = TREE_STRING_POINTER (string);
01211 while ((c = strchr (c, '%')) != NULL)
01212 {
01213 if (c[1] == '[')
01214 break;
01215 else if (ISALPHA (c[1]) && c[2] == '[')
01216 break;
01217 else
01218 {
01219 c += 1;
01220 continue;
01221 }
01222 }
01223
01224 if (c)
01225 {
01226
01227
01228
01229
01230 buffer = xstrdup (TREE_STRING_POINTER (string));
01231 p = buffer + (c - TREE_STRING_POINTER (string));
01232
01233 while ((p = strchr (p, '%')) != NULL)
01234 {
01235 if (p[1] == '[')
01236 p += 1;
01237 else if (ISALPHA (p[1]) && p[2] == '[')
01238 p += 2;
01239 else
01240 {
01241 p += 1;
01242 continue;
01243 }
01244
01245 p = resolve_operand_name_1 (p, outputs, inputs);
01246 }
01247
01248 string = build_string (strlen (buffer), buffer);
01249 free (buffer);
01250 }
01251
01252 return string;
01253 }
01254
01255
01256
01257
01258
01259
01260 static char *
01261 resolve_operand_name_1 (char *p, tree outputs, tree inputs)
01262 {
01263 char *q;
01264 int op;
01265 tree t;
01266 size_t len;
01267
01268
01269 q = strchr (p, ']');
01270 if (!q)
01271 {
01272 error ("missing close brace for named operand");
01273 return strchr (p, '\0');
01274 }
01275 len = q - p - 1;
01276
01277
01278 for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
01279 {
01280 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
01281 if (name)
01282 {
01283 const char *c = TREE_STRING_POINTER (name);
01284 if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
01285 goto found;
01286 }
01287 }
01288 for (t = inputs; t ; t = TREE_CHAIN (t), op++)
01289 {
01290 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
01291 if (name)
01292 {
01293 const char *c = TREE_STRING_POINTER (name);
01294 if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
01295 goto found;
01296 }
01297 }
01298
01299 *q = '\0';
01300 error ("undefined named operand %qs", p + 1);
01301 op = 0;
01302 found:
01303
01304
01305
01306
01307 sprintf (p, "%d", op);
01308 p = strchr (p, '\0');
01309
01310
01311 gcc_assert (p <= q);
01312
01313
01314 memmove (p, q + 1, strlen (q + 1) + 1);
01315
01316 return p;
01317 }
01318
01319
01320
01321 void
01322 expand_expr_stmt (tree exp)
01323 {
01324 rtx value;
01325 tree type;
01326
01327 value = expand_expr (exp, const0_rtx, VOIDmode, 0);
01328 type = TREE_TYPE (exp);
01329
01330
01331
01332 if (value && MEM_P (value) && TREE_THIS_VOLATILE (exp))
01333 {
01334 if (TYPE_MODE (type) == VOIDmode)
01335 ;
01336 else if (TYPE_MODE (type) != BLKmode)
01337 value = copy_to_reg (value);
01338 else
01339 {
01340 rtx lab = gen_label_rtx ();
01341
01342
01343 emit_cmp_and_jump_insns (value, value, EQ,
01344 expand_expr (TYPE_SIZE (type),
01345 NULL_RTX, VOIDmode, 0),
01346 BLKmode, 0, lab);
01347 emit_label (lab);
01348 }
01349 }
01350
01351
01352 free_temp_slots ();
01353 }
01354
01355
01356
01357
01358
01359 int
01360 warn_if_unused_value (tree exp, location_t locus)
01361 {
01362 restart:
01363 if (TREE_USED (exp))
01364 return 0;
01365
01366
01367
01368
01369 if (VOID_TYPE_P (TREE_TYPE (exp)))
01370 return 0;
01371
01372 if (EXPR_HAS_LOCATION (exp))
01373 locus = EXPR_LOCATION (exp);
01374
01375 switch (TREE_CODE (exp))
01376 {
01377 case PREINCREMENT_EXPR:
01378 case POSTINCREMENT_EXPR:
01379 case PREDECREMENT_EXPR:
01380 case POSTDECREMENT_EXPR:
01381 case MODIFY_EXPR:
01382 case INIT_EXPR:
01383 case TARGET_EXPR:
01384 case CALL_EXPR:
01385 case TRY_CATCH_EXPR:
01386 case WITH_CLEANUP_EXPR:
01387 case EXIT_EXPR:
01388 return 0;
01389
01390 case BIND_EXPR:
01391
01392 exp = BIND_EXPR_BODY (exp);
01393 goto restart;
01394
01395 case SAVE_EXPR:
01396 exp = TREE_OPERAND (exp, 0);
01397 goto restart;
01398
01399 case TRUTH_ORIF_EXPR:
01400 case TRUTH_ANDIF_EXPR:
01401
01402 exp = TREE_OPERAND (exp, 1);
01403 goto restart;
01404
01405 case COMPOUND_EXPR:
01406 if (TREE_NO_WARNING (exp))
01407 return 0;
01408 if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus))
01409 return 1;
01410
01411 if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
01412 return 0;
01413 exp = TREE_OPERAND (exp, 1);
01414 goto restart;
01415
01416 case NOP_EXPR:
01417 case CONVERT_EXPR:
01418 case NON_LVALUE_EXPR:
01419
01420 if (TREE_NO_WARNING (exp))
01421 return 0;
01422
01423
01424
01425
01426 {
01427 tree tem = TREE_OPERAND (exp, 0);
01428
01429 while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR)
01430 tem = TREE_OPERAND (tem, 0);
01431
01432 if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR
01433 || TREE_CODE (tem) == CALL_EXPR)
01434 return 0;
01435 }
01436 goto maybe_warn;
01437
01438 case INDIRECT_REF:
01439
01440
01441 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
01442 {
01443 exp = TREE_OPERAND (exp, 0);
01444 goto restart;
01445 }
01446
01447
01448 default:
01449
01450 if ((DECL_P (exp) || REFERENCE_CLASS_P (exp))
01451 && TREE_THIS_VOLATILE (exp))
01452 return 0;
01453
01454
01455
01456
01457 if (EXPRESSION_CLASS_P (exp) && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0)
01458 return 0;
01459
01460 maybe_warn:
01461
01462 if (TREE_SIDE_EFFECTS (exp))
01463 return 0;
01464
01465 warning ("%Hvalue computed is not used", &locus);
01466 return 1;
01467 }
01468 }
01469
01470
01471
01472
01473
01474 void
01475 expand_null_return (void)
01476 {
01477
01478
01479
01480 clobber_return_register ();
01481
01482 expand_null_return_1 ();
01483 }
01484
01485
01486
01487
01488 void
01489 expand_naked_return (void)
01490 {
01491 rtx end_label;
01492
01493 clear_pending_stack_adjust ();
01494 do_pending_stack_adjust ();
01495
01496 end_label = naked_return_label;
01497 if (end_label == 0)
01498 end_label = naked_return_label = gen_label_rtx ();
01499
01500 emit_jump (end_label);
01501 }
01502
01503
01504
01505 static void
01506 expand_value_return (rtx val)
01507 {
01508
01509
01510
01511 rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
01512 if (return_reg != val)
01513 {
01514 tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
01515 if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
01516 {
01517 int unsignedp = TYPE_UNSIGNED (type);
01518 enum machine_mode old_mode
01519 = DECL_MODE (DECL_RESULT (current_function_decl));
01520 enum machine_mode mode
01521 = promote_mode (type, old_mode, &unsignedp, 1);
01522
01523 if (mode != old_mode)
01524 val = convert_modes (mode, old_mode, val, unsignedp);
01525 }
01526 if (GET_CODE (return_reg) == PARALLEL)
01527 emit_group_load (return_reg, val, type, int_size_in_bytes (type));
01528 else
01529 emit_move_insn (return_reg, val);
01530 }
01531
01532 expand_null_return_1 ();
01533 }
01534
01535
01536
01537 static void
01538 expand_null_return_1 (void)
01539 {
01540 clear_pending_stack_adjust ();
01541 do_pending_stack_adjust ();
01542 emit_jump (return_label);
01543 }
01544
01545
01546
01547
01548 void
01549 expand_return (tree retval)
01550 {
01551 rtx result_rtl;
01552 rtx val = 0;
01553 tree retval_rhs;
01554
01555
01556 if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
01557 {
01558 expand_expr (retval, NULL_RTX, VOIDmode, 0);
01559 expand_null_return ();
01560 return;
01561 }
01562
01563 if (retval == error_mark_node)
01564 {
01565
01566
01567 expand_null_return ();
01568 return;
01569 }
01570 else if ((TREE_CODE (retval) == MODIFY_EXPR
01571 || TREE_CODE (retval) == INIT_EXPR)
01572 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
01573 retval_rhs = TREE_OPERAND (retval, 1);
01574 else
01575 retval_rhs = retval;
01576
01577 result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
01578
01579
01580
01581 if (TREE_CODE (retval_rhs) == RESULT_DECL)
01582 expand_value_return (result_rtl);
01583
01584
01585
01586
01587
01588
01589
01590
01591 else if (retval_rhs != 0
01592 && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
01593 && REG_P (result_rtl))
01594 {
01595 int i;
01596 unsigned HOST_WIDE_INT bitpos, xbitpos;
01597 unsigned HOST_WIDE_INT padding_correction = 0;
01598 unsigned HOST_WIDE_INT bytes
01599 = int_size_in_bytes (TREE_TYPE (retval_rhs));
01600 int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01601 unsigned int bitsize
01602 = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
01603 rtx *result_pseudos = alloca (sizeof (rtx) * n_regs);
01604 rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
01605 rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
01606 enum machine_mode tmpmode, result_reg_mode;
01607
01608 if (bytes == 0)
01609 {
01610 expand_null_return ();
01611 return;
01612 }
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 if (bytes % UNITS_PER_WORD != 0
01625 && (targetm.calls.return_in_msb (TREE_TYPE (retval_rhs))
01626 ? !BYTES_BIG_ENDIAN
01627 : BYTES_BIG_ENDIAN))
01628 padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
01629 * BITS_PER_UNIT));
01630
01631
01632 for (bitpos = 0, xbitpos = padding_correction;
01633 bitpos < bytes * BITS_PER_UNIT;
01634 bitpos += bitsize, xbitpos += bitsize)
01635 {
01636
01637
01638
01639 if (xbitpos % BITS_PER_WORD == 0
01640 || xbitpos == padding_correction)
01641 {
01642
01643 dst = gen_reg_rtx (word_mode);
01644 result_pseudos[xbitpos / BITS_PER_WORD] = dst;
01645
01646
01647 emit_move_insn (dst, CONST0_RTX (GET_MODE (dst)));
01648 }
01649
01650
01651
01652 if (bitpos % BITS_PER_WORD == 0)
01653 src = operand_subword_force (result_val,
01654 bitpos / BITS_PER_WORD,
01655 BLKmode);
01656
01657
01658
01659 store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
01660 extract_bit_field (src, bitsize,
01661 bitpos % BITS_PER_WORD, 1,
01662 NULL_RTX, word_mode, word_mode));
01663 }
01664
01665 tmpmode = GET_MODE (result_rtl);
01666 if (tmpmode == BLKmode)
01667 {
01668
01669
01670
01671 for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
01672 tmpmode != VOIDmode;
01673 tmpmode = GET_MODE_WIDER_MODE (tmpmode))
01674
01675 if (GET_MODE_SIZE (tmpmode) >= bytes)
01676 break;
01677
01678
01679 gcc_assert (tmpmode != VOIDmode);
01680
01681 PUT_MODE (result_rtl, tmpmode);
01682 }
01683
01684 if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
01685 result_reg_mode = word_mode;
01686 else
01687 result_reg_mode = tmpmode;
01688 result_reg = gen_reg_rtx (result_reg_mode);
01689
01690 for (i = 0; i < n_regs; i++)
01691 emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode),
01692 result_pseudos[i]);
01693
01694 if (tmpmode != result_reg_mode)
01695 result_reg = gen_lowpart (tmpmode, result_reg);
01696
01697 expand_value_return (result_reg);
01698 }
01699 else if (retval_rhs != 0
01700 && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
01701 && (REG_P (result_rtl)
01702 || (GET_CODE (result_rtl) == PARALLEL)))
01703 {
01704
01705
01706 tree ot = TREE_TYPE (DECL_RESULT (current_function_decl));
01707 tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
01708
01709 val = assign_temp (nt, 0, 0, 1);
01710 val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
01711 val = force_not_mem (val);
01712
01713 expand_value_return (val);
01714 }
01715 else
01716 {
01717
01718 expand_expr (retval, const0_rtx, VOIDmode, 0);
01719 expand_value_return (result_rtl);
01720 }
01721 }
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733 int
01734 is_body_block (tree stmt)
01735 {
01736 if (lang_hooks.no_body_blocks)
01737 return 0;
01738
01739 if (TREE_CODE (stmt) == BLOCK)
01740 {
01741 tree parent = BLOCK_SUPERCONTEXT (stmt);
01742
01743 if (parent && TREE_CODE (parent) == BLOCK)
01744 {
01745 tree grandparent = BLOCK_SUPERCONTEXT (parent);
01746
01747 if (grandparent && TREE_CODE (grandparent) == FUNCTION_DECL)
01748 return 1;
01749 }
01750 }
01751
01752 return 0;
01753 }
01754
01755
01756
01757 static void
01758 expand_nl_goto_receiver (void)
01759 {
01760
01761
01762 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
01763
01764
01765
01766 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
01767
01768 #ifdef HAVE_nonlocal_goto
01769 if (! HAVE_nonlocal_goto)
01770 #endif
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
01783
01784 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
01785 if (fixed_regs[ARG_POINTER_REGNUM])
01786 {
01787 #ifdef ELIMINABLE_REGS
01788
01789
01790
01791
01792
01793 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
01794 size_t i;
01795
01796 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
01797 if (elim_regs[i].from == ARG_POINTER_REGNUM
01798 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
01799 break;
01800
01801 if (i == ARRAY_SIZE (elim_regs))
01802 #endif
01803 {
01804
01805
01806 emit_move_insn (virtual_incoming_args_rtx,
01807 copy_to_reg (get_arg_pointer_save_area (cfun)));
01808 }
01809 }
01810 #endif
01811
01812 #ifdef HAVE_nonlocal_goto_receiver
01813 if (HAVE_nonlocal_goto_receiver)
01814 emit_insn (gen_nonlocal_goto_receiver ());
01815 #endif
01816
01817
01818
01819
01820
01821
01822 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
01823 }
01824
01825
01826
01827
01828 void
01829 expand_decl (tree decl)
01830 {
01831 tree type;
01832
01833 type = TREE_TYPE (decl);
01834
01835
01836
01837 if (TREE_CODE (decl) == CONST_DECL)
01838 {
01839 DECL_MODE (decl) = TYPE_MODE (type);
01840 DECL_ALIGN (decl) = TYPE_ALIGN (type);
01841 DECL_SIZE (decl) = TYPE_SIZE (type);
01842 DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
01843 return;
01844 }
01845
01846
01847
01848
01849
01850 if (TREE_CODE (decl) != VAR_DECL)
01851 return;
01852
01853 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
01854 return;
01855
01856
01857
01858 if (type == error_mark_node)
01859 SET_DECL_RTL (decl, gen_rtx_MEM (BLKmode, const0_rtx));
01860
01861 else if (DECL_SIZE (decl) == 0)
01862
01863 {
01864 rtx x;
01865 if (DECL_INITIAL (decl) == 0)
01866
01867 x = gen_rtx_MEM (BLKmode, const0_rtx);
01868 else
01869
01870
01871 x = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
01872
01873 set_mem_attributes (x, decl, 1);
01874 SET_DECL_RTL (decl, x);
01875 }
01876 else if (use_register_for_decl (decl))
01877 {
01878
01879 int unsignedp = TYPE_UNSIGNED (type);
01880 enum machine_mode reg_mode
01881 = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
01882
01883 SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
01884
01885
01886 if (!DECL_ARTIFICIAL (decl))
01887 {
01888 mark_user_reg (DECL_RTL (decl));
01889
01890
01891
01892
01893
01894
01895
01896 if (POINTER_TYPE_P (type))
01897 mark_reg_pointer (DECL_RTL (decl),
01898 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
01899 }
01900 }
01901
01902 else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
01903 && ! (flag_stack_check && ! STACK_CHECK_BUILTIN
01904 && 0 < compare_tree_int (DECL_SIZE_UNIT (decl),
01905 STACK_CHECK_MAX_VAR_SIZE)))
01906 {
01907
01908 rtx oldaddr = 0;
01909 rtx addr;
01910 rtx x;
01911
01912
01913
01914
01915
01916 if (DECL_RTL_SET_P (decl))
01917 {
01918 gcc_assert (MEM_P (DECL_RTL (decl)));
01919 gcc_assert (REG_P (XEXP (DECL_RTL (decl), 0)));
01920 oldaddr = XEXP (DECL_RTL (decl), 0);
01921 }
01922
01923
01924 DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
01925 : GET_MODE_BITSIZE (DECL_MODE (decl)));
01926 DECL_USER_ALIGN (decl) = 0;
01927
01928 x = assign_temp (decl, 1, 1, 1);
01929 set_mem_attributes (x, decl, 1);
01930 SET_DECL_RTL (decl, x);
01931
01932 if (oldaddr)
01933 {
01934 addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);
01935 if (addr != oldaddr)
01936 emit_move_insn (oldaddr, addr);
01937 }
01938 }
01939 else
01940
01941 {
01942 rtx address, size, x;
01943
01944
01945
01946 do_pending_stack_adjust ();
01947
01948
01949
01950 size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0);
01951 free_temp_slots ();
01952
01953
01954
01955
01956
01957 address = allocate_dynamic_stack_space (size, NULL_RTX,
01958 TYPE_ALIGN (TREE_TYPE (decl)));
01959
01960
01961 x = gen_rtx_MEM (DECL_MODE (decl), address);
01962 set_mem_attributes (x, decl, 1);
01963 SET_DECL_RTL (decl, x);
01964
01965
01966
01967 #ifdef STACK_BOUNDARY
01968 DECL_ALIGN (decl) = STACK_BOUNDARY;
01969 #else
01970 DECL_ALIGN (decl) = BIGGEST_ALIGNMENT;
01971 #endif
01972 DECL_USER_ALIGN (decl) = 0;
01973 }
01974 }
01975
01976
01977 rtx
01978 expand_stack_save (void)
01979 {
01980 rtx ret = NULL_RTX;
01981
01982 do_pending_stack_adjust ();
01983 emit_stack_save (SAVE_BLOCK, &ret, NULL_RTX);
01984 return ret;
01985 }
01986
01987
01988 void
01989 expand_stack_restore (tree var)
01990 {
01991 rtx sa = DECL_RTL (var);
01992
01993 emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
01994 }
01995
01996
01997
01998
01999
02000 void
02001 expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
02002 tree decl_elts)
02003 {
02004 rtx x;
02005 tree t;
02006
02007
02008 for (t = decl_elts; t; t = TREE_CHAIN (t))
02009 if (TREE_ADDRESSABLE (TREE_VALUE (t)))
02010 {
02011 TREE_ADDRESSABLE (decl) = 1;
02012 break;
02013 }
02014
02015 expand_decl (decl);
02016 x = DECL_RTL (decl);
02017
02018
02019 for (t = decl_elts; t; t = TREE_CHAIN (t))
02020 {
02021 tree decl_elt = TREE_VALUE (t);
02022 enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
02023 rtx decl_rtl;
02024
02025
02026
02027 if (TREE_USED (decl_elt))
02028 TREE_USED (decl) = 1;
02029
02030
02031 DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
02032 DECL_USER_ALIGN (decl_elt) = DECL_USER_ALIGN (decl);
02033
02034
02035
02036
02037 if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
02038 DECL_MODE (decl_elt) = mode
02039 = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
02040
02041 if (mode == GET_MODE (x))
02042 decl_rtl = x;
02043 else if (MEM_P (x))
02044
02045
02046 decl_rtl = adjust_address_nv (x, mode, 0);
02047 else
02048 {
02049 gcc_assert (REG_P (x));
02050 decl_rtl = gen_lowpart_SUBREG (mode, x);
02051 }
02052 SET_DECL_RTL (decl_elt, decl_rtl);
02053 }
02054 }
02055
02056
02057
02058
02059
02060
02061
02062 static struct case_node *
02063 add_case_node (struct case_node *head, tree type, tree low, tree high,
02064 tree label)
02065 {
02066 tree min_value, max_value;
02067 struct case_node *r;
02068
02069 gcc_assert (TREE_CODE (low) == INTEGER_CST);
02070 gcc_assert (!high || TREE_CODE (high) == INTEGER_CST);
02071
02072 min_value = TYPE_MIN_VALUE (type);
02073 max_value = TYPE_MAX_VALUE (type);
02074
02075
02076
02077
02078
02079 if (!high || tree_int_cst_equal (low, high))
02080 {
02081
02082 if ((TREE_CODE (min_value) == INTEGER_CST
02083 && tree_int_cst_compare (low, min_value) < 0)
02084 || (TREE_CODE (max_value) == INTEGER_CST
02085 && tree_int_cst_compare (low, max_value) > 0))
02086 return head;
02087 low = fold_convert (type, low);
02088 high = low;
02089 }
02090 else
02091 {
02092
02093 if ((TREE_CODE (min_value) == INTEGER_CST
02094 && tree_int_cst_compare (high, min_value) < 0)
02095 || (TREE_CODE (max_value) == INTEGER_CST
02096 && tree_int_cst_compare (low, max_value) > 0))
02097 return head;
02098
02099
02100
02101 if (TREE_CODE (min_value) == INTEGER_CST
02102 && tree_int_cst_compare (low, min_value) < 0)
02103 low = min_value;
02104 low = fold_convert (type, low);
02105
02106
02107
02108 if (TREE_CODE (max_value) == INTEGER_CST
02109 && tree_int_cst_compare (high, max_value) > 0)
02110 high = max_value;
02111 high = fold_convert (type, high);
02112 }
02113
02114
02115
02116 r = ggc_alloc (sizeof (struct case_node));
02117 r->low = low;
02118 r->high = high;
02119 r->code_label = label;
02120 r->parent = r->left = NULL;
02121 r->right = head;
02122 return r;
02123 }
02124
02125
02126 #define MAX_CASE_BIT_TESTS 3
02127
02128
02129 #ifndef CASE_USE_BIT_TESTS
02130 #define CASE_USE_BIT_TESTS (ashl_optab->handlers[word_mode].insn_code \
02131 != CODE_FOR_nothing)
02132 #endif
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142 struct case_bit_test
02143 {
02144 HOST_WIDE_INT hi;
02145 HOST_WIDE_INT lo;
02146 rtx label;
02147 int bits;
02148 };
02149
02150
02151
02152 static
02153 bool lshift_cheap_p (void)
02154 {
02155 static bool init = false;
02156 static bool cheap = true;
02157
02158 if (!init)
02159 {
02160 rtx reg = gen_rtx_REG (word_mode, 10000);
02161 int cost = rtx_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), SET);
02162 cheap = cost < COSTS_N_INSNS (3);
02163 init = true;
02164 }
02165
02166 return cheap;
02167 }
02168
02169
02170
02171
02172
02173 static int
02174 case_bit_test_cmp (const void *p1, const void *p2)
02175 {
02176 const struct case_bit_test *d1 = p1;
02177 const struct case_bit_test *d2 = p2;
02178
02179 return d2->bits - d1->bits;
02180 }
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197 static void
02198 emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
02199 tree range, case_node_ptr nodes, rtx default_label)
02200 {
02201 struct case_bit_test test[MAX_CASE_BIT_TESTS];
02202 enum machine_mode mode;
02203 rtx expr, index, label;
02204 unsigned int i,j,lo,hi;
02205 struct case_node *n;
02206 unsigned int count;
02207
02208 count = 0;
02209 for (n = nodes; n; n = n->right)
02210 {
02211 label = label_rtx (n->code_label);
02212 for (i = 0; i < count; i++)
02213 if (label == test[i].label)
02214 break;
02215
02216 if (i == count)
02217 {
02218 gcc_assert (count < MAX_CASE_BIT_TESTS);
02219 test[i].hi = 0;
02220 test[i].lo = 0;
02221 test[i].label = label;
02222 test[i].bits = 1;
02223 count++;
02224 }
02225 else
02226 test[i].bits++;
02227
02228 lo = tree_low_cst (fold (build2 (MINUS_EXPR, index_type,
02229 n->low, minval)), 1);
02230 hi = tree_low_cst (fold (build2 (MINUS_EXPR, index_type,
02231 n->high, minval)), 1);
02232 for (j = lo; j <= hi; j++)
02233 if (j >= HOST_BITS_PER_WIDE_INT)
02234 test[i].hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT);
02235 else
02236 test[i].lo |= (HOST_WIDE_INT) 1 << j;
02237 }
02238
02239 qsort (test, count, sizeof(*test), case_bit_test_cmp);
02240
02241 index_expr = fold (build2 (MINUS_EXPR, index_type,
02242 fold_convert (index_type, index_expr),
02243 fold_convert (index_type, minval)));
02244 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
02245 do_pending_stack_adjust ();
02246
02247 mode = TYPE_MODE (index_type);
02248 expr = expand_expr (range, NULL_RTX, VOIDmode, 0);
02249 emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
02250 default_label);
02251
02252 index = convert_to_mode (word_mode, index, 0);
02253 index = expand_binop (word_mode, ashl_optab, const1_rtx,
02254 index, NULL_RTX, 1, OPTAB_WIDEN);
02255
02256 for (i = 0; i < count; i++)
02257 {
02258 expr = immed_double_const (test[i].lo, test[i].hi, word_mode);
02259 expr = expand_binop (word_mode, and_optab, index, expr,
02260 NULL_RTX, 1, OPTAB_WIDEN);
02261 emit_cmp_and_jump_insns (expr, const0_rtx, NE, NULL_RTX,
02262 word_mode, 1, test[i].label);
02263 }
02264
02265 emit_jump (default_label);
02266 }
02267
02268 #ifndef HAVE_casesi
02269 #define HAVE_casesi 0
02270 #endif
02271
02272 #ifndef HAVE_tablejump
02273 #define HAVE_tablejump 0
02274 #endif
02275
02276
02277
02278
02279
02280
02281
02282 void
02283 expand_case (tree exp)
02284 {
02285 tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
02286 rtx default_label = 0;
02287 struct case_node *n;
02288 unsigned int count, uniq;
02289 rtx index;
02290 rtx table_label;
02291 int ncases;
02292 rtx *labelvec;
02293 int i, fail;
02294 rtx before_case, end, lab;
02295
02296 tree vec = SWITCH_LABELS (exp);
02297 tree orig_type = TREE_TYPE (exp);
02298 tree index_expr = SWITCH_COND (exp);
02299 tree index_type = TREE_TYPE (index_expr);
02300 int unsignedp = TYPE_UNSIGNED (index_type);
02301
02302
02303
02304 rtx start;
02305
02306
02307
02308 struct case_node *case_list = 0;
02309
02310
02311 tree default_label_decl;
02312
02313
02314
02315 gcc_assert (!SWITCH_BODY (exp));
02316 gcc_assert (SWITCH_LABELS (exp));
02317
02318 do_pending_stack_adjust ();
02319
02320
02321 if (index_type != error_mark_node)
02322 {
02323 tree elt;
02324 bitmap label_bitmap;
02325
02326
02327
02328 gcc_assert (TREE_CODE (index_expr) != INTEGER_CST);
02329
02330
02331 elt = TREE_VEC_ELT (vec, TREE_VEC_LENGTH (vec) - 1);
02332 gcc_assert (!CASE_HIGH (elt));
02333 gcc_assert (!CASE_LOW (elt));
02334 default_label_decl = CASE_LABEL (elt);
02335
02336 for (i = TREE_VEC_LENGTH (vec) - 1; --i >= 0; )
02337 {
02338 elt = TREE_VEC_ELT (vec, i);
02339 gcc_assert (CASE_LOW (elt));
02340 case_list = add_case_node (case_list, index_type,
02341 CASE_LOW (elt), CASE_HIGH (elt),
02342 CASE_LABEL (elt));
02343 }
02344
02345
02346
02347
02348 start = get_last_insn ();
02349 if (! NOTE_P (start))
02350 {
02351 emit_note (NOTE_INSN_DELETED);
02352 start = get_last_insn ();
02353 }
02354
02355 default_label = label_rtx (default_label_decl);
02356
02357 before_case = get_last_insn ();
02358
02359
02360
02361 uniq = 0;
02362 count = 0;
02363 label_bitmap = BITMAP_ALLOC (NULL);
02364 for (n = case_list; n; n = n->right)
02365 {
02366
02367
02368 if (count++ == 0)
02369 {
02370 minval = n->low;
02371 maxval = n->high;
02372 }
02373 else
02374 {
02375 if (INT_CST_LT (n->low, minval))
02376 minval = n->low;
02377 if (INT_CST_LT (maxval, n->high))
02378 maxval = n->high;
02379 }
02380
02381 if (! tree_int_cst_equal (n->low, n->high))
02382 count++;
02383
02384
02385
02386 lab = label_rtx (n->code_label);
02387 if (!bitmap_bit_p (label_bitmap, CODE_LABEL_NUMBER (lab)))
02388 {
02389 bitmap_set_bit (label_bitmap, CODE_LABEL_NUMBER (lab));
02390 uniq++;
02391 }
02392 }
02393
02394 BITMAP_FREE (label_bitmap);
02395
02396
02397
02398
02399
02400 if (count == 0)
02401 {
02402 emit_jump (default_label);
02403 return;
02404 }
02405
02406
02407 range = fold (build2 (MINUS_EXPR, index_type, maxval, minval));
02408
02409
02410
02411
02412 if (CASE_USE_BIT_TESTS
02413 && ! TREE_CONSTANT (index_expr)
02414 && compare_tree_int (range, GET_MODE_BITSIZE (word_mode)) < 0
02415 && compare_tree_int (range, 0) > 0
02416 && lshift_cheap_p ()
02417 && ((uniq == 1 && count >= 3)
02418 || (uniq == 2 && count >= 5)
02419 || (uniq == 3 && count >= 6)))
02420 {
02421
02422
02423
02424 if (compare_tree_int (minval, 0) > 0
02425 && compare_tree_int (maxval, GET_MODE_BITSIZE (word_mode)) < 0)
02426 {
02427 minval = integer_zero_node;
02428 range = maxval;
02429 }
02430 emit_case_bit_tests (index_type, index_expr, minval, range,
02431 case_list, default_label);
02432 }
02433
02434
02435
02436
02437
02438
02439 else if (count < case_values_threshold ()
02440 || compare_tree_int (range,
02441 (optimize_size ? 3 : 10) * count) > 0
02442
02443
02444 || compare_tree_int (range, 0) < 0
02445 #ifndef ASM_OUTPUT_ADDR_DIFF_ELT
02446 || flag_pic
02447 #endif
02448 || TREE_CONSTANT (index_expr)
02449
02450
02451 || (!HAVE_casesi && !HAVE_tablejump))
02452 {
02453 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
02454
02455
02456
02457
02458
02459
02460 if (GET_MODE_CLASS (GET_MODE (index)) == MODE_INT
02461 && ! have_insn_for (COMPARE, GET_MODE (index)))
02462 {
02463 enum machine_mode wider_mode;
02464 for (wider_mode = GET_MODE (index); wider_mode != VOIDmode;
02465 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
02466 if (have_insn_for (COMPARE, wider_mode))
02467 {
02468 index = convert_to_mode (wider_mode, index, unsignedp);
02469 break;
02470 }
02471 }
02472
02473 do_pending_stack_adjust ();
02474
02475 if (MEM_P (index))
02476 index = copy_to_reg (index);
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491 use_cost_table
02492 = (TREE_CODE (orig_type) != ENUMERAL_TYPE
02493 && estimate_case_costs (case_list));
02494 balance_case_nodes (&case_list, NULL);
02495 emit_case_nodes (index, case_list, default_label, index_type);
02496 emit_jump (default_label);
02497 }
02498 else
02499 {
02500 table_label = gen_label_rtx ();
02501 if (! try_casesi (index_type, index_expr, minval, range,
02502 table_label, default_label))
02503 {
02504 bool ok;
02505 index_type = integer_type_node;
02506
02507
02508
02509 if (! optimize_size
02510 && compare_tree_int (minval, 0) > 0
02511 && compare_tree_int (minval, 3) < 0)
02512 {
02513 minval = integer_zero_node;
02514 range = maxval;
02515 }
02516
02517 ok = try_tablejump (index_type, index_expr, minval, range,
02518 table_label, default_label);
02519 gcc_assert (ok);
02520 }
02521
02522
02523
02524 ncases = tree_low_cst (range, 0) + 1;
02525 labelvec = alloca (ncases * sizeof (rtx));
02526 memset (labelvec, 0, ncases * sizeof (rtx));
02527
02528 for (n = case_list; n; n = n->right)
02529 {
02530
02531
02532
02533 HOST_WIDE_INT i_low
02534 = tree_low_cst (fold (build2 (MINUS_EXPR, index_type,
02535 n->low, minval)), 1);
02536 HOST_WIDE_INT i_high
02537 = tree_low_cst (fold (build2 (MINUS_EXPR, index_type,
02538 n->high, minval)), 1);
02539 HOST_WIDE_INT i;
02540
02541 for (i = i_low; i <= i_high; i ++)
02542 labelvec[i]
02543 = gen_rtx_LABEL_REF (Pmode, label_rtx (n->code_label));
02544 }
02545
02546
02547 for (i = 0; i < ncases; i++)
02548 if (labelvec[i] == 0)
02549 labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
02550
02551
02552 emit_label (table_label);
02553
02554 if (CASE_VECTOR_PC_RELATIVE || flag_pic)
02555 emit_jump_insn (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
02556 gen_rtx_LABEL_REF (Pmode, table_label),
02557 gen_rtvec_v (ncases, labelvec),
02558 const0_rtx, const0_rtx));
02559 else
02560 emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
02561 gen_rtvec_v (ncases, labelvec)));
02562
02563
02564 emit_barrier ();
02565 }
02566
02567 before_case = NEXT_INSN (before_case);
02568 end = get_last_insn ();
02569 fail = squeeze_notes (&before_case, &end);
02570 gcc_assert (!fail);
02571 reorder_insns (before_case, end, start);
02572 }
02573
02574 free_temp_slots ();
02575 }
02576
02577
02578
02579 static void
02580 do_jump_if_equal (rtx op1, rtx op2, rtx label, int unsignedp)
02581 {
02582 if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
02583 {
02584 if (op1 == op2)
02585 emit_jump (label);
02586 }
02587 else
02588 emit_cmp_and_jump_insns (op1, op2, EQ, NULL_RTX,
02589 (GET_MODE (op1) == VOIDmode
02590 ? GET_MODE (op2) : GET_MODE (op1)),
02591 unsignedp, label);
02592 }
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617 static int
02618 estimate_case_costs (case_node_ptr node)
02619 {
02620 tree min_ascii = integer_minus_one_node;
02621 tree max_ascii = build_int_cst (TREE_TYPE (node->high), 127);
02622 case_node_ptr n;
02623 int i;
02624
02625
02626
02627
02628 if (! cost_table_initialized)
02629 {
02630 cost_table_initialized = 1;
02631
02632 for (i = 0; i < 128; i++)
02633 {
02634 if (ISALNUM (i))
02635 COST_TABLE (i) = 16;
02636 else if (ISPUNCT (i))
02637 COST_TABLE (i) = 8;
02638 else if (ISCNTRL (i))
02639 COST_TABLE (i) = -1;
02640 }
02641
02642 COST_TABLE (' ') = 8;
02643 COST_TABLE ('\t') = 4;
02644 COST_TABLE ('\0') = 4;
02645 COST_TABLE ('\n') = 2;
02646 COST_TABLE ('\f') = 1;
02647 COST_TABLE ('\v') = 1;
02648 COST_TABLE ('\b') = 1;
02649 }
02650
02651
02652
02653
02654
02655
02656
02657 for (n = node; n; n = n->right)
02658 {
02659 if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
02660 return 0;
02661
02662 for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);
02663 i <= (HOST_WIDE_INT) TREE_INT_CST_LOW (n->high); i++)
02664 if (COST_TABLE (i) < 0)
02665 return 0;
02666 }
02667
02668
02669
02670 return 1;
02671 }
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683 static void
02684 balance_case_nodes (case_node_ptr *head, case_node_ptr parent)
02685 {
02686 case_node_ptr np;
02687
02688 np = *head;
02689 if (np)
02690 {
02691 int cost = 0;
02692 int i = 0;
02693 int ranges = 0;
02694 case_node_ptr *npp;
02695 case_node_ptr left;
02696
02697
02698
02699 while (np)
02700 {
02701 if (!tree_int_cst_equal (np->low, np->high))
02702 {
02703 ranges++;
02704 if (use_cost_table)
02705 cost += COST_TABLE (TREE_INT_CST_LOW (np->high));
02706 }
02707
02708 if (use_cost_table)
02709 cost += COST_TABLE (TREE_INT_CST_LOW (np->low));
02710
02711 i++;
02712 np = np->right;
02713 }
02714
02715 if (i > 2)
02716 {
02717
02718 npp = head;
02719 left = *npp;
02720 if (use_cost_table)
02721 {
02722
02723
02724 int n_moved = 0;
02725 i = (cost + 1) / 2;
02726 while (1)
02727 {
02728
02729 if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
02730 i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->high));
02731 i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->low));
02732 if (i <= 0)
02733 break;
02734 npp = &(*npp)->right;
02735 n_moved += 1;
02736 }
02737 if (n_moved == 0)
02738 {
02739
02740
02741 np = *head;
02742 np->parent = parent;
02743 balance_case_nodes (&np->left, np);
02744 for (; np->right; np = np->right)
02745 np->right->parent = np;
02746 return;
02747 }
02748 }
02749
02750 else if (i == 3)
02751 npp = &(*npp)->right;
02752 else
02753 {
02754
02755
02756
02757 i = (i + ranges + 1) / 2;
02758 while (1)
02759 {
02760
02761 if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
02762 i--;
02763 i--;
02764 if (i <= 0)
02765 break;
02766 npp = &(*npp)->right;
02767 }
02768 }
02769 *head = np = *npp;
02770 *npp = 0;
02771 np->parent = parent;
02772 np->left = left;
02773
02774
02775 balance_case_nodes (&np->left, np);
02776 balance_case_nodes (&np->right, np);
02777 }
02778 else
02779 {
02780
02781
02782 np = *head;
02783 np->parent = parent;
02784 for (; np->right; np = np->right)
02785 np->right->parent = np;
02786 }
02787 }
02788 }
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800 static int
02801 node_has_low_bound (case_node_ptr node, tree index_type)
02802 {
02803 tree low_minus_one;
02804 case_node_ptr pnode;
02805
02806
02807
02808
02809 if (tree_int_cst_equal (node->low, TYPE_MIN_VALUE (index_type)))
02810 return 1;
02811
02812
02813
02814
02815
02816 if (node->left)
02817 return 0;
02818
02819 low_minus_one = fold (build2 (MINUS_EXPR, TREE_TYPE (node->low),
02820 node->low, integer_one_node));
02821
02822
02823
02824
02825 if (! tree_int_cst_lt (low_minus_one, node->low))
02826 return 0;
02827
02828 for (pnode = node->parent; pnode; pnode = pnode->parent)
02829 if (tree_int_cst_equal (low_minus_one, pnode->high))
02830 return 1;
02831
02832 return 0;
02833 }
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845 static int
02846 node_has_high_bound (case_node_ptr node, tree index_type)
02847 {
02848 tree high_plus_one;
02849 case_node_ptr pnode;
02850
02851
02852
02853 if (TYPE_MAX_VALUE (index_type) == NULL)
02854 return 1;
02855
02856
02857
02858
02859 if (tree_int_cst_equal (node->high, TYPE_MAX_VALUE (index_type)))
02860 return 1;
02861
02862
02863
02864
02865
02866 if (node->right)
02867 return 0;
02868
02869 high_plus_one = fold (build2 (PLUS_EXPR, TREE_TYPE (node->high),
02870 node->high, integer_one_node));
02871
02872
02873
02874
02875 if (! tree_int_cst_lt (node->high, high_plus_one))
02876 return 0;
02877
02878 for (pnode = node->parent; pnode; pnode = pnode->parent)
02879 if (tree_int_cst_equal (high_plus_one, pnode->low))
02880 return 1;
02881
02882 return 0;
02883 }
02884
02885
02886
02887
02888
02889 static int
02890 node_is_bounded (case_node_ptr node, tree index_type)
02891 {
02892 return (node_has_low_bound (node, index_type)
02893 && node_has_high_bound (node, index_type));
02894 }
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922 static void
02923 emit_case_nodes (rtx index, case_node_ptr node, rtx default_label,
02924 tree index_type)
02925 {
02926
02927 int unsignedp = TYPE_UNSIGNED (index_type);
02928 enum machine_mode mode = GET_MODE (index);
02929 enum machine_mode imode = TYPE_MODE (index_type);
02930
02931
02932
02933 if (node_is_bounded (node, index_type))
02934 emit_jump (label_rtx (node->code_label));
02935
02936 else if (tree_int_cst_equal (node->low, node->high))
02937 {
02938
02939
02940
02941 do_jump_if_equal (index,
02942 convert_modes (mode, imode,
02943 expand_expr (node->low, NULL_RTX,
02944 VOIDmode, 0),
02945 unsignedp),
02946 label_rtx (node->code_label), unsignedp);
02947
02948 if (node->right != 0 && node->left != 0)
02949 {
02950
02951
02952
02953
02954
02955
02956 if (node_is_bounded (node->right, index_type))
02957 {
02958 emit_cmp_and_jump_insns (index,
02959 convert_modes
02960 (mode, imode,
02961 expand_expr (node->high, NULL_RTX,
02962 VOIDmode, 0),
02963 unsignedp),
02964 GT, NULL_RTX, mode, unsignedp,
02965 label_rtx (node->right->code_label));
02966 emit_case_nodes (index, node->left, default_label, index_type);
02967 }
02968
02969 else if (node_is_bounded (node->left, index_type))
02970 {
02971 emit_cmp_and_jump_insns (index,
02972 convert_modes
02973 (mode, imode,
02974 expand_expr (node->high, NULL_RTX,
02975 VOIDmode, 0),
02976 unsignedp),
02977 LT, NULL_RTX, mode, unsignedp,
02978 label_rtx (node->left->code_label));
02979 emit_case_nodes (index, node->right, default_label, index_type);
02980 }
02981
02982
02983
02984
02985 else if (tree_int_cst_equal (node->right->low, node->right->high)
02986 && node->right->left == 0
02987 && node->right->right == 0
02988 && tree_int_cst_equal (node->left->low, node->left->high)
02989 && node->left->left == 0
02990 && node->left->right == 0)
02991 {
02992
02993
02994
02995
02996
02997 do_jump_if_equal (index,
02998 convert_modes (mode, imode,
02999 expand_expr (node->right->low,
03000 NULL_RTX,
03001 VOIDmode, 0),
03002 unsignedp),
03003 label_rtx (node->right->code_label),
03004 unsignedp);
03005
03006
03007
03008 do_jump_if_equal (index,
03009 convert_modes (mode, imode,
03010 expand_expr (node->left->low,
03011 NULL_RTX,
03012 VOIDmode, 0),
03013 unsignedp),
03014 label_rtx (node->left->code_label),
03015 unsignedp);
03016 }
03017
03018 else
03019 {
03020
03021
03022
03023 tree test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
03024
03025
03026 emit_cmp_and_jump_insns (index,
03027 convert_modes
03028 (mode, imode,
03029 expand_expr (node->high, NULL_RTX,
03030 VOIDmode, 0),
03031 unsignedp),
03032 GT, NULL_RTX, mode, unsignedp,
03033 label_rtx (test_label));
03034
03035
03036
03037 emit_case_nodes (index, node->left, default_label, index_type);
03038
03039
03040 emit_jump (default_label);
03041
03042
03043 expand_label (test_label);
03044 emit_case_nodes (index, node->right, default_label, index_type);
03045 }
03046 }
03047
03048 else if (node->right != 0 && node->left == 0)
03049 {
03050
03051
03052
03053
03054
03055
03056
03057 if (node->right->right || node->right->left
03058 || !tree_int_cst_equal (node->right->low, node->right->high))
03059 {
03060 if (!node_has_low_bound (node, index_type))
03061 {
03062 emit_cmp_and_jump_insns (index,
03063 convert_modes
03064 (mode, imode,
03065 expand_expr (node->high, NULL_RTX,
03066 VOIDmode, 0),
03067 unsignedp),
03068 LT, NULL_RTX, mode, unsignedp,
03069 default_label);
03070 }
03071
03072 emit_case_nodes (index, node->right, default_label, index_type);
03073 }
03074 else
03075
03076
03077
03078 do_jump_if_equal (index,
03079 convert_modes
03080 (mode, imode,
03081 expand_expr (node->right->low, NULL_RTX,
03082 VOIDmode, 0),
03083 unsignedp),
03084 label_rtx (node->right->code_label), unsignedp);
03085 }
03086
03087 else if (node->right == 0 && node->left != 0)
03088 {
03089
03090 if (node->left->left || node->left->right
03091 || !tree_int_cst_equal (node->left->low, node->left->high))
03092 {
03093 if (!node_has_high_bound (node, index_type))
03094 {
03095 emit_cmp_and_jump_insns (index,
03096 convert_modes
03097 (mode, imode,
03098 expand_expr (node->high, NULL_RTX,
03099 VOIDmode, 0),
03100 unsignedp),
03101 GT, NULL_RTX, mode, unsignedp,
03102 default_label);
03103 }
03104
03105 emit_case_nodes (index, node->left, default_label, index_type);
03106 }
03107 else
03108
03109
03110
03111 do_jump_if_equal (index,
03112 convert_modes
03113 (mode, imode,
03114 expand_expr (node->left->low, NULL_RTX,
03115 VOIDmode, 0),
03116 unsignedp),
03117 label_rtx (node->left->code_label), unsignedp);
03118 }
03119 }
03120 else
03121 {
03122
03123
03124
03125
03126 if (node->right != 0 && node->left != 0)
03127 {
03128
03129
03130
03131
03132
03133 tree test_label = 0;
03134
03135 if (node_is_bounded (node->right, index_type))
03136
03137
03138 emit_cmp_and_jump_insns (index,
03139 convert_modes
03140 (mode, imode,
03141 expand_expr (node->high, NULL_RTX,
03142 VOIDmode, 0),
03143 unsignedp),
03144 GT, NULL_RTX, mode, unsignedp,
03145 label_rtx (node->right->code_label));
03146 else
03147 {
03148
03149
03150
03151 test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
03152 emit_cmp_and_jump_insns (index,
03153 convert_modes
03154 (mode, imode,
03155 expand_expr (node->high, NULL_RTX,
03156 VOIDmode, 0),
03157 unsignedp),
03158 GT, NULL_RTX, mode, unsignedp,
03159 label_rtx (test_label));
03160 }
03161
03162
03163
03164 emit_cmp_and_jump_insns (index,
03165 convert_modes
03166 (mode, imode,
03167 expand_expr (node->low, NULL_RTX,
03168 VOIDmode, 0),
03169 unsignedp),
03170 GE, NULL_RTX, mode, unsignedp,
03171 label_rtx (node->code_label));
03172
03173
03174 emit_case_nodes (index, node->left, default_label, index_type);
03175
03176
03177
03178 if (test_label)
03179 {
03180
03181
03182 emit_jump (default_label);
03183
03184 expand_label (test_label);
03185 emit_case_nodes (index, node->right, default_label, index_type);
03186 }
03187 }
03188
03189 else if (node->right != 0 && node->left == 0)
03190 {
03191
03192
03193 if (!node_has_low_bound (node, index_type))
03194 {
03195 emit_cmp_and_jump_insns (index,
03196 convert_modes
03197 (mode, imode,
03198 expand_expr (node->low, NULL_RTX,
03199 VOIDmode, 0),
03200 unsignedp),
03201 LT, NULL_RTX, mode, unsignedp,
03202 default_label);
03203 }
03204
03205
03206
03207 emit_cmp_and_jump_insns (index,
03208 convert_modes
03209 (mode, imode,
03210 expand_expr (node->high, NULL_RTX,
03211 VOIDmode, 0),
03212 unsignedp),
03213 LE, NULL_RTX, mode, unsignedp,
03214 label_rtx (node->code_label));
03215
03216 emit_case_nodes (index, node->right, default_label, index_type);
03217 }
03218
03219 else if (node->right == 0 && node->left != 0)
03220 {
03221
03222
03223 if (!node_has_high_bound (node, index_type))
03224 {
03225 emit_cmp_and_jump_insns (index,
03226 convert_modes
03227 (mode, imode,
03228 expand_expr (node->high, NULL_RTX,
03229 VOIDmode, 0),
03230 unsignedp),
03231 GT, NULL_RTX, mode, unsignedp,
03232 default_label);
03233 }
03234
03235
03236
03237 emit_cmp_and_jump_insns (index,
03238 convert_modes
03239 (mode, imode,
03240 expand_expr (node->low, NULL_RTX,
03241 VOIDmode, 0),
03242 unsignedp),
03243 GE, NULL_RTX, mode, unsignedp,
03244 label_rtx (node->code_label));
03245
03246 emit_case_nodes (index, node->left, default_label, index_type);
03247 }
03248
03249 else
03250 {
03251
03252
03253
03254 int high_bound = node_has_high_bound (node, index_type);
03255 int low_bound = node_has_low_bound (node, index_type);
03256
03257 if (!high_bound && low_bound)
03258 {
03259 emit_cmp_and_jump_insns (index,
03260 convert_modes
03261 (mode, imode,
03262 expand_expr (node->high, NULL_RTX,
03263 VOIDmode, 0),
03264 unsignedp),
03265 GT, NULL_RTX, mode, unsignedp,
03266 default_label);
03267 }
03268
03269 else if (!low_bound && high_bound)
03270 {
03271 emit_cmp_and_jump_insns (index,
03272 convert_modes
03273 (mode, imode,
03274 expand_expr (node->low, NULL_RTX,
03275 VOIDmode, 0),
03276 unsignedp),
03277 LT, NULL_RTX, mode, unsignedp,
03278 default_label);
03279 }
03280 else if (!low_bound && !high_bound)
03281 {
03282
03283 tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
03284 tree low = build1 (CONVERT_EXPR, type, node->low);
03285 tree high = build1 (CONVERT_EXPR, type, node->high);
03286 rtx low_rtx, new_index, new_bound;
03287
03288
03289
03290 low_rtx = expand_expr (low, NULL_RTX, mode, 0);
03291 new_index = expand_simple_binop (mode, MINUS, index, low_rtx,
03292 NULL_RTX, unsignedp,
03293 OPTAB_WIDEN);
03294 new_bound = expand_expr (fold (build2 (MINUS_EXPR, type,
03295 high, low)),
03296 NULL_RTX, mode, 0);
03297
03298 emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
03299 mode, 1, default_label);
03300 }
03301
03302 emit_jump (label_rtx (node->code_label));
03303 }
03304 }
03305 }