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
27namespace llvm {
28namespace fuzzerop {
29
30/// @{
31/// Populate a small list of potentially interesting constants of a given type.
32void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
33std::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.
43class SourcePred {
44public:
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
54private:
55  PredT Pred;
56  MakeT Make;
57
58public:
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.
89struct OpDescriptor {
90  unsigned Weight;
91  SmallVector<SourcePred, 2> SourcePreds;
92  std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
93};
94
95static 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
105static 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
113static 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
121static 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
129static 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
143static inline SourcePred anyAggregateType() {
144  auto Pred = [](ArrayRef<Value *>, const Value *V) {
145    return V->getType()->isAggregateType();
146  };
147  // TODO: For now we only find aggregates in BaseTypes. It might be better to
148  // manufacture them out of the base types in some cases.
149  auto Find = None;
150  return {Pred, Find};
151}
152
153static inline SourcePred anyVectorType() {
154  auto Pred = [](ArrayRef<Value *>, const Value *V) {
155    return V->getType()->isVectorTy();
156  };
157  // TODO: For now we only find vectors in BaseTypes. It might be better to
158  // manufacture vectors out of the base types, but it's tricky to be sure
159  // that's actually a reasonable type.
160  auto Make = None;
161  return {Pred, Make};
162}
163
164/// Match values that have the same type as the first source.
165static inline SourcePred matchFirstType() {
166  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
167    assert(!Cur.empty() && "No first source yet");
168    return V->getType() == Cur[0]->getType();
169  };
170  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
171    assert(!Cur.empty() && "No first source yet");
172    return makeConstantsWithType(Cur[0]->getType());
173  };
174  return {Pred, Make};
175}
176
177/// Match values that have the first source's scalar type.
178static inline SourcePred matchScalarOfFirstType() {
179  auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
180    assert(!Cur.empty() && "No first source yet");
181    return V->getType() == Cur[0]->getType()->getScalarType();
182  };
183  auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
184    assert(!Cur.empty() && "No first source yet");
185    return makeConstantsWithType(Cur[0]->getType()->getScalarType());
186  };
187  return {Pred, Make};
188}
189
190} // end fuzzerop namespace
191} // end llvm namespace
192
193#endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
194