LLVM  10.0.0svn
OpDescriptor.h
Go to the documentation of this file.
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/STLExtras.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/DerivedTypes.h"
22 #include "llvm/IR/Instructions.h"
23 #include "llvm/IR/Type.h"
24 #include "llvm/IR/Value.h"
25 #include <functional>
26 
27 namespace llvm {
28 namespace fuzzerop {
29 
30 /// @{
31 /// Populate a small list of potentially interesting constants of a given type.
32 void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
33 std::vector<Constant *> makeConstantsWithType(Type *T);
34 /// @}
35 
36 /// A matcher/generator for finding suitable values for the next source in an
37 /// operation's partially completed argument list.
38 ///
39 /// Given that we're building some operation X and may have already filled some
40 /// subset of its operands, this predicate determines if some value New is
41 /// suitable for the next operand or generates a set of values that are
42 /// suitable.
43 class SourcePred {
44 public:
45  /// Given a list of already selected operands, returns whether a given new
46  /// operand is suitable for the next operand.
47  using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
48  /// Given a list of already selected operands and a set of valid base types
49  /// for a fuzzer, generates a list of constants that could be used for the
50  /// next operand.
51  using MakeT = std::function<std::vector<Constant *>(
53 
54 private:
55  PredT Pred;
56  MakeT Make;
57 
58 public:
59  /// Create a fully general source predicate.
60  SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
61  SourcePred(PredT Pred, NoneType) : Pred(Pred) {
62  Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
63  // Default filter just calls Pred on each of the base types.
64  std::vector<Constant *> Result;
65  for (Type *T : BaseTypes) {
66  Constant *V = UndefValue::get(T);
67  if (Pred(Cur, V))
68  makeConstantsWithType(T, Result);
69  }
70  if (Result.empty())
71  report_fatal_error("Predicate does not match for base types");
72  return Result;
73  };
74  }
75 
76  /// Returns true if \c New is compatible for the argument after \c Cur
77  bool matches(ArrayRef<Value *> Cur, const Value *New) {
78  return Pred(Cur, New);
79  }
80 
81  /// Generates a list of potential values for the argument after \c Cur.
82  std::vector<Constant *> generate(ArrayRef<Value *> Cur,
83  ArrayRef<Type *> BaseTypes) {
84  return Make(Cur, BaseTypes);
85  }
86 };
87 
88 /// A description of some operation we can build while fuzzing IR.
89 struct OpDescriptor {
90  unsigned Weight;
92  std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
93 };
94 
95 static inline SourcePred onlyType(Type *Only) {
96  auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
97  return V->getType() == Only;
98  };
99  auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
100  return makeConstantsWithType(Only);
101  };
102  return {Pred, Make};
103 }
104 
105 static inline SourcePred anyType() {
106  auto Pred = [](ArrayRef<Value *>, const Value *V) {
107  return !V->getType()->isVoidTy();
108  };
109  auto Make = None;
110  return {Pred, Make};
111 }
112 
113 static inline SourcePred anyIntType() {
114  auto Pred = [](ArrayRef<Value *>, const Value *V) {
115  return V->getType()->isIntegerTy();
116  };
117  auto Make = None;
118  return {Pred, Make};
119 }
120 
121 static inline SourcePred anyFloatType() {
122  auto Pred = [](ArrayRef<Value *>, const Value *V) {
123  return V->getType()->isFloatingPointTy();
124  };
125  auto Make = None;
126  return {Pred, Make};
127 }
128 
129 static inline SourcePred anyPtrType() {
130  auto Pred = [](ArrayRef<Value *>, const Value *V) {
131  return V->getType()->isPointerTy() && !V->isSwiftError();
132  };
133  auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
134  std::vector<Constant *> Result;
135  // TODO: Should these point at something?
136  for (Type *T : Ts)
137  Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
138  return Result;
139  };
140  return {Pred, Make};
141 }
142 
143 static inline SourcePred sizedPtrType() {
144  auto Pred = [](ArrayRef<Value *>, const Value *V) {
145  if (V->isSwiftError())
146  return false;
147 
148  if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
149  return PtrT->getElementType()->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 = None;
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 = None;
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.
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 } // end fuzzerop namespace
220 } // end llvm namespace
221 
222 #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
const NoneType None
Definition: None.h:23
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:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:264
NoneType
A simple null object to allow implicit construction of Optional<T> and similar types without having t...
Definition: None.h:22
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:52
static SourcePred sizedPtrType()
Definition: OpDescriptor.h:143
static SourcePred matchFirstType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:194
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
static SourcePred anyFloatType()
Definition: OpDescriptor.h:121
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
static SourcePred anyType()
Definition: OpDescriptor.h:105
static SourcePred anyVectorType()
Definition: OpDescriptor.h:182
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:47
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important base class in LLVM.
Definition: Constant.h:41
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:77
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:1433
static wasm::ValType getType(const TargetRegisterClass *RC)
SourcePred(PredT Pred, MakeT Make)
Create a fully general source predicate.
Definition: OpDescriptor.h:60
std::vector< Constant * > generate(ArrayRef< Value *> Cur, ArrayRef< Type *> BaseTypes)
Generates a list of potential values for the argument after Cur.
Definition: OpDescriptor.h:82
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:559
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
static SourcePred onlyType(Type *Only)
Definition: OpDescriptor.h:95
A matcher/generator for finding suitable values for the next source in an operation&#39;s partially compl...
Definition: OpDescriptor.h:43
static SourcePred anyPtrType()
Definition: OpDescriptor.h:129
static SourcePred anyAggregateType()
Definition: OpDescriptor.h:164
A description of some operation we can build while fuzzing IR.
Definition: OpDescriptor.h:89
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:207
SmallVector< SourcePred, 2 > SourcePreds
Definition: OpDescriptor.h:91
SourcePred(PredT Pred, NoneType)
Definition: OpDescriptor.h:61
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143
static SourcePred anyIntType()
Definition: OpDescriptor.h:113