Just in case anyone stumbles across this thread and wonders, "so how do I access setjmp/longjmp (via LLVM's SJLJ intrinsics), here is a snippet (playground link) that should help.
#![feature(link_llvm_intrinsics)]
extern crate libc; // 0.2.42
use std::mem;
use std::time::{SystemTime};
const WIDTH: usize = mem::size_of::<usize>()*8;
type Checkpoint = [i8; WIDTH];
static mut JUMP_POINT: Checkpoint = [0; WIDTH];
extern {
#[link_name = "llvm.setjmp"]
pub fn setjmp(a: *mut i8) -> i32;
#[link_name = "llvm.longjmp"]
pub fn longjmp(a: *mut i8, b: i32) -> ();
}
fn now() {
let now = SystemTime::now();
println!("{:?}", now);
let ptr: *mut Checkpoint = unsafe { &mut JUMP_POINT };
let franken_pointer: *mut i8 = unsafe { mem::transmute(ptr) };
unsafe { longjmp(franken_pointer, 1) };
}
fn main() {
//let mut buff: Checkpoint = [0; WIDTH];
let ptr: *mut Checkpoint = unsafe { &mut JUMP_POINT } ;
let franken_pointer: *mut i8 = unsafe { mem::transmute(ptr) };
let rc = unsafe { setjmp(franken_pointer) };
print!("{}\n", rc);
if rc != 0 {
println!("early return!");
} else {
println!("jump point was successfully set.");
now();
}
}
Some remarks:
I've used the type alias Checkpoint rather than setjmp_buf (as per GCC's docs) because it feels more descriptive to me.
Checkpoint is wider than strictly necessary. LLVM's documentation says that it only needs a "five word buffer".
i32 @llvm.eh.sjlj.setjmp(i8* %setjmp_buf)...
The single parameter is a pointer to a five word buffer in which the calling context is saved. The front end places the frame pointer in the first word, and the target implementation of this intrinsic should place the destination address for a llvm.eh.sjlj.longjmp in the second word. The following three words are available for use in a target-specific manner.