On Tue, 2025-06-17 at 20:22 -0700, Alexei Starovoitov wrote: > On Sun, Jun 15, 2025 at 1:55 AM Anton Protopopov > <a.s.protopopov@xxxxxxxxx> wrote: > > > > The final line generates an indirect jump. The > > format of the indirect jump instruction supported by BPF is > > > > BPF_JMP|BPF_X|BPF_JA, SRC=0, DST=Rx, off=0, imm=fd(M) > > [...] > Uglier alternatives is to redesign the gotox encoding and > drop ld_imm64 and *=8 altogether. > Then gotox jmp_table[R5] will be like jumbo insn that > does *=8 and load inside and JIT emits all that. > But it's ugly and likely has other downsides. I talked to Alexei and Yonghong off-list, and we seem to be in agreement that having a single gotox capturing both the map and the offset looks more elegant. E.g.: gotox imm32[dst_reg]; Where imm32 is an fd of the map corresponding to the jump table, and dst-reg is an offset inside the table (it could also be an index). So, instead of a current codegen: 0000000000000000 <foo>: ... 1: w1 = w1 2: r1 <<= 0x3 3: r2 = 0x0 ll 0000000000000018: R_BPF_64_64 .BPF.JT.0.0 5: r2 += r1 6: r1 = *(u64 *)(r2 + 0x0) 7: gotox r1 0000000000000038: R_BPF_64_64 .BPF.JT.0.0 LLVM would produce: 0000000000000000 <foo>: ... 1: w1 = w1 2: r1 <<= 0x3 3: gotox r1 0000000000000038: R_BPF_64_64 .BPF.JT.0.0 This sequence leaks a bit less implementation details and avoids a check for correspondence between load and gotox instructions. It will require using REG_AX on the jit side. LLVM side implementation is not hard, as it directly maps to `br_jt` selection DAG instruction. Anton, wdyt?