📄 stmt.c
字号:
break; } if (n == 0) except_stack->exit_label = except_stack->data.except_stmt.after_label; } if (escapeflag) { struct nesting *n; /* An `escape' from catch clauses goes out to next escape level, if there is one. Otherwise, it just goes to the end of the construct. */ for (n = except_stack->next; n; n = n->next) if (n->data.except_stmt.escape_label != 0) { except_stack->data.except_stmt.escape_label = n->data.except_stmt.escape_label; break; } if (n == 0) except_stack->data.except_stmt.escape_label = except_stack->data.except_stmt.after_label; } do_pending_stack_adjust (); emit_label (except_stack->data.except_stmt.except_label);}/* Generate code to `escape' from an exception contour. This is like `exiting', but does not conflict with constructs which use `exit_label'. Return nonzero if this contour is escapable, otherwise return zero, and language-specific code will emit the appropriate error message. */intexpand_escape_except (){ struct nesting *n; last_expr_type = 0; for (n = except_stack; n; n = n->next) if (n->data.except_stmt.escape_label != 0) { expand_goto_internal (NULL_TREE, n->data.except_stmt.escape_label, NULL_RTX); return 1; } return 0;}/* Finish processing and `except' contour. Culls out all exceptions which might be raise but not handled, and returns the list to the caller. Language-specific code is responsible for dealing with these exceptions. */treeexpand_end_except (){ struct nesting *n; tree raised = NULL_TREE; do_pending_stack_adjust (); emit_label (except_stack->data.except_stmt.after_label); n = except_stack->next; if (n) { /* Propagate exceptions raised but not handled to next highest level. */ tree handled = except_stack->data.except_stmt.raised; if (handled != void_type_node) { tree prev = NULL_TREE; raised = except_stack->data.except_stmt.raised; while (handled) { tree this_raise; for (this_raise = raised, prev = 0; this_raise; this_raise = TREE_CHAIN (this_raise)) { if (value_member (TREE_VALUE (this_raise), handled)) { if (prev) TREE_CHAIN (prev) = TREE_CHAIN (this_raise); else { raised = TREE_CHAIN (raised); if (raised == NULL_TREE) goto nada; } } else prev = this_raise; } handled = TREE_CHAIN (handled); } if (prev == NULL_TREE) prev = raised; if (prev) TREE_CHAIN (prev) = n->data.except_stmt.raised; nada: n->data.except_stmt.raised = raised; } } POPSTACK (except_stack); last_expr_type = 0; return raised;}/* Record that exception EX is caught by this exception handler. Return nonzero if in exception handling construct, otherwise return 0. */intexpand_catch (ex) tree ex;{ tree *raises_ptr; if (except_stack == 0) return 0; raises_ptr = &except_stack->data.except_stmt.handled; if (*raises_ptr != void_type_node && ex != NULL_TREE && ! value_member (ex, *raises_ptr)) *raises_ptr = tree_cons (NULL_TREE, ex, *raises_ptr); return 1;}/* Record that this exception handler catches all exceptions. Return nonzero if in exception handling construct, otherwise return 0. */intexpand_catch_default (){ if (except_stack == 0) return 0; except_stack->data.except_stmt.handled = void_type_node; return 1;}intexpand_end_catch (){ if (except_stack == 0 || except_stack->data.except_stmt.after_label == 0) return 0; expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label, NULL_RTX); return 1;}/* Generate RTL for the start of an if-then. COND is the expression whose truth should be tested. If EXITFLAG is nonzero, this conditional is visible to `exit_something'. */voidexpand_start_cond (cond, exitflag) tree cond; int exitflag;{ struct nesting *thiscond = ALLOC_NESTING (); /* Make an entry on cond_stack for the cond we are entering. */ thiscond->next = cond_stack; thiscond->all = nesting_stack; thiscond->depth = ++nesting_depth; thiscond->data.cond.next_label = gen_label_rtx (); /* Before we encounter an `else', we don't need a separate exit label unless there are supposed to be exit statements to exit this conditional. */ thiscond->exit_label = exitflag ? gen_label_rtx () : 0; thiscond->data.cond.endif_label = thiscond->exit_label; cond_stack = thiscond; nesting_stack = thiscond; do_jump (cond, thiscond->data.cond.next_label, NULL_RTX);}/* Generate RTL between then-clause and the elseif-clause of an if-then-elseif-.... */voidexpand_start_elseif (cond) tree cond;{ if (cond_stack->data.cond.endif_label == 0) cond_stack->data.cond.endif_label = gen_label_rtx (); emit_jump (cond_stack->data.cond.endif_label); emit_label (cond_stack->data.cond.next_label); cond_stack->data.cond.next_label = gen_label_rtx (); do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);}/* Generate RTL between the then-clause and the else-clause of an if-then-else. */voidexpand_start_else (){ if (cond_stack->data.cond.endif_label == 0) cond_stack->data.cond.endif_label = gen_label_rtx (); emit_jump (cond_stack->data.cond.endif_label); emit_label (cond_stack->data.cond.next_label); cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */}/* Generate RTL for the end of an if-then. Pop the record for it off of cond_stack. */voidexpand_end_cond (){ struct nesting *thiscond = cond_stack; do_pending_stack_adjust (); if (thiscond->data.cond.next_label) emit_label (thiscond->data.cond.next_label); if (thiscond->data.cond.endif_label) emit_label (thiscond->data.cond.endif_label); POPSTACK (cond_stack); last_expr_type = 0;}/* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this loop should be exited by `exit_something'. This is a loop for which `expand_continue' will jump to the top of the loop. Make an entry on loop_stack to record the labels associated with this loop. */struct nesting *expand_start_loop (exit_flag) int exit_flag;{ register struct nesting *thisloop = ALLOC_NESTING (); /* Make an entry on loop_stack for the loop we are entering. */ thisloop->next = loop_stack; thisloop->all = nesting_stack; thisloop->depth = ++nesting_depth; thisloop->data.loop.start_label = gen_label_rtx (); thisloop->data.loop.end_label = gen_label_rtx (); thisloop->data.loop.continue_label = thisloop->data.loop.start_label; thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0; loop_stack = thisloop; nesting_stack = thisloop; do_pending_stack_adjust (); emit_queue (); emit_note (NULL_PTR, NOTE_INSN_LOOP_BEG); emit_label (thisloop->data.loop.start_label); return thisloop;}/* Like expand_start_loop but for a loop where the continuation point (for expand_continue_loop) will be specified explicitly. */struct nesting *expand_start_loop_continue_elsewhere (exit_flag) int exit_flag;{ struct nesting *thisloop = expand_start_loop (exit_flag); loop_stack->data.loop.continue_label = gen_label_rtx (); return thisloop;}/* Specify the continuation point for a loop started with expand_start_loop_continue_elsewhere. Use this at the point in the code to which a continue statement should jump. */voidexpand_loop_continue_here (){ do_pending_stack_adjust (); emit_note (NULL_PTR, NOTE_INSN_LOOP_CONT); emit_label (loop_stack->data.loop.continue_label);}/* Finish a loop. Generate a jump back to the top and the loop-exit label. Pop the block off of loop_stack. */voidexpand_end_loop (){ register rtx insn = get_last_insn (); register rtx start_label = loop_stack->data.loop.start_label; rtx last_test_insn = 0; int num_insns = 0; /* Mark the continue-point at the top of the loop if none elsewhere. */ if (start_label == loop_stack->data.loop.continue_label) emit_note_before (NOTE_INSN_LOOP_CONT, start_label); do_pending_stack_adjust (); /* If optimizing, perhaps reorder the loop. If the loop starts with a conditional exit, roll that to the end where it will optimize together with the jump back. We look for the last conditional branch to the exit that we encounter before hitting 30 insns or a CALL_INSN. If we see an unconditional branch to the exit first, use it. We must also stop at NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes because moving them is not valid. */ if (optimize && ! (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET && SET_DEST (PATTERN (insn)) == pc_rtx && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)) { /* Scan insns from the top of the loop looking for a qualified conditional exit. */ for (insn = NEXT_INSN (loop_stack->data.loop.start_label); insn; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == CODE_LABEL) break; if (GET_CODE (insn) == NOTE && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)) break; if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == INSN) num_insns++; if (last_test_insn && num_insns > 30) break; if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET && SET_DEST (PATTERN (insn)) == pc_rtx && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE && ((GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == LABEL_REF && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0) == loop_stack->data.loop.end_label)) || (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 2)) == LABEL_REF && (XEXP (XEXP (SET_SRC (PATTERN (insn)), 2), 0) == loop_stack->data.loop.end_label)))) last_test_insn = insn; if (last_test_insn == 0 && GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET && SET_DEST (PATTERN (insn)) == pc_rtx && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF && (XEXP (SET_SRC (PATTERN (insn)), 0) == loop_stack->data.loop.end_label)) /* Include BARRIER. */ last_test_insn = NEXT_INSN (insn); } if (last_test_insn != 0 && last_test_insn != get_last_insn ()) { /* We found one. Move everything from there up to the end of the loop, and add a jump into the loop to jump to there. */ register rtx newstart_label = gen_label_rtx (); register rtx start_move = start_label; /* If the start label is preceded by a NOTE_INSN_LOOP_CONT note, then we want to move this note also. */ if (GET_CODE (PREV_INSN (start_move)) == NOTE && (NOTE_LINE_NUMBER (PREV_INSN (start_move)) == NOTE_INSN_LOOP_CONT)) start_move = PREV_INSN (start_move); emit_label_after (newstart_label, PREV_INSN (start_move)); reorder_insns (start_move, last_test_insn, get_last_insn ()); emit_jump_insn_after (gen_jump (start_label), PREV_INSN (newstart_label)); emit_barrier_after (PREV_INSN (newstart_label)); start_label = newstart_label; } } emit_jump (start_label); emit_note (NULL_PTR, NOTE_INSN_LOOP_END); emit_label (loop_stack->data.loop.end_label); POPSTACK (loop_stack); last_expr_type = 0;}/* Generate a jump to the current loop's continue-point. This is usually the top of the loop, but may be specified explicitly elsewhere. If not currently inside a loop, return 0 and do nothing; caller will print an error message. */intexpand_continue_loop (whichloop) struct nesting *whichloop;{ last_expr_type = 0; if (whichloop == 0) whichloop = loop_stack; if (whichloop == 0) return 0; expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label, NULL_RTX); return 1;}/* Generate a jump to exit the current loop. If not currently inside a loop, return 0 and do nothing; caller will print an error message.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -