tree tsi_split_statement_list_before (tree_stmt_iterator *i) { struct tree_statement_list_node *cur, *prev; tree old_sl, new_sl; cur = i->ptr; /* How can we possibly split after the end, or before the beginning? */ gcc_assert (cur); prev = cur->prev; old_sl = i->container; new_sl = alloc_stmt_list (); TREE_SIDE_EFFECTS (new_sl) = 1; i->container = new_sl; STATEMENT_LIST_HEAD (new_sl) = cur; STATEMENT_LIST_TAIL (new_sl) = STATEMENT_LIST_TAIL (old_sl); STATEMENT_LIST_TAIL (old_sl) = prev; cur->prev = NULL; if (prev) prev->next = NULL; else STATEMENT_LIST_HEAD (old_sl) = NULL; return new_sl; }
void free_stmt_list (tree t) { gcc_assert (!STATEMENT_LIST_HEAD (t)); gcc_assert (!STATEMENT_LIST_TAIL (t)); vec_safe_push (stmt_list_cache, t); }
void free_stmt_list (tree t) { gcc_assert (!STATEMENT_LIST_HEAD (t)); gcc_assert (!STATEMENT_LIST_TAIL (t)); /* If this triggers, it's a sign that the same list is being freed twice. */ gcc_assert (t != stmt_list_cache || stmt_list_cache == NULL); TREE_CHAIN (t) = stmt_list_cache; stmt_list_cache = t; }
tree expr_last (tree expr) { if (expr == NULL_TREE) return expr; if (TREE_CODE (expr) == STATEMENT_LIST) { struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); return n ? n->stmt : NULL_TREE; } while (TREE_CODE (expr) == COMPOUND_EXPR) expr = TREE_OPERAND (expr, 1); return expr; }
tree expr_only (tree expr) { if (expr == NULL_TREE) return NULL_TREE; if (TREE_CODE (expr) == STATEMENT_LIST) { struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr); if (n && STATEMENT_LIST_HEAD (expr) == n) return n->stmt; else return NULL_TREE; } if (TREE_CODE (expr) == COMPOUND_EXPR) return NULL_TREE; return expr; }
void tsi_delink (tree_stmt_iterator *i) { struct tree_statement_list_node *cur, *next, *prev; cur = i->ptr; next = cur->next; prev = cur->prev; if (prev) prev->next = next; else STATEMENT_LIST_HEAD (i->container) = next; if (next) next->prev = prev; else STATEMENT_LIST_TAIL (i->container) = prev; if (!next && !prev) TREE_SIDE_EFFECTS (i->container) = 0; i->ptr = next; }
void tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode) { struct tree_statement_list_node *head, *tail, *cur; /* Die on looping. */ gcc_assert (t != i->container); if (TREE_CODE (t) == STATEMENT_LIST) { head = STATEMENT_LIST_HEAD (t); tail = STATEMENT_LIST_TAIL (t); STATEMENT_LIST_HEAD (t) = NULL; STATEMENT_LIST_TAIL (t) = NULL; free_stmt_list (t); /* Empty statement lists need no work. */ if (!head || !tail) { gcc_assert (head == tail); return; } } else { head = ggc_alloc (sizeof (*head)); head->prev = NULL; head->next = NULL; head->stmt = t; tail = head; } TREE_SIDE_EFFECTS (i->container) = 1; cur = i->ptr; /* Link it into the list. */ if (cur) { head->prev = cur->prev; if (head->prev) head->prev->next = head; else STATEMENT_LIST_HEAD (i->container) = head; tail->next = cur; cur->prev = tail; } else { head->prev = STATEMENT_LIST_TAIL (i->container); if (head->prev) head->prev->next = head; else STATEMENT_LIST_HEAD (i->container) = head; STATEMENT_LIST_TAIL (i->container) = tail; } /* Update the iterator, if requested. */ switch (mode) { case TSI_NEW_STMT: case TSI_CONTINUE_LINKING: case TSI_CHAIN_START: i->ptr = head; break; case TSI_CHAIN_END: i->ptr = tail; break; case TSI_SAME_STMT: break; } }