For function arguments, current implementation will do
needed sign/zero extension for 32/64-bit integer types
in callee and 8/16-bit types in caller.
This patch forced sign/zero extension to be done in
callee. Alternatively, with a slightly different
implementation, sign/zero extension can be done in caller.
Similarly for function return value, current implementation
will do needed sign/zero extension for 32/64-bit integer
types in caller and 8/16-bit return values in callee.
This patch forced sign/zero extension in caller.
Alternatively, with a slightly different implementation,
sign/zero extension can be done in callee.
$ cat t.c unsigned char bar(); char foo(short a) { if (bar() != a) return a; else return a + 1; } $ clang -target bpf -O2 -g -c t.c $ llvm-objdump -S t.o ... ; char foo(short a) { 0: bf 16 00 00 00 00 00 00 r6 = r1 ; if (bar() != a) return a; else return a + 1; 1: bf 67 00 00 00 00 00 00 r7 = r6 2: 67 07 00 00 30 00 00 00 r7 <<= 48 3: c7 07 00 00 30 00 00 00 r7 s>>= 48 4: 85 10 00 00 ff ff ff ff call -1 5: bf 01 00 00 00 00 00 00 r1 = r0 6: 57 01 00 00 ff 00 00 00 r1 &= 255 7: b7 00 00 00 01 00 00 00 r0 = 1 8: 1d 71 01 00 00 00 00 00 if r1 == r7 goto +1 <LBB0_2> 9: b7 00 00 00 00 00 00 00 r0 = 0 0000000000000050 <LBB0_2>: ; if (bar() != a) return a; else return a + 1; 10: 0f 60 00 00 00 00 00 00 r0 += r6 ; } 11: 95 00 00 00 00 00 00 00 exit
In the above example, 16-bit argument value has sign extension
is done in callee before it is used. 8-bit return value has
zero extension done in caller before the value is used.
Note that we mostly care about 8-bit return value sign/zero
extension in the context of bpf program calling kernel functions
since for x86_64, the caller can directly access 8-bit %al
register while bpf can only access 32/64-bit registers.