Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llvm.eh.sjlj.setjmp needs returns_twice (to make nested __builtin_setjmp work on PowerPC) #49578

Open
xtkoba mannequin opened this issue May 6, 2021 · 4 comments
Open
Labels
bugzilla Issues migrated from bugzilla llvm:core

Comments

@xtkoba
Copy link
Mannequin

xtkoba mannequin commented May 6, 2021

Bugzilla Link 50234
Version trunk
OS Linux
Attachments Repro

Extended Description

The attached C program (named ppc_bsjlj.c) behaves incorrectly when compiled with optimization level -O1 or higher for PPC targets.

For 32-bit PPC

$ clang --target=powerpc-unknown-linux-gnu -O3 -c ppc_bsjlj.c

results in the output

value = 268566576
value = 268566596

where the two lines should be identical.

Similarly, for ppc64le

$ clang --target=powerpc64le-unknown-linux-gnu -O3 -c ppc_bsjlj.c

results in

value = 268566608
value = 268566648

Note that in the program the value of the local variable n is not changed between __builtin_setjmp and the corresponding __builtin_longjmp. Indeed it is const-qualified.

@xtkoba
Copy link
Mannequin Author

xtkoba mannequin commented Aug 13, 2021

FWIW, it seems that the workaround code in the repro does not work any more with Clang/LLVM version 12.0.1 or 13.0.0-rc1. With 12.0.1,

$ /usr/lib/llvm/12/bin/clang --target=powerpc64le-unknown-linux-musl -O3 ppc_bsjlj.c -DWORKAROUND=1

results in the hexdump'ed output

00000000 76 61 6c 75 65 20 3d 20 32 37 34 38 37 38 31 30 |value = 27487810|
00000010 37 38 35 36 0a f0 15 83 01 40 #8228.....@|

and with 13.0.0-rc1,

$ /usr/lib/llvm/13/bin/clang --target=powerpc64le-unknown-linux-musl -O3 ppc_bsjlj.c -DWORKAROUND=1

results in

00000000 76 61 6c 75 65 20 3d 20 32 37 34 38 37 38 31 30 |value = 27487810|
00000010 37 38 35 36 0a e0 15 83 01 40 #8228.....@|

I have no idea whether this is a separate issue or not. Note that this time musl is used as a target, and so the generated executable becomes a PIE, which I am not sure is relevant.

@xtkoba
Copy link
Mannequin Author

xtkoba mannequin commented Aug 31, 2021

Disassembly of main (compiled with -O1)
I investigated the disassembly of main. Full disasm is attached, but below are shown the key instructions in chronological order:

10b10: 50 80 83 e8 ld 4, -32688(3) # value of n loaded
10b1c: 70 75 63 38 addi 3, 3, 30064 # addr of format string
10b30: 70 00 61 f8 std 3, 112(1) # addr of format string saved
10b38: 78 00 81 f8 std 4, 120(1) # value of n saved
10b44: bd 02 00 48 bl 0x10e00 # call printf (1st)

10ba8: c0 80 83 38 addi 4, 3, -32576 # addr of jb2
10bb8: 78 00 81 f8 std 4, 120(1) # addr of jb2 saved (boom!)

10b78: 70 00 61 e8 ld 3, 112(1) # addr of format string reloaded
10b7c: 78 00 81 e8 ld 4, 120(1) # value of n (corrupt) reloaded
10b80: 81 02 00 48 bl 0x10e00 # call printf (2nd)

The value of n is saved at 120(1), but afterwards it is overwritten by the address of jb2.

Similarly, the funny output with -DWORKAROUND=1 shown in the previous comment seems due to the saved address of format string being corrupted afterwards (note that print_ulong is inlined).

I have no idea how to fix this for now.

@xtkoba
Copy link
Mannequin Author

xtkoba mannequin commented Sep 3, 2021

It seems that __builtin_setjmp needs attribute returns_twice.

Proposed change: https://reviews.llvm.org/D109248

@DimitryAndric
Copy link
Collaborator

mentioned in issue llvm/llvm-bugzilla-archive#51729

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm:core
Projects
None yet
Development

No branches or pull requests

1 participant