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.
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);
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.
#define T
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...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
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...
bool matches(ArrayRef< Value * > Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
SourcePred(PredT Pred, MakeT Make)
Create a fully general source predicate.
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,...
SourcePred(PredT Pred, std::nullopt_t)
std::vector< Constant * > generate(ArrayRef< Value * > Cur, ArrayRef< Type * > BaseTypes)
Generates a list of potential values for the argument after Cur.
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...
static SourcePred matchFirstLengthWAnyType()
static SourcePred anyFloatOrVecFloatType()
static SourcePred sizedPtrType()
LLVM_ABI void makeConstantsWithType(Type *T, std::vector< Constant * > &Cs)
static SourcePred anyAggregateType()
static SourcePred anyIntType()
static SourcePred matchScalarOfFirstType()
Match values that have the first source's scalar type.
static SourcePred onlyType(Type *Only)
static SourcePred anyIntOrVecIntType()
static SourcePred anyVectorType()
static SourcePred boolOrVecBoolType()
static SourcePred anyFloatType()
static SourcePred matchFirstType()
Match values that have the same type as the first source.
static SourcePred anyPtrType()
static SourcePred anyType()
static SourcePred matchSecondType()
Match values that have the same type as the first source.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:71
A description of some operation we can build while fuzzing IR.
std::function< Value *(ArrayRef< Value * >, BasicBlock::iterator)> BuilderFunc
SmallVector< SourcePred, 2 > SourcePreds