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