Skip to content

gccrs: Emit block scope drops through TRY_FINALLY_EXPR#4685

Open
Lishin1215 wants to merge 3 commits into
Rust-GCC:masterfrom
Lishin1215:drop-cleanup-try-finally
Open

gccrs: Emit block scope drops through TRY_FINALLY_EXPR#4685
Lishin1215 wants to merge 3 commits into
Rust-GCC:masterfrom
Lishin1215:drop-cleanup-try-finally

Conversation

@Lishin1215

@Lishin1215 Lishin1215 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

This PR consists of 3 commits.

It changes block-scope Drop emission to use a TRY_FINALLY_EXPR cleanup instead of
appending drop calls directly to the block body.

For example, a block like:

{
    let x = Droppable;
}

is lowered as:

try {
    let x = Droppable;
} finally {
    drop(x);
}

This follows the same general cleanup/finally shape used by the Go frontend for defer handling.

For now, this PR only covers block-scope drops. Function-scope drops, explicit return cleanup,
break/continue are left for follow-up work.


commit 1

gccrs: Add helper to build scope drop cleanup

gcc/rust/ChangeLog:

* backend/rust-compile-drop.cc
(CompileDrop::build_current_scope_drop_cleanup): New function to
build current scope drop calls as a statement tree.
(CompileDrop::emit_current_scope_drop_calls): Use it.
* backend/rust-compile-drop.h
(CompileDrop::build_current_scope_drop_cleanup): Declare.

commit 2

gccrs: Emit block scope drops through TRY_FINALLY_EXPR

gcc/rust/ChangeLog:

* backend/rust-compile-block.cc
(CompileBlock::visit): Build current scope drop cleanup and pass it
when popping the block.
* backend/rust-compile-context.h
(Context::pop_block): Use pop_block_impl.
(Context::pop_block_with_cleanup): New function for popping a block
with cleanup code.
(Context::pop_block_impl): New helper that adds the block statements
directly, or wraps them in TRY_FINALLY_EXPR when cleanup is present.

commit 3

gccrs: Use EH_ELSE_EXPR in block Drop TRY_FINALLY_EXPR

gcc/rust/ChangeLog:

* backend/rust-compile-context.h
(Context::pop_block_impl): Wrap Drop cleanup in an EH_ELSE_EXPR.

Note:

TRY_FINALLY_EXPR cleanup originally caused drop-nested-block-scope.rs to fail
to link with an undefined reference to __gccrs_personality_v0.

This version wraps the cleanup operand in EH_ELSE_EXPR, using the Drop cleanup
as the normal cleanup and an empty exceptional cleanup for now.
With that, drop-nested-block-scope.rs links and passes locally.

if (body == NULL_TREE)
body = build_empty_stmt (cleanup_locus);

tree exceptional_cleanup = build_empty_stmt (cleanup_locus);

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 followed the cleanup shape described in gccint 11.7.6, the TRY_FINALLY_EXPR
cleanup operand can be an EH_ELSE_EXPR selector.

I did not add the empty volatile asm used by rustc_codegen_gcc to keep the
EH_ELSE_EXPR around, because the normal cleanup side here contains the actual
Drop cleanup, and the relevant tests pass with an empty exceptional cleanup.

@Lishin1215 Lishin1215 marked this pull request as ready for review July 8, 2026 11:57
Add CompileDrop::build_current_scope_drop_cleanup to build the drop
calls for the current scope as one statement tree.

This allows a follow-up patch to place the same cleanup tree in a
TRY_FINALLY_EXPR.

gcc/rust/ChangeLog:

	* backend/rust-compile-drop.cc
	(CompileDrop::build_current_scope_drop_cleanup): New function to
	build current scope drop calls as a statement tree.
	(CompileDrop::emit_current_scope_drop_calls): Use it.
	* backend/rust-compile-drop.h
	(CompileDrop::build_current_scope_drop_cleanup): Declare.

Signed-off-by: Lishin <lishin1008@gmail.com>
Add Context::pop_block_with_cleanup for blocks that need cleanup.

Use it from CompileBlock so block-scope drops are emitted in a
TRY_FINALLY_EXPR cleanup instead of at the end of the block body.

gcc/rust/ChangeLog:

	* backend/rust-compile-block.cc
	(CompileBlock::visit): Build current scope drop cleanup and
	pass it when popping the block.
	* backend/rust-compile-context.h
	(Context::pop_block): Use pop_block_impl.
	(Context::pop_block_with_cleanup): New function for popping
	a block with cleanup code.
	(Context::pop_block_impl): New helper that adds the block
	statements directly, or wraps them in TRY_FINALLY_EXPR when
	cleanup is present.

Signed-off-by: Lishin <lishin1008@gmail.com>
Use the Drop cleanup as the normal cleanup and an empty statement as
the exceptional cleanup.

This keeps block-scope Drop cleanup on normal control-flow exits without
requiring the gccrs EH personality while stack unwinding is not implemented.

gcc/rust/ChangeLog:

	* backend/rust-compile-context.h:
	(Context::pop_block_impl): Wrap Drop cleanup in an EH_ELSE_EXPR.

Signed-off-by: Lishin <lishin1008@gmail.com>
@Lishin1215 Lishin1215 force-pushed the drop-cleanup-try-finally branch from 0dad855 to f470bb9 Compare July 9, 2026 08:29
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