Skip to content

Commit

Permalink
fix: condition if and ternaries.
Browse files Browse the repository at this point in the history
  • Loading branch information
rzvxa committed Jun 12, 2024
1 parent 5ed21a6 commit ff03d5f
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 153 deletions.
45 changes: 30 additions & 15 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.record_ast_nodes();
self.visit_expression(&stmt.test);
let test_node = self.retrieve_recorded_ast_nodes().into_iter().next();
self.cfg.append_condition(test_node);
self.cfg.append_condition_to(start_of_condition_graph_ix, test_node);

/* cfg */
let end_of_condition_graph_ix = self.cfg.current_node_ix;
Expand Down Expand Up @@ -678,13 +678,18 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
let kind = AstKind::ConditionalExpression(self.alloc(expr));
self.enter_node(kind);

/* cfg - condition basic block */
let before_conditional_graph_ix = self.cfg.current_node_ix;
let start_of_condition_graph_ix = self.cfg.new_basic_block_normal();
/* cfg */

self.record_ast_nodes();
self.visit_expression(&expr.test);
let test_node = self.retrieve_recorded_ast_nodes().into_iter().next();
self.cfg.append_condition(test_node);
self.cfg.append_condition_to(start_of_condition_graph_ix, test_node);

/* cfg */
let before_conditional_expr_graph_ix = self.cfg.current_node_ix;
let after_condition_graph_ix = self.cfg.current_node_ix;
// conditional expression basic block
let before_consequent_expr_graph_ix = self.cfg.new_basic_block_normal();
/* cfg */
Expand All @@ -702,25 +707,28 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
let after_alternate_graph_ix = self.cfg.current_node_ix;
/* bb after conditional expression joins consequent and alternate */
let after_conditional_graph_ix = self.cfg.new_basic_block_normal();
/* cfg */

self.cfg.add_edge(
before_conditional_graph_ix,
start_of_condition_graph_ix,
EdgeType::Normal,
);

self.cfg.add_edge(
after_consequent_expr_graph_ix,
after_conditional_graph_ix,
EdgeType::Normal,
);
self.cfg.add_edge(
before_conditional_expr_graph_ix,
after_condition_graph_ix,
before_consequent_expr_graph_ix,
EdgeType::Jump,
);

self.cfg.add_edge(
before_conditional_expr_graph_ix,
start_alternate_graph_ix,
EdgeType::Normal,
);
self.cfg.add_edge(after_condition_graph_ix, start_alternate_graph_ix, EdgeType::Normal);
self.cfg.add_edge(after_alternate_graph_ix, after_conditional_graph_ix, EdgeType::Normal);
/* cfg */

self.leave_node(kind);
}

Expand All @@ -744,7 +752,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.record_ast_nodes();
self.visit_expression(test);
let test_node = self.retrieve_recorded_ast_nodes().into_iter().next();
self.cfg.append_condition(test_node);
self.cfg.append_condition_to(test_graph_ix, test_node);
}

/* cfg */
Expand Down Expand Up @@ -925,13 +933,18 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
let kind = AstKind::IfStatement(self.alloc(stmt));
self.enter_node(kind);

/* cfg - condition basic block */
let before_if_stmt_graph_ix = self.cfg.current_node_ix;
let start_of_condition_graph_ix = self.cfg.new_basic_block_normal();
/* cfg */

self.record_ast_nodes();
self.visit_expression(&stmt.test);
let test_node = self.retrieve_recorded_ast_nodes().into_iter().next();
self.cfg.append_condition(test_node);
self.cfg.append_condition_to(start_of_condition_graph_ix, test_node);

/* cfg */
let before_if_stmt_graph_ix = self.cfg.current_node_ix;
let after_test_graph_ix = self.cfg.current_node_ix;
let before_consequent_stmt_graph_ix = self.cfg.new_basic_block_normal();
/* cfg */

Expand All @@ -956,9 +969,11 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
/* cfg - bb after if statement joins consequent and alternate */
let after_if_graph_ix = self.cfg.new_basic_block_normal();

self.cfg.add_edge(before_if_stmt_graph_ix, start_of_condition_graph_ix, EdgeType::Normal);

self.cfg.add_edge(after_consequent_stmt_graph_ix, after_if_graph_ix, EdgeType::Normal);

self.cfg.add_edge(before_if_stmt_graph_ix, before_consequent_stmt_graph_ix, EdgeType::Jump);
self.cfg.add_edge(after_test_graph_ix, before_consequent_stmt_graph_ix, EdgeType::Jump);

if let Some((start_of_alternate_stmt_graph_ix, after_alternate_stmt_graph_ix)) =
else_graph_ix
Expand Down Expand Up @@ -1285,7 +1300,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.record_ast_nodes();
self.visit_expression(&stmt.test);
let test_node = self.retrieve_recorded_ast_nodes().into_iter().next();
self.cfg.append_condition(test_node);
self.cfg.append_condition_to(condition_graph_ix, test_node);

/* cfg - body basic block */
let body_graph_ix = self.cfg.new_basic_block_normal();
Expand Down
24 changes: 19 additions & 5 deletions crates/oxc_semantic/src/control_flow/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,15 @@ impl<'a> ControlFlowGraphBuilder<'a> {
ControlFlowGraph { graph: self.graph, basic_blocks: self.basic_blocks }
}

/// # Panics
pub fn current_basic_block(&mut self) -> &mut BasicBlock {
self.basic_block_mut(self.current_node_ix)
}

/// # Panics
pub fn basic_block_mut(&mut self, basic_block: BasicBlockId) -> &mut BasicBlock {
let idx = *self
.graph
.node_weight(self.current_node_ix)
.node_weight(basic_block)
.expect("expected `self.current_node_ix` to be a valid node index in self.graph");
self.basic_blocks
.get_mut(idx)
Expand Down Expand Up @@ -145,8 +149,8 @@ impl<'a> ControlFlowGraphBuilder<'a> {
);
}

pub fn append_condition(&mut self, node: Option<AstNodeId>) {
self.push_instruction(InstructionKind::Condition, node);
pub fn append_condition_to(&mut self, block: BasicBlockId, node: Option<AstNodeId>) {
self.push_instruction_to(block, InstructionKind::Condition, node);
}

pub fn append_iteration(&mut self, node: Option<AstNodeId>, kind: IterationInstructionKind) {
Expand Down Expand Up @@ -199,7 +203,17 @@ impl<'a> ControlFlowGraphBuilder<'a> {

#[inline]
pub(self) fn push_instruction(&mut self, kind: InstructionKind, node_id: Option<AstNodeId>) {
self.current_basic_block().instructions.push(Instruction { kind, node_id });
self.push_instruction_to(self.current_node_ix, kind, node_id);
}

#[inline]
pub(self) fn push_instruction_to(
&mut self,
block: BasicBlockId,
kind: InstructionKind,
node_id: Option<AstNodeId>,
) {
self.basic_block_mut(block).instructions.push(Instruction { kind, node_id });
}

#[must_use]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@ digraph {
0 [ label = "" ]
1 [ label = "VariableDeclaration" ]
2 [ label = "" ]
3 [ label = "ExpressionStatement\nCondition(CallExpression)" ]
4 [ label = "" ]
3 [ label = "ExpressionStatement" ]
4 [ label = "Condition(CallExpression)" ]
5 [ label = "" ]
6 [ label = "" ]
7 [ label = "" ]
1 -> 0 [ label = "Error(Implicit)" ]
3 -> 2 [ label = "Error(Implicit)" ]
1 -> 3 [ label = "NewFunction" ]
4 -> 2 [ label = "Error(Implicit)" ]
5 -> 2 [ label = "Error(Implicit)" ]
6 -> 2 [ label = "Error(Implicit)" ]
7 -> 2 [ label = "Error(Implicit)" ]
3 -> 4 [ label = "Normal" ]
5 -> 7 [ label = "Normal" ]
4 -> 5 [ label = "Jump" ]
4 -> 6 [ label = "Normal" ]
3 -> 4 [ label = "Jump" ]
3 -> 5 [ label = "Normal" ]
5 -> 6 [ label = "Normal" ]
6 -> 7 [ label = "Normal" ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ bb2: {

bb3: {
statement
condition
}

bb4: {

condition
}

bb5: {
Expand All @@ -31,3 +30,7 @@ bb5: {
bb6: {

}

bb7: {

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ input_file: crates/oxc_semantic/tests/integration/cfg_fixtures/conditional_expre
---
digraph {
0 [ label = "" ]
1 [ label = "VariableDeclaration\nCondition(CallExpression)" ]
2 [ label = "" ]
1 [ label = "VariableDeclaration" ]
2 [ label = "Condition(CallExpression)" ]
3 [ label = "" ]
4 [ label = "VariableDeclaration" ]
4 [ label = "" ]
5 [ label = "VariableDeclaration" ]
1 -> 0 [ label = "Error(Implicit)" ]
2 -> 0 [ label = "Error(Implicit)" ]
3 -> 0 [ label = "Error(Implicit)" ]
4 -> 0 [ label = "Error(Implicit)" ]
5 -> 0 [ label = "Error(Implicit)" ]
1 -> 2 [ label = "Normal" ]
3 -> 5 [ label = "Normal" ]
2 -> 3 [ label = "Jump" ]
2 -> 4 [ label = "Normal" ]
1 -> 2 [ label = "Jump" ]
1 -> 3 [ label = "Normal" ]
3 -> 4 [ label = "Normal" ]
4 -> 5 [ label = "Normal" ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ bb0: {

bb1: {
statement
condition
}

bb2: {

condition
}

bb3: {

}

bb4: {

}

bb5: {
statement
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,39 @@ digraph {
1 [ label = "" ]
2 [ label = "" ]
3 [ label = "IfStatement" ]
4 [ label = "" ]
5 [ label = "Condition(LogicalExpression)" ]
6 [ label = "BlockStatement\nreturn <value>" ]
7 [ label = "unreachable" ]
8 [ label = "BlockStatement\nreturn <value>" ]
9 [ label = "unreachable" ]
10 [ label = "return <value>" ]
11 [ label = "unreachable" ]
12 [ label = "" ]
4 [ label = "Condition(LogicalExpression)" ]
5 [ label = "" ]
6 [ label = "" ]
7 [ label = "BlockStatement\nreturn <value>" ]
8 [ label = "unreachable" ]
9 [ label = "BlockStatement\nreturn <value>" ]
10 [ label = "unreachable" ]
11 [ label = "return <value>" ]
12 [ label = "unreachable" ]
13 [ label = "" ]
1 -> 0 [ label = "Error(Implicit)" ]
3 -> 2 [ label = "Error(Implicit)" ]
1 -> 3 [ label = "NewFunction" ]
4 -> 2 [ label = "Error(Implicit)" ]
5 -> 2 [ label = "Error(Implicit)" ]
3 -> 4 [ label = "Normal" ]
3 -> 5 [ label = "Normal" ]
4 -> 5 [ label = "Normal" ]
6 -> 2 [ label = "Error(Implicit)" ]
4 -> 5 [ label = "Normal" ]
4 -> 6 [ label = "Normal" ]
5 -> 6 [ label = "Normal" ]
7 -> 2 [ label = "Error(Implicit)" ]
6 -> 7 [ label = "Unreachable" , style = "dotted" ]
8 -> 2 [ label = "Error(Implicit)" ]
7 -> 8 [ label = "Unreachable" , style = "dotted" ]
9 -> 2 [ label = "Error(Implicit)" ]
8 -> 9 [ label = "Unreachable" , style = "dotted" ]
10 -> 2 [ label = "Error(Implicit)" ]
7 -> 10 [ label = "Normal" ]
5 -> 6 [ label = "Jump" ]
5 -> 8 [ label = "Normal" ]
9 -> 10 [ label = "Normal" ]
9 -> 10 [ label = "Unreachable" , style = "dotted" ]
11 -> 2 [ label = "Error(Implicit)" ]
10 -> 11 [ label = "Unreachable" , style = "dotted" ]
12 -> 0 [ label = "Error(Implicit)" ]
1 -> 12 [ label = "Normal" ]
3 -> 4 [ label = "Normal" ]
8 -> 11 [ label = "Normal" ]
6 -> 7 [ label = "Jump" ]
3 -> 9 [ label = "Normal" ]
10 -> 11 [ label = "Normal" ]
12 -> 2 [ label = "Error(Implicit)" ]
11 -> 12 [ label = "Unreachable" , style = "dotted" ]
13 -> 0 [ label = "Error(Implicit)" ]
1 -> 13 [ label = "Normal" ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,43 @@ bb3: {
}

bb4: {

condition
}

bb5: {
condition

}

bb6: {

}

bb7: {
statement
return <value>
}

bb7: {
bb8: {
unreachable
}

bb8: {
bb9: {
statement
return <value>
}

bb9: {
bb10: {
unreachable
}

bb10: {
bb11: {
return <value>
}

bb11: {
bb12: {
unreachable
}

bb12: {
bb13: {

}
Loading

0 comments on commit ff03d5f

Please sign in to comment.