llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.82k stars 11.46k forks source link

LLVM 13 Regression: `__builtin_longjmp` not working with `-Oz` #51071

Open 2e1c2d01-a631-41c2-93fe-8d40b95d8607 opened 3 years ago

2e1c2d01-a631-41c2-93fe-8d40b95d8607 commented 3 years ago
Bugzilla Link 51729
Version trunk
OS Linux
Blocks llvm/llvm-project#50580 llvm/llvm-project#51489
Attachments Repro, Repro (with workaround added), bsjlj.ll diff with D109248 applied
CC @aeubanks,@DimitryAndric,@RKSimon,@tstellar

Extended Description

Tested with 13.0.0-rc2 and 12.0.1. The repro could be made shorter.

Note that this issue is not necessarily specific to X86_64. A segfault is also observed for ARM.

$ cat bsjlj.c
void foo(void **jb, int n);
void bar(int n);

void
bsj(void **jb, volatile int n)
{
  if (__builtin_setjmp(jb) == 0) {
    foo(jb, n);
  } else {
    bar(n);
  }
}

void
blj(void **jb)
{
  __builtin_longjmp(jb, 1);
}

int printf (const char *__restrict __format, ...);

void
foo(void **jb, int n)
{
  printf("foo: n = %d\n", n);
  blj(jb);
}

void
bar(int n)
{
  printf("bar: n = %d\n", n);
}

int
main(int argc, char *argv[] __attribute__((unused)))
{
  void *jb[5];
  bsj(jb, argc);
  bsj(jb, argc+1);

  return 0;
}
$ /usr/lib/llvm/12/bin/clang --target=x86_64-linux-gnu bsjlj.c -Oz -Wall -Wextra -Wundef

$ ./a.out
foo: n = 1
bar: n = 1
foo: n = 2
bar: n = 2

$ /usr/lib/llvm/13/bin/clang --target=x86_64-linux-gnu bsjlj.c -Oz -Wall -Wextra -Wundef

$ ./a.out
foo: n = 1
bar: n = 32764
Segmentation fault
tstellar commented 2 years ago

mentioned in issue llvm/llvm-project#51489

DimitryAndric commented 3 years ago

Thanks for the investigation, Dimitry.

Now I am pretty much sure that the switch of the default pass manager just manifests a long-standing bug in __builtin_setjmp.

Should this be resolved as a duplicate of llvm/llvm-project#49578 ?

I would keep this one as it seems more general (bug 50234 appears to refer specifically to PowerPC, at first), and more people are CC'd on it.

2e1c2d01-a631-41c2-93fe-8d40b95d8607 commented 3 years ago

Thanks for the investigation, Dimitry.

Now I am pretty much sure that the switch of the default pass manager just manifests a long-standing bug in __builtin_setjmp.

Should this be resolved as a duplicate of llvm/llvm-project#49578 ?

DimitryAndric commented 3 years ago

Note this appears to have regressed with https://github.com/llvm/llvm-project/commit/669ddd1e9b12 ("Turn on the new pass manager by default"), at least that is what I see when doing a bisection.

However, this commit only turned on the new pass manager. If I compile the example with -flegacy-pass-manager, it does not segfault.

And vice versa, if I use any clang before 669ddd1e9b12 with -fno-legacy-pass-manager or -fexperimental-new-pass-manager, it does segfault. I went back to the llvmorg-10-init branch point, but even that makes it crash.

Ergo, there is something about the new pass manager that influences this particular crash scenario.

tstellar commented 2 years ago

The deadline for requesting fixes for the release has passed. This bug is being removed from the LLVM 13.0.1 release milestone. If you have a fix or think this bug is important enough to block the release, please explain why in a comment and add the bug back to the LLVM 13.0.1 release milestone.