[llvm-dev] 32-bit pointers, ARM and BPF
Adrian Szyndela via llvm-dev
llvm-dev at lists.llvm.org
Thu Oct 12 00:35:28 PDT 2017
Hi,
We're trying to use BPF on a 32-bit ARM. However, we have issues with
llvm.bpf.pseudo.
Let's consider a simple program (t.c):
#include <uapi/linux/bpf.h>
typedef unsigned long long u64;
u64 bpf_pseudo_fd(u64, u64) asm("llvm.bpf.pseudo");
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *) BPF_FUNC_map_lookup_elem;
int test_ok(void *ctx) {
// 0s below are for example
void *v = bpf_map_lookup_elem(bpf_pseudo_fd(0,0), 0);
return 0;
}
We put it into
clang -O2 -target armv7l-unknown-linux-gnueabi -emit-llvm -S t.c
to get
define i32 @test_ok(i8* nocapture readnone) local_unnamed_addr #0 {
%2 = tail call i64 @llvm.bpf.pseudo(i64 0, i64 0)
%3 = trunc i64 %2 to i32
%4 = inttoptr i32 %3 to i8*
%5 = tail call i8* inttoptr (i32 1 to i8* (i8*, i8*)*)(i8* %4, i8*
null) #1
ret i32 0
}
Note the 'trunc' instruction, which is there, because return type of
llvm.bpf.pseudo is i64, and it is converted to 32-bit pointer.
Now, after
llc -march=bpf t.ll
we get
test_ok: # @test_ok
ld_pseudo r1, 0, 0
r1 <<= 32
r1 >>= 32
r2 = 0
call 1
r0 = 0
exit
The return value of llvm.bpf.pseudo (u64) is truncated by shift-left +
shift-right. After the operation BPF verifier does not consider the
value in r1 as pointer anymore, and complains when it is passed as a
pointer to bpf_map_lookup_elem (call 1).
We have changed the return type of llvm.bpf.pseudo to pointer for our
purposes (see below), but what is the "correct" way of handling it?
include/llvm/IR/IntrinsicsBPF.td:
def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>;
+ Intrinsic<[llvm_ptr_ty], [llvm_i64_ty, llvm_i64_ty]>;
Thanks,
Adrian
More information about the llvm-dev
mailing list