LLVM 17.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/Type.h"
22#include "llvm/IR/Value.h"
23#include <functional>
24
25namespace llvm {
26class Instruction;
27namespace fuzzerop {
28
29/// @{
30/// Populate a small list of potentially interesting constants of a given type.
31void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
32std::vector<Constant *> makeConstantsWithType(Type *T);
33/// @}
34
35/// A matcher/generator for finding suitable values for the next source in an
36/// operation's partially completed argument list.
37///
38/// Given that we're building some operation X and may have already filled some
39/// subset of its operands, this predicate determines if some value New is
40/// suitable for the next operand or generates a set of values that are
41/// suitable.
43public:
44 /// Given a list of already selected operands, returns whether a given new
45 /// operand is suitable for the next operand.
46 using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
47 /// Given a list of already selected operands and a set of valid base types
48 /// for a fuzzer, generates a list of constants that could be used for the
49 /// next operand.
50 using MakeT = std::function<std::vector<Constant *>(
51 ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
52
53private:
54 PredT Pred;
55 MakeT Make;
56
57public:
58 /// Create a fully general source predicate.
59 SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
60 SourcePred(PredT Pred, std::nullopt_t) : Pred(Pred) {
61 Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
62 // Default filter just calls Pred on each of the base types.
63 std::vector<Constant *> Result;
64 for (Type *T : BaseTypes) {
66 if (Pred(Cur, V))
67 makeConstantsWithType(T, Result);
68 }
69 if (Result.empty())
70 report_fatal_error("Predicate does not match for base types");
71 return Result;
72 };
73 }
74
75 /// Returns true if \c New is compatible for the argument after \c Cur
76 bool matches(ArrayRef<Value *> Cur, const Value *New) {
77 return Pred(Cur, New);
78 }
79
80 /// Generates a list of potential values for the argument after \c Cur.
81 std::vector<Constant *> generate(ArrayRef<Value *> Cur,
82 ArrayRef<Type *> BaseTypes) {
83 return Make(Cur, BaseTypes);
84 }
85};
86
87/// A description of some operation we can build while fuzzing IR.
89 unsigned Weight;
92};
93
94static inline SourcePred onlyType(Type *Only) {
95 auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
96 return V->getType() == Only;
97 };
98 auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
99 return makeConstantsWithType(Only);
100 };
101 return {Pred, Make};
102}
103
104static inline SourcePred anyType() {
105 auto Pred = [](ArrayRef<Value *>, const Value *V) {
106 return !V->getType()->isVoidTy();
107 };
108 auto Make = std::nullopt;
109 return {Pred, Make};
110}
111
112static inline SourcePred anyIntType() {
113 auto Pred = [](ArrayRef<Value *>, const Value *V) {
114 return V->getType()->isIntegerTy();
115 };
116 auto Make = std::nullopt;
117 return {Pred, Make};
118}
119
120static inline SourcePred anyFloatType() {
121 auto Pred = [](ArrayRef<Value *>, const Value *V) {
122 return V->getType()->isFloatingPointTy();
123 };
124 auto Make = std::nullopt;
125 return {Pred, Make};
126}
127
128static inline SourcePred anyPtrType() {
129 auto Pred = [](ArrayRef<Value *>, const Value *V) {
130 return V->getType()->isPointerTy() && !V->isSwiftError();
131 };
132 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
133 std::vector<Constant *> Result;
134 // TODO: Should these point at something?
135 for (Type *T : Ts)
136 Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
137 return Result;
138 };
139 return {Pred, Make};
140}
141
142static inline SourcePred sizedPtrType() {
143 auto Pred = [](ArrayRef<Value *>, const Value *V) {
144 if (V->isSwiftError())
145 return false;
146
147 if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
148 return PtrT->isOpaque() ||
149 PtrT->getNonOpaquePointerElementType()->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
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 = std::nullopt;
179 return {Pred, Find};
180}
181
182static 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 = std::nullopt;
190 return {Pred, Make};
191}
192
193/// Match values that have the same type as the first source.
194static 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} // namespace fuzzerop
220} // namespace llvm
221
222#endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
This is an important base class in LLVM.
Definition: Constant.h:41
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:651
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1731
LLVM Value Representation.
Definition: Value.h:74
A matcher/generator for finding suitable values for the next source in an operation's partially compl...
Definition: OpDescriptor.h:42
bool matches(ArrayRef< Value * > Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
Definition: OpDescriptor.h:76
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:51
SourcePred(PredT Pred, MakeT Make)
Create a fully general source predicate.
Definition: OpDescriptor.h:59
SourcePred(PredT Pred, std::nullopt_t)
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:81
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:46
static SourcePred sizedPtrType()
Definition: OpDescriptor.h:142
void makeConstantsWithType(Type *T, std::vector< Constant * > &Cs)
static SourcePred anyAggregateType()
Definition: OpDescriptor.h:164
static SourcePred anyIntType()
Definition: OpDescriptor.h:112
static SourcePred matchScalarOfFirstType()
Match values that have the first source's scalar type.
Definition: OpDescriptor.h:207
static SourcePred onlyType(Type *Only)
Definition: OpDescriptor.h:94
static SourcePred anyVectorType()
Definition: OpDescriptor.h:182
static SourcePred anyFloatType()
Definition: OpDescriptor.h:120
static SourcePred matchFirstType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:194
static SourcePred anyPtrType()
Definition: OpDescriptor.h:128
static SourcePred anyType()
Definition: OpDescriptor.h:104
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
A description of some operation we can build while fuzzing IR.
Definition: OpDescriptor.h:88
SmallVector< SourcePred, 2 > SourcePreds
Definition: OpDescriptor.h:90
std::function< Value *(ArrayRef< Value * >, Instruction *)> BuilderFunc
Definition: OpDescriptor.h:91