[LLVMdev] building a jump table in LLVM IR

Joshua Cranmer pidgeot18 at gmail.com
Tue Jan 8 12:19:13 PST 2013

On 1/7/2013 10:51 AM, Tom Roeder wrote:
> AFAIK, this won't work: the way I want to use a jump table requires me
> to get a pointer into the table that I can use as a function pointer
> to call the original function in a normal call instruction. If I just
> add a new basic block in some containing function with a call
> instruction and somehow get a pointer to that instruction, then this
> does satisfy the goal of putting the new instructions somewhere, but a
> call through that pointer will not do the right thing, since it will
> be calling into the middle of the containing function, then calling
> the original function (whereas I want it to just jump to the original
> function directly so it doesn't mess up the call stack). The
> fundamental stumbling block is that it seems to be impossible (by
> design) to jump in this manner in LLVM IR.

Note that LLVM does do tail-call optimization, even if the called 
function is an indirect function call. E.g.:

extern void (**jmptbl)();

void foo(int idx) {

will produce the LLVM IR:
@jmptbl = external global void (...)**

define void @foo(i32 %x) nounwind uwtable {
   %1 = sext i32 %x to i64
   %2 = load void (...)*** @jmptbl, align 8
   %3 = getelementptr inbounds void (...)** %2, i64 %1
   %4 = load void (...)** %3, align 8
   tail call void (...)* %4() nounwind
   ret void

and the x86-64 assembly:
     .type    foo, at function
foo:                                    # @foo
# BB#0:
     movslq    %edi, %rcx
     movq    jmptbl(%rip), %rdx
     xorb    %al, %al
     jmpq    *(%rdx,%rcx,8)  # TAILCALL
     .size    foo, .Ltmp0-foo

This does require optimization levels to be applied (-O1 does it, -O0 
does not), and it won't guarantee that a stack frame will not be 
produced for a glue function.

Joshua Cranmer
News submodule owner
DXR coauthor

More information about the llvm-dev mailing list