This is an archive of the discontinued LLVM Phabricator instance.

[SEH] Fix wrong argument passes to the call of OutlinedFinally.
ClosedPublic

Authored by jyu2 on Aug 17 2023, 4:45 PM.

Details

Summary

When return out of __try block. In this test case, currently "false" is
passed to the OutlinedFinally call, "true" should be passed to indicate abnormal
terminations.

The rule: Except _leave and fall-through at the end, all other exits
in a _try (return/goto/continue/break) are considered as abnormal
terminations, NormalCleanupDestSlot is used to indicate abnormal
terminations.

The problem is, during the processing abnormal termination,
the ExitSwitch is used. However, in this case, Existswitch is route out.

One way to fix is to skip route it without a switch. So proper
abnormal termination's code could be generated.

IR before change:
invoke.cont: ; preds = %entry

invoke void @llvm.seh.try.begin()
        to label %invoke.cont1 unwind label %ehcleanup

invoke.cont1: ; preds = %invoke.cont

%1 = load volatile i32, ptr @y, align 4
%inc2 = add nsw i32 %1, 1
store volatile i32 %inc2, ptr @y, align 4
invoke void @llvm.seh.try.end()
        to label %invoke.cont3 unwind label %ehcleanup

invoke.cont3: ; preds = %invoke.cont1

%2 = call ptr @llvm.localaddress()
call void @"?fin$0@0@foo@@"(i8 noundef 0, ptr noundef %2)
ret void

IR after change:
invoke.cont: ; preds = %entry

invoke void @llvm.seh.try.begin()
        to label %invoke.cont1 unwind label %ehcleanup

invoke.cont1: ; preds = %invoke.cont

%1 = load volatile i32, ptr @y, align 4
%inc2 = add nsw i32 %1, 1
store volatile i32 %inc2, ptr @y, align 4
store volatile i32 1, ptr %cleanup.dest.slot, align 4
invoke void @llvm.seh.try.end()
        to label %invoke.cont3 unwind label %ehcleanup

invoke.cont3: ; preds = %invoke.cont1

%2 = call ptr @llvm.localaddress()
%cleanup.dest = load i32, ptr %cleanup.dest.slot, align 4
%3 = icmp ne i32 %cleanup.dest, 0
%4 = zext i1 %3 to i8
call void @"?fin$0@0@foo@@"(i8 noundef %4, ptr noundef %2)

...

Diff Detail

Event Timeline

jyu2 created this revision.Aug 17 2023, 4:45 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 17 2023, 4:45 PM
jyu2 requested review of this revision.Aug 17 2023, 4:45 PM
jyu2 edited the summary of this revision. (Show Details)Aug 21 2023, 6:20 AM
rnk added inline comments.Aug 21 2023, 10:28 AM
clang/lib/CodeGen/CGCleanup.cpp
882

This seems like it's only necessary when exiting a __try scope, but this check affects all exits from C++ cleanup scopes. Is there a way to check if there is an active try scope? When do we need to signal abnormal termination via normal control flow?

rnk added inline comments.Aug 21 2023, 10:53 AM
clang/lib/CodeGen/CGCleanup.cpp
882

You can consider usesSEHTry , but it will require some type checking and casting: https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html#a275d0f7f778c6ece58722aabde9b6d86

jyu2 updated this revision to Diff 552157.Aug 21 2023, 4:01 PM
jyu2 added inline comments.
clang/lib/CodeGen/CGCleanup.cpp
882

Thanks @rnk! That is good point. I was thinking I just turn off this optimization when EHa is used.

Can I use currentFunctionUsesSEHTry() instead?
Thanks.

rnk accepted this revision.Aug 21 2023, 4:05 PM

lgtm, thanks!

clang/lib/CodeGen/CGCleanup.cpp
881

I think FD is unused now that you use currentFunctionUsesSEHTry

This revision is now accepted and ready to land.Aug 21 2023, 4:05 PM
This revision was landed with ongoing or failed builds.Aug 21 2023, 5:12 PM
This revision was automatically updated to reflect the committed changes.