mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
improvement(semantic/cfg): add explicit break block element. (#3223)
Works similar to how `throw` is working but is done for `break` statements.
This commit is contained in:
parent
5e36e0d575
commit
20f643063e
15 changed files with 40 additions and 16 deletions
|
|
@ -288,6 +288,8 @@ impl GetterReturn {
|
|||
|
||||
return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false);
|
||||
}
|
||||
// Ignore irrelevant elements.
|
||||
BasicBlockElement::Break(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -489,14 +489,20 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
|||
fn visit_break_statement(&mut self, stmt: &BreakStatement<'a>) {
|
||||
let kind = AstKind::BreakStatement(self.alloc(stmt));
|
||||
self.enter_node(kind);
|
||||
let maybe_label = stmt.label.as_ref();
|
||||
|
||||
/* cfg */
|
||||
let statement_state = self
|
||||
.cfg
|
||||
.before_statement(self.current_node_id, StatementControlFlowType::DoesNotUseContinue);
|
||||
let break_label = maybe_label.and_then(|_| {
|
||||
let reg = Some(self.cfg.new_register());
|
||||
self.cfg.use_this_register = reg;
|
||||
reg
|
||||
});
|
||||
/* cfg */
|
||||
|
||||
if let Some(break_target) = &stmt.label {
|
||||
if let Some(break_target) = maybe_label {
|
||||
self.visit_label_identifier(break_target);
|
||||
|
||||
/* cfg */
|
||||
|
|
@ -527,6 +533,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
|||
}
|
||||
self.cfg.put_unreachable();
|
||||
|
||||
self.cfg.put_break(break_label);
|
||||
self.cfg.after_statement(
|
||||
&statement_state,
|
||||
self.current_node_id,
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ pub enum BasicBlockElement {
|
|||
Unreachable,
|
||||
Assignment(Register, AssignmentValue),
|
||||
Throw(Register),
|
||||
Break(Option<Register>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -239,6 +240,10 @@ impl ControlFlowGraph {
|
|||
self.current_basic_block().push(BasicBlockElement::Throw(throw_expr));
|
||||
}
|
||||
|
||||
pub fn put_break(&mut self, label: Option<Register>) {
|
||||
self.current_basic_block().push(BasicBlockElement::Break(label));
|
||||
}
|
||||
|
||||
pub fn put_unreachable(&mut self) {
|
||||
let current_node_ix = self.current_node_ix;
|
||||
let basic_block_with_unreachable_graph_ix = self.new_basic_block();
|
||||
|
|
@ -380,6 +385,13 @@ pub fn print_basic_block(basic_block_elements: &Vec<BasicBlockElement>) -> Strin
|
|||
BasicBlockElement::Throw(reg) => {
|
||||
output.push_str(&format!("throw {}\n", print_register(*reg)));
|
||||
}
|
||||
|
||||
BasicBlockElement::Break(Some(reg)) => {
|
||||
output.push_str(&format!("break {}\n", print_register(*reg)));
|
||||
}
|
||||
BasicBlockElement::Break(None) => {
|
||||
output.push_str("break");
|
||||
}
|
||||
BasicBlockElement::Assignment(to, with) => {
|
||||
output.push_str(&format!("{} = ", print_register(*to)));
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/break_from_a_label_in_global_
|
|||
---
|
||||
digraph {
|
||||
0 [ label = ""]
|
||||
1 [ label = "Unreachable()"]
|
||||
1 [ label = "Unreachable()\nbreak $0"]
|
||||
0 -> 1 [ ]
|
||||
0 -> 1 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ bb0: {
|
|||
|
||||
bb1: {
|
||||
Unreachable()
|
||||
break $0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ digraph {
|
|||
2 [ label = ""]
|
||||
3 [ label = ""]
|
||||
4 [ label = ""]
|
||||
5 [ label = "Unreachable()"]
|
||||
5 [ label = "Unreachable()\nbreak"]
|
||||
6 [ label = ""]
|
||||
7 [ label = ""]
|
||||
8 [ label = "Unreachable()"]
|
||||
9 [ label = ""]
|
||||
10 [ label = ""]
|
||||
11 [ label = "Unreachable()"]
|
||||
11 [ label = "Unreachable()\nbreak"]
|
||||
12 [ label = ""]
|
||||
13 [ label = ""]
|
||||
14 [ label = ""]
|
||||
|
|
@ -41,4 +41,3 @@ digraph {
|
|||
13 -> 14 [ ]
|
||||
0 -> 15 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ bb4: {
|
|||
|
||||
bb5: {
|
||||
Unreachable()
|
||||
break
|
||||
}
|
||||
|
||||
bb6: {
|
||||
|
|
@ -49,6 +50,7 @@ bb10: {
|
|||
|
||||
bb11: {
|
||||
Unreachable()
|
||||
break
|
||||
}
|
||||
|
||||
bb12: {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ digraph {
|
|||
3 [ label = ""]
|
||||
4 [ label = ""]
|
||||
5 [ label = ""]
|
||||
6 [ label = "Unreachable()"]
|
||||
6 [ label = "Unreachable()\nbreak"]
|
||||
7 [ label = ""]
|
||||
8 [ label = ""]
|
||||
9 [ label = "Unreachable()"]
|
||||
|
|
@ -42,4 +42,3 @@ digraph {
|
|||
9 -> 3 [ ]
|
||||
0 -> 15 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ bb5: {
|
|||
|
||||
bb6: {
|
||||
Unreachable()
|
||||
break
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ digraph {
|
|||
1 [ label = ""]
|
||||
2 [ label = ""]
|
||||
3 [ label = ""]
|
||||
4 [ label = "Unreachable()"]
|
||||
4 [ label = "Unreachable()\nbreak $0"]
|
||||
5 [ label = ""]
|
||||
6 [ label = ""]
|
||||
0 -> 1 [ ]
|
||||
|
|
@ -21,4 +21,3 @@ digraph {
|
|||
3 -> 5 [ ]
|
||||
5 -> 6 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ bb3: {
|
|||
|
||||
bb4: {
|
||||
Unreachable()
|
||||
break $0
|
||||
}
|
||||
|
||||
bb5: {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ digraph {
|
|||
3 [ label = ""]
|
||||
4 [ label = ""]
|
||||
5 [ label = "Unreachable()"]
|
||||
6 [ label = "Unreachable()"]
|
||||
6 [ label = "Unreachable()\nbreak $0"]
|
||||
7 [ label = "Unreachable()"]
|
||||
8 [ label = ""]
|
||||
9 [ label = "Unreachable()"]
|
||||
9 [ label = "Unreachable()\nbreak $1"]
|
||||
10 [ label = "$return = <value>"]
|
||||
11 [ label = ""]
|
||||
12 [ label = "Unreachable()"]
|
||||
|
|
@ -35,4 +35,3 @@ digraph {
|
|||
11 -> 12 [ ]
|
||||
0 -> 13 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ bb5: {
|
|||
|
||||
bb6: {
|
||||
Unreachable()
|
||||
break $0
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
|
@ -41,6 +42,7 @@ bb8: {
|
|||
|
||||
bb9: {
|
||||
Unreachable()
|
||||
break $1
|
||||
}
|
||||
|
||||
bb10: {
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ digraph {
|
|||
1 [ label = ""]
|
||||
2 [ label = ""]
|
||||
3 [ label = ""]
|
||||
4 [ label = "Unreachable()"]
|
||||
4 [ label = "Unreachable()\nbreak"]
|
||||
5 [ label = ""]
|
||||
6 [ label = ""]
|
||||
7 [ label = ""]
|
||||
8 [ label = ""]
|
||||
9 [ label = "Unreachable()"]
|
||||
9 [ label = "Unreachable()\nbreak"]
|
||||
10 [ label = ""]
|
||||
11 [ label = "$return = <value>"]
|
||||
12 [ label = ""]
|
||||
|
|
@ -70,4 +70,3 @@ digraph {
|
|||
20 -> 21 [ ]
|
||||
0 -> 22 [ ]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ bb3: {
|
|||
|
||||
bb4: {
|
||||
Unreachable()
|
||||
break
|
||||
}
|
||||
|
||||
bb5: {
|
||||
|
|
@ -41,6 +42,7 @@ bb8: {
|
|||
|
||||
bb9: {
|
||||
Unreachable()
|
||||
break
|
||||
}
|
||||
|
||||
bb10: {
|
||||
|
|
|
|||
Loading…
Reference in a new issue