LCOV - code coverage report
Current view: top level - include/llvm/FuzzMutate - OpDescriptor.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 65 68 95.6 %
Date: 2017-09-14 15:23:50 Functions: 21 22 95.5 %
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/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        9186 : 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         633 :   SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
      61         663 :   SourcePred(PredT Pred, NoneType) : Pred(Pred) {
      62        4114 :     Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
      63             :       // Default filter just calls Pred on each of the base types.
      64           4 :       std::vector<Constant *> Result;
      65          18 :       for (Type *T : BaseTypes) {
      66          10 :         Constant *V = UndefValue::get(T);
      67          20 :         if (Pred(Cur, V))
      68           6 :           makeConstantsWithType(T, Result);
      69             :       }
      70           4 :       if (Result.empty())
      71           0 :         report_fatal_error("Predicate does not match for base types");
      72           4 :       return Result;
      73         442 :     };
      74         221 :   }
      75             : 
      76             :   /// Returns true if \c New is compatible for the argument after \c Cur
      77          54 :   bool matches(ArrayRef<Value *> Cur, const Value *New) {
      78         108 :     return Pred(Cur, New);
      79             :   }
      80             : 
      81             :   /// Generates a list of potential values for the argument after \c Cur.
      82          12 :   std::vector<Constant *> generate(ArrayRef<Value *> Cur,
      83             :                                    ArrayRef<Type *> BaseTypes) {
      84          24 :     return Make(Cur, BaseTypes);
      85             :   }
      86             : };
      87             : 
      88             : /// A description of some operation we can build while fuzzing IR.
      89        3363 : struct OpDescriptor {
      90             :   unsigned Weight;
      91             :   SmallVector<SourcePred, 2> SourcePreds;
      92             :   std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
      93             : };
      94             : 
      95           1 : static inline SourcePred onlyType(Type *Only) {
      96           4 :   auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
      97           4 :     return V->getType() == Only;
      98           5 :   };
      99           1 :   auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
     100             :     return makeConstantsWithType(Only);
     101           2 :   };
     102           4 :   return {Pred, Make};
     103             : }
     104             : 
     105           1 : static inline SourcePred anyType() {
     106             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     107          16 :     return !V->getType()->isVoidTy();
     108           8 :   };
     109           1 :   auto Make = None;
     110           3 :   return {Pred, Make};
     111             : }
     112             : 
     113         106 : static inline SourcePred anyIntType() {
     114             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     115           8 :     return V->getType()->isIntegerTy();
     116           8 :   };
     117         106 :   auto Make = None;
     118         318 :   return {Pred, Make};
     119             : }
     120             : 
     121          85 : static inline SourcePred anyFloatType() {
     122             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     123           8 :     return V->getType()->isFloatingPointTy();
     124           8 :   };
     125          85 :   auto Make = None;
     126         255 :   return {Pred, Make};
     127             : }
     128             : 
     129           6 : static inline SourcePred anyPtrType() {
     130             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     131           5 :     return V->getType()->isPointerTy();
     132           5 :   };
     133           1 :   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
     134           1 :     std::vector<Constant *> Result;
     135             :     // TODO: Should these point at something?
     136           5 :     for (Type *T : Ts)
     137           6 :       Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
     138           1 :     return Result;
     139             :   };
     140          30 :   return {Pred, Make};
     141             : }
     142             : 
     143          10 : static inline SourcePred anyAggregateType() {
     144             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     145           8 :     return V->getType()->isAggregateType();
     146           8 :   };
     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          10 :   auto Find = None;
     150          30 :   return {Pred, Find};
     151             : }
     152             : 
     153          13 : static inline SourcePred anyVectorType() {
     154             :   auto Pred = [](ArrayRef<Value *>, const Value *V) {
     155           6 :     return V->getType()->isVectorTy();
     156           6 :   };
     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          13 :   auto Make = None;
     161          39 :   return {Pred, Make};
     162             : }
     163             : 
     164             : /// Match values that have the same type as the first source.
     165         181 : static inline SourcePred matchFirstType() {
     166             :   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
     167             :     assert(!Cur.empty() && "No first source yet");
     168           4 :     return V->getType() == Cur[0]->getType();
     169             :   };
     170             :   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
     171             :     assert(!Cur.empty() && "No first source yet");
     172           3 :     return makeConstantsWithType(Cur[0]->getType());
     173             :   };
     174         905 :   return {Pred, Make};
     175             : }
     176             : 
     177             : /// Match values that have the first source's scalar type.
     178           4 : static inline SourcePred matchScalarOfFirstType() {
     179             :   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
     180             :     assert(!Cur.empty() && "No first source yet");
     181           0 :     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           0 :     return makeConstantsWithType(Cur[0]->getType()->getScalarType());
     186             :   };
     187          20 :   return {Pred, Make};
     188             : }
     189             : 
     190             : } // end fuzzerop namespace
     191             : } // end llvm namespace
     192             : 
     193             : #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H

Generated by: LCOV version 1.13