RandomIRBuilder.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. //===-- RandomIRBuilder.cpp -----------------------------------------------===//
  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. #include "llvm/FuzzMutate/RandomIRBuilder.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/FuzzMutate/OpDescriptor.h"
  11. #include "llvm/FuzzMutate/Random.h"
  12. #include "llvm/IR/BasicBlock.h"
  13. #include "llvm/IR/Constants.h"
  14. #include "llvm/IR/DataLayout.h"
  15. #include "llvm/IR/Instructions.h"
  16. #include "llvm/IR/IntrinsicInst.h"
  17. using namespace llvm;
  18. using namespace fuzzerop;
  19. Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
  20. ArrayRef<Instruction *> Insts) {
  21. return findOrCreateSource(BB, Insts, {}, anyType());
  22. }
  23. Value *RandomIRBuilder::findOrCreateSource(BasicBlock &BB,
  24. ArrayRef<Instruction *> Insts,
  25. ArrayRef<Value *> Srcs,
  26. SourcePred Pred,
  27. bool allowConstant) {
  28. auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) {
  29. return Pred.matches(Srcs, Inst);
  30. };
  31. auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred));
  32. // Also consider choosing no source, meaning we want a new one.
  33. RS.sample(nullptr, /*Weight=*/1);
  34. if (Instruction *Src = RS.getSelection())
  35. return Src;
  36. return newSource(BB, Insts, Srcs, Pred, allowConstant);
  37. }
  38. Value *RandomIRBuilder::newSource(BasicBlock &BB, ArrayRef<Instruction *> Insts,
  39. ArrayRef<Value *> Srcs, SourcePred Pred,
  40. bool allowConstant) {
  41. // Generate some constants to choose from.
  42. auto RS = makeSampler<Value *>(Rand);
  43. RS.sample(Pred.generate(Srcs, KnownTypes));
  44. // If we can find a pointer to load from, use it half the time.
  45. Value *Ptr = findPointer(BB, Insts, Srcs, Pred);
  46. if (Ptr) {
  47. // Create load from the chosen pointer
  48. auto IP = BB.getFirstInsertionPt();
  49. if (auto *I = dyn_cast<Instruction>(Ptr)) {
  50. IP = ++I->getIterator();
  51. assert(IP != BB.end() && "guaranteed by the findPointer");
  52. }
  53. // For opaque pointers, pick the type independently.
  54. Type *AccessTy = Ptr->getType()->isOpaquePointerTy()
  55. ? RS.getSelection()->getType()
  56. : Ptr->getType()->getNonOpaquePointerElementType();
  57. auto *NewLoad = new LoadInst(AccessTy, Ptr, "L", &*IP);
  58. // Only sample this load if it really matches the descriptor
  59. if (Pred.matches(Srcs, NewLoad))
  60. RS.sample(NewLoad, RS.totalWeight());
  61. else
  62. NewLoad->eraseFromParent();
  63. }
  64. Value *newSrc = RS.getSelection();
  65. // Generate a stack alloca and store the constant to it if constant is not
  66. // allowed, our hope is that later mutations can generate some values and
  67. // store to this placeholder.
  68. if (!allowConstant && isa<Constant>(newSrc)) {
  69. Type *Ty = newSrc->getType();
  70. Function *F = BB.getParent();
  71. BasicBlock *EntryBB = &F->getEntryBlock();
  72. /// TODO: For all Allocas, maybe allocate an array.
  73. DataLayout DL(BB.getParent()->getParent());
  74. AllocaInst *Alloca = new AllocaInst(Ty, DL.getProgramAddressSpace(), "A",
  75. EntryBB->getTerminator());
  76. new StoreInst(newSrc, Alloca, EntryBB->getTerminator());
  77. if (BB.getTerminator()) {
  78. newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", BB.getTerminator());
  79. } else {
  80. newSrc = new LoadInst(Ty, Alloca, /*ArrLen,*/ "L", &BB);
  81. }
  82. }
  83. return newSrc;
  84. }
  85. static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
  86. const Value *Replacement) {
  87. unsigned int OperandNo = Operand.getOperandNo();
  88. if (Operand->getType() != Replacement->getType())
  89. return false;
  90. switch (I->getOpcode()) {
  91. case Instruction::GetElementPtr:
  92. case Instruction::ExtractElement:
  93. case Instruction::ExtractValue:
  94. // TODO: We could potentially validate these, but for now just leave indices
  95. // alone.
  96. if (OperandNo >= 1)
  97. return false;
  98. break;
  99. case Instruction::InsertValue:
  100. case Instruction::InsertElement:
  101. case Instruction::ShuffleVector:
  102. if (OperandNo >= 2)
  103. return false;
  104. break;
  105. // For Br/Switch, we only try to modify the 1st Operand (condition).
  106. // Modify other operands, like switch case may accidently change case from
  107. // ConstantInt to a register, which is illegal.
  108. case Instruction::Switch:
  109. case Instruction::Br:
  110. if (OperandNo >= 1)
  111. return false;
  112. break;
  113. default:
  114. break;
  115. }
  116. return true;
  117. }
  118. void RandomIRBuilder::connectToSink(BasicBlock &BB,
  119. ArrayRef<Instruction *> Insts, Value *V) {
  120. auto RS = makeSampler<Use *>(Rand);
  121. for (auto &I : Insts) {
  122. if (isa<IntrinsicInst>(I))
  123. // TODO: Replacing operands of intrinsics would be interesting, but
  124. // there's no easy way to verify that a given replacement is valid given
  125. // that intrinsics can impose arbitrary constraints.
  126. continue;
  127. for (Use &U : I->operands())
  128. if (isCompatibleReplacement(I, U, V))
  129. RS.sample(&U, 1);
  130. }
  131. // Also consider choosing no sink, meaning we want a new one.
  132. RS.sample(nullptr, /*Weight=*/1);
  133. if (Use *Sink = RS.getSelection()) {
  134. User *U = Sink->getUser();
  135. unsigned OpNo = Sink->getOperandNo();
  136. U->setOperand(OpNo, V);
  137. return;
  138. }
  139. newSink(BB, Insts, V);
  140. }
  141. void RandomIRBuilder::newSink(BasicBlock &BB, ArrayRef<Instruction *> Insts,
  142. Value *V) {
  143. Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType());
  144. if (!Ptr) {
  145. if (uniform(Rand, 0, 1))
  146. Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt());
  147. else
  148. Ptr = UndefValue::get(PointerType::get(V->getType(), 0));
  149. }
  150. new StoreInst(V, Ptr, Insts.back());
  151. }
  152. Value *RandomIRBuilder::findPointer(BasicBlock &BB,
  153. ArrayRef<Instruction *> Insts,
  154. ArrayRef<Value *> Srcs, SourcePred Pred) {
  155. auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) {
  156. // Invoke instructions sometimes produce valid pointers but currently
  157. // we can't insert loads or stores from them
  158. if (Inst->isTerminator())
  159. return false;
  160. if (auto *PtrTy = dyn_cast<PointerType>(Inst->getType())) {
  161. if (PtrTy->isOpaque())
  162. return true;
  163. // We can never generate loads from non first class or non sized types
  164. Type *ElemTy = PtrTy->getNonOpaquePointerElementType();
  165. if (!ElemTy->isSized() || !ElemTy->isFirstClassType())
  166. return false;
  167. // TODO: Check if this is horribly expensive.
  168. return Pred.matches(Srcs, UndefValue::get(ElemTy));
  169. }
  170. return false;
  171. };
  172. if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr)))
  173. return RS.getSelection();
  174. return nullptr;
  175. }
  176. Type *RandomIRBuilder::randomType() {
  177. uint64_t TyIdx = uniform<uint64_t>(Rand, 0, KnownTypes.size() - 1);
  178. return KnownTypes[TyIdx];
  179. }