Преглед изворни кода

cranelift: Support stores

Signed-off-by: Afonso Bordado <afonsobordado@az8.co>
Signed-off-by: Quentin Monnet <quentin@isovalent.com>
Afonso Bordado пре 2 година
родитељ
комит
6e12fe7a69
2 измењених фајлова са 227 додато и 0 уклоњено
  1. 49 0
      src/cranelift.rs
  2. 178 0
      tests/cranelift.rs

+ 49 - 0
src/cranelift.rs

@@ -220,6 +220,47 @@ impl CraneliftCompiler {
                     self.set_dst(bcx, &insn, ext);
                 }
 
+                // BPF_ST and BPF_STX class
+                ebpf::ST_B_IMM
+                | ebpf::ST_H_IMM
+                | ebpf::ST_W_IMM
+                | ebpf::ST_DW_IMM
+                | ebpf::ST_B_REG
+                | ebpf::ST_H_REG
+                | ebpf::ST_W_REG
+                | ebpf::ST_DW_REG => {
+                    let ty = match insn.opc {
+                        ebpf::ST_B_IMM | ebpf::ST_B_REG => I8,
+                        ebpf::ST_H_IMM | ebpf::ST_H_REG => I16,
+                        ebpf::ST_W_IMM | ebpf::ST_W_REG => I32,
+                        ebpf::ST_DW_IMM | ebpf::ST_DW_REG => I64,
+                        _ => unreachable!(),
+                    };
+                    let is_imm = match insn.opc {
+                        ebpf::ST_B_IMM | ebpf::ST_H_IMM | ebpf::ST_W_IMM | ebpf::ST_DW_IMM => true,
+                        ebpf::ST_B_REG | ebpf::ST_H_REG | ebpf::ST_W_REG | ebpf::ST_DW_REG => false,
+                        _ => unreachable!(),
+                    };
+
+                    let value = if is_imm {
+                        self.insn_imm64(bcx, &insn)
+                    } else {
+                        self.insn_src(bcx, &insn)
+                    };
+
+                    let narrow = if ty != I64 {
+                        bcx.ins().ireduce(ty, value)
+                    } else {
+                        value
+                    };
+
+                    let base = self.insn_dst(bcx, &insn);
+                    self.reg_store(bcx, base, insn.off, narrow);
+                }
+
+                ebpf::ST_W_XADD => unimplemented!(),
+                ebpf::ST_DW_XADD => unimplemented!(),
+
                 // BPF_ALU class
                 // TODO Check how overflow works in kernel. Should we &= U32MAX all src register value
                 // before we do the operation?
@@ -722,4 +763,12 @@ impl CraneliftCompiler {
 
         bcx.ins().load(ty, flags, base, offset as i32)
     }
+    fn reg_store(&mut self, bcx: &mut FunctionBuilder, base: Value, offset: i16, val: Value) {
+        // TODO: Emit bounds checks
+
+        let mut flags = MemFlags::new();
+        flags.set_endianness(Endianness::Little);
+
+        bcx.ins().store(flags, val, base, offset as i32);
+    }
 }

+ 178 - 0
tests/cranelift.rs

@@ -636,6 +636,18 @@ test_cranelift!(
     0x2211
 );
 
+test_cranelift!(
+    test_cranelift_ldxh_same_reg,
+    "
+    mov r0, r1
+    sth [r0], 0x1234
+    ldxh r0, [r0]
+    exit
+    ",
+    [0xff, 0xff],
+    0x1234
+);
+
 test_cranelift!(
     test_cranelift_ldxw_all,
     "
@@ -833,3 +845,169 @@ test_cranelift!(
     ",
     0x100000004
 );
+
+test_cranelift!(
+    test_cranelift_stb,
+    "
+    stb [r1+2], 0x11
+    ldxb r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xcc, 0xdd],
+    0x11
+);
+
+test_cranelift!(
+    test_cranelift_stdw,
+    "
+    stdw [r1+2], 0x44332211
+    ldxdw r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
+    0x44332211
+);
+
+test_cranelift!(
+    test_cranelift_sth,
+    "
+    sth [r1+2], 0x2211
+    ldxh r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd],
+    0x2211
+);
+
+test_cranelift!(
+    test_cranelift_stw,
+    "
+    stw [r1+2], 0x44332211
+    ldxw r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
+    0x44332211
+);
+
+test_cranelift!(
+    test_cranelift_stxb,
+    "
+    mov32 r2, 0x11
+    stxb [r1+2], r2
+    ldxb r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xcc, 0xdd],
+    0x11
+);
+
+test_cranelift!(
+    test_cranelift_stxb_all,
+    "
+    mov r0, 0xf0
+    mov r2, 0xf2
+    mov r3, 0xf3
+    mov r4, 0xf4
+    mov r5, 0xf5
+    mov r6, 0xf6
+    mov r7, 0xf7
+    mov r8, 0xf8
+    stxb [r1], r0
+    stxb [r1+1], r2
+    stxb [r1+2], r3
+    stxb [r1+3], r4
+    stxb [r1+4], r5
+    stxb [r1+5], r6
+    stxb [r1+6], r7
+    stxb [r1+7], r8
+    ldxdw r0, [r1]
+    be64 r0
+    exit
+    ",
+    [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+    0xf0f2f3f4f5f6f7f8
+);
+
+test_cranelift!(
+    test_cranelift_stxb_all2,
+    "
+    mov r0, r1
+    mov r1, 0xf1
+    mov r9, 0xf9
+    stxb [r0], r1
+    stxb [r0+1], r9
+    ldxh r0, [r0]
+    be16 r0
+    exit
+    ",
+    [0xff, 0xff],
+    0xf1f9
+);
+
+test_cranelift!(
+    test_cranelift_stxb_chain,
+    "
+    mov r0, r1
+    ldxb r9, [r0+0]
+    stxb [r0+1], r9
+    ldxb r8, [r0+1]
+    stxb [r0+2], r8
+    ldxb r7, [r0+2]
+    stxb [r0+3], r7
+    ldxb r6, [r0+3]
+    stxb [r0+4], r6
+    ldxb r5, [r0+4]
+    stxb [r0+5], r5
+    ldxb r4, [r0+5]
+    stxb [r0+6], r4
+    ldxb r3, [r0+6]
+    stxb [r0+7], r3
+    ldxb r2, [r0+7]
+    stxb [r0+8], r2
+    ldxb r1, [r0+8]
+    stxb [r0+9], r1
+    ldxb r0, [r0+9]
+    exit
+    ",
+    [0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+    0x2a
+);
+
+test_cranelift!(
+    test_cranelift_stxdw,
+    "
+    mov r2, -2005440939
+    lsh r2, 32
+    or r2, 0x44332211
+    stxdw [r1+2], r2
+    ldxdw r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
+    0x8877665544332211
+);
+
+test_cranelift!(
+    test_cranelift_stxh,
+    "
+    mov32 r2, 0x2211
+    stxh [r1+2], r2
+    ldxh r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd],
+    0x2211
+);
+
+test_cranelift!(
+    test_cranelift_stxw,
+    "
+    mov32 r2, 0x44332211
+    stxw [r1+2], r2
+    ldxw r0, [r1+2]
+    exit
+    ",
+    [0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd],
+    0x44332211
+);