/*
 * Reduced test for a SPARC wrong-code bug: a constant held in a
 * windowed (call-saved) register before sigsetjmp() is reused after
 * sigsetjmp() returns the second time.  On SPARC, siglongjmp()
 * restores %l and %i registers from the register window save area,
 * that is, with the values they held at siglongjmp() time, not at
 * sigsetjmp() time.
 *
 * Build: gcc -O2 -m64 sj.c sj2.c -o sj && ./sj
 * Expect: "ok".  With the bug: SIGSEGV or SIGBUS.
 */
#include <setjmp.h>
#include <stdio.h>
#include <string.h>

extern sigjmp_buf *exc;
extern void use(void *p);
extern void thrower(const char *a, const char *b, const char *c);

sigjmp_buf *exc;

void
victim(void *a, void *b, void *c)
{
	char		big[8192];
	void	   *va = a;
	void	   *vb = b;
	void	   *vc = c;
	sigjmp_buf	jb;
	sigjmp_buf *save = exc;
	volatile int r;

	use(&va);
	use(&vb);
	use(&vc);
	r = sigsetjmp(jb, 0);
	if (r == 0)
	{
		int			i;

		exc = &jb;
		for (i = 0; i < 3; i++)
		{
			use(big);
			thrower("one", "two", "three");
		}
		memset(big, 0, sizeof(big));
		use(big);
		exc = save;
	}
	else
	{
		exc = save;
		use(&va);
		use(&vb);
		use(&vc);
	}
}

int
main(void)
{
	int			x, y, z;

	victim(&x, &y, &z);
	puts("ok");
	return 0;
}
