Skip to content

gccrs: Generate backend drop flags for conditional moves - #4798

Open
Lishin1215 wants to merge 2 commits into
Rust-GCC:masterfrom
Lishin1215:bir-cfg-conditional-drop-backend
Open

gccrs: Generate backend drop flags for conditional moves#4798
Lishin1215 wants to merge 2 commits into
Rust-GCC:masterfrom
Lishin1215:bir-cfg-conditional-drop-backend

Conversation

@Lishin1215

Copy link
Copy Markdown
Contributor

This patch connects the conditional BIR Drop analysis to the existing backend cleanup.

For now, in a conditional move case like:

fn f(cond: bool) {
    let x = Droppable { value: 1 };


    if cond {
        let y = x;
    }
}

The BIR Drop analysis classifies the cleanup of x as:

Drop(x): Conditional

The backend then creates a Drop flag for x.
Conceptually, the generated backend code behaves like:

try {
    bool flag = false;
    let x = Droppable { value: 1 };
    flag = true;


    if (cond) {
        let y = x;
        flag = false;
    }
}
finally {
    if (flag) {
        flag = false;
        Drop(x);
    }
}
  • When x is initialized, the flag is set to true.
  • When x is moved, the flag is cleared to false, so Drop(x) is skipped during cleanup.
  • When x is not moved, the flag remains true, so Drop(x) is called.

Track whole-local initialization across BIR control-flow branches.

When a local is moved on only some paths, mark its Drop as conditional.
Keep the existing backend handling for straight-line CFGs and add tests
for static, dead and conditional Drops.

gcc/rust/ChangeLog:

	* checks/errors/borrowck/rust-bir-drop-analysis.cc
	(struct BlockInitializationState): New struct.
	(is_straight_line): New function.
	(set_initialized): Likewise.
	(set_uninitialized): Likewise.
	(merge_state): Likewise.
	(update_state_for_statement): Likewise.
	(classify_drop): Likewise.
	(compute_entry_states): Likewise.
	(record_drop_for_straight_line_backend): Likewise.
	(annotate_drop_statements): Likewise.
	(DropAnalysis::analyze): Propagate initialization state across the
	CFG and classify Drop statements.
	* checks/errors/borrowck/rust-bir-drop-analysis.h: Update class
	comment.

gcc/testsuite/ChangeLog:

	* rust/borrowck/drop_analysis_conditional_move.rs: New test.

Signed-off-by: Lishin <lishin1008@gmail.com>
Generate runtime Drop flags for Conditional Drops.
Use BIR analysis results to identify locals that need Drop flags and the moves that clear those flags.
The HIR backend sets a flag when initialization, clears it after a move, and checks it before cleanup.

gcc/rust/ChangeLog:

	* backend/rust-compile-context.h
	(Context::insert_drop_flag): New function.
	(Context::lookup_drop_flag): Likewise.
	(Context::drop_flags): New member.
	* backend/rust-compile-drop-builder.cc
	(DropBuilder::maybe_create_drop_flag): New function.
	(DropBuilder::drop_flag_assignment): Likewise.
	* backend/rust-compile-drop-builder.h
	(DropBuilder::maybe_create_drop_flag): New declaration.
	(DropBuilder::drop_flag_assignment): Likewise.
	* backend/rust-compile-drop.cc
	(CompileDrop::build_current_scope_drop_cleanup): Check Drop flags before
	running conditional Drops.
	* backend/rust-compile-pattern.cc
	(CompilePatternLet::visit): Set the Drop flag after initialization.
	* backend/rust-compile-stmt.cc
	(CompileStmt::visit): Create Drop flags and clear them after moves.
	* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
	(ExprStmtBuilder::visit): Pass expression HirIds to BIR.
	* checks/errors/borrowck/rust-bir-builder-internal.h
	(AbstractBuilder::push_assignment): Pass move-site HirIds.
	(AbstractExprBuilder::return_place): Likewise.
	* checks/errors/borrowck/rust-bir-drop-analysis.cc
	(is_straight_line): Remove.
	(record_drop_for_backend): Rename from
	record_drop_for_straight_line_backend.
	(annotate_drop_statements): Record conditional Drops and move
	sources.
	(DropAnalysis::clear): Clear the new analysis results.
	(DropAnalysis::needs_drop_flag): New function.
	(DropAnalysis::lookup_move_source): Likewise.
	(DropAnalysis::analyze): Record results for the backend.
	* checks/errors/borrowck/rust-bir-drop-analysis.h
	(DropAnalysis::needs_drop_flag): New declaration.
	(DropAnalysis::lookup_move_source): Likewise.
	(DropAnalysis::conditionally_dropped): New member.
	(DropAnalysis::move_sources): Likewise.
	* checks/errors/borrowck/rust-bir.h
	(Statement::make_assignment): Accept a move-site HirId.
	(Statement::Statement): Likewise.
	(Statement::get_move_site): New function.
	(Statement::move_site): New member.

gcc/testsuite/ChangeLog:

	* rust/execute/drop-conditional-move.rs: New test.

private:
std::set<HirId> definitely_dead;
std::set<HirId> conditionally_dropped;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added conditionally_dropped to save those that are classified as Conditional.
I need this information to determine whether a variable requires a Drop flag.
It is used when generating the backend code.

private:
std::set<HirId> definitely_dead;
std::set<HirId> conditionally_dropped;
std::map<HirId, HirId> move_sources;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added move_sources to map the move expression HirId to the source local HirId.

Since the move expression x and the source local x have different HirIds.
And also I need the source local x's HirId to find the Drop flag,
so this map lets me find the source HirId from the move expression HirId.

For example:

...
  let x = Droppable();  // source local HirId = 10
  x.flag = true;  // associate with source local HirId 10
...
  let y = x;  // move expression HirId = 30

Here I only have HirId 30, but the flag is associated with HirId 10.
So I need:

  move_sources[30] = 10

Then the backend can use HirId 10 to find the correct flag and clear it:

x.flag = false;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant