LCOV - code coverage report
Current view: top level - include/llvm/FuzzMutate - OpDescriptor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 67 70 95.7 %
Date: 2018-07-13 00:08:38 Functions: 24 24 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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       13262 : 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         856 :   SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
      62         922 :   SourcePred(PredT Pred, NoneType) : Pred(Pred) {
      63        1920 :     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          75 :       for (Type *T : BaseTypes) {
      67          29 :         Constant *V = UndefValue::get(T);
      68          29 :         if (Pred(Cur, V))
      69          25 :           makeConstantsWithType(T, Result);
      70             :       }
      71          17 :       if (Result.empty())
      72           0 :         report_fatal_error("Predicate does not match for base types");
      73          17 :       return Result;
      74         461 :     };
      75         461 :   }
      76             : 
      77             :   /// Returns true if \c New is compatible for the argument after \c Cur
      78         303 :   bool matches(ArrayRef<Value *> Cur, const Value *New) {
      79         303 :     return Pred(Cur, New);
      80             :   }
      81             : 
      82             :   /// Generates a list of potential values for the argument after \c Cur.
      83          96 :   std::vector<Constant *> generate(ArrayRef<Value *> Cur,
      84             :                                    ArrayRef<Type *> BaseTypes) {
      85          96 :     return Make(Cur, BaseTypes);
      86             :   }
      87             : };
      88             : 
      89             : /// A description of some operation we can build while fuzzing IR.
      90        4500 : struct OpDescriptor {
      91             :   unsigned Weight;
      92             :   SmallVector<SourcePred, 2> SourcePreds;
      93             :   std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
      94             : };
      95             : 
      96           1 : static inline SourcePred onlyType(Type *Only) {
      97           4 :   auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
      98           4 :     return V->getType() == Only;
      99           4 :   };
     100           1 :   auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
     101             :     return makeConstantsWithType(Only);
     102           1 :   };
     103           3 :   return {Pred, Make};
     104             : }
     105             : 
     106          12 : static inline SourcePred anyType() {
     107             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     108          37 :     return !V->getType()->isVoidTy();
     109          37 :   };
     110             :   auto Make = None;
     111          24 :   return {Pred, Make};
     112             : }
     113             : 
     114         222 : static inline SourcePred anyIntType() {
     115             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     116          51 :     return V->getType()->isIntegerTy();
     117             :   };
     118             :   auto Make = None;
     119         444 :   return {Pred, Make};
     120             : }
     121             : 
     122         169 : static inline SourcePred anyFloatType() {
     123             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     124          29 :     return V->getType()->isFloatingPointTy();
     125             :   };
     126             :   auto Make = None;
     127         338 :   return {Pred, Make};
     128             : }
     129             : 
     130           1 : static inline SourcePred anyPtrType() {
     131             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     132           8 :     return V->getType()->isPointerTy() && !V->isSwiftError();
     133             :   };
     134           1 :   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
     135             :     std::vector<Constant *> Result;
     136             :     // TODO: Should these point at something?
     137           7 :     for (Type *T : Ts)
     138           6 :       Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
     139           1 :     return Result;
     140             :   };
     141           3 :   return {Pred, Make};
     142             : }
     143             : 
     144          11 : static inline SourcePred sizedPtrType() {
     145          34 :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     146          34 :     if (V->isSwiftError())
     147             :       return false;
     148             : 
     149          24 :     if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
     150          23 :       return PtrT->getElementType()->isSized();
     151             :     return false;
     152             :   };
     153          10 :   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
     154             :     std::vector<Constant *> Result;
     155             : 
     156          30 :     for (Type *T : Ts)
     157          10 :       if (T->isSized())
     158          20 :         Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
     159             : 
     160          10 :     return Result;
     161             :   };
     162          33 :   return {Pred, Make};
     163             : }
     164             : 
     165          21 : static inline SourcePred anyAggregateType() {
     166             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     167             :     // We can't index zero sized arrays.
     168          28 :     if (isa<ArrayType>(V->getType()))
     169           5 :       return V->getType()->getArrayNumElements() > 0;
     170             : 
     171             :     // Structs can also be zero sized. I.e opaque types.
     172           9 :     if (isa<StructType>(V->getType()))
     173           5 :       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          42 :   return {Pred, Find};
     181             : }
     182             : 
     183          26 : static inline SourcePred anyVectorType() {
     184             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     185          10 :     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          52 :   return {Pred, Make};
     192             : }
     193             : 
     194             : /// Match values that have the same type as the first source.
     195         365 : static inline SourcePred matchFirstType() {
     196             :   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
     197             :     assert(!Cur.empty() && "No first source yet");
     198           5 :     return V->getType() == Cur[0]->getType();
     199             :   };
     200             :   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
     201             :     assert(!Cur.empty() && "No first source yet");
     202           4 :     return makeConstantsWithType(Cur[0]->getType());
     203             :   };
     204        1095 :   return {Pred, Make};
     205             : }
     206             : 
     207             : /// Match values that have the first source's scalar type.
     208           8 : static inline SourcePred matchScalarOfFirstType() {
     209             :   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
     210             :     assert(!Cur.empty() && "No first source yet");
     211           0 :     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           0 :     return makeConstantsWithType(Cur[0]->getType()->getScalarType());
     216             :   };
     217          24 :   return {Pred, Make};
     218             : }
     219             : 
     220             : } // end fuzzerop namespace
     221             : } // end llvm namespace
     222             : 
     223             : #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H

Generated by: LCOV version 1.13