]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / FuzzMutate / OpDescriptor.h
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/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 *>(
52       ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
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;
91   SmallVector<SourcePred, 2> SourcePreds;
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();
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 (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
146       return PtrT->getElementType()->isSized();
147     return false;
148   };
149   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
150     std::vector<Constant *> Result;
151
152     for (Type *T : Ts)
153       if (T->isSized())
154         Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
155
156     return Result;
157   };
158   return {Pred, Make};
159 }
160
161 static inline SourcePred anyAggregateType() {
162   auto Pred = [](ArrayRef<Value *>, const Value *V) {
163     // We can't index zero sized arrays.
164     if (isa<ArrayType>(V->getType()))
165       return V->getType()->getArrayNumElements() > 0;
166
167     // Structs can also be zero sized. I.e opaque types.
168     if (isa<StructType>(V->getType()))
169       return V->getType()->getStructNumElements() > 0;
170
171     return V->getType()->isAggregateType();
172   };
173   // TODO: For now we only find aggregates in BaseTypes. It might be better to
174   // manufacture them out of the base types in some cases.
175   auto Find = None;
176   return {Pred, Find};
177 }
178
179 static inline SourcePred anyVectorType() {
180   auto Pred = [](ArrayRef<Value *>, const Value *V) {
181     return V->getType()->isVectorTy();
182   };
183   // TODO: For now we only find vectors in BaseTypes. It might be better to
184   // manufacture vectors out of the base types, but it's tricky to be sure
185   // that's actually a reasonable type.
186   auto Make = None;
187   return {Pred, Make};
188 }
189
190 /// Match values that have the same type as the first source.
191 static inline SourcePred matchFirstType() {
192   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
193     assert(!Cur.empty() && "No first source yet");
194     return V->getType() == Cur[0]->getType();
195   };
196   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
197     assert(!Cur.empty() && "No first source yet");
198     return makeConstantsWithType(Cur[0]->getType());
199   };
200   return {Pred, Make};
201 }
202
203 /// Match values that have the first source's scalar type.
204 static inline SourcePred matchScalarOfFirstType() {
205   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
206     assert(!Cur.empty() && "No first source yet");
207     return V->getType() == Cur[0]->getType()->getScalarType();
208   };
209   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
210     assert(!Cur.empty() && "No first source yet");
211     return makeConstantsWithType(Cur[0]->getType()->getScalarType());
212   };
213   return {Pred, Make};
214 }
215
216 } // end fuzzerop namespace
217 } // end llvm namespace
218
219 #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H