Home | History | Annotate | Download | only in FuzzMutate
      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/Instructions.h"
     24 #include "llvm/IR/Type.h"
     25 #include "llvm/IR/Value.h"
     26 #include <functional>
     27 
     28 namespace llvm {
     29 namespace fuzzerop {
     30 
     31 /// @{
     32 /// Populate a small list of potentially interesting constants of a given type.
     33 void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
     34 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.
     44 class SourcePred {
     45 public:
     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 
     55 private:
     56   PredT Pred;
     57   MakeT Make;
     58 
     59 public:
     60   /// Create a fully general source predicate.
     61   SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
     62   SourcePred(PredT Pred, NoneType) : 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) {
     67         Constant *V = UndefValue::get(T);
     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.
     90 struct OpDescriptor {
     91   unsigned Weight;
     92   SmallVector<SourcePred, 2> SourcePreds;
     93   std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
     94 };
     95 
     96 static 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 
    106 static inline SourcePred anyType() {
    107   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    108     return !V->getType()->isVoidTy();
    109   };
    110   auto Make = None;
    111   return {Pred, Make};
    112 }
    113 
    114 static inline SourcePred anyIntType() {
    115   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    116     return V->getType()->isIntegerTy();
    117   };
    118   auto Make = None;
    119   return {Pred, Make};
    120 }
    121 
    122 static inline SourcePred anyFloatType() {
    123   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    124     return V->getType()->isFloatingPointTy();
    125   };
    126   auto Make = None;
    127   return {Pred, Make};
    128 }
    129 
    130 static inline SourcePred anyPtrType() {
    131   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    132     return V->getType()->isPointerTy() && !V->isSwiftError();
    133   };
    134   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
    135     std::vector<Constant *> Result;
    136     // TODO: Should these point at something?
    137     for (Type *T : Ts)
    138       Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
    139     return Result;
    140   };
    141   return {Pred, Make};
    142 }
    143 
    144 static inline SourcePred sizedPtrType() {
    145   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    146     if (V->isSwiftError())
    147       return false;
    148 
    149     if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
    150       return PtrT->getElementType()->isSized();
    151     return false;
    152   };
    153   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
    154     std::vector<Constant *> Result;
    155 
    156     for (Type *T : Ts)
    157       if (T->isSized())
    158         Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
    159 
    160     return Result;
    161   };
    162   return {Pred, Make};
    163 }
    164 
    165 static inline SourcePred anyAggregateType() {
    166   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    167     // We can't index zero sized arrays.
    168     if (isa<ArrayType>(V->getType()))
    169       return V->getType()->getArrayNumElements() > 0;
    170 
    171     // Structs can also be zero sized. I.e opaque types.
    172     if (isa<StructType>(V->getType()))
    173       return V->getType()->getStructNumElements() > 0;
    174 
    175     return V->getType()->isAggregateType();
    176   };
    177   // TODO: For now we only find aggregates in BaseTypes. It might be better to
    178   // manufacture them out of the base types in some cases.
    179   auto Find = None;
    180   return {Pred, Find};
    181 }
    182 
    183 static inline SourcePred anyVectorType() {
    184   auto Pred = [](ArrayRef<Value *>, const Value *V) {
    185     return V->getType()->isVectorTy();
    186   };
    187   // TODO: For now we only find vectors in BaseTypes. It might be better to
    188   // manufacture vectors out of the base types, but it's tricky to be sure
    189   // that's actually a reasonable type.
    190   auto Make = None;
    191   return {Pred, Make};
    192 }
    193 
    194 /// Match values that have the same type as the first source.
    195 static inline SourcePred matchFirstType() {
    196   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
    197     assert(!Cur.empty() && "No first source yet");
    198     return V->getType() == Cur[0]->getType();
    199   };
    200   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
    201     assert(!Cur.empty() && "No first source yet");
    202     return makeConstantsWithType(Cur[0]->getType());
    203   };
    204   return {Pred, Make};
    205 }
    206 
    207 /// Match values that have the first source's scalar type.
    208 static inline SourcePred matchScalarOfFirstType() {
    209   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
    210     assert(!Cur.empty() && "No first source yet");
    211     return V->getType() == Cur[0]->getType()->getScalarType();
    212   };
    213   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
    214     assert(!Cur.empty() && "No first source yet");
    215     return makeConstantsWithType(Cur[0]->getType()->getScalarType());
    216   };
    217   return {Pred, Make};
    218 }
    219 
    220 } // end fuzzerop namespace
    221 } // end llvm namespace
    222 
    223 #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
    224