[llvm-dev] Usage of the jumptable attribute
CompilerCrash via llvm-dev
llvm-dev at lists.llvm.org
Sat Aug 31 00:22:06 PDT 2019
Hello everyone,
I'm new to LLVM (which is a really great project by the way) and I hope
this is the right place for my question.
In the LLVM Language Reference Manual I found the "jumptable" function
attribute, which seems to be exactly what I need for my project (where I
want to add one level of indirection to every function call), but I have
trouble figuring out, how to use it correctly.
I wrote my own transformation pass (using LLVM 8.0.1) to add this
attribute as well as unnamed_addr (I'm aware that this might break some
programs, but jumptable requires it) to every function definition:
// includes ...
using namespace llvm;
namespace {
struct MyPass : public ModulePass {
static char ID;
MyPass() : ModulePass(ID) {}
bool runOnModule(Module &M) override {
for (Function &F : M.getFunctionList()) {
if (!F.isDeclaration()) {
F.setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
F.addFnAttr(Attribute::JumpTable);
}
}
return true;
}
};
}
char MyPass::ID = 0;
static RegisterPass<MyPass> X("mypass", "My Pass");
And I wrote a program test.c:
#include <stdio.h>
void foo() {
puts("Hello World");
}
int main() {
foo();
}
I compiled it to test.ll and ran it through opt:
clang -O0 -emit-llvm -S -o test.ll test.c
build/bin/opt -load build/lib/LLVMMyPass.so -mypass -S -o
test.out.ll test.ll
The output (test.out.ll) was identical to test.ll except for the 3
occurrences of jumptable and the last 2 occurrences of unnamed_addr:
; ModuleID = 'test.ll'
source_filename = "test.c"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@.str = private unnamed_addr constant [12 x i8] c"Hello World\00",
align 1
; Function Attrs: jumptable noinline nounwind optnone uwtable
define dso_local void @foo() unnamed_addr #0 {
%1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x
i8]* @.str, i32 0, i32 0))
ret void
}
declare dso_local i32 @puts(i8*) #1
; Function Attrs: jumptable noinline nounwind optnone uwtable
define dso_local i32 @main() unnamed_addr #0 {
call void @foo()
ret i32 0
}
attributes #0 = { jumptable noinline nounwind optnone uwtable
"no-jump-tables"="false"
; ... many more attributes ...
}
attributes #1 = {
; ... many more attributes ...
}
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"}
Finally, I executed:
build/bin/llc -o test.out.s test.out.ll
clang -o test.out.native test.out.s
objdump --disassemble-all test.out.native
I hoped to see some kind of jump table being used for the call to foo
(maybe even the plt mechanism the dynamic library calls use), but it is
just a "normal" jump to foo's address:
0000000000400500 <foo>:
400500: 55 push %rbp
400501: 48 89 e5 mov %rsp,%rbp
400504: 48 bf c0 05 40 00 00 movabs $0x4005c0,%rdi
40050b: 00 00 00
40050e: e8 cd fe ff ff callq 4003e0 <puts at plt>
400513: 5d pop %rbp
400514: c3 retq
400515: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40051c: 00 00 00
40051f: 90 nop
0000000000400520 <main>:
400520: 55 push %rbp
400521: 48 89 e5 mov %rsp,%rbp
400524: e8 d7 ff ff ff callq 400500 <foo>
400529: 31 c0 xor %eax,%eax
40052b: 5d pop %rbp
40052c: c3 retq
40052d: 0f 1f 00 nopl (%rax)
So, what am I doing wrong? The documentation indicates that the jump
table is created at code-generation time. So I guess my pass works fine
and I just need to get the code generator to process the jumptable
attribute somehow? I found the createJumpInstrTablesPass in
include/CodeGen/Passes.h, but it seems like it's never used.
Thanks in advance
Daniel
More information about the llvm-dev
mailing list