[LLVMdev] Re: setjmp/longjmp interoperable between llvm and gcc?

Kurt Harriman kharriman at greenplum.com
Fri Nov 25 11:39:35 PST 2005


On Mon, 21 Nov 2005 16:53:58 -0600 (CST), Chris wrote:
 >On Mon, 21 Nov 2005, Kurt Harriman wrote:
 >> I would like to build an x86 executable consisting of a number of
 >> subsystems (mostly legacy C code).  One subsystem will be compiled
 >> to native code using llvm.  It calls, and is called by, the other
 >> subsystems, many of which have to be compiled using gcc because they
 >> use small amounts of inline assembly.  All of the subsystems catch
 >> and throw errors to one another using setjmp/longjmp.
 >>
 >> When gcc-built code calls longjmp(), the destination might be a
 >> setjmp() in llvm-built code, and vice versa.  At present the
 >> gcc-built code uses the setjmp/longjmp implementations provided
 >> by the gnu C library; and presumably the llvm-built code will use
 >> llvm's setjmp/longjmp intrinsics.  Are the two implementations
 >> safely interoperable?
 >
 >No, not right now.  EH in general doesn't interoperate.  This will be
 >fixed in the future, but is problematic for the time being.
 >
 >> Alternatives would be to force the llvm-built code to use the libgc
 >> setjmp/longjmp; force the gcc-built code to use a setjmp/longjmp
 >> borrowed from llvm; or perhaps make each setjmp tag the jmpbuf to
 >> show which flavor of longjmp is required.
 >
 >I depends on what sort of thing you want to do.  Another option is to
 >compile everything with LLVM if possible.
 >
 >-Chris

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)) )

/*-----------------------------------------*/




More information about the llvm-dev mailing list