Skip to content

Instantly share code, notes, and snippets.

@rikusalminen
Created January 31, 2013 11:55
Show Gist options
  • Save rikusalminen/4682367 to your computer and use it in GitHub Desktop.
Save rikusalminen/4682367 to your computer and use it in GitHub Desktop.
LLVM trampoline fun
declare void @llvm.init.trampoline(i8*, i8*, i8*);
declare i8* @llvm.adjust.trampoline(i8*);
define i32 @foo(i32* nest %ptr, i32 %val)
{
%x = load i32* %ptr
%sum = add i32 %x, %val
ret i32 %sum
}
define i32 @main(i32, i8**)
{
%closure = alloca i32
store i32 13, i32* %closure
%closure_ptr = bitcast i32* %closure to i8*
%tramp_buf = alloca [32 x i8], align 4
%tramp_ptr = getelementptr [32 x i8]* %tramp_buf, i32 0, i32 0
call void @llvm.init.trampoline(
i8* %tramp_ptr,
i8* bitcast (i32 (i32*, i32)* @foo to i8*),
i8* %closure_ptr)
%ptr = call i8* @llvm.adjust.trampoline(i8* %tramp_ptr)
%fp = bitcast i8* %ptr to i32(i32)*
%val2 = call i32 %fp (i32 13)
; %val = call i32 @foo(i32* %closure, i32 42);
ret i32 %val2
}
@molenzwiebel
Copy link

Note that this example will not work on most platforms, due to the memory used for the trampoline not being executable. Changing

%tramp_buf = alloca [32 x i8], align 4
%tramp_ptr = getelementptr [32 x i8]* %tramp_buf, i32 0, i32 0

to a mmap call to allocate executable memory will work:

%tramp_ptr = call i8* @"\01_mmap"(i8* null, i64 32, i32 7, i32 4098, i32 0, i64 0)

Don't forget to declare mmap (declare i8* @"\01_mmap"(i8*, i64, i32, i32, i32, i64)), and note that it might be named differently on other systems. Compile mmap(NULL, 32, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0) with clang -S -emit-llvm to see what it is on your machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment