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/Type.h"
     24 #include "llvm/IR/Value.h"
     25 #include <functional>
     26 
     27 namespace llvm {
     28 namespace fuzzerop {
     29 
     30 /// @{
     31 /// Populate a small list of potentially interesting constants of a given type.
     32 void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
     33 std::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.
     43 class SourcePred {
     44 public:
     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 
     54 private:
     55   PredT Pred;
     56   MakeT Make;
     57 
     58 public:
     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.
     89 struct OpDescriptor {
     90   unsigned Weight;
     91   SmallVector<SourcePred, 2> SourcePreds;
     92   std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
     93 };
     94 
     95 static 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 
    105 static 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 
    113 static 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 
    121 static 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 
    129 static 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 
    143 static 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 
    153 static 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.
    165 static 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.
    178 static 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