Commit 170dfab4 authored by Yonghong Song's avatar Yonghong Song
Browse files

bpf: fix bug on silently truncating 64-bit immediate

We came across an llvm bug when compiling some testcases that 64-bit
immediates are silently truncated into 32-bit and then packed into
BPF_JMP | BPF_K encoding.  This caused comparison with wrong value.

This bug looks to be introduced by r308080 (llvm 5.0). The Select_Ri pattern is
supposed to be lowered into J*_Ri while the latter only support 32-bit
immediate encoding, therefore Select_Ri should have similar immediate
predicate check as what J*_Ri are doing.

The bug is fixed by
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315889

 91177308-0d34-0410-b5e6-96231b3b80d8
in llvm 6.0.

This patch is largely the same as the fix in llvm 6.0 except
one minor adjustment for the test case.

Reported-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Reported-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarJiong Wang <jiong.wang@netronome.com>
Reviewed-by: default avatarYonghong Song <yhs@fb.com>
llvm-svn: 319633
parent 1254c70d
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -578,11 +578,15 @@ BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
        .addReg(LHS)
        .addReg(MI.getOperand(2).getReg())
        .addMBB(Copy1MBB);
  else
  else {
    int64_t imm32 = MI.getOperand(2).getImm();
    // sanity check before we build J*_ri instruction.
    assert (isInt<32>(imm32));
    BuildMI(BB, DL, TII.get(NewCC))
        .addReg(LHS)
        .addImm(MI.getOperand(2).getImm())
        .addImm(imm32)
        .addMBB(Copy1MBB);
  }

  // Copy0MBB:
  //  %FalseValue = ...
+1 −1
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ let usesCustomInserter = 1 in {
                      (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR:$src, GPR:$src2),
                      "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
                      [(set i64:$dst,
                       (BPFselectcc i64:$lhs, (i64 imm:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>;
                       (BPFselectcc i64:$lhs, (i64 i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>;
}

// load 64-bit global addr into register
+35 −0
Original line number Diff line number Diff line
@@ -25,3 +25,38 @@ entry:
}

attributes #0 = { norecurse nounwind readonly }

; test immediate out of 32-bit range
; Source file:

; unsigned long long
; load_word(void *buf, unsigned long long off)
; asm("llvm.bpf.load.word");
;
; int
; foo(void *buf)
; {
;  unsigned long long sum = 0;
;
;  sum += load_word(buf, 100);
;  sum += load_word(buf, 104);
;
;  if (sum != 0x1ffffffffULL)
;    return ~0U;
;
;  return 0;
;}

; Function Attrs: nounwind readonly
define i32 @foo(i8*) local_unnamed_addr #0 {
  %2 = tail call i64 @llvm.bpf.load.word(i8* %0, i64 100)
  %3 = tail call i64 @llvm.bpf.load.word(i8* %0, i64 104)
  %4 = add i64 %3, %2
  %5 = icmp ne i64 %4, 8589934591
; CHECK:  r{{[0-9]+}} = 8589934591ll
  %6 = sext i1 %5 to i32
  ret i32 %6
}

; Function Attrs: nounwind readonly
declare i64 @llvm.bpf.load.word(i8*, i64) #1