📄 c-iterate.c
字号:
expand_start_loop_continue_elsewhere (1); ITERATOR_BOUND_P (idecl) = 1; if (end_note) *end_note = emit_note (0, NOTE_INSN_DELETED);}/* Similar to the previous function, but for the end of the loop. DECL_RTL is zeroed unless we are inside "({...})". The reason for that is described below. When we create two (or more) loops based on the same IDECL, and both inside the same "({...})" construct, we must be prepared to delete both of the loops and create a single one on the level above, i.e. enclosing the "({...})". The new loop has to use the same counter rtl because the references to the iterator decl (IDECL) have already been expanded as references to the counter rtl. It is incorrect to use the same counter reg in different functions, and it is desirable to use different counters in disjoint loops when we know there's no need to combine them (because then they can get allocated separately). */static voiditerator_loop_epilogue (idecl, start_note, end_note) tree idecl; rtx *start_note, *end_note;{ tree test, incr; if (start_note) *start_note = emit_note (0, NOTE_INSN_DELETED); expand_loop_continue_here (); incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0); incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr); TREE_SIDE_EFFECTS (incr) = 1; expand_expr (incr, const0_rtx, VOIDmode, 0); test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0); expand_exit_loop_if_false (0, test); expand_end_loop (); ITERATOR_BOUND_P (idecl) = 0; /* we can reset rtl since there is not chance that this expansion */ /* would be superseded by a higher level one */ /* but don't do this if the decl is static, since we need to share */ /* the same decl in that case. */ if (top_level_ixpansion_p () && ! TREE_STATIC (idecl)) DECL_RTL (idecl) = 0; if (end_note) *end_note = emit_note (0, NOTE_INSN_DELETED);}/* Return true if we are not currently inside a "({...})" construct. */static inttop_level_ixpansion_p (){ return iter_stack == 0;}/* Given two chains of iter_stack_nodes, append the nodes in X into Y. */static voidisn_append (x, y) struct iter_stack_node *x, *y;{ if (x->first == 0) return; if (y->first == 0) { y->first = x->first; y->last = x->last; } else { y->last->next = x->first; y->last = x->last; }}/** Make X empty **/#define ISN_ZERO(X) (X).first=(X).last=0/* Move the ixpansions in sublevel_ixpansions into the current node on the iter_stack, or discard them if the iter_stack is empty. We do this at the end of a statement. */static voidistack_sublevel_to_current (){ /* At the top level we can throw away sublevel's expansions **/ /* because there is nobody above us to ask for a cleanup **/ if (iter_stack != 0) /** Merging with empty sublevel list is a no-op **/ if (sublevel_ixpansions.last) isn_append (&sublevel_ixpansions, iter_stack); if (iter_stack == 0) obstack_free (&ixp_obstack, ixp_firstobj); ISN_ZERO (sublevel_ixpansions);}/* Push a new node on the iter_stack, when we enter a ({...}). */voidpush_iterator_stack (){ struct iter_stack_node *new_top = (struct iter_stack_node *) obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node)); new_top->first = 0; new_top->last = 0; new_top->next = iter_stack; iter_stack = new_top;}/* Pop iter_stack, moving the ixpansions in the node being popped into sublevel_ixpansions. */voidpop_iterator_stack (){ if (iter_stack == 0) abort (); isn_append (iter_stack, &sublevel_ixpansions); /** Pop current level node: */ iter_stack = iter_stack->next;}/* Record an iterator expansion ("ixpansion") for IDECL. The remaining parameters are the notes in the loop entry and exit rtl. */static voidadd_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end) tree idecl; rtx pro_start, pro_end, epi_start, epi_end;{ struct ixpansion *newix; /* Do nothing if we are not inside "({...})", as in that case this expansion can't need subsequent RTL modification. */ if (iter_stack == 0) return; newix = (struct ixpansion *) obstack_alloc (&ixp_obstack, sizeof (struct ixpansion)); newix->ixdecl = idecl; newix->ixprologue_start = pro_start; newix->ixprologue_end = pro_end; newix->ixepilogue_start = epi_start; newix->ixepilogue_end = epi_end; newix->next = iter_stack->first; iter_stack->first = newix; if (iter_stack->last == 0) iter_stack->last = newix;}/* Delete the RTL for all ixpansions for iterator IDECL in our sublevels. We do this when we make a larger containing expansion for IDECL. */static voiddelete_ixpansion (idecl) tree idecl;{ struct ixpansion *previx = 0, *ix; for (ix = sublevel_ixpansions.first; ix; ix = ix->next) if (ix->ixdecl == idecl) { /** zero means that this is a mark for FOR -- **/ /** we do not delete anything, just issue an error. **/ if (ix->ixprologue_start == 0) error_with_decl (idecl, "`for (%s)' appears within implicit iteration"); else { rtx insn; /* We delete all insns, including notes because leaving loop */ /* notes and barriers produced by iterator expansion would */ /* be misleading to other phases */ for (insn = NEXT_INSN (ix->ixprologue_start); insn != ix->ixprologue_end; insn = NEXT_INSN (insn)) delete_insn (insn); for (insn = NEXT_INSN (ix->ixepilogue_start); insn != ix->ixepilogue_end; insn = NEXT_INSN (insn)) delete_insn (insn); } /* Delete this ixpansion from sublevel_ixpansions. */ if (previx) previx->next = ix->next; else sublevel_ixpansions.first = ix->next; if (sublevel_ixpansions.last == ix) sublevel_ixpansions.last = previx; } else previx = ix;}#ifdef DEBUG_ITERATORS/* The functions below are for use from source level debugger. They print short forms of iterator lists and the iterator stack. *//* Print the name of the iterator D. */voidprdecl (d) tree d;{ if (d) { if (TREE_CODE (d) == VAR_DECL) { tree tname = DECL_NAME (d); char *dname = IDENTIFIER_POINTER (tname); fprintf (stderr, dname); } else fprintf (stderr, "<<Not a Decl!!!>>"); } else fprintf (stderr, "<<NULL!!>>");}/* Print Iterator List -- names only */treepil (head) tree head;{ tree current, next; for (current = head; current; current = next) { tree node = TREE_VALUE (current); prdecl (node); next = TREE_CHAIN (current); if (next) fprintf (stderr, ","); } fprintf (stderr, "\n");}/* Print IXpansion List */struct ixpansion *pixl (head) struct ixpansion *head;{ struct ixpansion *current, *next; fprintf (stderr, "> "); if (head == 0) fprintf (stderr, "(empty)"); for (current=head; current; current = next) { tree node = current->ixdecl; prdecl (node); next = current->next; if (next) fprintf (stderr, ","); } fprintf (stderr, "\n"); return head;}/* Print Iterator Stack. */voidpis (){ struct iter_stack_node *stack_node; fprintf (stderr, "--SubLevel: "); pixl (sublevel_ixpansions.first); fprintf (stderr, "--Stack:--\n"); for (stack_node = iter_stack; stack_node; stack_node = stack_node->next) pixl (stack_node->first);}#endif /* DEBUG_ITERATORS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -