[llvm] [RFC][BPF] Support Jump Table (PR #133856)

Anton Protopopov via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 14 03:17:51 PDT 2025


aspsk wrote:

Hi @yonghong-song!

I was trying different switch variants, simple ones work like magic, so we're definitely going the right direction.

One simple case fails for me though. Namely, in the example below LLVM generates an unreachable instruction. Could you take a look please? An example source program is
```
SEC("syscall") int foo(struct simple_ctx *ctx)
{
        switch (ctx->x) {
        case 0:
                ret_user = 2;
                break;
        case 11:
                ret_user = 3;
                break;
        case 27:
                ret_user = 4;
                break;
        case 31:
                ret_user = 5;
                break;
        default:
                ret_user = 19;
                break;
        }

        return 0;
}
```
Then the object file looks like
```
0000000000000700 <foo>:
;       switch (ctx->x) {
     224:       79 11 00 00 00 00 00 00 r1 = *(u64 *)(r1 + 0x0)
     225:       25 01 0f 00 1f 00 00 00 if r1 > 0x1f goto +0xf <foo+0x88>
     226:       67 01 00 00 03 00 00 00 r1 <<= 0x3
     227:       18 02 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 r2 = 0xa8 ll
                0000000000000718:  R_BPF_64_64  .rodata
     229:       0f 12 00 00 00 00 00 00 r2 += r1
     230:       79 21 00 00 00 00 00 00 r1 = *(u64 *)(r2 + 0x0)
     231:       0d 01 00 00 00 00 00 00 gotox r1
     232:       05 00 08 00 00 00 00 00 goto +0x8 <foo+0x88>
     233:       b7 01 00 00 02 00 00 00 r1 = 0x2
;       switch (ctx->x) {
     234:       05 00 07 00 00 00 00 00 goto +0x7 <foo+0x90>
     235:       b7 01 00 00 04 00 00 00 r1 = 0x4
;               break;
     236:       05 00 05 00 00 00 00 00 goto +0x5 <foo+0x90>
     237:       b7 01 00 00 03 00 00 00 r1 = 0x3
;               break;
     238:       05 00 03 00 00 00 00 00 goto +0x3 <foo+0x90>
     239:       b7 01 00 00 05 00 00 00 r1 = 0x5
;               break;
     240:       05 00 01 00 00 00 00 00 goto +0x1 <foo+0x90>
     241:       b7 01 00 00 13 00 00 00 r1 = 0x13
     242:       18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0x0 ll
                0000000000000790:  R_BPF_64_64  ret_user
     244:       7b 12 00 00 00 00 00 00 *(u64 *)(r2 + 0x0) = r1
;       return 0;
     245:       b4 00 00 00 00 00 00 00 w0 = 0x0
     246:       95 00 00 00 00 00 00 00 exit
```

Now, the jump table is
```
242, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 237, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 235, 241, 241, 241, 239
```
And the check 
```
225:       25 01 0f 00 1f 00 00 00 if r1 > 0x1f goto +0xf <foo+0x88>
```
makes sure that `r1` is always loaded from the jump table.

And this makes the instruction
```
232:       05 00 08 00 00 00 00 00 goto +0x8 <foo+0x88>
```
unreachable.

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


More information about the llvm-commits mailing list