[InstCombine] Signed saturation patterns
[llvm-core.git] / include / llvm / FuzzMutate / OpDescriptor.h
blobd6c98cd949a29da7aecf9cf2a5da4a74d70e8077
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.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
15 #define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
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>
27 namespace llvm {
28 namespace fuzzerop {
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 /// @}
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)>;
54 private:
55 PredT Pred;
56 MakeT Make;
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);
70 if (Result.empty())
71 report_fatal_error("Predicate does not match for base types");
72 return Result;
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);
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);
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;
95 static inline SourcePred onlyType(Type *Only) {
96 auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
97 return V->getType() == Only;
99 auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
100 return makeConstantsWithType(Only);
102 return {Pred, Make};
105 static inline SourcePred anyType() {
106 auto Pred = [](ArrayRef<Value *>, const Value *V) {
107 return !V->getType()->isVoidTy();
109 auto Make = None;
110 return {Pred, Make};
113 static inline SourcePred anyIntType() {
114 auto Pred = [](ArrayRef<Value *>, const Value *V) {
115 return V->getType()->isIntegerTy();
117 auto Make = None;
118 return {Pred, Make};
121 static inline SourcePred anyFloatType() {
122 auto Pred = [](ArrayRef<Value *>, const Value *V) {
123 return V->getType()->isFloatingPointTy();
125 auto Make = None;
126 return {Pred, Make};
129 static inline SourcePred anyPtrType() {
130 auto Pred = [](ArrayRef<Value *>, const Value *V) {
131 return V->getType()->isPointerTy() && !V->isSwiftError();
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;
140 return {Pred, Make};
143 static inline SourcePred sizedPtrType() {
144 auto Pred = [](ArrayRef<Value *>, const Value *V) {
145 if (V->isSwiftError())
146 return false;
148 if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
149 return PtrT->getElementType()->isSized();
150 return false;
152 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
153 std::vector<Constant *> Result;
155 for (Type *T : Ts)
156 if (T->isSized())
157 Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
159 return Result;
161 return {Pred, Make};
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;
170 // Structs can also be zero sized. I.e opaque types.
171 if (isa<StructType>(V->getType()))
172 return V->getType()->getStructNumElements() > 0;
174 return V->getType()->isAggregateType();
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};
182 static inline SourcePred anyVectorType() {
183 auto Pred = [](ArrayRef<Value *>, const Value *V) {
184 return V->getType()->isVectorTy();
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};
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();
199 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
200 assert(!Cur.empty() && "No first source yet");
201 return makeConstantsWithType(Cur[0]->getType());
203 return {Pred, Make};
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();
212 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
213 assert(!Cur.empty() && "No first source yet");
214 return makeConstantsWithType(Cur[0]->getType()->getScalarType());
216 return {Pred, Make};
219 } // end fuzzerop namespace
220 } // end llvm namespace
222 #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H