LCOV - code coverage report
Current view: top level - include/llvm/FuzzMutate - OpDescriptor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 43 46 93.5 %
Date: 2018-10-20 13:21:21 Functions: 14 14 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           4 : 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         428 :   SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
      62         922 :   SourcePred(PredT Pred, NoneType) : Pred(Pred) {
      63           0 :     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         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           3 : 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             :   auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
      98           4 :     return V->getType() == Only;
      99             :   };
     100             :   auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
     101           1 :     return makeConstantsWithType(Only);
     102             :   };
     103           2 :   return {Pred, Make};
     104             : }
     105             : 
     106          12 : static inline SourcePred anyType() {
     107             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     108          74 :     return !V->getType()->isVoidTy();
     109             :   };
     110             :   auto Make = None;
     111          12 :   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         222 :   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         169 :   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             :   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           2 :   return {Pred, Make};
     142             : }
     143             : 
     144          11 : 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          22 :   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          21 :   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          26 :   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         730 :   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          16 :   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