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