OpDescriptor.h 7.1 KB

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