Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===-- OpDescriptor.h ------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Provides the fuzzerop::Descriptor class and related tools for describing
10
// operations an IR fuzzer can work with.
11
//
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
15
#define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
16
 
17
#include "llvm/ADT/ArrayRef.h"
18
#include "llvm/ADT/SmallVector.h"
19
#include "llvm/IR/Constants.h"
20
#include "llvm/IR/DerivedTypes.h"
21
#include "llvm/IR/Type.h"
22
#include "llvm/IR/Value.h"
23
#include <functional>
24
 
25
namespace llvm {
26
class Instruction;
27
namespace fuzzerop {
28
 
29
/// @{
30
/// Populate a small list of potentially interesting constants of a given type.
31
void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
32
std::vector<Constant *> makeConstantsWithType(Type *T);
33
/// @}
34
 
35
/// A matcher/generator for finding suitable values for the next source in an
36
/// operation's partially completed argument list.
37
///
38
/// Given that we're building some operation X and may have already filled some
39
/// subset of its operands, this predicate determines if some value New is
40
/// suitable for the next operand or generates a set of values that are
41
/// suitable.
42
class SourcePred {
43
public:
44
  /// Given a list of already selected operands, returns whether a given new
45
  /// operand is suitable for the next operand.
46
  using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
47
  /// Given a list of already selected operands and a set of valid base types
48
  /// for a fuzzer, generates a list of constants that could be used for the
49
  /// next operand.
50
  using MakeT = std::function<std::vector<Constant *>(
51
      ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
52
 
53
private:
54
  PredT Pred;
55
  MakeT Make;
56
 
57
public:
58
  /// Create a fully general source predicate.
59
  SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
60
  SourcePred(PredT Pred, std::nullopt_t) : Pred(Pred) {
61
    Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
62
      // Default filter just calls Pred on each of the base types.
63
      std::vector<Constant *> Result;
64
      for (Type *T : BaseTypes) {
65
        Constant *V = UndefValue::get(T);
66
        if (Pred(Cur, V))
67
          makeConstantsWithType(T, Result);
68
      }
69
      if (Result.empty())
70
        report_fatal_error("Predicate does not match for base types");
71
      return Result;
72
    };
73
  }
74
 
75
  /// Returns true if \c New is compatible for the argument after \c Cur
76
  bool matches(ArrayRef<Value *> Cur, const Value *New) {
77
    return Pred(Cur, New);
78
  }
79
 
80
  /// Generates a list of potential values for the argument after \c Cur.
81
  std::vector<Constant *> generate(ArrayRef<Value *> Cur,
82
                                   ArrayRef<Type *> BaseTypes) {
83
    return Make(Cur, BaseTypes);
84
  }
85
};
86
 
87
/// A description of some operation we can build while fuzzing IR.
88
struct OpDescriptor {
89
  unsigned Weight;
90
  SmallVector<SourcePred, 2> SourcePreds;
91
  std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
92
};
93
 
94
static inline SourcePred onlyType(Type *Only) {
95
  auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
96
    return V->getType() == Only;
97
  };
98
  auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
99
    return makeConstantsWithType(Only);
100
  };
101
  return {Pred, Make};
102
}
103
 
104
static inline SourcePred anyType() {
105
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
106
    return !V->getType()->isVoidTy();
107
  };
108
  auto Make = std::nullopt;
109
  return {Pred, Make};
110
}
111
 
112
static inline SourcePred anyIntType() {
113
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
114
    return V->getType()->isIntegerTy();
115
  };
116
  auto Make = std::nullopt;
117
  return {Pred, Make};
118
}
119
 
120
static inline SourcePred anyFloatType() {
121
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
122
    return V->getType()->isFloatingPointTy();
123
  };
124
  auto Make = std::nullopt;
125
  return {Pred, Make};
126
}
127
 
128
static inline SourcePred anyPtrType() {
129
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
130
    return V->getType()->isPointerTy() && !V->isSwiftError();
131
  };
132
  auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
133
    std::vector<Constant *> Result;
134
    // TODO: Should these point at something?
135
    for (Type *T : Ts)
136
      Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
137
    return Result;
138
  };
139
  return {Pred, Make};
140
}
141
 
142
static inline SourcePred sizedPtrType() {
143
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
144
    if (V->isSwiftError())
145
      return false;
146
 
147
    if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
148
      return PtrT->isOpaque() ||
149
             PtrT->getNonOpaquePointerElementType()->isSized();
150
    return false;
151
  };
152
  auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
153
    std::vector<Constant *> Result;
154
 
155
    for (Type *T : Ts)
156
      if (T->isSized())
157
        Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
158
 
159
    return Result;
160
  };
161
  return {Pred, Make};
162
}
163
 
164
static inline SourcePred anyAggregateType() {
165
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
166
    // We can't index zero sized arrays.
167
    if (isa<ArrayType>(V->getType()))
168
      return V->getType()->getArrayNumElements() > 0;
169
 
170
    // Structs can also be zero sized. I.e opaque types.
171
    if (isa<StructType>(V->getType()))
172
      return V->getType()->getStructNumElements() > 0;
173
 
174
    return V->getType()->isAggregateType();
175
  };
176
  // TODO: For now we only find aggregates in BaseTypes. It might be better to
177
  // manufacture them out of the base types in some cases.
178
  auto Find = std::nullopt;
179
  return {Pred, Find};
180
}
181
 
182
static inline SourcePred anyVectorType() {
183
  auto Pred = [](ArrayRef<Value *>, const Value *V) {
184
    return V->getType()->isVectorTy();
185
  };
186
  // TODO: For now we only find vectors in BaseTypes. It might be better to
187
  // manufacture vectors out of the base types, but it's tricky to be sure
188
  // that's actually a reasonable type.
189
  auto Make = std::nullopt;
190
  return {Pred, Make};
191
}
192
 
193
/// Match values that have the same type as the first source.
194
static inline SourcePred matchFirstType() {
195
  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
196
    assert(!Cur.empty() && "No first source yet");
197
    return V->getType() == Cur[0]->getType();
198
  };
199
  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
200
    assert(!Cur.empty() && "No first source yet");
201
    return makeConstantsWithType(Cur[0]->getType());
202
  };
203
  return {Pred, Make};
204
}
205
 
206
/// Match values that have the first source's scalar type.
207
static inline SourcePred matchScalarOfFirstType() {
208
  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
209
    assert(!Cur.empty() && "No first source yet");
210
    return V->getType() == Cur[0]->getType()->getScalarType();
211
  };
212
  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
213
    assert(!Cur.empty() && "No first source yet");
214
    return makeConstantsWithType(Cur[0]->getType()->getScalarType());
215
  };
216
  return {Pred, Make};
217
}
218
 
219
} // namespace fuzzerop
220
} // namespace llvm
221
 
222
#endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H