LLVM 22.0.0git
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"
19#include "llvm/IR/Constants.h"
21#include "llvm/IR/InstrTypes.h"
22#include "llvm/IR/Type.h"
23#include "llvm/IR/Value.h"
25#include <functional>
26
27namespace llvm {
28class Instruction;
29namespace fuzzerop {
30
31/// @{
32/// Populate a small list of potentially interesting constants of a given type.
33LLVM_ABI void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
34LLVM_ABI 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.
45public:
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 *>(
53 ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
54
55private:
56 PredT Pred;
57 MakeT Make;
58
59public:
60 /// Create a fully general source predicate.
61 SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
62 SourcePred(PredT Pred, std::nullopt_t) : 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) {
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.
91 unsigned Weight;
94};
95
96static 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
106static inline SourcePred anyType() {
107 auto Pred = [](ArrayRef<Value *>, const Value *V) {
108 return !V->getType()->isVoidTy();
109 };
110 auto Make = std::nullopt;
111 return {Pred, Make};
112}
113
114static inline SourcePred anyIntType() {
115 auto Pred = [](ArrayRef<Value *>, const Value *V) {
116 return V->getType()->isIntegerTy();
117 };
118 auto Make = std::nullopt;
119 return {Pred, Make};
120}
121
123 auto Pred = [](ArrayRef<Value *>, const Value *V) {
124 return V->getType()->isIntOrIntVectorTy();
125 };
126 return {Pred, std::nullopt};
127}
128
130 auto Pred = [](ArrayRef<Value *>, const Value *V) {
131 return V->getType()->isIntOrIntVectorTy(1);
132 };
133 return {Pred, std::nullopt};
134}
135
136static inline SourcePred anyFloatType() {
137 auto Pred = [](ArrayRef<Value *>, const Value *V) {
138 return V->getType()->isFloatingPointTy();
139 };
140 auto Make = std::nullopt;
141 return {Pred, Make};
142}
143
145 auto Pred = [](ArrayRef<Value *>, const Value *V) {
146 return V->getType()->isFPOrFPVectorTy();
147 };
148 return {Pred, std::nullopt};
149}
150
151static inline SourcePred anyPtrType() {
152 auto Pred = [](ArrayRef<Value *>, const Value *V) {
153 return V->getType()->isPointerTy() && !V->isSwiftError();
154 };
155 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
156 std::vector<Constant *> Result;
157 // TODO: Should these point at something?
158 for (Type *T : Ts)
159 Result.push_back(
161 return Result;
162 };
163 return {Pred, Make};
164}
165
166static inline SourcePred sizedPtrType() {
167 auto Pred = [](ArrayRef<Value *>, const Value *V) {
168 if (V->isSwiftError())
169 return false;
170
171 return V->getType()->isPointerTy();
172 };
173 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
174 std::vector<Constant *> Result;
175
176 // TODO: This doesn't really make sense with opaque pointers,
177 // as the pointer type will always be the same.
178 for (Type *T : Ts)
179 if (T->isSized())
180 Result.push_back(
182
183 return Result;
184 };
185 return {Pred, Make};
186}
187
189 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
190 assert(!Cur.empty() && "No first source yet");
191 Type *This = V->getType(), *First = Cur[0]->getType();
192 VectorType *ThisVec = dyn_cast<VectorType>(This);
193 VectorType *FirstVec = dyn_cast<VectorType>(First);
194 if (ThisVec && FirstVec) {
195 return ThisVec->getElementCount() == FirstVec->getElementCount();
196 }
197 return (ThisVec == nullptr) && (FirstVec == nullptr) && (!This->isVoidTy());
198 };
199 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
200 assert(!Cur.empty() && "No first source yet");
201 std::vector<Constant *> Result;
202 ElementCount EC;
203 bool isVec = false;
204 if (VectorType *VecTy = dyn_cast<VectorType>(Cur[0]->getType())) {
205 EC = VecTy->getElementCount();
206 isVec = true;
207 }
208 for (Type *T : BaseTypes) {
210 if (isVec)
211 // If the first pred is <i1 x N>, make the result <T x N>
213 else
214 makeConstantsWithType(T, Result);
215 }
216 }
217 assert(!Result.empty() && "No potential constants.");
218 return Result;
219 };
220 return {Pred, Make};
221}
222
223/// Match values that have the same type as the first source.
225 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
226 assert((Cur.size() > 1) && "No second source yet");
227 return V->getType() == Cur[1]->getType();
228 };
229 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
230 assert((Cur.size() > 1) && "No second source yet");
231 return makeConstantsWithType(Cur[1]->getType());
232 };
233 return {Pred, Make};
234}
235
237 auto Pred = [](ArrayRef<Value *>, const Value *V) {
238 // We can't index zero sized arrays.
239 if (isa<ArrayType>(V->getType()))
240 return V->getType()->getArrayNumElements() > 0;
241
242 // Structs can also be zero sized. I.e opaque types.
243 if (isa<StructType>(V->getType()))
244 return V->getType()->getStructNumElements() > 0;
245
246 return V->getType()->isAggregateType();
247 };
248 // TODO: For now we only find aggregates in BaseTypes. It might be better to
249 // manufacture them out of the base types in some cases.
250 auto Find = std::nullopt;
251 return {Pred, Find};
252}
253
254static inline SourcePred anyVectorType() {
255 auto Pred = [](ArrayRef<Value *>, const Value *V) {
256 return V->getType()->isVectorTy();
257 };
258 // TODO: For now we only find vectors in BaseTypes. It might be better to
259 // manufacture vectors out of the base types, but it's tricky to be sure
260 // that's actually a reasonable type.
261 auto Make = std::nullopt;
262 return {Pred, Make};
263}
264
265/// Match values that have the same type as the first source.
266static inline SourcePred matchFirstType() {
267 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
268 assert(!Cur.empty() && "No first source yet");
269 return V->getType() == Cur[0]->getType();
270 };
271 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
272 assert(!Cur.empty() && "No first source yet");
273 return makeConstantsWithType(Cur[0]->getType());
274 };
275 return {Pred, Make};
276}
277
278/// Match values that have the first source's scalar type.
280 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
281 assert(!Cur.empty() && "No first source yet");
282 return V->getType() == Cur[0]->getType()->getScalarType();
283 };
284 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
285 assert(!Cur.empty() && "No first source yet");
286 return makeConstantsWithType(Cur[0]->getType()->getScalarType());
287 };
288 return {Pred, Make};
289}
290
291} // namespace fuzzerop
292} // namespace llvm
293
294#endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:39
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:170
This is an important base class in LLVM.
Definition: Constant.h:43
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Definition: DerivedTypes.h:720
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1885
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
Base class of all SIMD vector types.
Definition: DerivedTypes.h:430
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Definition: DerivedTypes.h:695
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
A matcher/generator for finding suitable values for the next source in an operation's partially compl...
Definition: OpDescriptor.h:44
bool matches(ArrayRef< Value * > Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
Definition: OpDescriptor.h:78
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,...
Definition: OpDescriptor.h:53
SourcePred(PredT Pred, MakeT Make)
Create a fully general source predicate.
Definition: OpDescriptor.h:61
SourcePred(PredT Pred, std::nullopt_t)
Definition: OpDescriptor.h:62
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
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
static SourcePred matchFirstLengthWAnyType()
Definition: OpDescriptor.h:188
static SourcePred anyFloatOrVecFloatType()
Definition: OpDescriptor.h:144
static SourcePred sizedPtrType()
Definition: OpDescriptor.h:166
LLVM_ABI void makeConstantsWithType(Type *T, std::vector< Constant * > &Cs)
static SourcePred anyAggregateType()
Definition: OpDescriptor.h:236
static SourcePred anyIntType()
Definition: OpDescriptor.h:114
static SourcePred matchScalarOfFirstType()
Match values that have the first source's scalar type.
Definition: OpDescriptor.h:279
static SourcePred onlyType(Type *Only)
Definition: OpDescriptor.h:96
static SourcePred anyIntOrVecIntType()
Definition: OpDescriptor.h:122
static SourcePred anyVectorType()
Definition: OpDescriptor.h:254
static SourcePred boolOrVecBoolType()
Definition: OpDescriptor.h:129
static SourcePred anyFloatType()
Definition: OpDescriptor.h:136
static SourcePred matchFirstType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:266
static SourcePred anyPtrType()
Definition: OpDescriptor.h:151
static SourcePred anyType()
Definition: OpDescriptor.h:106
static SourcePred matchSecondType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:224
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
A description of some operation we can build while fuzzing IR.
Definition: OpDescriptor.h:90
std::function< Value *(ArrayRef< Value * >, BasicBlock::iterator)> BuilderFunc
Definition: OpDescriptor.h:93
SmallVector< SourcePred, 2 > SourcePreds
Definition: OpDescriptor.h:92