reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=poison-checking -S < %s | FileCheck %s

; This file contains tests to exercise the UB triggering instructions with
; a potential source of UB.  The UB source is kept simple; we focus on the
; UB triggering instructions here.

define void @store(i8* %base, i32 %a) {
; CHECK-LABEL: @store(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
; CHECK-NEXT:    [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    store i8 0, i8* [[P]]
; CHECK-NEXT:    ret void
;
  %add = add nsw i32 %a, 1
  %p = getelementptr i8, i8* %base, i32 %add
  store i8 0, i8* %p
  ret void
}

define void @load(i8* %base, i32 %a) {
; CHECK-LABEL: @load(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
; CHECK-NEXT:    [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[TMP4:%.*]] = load volatile i8, i8* [[P]]
; CHECK-NEXT:    ret void
;
  %add = add nsw i32 %a, 1
  %p = getelementptr i8, i8* %base, i32 %add
  load volatile i8, i8* %p
  ret void
}

define void @atomicrmw(i8* %base, i32 %a) {
; CHECK-LABEL: @atomicrmw(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
; CHECK-NEXT:    [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[TMP4:%.*]] = atomicrmw add i8* [[P]], i8 1 seq_cst
; CHECK-NEXT:    ret void
;
  %add = add nsw i32 %a, 1
  %p = getelementptr i8, i8* %base, i32 %add
  atomicrmw add i8* %p, i8 1 seq_cst
  ret void
}

define void @cmpxchg(i8* %base, i32 %a) {
; CHECK-LABEL: @cmpxchg(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
; CHECK-NEXT:    [[P:%.*]] = getelementptr i8, i8* [[BASE:%.*]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[TMP4:%.*]] = cmpxchg i8* [[P]], i8 1, i8 0 seq_cst seq_cst
; CHECK-NEXT:    ret void
;
  %add = add nsw i32 %a, 1
  %p = getelementptr i8, i8* %base, i32 %add
  cmpxchg i8* %p, i8 1, i8 0 seq_cst seq_cst
  ret void
}

define i32 @udiv(i8* %base, i32 %a) {
; CHECK-LABEL: @udiv(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[RES:%.*]] = udiv i32 2048, [[ADD]]
; CHECK-NEXT:    ret i32 [[RES]]
;
  %add = add nuw i32 %a, 1
  %res = udiv i32 2048, %add
  ret i32 %res
}

define i32 @sdiv(i8* %base, i32 %a) {
; CHECK-LABEL: @sdiv(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[RES:%.*]] = sdiv i32 2048, [[ADD]]
; CHECK-NEXT:    ret i32 [[RES]]
;
  %add = add nuw i32 %a, 1
  %res = sdiv i32 2048, %add
  ret i32 %res
}

define i32 @urem(i8* %base, i32 %a) {
; CHECK-LABEL: @urem(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[RES:%.*]] = urem i32 2048, [[ADD]]
; CHECK-NEXT:    ret i32 [[RES]]
;
  %add = add nuw i32 %a, 1
  %res = urem i32 2048, %add
  ret i32 %res
}

define i32 @srem(i8* %base, i32 %a) {
; CHECK-LABEL: @srem(
; CHECK-NEXT:    [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 1)
; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT:    call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT:    [[RES:%.*]] = srem i32 2048, [[ADD]]
; CHECK-NEXT:    ret i32 [[RES]]
;
  %add = add nuw i32 %a, 1
  %res = srem i32 2048, %add
  ret i32 %res
}