gccrs: Generate backend drop flags for conditional moves - #4798
gccrs: Generate backend drop flags for conditional moves#4798Lishin1215 wants to merge 2 commits into
Conversation
|
|
||
| private: | ||
| std::set<HirId> definitely_dead; | ||
| std::set<HirId> conditionally_dropped; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 = 30Here I only have HirId 30, but the flag is associated with HirId 10.
So I need:
move_sources[30] = 10Then the backend can use HirId 10 to find the correct flag and clear it:
x.flag = false;There was a problem hiding this comment.
What if multiple id are moved within the same location ? I guess any product type that move by construction would have multiple ids associated to the same hir id ?
There was a problem hiding this comment.
Hi, this is a good point.
The current patch only records move sources for direct whole-local moves such as let y = x.
For these moves, push_assignment() is called with a move_site.
Product type will go through a different path and do not carry a move_site, so they are not recorded in move_sources. Therefore, multiple source HirIds will not currently be associated with the same key.
I am thinking of keeping the current map and adding a comment such as:
// This may need to be extended to std::map<HirId, std::set<HirId>>
// to support product moves in the future.Or do you think it would still be better to use a set now?
Please let me know if I misunderstood anything. Thanks!
There was a problem hiding this comment.
Either the comment or the change to map would be good!
Also, is there any reason why you're using map/set and not unordered_set/unordered_map ?
There was a problem hiding this comment.
You're right. I don't think there is any ordering requirement here.
I'll change them to std::unordered_map and std::unordered_set.
Thanks!
There was a problem hiding this comment.
I've added the comment and changed std::map and std::set to std::unordered_map and std::unordered_set. Thanks!
There was a problem hiding this comment.
I've now made the case you mentioned explicitly unsupported in a new commit (gccrs: Reject multiple move sources in product-type expressions)
If multiple moved IDs are associated with the same move site, gccrs emits a diagnostic using rust_sorry_at.
I've also added test! Thanks.
90f2b12 to
6a26056
Compare
| protected: // Helpers to add BIR statements | ||
| void push_assignment (PlaceId lhs, AbstractExpr *rhs, location_t location) | ||
| void push_assignment (PlaceId lhs, AbstractExpr *rhs, location_t location, | ||
| HirId move_site = UNKNOWN_HIRID) |
There was a problem hiding this comment.
Could we benefit from an optional ?
There was a problem hiding this comment.
Yes, I've changed move_site to optional now. Thanks!
There was a problem hiding this comment.
Thank you, I feel it makes it clearer that no value can be provided instead of relying uniquely on function overloading.
| // Keep the existing backend handling for straight-line CFGs. | ||
| const bool record_straight_line_backend_drops = is_straight_line (function); | ||
|
|
||
| std::set<HirId> dead_drop_hir_ids; |
There was a problem hiding this comment.
I've got a feeling it would be better to pack those into a class / structure ? This way we could add annotate_drop_statement and record_drop_label as member functions and avoid carrying this state around everywhere as 4 different arguments. It would be either this if we make them member function or a single argument if we pass that struct by ref.
There was a problem hiding this comment.
I've packed the four pieces of state into a DropAnalysisResults struct and now pass it by reference as a single argument!
| private: | ||
| std::set<HirId> definitely_dead; | ||
| std::set<HirId> conditionally_dropped; | ||
| std::map<HirId, HirId> move_sources; |
There was a problem hiding this comment.
What if multiple id are moved within the same location ? I guess any product type that move by construction would have multiple ids associated to the same hir id ?
8ff0583 to
c019cd7
Compare
P-E-P
left a comment
There was a problem hiding this comment.
Great work! One last nitpick and I'll merge this!
| #include <unordered_map> | ||
| #include <unordered_set> |
There was a problem hiding this comment.
You cannot rely on system import, you instead need to rely on rust-system.h
There was a problem hiding this comment.
Thanks for pointing this out!
I've updated it to rely on rust-system.h.
c019cd7 to
e355579
Compare
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.
Pass the struct expression HIR ID through BIR so moves from the same expression can be identified. For now, report the case as unsupported when an expression moves more than one value. gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Pass the struct expression HIR ID. * checks/errors/borrowck/rust-bir-builder-internal.h (AbstractBuilder::push_tmp_assignment): Propagate move sites. (AbstractBuilder::move_place): Likewise. (AbstractBuilder::move_all): Likewise. * checks/errors/borrowck/rust-bir-drop-analysis.cc (annotate_drop_statements): Reject multiple move sources. gcc/testsuite/ChangeLog: * rust/compile/drop-conditional-product-move.rs: New test. Signed-off-by: Lishin <lishin1008@gmail.com>
e355579 to
0fe4006
Compare
This patch connects the conditional BIR Drop analysis to the existing backend cleanup.
For now, in a conditional move case like:
The BIR Drop analysis classifies the cleanup of x as:
The backend then creates a Drop flag for x.
Conceptually, the generated backend code behaves like: