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:
Ali Rezvani 2024-05-10 17:52:30 +03:30 committed by GitHub
parent 5e36e0d575
commit 20f643063e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 40 additions and 16 deletions

View file

@ -288,6 +288,8 @@ impl GetterReturn {
return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false);
}
// Ignore irrelevant elements.
BasicBlockElement::Break(_) => {}
}
}

View file

@ -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,

View file

@ -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)));

View file

@ -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 [ ]
}

View file

@ -9,4 +9,5 @@ bb0: {
bb1: {
Unreachable()
break $0
}

View file

@ -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 [ ]
}

View file

@ -25,6 +25,7 @@ bb4: {
bb5: {
Unreachable()
break
}
bb6: {
@ -49,6 +50,7 @@ bb10: {
bb11: {
Unreachable()
break
}
bb12: {

View file

@ -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 [ ]
}

View file

@ -29,6 +29,7 @@ bb5: {
bb6: {
Unreachable()
break
}
bb7: {

View file

@ -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 [ ]
}

View file

@ -21,6 +21,7 @@ bb3: {
bb4: {
Unreachable()
break $0
}
bb5: {

View file

@ -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 [ ]
}

View file

@ -29,6 +29,7 @@ bb5: {
bb6: {
Unreachable()
break $0
}
bb7: {
@ -41,6 +42,7 @@ bb8: {
bb9: {
Unreachable()
break $1
}
bb10: {

View file

@ -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 [ ]
}

View file

@ -21,6 +21,7 @@ bb3: {
bb4: {
Unreachable()
break
}
bb5: {
@ -41,6 +42,7 @@ bb8: {
bb9: {
Unreachable()
break
}
bb10: {