I'm having success with the third alternative, in which each setjmp
tags the jmpbuf to show which flavor of longjmp is required.
Below is the header file that I defined to wrap the setjmp/longjmp calls.
ZZ_SIGSETJMP augments the jmpbuf with a function pointer to a longjmp
call that is compiled in the same compilation unit as the setjmp.
ZZ_SIGLONGJMP calls through this function pointer.
This way, an llvm-compiled longjmp is used for every longjmp to an
llvm-compiled setjmp; and a gcc-compiled longjmp is used for every
longmp to a gcc-compiled setjmp. C++ exceptions or destructors
wouldn't be handled properly, but that doesn't matter in this
application because it is all in C.
Note also that it is necessary to invoke llc with the
--enable-correct-eh-support flag to enable setjmp/longjmp.
Regards,
... kurt
/*-------------setjmpwrapper.h-------------*/
#include <setjmp.h>
/* llvm doesn't support sigsetjmp; use plain setjmp instead */
#undef sigsetjmp
#define sigjmp_buf jmp_buf
#define sigsetjmp(x,y) setjmp(x)
#define siglongjmp longjmp
typedef struct ZZ_SIGJMP_BUF
{
void (*zz_siglongjmp)(struct ZZ_SIGJMP_BUF *self, int value)
__attribute__((__noreturn__));
sigjmp_buf jmpbuf;
} ZZ_SIGJMP_BUF;
static void
zz_siglongjmp(struct ZZ_SIGJMP_BUF *self, int value)
__attribute__((__noreturn__))
__attribute__((__always_inline__));
void
zz_siglongjmp(struct ZZ_SIGJMP_BUF *self, int value)
{
siglongjmp(self->jmpbuf, value);
}
#define ZZ_SIGSETJMP(zz_sigjmp_buf, savesigs) \
( (zz_sigjmp_buf).zz_siglongjmp = zz_siglongjmp, \
sigsetjmp((zz_sigjmp_buf).jmpbuf, (savesigs)) )
#define ZZ_SIGLONGJMP(zz_sigjmp_buf, value) \
( (zz_sigjmp_buf).zz_siglongjmp(&(zz_sigjmp_buf), (value)) )
/*-----------------------------------------*/