[clang] [llvm] [Clang][BPF] Allow sign/zero extension for call parameters with int/uint types (PR #84874)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 12 17:38:16 PDT 2024


yonghong-song wrote:

The following is an example to show 'unsigned int' case. The current behavior (i.e., without this patch):
```
$ cat u.c
void foo(unsigned);
void bar(unsigned a, unsigned b) {
  foo(a + b);
}
$ clang --target=bpf -O2 -c u.c && llvm-objdump -d u.o

u.o:    file format elf64-bpf

Disassembly of section .text:

0000000000000000 <bar>:
       0:       0f 12 00 00 00 00 00 00 r2 += r1
       1:       bf 21 00 00 00 00 00 00 r1 = r2
       2:       85 10 00 00 ff ff ff ff call -0x1
       3:       95 00 00 00 00 00 00 00 exit
```
Basically, we didn't do zero extension for 'uint' argument in the above. We expect the callee 'foo' to do proper zero extension. If both 'foo' and 'far' are functions written in bpf programs, we should be okay. But if 'foo' is a kfunc (e.g., a kernel function for a specific arch e.g. riscv) and the arch will just use the full register 'r1' to do operation without zero extension of 32-bit value, the wrong results could happen.

With this patch, we will have the following asm code,
```
$ clang --target=bpf -O2 -c u.c && llvm-objdump -d u.o

u.o:    file format elf64-bpf

Disassembly of section .text:

0000000000000000 <bar>:
       0:       0f 12 00 00 00 00 00 00 r2 += r1
       1:       67 02 00 00 20 00 00 00 r2 <<= 0x20
       2:       77 02 00 00 20 00 00 00 r2 >>= 0x20
       3:       bf 21 00 00 00 00 00 00 r1 = r2
       4:       85 10 00 00 ff ff ff ff call -0x1
       5:       95 00 00 00 00 00 00 00 exit
```
That is, we will do zero extension for uint argument here. This will guarantee correct value if 'foo' is a kernel function. If 'foo' is not a kernel function, the 'foo' will be able to use r2 directly as a 32-bit value without doing shifting, one example like below
```
long g1, g2;
__attribute__((noinline)) void foo(unsigned a) {
  if (a == g1) g2 = 1;
  else g2 = 2;  
}

....
0000000000000000 <foo>:
       0:       18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0x0 ll
       2:       79 23 00 00 00 00 00 00 r3 = *(u64 *)(r2 + 0x0)
       3:       b7 02 00 00 01 00 00 00 r2 = 0x1
       4:       1d 13 01 00 00 00 00 00 if r3 == r1 goto +0x1 <LBB0_2>
       5:       b7 02 00 00 02 00 00 00 r2 = 0x2

0000000000000030 <LBB0_2>:
       6:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x0 ll
       8:       7b 21 00 00 00 00 00 00 *(u64 *)(r1 + 0x0) = r2
       9:       95 00 00 00 00 00 00 00 exit
```


https://github.com/llvm/llvm-project/pull/84874


More information about the cfe-commits mailing list