LLVM  8.0.1
OpDescriptor.h
Go to the documentation of this file.
1 //===-- OpDescriptor.h ------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Provides the fuzzerop::Descriptor class and related tools for describing
11 // operations an IR fuzzer can work with.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
16 #define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
17 
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/IR/Type.h"
25 #include "llvm/IR/Value.h"
26 #include <functional>
27 
28 namespace llvm {
29 namespace fuzzerop {
30 
31 /// @{
32 /// Populate a small list of potentially interesting constants of a given type.
33 void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
34 std::vector<Constant *> makeConstantsWithType(Type *T);
35 /// @}
36 
37 /// A matcher/generator for finding suitable values for the next source in an
38 /// operation's partially completed argument list.
39 ///
40 /// Given that we're building some operation X and may have already filled some
41 /// subset of its operands, this predicate determines if some value New is
42 /// suitable for the next operand or generates a set of values that are
43 /// suitable.
44 class SourcePred {
45 public:
46  /// Given a list of already selected operands, returns whether a given new
47  /// operand is suitable for the next operand.
48  using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
49  /// Given a list of already selected operands and a set of valid base types
50  /// for a fuzzer, generates a list of constants that could be used for the
51  /// next operand.
52  using MakeT = std::function<std::vector<Constant *>(
54 
55 private:
56  PredT Pred;
57  MakeT Make;
58 
59 public:
60  /// Create a fully general source predicate.
61  SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
62  SourcePred(PredT Pred, NoneType) : Pred(Pred) {
63  Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
64  // Default filter just calls Pred on each of the base types.
65  std::vector<Constant *> Result;
66  for (Type *T : BaseTypes) {
67  Constant *V = UndefValue::get(T);
68  if (Pred(Cur, V))
69  makeConstantsWithType(T, Result);
70  }
71  if (Result.empty())
72  report_fatal_error("Predicate does not match for base types");
73  return Result;
74  };
75  }
76 
77  /// Returns true if \c New is compatible for the argument after \c Cur
78  bool matches(ArrayRef<Value *> Cur, const Value *New) {
79  return Pred(Cur, New);
80  }
81 
82  /// Generates a list of potential values for the argument after \c Cur.
83  std::vector<Constant *> generate(ArrayRef<Value *> Cur,
84  ArrayRef<Type *> BaseTypes) {
85  return Make(Cur, BaseTypes);
86  }
87 };
88 
89 /// A description of some operation we can build while fuzzing IR.
90 struct OpDescriptor {
91  unsigned Weight;
93  std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
94 };
95 
96 static inline SourcePred onlyType(Type *Only) {
97  auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
98  return V->getType() == Only;
99  };
100  auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
101  return makeConstantsWithType(Only);
102  };
103  return {Pred, Make};
104 }
105 
106 static inline SourcePred anyType() {
107  auto Pred = [](ArrayRef<Value *>, const Value *V) {
108  return !V->getType()->isVoidTy();
109  };
110  auto Make = None;
111  return {Pred, Make};
112 }
113 
114 static inline SourcePred anyIntType() {
115  auto Pred = [](ArrayRef<Value *>, const Value *V) {
116  return V->getType()->isIntegerTy();
117  };
118  auto Make = None;
119  return {Pred, Make};
120 }
121 
122 static inline SourcePred anyFloatType() {
123  auto Pred = [](ArrayRef<Value *>, const Value *V) {
124  return V->getType()->isFloatingPointTy();
125  };
126  auto Make = None;
127  return {Pred, Make};
128 }
129 
130 static inline SourcePred anyPtrType() {
131  auto Pred = [](ArrayRef<Value *>, const Value *V) {
132  return V->getType()->isPointerTy() && !V->isSwiftError();
133  };
134  auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
135  std::vector<Constant *> Result;
136  // TODO: Should these point at something?
137  for (Type *T : Ts)
138  Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
139  return Result;
140  };
141  return {Pred, Make};
142 }
143 
144 static inline SourcePred sizedPtrType() {
145  auto Pred = [](ArrayRef<Value *>, const Value *V) {
146  if (V->isSwiftError())
147  return false;
148 
149  if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
150  return PtrT->getElementType()->isSized();
151  return false;
152  };
153  auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
154  std::vector<Constant *> Result;
155 
156  for (Type *T : Ts)
157  if (T->isSized())
158  Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
159 
160  return Result;
161  };
162  return {Pred, Make};
163 }
164 
165 static inline SourcePred anyAggregateType() {
166  auto Pred = [](ArrayRef<Value *>, const Value *V) {
167  // We can't index zero sized arrays.
168  if (isa<ArrayType>(V->getType()))
169  return V->getType()->getArrayNumElements() > 0;
170 
171  // Structs can also be zero sized. I.e opaque types.
172  if (isa<StructType>(V->getType()))
173  return V->getType()->getStructNumElements() > 0;
174 
175  return V->getType()->isAggregateType();
176  };
177  // TODO: For now we only find aggregates in BaseTypes. It might be better to
178  // manufacture them out of the base types in some cases.
179  auto Find = None;
180  return {Pred, Find};
181 }
182 
183 static inline SourcePred anyVectorType() {
184  auto Pred = [](ArrayRef<Value *>, const Value *V) {
185  return V->getType()->isVectorTy();
186  };
187  // TODO: For now we only find vectors in BaseTypes. It might be better to
188  // manufacture vectors out of the base types, but it's tricky to be sure
189  // that's actually a reasonable type.
190  auto Make = None;
191  return {Pred, Make};
192 }
193 
194 /// Match values that have the same type as the first source.
195 static inline SourcePred matchFirstType() {
196  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
197  assert(!Cur.empty() && "No first source yet");
198  return V->getType() == Cur[0]->getType();
199  };
200  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
201  assert(!Cur.empty() && "No first source yet");
202  return makeConstantsWithType(Cur[0]->getType());
203  };
204  return {Pred, Make};
205 }
206 
207 /// Match values that have the first source's scalar type.
209  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
210  assert(!Cur.empty() && "No first source yet");
211  return V->getType() == Cur[0]->getType()->getScalarType();
212  };
213  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
214  assert(!Cur.empty() && "No first source yet");
215  return makeConstantsWithType(Cur[0]->getType()->getScalarType());
216  };
217  return {Pred, Make};
218 }
219 
220 } // end fuzzerop namespace
221 } // end llvm namespace
222 
223 #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
const NoneType None
Definition: None.h:24
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:265
NoneType
A simple null object to allow implicit construction of Optional<T> and similar types without having t...
Definition: None.h:23
std::function< std::vector< Constant * >(ArrayRef< Value * > Cur, ArrayRef< Type * > BaseTypes)> MakeT
Given a list of already selected operands and a set of valid base types for a fuzzer, generates a list of constants that could be used for the next operand.
Definition: OpDescriptor.h:53
static SourcePred sizedPtrType()
Definition: OpDescriptor.h:144
static SourcePred matchFirstType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:195
static SourcePred anyFloatType()
Definition: OpDescriptor.h:122
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
static SourcePred anyType()
Definition: OpDescriptor.h:106
static SourcePred anyVectorType()
Definition: OpDescriptor.h:183
std::function< bool(ArrayRef< Value * > Cur, const Value *New)> PredT
Given a list of already selected operands, returns whether a given new operand is suitable for the ne...
Definition: OpDescriptor.h:48
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important base class in LLVM.
Definition: Constant.h:42
static const SubtargetFeatureKV * Find(StringRef S, ArrayRef< SubtargetFeatureKV > A)
Find KV in array using binary search.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
bool matches(ArrayRef< Value *> Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
Definition: OpDescriptor.h:78
void makeConstantsWithType(Type *T, std::vector< Constant *> &Cs)
static UndefValue * get(Type *T)
Static factory methods - Return an &#39;undef&#39; object of the specified type.
Definition: Constants.cpp:1415
static wasm::ValType getType(const TargetRegisterClass *RC)
SourcePred(PredT Pred, MakeT Make)
Create a fully general source predicate.
Definition: OpDescriptor.h:61
std::vector< Constant * > generate(ArrayRef< Value *> Cur, ArrayRef< Type *> BaseTypes)
Generates a list of potential values for the argument after Cur.
Definition: OpDescriptor.h:83
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
Definition: DerivedTypes.h:482
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
static SourcePred onlyType(Type *Only)
Definition: OpDescriptor.h:96
A matcher/generator for finding suitable values for the next source in an operation&#39;s partially compl...
Definition: OpDescriptor.h:44
static SourcePred anyPtrType()
Definition: OpDescriptor.h:130
static SourcePred anyAggregateType()
Definition: OpDescriptor.h:165
A description of some operation we can build while fuzzing IR.
Definition: OpDescriptor.h:90
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
static SourcePred matchScalarOfFirstType()
Match values that have the first source&#39;s scalar type.
Definition: OpDescriptor.h:208
SmallVector< SourcePred, 2 > SourcePreds
Definition: OpDescriptor.h:92
SourcePred(PredT Pred, NoneType)
Definition: OpDescriptor.h:62
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:144
static SourcePred anyIntType()
Definition: OpDescriptor.h:114