Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===-- OpDescriptor.h ------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Provides the fuzzerop::Descriptor class and related tools for describing
  10. // operations an IR fuzzer can work with.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
  15. #define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
  16.  
  17. #include "llvm/ADT/ArrayRef.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/IR/Constants.h"
  20. #include "llvm/IR/DerivedTypes.h"
  21. #include "llvm/IR/Type.h"
  22. #include "llvm/IR/Value.h"
  23. #include <functional>
  24.  
  25. namespace llvm {
  26. class Instruction;
  27. namespace fuzzerop {
  28.  
  29. /// @{
  30. /// Populate a small list of potentially interesting constants of a given type.
  31. void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
  32. std::vector<Constant *> makeConstantsWithType(Type *T);
  33. /// @}
  34.  
  35. /// A matcher/generator for finding suitable values for the next source in an
  36. /// operation's partially completed argument list.
  37. ///
  38. /// Given that we're building some operation X and may have already filled some
  39. /// subset of its operands, this predicate determines if some value New is
  40. /// suitable for the next operand or generates a set of values that are
  41. /// suitable.
  42. class SourcePred {
  43. public:
  44.   /// Given a list of already selected operands, returns whether a given new
  45.   /// operand is suitable for the next operand.
  46.   using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
  47.   /// Given a list of already selected operands and a set of valid base types
  48.   /// for a fuzzer, generates a list of constants that could be used for the
  49.   /// next operand.
  50.   using MakeT = std::function<std::vector<Constant *>(
  51.       ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
  52.  
  53. private:
  54.   PredT Pred;
  55.   MakeT Make;
  56.  
  57. public:
  58.   /// Create a fully general source predicate.
  59.   SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
  60.   SourcePred(PredT Pred, std::nullopt_t) : Pred(Pred) {
  61.     Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
  62.       // Default filter just calls Pred on each of the base types.
  63.       std::vector<Constant *> Result;
  64.       for (Type *T : BaseTypes) {
  65.         Constant *V = UndefValue::get(T);
  66.         if (Pred(Cur, V))
  67.           makeConstantsWithType(T, Result);
  68.       }
  69.       if (Result.empty())
  70.         report_fatal_error("Predicate does not match for base types");
  71.       return Result;
  72.     };
  73.   }
  74.  
  75.   /// Returns true if \c New is compatible for the argument after \c Cur
  76.   bool matches(ArrayRef<Value *> Cur, const Value *New) {
  77.     return Pred(Cur, New);
  78.   }
  79.  
  80.   /// Generates a list of potential values for the argument after \c Cur.
  81.   std::vector<Constant *> generate(ArrayRef<Value *> Cur,
  82.                                    ArrayRef<Type *> BaseTypes) {
  83.     return Make(Cur, BaseTypes);
  84.   }
  85. };
  86.  
  87. /// A description of some operation we can build while fuzzing IR.
  88. struct OpDescriptor {
  89.   unsigned Weight;
  90.   SmallVector<SourcePred, 2> SourcePreds;
  91.   std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
  92. };
  93.  
  94. static inline SourcePred onlyType(Type *Only) {
  95.   auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
  96.     return V->getType() == Only;
  97.   };
  98.   auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
  99.     return makeConstantsWithType(Only);
  100.   };
  101.   return {Pred, Make};
  102. }
  103.  
  104. static inline SourcePred anyType() {
  105.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  106.     return !V->getType()->isVoidTy();
  107.   };
  108.   auto Make = std::nullopt;
  109.   return {Pred, Make};
  110. }
  111.  
  112. static inline SourcePred anyIntType() {
  113.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  114.     return V->getType()->isIntegerTy();
  115.   };
  116.   auto Make = std::nullopt;
  117.   return {Pred, Make};
  118. }
  119.  
  120. static inline SourcePred anyFloatType() {
  121.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  122.     return V->getType()->isFloatingPointTy();
  123.   };
  124.   auto Make = std::nullopt;
  125.   return {Pred, Make};
  126. }
  127.  
  128. static inline SourcePred anyPtrType() {
  129.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  130.     return V->getType()->isPointerTy() && !V->isSwiftError();
  131.   };
  132.   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
  133.     std::vector<Constant *> Result;
  134.     // TODO: Should these point at something?
  135.     for (Type *T : Ts)
  136.       Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
  137.     return Result;
  138.   };
  139.   return {Pred, Make};
  140. }
  141.  
  142. static inline SourcePred sizedPtrType() {
  143.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  144.     if (V->isSwiftError())
  145.       return false;
  146.  
  147.     if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
  148.       return PtrT->isOpaque() ||
  149.              PtrT->getNonOpaquePointerElementType()->isSized();
  150.     return false;
  151.   };
  152.   auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
  153.     std::vector<Constant *> Result;
  154.  
  155.     for (Type *T : Ts)
  156.       if (T->isSized())
  157.         Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
  158.  
  159.     return Result;
  160.   };
  161.   return {Pred, Make};
  162. }
  163.  
  164. static inline SourcePred anyAggregateType() {
  165.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  166.     // We can't index zero sized arrays.
  167.     if (isa<ArrayType>(V->getType()))
  168.       return V->getType()->getArrayNumElements() > 0;
  169.  
  170.     // Structs can also be zero sized. I.e opaque types.
  171.     if (isa<StructType>(V->getType()))
  172.       return V->getType()->getStructNumElements() > 0;
  173.  
  174.     return V->getType()->isAggregateType();
  175.   };
  176.   // TODO: For now we only find aggregates in BaseTypes. It might be better to
  177.   // manufacture them out of the base types in some cases.
  178.   auto Find = std::nullopt;
  179.   return {Pred, Find};
  180. }
  181.  
  182. static inline SourcePred anyVectorType() {
  183.   auto Pred = [](ArrayRef<Value *>, const Value *V) {
  184.     return V->getType()->isVectorTy();
  185.   };
  186.   // TODO: For now we only find vectors in BaseTypes. It might be better to
  187.   // manufacture vectors out of the base types, but it's tricky to be sure
  188.   // that's actually a reasonable type.
  189.   auto Make = std::nullopt;
  190.   return {Pred, Make};
  191. }
  192.  
  193. /// Match values that have the same type as the first source.
  194. static inline SourcePred matchFirstType() {
  195.   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
  196.     assert(!Cur.empty() && "No first source yet");
  197.     return V->getType() == Cur[0]->getType();
  198.   };
  199.   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
  200.     assert(!Cur.empty() && "No first source yet");
  201.     return makeConstantsWithType(Cur[0]->getType());
  202.   };
  203.   return {Pred, Make};
  204. }
  205.  
  206. /// Match values that have the first source's scalar type.
  207. static inline SourcePred matchScalarOfFirstType() {
  208.   auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
  209.     assert(!Cur.empty() && "No first source yet");
  210.     return V->getType() == Cur[0]->getType()->getScalarType();
  211.   };
  212.   auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
  213.     assert(!Cur.empty() && "No first source yet");
  214.     return makeConstantsWithType(Cur[0]->getType()->getScalarType());
  215.   };
  216.   return {Pred, Make};
  217. }
  218.  
  219. } // namespace fuzzerop
  220. } // namespace llvm
  221.  
  222. #endif // LLVM_FUZZMUTATE_OPDESCRIPTOR_H
  223.